Implementing a user login and logout system.
July 19, 2007
Yesterday i’d got as far as starting the controller code for my user login stuff.
Carrying on with that, from this tutorial. Finished the controller methods.
Some of the unit tests are failing, i think that might be to do with stuff that comes later in the tutorial though. The tutorial writer did say he did it in a different order to how it’s all written down, so i think later we’ll get to the stuff required to make the tests pass.
Next step is to create a mailer, to email out the forgotten passwords. This takes a little bit of work. I need to configure it in the ‘environment configuration file’. I’m not sure which file this is: there’s config/environment.rb or config/environments/development.rb. I’m going with the first one. It already has a ton of stuff in it, i’ve added the required code from the tutorial down at the bottom.
Added the forgot_password method to Notifications – this should make the earlier tests pass now.
Added all the views for the login stuff. There was one bit of security advice that seems very relevant to newspipe:
Make sure you check ids against users. If you are controlling access to items based on the user, make sure all your find methods include the user_id in the query. E.g. if you have a multi-user blog with an edit method takes the id of the post to edit as a parameter. Dont just use the id to find the post – use the user_id in the query too:
def edit @item=Blog.find(:first, :conditions=>["user_id=? and id=?", current_user.id, params[:id]]) ... end
See here for more about securing rails application.
More security advice:
- Use a CAPTCHA – those distorted character strings that are designed to differentiate between humans and bots. I would maybe use one of these on the “sign up” screen.
OK – got the user stuff up and running, some of it at least, now i need to tie it in with the rest of the app. I changed the login action to send the user to the article list screen once they logged in. This took a bit of investigation but the syntax for choosing an action in a different controller is
redirect_to :controller => “newspipe”, :action => “list”
ie, we specify what controller we want.
Next step – to start putting some links to the login, log out stuff on the various pages, and also to have something along the lines of “you are logged in as login_name”. I think that a template is the best way to do this – ie to have the login stuff and also a newspipe title on every page.
OK – got the list page working – the code (currently at the top of the list.rhtml page) is this:
<% user = session[:user] %>
<% if user %>
<%= “You are logged in as ” %> <strong> <%= user.login %> </strong> <span> </span>
<%= link_to ‘Log out’, :controller => “user”, :action => “logout” %> <br/>
<% else %>
<%= link_to ‘Log in’, :controller => “user”, :action => “login” %>
<% end %><br />
This rhtml code is a bit of a pain to write and is really hard to read. Going to look at that haml stuff again…
Oh man, this is so confusing. The haml site says that you should install haml via rails’ plugin installer. However when i try and install any plugins i get this message:
"ruby: No such file or directory -- script//plugin (LoadError)"
I get this whatever plugin i try and install. It’s as if ruby isn’t set up for plugins. Asked on a forum.
Fixed it – you have to install it inside the actual app folder. This makes sense i guess, since it’s a plugin, it should have something to plug into. But, since it’s a way of reformatting rhtml i thought it would be a bit more general. Reading on, it looks like i need to have “subversion” installed as well. Looking into subversion some more, i’m required to have an apache server, or something…Man this is a pain in the ass! I’m going to forget about haml for now and just get some work done. I’m pleased i got the user stuff working today but i wanted to do more about tying it in as well.
Want to change the “mail password” functionality to simply mail out the old password rather than a new one – just for the sake of my use of the system: since the email isn’t getting through (i think it’s not being sent properly because of the defaults – do i need a mail server or something?), when it changes the password there’s no way for me to tell what the new one is (it’s even encrypted in the database!). So, I’m going to try to disable the new password thing and get it to just mail the old one. I don’t think that really compromises security anyway.
Got it working so that when an article is added, it’s user_id is automatically set to the id of the currently logged in user. Which is nice.
What i want to do next is on the show page, after ‘added 5 mins ago’ is put ‘by <name of user>’
This should be simple but i’m having trouble thinking of the logic. What i want to do is
- Get the user id of the current article.
- Get the user with that id
- Get their login name
Ok, got an answer off the forum – this is amazingly simple. I want ‘the article’s user’s login’, so i just say
Awesome! I must have used this before without realising the significance. BTW, this relies on the models having the right relationship data, ie User has_many :articles and Article belongs_to :user.
After a bit of experimentation, worked out how to get it using the find method (which is a very powerful equivalent of an sql select statement):
(By default, if we pass one argument to find, it tries to match it against the primary id key.)
So, i’ve got users logging in and out, the app forcing people to log in before they can post an article, and the article displaying who posted it. That’s a good time to stop for today.