<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>TODO</filename>
    </added>
    <added>
      <filename>app/views/users/new.html.erb</filename>
    </added>
    <added>
      <filename>spec/requests/users_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -5,16 +5,36 @@ class Users &lt; Application
     @user = User.first(:login =&gt; id)
     raise NotFound unless @user
     @types = [ OpenID::OPENID_2_0_TYPE, OpenID::SREG_URI ]
-    headers['X-XRDS-Location'] = absolute_url(:user_xrds, {:id =&gt; @user.login})
+    headers['X-XRDS-Location'] = absolute_url(:user, {:id =&gt; @user.login, :format =&gt; :xrds})
     render :layout =&gt; false
   end
 
-  def signup
-    send_mail(SignupMailer, :notify_on_event, {
-      :from =&gt; 'root@example.com',
-      :to =&gt; &quot;someoneelse@gmail.com&quot;,
-      :subject =&gt; &quot;Welcome to the Flatirons OpenID Provider&quot;
-    })
-    redirect url(:login)
+  def new
+    render
+  end
+
+  def create(login, email)
+    @user = User.create(:login =&gt; login, :email =&gt; email)
+    if @user.valid?
+      send_mail(SignupMailer, :notify_on_event, {
+        :from =&gt; 'root@example.com',
+        :to =&gt; @user.email,
+        :subject =&gt; &quot;Welcome to the Flatirons OpenID Provider&quot;
+      })
+      redirect url(:login)
+    else
+      Merb.logger.info! @user.errors.inspect
+      render :new
+    end
+  end
+
+  def update(id, user)
+    raise
+  end
+
+  def destroy(id)
+    @user = User.first(:login =&gt; id)
+    @user.destroy
+    redirect(url(:new_user))
   end
 end</diff>
      <filename>app/controllers/users.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,7 @@
 class SignupMailer &lt; Merb::MailController
   def notify_on_event
     @host = 'http://example.org'
-    @user = session.user
-    # use params[] passed to this controller to get data
-    # read more at http://wiki.merbivore.com/pages/mailers
+    @user = User.first(:login =&gt; params[:login])
     render_mail
   end
 end</diff>
      <filename>app/mailers/signup_mailer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@ Greetings,
 Someone claiming to be you requested an account on the OpenID provider
 at &lt;%= @host %&gt;.  If you want to enable an account for this
 email address(&lt;%= @user.email %&gt;) then click 
-&lt;a href=&quot;/lolerskates'&gt;here&lt;/a&gt; confirm 
+&lt;a href=&quot;/users/signup/&lt;%= @user.registration_token %&gt;'&gt;here&lt;/a&gt; confirm 
 &lt;%= &quot;#{@host}/#{@user.login}&quot;  %&gt; as your OpenID url.
 
 __</diff>
      <filename>app/mailers/views/signup_mailer/notify_on_event.text.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,20 +1,23 @@
-# This is a default user class used to activate merb-auth.  Feel free to change from a User to 
-# Some other class, or to remove it altogether.  If removed, merb-auth may not work by default.
-#
-# Don't forget that by default the salted_user mixin is used from merb-more
-# You'll need to setup your db as per the salted_user mixin, and you'll need
-# To use :password, and :password_confirmation when creating a user
-#
-# see merb/merb-auth/setup.rb to see how to disable the salted_user mixin
-# 
-# You will need to setup your database and create a user.
-
 class User
   include DataMapper::Resource
  
   property :id, Serial
