diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4948f5e79..c7eb8c6bd 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,7 +8,7 @@ class ApplicationController < ActionController::Base layout :layout_by_resource # Hack to prevent token auth on all pages except atom feed: - prepend_before_filter lambda { redirect_to(new_user_session_path) if params[:token] && params[:format] != 'atom'} + prepend_before_filter lambda { redirect_to(new_user_session_path) if params[:token] && params[:token].is_a?(String) && params[:format] != 'atom'} before_filter :set_locale before_filter lambda { EventLog.current_controller = self }, diff --git a/app/controllers/platforms/tokens_controller.rb b/app/controllers/platforms/tokens_controller.rb new file mode 100644 index 000000000..cf785b0be --- /dev/null +++ b/app/controllers/platforms/tokens_controller.rb @@ -0,0 +1,44 @@ +class Platforms::TokensController < ApplicationController + before_filter :authenticate_user! + + # load_and_authorize_resource :platform + # load_and_authorize_resource #:token#, :through => :subject + # load_and_authorize_resource :token, :through => :subject + + load_resource :platform + load_and_authorize_resource :through => :platform, :shallow => true + + def index + @tokens = @platform.tokens.includes(:creator, :updater) + .paginate(:per_page => 20, :page => params[:page]) + end + + def show + end + + def withdraw + if @token.block + redirect_to :back, :notice => t('layout.tokens.withdraw_success') + else + redirect_to :back, :notice => t('layout.tokens.withdraw_fail') + end + end + + def new + + end + + def create + @token = @platform.tokens.build params[:token] + @token.creator = current_user + if @token.save + flash[:notice] = t('flash.tokens.saved') + redirect_to platform_tokens_path(@platform) + else + flash[:error] = t('flash.tokens.save_error') + flash[:warning] = @token.errors.full_messages.join('. ') unless @token.errors.blank? + render :new + end + end + +end diff --git a/app/models/ability.rb b/app/models/ability.rb index 85eebe6be..7a4c7fccd 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -122,6 +122,8 @@ class Ability can([:create, :destroy], KeyPair) {|key_pair| owner?(key_pair.repository.platform) || local_admin?(key_pair.repository.platform)} + can([:read, :create], Token) {|token| local_admin?(token.subject)} + can :read, Product, :platform => {:owner_type => 'User', :owner_id => user.id, :platform_type => 'main'} can :read, Product, :platform => {:owner_type => 'Group', :owner_id => user.group_ids, :platform_type => 'main'} can(:read, Product, read_relations_for('products', 'platforms')) {|product| product.platform.main?} diff --git a/app/models/platform.rb b/app/models/platform.rb index a3b69ca62..47c364410 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -7,6 +7,7 @@ class Platform < ActiveRecord::Base has_many :repositories, :dependent => :destroy has_many :products, :dependent => :destroy + has_many :tokens, :as => :subject, :dependent => :destroy has_many :relations, :as => :target, :dependent => :destroy has_many :actors, :as => :target, :class_name => 'Relation', :dependent => :destroy diff --git a/app/models/token.rb b/app/models/token.rb new file mode 100644 index 000000000..1e53ffa7c --- /dev/null +++ b/app/models/token.rb @@ -0,0 +1,30 @@ +# -*- encoding : utf-8 -*- +class Token < ActiveRecord::Base + belongs_to :subject, :polymorphic => true, :touch => true + belongs_to :creator, :class_name => 'User' + belongs_to :updater, :class_name => 'User' + + validates :creator_id, :subject_id, :subject_type, :presence => true + + default_scope order("#{table_name}.created_at") + + before_create :generate_token + + attr_accessible :description + + state_machine :status, :initial => :active do + event :block do + transition [:active, :blocked] => :blocked + end + end + + protected + + def generate_token + self.authentication_token = loop do + token = SecureRandom.urlsafe_base64(64) + break token unless Token.where(:authentication_token => token).exists? + end + end + +end diff --git a/app/views/platforms/base/_sidebar.html.haml b/app/views/platforms/base/_sidebar.html.haml index ed5ef3e83..5775c9314 100644 --- a/app/views/platforms/base/_sidebar.html.haml +++ b/app/views/platforms/base/_sidebar.html.haml @@ -30,6 +30,8 @@ - if can? :edit, @platform %li{:class => (act == :index && contr == :key_pairs) ? 'active' : ''} = link_to t("layout.key_pairs.header"), platform_key_pairs_path(@platform) + %li{:class => (contr == :tokens) ? 'active' : ''} + = link_to t('layout.tokens.header'), platform_tokens_path(@platform) -#- if current_user.owner_of? @platform or current_user.admin? %li{:class => (act == :index && contr == :private_users) ? 'active' : ''} = link_to t("layout.platforms.private_users"), platform_private_users_path(@platform) diff --git a/app/views/platforms/tokens/index.html.haml b/app/views/platforms/tokens/index.html.haml new file mode 100644 index 000000000..1ff4ef6c4 --- /dev/null +++ b/app/views/platforms/tokens/index.html.haml @@ -0,0 +1,21 @@ +-set_meta_tags :title => [title_object(@platform), t('layout.tokens.list_header')] += render 'platforms/base/submenu' += render 'platforms/base/sidebar' += link_to t('layout.tokens.new'), new_platform_token_path(@platform), :class => 'button' if can? :create, @platform.tokens.build + +%table#myTable.tablesorter.platform-repos{:cellspacing => "0", :cellpadding => "0"} + %thead + %tr + %th= t('activerecord.attributes.token.id') + %th.th1= t('activerecord.attributes.token.description') + %th= t('layout.tokens.creator') + %th= t('activerecord.attributes.token.status') + %tbody + - @tokens.each do |token| + %tr{:class => cycle('odd', 'even')} + %td= link_to token.id, platform_token_path(@platform, token) + %td= token.description + %td= link_to token.creator.try(:fullname), token.creator + %td= token.status + += will_paginate @tokens diff --git a/app/views/platforms/tokens/new.html.haml b/app/views/platforms/tokens/new.html.haml new file mode 100644 index 000000000..589afe132 --- /dev/null +++ b/app/views/platforms/tokens/new.html.haml @@ -0,0 +1,16 @@ +-set_meta_tags :title => [title_object(@platform), t('layout.tokens.new')] += render 'platforms/base/submenu' += render 'platforms/base/sidebar' + +%h3= t('layout.tokens.new_header') + += form_for @token, :url => platform_tokens_path(@platform), :method => :post, :html => { :class => :form } do |f| + .leftlist= f.label :description + .rightlist= f.text_area :description + + .both + .hr + .button_block + = submit_tag t('layout.save') + %span.text_button_padding= t('layout.or') + = link_to t('layout.cancel'), platform_tokens_path(@platform), :class => 'button' diff --git a/config/routes.rb b/config/routes.rb index 85b4d3d37..7ee792bc5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -169,6 +169,11 @@ Rosa::Application.routes.draw do end end resources :key_pairs, :only => [:create, :index, :destroy] + resources :tokens, :only => [:create, :index, :show, :new] do + member do + post :withdraw + end + end resources :products do resources :product_build_lists, :only => [:create, :destroy, :new, :show, :update] do member { diff --git a/db/migrate/20130624095928_create_tokens.rb b/db/migrate/20130624095928_create_tokens.rb new file mode 100644 index 000000000..a3bde8ba5 --- /dev/null +++ b/db/migrate/20130624095928_create_tokens.rb @@ -0,0 +1,19 @@ +class CreateTokens < ActiveRecord::Migration + + def change + create_table :tokens do |t| + t.integer :subject_id, :null => false + t.string :subject_type, :null => false + t.integer :creator_id, :null => false + t.integer :updater_id + t.string :status, :default => 'active' + t.text :description + t.string :authentication_token, :null => false + + t.timestamps + end + add_index :tokens, :authentication_token, :unique => true + add_index :tokens, [:subject_id, :subject_type] + end + +end diff --git a/db/schema.rb b/db/schema.rb index 662e1dba7..b688dfac8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130603124853) do +ActiveRecord::Schema.define(:version => 20130624095928) do create_table "activity_feeds", :force => true do |t| t.integer "user_id", :null => false @@ -501,6 +501,21 @@ ActiveRecord::Schema.define(:version => 20130603124853) do t.decimal "subscribeable_id", :precision => 50, :scale => 0 end + create_table "tokens", :force => true do |t| + t.integer "subject_id", :null => false + t.string "subject_type", :null => false + t.integer "creator_id", :null => false + t.integer "updater_id" + t.string "status", :default => "active" + t.text "description" + t.string "authentication_token", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "tokens", ["authentication_token"], :name => "index_tokens_on_authentication_token", :unique => true + add_index "tokens", ["subject_id", "subject_type"], :name => "index_tokens_on_subject_id_and_subject_type" + create_table "users", :force => true do |t| t.string "name" t.string "email", :default => "", :null => false