Re: [deltacloud-devel] deltacloud.org favicon - shadowman?
by Jeremy Perry
On Oct 19, 2009, at 10:43 AM, Hugh O. Brock wrote:
> On Mon, Oct 19, 2009 at 10:39:39AM -0400, Jeremy Perry wrote:
>> That's an old one for the portal (which I guess we will rebrand to
>> match
>> the site). We can use this one now.
>>
>> Hugh - can you drop this in the root for the site so it gets picked
>> up
>> as the favicon?
>>
>> -Jeremy
>>
>
> Done, let me know if it shows up in the right place.
>
> --H
>
I think you need to put that two directories up, same as index.html
14 years, 7 months
Deltacloud portal permissions model
by Scott Seago
Now that we have login authentication for the portal, the next step is
to come up with an infrastructure for granting and enforcing
permissions on objects.
At the moment I'd like to follow the same overall approach that we
took for oVirt, with a few modifications.
At the lowest level, we maintain a list of "privileges" in the
database which represent a particular type of allowed action. These
could be very fine-grained levels such as "start instance", "create
instance", "create pool", "view instance statistics", "grant user
access", etc., or we could use more general privileges such as
"modify", "view", "control instances", etc.
Privileges will be fairly closely tied to available actions, so we
would not provide an API to add/remove these -- they're fairly closely
tied to the actions we've already implemented in the portal code.
Going up one level, a "role" is an associated group of privileges (but
not yet tied to a particular resource). Roles exist mainly for
convenience -- a set of privileges often used together are grouped in
a role to simplify granting permissions to a user. So, for example, an
"admin" role might combine "create instance", "create Pool", "start
Instance", etc. -- or if we're using less fine-grained privileges,
"admin" might include "create", "modify", and "view" privileges.
For oVirt we never got to the point of providing an API for
manipulating roles (i.e. create a new role that combines privileges X,
Y, and Z), but we could do that here as a future enhancement.
A Permission record (or perhaps "granted permission") associates a
user with a resource and a particular role. For example, when a user
creates a portal pool, a permission record will be created that
assigns the creating user an "admin" role for the pool. This user
might later grant a lesser "instance management" role to another user
for this same pool -- in order to delegate permission to start/stop
instances, etc. In addition we might want to control access to images,
so we might want to grant users permission to use specific images for
instance creation.
What other actions need permissions defined on them? Some possibilities:
1) Provider creation: Should only certain users be allowed to
associate the portal with external cloud providers? What object would
these permissions be attached to?
2) Create new pool/cloud account for a provider: Is this allowed for
any user, or will a user need permissions granted for the provider
object to allow the user to add a new pool/cloud account.
3) Create new pool for existing cloud account: Other than providing
appropriate cloud account credentials, are there additional
permissions required if the cloud account is already used by
another user for a different pool (since one cloud account can be
used for multiple portal pools)?
4) High-level admin role: Able to grant permissions for 1), add new
user accounts, etc
In addition to using a polymporphic association for the "permission
object" rather than just a pool (to support permission grants on a
variety of resource types), we might need to make the field nullable
so that we can define "global" roles for permissions not attached to a
specific resource (who can create providers, who can grant top-level
permissions, etc)
As for the UI, we can use the ovirt permissions UI as the starting
point. For the associated object (pool, provider, etc) we add a
permissions tab with a table/grid of users showing assigned roles.
The global roles would need to be accessed as a separate tab somewhere
on the main UI.
Scott
14 years, 7 months
pushing to fedorahosted repos
by Michael Neale
Hey all - on the deltacloud website it wants patches to be emailed
around (recently I had a ticket closed to import my rackspace driver -
so it looks like that was a one off).
Is that still the case? I am referring to framework, docs and drivers
(not portal).
--
Michael D Neale
home: www.michaelneale.net
blog: michaelneale.blogspot.com
14 years, 8 months
[PATCH] added initial auth functionality based on authlogic. (revised)
by Scott Seago
At the moment you've got to install the authlogic gem -- we will eventually need to package it as an RPM and add it as a dependency in the specfile.
Right now any user can create an account and access all pages. We aren't doing any access control beyond requiring a login account.
Signed-off-by: Scott Seago <sseago(a)redhat.com>
---
src/app/controllers/application_controller.rb | 39 ++++++++++++++++
src/app/controllers/instance_controller.rb | 2 +
src/app/controllers/portal_pool_controller.rb | 2 +
src/app/controllers/provider_controller.rb | 2 +
src/app/controllers/user_sessions_controller.rb | 24 ++++++++++
src/app/controllers/users_controller.rb | 36 +++++++++++++++
src/app/helpers/user_sessions_helper.rb | 2 +
src/app/helpers/users_helper.rb | 2 +
src/app/models/user.rb | 3 +
src/app/models/user_session.rb | 8 +++
src/app/views/layouts/_header.rhtml | 8 +++-
src/app/views/layouts/dcloud.rhtml | 2 +-
src/app/views/user_sessions/login.html.erb | 18 ++++++++
src/app/views/users/_form.erb | 10 ++++
src/app/views/users/edit.html.erb | 11 +++++
src/app/views/users/new.html.erb | 9 ++++
src/app/views/users/show.html.erb | 40 +++++++++++++++++
src/config/environment.rb | 1 +
src/config/routes.rb | 9 +++-
src/db/migrate/20090917192602_create_users.rb | 30 ++++++++++++
src/test/fixtures/users.yml | 15 ++++++
src/test/functional/task_controller_test.rb | 47 --------------------
.../functional/user_sessions_controller_test.rb | 23 ++++++++++
src/test/functional/users_controller_test.rb | 38 ++++++++++++++++
src/test/test_helper.rb | 5 ++
src/test/unit/helpers/user_sessions_helper_test.rb | 4 ++
src/test/unit/helpers/users_helper_test.rb | 4 ++
src/test/unit/user_test.rb | 8 +++
28 files changed, 350 insertions(+), 52 deletions(-)
create mode 100644 src/app/controllers/user_sessions_controller.rb
create mode 100644 src/app/controllers/users_controller.rb
create mode 100644 src/app/helpers/user_sessions_helper.rb
create mode 100644 src/app/helpers/users_helper.rb
create mode 100644 src/app/models/user.rb
create mode 100644 src/app/models/user_session.rb
create mode 100644 src/app/views/user_sessions/login.html.erb
create mode 100644 src/app/views/users/_form.erb
create mode 100644 src/app/views/users/edit.html.erb
create mode 100644 src/app/views/users/new.html.erb
create mode 100644 src/app/views/users/show.html.erb
create mode 100644 src/db/migrate/20090917192602_create_users.rb
create mode 100644 src/test/fixtures/users.yml
delete mode 100644 src/test/functional/task_controller_test.rb
create mode 100644 src/test/functional/user_sessions_controller_test.rb
create mode 100644 src/test/functional/users_controller_test.rb
create mode 100644 src/test/unit/helpers/user_sessions_helper_test.rb
create mode 100644 src/test/unit/helpers/users_helper_test.rb
create mode 100644 src/test/unit/user_test.rb
diff --git a/src/app/controllers/application_controller.rb b/src/app/controllers/application_controller.rb
index d32f1de..c417641 100644
--- a/src/app/controllers/application_controller.rb
+++ b/src/app/controllers/application_controller.rb
@@ -24,6 +24,8 @@
class ApplicationController < ActionController::Base
# FIXME: not sure what we're doing aobut service layer w/ deltacloud
include ApplicationService
+ filter_parameter_logging :password, :password_confirmation
+ helper_method :current_user_session, :current_user
init_gettext "ovirt"
layout :choose_layout
@@ -186,4 +188,41 @@ class ApplicationController < ActionController::Base
end
return hash
end
+
+ def current_user_session
+ return @current_user_session unless @current_user_session.nil?
+ @current_user_session = UserSession.find
+ end
+
+ def current_user
+ return @current_user unless @current_user.nil?
+ @current_user = current_user_session && current_user_session.user
+ end
+
+ def require_user
+ unless current_user
+ store_location
+ flash[:notice] = "You must be logged in to access this page"
+ redirect_to login_url
+ return false
+ end
+ end
+
+ def require_no_user
+ if current_user
+ store_location
+ flash[:notice] = "You must be logged out to access this page"
+ redirect_to account_url
+ return false
+ end
+ end
+
+ def store_location
+ session[:return_to] = request.request_uri
+ end
+
+ def redirect_back_or_default(default)
+ redirect_to(session[:return_to] || default)
+ session[:return_to] = nil
+ end
end
diff --git a/src/app/controllers/instance_controller.rb b/src/app/controllers/instance_controller.rb
index 398fdde..59e19ed 100644
--- a/src/app/controllers/instance_controller.rb
+++ b/src/app/controllers/instance_controller.rb
@@ -1,4 +1,6 @@
class InstanceController < ApplicationController
+ before_filter :require_user
+
def index
end
diff --git a/src/app/controllers/portal_pool_controller.rb b/src/app/controllers/portal_pool_controller.rb
index 49c2d90..9f41cf6 100644
--- a/src/app/controllers/portal_pool_controller.rb
+++ b/src/app/controllers/portal_pool_controller.rb
@@ -1,4 +1,6 @@
class PortalPoolController < ApplicationController
+ before_filter :require_user
+
def index
render :action => 'new'
end
diff --git a/src/app/controllers/provider_controller.rb b/src/app/controllers/provider_controller.rb
index 9b5e841..e0a96b7 100644
--- a/src/app/controllers/provider_controller.rb
+++ b/src/app/controllers/provider_controller.rb
@@ -1,4 +1,6 @@
class ProviderController < ApplicationController
+ before_filter :require_user
+
def index
render :action => 'new'
end
diff --git a/src/app/controllers/user_sessions_controller.rb b/src/app/controllers/user_sessions_controller.rb
new file mode 100644
index 0000000..7320ed0
--- /dev/null
+++ b/src/app/controllers/user_sessions_controller.rb
@@ -0,0 +1,24 @@
+class UserSessionsController < ApplicationController
+ before_filter :require_no_user, :only => [:new, :create]
+ before_filter :require_user, :only => :destroy
+
+ def login
+ @user_session = UserSession.new
+ end
+
+ def create
+ @user_session = UserSession.new(params[:user_session])
+ if @user_session.save
+ flash[:notice] = "Login successful!"
+ redirect_back_or_default account_url
+ else
+ render :action => :login
+ end
+ end
+
+ def logout
+ current_user_session.destroy
+ flash[:notice] = "Logout successful!"
+ redirect_back_or_default login_url
+ end
+end
diff --git a/src/app/controllers/users_controller.rb b/src/app/controllers/users_controller.rb
new file mode 100644
index 0000000..9fd4212
--- /dev/null
+++ b/src/app/controllers/users_controller.rb
@@ -0,0 +1,36 @@
+class UsersController < ApplicationController
+ before_filter :require_no_user, :only => [:new, :create]
+ before_filter :require_user, :only => [:show, :edit, :update]
+
+ def new
+ @user = User.new
+ end
+
+ def create
+ @user = User.new(params[:user])
+ if @user.save
+ flash[:notice] = "User registered!"
+ redirect_back_or_default account_url
+ else
+ render :action => :new
+ end
+ end
+
+ def show
+ @user = @current_user
+ end
+
+ def edit
+ @user = @current_user
+ end
+
+ def update
+ @user = @current_user # makes our views "cleaner" and more consistent
+ if @user.update_attributes(params[:user])
+ flash[:notice] = "User updated!"
+ redirect_to account_url
+ else
+ render :action => :edit
+ end
+ end
+end
diff --git a/src/app/helpers/user_sessions_helper.rb b/src/app/helpers/user_sessions_helper.rb
new file mode 100644
index 0000000..2018402
--- /dev/null
+++ b/src/app/helpers/user_sessions_helper.rb
@@ -0,0 +1,2 @@
+module UserSessionsHelper
+end
diff --git a/src/app/helpers/users_helper.rb b/src/app/helpers/users_helper.rb
new file mode 100644
index 0000000..2310a24
--- /dev/null
+++ b/src/app/helpers/users_helper.rb
@@ -0,0 +1,2 @@
+module UsersHelper
+end
diff --git a/src/app/models/user.rb b/src/app/models/user.rb
new file mode 100644
index 0000000..04c7d17
--- /dev/null
+++ b/src/app/models/user.rb
@@ -0,0 +1,3 @@
+class User < ActiveRecord::Base
+ acts_as_authentic
+end
diff --git a/src/app/models/user_session.rb b/src/app/models/user_session.rb
new file mode 100644
index 0000000..6f99d26
--- /dev/null
+++ b/src/app/models/user_session.rb
@@ -0,0 +1,8 @@
+class UserSession < Authlogic::Session::Base
+ # gettext_activerecord defines a gettext method for the activerecord
+ # Validations module. Authlogic uses these Validations also but does
+ # not define the gettext method. We define it here instead.
+ def gettext(str)
+ GetText._(str)
+ end
+end
diff --git a/src/app/views/layouts/_header.rhtml b/src/app/views/layouts/_header.rhtml
index 76f9e73..3086620 100644
--- a/src/app/views/layouts/_header.rhtml
+++ b/src/app/views/layouts/_header.rhtml
@@ -1,10 +1,14 @@
<div class="header_logo"><%= image_tag "dcloud.png" %></div>
<div class="header_info">
- <div id="hi-username">Hi, <%= @user %></div>
+ <div id="hi-username">
+ <%= link_to "Hi, " + @current_user.login,
+ { :controller => "users", :action => "show"} unless @current_user.nil? %>
+ </div>
<form method="POST" id="search-form" action="<%= url_for :controller => "search", :action => 'results' %>">
<input id="textfield_effect" name="terms" value="Search" onkeypress="" onfocus="if( this.value == this.defaultValue ) this.value='';" type="text">
<input id="searchbox-button" src="<%= image_path "icon_search.png"%>" title="Search" type="image"> |
</form>
- <%= link_to 'Log out', { :controller => "login", :action => "logout"}%>
+ <%= link_to 'Log out', logout_url unless @current_user.nil? %>
+ <%= link_to 'Log in', login_url if @current_user.nil? %>
</div>
\ No newline at end of file
diff --git a/src/app/views/layouts/dcloud.rhtml b/src/app/views/layouts/dcloud.rhtml
index 725f630..60e0ad8 100644
--- a/src/app/views/layouts/dcloud.rhtml
+++ b/src/app/views/layouts/dcloud.rhtml
@@ -69,7 +69,7 @@
</div>
<div id="side">
- <%= render :partial => '/layouts/main_nav' %>
+ <%= render :partial => '/layouts/main_nav' unless @current_user.nil? %>
</div>
<div id="tabs-and-content-container">
diff --git a/src/app/views/user_sessions/login.html.erb b/src/app/views/user_sessions/login.html.erb
new file mode 100644
index 0000000..ee7da51
--- /dev/null
+++ b/src/app/views/user_sessions/login.html.erb
@@ -0,0 +1,18 @@
+<div class="dcloud_form">
+ <h2>Login</h2>
+
+ <% form_for @user_session, :url => user_session_path do |f| %>
+ <%= f.error_messages %>
+ <%= f.label :login %><br />
+ <%= f.text_field :login %><br />
+ <br />
+ <%= f.label :password %><br />
+ <%= f.password_field :password %><br />
+ <br />
+ <%= f.check_box :remember_me %><%= f.label :remember_me %><br />
+ <br />
+ <%= f.submit "Login" %>
+ <% end %>
+ <%= link_to 'Register', {:controller => 'users', :action => 'new'}, :class => 'actionlink' %>
+
+</div>
diff --git a/src/app/views/users/_form.erb b/src/app/views/users/_form.erb
new file mode 100644
index 0000000..a278d9a
--- /dev/null
+++ b/src/app/views/users/_form.erb
@@ -0,0 +1,10 @@
+<%= form.label :login %><br />
+<%= form.text_field :login %><br />
+<%= form.label :email %><br />
+<%= form.text_field :email %><br />
+<br />
+<%= form.label :password, form.object.new_record? ? nil : "Change password" %><br />
+<%= form.password_field :password %><br />
+<br />
+<%= form.label :password_confirmation %><br />
+<%= form.password_field :password_confirmation %><br />
diff --git a/src/app/views/users/edit.html.erb b/src/app/views/users/edit.html.erb
new file mode 100644
index 0000000..73fdedd
--- /dev/null
+++ b/src/app/views/users/edit.html.erb
@@ -0,0 +1,11 @@
+<div class="dcloud_form">
+ <h2>Edit My Profile</h2>
+
+ <% form_for @user, :url => account_path do |f| %>
+ <%= f.error_messages %>
+ <%= render :partial => "form", :object => f %>
+ <%= f.submit "Update" %>
+ <% end %>
+
+ <br /><%= link_to "My Profile", account_path, :class => 'actionlink' %>
+</div>
diff --git a/src/app/views/users/new.html.erb b/src/app/views/users/new.html.erb
new file mode 100644
index 0000000..d6a35e4
--- /dev/null
+++ b/src/app/views/users/new.html.erb
@@ -0,0 +1,9 @@
+<div class="dcloud_form">
+ <h2>Register</h2>
+
+ <% form_for @user, :url => account_path do |f| %>
+ <%= f.error_messages %>
+ <%= render :partial => "form", :object => f %>
+ <%= f.submit "Register" %>
+ <% end %>
+</div>
diff --git a/src/app/views/users/show.html.erb b/src/app/views/users/show.html.erb
new file mode 100644
index 0000000..632b630
--- /dev/null
+++ b/src/app/views/users/show.html.erb
@@ -0,0 +1,40 @@
+<div class="dcloud_form">
+ <h2>User Profile for <%=h @user.login %></h2>
+<p>
+ <b>Login:</b>
+ <%=h @user.login %>
+</p>
+
+<p>
+ <b>Login count:</b>
+ <%=h @user.login_count %>
+</p>
+
+<p>
+ <b>Last request at:</b>
+ <%=h @user.last_request_at %>
+</p>
+
+<p>
+ <b>Last login at:</b>
+ <%=h @user.last_login_at %>
+</p>
+
+<p>
+ <b>Current login at:</b>
+ <%=h @user.current_login_at %>
+</p>
+
+<p>
+ <b>Last login ip:</b>
+ <%=h @user.last_login_ip %>
+</p>
+
+<p>
+ <b>Current login ip:</b>
+ <%=h @user.current_login_ip %>
+</p>
+
+
+<%= link_to 'Edit', edit_account_path, :class => 'actionlink' %>
+</div>
diff --git a/src/config/environment.rb b/src/config/environment.rb
index 5098306..9a3433d 100644
--- a/src/config/environment.rb
+++ b/src/config/environment.rb
@@ -42,6 +42,7 @@ Rails::Initializer.run do |config|
# config.gem "aws-s3", :lib => "aws/s3"
config.gem "gettext", :lib => "gettext_rails"
config.gem "gettext", :lib => "gettext_activerecord"
+ config.gem "authlogic"
# Only load the plugins named here, in the order given. By default, all plugins
# in vendor/plugins are loaded in alphabetical order.
diff --git a/src/config/routes.rb b/src/config/routes.rb
index ae9bc75..6e08af0 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -33,8 +33,13 @@ ActionController::Routing::Routes.draw do |map|
# -- just remember to delete public/index.html.
map.default '', :controller => 'provider'
- map.login '/login', :controller => 'resources', :action => 'list'
- map.logout '/logout', :controller => 'resources', :action => 'list'
+ map.resource :user_session
+ map.root :controller => "user_sessions", :action => "login"
+ map.login 'login', :controller => "user_sessions", :action => "login"
+ map.logout 'logout', :controller => "user_sessions", :action => "logout"
+ map.resource :account, :controller => "users"
+ map.resources :users
+
# Allow downloading Web Service WSDL as a file with an extension
# instead of a file named 'wsdl'
diff --git a/src/db/migrate/20090917192602_create_users.rb b/src/db/migrate/20090917192602_create_users.rb
new file mode 100644
index 0000000..1bcf0d4
--- /dev/null
+++ b/src/db/migrate/20090917192602_create_users.rb
@@ -0,0 +1,30 @@
+class CreateUsers < ActiveRecord::Migration
+ def self.up
+ create_table :users do |t|
+ t.string :login, :null => false
+ t.string :email, :null => false
+ t.string :crypted_password, :null => false
+ t.string :password_salt, :null => false
+ t.string :persistence_token, :null => false
+ t.string :single_access_token, :null => false
+ t.string :perishable_token, :null => false
+ # Magic columns, just like ActiveRecord's created_at and updated_at.
+ # These are automatically maintained by Authlogic if they are present.
+ t.integer :login_count, :null => false, :default => 0
+ t.integer :failed_login_count, :null => false, :default => 0
+ t.datetime :last_request_at
+ t.datetime :current_login_at
+ t.datetime :last_login_at
+ t.string :current_login_ip
+ t.string :last_login_ip
+ t.timestamps
+ end
+ add_index :users, :login
+ add_index :users, :persistence_token
+ add_index :users, :last_request_at
+ end
+
+ def self.down
+ drop_table :users
+ end
+end
diff --git a/src/test/fixtures/users.yml b/src/test/fixtures/users.yml
new file mode 100644
index 0000000..3a3acb5
--- /dev/null
+++ b/src/test/fixtures/users.yml
@@ -0,0 +1,15 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+# one:
+# column: value
+#
+# two:
+# column: value
+test_user:
+ login: tuser
+ email: tuser(a)example.com
+ password_salt: <%= salt = Authlogic::Random.hex_token %>
+ crypted_password: <%= Authlogic::CryptoProviders::Sha512.encrypt("testpass" + salt) %>
+ persistence_token: 5136b29cb04a5b8840fe74451b8bdf83531f57c072826eaf63a5c05e71828ed58fc5359a2f22b02e54298d64e043a870bc03d898249dd7f577f6c5418d5ba5a6
+ single_access_token: YxaPK0smnUj2t9Pq0xuK
+ perishable_token: XZO-3xU2OIqHAUJOkDMX
diff --git a/src/test/functional/task_controller_test.rb b/src/test/functional/task_controller_test.rb
deleted file mode 100644
index a2a6393..0000000
--- a/src/test/functional/task_controller_test.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Copyright (C) 2008 Red Hat, Inc.
-# Written by Scott Seago <sseago(a)redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301, USA. A copy of the GNU General Public License is
-# also available at http://www.gnu.org/copyleft/gpl.html.
-
-require File.dirname(__FILE__) + '/../test_helper'
-require 'task_controller'
-
-# Re-raise errors caught by the controller.
-class TaskController; def rescue_action(e) raise e end; end
-
-class TaskControllerTest < ActionController::TestCase
- fixtures :tasks, :vms, :pools
-
- def setup
- @controller = TaskController.new
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
-
- @task_id = tasks(:shutdown_production_httpd_appliance_task).id
- end
-
- def test_show
- get :show, :id => @task_id
-
- assert_response :success
- assert_template 'show'
-
- assert_not_nil assigns(:task)
- assert assigns(:task).valid?
- end
-
-end
diff --git a/src/test/functional/user_sessions_controller_test.rb b/src/test/functional/user_sessions_controller_test.rb
new file mode 100644
index 0000000..cac84a9
--- /dev/null
+++ b/src/test/functional/user_sessions_controller_test.rb
@@ -0,0 +1,23 @@
+require 'test_helper'
+
+class UserSessionsControllerTest < ActionController::TestCase
+ fixtures :users
+ test "should get new" do
+ get :login
+ assert_response :success
+ end
+
+ test "should create user session" do
+ post :create, :user_session => { :login => "tuser", :password => "testpass" }
+ assert user_session = UserSession.find
+ assert_equal users(:test_user), user_session.user
+ assert_redirected_to account_path
+ end
+
+ test "should destroy user session" do
+ post :create, :user_session => { :login => "tuser", :password => "testpass" }
+ delete :logout
+ assert_nil UserSession.find
+ assert_redirected_to login_path
+ end
+end
diff --git a/src/test/functional/users_controller_test.rb b/src/test/functional/users_controller_test.rb
new file mode 100644
index 0000000..0f04dd2
--- /dev/null
+++ b/src/test/functional/users_controller_test.rb
@@ -0,0 +1,38 @@
+require 'test_helper'
+
+class UsersControllerTest < ActionController::TestCase
+ fixtures :users
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create user" do
+ assert_difference('User.count') do
+ post :create, :user => { :login => "tuser2", :email => "tuser2(a)example.com",
+ :password => "testpass",
+ :password_confirmation => "testpass" }
+ end
+
+ assert_redirected_to account_path
+ end
+
+ test "should show user" do
+ UserSession.create(users(:test_user))
+ get :show
+ assert_response :success
+ end
+
+ test "should get edit" do
+ UserSession.create(users(:test_user))
+ get :edit, :id => users(:test_user).id
+ assert_response :success
+ end
+
+ test "should update user" do
+ UserSession.create(users(:test_user))
+ put :update, :id => users(:test_user).id, :user => { }
+ assert_redirected_to account_path
+ end
+end
diff --git a/src/test/test_helper.rb b/src/test/test_helper.rb
index 009dfc8..7d902b7 100644
--- a/src/test/test_helper.rb
+++ b/src/test/test_helper.rb
@@ -20,6 +20,7 @@
ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'test_help'
+require 'authlogic/test_case'
class ActiveSupport::TestCase
# Transactional fixtures accelerate your tests by wrapping each test method
@@ -48,3 +49,7 @@ class ActiveSupport::TestCase
RAILS_DEFAULT_LOGGER
end
end
+
+class ActionController::TestCase
+ setup :activate_authlogic
+end
diff --git a/src/test/unit/helpers/user_sessions_helper_test.rb b/src/test/unit/helpers/user_sessions_helper_test.rb
new file mode 100644
index 0000000..20dabdf
--- /dev/null
+++ b/src/test/unit/helpers/user_sessions_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class UserSessionsHelperTest < ActionView::TestCase
+end
diff --git a/src/test/unit/helpers/users_helper_test.rb b/src/test/unit/helpers/users_helper_test.rb
new file mode 100644
index 0000000..96af37a
--- /dev/null
+++ b/src/test/unit/helpers/users_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class UsersHelperTest < ActionView::TestCase
+end
diff --git a/src/test/unit/user_test.rb b/src/test/unit/user_test.rb
new file mode 100644
index 0000000..a64d2d3
--- /dev/null
+++ b/src/test/unit/user_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
--
1.6.2.5
14 years, 8 months
taskomatic plans
by Ian Main
So I've been looking over some things and doing a lot of pondering on
how to move forward with taskomatic for deltacloud.
The plan I'm working with now is to:
- Finish the infrastructure for dependency information between tasks
and implement threading. I think it would be wise to just do this
up front so that as we implement tasks we can figure out the
dependencies and implement them. The task dependencies will work as
David and I worked out before for ovirt, using a class for each task
type, an instance for each action will be added to a list which can
be scanned by each instance to determine if it can run. I actually
don't think this will add too much difficulty given the limited number
of tasks in dcloud.
- Implement a seperate thread that deals with updates from the service
providers. This will basically be the "dbomatic" for dcloud. The
poll interval will be based on an XML config value in each driver and
will likely be fairly longish (I'm thinking 60sec or so depending).
- Plumb in a system that allows quicker updates to objects on which
recent actions have taken place. For example when an instance is
started we want to have more frequent polling of that instance until
its state changes so that we can more quickly inform the user. I am
unsure whether I will just use a seperate thread (or even be part of
the task) to do the updates or somehow notify the main update
thread. I suspect another thread will be easier..
- Work on/test task implementations to make them reliable.
- I'm not going to worry about torqeubox for now. If we do end up
using it it may be useful to use the queuing system as a method to
notify taskomatic of new tasks.
Sound reasonable to everyone?
Ian
14 years, 8 months
[PATCH] added initial auth functionality based on authlogic.
by Scott Seago
At the moment you've got to install the authlogic gem -- we will eventually need to package it as an RPM and add it as a dependency in the specfile.
Right now any user can create an account and access all pages. We aren't doing any access control beyond requiring a login account.
Signed-off-by: Scott Seago <sseago(a)redhat.com>
---
src/app/controllers/application_controller.rb | 39 ++++++++++++++++++++
src/app/controllers/instance_controller.rb | 2 +
src/app/controllers/portal_pool_controller.rb | 2 +
src/app/controllers/provider_controller.rb | 2 +
src/app/controllers/user_sessions_controller.rb | 24 ++++++++++++
src/app/controllers/users_controller.rb | 36 ++++++++++++++++++
src/app/helpers/user_sessions_helper.rb | 2 +
src/app/helpers/users_helper.rb | 2 +
src/app/models/user.rb | 3 ++
src/app/models/user_session.rb | 8 ++++
src/app/views/layouts/_header.rhtml | 4 +-
src/app/views/layouts/dcloud.rhtml | 2 +-
src/app/views/user_sessions/login.html.erb | 19 ++++++++++
src/app/views/users/_form.erb | 10 +++++
src/app/views/users/edit.html.erb | 12 ++++++
src/app/views/users/new.html.erb | 10 +++++
src/app/views/users/show.html.erb | 37 +++++++++++++++++++
src/config/environment.rb | 1 +
src/config/routes.rb | 8 +++-
src/db/migrate/20090917192602_create_users.rb | 30 +++++++++++++++
src/test/fixtures/users.yml | 7 ++++
.../functional/user_sessions_controller_test.rb | 8 ++++
src/test/functional/users_controller_test.rb | 8 ++++
src/test/unit/helpers/user_sessions_helper_test.rb | 4 ++
src/test/unit/helpers/users_helper_test.rb | 4 ++
src/test/unit/user_test.rb | 8 ++++
26 files changed, 287 insertions(+), 5 deletions(-)
create mode 100644 src/app/controllers/user_sessions_controller.rb
create mode 100644 src/app/controllers/users_controller.rb
create mode 100644 src/app/helpers/user_sessions_helper.rb
create mode 100644 src/app/helpers/users_helper.rb
create mode 100644 src/app/models/user.rb
create mode 100644 src/app/models/user_session.rb
create mode 100644 src/app/views/user_sessions/login.html.erb
create mode 100644 src/app/views/users/_form.erb
create mode 100644 src/app/views/users/edit.html.erb
create mode 100644 src/app/views/users/new.html.erb
create mode 100644 src/app/views/users/show.html.erb
create mode 100644 src/db/migrate/20090917192602_create_users.rb
create mode 100644 src/test/fixtures/users.yml
create mode 100644 src/test/functional/user_sessions_controller_test.rb
create mode 100644 src/test/functional/users_controller_test.rb
create mode 100644 src/test/unit/helpers/user_sessions_helper_test.rb
create mode 100644 src/test/unit/helpers/users_helper_test.rb
create mode 100644 src/test/unit/user_test.rb
diff --git a/src/app/controllers/application_controller.rb b/src/app/controllers/application_controller.rb
index d32f1de..99433c6 100644
--- a/src/app/controllers/application_controller.rb
+++ b/src/app/controllers/application_controller.rb
@@ -24,6 +24,8 @@
class ApplicationController < ActionController::Base
# FIXME: not sure what we're doing aobut service layer w/ deltacloud
include ApplicationService
+ filter_parameter_logging :password, :password_confirmation
+ helper_method :current_user_session, :current_user
init_gettext "ovirt"
layout :choose_layout
@@ -186,4 +188,41 @@ class ApplicationController < ActionController::Base
end
return hash
end
+
+ def current_user_session
+ return @current_user_session if defined?(@current_user_session)
+ @current_user_session = UserSession.find
+ end
+
+ def current_user
+ return @current_user if defined?(@current_user)
+ @current_user = current_user_session && current_user_session.user
+ end
+
+ def require_user
+ unless current_user
+ store_location
+ flash[:notice] = "You must be logged in to access this page"
+ redirect_to login_url
+ return false
+ end
+ end
+
+ def require_no_user
+ if current_user
+ store_location
+ flash[:notice] = "You must be logged out to access this page"
+ redirect_to account_url
+ return false
+ end
+ end
+
+ def store_location
+ session[:return_to] = request.request_uri
+ end
+
+ def redirect_back_or_default(default)
+ redirect_to(session[:return_to] || default)
+ session[:return_to] = nil
+ end
end
diff --git a/src/app/controllers/instance_controller.rb b/src/app/controllers/instance_controller.rb
index 398fdde..59e19ed 100644
--- a/src/app/controllers/instance_controller.rb
+++ b/src/app/controllers/instance_controller.rb
@@ -1,4 +1,6 @@
class InstanceController < ApplicationController
+ before_filter :require_user
+
def index
end
diff --git a/src/app/controllers/portal_pool_controller.rb b/src/app/controllers/portal_pool_controller.rb
index 49c2d90..9f41cf6 100644
--- a/src/app/controllers/portal_pool_controller.rb
+++ b/src/app/controllers/portal_pool_controller.rb
@@ -1,4 +1,6 @@
class PortalPoolController < ApplicationController
+ before_filter :require_user
+
def index
render :action => 'new'
end
diff --git a/src/app/controllers/provider_controller.rb b/src/app/controllers/provider_controller.rb
index 9b5e841..e0a96b7 100644
--- a/src/app/controllers/provider_controller.rb
+++ b/src/app/controllers/provider_controller.rb
@@ -1,4 +1,6 @@
class ProviderController < ApplicationController
+ before_filter :require_user
+
def index
render :action => 'new'
end
diff --git a/src/app/controllers/user_sessions_controller.rb b/src/app/controllers/user_sessions_controller.rb
new file mode 100644
index 0000000..c6cdd80
--- /dev/null
+++ b/src/app/controllers/user_sessions_controller.rb
@@ -0,0 +1,24 @@
+class UserSessionsController < ApplicationController
+ before_filter :require_no_user, :only => [:new, :create]
+ before_filter :require_user, :only => :destroy
+
+ def login
+ @user_session = UserSession.new
+ end
+
+ def create
+ @user_session = UserSession.new(params[:user_session])
+ if @user_session.save
+ flash[:notice] = "Login successful!"
+ redirect_back_or_default account_url
+ else
+ render :action => :new
+ end
+ end
+
+ def logout
+ current_user_session.destroy
+ flash[:notice] = "Logout successful!"
+ redirect_back_or_default login_url
+ end
+end
diff --git a/src/app/controllers/users_controller.rb b/src/app/controllers/users_controller.rb
new file mode 100644
index 0000000..9fd4212
--- /dev/null
+++ b/src/app/controllers/users_controller.rb
@@ -0,0 +1,36 @@
+class UsersController < ApplicationController
+ before_filter :require_no_user, :only => [:new, :create]
+ before_filter :require_user, :only => [:show, :edit, :update]
+
+ def new
+ @user = User.new
+ end
+
+ def create
+ @user = User.new(params[:user])
+ if @user.save
+ flash[:notice] = "User registered!"
+ redirect_back_or_default account_url
+ else
+ render :action => :new
+ end
+ end
+
+ def show
+ @user = @current_user
+ end
+
+ def edit
+ @user = @current_user
+ end
+
+ def update
+ @user = @current_user # makes our views "cleaner" and more consistent
+ if @user.update_attributes(params[:user])
+ flash[:notice] = "User updated!"
+ redirect_to account_url
+ else
+ render :action => :edit
+ end
+ end
+end
diff --git a/src/app/helpers/user_sessions_helper.rb b/src/app/helpers/user_sessions_helper.rb
new file mode 100644
index 0000000..2018402
--- /dev/null
+++ b/src/app/helpers/user_sessions_helper.rb
@@ -0,0 +1,2 @@
+module UserSessionsHelper
+end
diff --git a/src/app/helpers/users_helper.rb b/src/app/helpers/users_helper.rb
new file mode 100644
index 0000000..2310a24
--- /dev/null
+++ b/src/app/helpers/users_helper.rb
@@ -0,0 +1,2 @@
+module UsersHelper
+end
diff --git a/src/app/models/user.rb b/src/app/models/user.rb
new file mode 100644
index 0000000..04c7d17
--- /dev/null
+++ b/src/app/models/user.rb
@@ -0,0 +1,3 @@
+class User < ActiveRecord::Base
+ acts_as_authentic
+end
diff --git a/src/app/models/user_session.rb b/src/app/models/user_session.rb
new file mode 100644
index 0000000..6f99d26
--- /dev/null
+++ b/src/app/models/user_session.rb
@@ -0,0 +1,8 @@
+class UserSession < Authlogic::Session::Base
+ # gettext_activerecord defines a gettext method for the activerecord
+ # Validations module. Authlogic uses these Validations also but does
+ # not define the gettext method. We define it here instead.
+ def gettext(str)
+ GetText._(str)
+ end
+end
diff --git a/src/app/views/layouts/_header.rhtml b/src/app/views/layouts/_header.rhtml
index 76f9e73..f85510f 100644
--- a/src/app/views/layouts/_header.rhtml
+++ b/src/app/views/layouts/_header.rhtml
@@ -1,10 +1,10 @@
<div class="header_logo"><%= image_tag "dcloud.png" %></div>
<div class="header_info">
- <div id="hi-username">Hi, <%= @user %></div>
+ <div id="hi-username"><%= "Hi, " + @current_user.login if defined? @current_user %></div>
<form method="POST" id="search-form" action="<%= url_for :controller => "search", :action => 'results' %>">
<input id="textfield_effect" name="terms" value="Search" onkeypress="" onfocus="if( this.value == this.defaultValue ) this.value='';" type="text">
<input id="searchbox-button" src="<%= image_path "icon_search.png"%>" title="Search" type="image"> |
</form>
- <%= link_to 'Log out', { :controller => "login", :action => "logout"}%>
+ <%= link_to 'Log out', { :controller => "user_sessions", :action => "logout"}%>
</div>
\ No newline at end of file
diff --git a/src/app/views/layouts/dcloud.rhtml b/src/app/views/layouts/dcloud.rhtml
index 725f630..53dfc67 100644
--- a/src/app/views/layouts/dcloud.rhtml
+++ b/src/app/views/layouts/dcloud.rhtml
@@ -69,7 +69,7 @@
</div>
<div id="side">
- <%= render :partial => '/layouts/main_nav' %>
+ <%= render :partial => '/layouts/main_nav' if defined? @current_user %>
</div>
<div id="tabs-and-content-container">
diff --git a/src/app/views/user_sessions/login.html.erb b/src/app/views/user_sessions/login.html.erb
new file mode 100644
index 0000000..1322fa2
--- /dev/null
+++ b/src/app/views/user_sessions/login.html.erb
@@ -0,0 +1,19 @@
+<div class="dcloud_form">
+ <%= error_messages_for 'user_session' %>
+ <h2>Login</h2>
+
+ <% form_for @user_session, :url => user_session_path do |f| %>
+ <%= f.error_messages %>
+ <%= f.label :login %><br />
+ <%= f.text_field :login %><br />
+ <br />
+ <%= f.label :password %><br />
+ <%= f.password_field :password %><br />
+ <br />
+ <%= f.check_box :remember_me %><%= f.label :remember_me %><br />
+ <br />
+ <%= f.submit "Login" %>
+ <% end %>
+ <%= link_to 'Register', {:controller => 'users', :action => 'new'}, :class => 'actionlink' %>
+
+</div>
diff --git a/src/app/views/users/_form.erb b/src/app/views/users/_form.erb
new file mode 100644
index 0000000..a278d9a
--- /dev/null
+++ b/src/app/views/users/_form.erb
@@ -0,0 +1,10 @@
+<%= form.label :login %><br />
+<%= form.text_field :login %><br />
+<%= form.label :email %><br />
+<%= form.text_field :email %><br />
+<br />
+<%= form.label :password, form.object.new_record? ? nil : "Change password" %><br />
+<%= form.password_field :password %><br />
+<br />
+<%= form.label :password_confirmation %><br />
+<%= form.password_field :password_confirmation %><br />
diff --git a/src/app/views/users/edit.html.erb b/src/app/views/users/edit.html.erb
new file mode 100644
index 0000000..7c9db32
--- /dev/null
+++ b/src/app/views/users/edit.html.erb
@@ -0,0 +1,12 @@
+<div class="dcloud_form">
+ <%= error_messages_for 'user' %>
+ <h2>Edit My Profile</h2>
+
+ <% form_for @user, :url => account_path do |f| %>
+ <%= f.error_messages %>
+ <%= render :partial => "form", :object => f %>
+ <%= f.submit "Update" %>
+ <% end %>
+
+ <br /><%= link_to "My Profile", account_path %>
+</div>
diff --git a/src/app/views/users/new.html.erb b/src/app/views/users/new.html.erb
new file mode 100644
index 0000000..681d9b0
--- /dev/null
+++ b/src/app/views/users/new.html.erb
@@ -0,0 +1,10 @@
+<div class="dcloud_form">
+ <%= error_messages_for 'user' %>
+ <h2>Register</h2>
+
+ <% form_for @user, :url => account_path do |f| %>
+ <%= f.error_messages %>
+ <%= render :partial => "form", :object => f %>
+ <%= f.submit "Register" %>
+ <% end %>
+</div>
diff --git a/src/app/views/users/show.html.erb b/src/app/views/users/show.html.erb
new file mode 100644
index 0000000..e4e6e67
--- /dev/null
+++ b/src/app/views/users/show.html.erb
@@ -0,0 +1,37 @@
+<p>
+ <b>Login:</b>
+ <%=h @user.login %>
+</p>
+
+<p>
+ <b>Login count:</b>
+ <%=h @user.login_count %>
+</p>
+
+<p>
+ <b>Last request at:</b>
+ <%=h @user.last_request_at %>
+</p>
+
+<p>
+ <b>Last login at:</b>
+ <%=h @user.last_login_at %>
+</p>
+
+<p>
+ <b>Current login at:</b>
+ <%=h @user.current_login_at %>
+</p>
+
+<p>
+ <b>Last login ip:</b>
+ <%=h @user.last_login_ip %>
+</p>
+
+<p>
+ <b>Current login ip:</b>
+ <%=h @user.current_login_ip %>
+</p>
+
+
+<%= link_to 'Edit', edit_account_path %>
diff --git a/src/config/environment.rb b/src/config/environment.rb
index 5098306..9a3433d 100644
--- a/src/config/environment.rb
+++ b/src/config/environment.rb
@@ -42,6 +42,7 @@ Rails::Initializer.run do |config|
# config.gem "aws-s3", :lib => "aws/s3"
config.gem "gettext", :lib => "gettext_rails"
config.gem "gettext", :lib => "gettext_activerecord"
+ config.gem "authlogic"
# Only load the plugins named here, in the order given. By default, all plugins
# in vendor/plugins are loaded in alphabetical order.
diff --git a/src/config/routes.rb b/src/config/routes.rb
index ae9bc75..d2a171b 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -33,8 +33,12 @@ ActionController::Routing::Routes.draw do |map|
# -- just remember to delete public/index.html.
map.default '', :controller => 'provider'
- map.login '/login', :controller => 'resources', :action => 'list'
- map.logout '/logout', :controller => 'resources', :action => 'list'
+ map.resource :user_session
+ map.root :controller => "user_sessions", :action => "login"
+ map.login 'login', :controller => "user_sessions", :action => "login"
+ map.resource :account, :controller => "users"
+ map.resources :users
+
# Allow downloading Web Service WSDL as a file with an extension
# instead of a file named 'wsdl'
diff --git a/src/db/migrate/20090917192602_create_users.rb b/src/db/migrate/20090917192602_create_users.rb
new file mode 100644
index 0000000..1bcf0d4
--- /dev/null
+++ b/src/db/migrate/20090917192602_create_users.rb
@@ -0,0 +1,30 @@
+class CreateUsers < ActiveRecord::Migration
+ def self.up
+ create_table :users do |t|
+ t.string :login, :null => false
+ t.string :email, :null => false
+ t.string :crypted_password, :null => false
+ t.string :password_salt, :null => false
+ t.string :persistence_token, :null => false
+ t.string :single_access_token, :null => false
+ t.string :perishable_token, :null => false
+ # Magic columns, just like ActiveRecord's created_at and updated_at.
+ # These are automatically maintained by Authlogic if they are present.
+ t.integer :login_count, :null => false, :default => 0
+ t.integer :failed_login_count, :null => false, :default => 0
+ t.datetime :last_request_at
+ t.datetime :current_login_at
+ t.datetime :last_login_at
+ t.string :current_login_ip
+ t.string :last_login_ip
+ t.timestamps
+ end
+ add_index :users, :login
+ add_index :users, :persistence_token
+ add_index :users, :last_request_at
+ end
+
+ def self.down
+ drop_table :users
+ end
+end
diff --git a/src/test/fixtures/users.yml b/src/test/fixtures/users.yml
new file mode 100644
index 0000000..5bf0293
--- /dev/null
+++ b/src/test/fixtures/users.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+# one:
+# column: value
+#
+# two:
+# column: value
diff --git a/src/test/functional/user_sessions_controller_test.rb b/src/test/functional/user_sessions_controller_test.rb
new file mode 100644
index 0000000..5024b23
--- /dev/null
+++ b/src/test/functional/user_sessions_controller_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class UserSessionsControllerTest < ActionController::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
diff --git a/src/test/functional/users_controller_test.rb b/src/test/functional/users_controller_test.rb
new file mode 100644
index 0000000..c3db123
--- /dev/null
+++ b/src/test/functional/users_controller_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class UsersControllerTest < ActionController::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
diff --git a/src/test/unit/helpers/user_sessions_helper_test.rb b/src/test/unit/helpers/user_sessions_helper_test.rb
new file mode 100644
index 0000000..20dabdf
--- /dev/null
+++ b/src/test/unit/helpers/user_sessions_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class UserSessionsHelperTest < ActionView::TestCase
+end
diff --git a/src/test/unit/helpers/users_helper_test.rb b/src/test/unit/helpers/users_helper_test.rb
new file mode 100644
index 0000000..96af37a
--- /dev/null
+++ b/src/test/unit/helpers/users_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class UsersHelperTest < ActionView::TestCase
+end
diff --git a/src/test/unit/user_test.rb b/src/test/unit/user_test.rb
new file mode 100644
index 0000000..a64d2d3
--- /dev/null
+++ b/src/test/unit/user_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
--
1.6.2.5
14 years, 8 months