-  property :login,        String, :nullable =&gt; false, :unique =&gt; true, :unique_index =&gt; true
-  property :email,        String, :nullable =&gt; false, :unique =&gt; true, :unique_index =&gt; true
- 
-  validates_format :email, :as =&gt; :email_address
+  property :login,               String, :nullable =&gt; false, :unique =&gt; true, :unique_index =&gt; true
+  property :email,               String, :nullable =&gt; false, :unique =&gt; true, :unique_index =&gt; true, :format =&gt; :email_address
+  property :registration_token,  String, :nullable =&gt; true,  :unique =&gt; true, :unique_index =&gt; true
+
+  def password_required?; !new_record? end 
+  
+  before :save, :set_defaults
+  def set_defaults
+    @registration_token = Digest::SHA1.hexdigest(&quot;#{email}#{Time.now.to_i}&quot;)
+    randpass = Digest::SHA1.hexdigest(&quot;#{email}#{Time.now.to_i}&quot;)
+    @password ||= randpass
+    @password_confirmation ||= randpass
+    true
+  end
+
+  def registered?
+    registration_token.nil?
+  end
 end</diff>
      <filename>app/models/user.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,15 +1,8 @@
 &lt;%= error_messages_for session.authentication, :header =&gt; '&lt;h2&gt;Unable to login&lt;/h2&gt;' %&gt;
-&lt;form id=&quot;signup&quot; action=&quot;&lt;%= url(:perform_login) %&gt;&quot; method=&quot;POST&quot; accept-charset=&quot;utf-8&quot;&gt;
-  &lt;input type=&quot;hidden&quot; name=&quot;_method&quot; value=&quot;PUT&quot; /&gt;
-  &lt;h1&gt;Login&lt;/h1&gt;
-  &lt;label for='email'&gt;Login
-    &lt;input type='text' name=&quot;login&quot; id='login' /&gt;
-  &lt;/label&gt;
-
-  &lt;label for='password'&gt;Password
-    &lt;input type=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot; id=&quot;password&quot; /&gt;
-  &lt;/label&gt;
-
-  &lt;input type='submit' class='submit' value='Log in' /&gt;
-&lt;/form&gt;
+&lt;%= form :action =&gt; url(:perform_login) do %&gt;
+  &lt;%= hidden_field :name =&gt; '_method', :value =&gt; 'PUT' %&gt;
+  &lt;%= text_field :name =&gt; &quot;login&quot;, :id =&gt; 'login', :label =&gt; &quot;Login&quot; %&gt;
+  &lt;%= password_field :name =&gt; 'password', :id =&gt; 'password', :label =&gt; 'Password' %&gt;
+  &lt;%= submit &quot;Log in&quot; %&gt;
+&lt;% end =%&gt;
 </diff>
      <filename>app/views/exceptions/unauthenticated.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -10,4 +10,4 @@
       &lt;URI&gt;&lt;%= absolute_url(:servers) %&gt;&lt;/URI&gt;
     &lt;/Service&gt;
   &lt;/XRD&gt;
-&lt;/xrds:XRDS&gt;
\ No newline at end of file
+&lt;/xrds:XRDS&gt;</diff>
      <filename>app/views/servers/_yadis.xrds.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 &lt;html&gt;
   &lt;head&gt;
-    &lt;meta http-equiv=&quot;X-XRDS-Location&quot; content=&quot;&lt;%= absolute_url(:user_xrds, {:id =&gt; @user.login}) %&gt;&quot; /&gt;
+    &lt;meta http-equiv=&quot;X-XRDS-Location&quot; content=&quot;&lt;%= absolute_url(:user, {:id =&gt; @user.login, :format =&gt; :xrds}) %&gt;&quot; /&gt;
     &lt;link rel=&quot;openid.server&quot; href=&quot;&lt;%= absolute_url(:servers) %&gt;&quot; /&gt;
   &lt;/head&gt;
   &lt;body&gt;</diff>
      <filename>app/views/users/show.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,7 @@ r.setup_requirements
 
 # Go to http://wiki.merbivore.com/pages/init-rb
 require 'pp'
+require 'digest/sha1'
 
 use_orm :datamapper
 use_test :rspec</diff>
      <filename>config/init.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,7 +29,8 @@ Merb.logger.info(&quot;Compiling routes...&quot;)
 Merb::Router.prepare do
   # RESTful routes
   # resources :posts
-  
+  resources :users
+
   # Adds the required routes for merb-auth using the password slice
   slice(:merb_auth_slice_password, :name_prefix =&gt; nil, :path_prefix =&gt; &quot;&quot;)
 
@@ -37,16 +38,7 @@ Merb::Router.prepare do
   match(&quot;/servers/xrds&quot;).to(:controller =&gt; 'servers', :action =&gt; :idp_page).name('xrds')
   match(&quot;/servers/acceptance&quot;).to(:controller =&gt; 'servers', :action =&gt; 'acceptance').name('acceptance')
   match(&quot;/servers/decision&quot;).to(:controller =&gt; 'servers', :action =&gt; 'decision').name('server_decision')
-  match(&quot;/users/signup&quot;).to(:controller =&gt; :users, :action =&gt; :signup).name('signup')
-  match(&quot;/users/:id&quot;).to(:controller =&gt; :users, :action =&gt; :show).name('user')
-  match(&quot;/users/:id/xrds&quot;).to(:controller =&gt; :users, :action =&gt; :show).name(&quot;user_xrds&quot;)
 
-  # This is the default route for /:controller/:action/:id
-  # This is fine for most cases.  If you're heavily using resource-based
-  # routes, you may want to comment/remove this line to prevent
-  # clients from calling your create or destroy actions with a GET
-  # default_routes
-  
   # Change this for your home page to be available at /
   match('/').to(:controller =&gt; 'servers', :action =&gt; 'landing')
 end</diff>
      <filename>config/router.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,13 +3,27 @@ describe SignupMailer, &quot;#notify_on_event email template&quot; do
     clear_mail_deliveries
   end
   
-  describe &quot;signup quentin up&quot;, :given =&gt; 'an authenticated user' do
-    it &quot;includes welcome phrase in email text&quot; do
-      response = request(&quot;/users/signup&quot;)
+  describe &quot;arthur signing up for an account with valid info&quot; do
+    it &quot;welcomes arthur to our sight and provides a registration url&quot; do
+      response = request(&quot;/users&quot;, :method =&gt; 'post', 
+                         :params =&gt; {:email =&gt; 'arthur@example.com', :login =&gt; 'arthur'})
       response.should redirect_to('/login')
 
-      last_delivered_mail.text.should match(%r!http://example.org/quentin!)
-      last_delivered_mail.text.should match(%r!/lolerskates!)
+      last_delivered_mail.text.should match(%r!http://example.org/arthur!)
+      registration_url = &quot;/users/signup/#{User.first(:login =&gt; 'arthur').registration_token}&quot;
+      last_delivered_mail.text.should match(%r!#{registration_url}!)
+    end
+  end
+  describe &quot;arthur signing up for an account with invalid info&quot; do
+    it &quot;welcomes arthur to our sight and provides a registration url&quot; do
+      response = request(&quot;/users&quot;, :method =&gt; 'post', 
+                         :params =&gt; {:email =&gt; 'arthur.com', :login =&gt; 'arthur'})
+      response.should be_successful
+      response.should have_selector(&quot;form[action='/users'][method='post']&quot;)
+      response.should have_selector(&quot;input#login[type='text'][name='login']&quot;)
+      response.should have_selector(&quot;input#email[type='text'][name='email']&quot;)
+
+      last_delivered_mail.should be_nil
     end
   end
 end</diff>
      <filename>spec/mailers/signup_mailer_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,10 @@
 describe User do
-  after(:each) { User.all.destroy! }
   describe &quot;#create with valid params&quot; do
     it &quot;should be valid&quot; do
-      user = User.first_or_create({ :login =&gt; 'atmos', :email =&gt; 'joe@atmoose.org'}, 
-                    {:password =&gt; 'foo', :password_confirmation =&gt; 'foo'})
+      user = User.create(:login =&gt; 'arthur', :email =&gt; 'arthur@example.org')
+      user.save
       user.should be_valid
+      user.should_not be_registered
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>spec/models/user_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ describe &quot;Identity Discovery&quot; do
     it &quot;renders the user's identity page(/users/quentin)&quot; do
       response = request(&quot;/users/quentin&quot;, {'HTTP_ACCEPT' =&gt; 'application/xrds+xml'})
       response.should be_successful
-      response.headers[&quot;X-XRDS-Location&quot;].should == &quot;http://example.org/users/quentin/xrds&quot;
+      response.headers[&quot;X-XRDS-Location&quot;].should == &quot;http://example.org/users/quentin.xrds&quot;
       response.should have_xpath(&quot;//xrd/service[uri='http://example.org/servers']&quot;)
       response.should have_xpath(&quot;//xrd/service[type='http://specs.openid.net/auth/2.0/signon']&quot;)
       response.should have_xpath(&quot;//xrd/service[type='http://openid.net/sreg/1.0']&quot;)
@@ -21,14 +21,23 @@ describe &quot;Identity Discovery&quot; do
       response = request(&quot;/users/quentin&quot;)
       response.should be_successful
       response.should have_selector(&quot;head link[rel='openid.server'][href='http://example.org/servers']&quot;)
-      response.should have_selector(&quot;head meta[http-equiv='X-XRDS-Location'][content='http://example.org/users/quentin/xrds']&quot;)
+      response.should have_selector(&quot;head meta[http-equiv='X-XRDS-Location'][content='http://example.org/users/quentin.xrds']&quot;)
       response.should have_selector(&quot;body p:contains('OpenID identity page for quentin')&quot;)
-      response.headers[&quot;X-XRDS-Location&quot;].should == &quot;http://example.org/users/quentin/xrds&quot;
+      response.headers[&quot;X-XRDS-Location&quot;].should == &quot;http://example.org/users/quentin.xrds&quot;
     end
   end
 
-  it &quot;should handle routing for /users/quentin/xrds properly&quot; do
-    request_to(&quot;/users/quentin/xrds&quot;, :get, {:http_accept =&gt; 'application/xrds+xml'}).
+  it &quot;renders the user's identity page(/users/quentin.xrds)&quot; do
+    response = request(&quot;/users/quentin.xrds&quot;, {'HTTP_ACCEPT' =&gt; 'application/xrds+xml'})
+    response.should be_successful
+    response.headers[&quot;X-XRDS-Location&quot;].should == &quot;http://example.org/users/quentin.xrds&quot;
+    response.should have_xpath(&quot;//xrd/service[uri='http://example.org/servers']&quot;)
+    response.should have_xpath(&quot;//xrd/service[type='http://specs.openid.net/auth/2.0/signon']&quot;)
+    response.should have_xpath(&quot;//xrd/service[type='http://openid.net/sreg/1.0']&quot;)
+  end
+
+  it &quot;should handle routing for /users/quentin.xrds properly&quot; do
+    request_to(&quot;/users/quentin.xrds&quot;, :get, {:http_accept =&gt; 'application/xrds+xml'}).
       should route_to(Users, :show).with(:id =&gt; 'quentin')
   end
 end</diff>
      <filename>spec/requests/openid/identity_discovery_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -50,7 +50,7 @@ module FlatironsLoginForm
     def matches?(target)
       target.status.should == 401
       login_param = Merb::Plugins.config[:&quot;merb-auth&quot;][:login_param]
-      target.should have_selector(&quot;div.content form[action='/login'][method='POST']&quot;)
+      target.should have_selector(&quot;div.content form[action='/login'][method='post']&quot;)
       target.should have_selector(&quot;div.content form input[type='hidden'][name='_method'][value='PUT']&quot;)
       target.should have_selector(&quot;div.content form input##{login_param}[name='#{login_param}'][type='text']&quot;)
       target.should have_selector(&quot;div.content form input#password[name='password'][type='password']&quot;)
@@ -74,13 +74,15 @@ Spec::Runner.configure do |config|
   config.include(FlatironsLoginForm)
   config.include(Flatirons::MailControllerTestHelper)
   config.mock_with(:rr)
-
+  config.before(:each) do
+    User.all.destroy!
+  end
   def setup_user
     @user =  User.create(:login =&gt; 'quentin', :email =&gt; 'quentin@example.com', :password =&gt; 'foo', :password_confirmation =&gt; 'foo')
   end
 
   def login_user
-    response = request &quot;/login&quot;, :method =&gt; &quot;PUT&quot;, :params =&gt; { :login =&gt; 'quentin', :password =&gt; 'foo' }
+    response = request url(:perform_login), :method =&gt; &quot;PUT&quot;, :params =&gt; { :login =&gt; 'quentin', :password =&gt; 'foo' }
     response.should redirect_to(&quot;/&quot;)
   end
 </diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>8655610be55338bd60bcc36122ae2df9eac40bd1</id>
    </parent>
  </parents>
  <author>
    <name>Corey Donohoe</name>
    <email>atmos@atmos.org</email>
  </author>
  <url>http://github.com/atmos/flatirons/commit/ebb47153db88268513564f2d80e0f79cf863de48</url>
  <id>ebb47153db88268513564f2d80e0f79cf863de48</id>
  <committed-date>2008-12-01T20:31:40-08:00</committed-date>
  <authored-date>2008-12-01T20:31:40-08:00</authored-date>
  <message>more work, shuffling things, users are resources instead of a serious of route matches, start adding restful stuff to handle user registration</message>
  <tree>37b63c702708e65ff420cab632b366caef989761</tree>
  <committer>
    <name>Corey Donohoe</name>
    <email>atmos@atmos.org</email>
  </committer>
</commit>
