From bcfa571b0328a4b3e94479a31c027621ceb86ad5 Mon Sep 17 00:00:00 2001
From: Luke Shumaker <shumakl@purdue.edu>
Date: Fri, 4 Apr 2014 20:35:16 -0400
Subject: Implement the new security mechanism

---
 app/controllers/alerts_controller.rb      | 13 +----
 app/controllers/application_controller.rb | 45 +++++++++++++++
 app/controllers/games_controller.rb       |  2 -
 app/controllers/matches_controller.rb     | 54 +----------------
 app/controllers/pms_controller.rb         |  2 -
 app/controllers/servers_controller.rb     |  2 -
 app/controllers/sessions_controller.rb    |  8 ++-
 app/controllers/teams_controller.rb       |  5 +-
 app/controllers/tournaments_controller.rb | 96 ++++++++++++++-----------------
 app/controllers/users_controller.rb       | 21 +------
 10 files changed, 106 insertions(+), 142 deletions(-)

(limited to 'app/controllers')

diff --git a/app/controllers/alerts_controller.rb b/app/controllers/alerts_controller.rb
index d2b1558..333022a 100644
--- a/app/controllers/alerts_controller.rb
+++ b/app/controllers/alerts_controller.rb
@@ -1,7 +1,4 @@
 class AlertsController < ApplicationController
-	before_action :set_alert, only: [:show, :edit, :update, :destroy]
-	before_action :check_perms, only: [:new, :create, :edit, :update, :destroy]
-
 	# GET /alerts
 	# GET /alerts.json
 	def index
@@ -63,18 +60,14 @@ class AlertsController < ApplicationController
 	end
 
 	private
+
 	# Use callbacks to share common setup or constraints between actions.
 	def set_alert
 		@alert = Alert.find(params[:id])
 	end
 
-	def check_perms
-		unless (signed_in? and (current_user.in_group?(:admin) or current_user.in_group?(:host)))
-			respond_to do |format|
-				format.html { render action: 'permission_denied', status: :forbidden }
-				format.json { render json: "Permission denied", status: :forbidden }
-			end
-		end
+	def is_owner?(object)
+		object.author == current_user
 	end
 
 	# Never trust parameters from the scary internet, only allow the white list through.
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0ac3486..85fc5b0 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,8 +1,53 @@
 class ApplicationController < ActionController::Base
+	before_action :set_object, only: [:show]
+	before_action :check_create, only: [:new, :create]
+	before_action :check_edit, only: [:edit, :update]
+	before_action :check_delete, only: [:destroy]
+
 	# Prevent CSRF attacks by raising an exception.
 	# For APIs, you may want to use :null_session instead.
 	protect_from_forgery with: :exception
 
 	#include sessionhelper for the session controller and view
 	include SessionsHelper
+
+	def check_permission(verb, object=nil)
+		unless current_user.can?((verb.to_s+"_"+noun).to_sym) or (!object.nil? and is_owner?(object))
+			respond_to do |format|
+				format.html do
+					if object.nil?
+						redirect_to send(noun.pluralize+"_url"), notice: "You don't have permission to #{verb} #{noun.pluralize}."
+					else
+						redirect_to object, notice: "You don't have permission to #{verb} this #{noun}."
+					end
+				end
+				format.json { render json: "Permission denied", status: :forbidden }
+			end
+		end
+	end
+
+	def noun
+		@noun ||= self.class.name.underscore.sub(/_controller$/, '').singularize
+	end
+
+	def set_object
+		object = send("set_"+noun)
+	end
+
+	def check_create
+		check_permission(:create)
+	end
+	def check_edit
+		object = send("set_"+noun)
+		check_permission(:edit, object)
+	end
+	def check_delete
+		object = send("set_"+noun)
+		check_permission(:edit, object)
+	end
+
+	# Override this
+	def is_owner?(object)
+		return false
+	end
 end
diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb
index e9620b4..f18a5ad 100644
--- a/app/controllers/games_controller.rb
+++ b/app/controllers/games_controller.rb
@@ -1,6 +1,4 @@
 class GamesController < ApplicationController
-	before_action :set_game, only: [:show, :edit, :update, :destroy]
-
 	# GET /games
 	# GET /games.json
 	def index
diff --git a/app/controllers/matches_controller.rb b/app/controllers/matches_controller.rb
index ba6ab16..474ae04 100644
--- a/app/controllers/matches_controller.rb
+++ b/app/controllers/matches_controller.rb
@@ -1,6 +1,6 @@
 class MatchesController < ApplicationController
-	before_action :set_tournament, only: [:index, :new, :create]
-	before_action :set_match, only: [:show, :edit, :update, :destroy]
+	before_action :set_tournament, only: [:index]
+
 	# GET /matches
 	# GET /matches.json
 	def index
@@ -12,58 +12,10 @@ class MatchesController < ApplicationController
 	def show
 	end
 
