Archive for October 2010
Super-audacious scam email
Wow. I just received a scam/spam email that takes the prize for most audacious. I guess the idea is McChrystal is hard up for cash(?). To be fair, the details are a bit dated, which, I suppose, could be interpreted as a wink to the better informed.
For your enjoyment, I reprint it below in full. I hope the author doesn’t mind
Greetings This is General Stanley Mc Chrystal from the states but on duties now in Afghanistan the commander of the multi international forces here in Afghanistan, first I apologies to you on contacting you through this media. Actually I have gotten a business proposal for you dear sir, it may sound strange or surprising to contact you through this media but really I am in need of someone to help me from your country. I acquire $ 20, million dollars on the attack when we try to apprehend the Taliban in a hidden cave here in Afghanistan. I am looking for an honest and trustful person that is capable of handling this transaction as we can understand that I am talking about hug amount of funds and I will like to transfer the funds out of Afghanistan to any country where the funds can be secure for some while until my arrival to your country. I could not transfer this huge amount of money to my country to prevent me for been probe by the house of pentagon on how I made that hug amount and to avoid been questioned by the United States government. This is a top secret transaction I do not want you to discuss this transaction in the public places for security reasons and also to secure my status and a serving American 4star General Please contact me via email address for more information detail regarding this transaction: stanleychrystal9@hotmail.com Your email address and telephone contact is needed for easy communication. Best regards General Stanley Mc Chrystal
Credit: stanleychrystal9@hotmail.com, info@general.com, and/or some unfortunate collection of writers & zombie machines
getting started with Node.js
I found what appears to be a nice tutorial for installing Node on Ubuntu 10.4, so I’ll start with that.
To keep things simple, I’m going to skip the dependencies, grab the tgz file, and just try running it. Why not? Thing’s could’ve changed w/ Node and/or Ubuntu since that post was written, and I love it when packages are designed well enough to provide irrational users with informative feedback, so let’s see.
- wget http://nodejs.org/dist/node-v0.2.3.tar.gz
- tar -xf node-v0.2.3.tar.gz
- cd node
- ./configure
- make
- sudo make install
/home/erik/node-v0.2.3/wscript:132: error: could not configure a cxx compiler!
Nice! I need g++:
sudo apt-get install g++
/home/erik/node-v0.2.3/wscript:188: error: Could not autodetect OpenSSL support. Make sure OpenSSL development packages are installed. Use configure --without-ssl to disable this message.
Looks like I need ssl too:
sudo apt-get install libssl-dev
Configuration now passes, but I see this in the output:
... Checking for openssl : not found Checking for function SSL_library_init : yes Checking for header openssl/crypto.h : yes Checking for library rt : yes --- libeio --- Checking for library pthread : yes Checking for function pthread_create : yes Checking for function pthread_atfork : yes Checking for futimes(2) : yes Checking for readahead(2) : yes Checking for fdatasync(2) : yes Checking for pread(2) and pwrite(2) : yes Checking for sendfile(2) : yes Checking for sync_file_range(2) : yes --- libev --- Checking for header sys/inotify.h : yes Checking for function inotify_init : yes Checking for header sys/epoll.h : yes Checking for function epoll_ctl : yes Checking for header port.h : not found Checking for header poll.h : yes Checking for function poll : yes Checking for header sys/event.h : not found Checking for header sys/queue.h : yes Checking for function kqueue : not found ...
Rather than run into mysterious errors later, I’ll go ahead and install all the dependencies mentioned in the post:
sudo apt-get install g++ curl libssl-dev apache2-utils
But it doesn’t correct the problem. Doh! Oh, well. I’ll deal with any errors later.
Continuing on, I run make (it’s been a while since I watched C compile), and then sudo make install:
'install' finished successfully (0.239s)
Rather than starting with the tutorial’s translation example, I opt for the hello world example on the Node site:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
I tried loading this, but no response. However, I grappled with my vm’s firewall recently enough to remember that I hadn’t opened port 8124, so I update the code to use port 80, and re-launch, but still get no response. Undaunted, I tell ufw to take a break:
sudo ufw disable && sudo shutdown -r now
Upon trying again, I noticed that I had the address wrong earlier – pilot error – but before enabling ufw, let’s see if we can get a response.
Curling http://127.0.0.1:8124/ returns “hello world”, but I’m not able to see this server from my laptop, i.e., curl http://172.16.83.133:8124/ doesn’t work.
Update (11/22/10): check out Padraig’s comment below about binding to 0.0.0.0.
It’s getting late, so this is a race against mental mutiny. Desparate, I stumble across another node.js + Ubuntu tutorial, and blindly install everything. I launch socket.io as per the instructions, bounce over to the browser, and … it works. Awesome. To the author of that post, nice job.
Ok. That’s enough for tonight. I’ll revisit this again later and try to understand what just happened.
In parting: Cats! In 3D! Don’t think. Just stare.
getting started with Ubuntu server, continued
I’ve been playing around with an Ubuntu 10.10 64-bit server vm for the past couple days. My previous post ended with me unable to ssh into the vm. Today, I read a post on serverfault that got me thinking about trying to ping the vm. For whatever reason, I might have more success with that than ssh.
The post also mentioned turning off the firewall, which seems like a logical step, though I’ve been paranoid for so long, I’m uncomfortable doing so, even on a vm. Nevertheless, I turned off the firewall: sudo ufw disable
Restarted the vm: sudo shutdown -r now
Ran ifconfig to confirm that the ip hadn’t changed: ifconfig
But it had. It was now something like 0.0.0.255, which looked off. It didn’t seem like something I could ssh into. When I was hacking around the other day, I had tried configuring the vm to use a bridged network. I now switched back to the default NAT setting: Virtual Machine > settings > Network > Share the Mac’s network connection
I restarted the machine, and ran ifconfig again. Now it was back to an ip that looked more familiar:
… inet addr:172.16.83.133 …
From my Mac, I tried pinging the vm: ping 172.16.83.133
To my surprise, it responded. Amazing. I tried ssh’ing in and was rejected with
ssh: connect to host 172.16.83.133 port 22: Connection refused.
Then I remembered I had set the ssh port to 2222, and tried again:
ssh erik@172.16.83.133 -p 2222
Success! Amazing again. Then I went overboard and turned the firewall back on, sudo ufw enable, and restarted, but it still worked(!). I checked the status of the firewall just to make sure I wasn’t delusional: sudo ufw status
Status: active To Action From -- ------ ---- 2222 ALLOW Anywhere 22 ALLOW Anywhere 80/tcp ALLOW Anywhere
This is madness, but it’s working, so I’m not complaining.
To wrap up the ssh piece, I want to configure ssh to use a public key instead of a password. I’ll follow the SSH/OpenSSH keys tutorial on the Ubuntu wiki.
I created a new ssh key, ssh-keygen -t rsa, and save it in a file called ~/.ssh/erik_rsa.
Then I copied the key to the vm:
scp -P 2222 ~/.ssh/erik_rsa.pub erik@172.16.83.133:.ssh/authorized_keys
Ideally (for me), the vm would now just automagically prefer public key authentication. I gave it a shot and immediately tried ssh’ing into the vm, but it still prompted me for a password. Oh well.
I edited the sshd_config file to uncomment the line AuthorizedKeysFile %h/.ssh/authorized_keys and set PasswordAuthentication to “no”, and then restarted sshd: sudo /etc/init.d/ssh restart
I exited the vm, and tried ssh’ing in again, this time specifying the location of my shiny new ssh key: ssh erik@172.16.83.133 -p 2222 -i ~/.ssh/erik_rsa
Wow. It worked. I’m always astounded when things like this actually work. Mac prompted me to enter my passphrase, and then I was in.
Now that I can ssh and I have a firewall, it’s time to move on to the next step of the security wiki … hmm … well, before I dive into denyhosts and fail2ban, I think I’ll play around with the real reason I wanted to get an OS up and running, to install node.js.
getting started with ufw on Ubuntu server
Rather than read the entrails of iptables syntax, I’d prefer to continue respecting myself, and use something more user-friendly, something like the Uncomplicated Firewall (ufw). I just learned about this, but it’s the Ubuntu default. I’d like to have faith, but for now I just hope it doesn’t suck.
The UFW wiki page linked above states “Setting the default mode of ufw is recommended before turning it on …”: sudo ufw default deny
That was easy. Next, I’ll enable it: sudo ufw enable
Now, I’ll allow port 2222 for ssh: sudo ufw allow 2222
And allow port 80 for tcp: sudo ufw allow 80/tcp
Check the current settings: sudo ufw status
Turn on logging: sudo ufw logging on
Ubuntu’s saying I need to restart in order for the changes to take effect. Fingers-crossed. Holding breath: sudo shutdown -r now …
As an aside, why does it have to be this way? Why can’t we just know that it will work? To be fair, UFW does seem pretty simple, and UFW’s –dry-run might be exactly what I’m looking for. Hopefully, UFW keeps me safe. Once I figure out how to automate deployment, things might be ok.
Ok, let’s check on the our ability to log in locally …
Good. I can still log in locally, so I didn’t lock myself out utterly. Checking local ssh as a sanity check: ssh -v localhost -p 2222
That works. Checking remote log in: ssh erik@172.16.83.133 -p 2222
Hmm. That still doesn’t work, and nothing is showing up in either /var/logs/auth.log or /var/logs/messages. Lemme try viewing the iptables directly:
sudo iptables -L
Wow. UFW knows how to generate iptables. The list goes on forever. Let’s try again w/ less: sudo iptables -L | less
I can see 2222, www, and ssh allowed, so it’s not obvious why I can’t ssh in. Following a couple suggestions on the vmware forums, I set /etc/hosts.allow to “SSHD:ALL”, and set networking to “bridged”, but still no luck.
Ok. I’ll hang it up for now. Here’s a nice, soothing picture of a kelp forrest to chill out to:
getting started with Ubuntu server security
In preparation for playing around with a VPS, I’d like to get familiar with Ubuntu 10.10 64-bit server. I grabbed the iso from their download page and installed it on vmware. Please pause with me and feel gratitude for Ubuntu. Thank you, Ubuntu, for being awesome. I was going to pick a more commercially popular OS, but I value my life, and Ubuntu was made with humans in mind.
The first thing I want to look at is security. Ubuntu’s forum has a sticky for general, intro-level security.
Ubuntu Wiki configure SSH seems like as good a place as any to get started.
This wiki page leads with “Once you have installed an OpenSSH server…”, so I set off to install openssh-server: sudo apt-get install openssh-server
But that gave me an error about openssh-server not being available for my system. After some digging, I got the impression that I might just need to update my system:
sudo apt-get update
Yup, that was it. Whew! I’m grateful it wasn’t a multi-hour quest for some random config setting.
Allegedly, after installing openssh, I should be able to ssh in right away. I ran ifconfig to get my vm’s ip address, and then tried it: ssh erik@172.16.83.255
ssh: connect to host 172.16.83.255 port 22: Permission denied.
Well, at least it’s talking to me. I think we’re ready to move on with the wiki.
I was able to make a backup of the default ssd_config file and set permissions on it without issue. On to customizing my sshd_config file: sudo vi /etc/ssh/sshd_config
- Change PasswordAuthentication to “no”
- I didn’t see a default setting for AllowTcpForwarding an X11Forwarding, so I added entries to turn each of these off
- I added an AllowUsers entry for my username
- Changed LoginGraceTime from 120 to 20
- Changes the LogLevel from “INFO” to “VERBOSE”
- Uncommented the Banner entry, and changed the file name from “issue.net” to “issue” for simplicity. I’ll defer setting the contents of this file.
- I also changed PermitRootLogin to “no”
As a sanity check, I ran ps -A | grep sshd to confirm sshd is running. As a second sanity check, I tried logging in via the local machine: ssh -v localhost. Amazingly, this also worked.
Ok. Moment of truth. Restarting sshd: sudo /etc/init.d/ssh restart.
Doh! I forgot to add my ssh key before disabling password login. Quick edit to restore PasswordAuthentication. Trying again … Connection refused on port 22. Oh, yeah. I changed it to 2222. Trying again … success! – from the local machine. Still can’t ssh in from a remote host. Time to check the ssh log: tail -f /var/log/auth.log
My ssh requests aren’t showing up in the logs. Time to look into the iptables settings. I’m guessing there’s a rule in there to ignore ssh, or no rule to allow ssh. I’ll continue this in another post.
A recipe for spaghetti sauce
- 1 large (1/2 lb) yellow onion
- 1 28 oz can of chunky tomato sauce
- 1 Tbsp olive oil, or enough to coat the bottom of a saute pan
- 10 basil leaves
instructions
- dice onion
- saute onion
- add sauce when onions are cooked sufficiently (I like translucence, and a little browning)
- simmer for 15 minutes
- mince basil and stir into sauce
variations
- saute 1 zucchini, diced, with the onion
- add pre-cooked meatballs when the sauce is added
notes
- Trader Joe’s sells bags containing two 1/2 lb organic onions
- I like Muir Glen organic tomato sauce
- Trader Joe’s sells tasty frozen, pre-cooked meetballs
Linked Data: notes from Tim Berners-Lee’s 2009 TED talk video
I started watching Tim Berners-Lee’s TED talk last night. He defines the term linked data to refer to pieces of data placed on the Web and linked to one anaother. He said there are three rules for putting something on the Web:
- http addresses are now being used to reference any unique entity on the Web, people, places, products, events, etc., not just documents
- If we request an object identified by an http address, we should get back useful information
- The object should include relationship pointers, formatted as http addresses, to other objects, e.g., “this person was born in Berlin, and Berlin is in Germany”. A person can link to a city, which can link to a region …
Linked data is browsable. The more data is connected together, the more powerful it is.
Berners-Lee mentioned DBpedia. dbpedia.org describes itself as “a community effort to extract structured information from Wikipedia and to make this information available on the Web”.
Diversity on the Web is important. We can put all kinds of data on the Web, government, university, enterprise, scientific, personal, weather, events, news, etc. Transparency in government is important, but this data is also beneficial because it describes how life is lived. It’s actually useful.
But owners of data are tempted to hang on to it. Hans Rosling calls this”database hugging”. So, make a beautiful Website, but first make the unadulterated data available. ”Raw data now!”. A lot of the data concerning that state of the human race is sitting on computers unaccessible by the Web. Now that scientists are putting genomic data and protein data on the Web as linked data, they can ask questions like “What proteins are involved in signal transduction and are related to pyramidal neurons?” (personal note: this seems a lot like a db query).
Linked social data is only possible if we break down the walls of social networks.
Open Street Map is all about everyone doing their bit. Linked data is all you doing your bit, everyone else doing theirs, and it all connecting.
“Linked data. I want you to make it. I want you to demand it. I think it’s an idea worth spreading.”
Thanks, Tim!
Getting started with Google App Engine Java SDK
A few days ago, I tried to use the App Engine Eclipse plugin, but ran into some issues, as described in an earlier post. These were probably due to my lack of experience with Java, Eclipse, and/or the AppEngine dev model, but I was blocked all the same. This time, I’ll start at a lower level, with the App Engine Java SDK.
My first stop was the App Engine Java overview page, which suggests “… you haven’t already, see the Java Getting Started Guide …”, so I hopped over.
The steps outlined in Installing the Java SDK worked well, and I was able to launch the dev server.
Next, I created my first project, the Guestbook app. The steps here were helpful too, and I was able to compile the app successfully (via the Using Apache Ant documentation), but I ran into trouble when I tried to run it:
$ ant runserver
Unable to find a $JAVA_HOME at "/usr", continuing with system-provided Java...
Buildfile: build.xml
copyjars:
compile:
runserver:
[java] 2010-10-14 00:47:18.489 java[24218:903] [Java CocoaComponent compatibility mode]: Enabled
[java] 2010-10-14 00:47:18.492 java[24218:903] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
[java] Oct 14, 2010 7:47:20 AM com.google.apphosting.utils.jetty.JettyLogger info
[java] INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
[java] Oct 14, 2010 7:47:20 AM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
[java] SEVERE: Received exception processing /Users/foo/Sites/appengine/Guestbook/war/WEB-INF/appengine-web.xml
[java] com.google.apphosting.utils.config.AppEngineConfigException: Could not locate /Users/foo/Sites/appengine/Guestbook/war/WEB-INF/appengine-web.xml
...
BUILD SUCCESSFUL
Total time: 3 seconds
The missing file is located in /Users/foo/Sites/appengine/Guestbook/war/WEB-INF/classes/WEB-INF/appengine-web.xml, which seems to be intentional given the statement “All other files found in src/, such as the META-INF/ directory, are copied verbatim to war/WEB-INF/classes/”.
If I add the following to build.xml, so appengine-web.xml and web.xml are coped into the src/WEB-INF dir, then it works:
<copy todir="war/WEB-INF">
<fileset dir="src/WEB-INF">
</fileset>
</copy>
The next step would be to Using the Users Service, but it’s getting alte, and I’z getting seelpy, so I’ll save that for another day.
To conclude w/ something uplifting, here’s a pic of a sleeping hedgehog.
First experiences with Rack::Test
I love test-driven development, and I love Rack apps, so I was delighted to discover the Rack::Test toolset. But, I wasn’t able to get it working immediately using the documentation I could find, so I’m taking notes here along my journey to discovery.
I. Install Rack::Test
The docs on the Rack::Test site didn’t do me wrong. Rack::Test installed cleanly with:
sudo gem install rack-test
II. Define some test code to get started
I grabbed the sample code from the Rack::Test site and saved it into a file called test.rb.
require "rack/test"
class HomepageTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
MyApp.new
end
def test_redirect_logged_in_users_to_dashboard
authorize "bryan", "secret"
get "/"
follow_redirect!
assert_equal "http://example.org/redirected", last_request.url
assert last_response.ok?
end
end
III. Run the code
Now, this is where I stumbled. How do we run this?
I tried rackup test.rb and ruby test.rb, but both complained of an “uninitialized constant Test”, so I guess there’s a prerequisite.
I checked out the Rack::Test Gemfile and installed rspec and upgraded rack to no avail.
I’m on Mac 10.6, btw. I’ve got rack 1.2.1 and rack-test 0.5.6.
Aha! As per a stackoverflow thread, I learned I need to add require “test/unit” to my code, so it looks like
require "rack/test" require "test/unit" ...
Now, when I run ruby test.rb, it throws, `require’: no such file to load — rack/test, but this is easily solved by requiring rubygems:
require "rubygems" require "rack/test" require "test/unit" ...
Dah! NameError: uninitialized constant HomepageTest::MyApp
I’ll just use Sinatra, that’s my end goal anyways.
require "rubygems"
require "sinatra"
require "rack/test"
require "test/unit"
class HomepageTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
Sinatra::Application
end
...
There we go:
Loaded suite test.rb
Started
E
Finished in 0.007586 seconds.
1) Error:
test_redirect_logged_in_users_to_dashboard(HomepageTest):
Rack::Test::Error: Last response was not a redirect. Cannot follow_redirect!
…
Now it’s time for bed. Sweet dreams
Helpful links
- The Rack::Test site
- The Sinatra README, from which I first learned about Rack::Test
- Joel Gascoigne’s blog post All in a day’s work: heroku, sinatra, passenger, haml, sass, mongodb and a touch of AJAX, which got me all fired up to use Sinatra
Simple YUI 3 module for Yahoo! login
Looking at the OpenID landing page on the YDN site might give the impression that logging users into a site with a Yahoo! ID is difficult. Given the following conditions, however, adding Yahoo! login to your site can be quite simple:
- Because we’re only targeting Yahoo! accounts, we can preset the login location to https://open.login.yahooapis.com/openid/op/auth
- If we log users in via a popup, but manage everything via JavaScript on the parent page, we can skip validation of the response coming back from Yahoo!
Here’s an HTML stub to demonstrate all the code that’s required to add Yahoo! login to your site:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head></head>
<body>
<span id="login"></span>
<script type="text/javascript" src="http://yui.yahooapis.com/3.2.0pr2/build/yui/yui-min.js"></script>
<script type="text/javascript"src="http://gist.github.com/raw/619947/f344557a242fc987f95e7f5af3173a28ba94a58c/yui-login.js"></script>
<script>
YUI().use('login', function(Y) {
Y.login.renderLoginButton('login');
});
</script>
</body>
</html>
You can run it here: http://example.erikeldridge.com/619947/demo.html
This code is maintained in a github gist: http://gist.github.com/619947
Here’s the YUI 3 module used in the code above. It provides simple login/logout buttons to perform the authentication flow. All it requires is an element on the page with an id. In the html above, the element has the id “login”. The id name is then passed into the Y.login.renderLoginButton method.
YUI.add('login', function(Y) {
// This module assumes the openid flow takes place via a popup that cannot be accessed directly.
// Given this condition, and to maintain simplicity, it doesn't attempt to verfiy the assertion.
// If you modify this script to use a file that processes the assertion directly, you should verify the assertion.
// @see http://openid.net/specs/openid-authentication-2_0.html#verification
// Licensed under Yahoo! BSD
// @see http://gist.github.com/375593
Y.namespace('login');
Y.login.cookieName = 'login_session';
Y.login.sessionReadyEventName = 'login:sessionReady';
// This function constructs an openid login url for Yahoo!, and opens a popup to this location
// @param {string} returnUrl is the url to redirect to after the user goes through the login flow. Defaults to document.location.href
Y.login.popup = function (returnUrl) {
returnUrl = returnUrl || document.location.href;
// @see http://openid.net/specs/openid-authentication-2_0.html#realms
var realm = returnUrl.match(/(http[s]?:\/\/[^\/?]+)/)[0];
// Load openid login flow in popup window
// @see http://developer.yahoo.com/openid/
var url = 'https://open.login.yahooapis.com/openid/op/auth?' + Y.QueryString.stringify({
'openid.return_to': returnUrl,
'openid.mode': 'checkid_setup',
'openid.identity': 'http://specs.openid.net/auth/2.0/identifier_select',
'openid.ns': 'http://specs.openid.net/auth/2.0',
'openid.realm': realm,
'openid.claimed_id': 'http://specs.openid.net/auth/2.0/identifier_select'
});
var name = 'login';
var params = 'toolbar=1,scrollbars=1,location=1,statusbar=1,menubar=0,resizable=1, width=500,height=500,left=200,top=200';
var popup = window.open(url, name, params);
// Poll popup every 300 msec to see if it's redirected back to this domain
// @see http://developer.yahoo.com/yui/3/api/YUI.html#method_later
var timer = Y.later(300, Y, function() {
// If user's closed window, stop timer
if (popup.closed) {
timer.cancel();
return;
}
// Wrap in try/catch to avoid fatal cross-domain exceptions
try {
// Openid's response is called the "assertion"
// @see http://openid.net/specs/openid-authentication-2_0.html#positive_assertions
var assertion = popup.location.href.split('?')[1];
assertion = Y.QueryString.parse(assertion);
// Extract the user-specific info
var session = {
'username': assertion['openid.identity']
};
var json = Y.JSON.stringify(session);
// Cache the session in a cookie
Y.Cookie.set(Y.login.cookieName, json);
// Notify anyone who's listening in this yui sandbox that the session's ready
Y.fire(Y.login.sessionReadyEventName);
// Stop polling popup & close it
timer.cancel();
popup.close();
} catch(e) {
Y.log(e);
}
}, '', true);
// Self-close login window if user hasn't completed flow in 30 sec
Y.later(30000, Y, function () {
timer.cancel();
popup.close();
});
};
// This function creates markup and event handling for a login button
// @param {string} id is the id of the DOM element to insert login button into
// @param {string} html is an optional param for custom button markup
// @throws Error if an id is not passed in
// @throws Error if there is no DOM element with the id passed in
Y.login.renderLoginButton = function (id, html) {
if (!id) {
throw new Error('Y.login.renderLoginButton - A DOM element id is a required argument');
}
var button = Y.one('#'+id);
if (!button) {
throw new Error('Y.login.renderLoginButton - No DOM element with id "'+id+'" found');
}
html = html || '<img src="http://l.yimg.com/a/i/reg/openid/buttons/1_new.png"/>';
button.set('innerHTML', html);
Y.on(Y.login.sessionReadyEventName, function () {
// login handling is async, so remove handler after auth is complete
Y.Event.purgeElement(button);
Y.login.renderLogoutButton(id);
});
// check for previously saved session
var session = Y.Cookie.get(Y.login.cookieName);
// if there is a session, fire session ready event and exit early
if (session) {
Y.fire(Y.login.sessionReadyEventName);
return;
}
button.on('click', function(e) {
Y.login.popup();
});
};
// This function creates markup and event handling for a logout button
// @param {string} id is the id of the DOM element to insert login button into
// @param {string} html is an optional param for custom button markup
// @throws Error if an id is not passed in
// @throws Error if there is no DOM element with the id passed in
Y.login.renderLogoutButton = function (id, html) {
if (!id) {
throw new Error('Y.login.renderLogoutButton - A DOM element id is a required argument');
}
var button = Y.one('#'+id);
if (!button) {
throw new Error('Y.login.renderLogoutButton - No DOM element with id "'+id+'" found');
}
//fetch username for display to make the login/logout a bit more realistic
var json = Y.Cookie.get(Y.login.cookieName);
var session = Y.JSON.parse(json);
html = html || 'User id: '+session['username']+'<br><a href="#">log out</a>';
button.set('innerHTML', html);
var handler = button.on('click', function(e) {
e.preventDefault();
// remove session cookie
Y.Cookie.remove(Y.login.cookieName);
// remove logout click handler
Y.Event.purgeElement(button);
// restore login button
Y.login.renderLoginButton(id);
});
};
}, '', {requires:['cookie', 'event', 'querystring', 'json', 'node']});



