diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 6811f77..dbfa98b 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -2,6 +2,7 @@ class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
+
# GET /projects
# GET /projects.json
diff --git a/app/controllers/whitelists_controller.rb b/app/controllers/whitelists_controller.rb
new file mode 100644
index 0000000..2b621fc
--- /dev/null
+++ b/app/controllers/whitelists_controller.rb
@@ -0,0 +1,87 @@
+class WhitelistsController < ApplicationController
+ before_action :check_if_coach
+
+ # GET /whitelists
+ def index
+ @permitted_users = User.all
+ end
+
+ # GET /whitelists/new
+ def new
+ @authorized_user = Whitelist.new(user_params)
+ end
+
+ # POST /whitelists/
+ def create
+ username = params[:username]
+ if Whitelist.has_username?(username)
+ flash[:notice] = "User #{username} already exists in whitelist. "
+ else
+ begin
+ Whitelist.create!(username: username)
+ flash[:notice] = "Add user #{username} successfully."
+ rescue ActiveRecord::RecordInvalid
+ flash[:notice] = "Invalid username format."
+ end
+ end
+ redirect_to whitelists_path
+ end
+
+ # DELETE /whitelists/
+ def destroy
+ user = Whitelist.find(params[:id])
+ if user.username.eql?(current_user.provider_username)
+ flash[:notice] = "Delete yourself from the whitelist is not allowed. "
+ else
+ user.destroy!
+ flash[:notice] = "User is deleted successfully."
+ end
+ redirect_to whitelists_path
+ end
+
+ def check_if_coach
+ unless current_user.role.eql?("admin") or current_user.role.eql?("coach")
+ flash[:notice] = "You have no privilege to manipulate privilege control."
+ redirect_to projects_url
+ end
+ end
+
+ def upgrade
+ unless current_user.role.eql?("admin") or current_user.role.eql?("coach")
+ flash[:alert] = "You do not have privilege to change other user's role. "
+ redirect_to whitelists_path
+ return
+ end
+ user = User.find(params[:id])
+ if user.role.eql?("admin")
+ flash[:alert] = "Admin role cannot be changed."
+ end
+ if user.role.eql?("student")
+ user.change_role("coach")
+ end
+ redirect_to whitelists_path
+ end
+
+ def downgrade
+ unless current_user.role.eql?("admin") or current_user.role.eql?("coach")
+ flash[:alert] = "You do not have privilege to change other user's role. "
+ redirect_to whitelists_path
+ return
+ end
+ user = User.find(params[:id])
+ if user.role.eql?("admin")
+ flash[:alert] = "Admin role cannot be changed."
+ end
+ if user.role.eql?("coach")
+ user.change_role("student")
+ end
+ redirect_to whitelists_path
+ end
+
+ private
+
+ def user_params
+ params.require(:whitelist).permit(:username)
+ end
+
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 9767930..ecbfc8e 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -36,6 +36,7 @@ class User < ActiveRecord::Base
ADMIN = "admin"
COACH = "coach"
+ STUDENT = "student"
def self.from_omniauth(auth)
email = auth.info.email.nil? ? auth.extra.raw_info.email : auth.info.email
@@ -59,6 +60,11 @@ def is_admin?
self.role == ADMIN
end
+ def change_role(role)
+ self.role = role
+ self.save!
+ end
+
def preferred_projects
self.selected_projects = Project.all if self.selected_projects.empty?
self.selected_projects
diff --git a/app/models/whitelist.rb b/app/models/whitelist.rb
new file mode 100644
index 0000000..455fcd6
--- /dev/null
+++ b/app/models/whitelist.rb
@@ -0,0 +1,15 @@
+# == Schema Information
+#
+# Table name: whitelists
+#
+# id :integer not null, primary key
+# username :string
+#
+
+class Whitelist < ActiveRecord::Base
+ validates_format_of :username,:with => /\A[a-z0-9\-_]+\z/i
+
+ def self.has_username?(username)
+ return !Whitelist.find_by_username(username).nil?
+ end
+end
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
index c310194..703fb48 100644
--- a/app/views/devise/sessions/new.html.erb
+++ b/app/views/devise/sessions/new.html.erb
@@ -6,6 +6,7 @@
Welcome to ProjectScope
+
<%= render "devise/shared/links" %>
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb
index 70e49c4..588b408 100644
--- a/app/views/devise/shared/_links.html.erb
+++ b/app/views/devise/shared/_links.html.erb
@@ -12,6 +12,7 @@
<%= link_to "Sign up", new_registration_path(resource_name) %>
<% end -%>
+
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
<% end -%>
diff --git a/app/views/projects/index.html.haml b/app/views/projects/index.html.haml
index 14a820d..22577a7 100644
--- a/app/views/projects/index.html.haml
+++ b/app/views/projects/index.html.haml
@@ -20,6 +20,17 @@
= '%.2f'.try(:%,sample.try(:score) || 0.0)
#{raw sample.try(:image)}
-%br/
+-unless current_user.role.eql?("coach") or current_user.role.eql?("admin")
+ %br/
+
+ = link_to 'Create New Project', new_project_path, :class => "btn btn-primary"
+
+-else
+ %br/
+
+ = link_to 'Privilege Control', whitelists_path, :class => "btn btn-primary"
+
+ %br/
+
+ = link_to 'Create New Project', new_project_path, :class => "btn btn-primary"
-= link_to 'Create New Project', new_project_path, :class => "btn btn-primary"
diff --git a/app/views/whitelists/_add.html.haml b/app/views/whitelists/_add.html.haml
new file mode 100644
index 0000000..0e811ed
--- /dev/null
+++ b/app/views/whitelists/_add.html.haml
@@ -0,0 +1,5 @@
+= form_tag whitelists_path do
+ = field_set_tag do
+ = label_tag :username, 'GitHub username'
+ = text_field_tag :username
+ = submit_tag 'Add'
\ No newline at end of file
diff --git a/app/views/whitelists/index.html.haml b/app/views/whitelists/index.html.haml
new file mode 100644
index 0000000..e7af39f
--- /dev/null
+++ b/app/views/whitelists/index.html.haml
@@ -0,0 +1,50 @@
+:css
+ #Users{
+ border-collapse: collapse;
+ width: 80%;
+ margin-right: auto;
+ }
+
+ #Users td, #Users th {
+ border: 1px solid #ddd;
+ padding: 8px;
+ }
+
+ #Users tr:nth-child(even){background-color: #f2f2f2;}
+
+ #Users tr:hover {background-color: #ddd;}
+
+ #Users th {
+ padding-top: 12px;
+ padding-bottom: 12px;
+ text-align: left;
+ background-color: #337ab7;
+ color: white;
+ }
+ #Users tr {
+ text-align: left;
+ }
+
+%h1 Privilege Control
+
+%table#Users
+ %thead
+ %tr
+ %th GitHub Account
+ %th Role
+ %th Action
+
+ %tbody
+ - @permitted_users.each do |user|
+ %tr
+ %td= user.provider_username
+ %td= user.role
+ -if user.role.eql?("coach")
+ %td= link_to "Downgrade to student", downgrade_user_path(user), :method => :get, data: { confirm: "Do you want to downgrade user #{user.provider_username} from the whitelist?" }, :user => user
+ -elsif user.role.eql?("student")
+ %td= link_to "Upgrade to coach", upgrade_user_path(user), :method => :get, data: { confirm: "Do you want to upgrade user #{user.provider_username} from the whitelist?" }, :user => user
+ -else
+ %td
+
+%br/
+= link_to 'Back to project page', projects_url
diff --git a/app/views/whitelists/new.html.erb b/app/views/whitelists/new.html.erb
new file mode 100644
index 0000000..5a87a72
--- /dev/null
+++ b/app/views/whitelists/new.html.erb
@@ -0,0 +1,6 @@
+
Authorize Users to have access to ProjectScope
+
+<%= render 'add' %>
+
+
+<%= link_to 'Back', whitelists_path %>
diff --git a/config/routes.rb b/config/routes.rb
index 6e6493e..c293161 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,7 +1,12 @@
Rails.application.routes.draw do
resources :users, :only => [:show, :update], :path => "u"
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }, :skip => [:password]
-
+
resources :projects
root 'projects#index'
+ resources :whitelists
+
+ get '/whitelists/upgrade/:id', :to => 'whitelists#upgrade', :as => 'upgrade_user'
+ get '/whitelists/downgrade/:id', :to => 'whitelists#downgrade', :as => 'downgrade_user'
+
end
diff --git a/db/migrate/20161020034239_add_role_to_users.rb b/db/migrate/20161020034239_add_role_to_users.rb
index ea24805..b785826 100644
--- a/db/migrate/20161020034239_add_role_to_users.rb
+++ b/db/migrate/20161020034239_add_role_to_users.rb
@@ -1,5 +1,5 @@
class AddRoleToUsers < ActiveRecord::Migration
def change
- add_column :users, :role, :string, null: false, default: "coach"
+ add_column :users, :role, :string, null: false, default: "student"
end
end
diff --git a/db/migrate/20161020040440_create_root_user.rb b/db/migrate/20161020040440_create_root_user.rb
index d9bf218..64fb5ab 100644
--- a/db/migrate/20161020040440_create_root_user.rb
+++ b/db/migrate/20161020040440_create_root_user.rb
@@ -4,16 +4,22 @@ def up
password: Devise.friendly_token[0,20],
provider_username: "DrakeW",
provider: "github",
- role: "admin")
+ role: "coach")
User.create!(email: "fox@cs.berkeley.edu",
password: Devise.friendly_token[0,20],
provider_username: "armandofox",
provider: "github",
role: "admin")
+ User.create!(email: "jiachengwu@berkeley.edu",
+ password: Devise.friendly_token[0,20],
+ provider_username: "ysiad",
+ provider: "github",
+ role: "coach")
end
def down
User.where(email: "junyuw@berkeley.edu", provider: "github").first.destroy
User.where(email: "fox@cs.berkeley.edu", provider: "github").first.destroy
+ User.where(email: "jiachengwu@berkeley.edu", provider: "github").first.destroy
end
end
diff --git a/db/migrate/20161022053537_create_whitelists.rb b/db/migrate/20161022053537_create_whitelists.rb
new file mode 100644
index 0000000..b385a78
--- /dev/null
+++ b/db/migrate/20161022053537_create_whitelists.rb
@@ -0,0 +1,9 @@
+class CreateWhitelists < ActiveRecord::Migration
+ def change
+ create_table :whitelists, :force => true do |t|
+ t.string :username # default: "", null: false
+ end
+ add_index :whitelists, :username
+ end
+end
+
diff --git a/db/migrate/20161022053828_create_authorized_user.rb b/db/migrate/20161022053828_create_authorized_user.rb
new file mode 100644
index 0000000..a933bf1
--- /dev/null
+++ b/db/migrate/20161022053828_create_authorized_user.rb
@@ -0,0 +1,11 @@
+class CreateAuthorizedUser < ActiveRecord::Migration
+ def up
+ Whitelist.create!(username: "DrakeW")
+ Whitelist.create!(username: "armandofox")
+ end
+
+ def down
+ Whitelist.where(username: "DrakeW").first.destroy
+ Whitelist.where(username: "armandofox").first.destroy
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 66f6a3a..8222ae3 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -79,4 +79,10 @@
add_index "users", ["provider_username"], name: "index_users_on_provider_username", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
+ create_table "whitelists", force: :cascade do |t|
+ t.string "username"
+ end
+
+ add_index "whitelists", ["username"], name: "index_whitelists_on_username"
+
end
diff --git a/features/github_user_login.feature b/features/github_user_login.feature
index e0c86ec..8331dcd 100644
--- a/features/github_user_login.feature
+++ b/features/github_user_login.feature
@@ -5,6 +5,7 @@ Feature: GitHub User Login
Scenario: github user login with email
Given I am on the login page
+ And "test-coach" is in the whitelist
And I have a valid github account with email "test-coach@test.com" username "test-coach"
When I follow "Sign in with GitHub"
Then I should be on the home page
@@ -12,6 +13,7 @@ Scenario: github user login with email
Scenario: github user login without email
Given I am on the login page
+ And "test-coach" is in the whitelist
And I have a valid github account with email "" username "test-coach"
When I follow "Sign in with GitHub"
Then I should be on the home page
diff --git a/features/step_definitions/project_steps.rb b/features/step_definitions/project_steps.rb
index 6bbdc55..193dfca 100644
--- a/features/step_definitions/project_steps.rb
+++ b/features/step_definitions/project_steps.rb
@@ -56,6 +56,7 @@
end
And(/^I am logged in$/) do
+ Whitelist.create :username => "test-coach"
visit path_to("the login page")
OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(
{
diff --git a/features/step_definitions/whitelist_steps.rb b/features/step_definitions/whitelist_steps.rb
new file mode 100644
index 0000000..aedb525
--- /dev/null
+++ b/features/step_definitions/whitelist_steps.rb
@@ -0,0 +1,16 @@
+Given(/^"([^"]*)" is in the whitelist$/) do |username|
+ Whitelist.create!(username: username)
+end
+
+Then /^I should be admin$/ do
+ expect(current_user.role).to eq "admin"
+end
+
+Given /^I enter the whitelist page$/ do
+ visit path_to("the whitelist page")
+ sleep(1)
+end
+
+When /^I follow the first "Delete"$/ do
+ first(:link, "Delete").click
+end
\ No newline at end of file
diff --git a/features/support/paths.rb b/features/support/paths.rb
index 429951b..8fea221 100644
--- a/features/support/paths.rb
+++ b/features/support/paths.rb
@@ -21,6 +21,10 @@ def path_to(page_name)
"/projects/#{Project.find_by(name: $1).id}/edit"
when /^the login page/ then
'/users/sign_in'
+ when /^the whitelist page/ then
+ '/whitelists'
+ when /^the whitelist management page/ then
+ '/whitelists/new'
# Add more mappings here.
# Here is an example that pulls values out of the Regexp:
#
diff --git a/features/whitelist.feature b/features/whitelist.feature
new file mode 100644
index 0000000..9ea4567
--- /dev/null
+++ b/features/whitelist.feature
@@ -0,0 +1,70 @@
+@omniauth
+Feature: Whitelist
+ As a whitelist user, I will be able to login to the projectscope and see the whitelist.
+ If I am not a whitelist user, I will not be able to login and manipulate the whitelist.
+
+Background:
+ Given "test-admin" is in the whitelist
+ And "ysiad" is in the whitelist
+
+Scenario: Users in the whitelist should be able to login
+ Given I am on the login page
+ And I have a valid github account with email "test-coach@test.com" username "test-admin"
+ When I follow "Sign in with GitHub"
+ Then I should be on the home page
+ And I should see "Signed in successfully."
+
+Scenario: Users that are not in the whitelist will not be able to login
+ Given I am on the login page
+ And I have a valid github account with email "test-coach@test.com" username "test-coach"
+ When I follow "Sign in with GitHub"
+ Then I should be on the login page
+ And I should see "You are not authorized."
+
+Scenario: Not whitelist user cannot see the whitelist
+ Given I am on the login page
+ When I go to the whitelist page
+ Then I should see "You are not authorized to manipulate whitelist."
+
+Scenario: Whitelist users can see the whitelist
+ Given I am logged in
+ Then I should be on the home page
+ And I should see "Whitelist"
+ When I follow "Whitelist"
+ Then I should be on the whitelist page
+ Then I should see "ysiad"
+ Then I should see "test-admin"
+
+Scenario: Whitelist users add a user to the whitelist
+ Given I am logged in
+ And I enter the whitelist page
+ Then I should see "Add user to whitelist"
+ When I follow "Add user to whitelist"
+ Then I should be on the whitelist management page
+ When I fill in "username" with "daisy"
+ And I press "Add"
+ Then I should be on the whitelist page
+ And I should see "daisy"
+
+ Scenario: Whitelist users delete a user from the whitelist
+ Given I am logged in
+ And I enter the whitelist page
+ Then I should see "test-admin"
+ When I follow the first "Delete"
+ Then I should see "User is deleted successfully."
+ And I should not see "test-admin"
+
+ Scenario: Whitelist users are unable to delete themselves from the whitelist
+ Given I am logged in
+ And I enter the whitelist page
+ Then I should see "test-admin"
+ Then I should see "ysiad"
+ Then I should see "test-coach"
+ When I follow the first "Delete"
+ Then I should not see "test-admin"
+ When I follow the first "Delete"
+ Then I should not see "ysiad"
+ Then I should not see "Delete"
+
+
+
diff --git a/users b/users
new file mode 100644
index 0000000..e69de29