-	# GET /matches/new
-	def new
-	end
-
-	# GET /matches/1/edit
-	def edit
-	end
-
-	# POST /matches
-	# POST /matches.json
-	def create
-		@match = @tournament.matches.build(match_params)
-
-		respond_to do |format|
-			if @match.save
-				format.html { redirect_to tournament_matches_path, notice: 'Match was successfully created.' }
-				format.json { render action: 'show', status: :created, location: @match }
-			else
-				format.html { render action: 'new' }
-				format.json { render json: @match.errors, status: :unprocessable_entity }
-			end
-		end
-	end
-
-	# PATCH/PUT /matches/1
-	# PATCH/PUT /matches/1.json
-	def update
-		respond_to do |format|
-			if @match.update(match_params)
-				format.html { redirect_to [@tournament, @match], notice: 'Match was successfully updated.' }
-				format.json { head :no_content }
-			else
-				format.html { render action: 'edit' }
-				format.json { render json: @match.errors, status: :unprocessable_entity }
-			end
-		end
-	end
-
-	# DELETE /matches/1
-	# DELETE /matches/1.json
-	def destroy
-		@match.destroy
-		respond_to do |format|
-			format.html { redirect_to tournament_matches_path }
-			format.json { head :no_content }
-		end
-	end
-
 	private
 	# Use callbacks to share common setup or constraints between actions.
 	def set_match
-		@tournament = Tournament.find(params[:tournament_id])
+		set_tournament
 		@match = @tournament.matches.find(params[:id]);
 	end
 	def set_tournament
diff --git a/app/controllers/pms_controller.rb b/app/controllers/pms_controller.rb
index b62a6ef..af112d1 100644
--- a/app/controllers/pms_controller.rb
+++ b/app/controllers/pms_controller.rb
@@ -1,6 +1,4 @@
 class PmsController < ApplicationController
-	before_action :set_pm, only: [:show, :edit, :update, :destroy]
-
 	# GET /pms
 	# GET /pms.json
 	def index
diff --git a/app/controllers/servers_controller.rb b/app/controllers/servers_controller.rb
index f23f2bf..3f11075 100644
--- a/app/controllers/servers_controller.rb
+++ b/app/controllers/servers_controller.rb
@@ -1,6 +1,4 @@
 class ServersController < ApplicationController
-	before_action :set_server, only: [:show, :edit, :update, :destroy]
-	before_action :check_perms
 
 	# GET /servers
 	# GET /servers.json
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 1bae258..a0390ad 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,5 +1,4 @@
 class SessionsController < ApplicationController
-	before_action :set_session, only: [:destroy]
 
 	# GET /sessions/new
 	def new
@@ -41,11 +40,16 @@ class SessionsController < ApplicationController
 	private
 	# Use callbacks to share common setup or constraints between actions.
 	def set_session
-		#@session = Session.find(cookies[:remember_token])
+		@token = Session.hash_token(cookies[:remember_token])
+		@session = Session.find_by(token: @token)
 	end
 
 	# Never trust parameters from the scary internet, only allow the white list through.
 	def session_params
 		params.require(:session).permit(:session_email, :session_user_name, :session_password)
 	end
+
+	def is_owner?(object)
+		object.user == current_user
+	end
 end
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index 05e7a12..57ae256 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -1,5 +1,4 @@
 class TeamsController < ApplicationController
-	before_action :set_team, only: [:show, :edit, :update, :destroy]
 
 	# GET /teams
 	# GET /teams.json
@@ -71,4 +70,8 @@ class TeamsController < ApplicationController
 	def team_params
 		params.require(:team).permit(:match_id)
 	end
+
+	def is_owner?(object)
+		object.users.include?(current_user)
+	end
 end
diff --git a/app/controllers/tournaments_controller.rb b/app/controllers/tournaments_controller.rb
index 9cf3404..2d63068 100644
--- a/app/controllers/tournaments_controller.rb
+++ b/app/controllers/tournaments_controller.rb
@@ -1,6 +1,4 @@
 class TournamentsController < ApplicationController
-	before_action :set_tournament, only: [:show, :edit, :update, :destroy, :join]
-	before_action :check_perms, only: [:new, :create, :edit, :destroy]
 
 	# GET /tournaments
 	# GET /tournaments.json
@@ -36,12 +34,7 @@ class TournamentsController < ApplicationController
 
 	# GET /tournaments/1/edit
 	def edit
-		if params['close_action'] == 'close'
-			@tournament.status = 1
-			@tournament.save
-			@tournament.setup(@tournament)
-			redirect_to "/tournaments"
-		end
+		check_permission(:edit, @tournament)
 	end
 
 	# POST /tournaments
@@ -64,9 +57,9 @@ class TournamentsController < ApplicationController
 	# PATCH/PUT /tournaments/1
 	# PATCH/PUT /tournaments/1.json
 	def update
-
-		if params[:update_action].nil?
-			check_perms
+		case params[:update_action]
+		when nil
+			check_permission(:edit, @tournament)
 			respond_to do |format|
 				if @tournament.update(tournament_params)
 					format.html { redirect_to @tournament, notice: 'Tournament was successfully updated.' }
@@ -76,42 +69,40 @@ class TournamentsController < ApplicationController
 					format.json { render json: @tournament.errors, status: :unprocessable_entity }
 				end
 			end
-		else
-			case params[:update_action]
-			when "join"
-				respond_to do |format|
-					if @tournament.join(current_user)
-						format.html { render action: 'show', notice: 'You have joined this tournament.' }
-						format.json { head :no_content }
-					end
-					format.html { render action: 'permission_denied', status: :forbidden }
-					format.json { render json: "Permission denied", status: :forbidden }
+
+		when "join"
+			check_permission(:join)
+			respond_to do |format|
+				if @tournament.join(current_user)
+					format.html { render action: 'show', notice: 'You have joined this tournament.' }
+					format.json { head :no_content }
 				end
-			when "leave"
-				respond_to do |format|
-					if @tournament.leave(current_user)
-						format.html {redirect_to tournaments_url, notice: 'You have left the tournament.' }
-						format.json { head :no_content }
-					end
-					format.html {redirect_to @tournament, notice: 'You were\'t a part of this tournament.' }
-					format.json { render json: "Permission denied", status: :forbidden }
-				end         
-			when "open"
-				respond_to do |format|
-					if @tournament.setup
-						format.html { render action: 'show', notice: 'You have joined this tournament.' }
-						format.json { head :no_content }
-					end
-					format.html { render action: 'permission_denied', status: :forbidden }
-					format.json { render json: "Permission denied", status: :forbidden }
+				format.html { render action: 'permission_denied', status: :forbidden }
+				format.json { render json: "Permission denied", status: :forbidden }
+			end
+		when "leave"
+			respond_to do |format|
+				if @tournament.leave(current_user)
+					format.html {redirect_to tournaments_url, notice: 'You have left the tournament.' }
+					format.json { head :no_content }
 				end
-				#when "close"
-				# TODO
-			else
-				respond_to do |format|
-					format.html { render action: 'show', notice: "Invalid action", status: :unprocessable_entity }
-					format.json { render json: @tournament.errors, status: :unprocessable_entity }
+				format.html {redirect_to @tournament, notice: 'You were\'t a part of this tournament.' }
+				format.json { render json: "Permission denied", status: :forbidden }
+			end
+		when "open"
+			check_permission(:edit, @tournament)
+			respond_to do |format|
+				if @tournament.setup
+					format.html { render action: 'show', notice: 'You have joined this tournament.' }
+					format.json { head :no_content }
 				end
+				format.html { render action: 'permission_denied', status: :forbidden }
+				format.json { render json: "Permission denied", status: :forbidden }
+			end
+		else
+			respond_to do |format|
+				format.html { render action: 'show', notice: "Invalid action", status: :unprocessable_entity }
+				format.json { render json: @tournament.errors, status: :unprocessable_entity }
 			end
 		end
 	end
@@ -132,17 +123,16 @@ class TournamentsController < ApplicationController
 		@tournament = Tournament.find(params[:id])
 	end
 
-	def check_perms
-		unless (signed_in? and current_user.in_group?(:host))
-			respond_to do |format|
-				format.html { render action: 'permission_denied', status: :forbidden }
-				format.json { render json: "Permission denied", status: :forbidden }
-			end
-		end
-	end
-
 	# Never trust parameters from the scary internet, only allow the white list through.
 	def tournament_params
 		params.require(:tournament).permit(:game, :name, :game_id, :status, :min_players_per_team, :max_players_per_team, :min_teams_per_match, :max_teams_per_match, :set_rounds, :randomized_teams)
 	end
+
+	def is_owner?(object)
+		object.hosts.include?(current_user)
+	end
+
+	# Turn of check_edit, since our #update is flexible
+	def check_edit
+	end
 end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 60857f1..82edae7 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,7 +1,4 @@
 class UsersController < ApplicationController
-	before_action :set_user, only: [:show, :edit, :update, :destroy]
-	before_action :perms_edit, only: [:edit, :update, :destroy]
-	before_action :perms_create, only: [:new, :create]
 
 	# GET /users
 	# GET /users.json
@@ -69,22 +66,8 @@ class UsersController < ApplicationController
 		@user = User.find(params[:id])
 	end
 
-	def perms_edit
-		unless (current_user == @user) or (signed_in? and current_user.in_group? :admin)
-			respond_to do |format|
-				format.html { render action: 'permission_denied', status: :forbidden }
-				format.json { render json: "Permission denied", status: :forbidden }
-			end
-		end
-	end
-
-	def perms_create
-		if signed_in?
-			respond_to do |format|
-				format.html { render action: 'already_signed_in', status: :unprocessable_entity }
-				format.json { render json: "Already signed in", status: :unprocessable_entity }
-			end
-		end
+	def is_owner?(object)
+		object == current_user
 	end
 
 	# Never trust parameters from the scary internet, only allow the white list through.
-- 
cgit v1.2.3-2-g168b