diff options
Diffstat (limited to 'app')
48 files changed, 830 insertions, 245 deletions
diff --git a/app/assets/javascripts/ajax.js b/app/assets/javascripts/ajax.js new file mode 100644 index 0000000..040c100 --- /dev/null +++ b/app/assets/javascripts/ajax.js @@ -0,0 +1,19 @@ +function populate() { + //populate optionArray + //make a form element + var e = document.getElementById("tournament_id"); + var gameType = e.options[e.selectedIndex].text; + if (gameType != "Select a Game Type") { + alert(gameType + " was Selected!"); + //populate optionArray via AJAX + //select * from tournament_settings where gametype = GameType + for(var option in optionArray){ + //identify the number of + ; + } + }; + +//$.ajax(url: "/selected").done (html) -> $("#ajax-form").append html + +} + diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3192ec8..b3f5d46 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -11,3 +11,15 @@ *= require_self *= require_tree . */ + +#query{ + background-color: white; + border: 2px solid #ED9C28; + border-radius: 5px; + color: #FFF; + font-weight: bold; + height: 30px; +} +.navbar{ + background-color: white; +} diff --git a/app/assets/stylesheets/custom.css.scss b/app/assets/stylesheets/custom.css.scss new file mode 100644 index 0000000..1a9b09a --- /dev/null +++ b/app/assets/stylesheets/custom.css.scss @@ -0,0 +1,53 @@ +@import "bootstrap"; + +header > nav { + @extend .navbar; + @extend .navbar-inverse; + color: white; + + #log-buttons { + margin-top: 8px; + form { display: inline; } + } + form.search { + @extend .navbar-form; + @extend .navbar-right; + input[type="submit"] { + @extend .btn-warning; margin-top: -3px; margin-right: 8px; + } + } +} + +a, input[type="submit"] { + @extend .btn; + &.user { @extend .btn-info; } + &.signup { @extend .btn-success; } + &.signin { @extend .btn-info; } + &.signout { @extend .btn-danger; } +} + +p.errors { + background-color: #FCF8C7; + color: red; + border-radius: 7px; + padding: 10px; +} + +#errorExplanation { + h2 { + font-size: 1em; + color: red; + font-weight: bold; + } + li { + font-size: 1em; + color: red; + font-style: italic; + } + +} + +#notice { + text-align: center; + font-weight: bold; +}
\ No newline at end of file diff --git a/app/assets/stylesheets/scaffolds.css.scss b/app/assets/stylesheets/scaffolds.css.scss index 6ec6a8f..6700fef 100644 --- a/app/assets/stylesheets/scaffolds.css.scss +++ b/app/assets/stylesheets/scaffolds.css.scss @@ -1,3 +1,5 @@ +@import "bootstrap"; + body { background-color: #fff; color: #333; @@ -6,6 +8,10 @@ body { line-height: 18px; } +h1, h2, h3, h4, h5{ + color: #0f0f0f; +} + p, ol, ul, td { font-family: verdana, arial, helvetica, sans-serif; font-size: 13px; @@ -21,11 +27,11 @@ pre { a { color: #000; &:visited { - color: #666; + color: #000; } &:hover { - color: #fff; - background-color: #000; + color: green; + text-decoration: none; } } @@ -40,8 +46,9 @@ div { } .field_with_errors { - padding: 2px; - background-color: red; + padding: 1px; + background-color: #FF4C4C; + box-shadow: 0px 0px 5px red; display: table; } @@ -67,3 +74,26 @@ div { list-style: square; } } + +.navbar-brand { + @extend .no-dec; + a{ + color: white; + &:hover, &:active, &:focus { + color: white; + font-weight: normal; + text-decoration: none; + } + } +} + +footer { + text-align: center; + border-top: solid 1px #999999; + padding-top: 18px; + margin-top: 18px; +} + +button, input[type="submit"] { + @extend .btn; +} diff --git a/app/assets/stylesheets/static.css.scss b/app/assets/stylesheets/static.css.scss index 5a803c8..d73e77d 100644 --- a/app/assets/stylesheets/static.css.scss +++ b/app/assets/stylesheets/static.css.scss @@ -1,3 +1,12 @@ // Place all the styles related to the static controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ + +.jumbotron { + background-color: #FFF; + + p { + line-height: 1.5em; + } + +} diff --git a/app/assets/stylesheets/tournaments.css.scss b/app/assets/stylesheets/tournaments.css.scss index e372b90..458897e 100644 --- a/app/assets/stylesheets/tournaments.css.scss +++ b/app/assets/stylesheets/tournaments.css.scss @@ -1,3 +1,12 @@ // Place all the styles related to the tournaments controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ + +p.default-field { + display: inline; +} + +span.default-explanation { + color: gray; + font-style: italic; +} diff --git a/app/controllers/alerts_controller.rb b/app/controllers/alerts_controller.rb index 873e9b7..ac11854 100644 --- a/app/controllers/alerts_controller.rb +++ b/app/controllers/alerts_controller.rb @@ -1,5 +1,6 @@ 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 @@ -67,6 +68,15 @@ class AlertsController < ApplicationController @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 + end + # Never trust parameters from the scary internet, only allow the white list through. def alert_params params.require(:alert).permit(:author_id, :message) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e..7487f87 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,7 @@ class ApplicationController < ActionController::Base # 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 end diff --git a/app/controllers/matches_controller.rb b/app/controllers/matches_controller.rb index d79a7fc..b312e9e 100644 --- a/app/controllers/matches_controller.rb +++ b/app/controllers/matches_controller.rb @@ -1,10 +1,10 @@ class MatchesController < ApplicationController + before_action :set_tournament, only: [:index, :new, :create] before_action :set_match, only: [:show, :edit, :update, :destroy] - # GET /matches # GET /matches.json def index - @matches = Match.all + @matches = @tournament.matches end # GET /matches/1 @@ -14,7 +14,7 @@ class MatchesController < ApplicationController # GET /matches/new def new - @match = Match.new + end # GET /matches/1/edit @@ -24,11 +24,11 @@ class MatchesController < ApplicationController # POST /matches # POST /matches.json def create - @match = Match.new(match_params) + @match = @tournament.matches.build(match_params) respond_to do |format| if @match.save - format.html { redirect_to @match, notice: 'Match was successfully created.' } + 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' } @@ -42,7 +42,7 @@ class MatchesController < ApplicationController def update respond_to do |format| if @match.update(match_params) - format.html { redirect_to @match, notice: 'Match was successfully updated.' } + format.html { redirect_to [@tournament, @match], notice: 'Match was successfully updated.' } format.json { head :no_content } else format.html { render action: 'edit' } @@ -54,19 +54,22 @@ class MatchesController < ApplicationController # DELETE /matches/1 # DELETE /matches/1.json def destroy + @match.destroy respond_to do |format| - format.html { redirect_to matches_url } - format.json { head :no_content } + format.html { redirect_to tournament_matches_path } end end private # Use callbacks to share common setup or constraints between actions. def set_match - @match = Match.find(params[:id]) + @tournament = Tournament.find(params[:tournament_id]) + @match = @tournament.matches.find(params[:id]); + end + def set_tournament + @tournament = Tournament.find(params[:tournament_id]) end - # Never trust parameters from the scary internet, only allow the white list through. def match_params params.require(:match).permit(:status, :tournament_id, :name, :winner_id) diff --git a/app/controllers/servers_controller.rb b/app/controllers/servers_controller.rb index 7d54eb6..bb5d5f7 100644 --- a/app/controllers/servers_controller.rb +++ b/app/controllers/servers_controller.rb @@ -1,5 +1,6 @@ class ServersController < ApplicationController before_action :set_server, only: [:show, :edit, :update, :destroy] + before_action :check_perms # GET /servers # GET /servers.json @@ -67,6 +68,15 @@ class ServersController < ApplicationController @server = Server.find(params[:id]) end + def check_perms + unless (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 + # Never trust parameters from the scary internet, only allow the white list through. def server_params params[:server] diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 2f72bf7..7cb16e8 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,74 +1,52 @@ class SessionsController < ApplicationController - before_action :set_session, only: [:show, :edit, :update, :destroy] - - # GET /sessions - # GET /sessions.json - def index - @sessions = Session.all - end - - # GET /sessions/1 - # GET /sessions/1.json - def show - end - - # GET /sessions/new - def new - @session = Session.new - end - - # GET /sessions/1/edit - def edit - end - - # POST /sessions - # POST /sessions.json - def create - @session = Session.new(session_params) - - respond_to do |format| - if @session.save - format.html { redirect_to @session, notice: 'Session was successfully created.' } - format.json { render action: 'show', status: :created, location: @session } - else - format.html { render action: 'new' } - format.json { render json: @session.errors, status: :unprocessable_entity } - end - end - end - - # PATCH/PUT /sessions/1 - # PATCH/PUT /sessions/1.json - def update - respond_to do |format| - if @session.update(session_params) - format.html { redirect_to @session, notice: 'Session was successfully updated.' } - format.json { head :no_content } - else - format.html { render action: 'edit' } - format.json { render json: @session.errors, status: :unprocessable_entity } - end - end - end - - # DELETE /sessions/1 - # DELETE /sessions/1.json - def destroy - @session.destroy - respond_to do |format| - format.html { redirect_to sessions_url } - format.json { head :no_content } - end - end - - private - # Use callbacks to share common setup or constraints between actions. - def set_session - @session = Session.find(params[:id]) - end - - # Never trust parameters from the scary internet, only allow the white list through. - def session_params - params.require(:session).permit(:user_id) - end + before_action :set_session, only: [:destroy] + + # GET /sessions/new + def new + @user = User.new + #@session = Session.new + end + + # POST /sessions + # POST /sessions.json + def create + # find the user... + @user = User.find_by_email(params[:session][:username_or_email]) || User.find_by_user_name(params[:session][:username_or_email]) + + #@session = Session.new(@user) + # ... and create a new session + respond_to do |format| + if @user && @user.authenticate(params[:session][:password]) + sign_in @user + format.html { redirect_to root_path } + #format.json { #TODO } + else + format.html { render action: 'new' } + format.json { render json: @user.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /sessions/1 + # DELETE /sessions/1.json + def destroy + #@session.destroy + sign_out + respond_to do |format| + format.html { redirect_to root_path } + format.json { head :no_content } + end + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_session + #@session = Session.find(cookies[:remember_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 end diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb index c6df11e..6fc9490 100644 --- a/app/controllers/static_controller.rb +++ b/app/controllers/static_controller.rb @@ -1,2 +1,4 @@ class StaticController < ApplicationController + def homepage + end end diff --git a/app/controllers/tournaments_controller.rb b/app/controllers/tournaments_controller.rb index d7db632..8d90758 100644 --- a/app/controllers/tournaments_controller.rb +++ b/app/controllers/tournaments_controller.rb @@ -1,5 +1,6 @@ class TournamentsController < ApplicationController - before_action :set_tournament, only: [:show, :edit, :update, :destroy] + before_action :set_tournament, only: [:show, :edit, :update, :destroy, :join] + before_action :check_perms, only: [:new, :create, :edit, :destroy] # GET /tournaments # GET /tournaments.json @@ -10,24 +11,37 @@ class TournamentsController < ApplicationController # GET /tournaments/1 # GET /tournaments/1.json def show + case @tournament.status + when 0 + when 1..2 + redirect_to "/tournaments/" + @tournament.id.to_s + "/matches" #tournament_matches_page(@tournament) + end end # GET /tournaments/new def new - @tournament = Tournament.new + @games = Game.all + @tournament = Tournament.new(game: Game.find_by_id(params[:game])) end # GET /tournaments/1/edit def edit + if params['close_action'] == 'close' + @tournament.status = 1 + @tournament.save + @tournament.setup(@tournament) + redirect_to "/tournaments" + end end # POST /tournaments # POST /tournaments.json def create @tournament = Tournament.new(tournament_params) - + @tournament.status = 0 respond_to do |format| if @tournament.save + @tournament.hosts.push(current_user) format.html { redirect_to @tournament, notice: 'Tournament was successfully created.' } format.json { render action: 'show', status: :created, location: @tournament } else @@ -40,13 +54,45 @@ class TournamentsController < ApplicationController # PATCH/PUT /tournaments/1 # PATCH/PUT /tournaments/1.json def update - respond_to do |format| - if @tournament.update(tournament_params) - format.html { redirect_to @tournament, notice: 'Tournament was successfully updated.' } - format.json { head :no_content } + + if params[:update_action].nil? + check_perms + respond_to do |format| + if @tournament.update(tournament_params) + format.html { redirect_to @tournament, notice: 'Tournament was successfully updated.' } + format.json { head :no_content } + else + format.html { render action: 'edit' } + 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 } + 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 } + end + #when "close" + # TODO else - format.html { render action: 'edit' } - format.json { render json: @tournament.errors, status: :unprocessable_entity } + 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 end @@ -67,8 +113,19 @@ 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(:name, :game_id, :status, :min_players_per_team, :max_players_per_team, :min_teams_per_match, :max_teams_per_match, :set_rounds, :randomized_teams) + + 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 end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index b18efed..70facca 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,7 @@ 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 @@ -10,6 +12,7 @@ class UsersController < ApplicationController # GET /users/1 # GET /users/1.json def show + @user = User.find(params[:id]) end # GET /users/new @@ -25,13 +28,14 @@ class UsersController < ApplicationController # POST /users.json def create @user = User.new(user_params) - + @user.groups = 0 respond_to do |format| if @user.save - format.html { redirect_to @user, notice: 'User was successfully created.' } + sign_in @user + format.html { redirect_to root_path, notice: 'User was successfully created.' } format.json { render action: 'show', status: :created, location: @user } else - format.html { render action: 'new' } + format.html { render action: 'new', status: :unprocessable_entity } format.json { render json: @user.errors, status: :unprocessable_entity } end end @@ -67,8 +71,26 @@ 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 + end + # Never trust parameters from the scary internet, only allow the white list through. def user_params - params.require(:user).permit(:name, :email, :user_name) + params.require(:user).permit(:name, :email, :user_name, :password, :password_confirmation) end end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 309f8b2..046ca6f 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,2 +1,73 @@ module SessionsHelper + + def sign_in(user) + #create a new remember token + remember_token = User.new_remember_token + #place token inside of the browser + cookies.permanent[:remember_token] = remember_token + #save the hashed token to the database + user.update_attribute(:remember_token, + User.hash(remember_token)) + #set the current user to be the given user + self.current_user = user + end + +# The curret_user=(user) is the conversion of self.current_user = user + def current_user=(user) + @current_user = user + end + +# sets the @current_user instance virable to the user corresponding +# to the remember token, but only if @current_user is undefined +# since the remember token is hashed, we need to hash the cookie +# to find match the remember token + def current_user + remember_token = User.hash(cookies[:remember_token]) + @current_user ||= User.find_by(remember_token: remember_token) + end + + # checks if someone is currently signed in + def signed_in? + !current_user.nil? + end + + def sign_out + current_user.update_attribute(:remember_token, User.hash(User.new_remember_token)) + cookies.delete(:remember_token) + self.current_user = nil + end + +=begin + +This is for anyone that cares about how long a user is signed +in: + +Currently I have a user to be signed in forever unless they +log out (cookies.permanent....). + +If you want to change that, change line 7 to this: + +cookies[:remember_token] = { value: remember_token, + expires: 20.years.from_now.utc } + +which will expire the cookie in 20 years from its date of +creation. + +Oddly enough, this line above is equivalent to the: + +cookies.permanent + +This is just a short cut for this line since most people +create permanent cookies these days. + +Other times are: + +10.weeks.from_now + +5.days.ago + +etc... + +=end + end diff --git a/app/models/match.rb b/app/models/match.rb index bb814c1..782dce8 100644 --- a/app/models/match.rb +++ b/app/models/match.rb @@ -1,4 +1,8 @@ class Match < ActiveRecord::Base belongs_to :tournament - belongs_to :winner + + has_and_belongs_to_many :teams + + belongs_to :winner, class_name: "Team" + end diff --git a/app/models/team.rb b/app/models/team.rb index 9e71557..2348de5 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -1,3 +1,5 @@ class Team < ActiveRecord::Base belongs_to :match + has_and_belongs_to_many :matches + has_and_belongs_to_many :users end diff --git a/app/models/tournament.rb b/app/models/tournament.rb index cc915a0..69bedf5 100644 --- a/app/models/tournament.rb +++ b/app/models/tournament.rb @@ -1,3 +1,42 @@ class Tournament < ActiveRecord::Base - belongs_to :game + belongs_to :game + has_many :matches + has_and_belongs_to_many :players, class_name: "User", association_foreign_key: "player_id", join_table: "players_tournaments" + has_and_belongs_to_many :hosts, class_name: "User", association_foreign_key: "host_id", join_table: "hosts_tournaments" + + def open? + return true + end + + def joinable_by?(user) + return ((not user.nil?) and user.in_group?(:player) and open?) + end + + def join(user) + unless joinable_by?(user) + return false + end + players.push(user) + end + + def setup(tournament) + num_teams = (self.players.count/self.max_players_per_team).floor + num_matches = num_teams - 1 + for i in 1..num_matches + self.matches.create(name: "Match #{i}") + end + match_num = 0 + team_num = 0 + self.players.each_slice(tournament.max_players_per_team) do |players| + self.matches[match_num].teams.push(Team.create(users: players)) + if (team_num != 0 and team_num % tournament.max_teams_per_match == 0) + match_num += 1 + team_num = 0 + else + team_num += 1 + end + end + end + + end diff --git a/app/models/user.rb b/app/models/user.rb index 4a57cf0..6e439fb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,2 +1,151 @@ class User < ActiveRecord::Base + has_and_belongs_to_many :tournaments_played, class_name: "Tournament", foreign_key: "player_id", join_table: "players_tournaments" + has_and_belongs_to_many :tournaments_hosted, class_name: "Tournament", foreign_key: "host_id", join_table: "hosts_tournaments" + has_and_belongs_to_many :teams + + before_save { self.email = email.downcase } + before_save { self.user_name = user_name } + + ## + # Rails looks for the create_remember_token and runs the method + # before anything else. + # + # This method cannot be called by a user since it is denoted + # as private. + before_create :create_remember_token + + def in_group?(group) + case group + when :admin + return ((groups & 2) != 0) + when :host + return true #((groups & 1) != 0) + when :player + return true + when :specator + return true + else + return false + end + end + + def join_groups(join=[]) + # FIXME: race condition + join.each do |group| + case group + when :admin + groups |= 2 + when :host + groups |= 1 + else + end + end + end + + def leave_groups(leave=[]) + # FIXME: race condition + leave.each do |group| + case group + when :admin + groups &= ~ 2 + when :host + groups &= ~ 1 + else + end + end + end + + ## + # VAILD_EMAIL is the regex used to validate a user given email. + VALID_EMAIL_REG = /\A\S+@\S+\.\S+\z/i + + ## + # VALID_USER_NAME checks to make sure a user's user_name + # is in the proper format. + VALID_USER_NAME_REG = /\A[a-zA-Z0-9\-]+\z/ + + ## + # The following lines put a user account through a series of + # validations in order to make sure all of their information + # is in the proper format. + # + # validates :symbol_to_be_validated + # + # - presence: determines whether or not a symbol is filled or not + # - length: ensures there is a length limit on the symbol + # - format: checks the format of given information to ensure + # validity + validates(:name, presence: true, length: { maximum: 50 }) + validates(:email, presence: true, format: {with: + VALID_EMAIL_REG}, + uniqueness: { case_sensitive: false }) + validates(:user_name, presence: true, length:{maximum: 50}, + format: {with: VALID_USER_NAME_REG }, + uniqueness: {case_sensitive: false }) + + ## + # Instead of adding password and password_confirmation + # attributes, requiring the presence of a password, + # requiring that pw and pw_com match, and add an authenticate + # method to compare an encrypted password to the + # password_digest to authenticate users, I can just add + # has_secure_password which does all of this for me. + has_secure_password + + validates :password, length: { minimum: 6 } + + ## + # Create a random remember token for the user. This will be + # changed every time the user creates a new session. + # + # By changing the cookie every new session, any hijacked sessions + # (where the attacker steals a cookie to sign in as a certain + # user) will expire the next time the user signs back in. + # + # The random string is of length 16 composed of A-Z, a-z, 0-9 + # This is the browser's cookie value. + def User.new_remember_token + SecureRandom.urlsafe_base64 + end + + ## + # Encrypt the remember token. + # This is the encrypted version of the cookie stored on + # the database. + # + # The reasoning for storing a hashed token is so that even if + # the database is compromised, the attacker won't be able to use + # the remember tokens to sign in. + def User.hash(token) + Digest::SHA1.hexdigest(token.to_s) + end + + ## + # SHA-1 (Secure Hash Algorithm) is a US engineered hash + # function that produces a 20 byte hash value which typically + # forms a hexadecimal number 40 digits long. + # The reason I am not using the Bcrypt algorithm is because + # SHA-1 is much faster and I will be calling this on + # every page a user accesses. + # + # https://en.wikipedia.org/wiki/SHA-1 + + + # Everything under private is hidden so you cannot call. + private + + ## + # Create_remember_token in order to ensure a user always has + # a remember token. + def create_remember_token + self.remember_token = User.hash(User.new_remember_token) + end + + ## + # In order to ensure that someone did not accidentally submit + # two accounts rapidly (which would throw off the validates + # for user_name and email), I added an index to the Users + # email and user_name in the database to ensure uniqueness + # This also gives and index to the user_name and email + # so finding a user SHOULD be easier for the database. end diff --git a/app/views/alerts/show.html.erb b/app/views/alerts/show.html.erb index eeab7f7..5dda2c9 100644 --- a/app/views/alerts/show.html.erb +++ b/app/views/alerts/show.html.erb @@ -1,5 +1,3 @@ -<p id="notice"><%= notice %></p> - <p> <strong>Author:</strong> <%= @alert.author %> diff --git a/app/views/application/permission_denied.html.erb b/app/views/application/permission_denied.html.erb new file mode 100644 index 0000000..1ef883c --- /dev/null +++ b/app/views/application/permission_denied.html.erb @@ -0,0 +1 @@ +<h1>Permission denied</h1> diff --git a/app/views/common/_error_messages.html.erb b/app/views/common/_error_messages.html.erb new file mode 100644 index 0000000..731f62c --- /dev/null +++ b/app/views/common/_error_messages.html.erb @@ -0,0 +1,11 @@ +<%# http://railscasts.com/episodes/211-validations-in-rails-3 %> +<% if target.errors.any? %> +<div id="errorExplanation"> + <h2><%= pluralize(target.errors.count, "error") %> prohibited this form from being submitted:</h2> + <ul> + <% target.errors.full_messages.each do |msg| %> + <li><%= msg %></li> + <% end %> + </ul> +</div> +<% end %> diff --git a/app/views/games/index.html.erb b/app/views/games/index.html.erb index 27c5860..79acd1e 100644 --- a/app/views/games/index.html.erb +++ b/app/views/games/index.html.erb @@ -1,6 +1,6 @@ <h1>Listing games</h1> -<table> +<table class="table table-hover"> <thead> <tr> <th>Name</th> @@ -36,4 +36,6 @@ <br> -<%= link_to 'New Game', new_game_path %> + +<%= link_to 'New Game', new_game_path, {:class => "btn btn-warning"} %> + diff --git a/app/views/games/show.html.erb b/app/views/games/show.html.erb index 1f1a154..39d4a97 100644 --- a/app/views/games/show.html.erb +++ b/app/views/games/show.html.erb @@ -1,5 +1,3 @@ -<p id="notice"><%= notice %></p> - <p> <strong>Name:</strong> <%= @game.name %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cefd1be..976ee85 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -5,10 +5,36 @@ <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%= javascript_include_tag "application", "data-turbolinks-track" => true %> <%= csrf_meta_tags %> + <%= yield :head %> </head> <body> +<header><nav> + <div class="navbar-brand"><%= link_to('Leaguer', root_path) %></div> + <div> + <%= form_tag("/search", method: "get", :class => "search") do %> + <%= text_field_tag(:query, nil, :placeholder => "Search") %> + <%= submit_tag("Go") %> + <% end %> + </div> -<%= yield %> + <div id="log-buttons"> + <% if signed_in? %> + <%= link_to current_user.user_name, current_user, :class => "user" %> + <%= link_to "Sign out", session_path("current"), method: "delete", :class => "signout" %> + <% else %> + <%= link_to "Log in", new_session_path, :class => "signin" %> + <%= link_to "Sign up", new_user_path, :class => "signup" %> + <% end %> + </div> +</nav></header> +<% if notice %><div id="notice"><p><%= notice %></p></div><% end %> + +<div class="container"><%= yield %></div> + +<footer> + <p>Leaguer © 2014, Tomer Kimia, Andrew Murrell, Luke Shumaker, Nathaniel Foy, Davis Webb, and Guntas Grewal</p> +</footer> +<%= debug(params) if Rails.env.development? %> </body> </html> diff --git a/app/views/matches/_form.html.erb b/app/views/matches/_form.html.erb index 727c002..3efb566 100644 --- a/app/views/matches/_form.html.erb +++ b/app/views/matches/_form.html.erb @@ -1,16 +1,5 @@ -<%= form_for(@match) do |f| %> - <% if @match.errors.any? %> - <div id="error_explanation"> - <h2><%= pluralize(@match.errors.count, "error") %> prohibited this match from being saved:</h2> - - <ul> - <% @match.errors.full_messages.each do |msg| %> - <li><%= msg %></li> - <% end %> - </ul> - </div> - <% end %> - +<%= form_for([@tournament, @tournament.matches.build]) do |f| %> + <div class="field"> <%= f.label :status %><br> <%= f.number_field :status %> @@ -23,10 +12,6 @@ <%= f.label :name %><br> <%= f.text_field :name %> </div> - <div class="field"> - <%= f.label :winner_id %><br> - <%= f.text_field :winner_id %> - </div> <div class="actions"> <%= f.submit %> </div> diff --git a/app/views/matches/index.html.erb b/app/views/matches/index.html.erb index 400efb4..d862d57 100644 --- a/app/views/matches/index.html.erb +++ b/app/views/matches/index.html.erb @@ -14,15 +14,16 @@ </thead> <tbody> - <% @matches.each do |match| %> + <% @tournament.matches.each do |match| %> <tr> + <td><%= match.tournament.id %></td> <td><%= match.status %></td> <td><%= match.tournament %></td> <td><%= match.name %></td> <td><%= match.winner %></td> - <td><%= link_to 'Show', match %></td> - <td><%= link_to 'Edit', edit_match_path(match) %></td> - <td><%= link_to 'Destroy', match, method: :delete, data: { confirm: 'Are you sure?' } %></td> + <td><%= link_to 'Show', tournament_match_path(@tournament, match) %></td> + <td><%= link_to 'Edit', edit_tournament_match_path(@tournament, match) %></td> + <td><%= link_to 'Destroy', tournament_match_path(@tournament, match), method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> @@ -30,4 +31,4 @@ <br> -<%= link_to 'New Match', new_match_path %> +<%= link_to 'New Match', new_tournament_match_path %> diff --git a/app/views/matches/new.html.erb b/app/views/matches/new.html.erb index bd4c78c..74e7e3a 100644 --- a/app/views/matches/new.html.erb +++ b/app/views/matches/new.html.erb @@ -1,5 +1,3 @@ <h1>New match</h1> <%= render 'form' %> - -<%= link_to 'Back', matches_path %> diff --git a/app/views/matches/show.html.erb b/app/views/matches/show.html.erb index f3fc822..6b962ad 100644 --- a/app/views/matches/show.html.erb +++ b/app/views/matches/show.html.erb @@ -1,5 +1,3 @@ -<p id="notice"><%= notice %></p> - <p> <strong>Status:</strong> <%= @match.status %> @@ -7,7 +5,7 @@ <p> <strong>Tournament:</strong> - <%= @match.tournament %> + <%= @match.tournament.id %> </p> <p> @@ -15,10 +13,23 @@ <%= @match.name %> </p> -<p> - <strong>Winner:</strong> - <%= @match.winner %> -</p> +<% if (@tournament.hosts.include?(current_user) and @match.winner.nil?) %> + <%= form_for([@tournament, @match], method: "put") do |f| %> + <ul> + <% @match.teams.each do |team| %> + <li><label><%= f.radio_button(:winner, team.id) %> + <%= team.users.collect{|u| u.user_name}.join(", ") %></label></li> + <% end %> + </ul> + <%= f.submit("Select winner") %> + <% end %> +<% end %> + +<% unless @match.winner.nil? %> + <p> + <strong>Winner:</strong> + <%= @match.winner.users.collect{|u| u.user_name}.join(", ") %> + </p> +<% end %> -<%= link_to 'Edit', edit_match_path(@match) %> | -<%= link_to 'Back', matches_path %> +<%= link_to 'Back', tournament_matches_path %> diff --git a/app/views/pms/show.html.erb b/app/views/pms/show.html.erb index 5ee483f..2a03716 100644 --- a/app/views/pms/show.html.erb +++ b/app/views/pms/show.html.erb @@ -1,5 +1,3 @@ -<p id="notice"><%= notice %></p> - <p> <strong>Author:</strong> <%= @pm.author %> diff --git a/app/views/servers/show.html.erb b/app/views/servers/show.html.erb index 039cd8f..67f7647 100644 --- a/app/views/servers/show.html.erb +++ b/app/views/servers/show.html.erb @@ -1,4 +1,2 @@ -<p id="notice"><%= notice %></p> - <%= link_to 'Edit', edit_server_path(@server) %> | <%= link_to 'Back', servers_path %> diff --git a/app/views/sessions/_form.html.erb b/app/views/sessions/_form.html.erb deleted file mode 100644 index 1b94e77..0000000 --- a/app/views/sessions/_form.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -<%= form_for(@session) do |f| %> - <% if @session.errors.any? %> - <div id="error_explanation"> - <h2><%= pluralize(@session.errors.count, "error") %> prohibited this session from being saved:</h2> - - <ul> - <% @session.errors.full_messages.each do |msg| %> - <li><%= msg %></li> - <% end %> - </ul> - </div> - <% end %> - - <div class="field"> - <%= f.label :user_id %><br> - <%= f.text_field :user_id %> - </div> - <div class="actions"> - <%= f.submit %> - </div> -<% end %> diff --git a/app/views/sessions/edit.html.erb b/app/views/sessions/edit.html.erb deleted file mode 100644 index bbd8407..0000000 --- a/app/views/sessions/edit.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -<h1>Editing session</h1> - -<%= render 'form' %> - -<%= link_to 'Show', @session %> | -<%= link_to 'Back', sessions_path %> diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb deleted file mode 100644 index 707a47d..0000000 --- a/app/views/sessions/index.html.erb +++ /dev/null @@ -1,27 +0,0 @@ -<h1>Listing sessions</h1> - -<table> - <thead> - <tr> - <th>User</th> - <th></th> - <th></th> - <th></th> - </tr> - </thead> - - <tbody> - <% @sessions.each do |session| %> - <tr> - <td><%= session.user %></td> - <td><%= link_to 'Show', session %></td> - <td><%= link_to 'Edit', edit_session_path(session) %></td> - <td><%= link_to 'Destroy', session, method: :delete, data: { confirm: 'Are you sure?' } %></td> - </tr> - <% end %> - </tbody> -</table> - -<br> - -<%= link_to 'New Session', new_session_path %> diff --git a/app/views/sessions/index.json.jbuilder b/app/views/sessions/index.json.jbuilder deleted file mode 100644 index 18fd4fa..0000000 --- a/app/views/sessions/index.json.jbuilder +++ /dev/null @@ -1,4 +0,0 @@ -json.array!(@sessions) do |session| - json.extract! session, :id, :user_id - json.url session_url(session, format: :json) -end diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index 55c9eca..b4acf77 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,5 +1,23 @@ -<h1>New session</h1> +<h1>Sign in</h1> +<% if @user.nil? %> + <p class="errors"> The email/username or password is incorrect. Verify that CAPS LOCK is not on, and then retype the current email/username and password. </p> +<% end %> -<%= render 'form' %> + <div class="span6 offset3"> + <%= form_for(:session, url: sessions_path) do |f| %> + <p> + <%= f.label(:username_or_email, "Username/Email") %><br/> + <%= f.text_field :username_or_email%> + </p> + <p> + <%= f.label :password %><br/> + <%= f.password_field :password %> + </p> + <p> + <%= f.submit "Sign in", class: "btn btn-large btn-primary" %> + </p> + <% end %> + + <p>New user? <%= link_to("Sign up now!", new_user_path) %></p> + </div> -<%= link_to 'Back', sessions_path %> diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb deleted file mode 100644 index 5176869..0000000 --- a/app/views/sessions/show.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -<p id="notice"><%= notice %></p> - -<p> - <strong>User:</strong> - <%= @session.user %> -</p> - -<%= link_to 'Edit', edit_session_path(@session) %> | -<%= link_to 'Back', sessions_path %> diff --git a/app/views/sessions/show.json.jbuilder b/app/views/sessions/show.json.jbuilder deleted file mode 100644 index 4ebf936..0000000 --- a/app/views/sessions/show.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.extract! @session, :id, :user_id, :created_at, :updated_at diff --git a/app/views/static/homepage.html.erb b/app/views/static/homepage.html.erb new file mode 100644 index 0000000..3ca8176 --- /dev/null +++ b/app/views/static/homepage.html.erb @@ -0,0 +1,18 @@ +<div role="main" class="container theme-showcase"> + + <div class="jumbotron"> + <h1>Welcome to Leaguer</h1> + <p>This is a tournment management system designed to be used for any team sport. Our peer review system ensures that the best players move on to the next round! Try creating a new tournament and having people sign up for it. </p> + <p id="jumbo-buttons"> + <% if !signed_in? %> + <%= link_to 'Log In', new_session_path, :class => "btn btn-warning btn-lg", :role => "button" %> + <%= link_to 'Sign Up', new_user_path, :class => "btn btn-warning btn-lg", :role => "button" %> + <% else %> + <%= link_to 'Start a Tournament', new_tournament_path, :class => "btn btn-warning btn-lg", :role => "button" %> + <% end %> + <%= link_to 'See Ongoing Tournaments', tournaments_path, :class => "btn btn-warning btn-lg", :role => "button" %> + + </p> + </div> + + </div> diff --git a/app/views/tournaments/_selected.html.erb b/app/views/tournaments/_selected.html.erb new file mode 100644 index 0000000..8734b14 --- /dev/null +++ b/app/views/tournaments/_selected.html.erb @@ -0,0 +1,21 @@ +<%= form_for(@tournament) do |f| %> + <%= render "common/error_messages", :target => @tournament %> + <%= f.hidden_field(:game_id) %> + + <% @chosen = Game.find_by(params[:game]) %> + <% @tournament.attributes.each do |name, value| %> + <% if (name == "id") or (name =~ /.*_at$/) or (name == "game_id") or (name == "status") %> + <% next %> + <% end %> + <p> + <%= f.label name %><br> + <% if !@chosen.attributes[name].nil? %> + <%= f.text_field(name, :value => @chosen.attributes[name] ) %> + <% else %> + <%= f.text_field name %> + <% end %> + </p> + <% end %> + + <%= f.submit %> +<% end %> diff --git a/app/views/tournaments/index.html.erb b/app/views/tournaments/index.html.erb index f8f21e7..90c3d7a 100644 --- a/app/views/tournaments/index.html.erb +++ b/app/views/tournaments/index.html.erb @@ -1,16 +1,14 @@ -<h1>Listing tournaments</h1> +<h1>Listing Tournaments</h1> -<table> +<% if @tournaments.length > 0 %> +<table class="table table-hover"> <thead> <tr> <th>Name</th> <th>Game</th> <th>Status</th> - <th>Min players per team</th> - <th>Max players per team</th> - <th>Min teams per match</th> - <th>Max teams per match</th> - <th>Set rounds</th> + <th>Players per team</th> + <th>Teams per match</th> <th>Randomized teams</th> <th></th> <th></th> @@ -22,13 +20,28 @@ <% @tournaments.each do |tournament| %> <tr> <td><%= tournament.name %></td> - <td><%= tournament.game %></td> - <td><%= tournament.status %></td> - <td><%= tournament.min_players_per_team %></td> - <td><%= tournament.max_players_per_team %></td> - <td><%= tournament.min_teams_per_match %></td> - <td><%= tournament.max_teams_per_match %></td> - <td><%= tournament.set_rounds %></td> + <td><% case tournament.status + when 0 %> + <%= form_tag(tournament_path(tournament), method: "put") do %> + <input type="hidden" name="update_action" value="join"> + <%= submit_tag("Join") %> + <% end %> + <% when 1 %> + Ongoing + <% else %> + Closed + <%end %> + </td> + <td><%= tournament.min_players_per_team %> + <% if tournament.min_players_per_team != tournament.max_players_per_team %> + to <%= tournament.max_players_per_team %> + <% end %> + </td> + <td><%= tournament.min_teams_per_match %> + <% if tournament.min_teams_per_match != tournament.max_teams_per_match %> + to <%= tournament.max_teams_per_match %> + <% end %> + </td> <td><%= tournament.randomized_teams %></td> <td><%= link_to 'Show', tournament %></td> <td><%= link_to 'Edit', edit_tournament_path(tournament) %></td> @@ -37,7 +50,9 @@ <% end %> </tbody> </table> - +<% else %> + <p class="no-entries"> No tournaments going on right now... Why not start your own? </p> +<% end %> <br> -<%= link_to 'New Tournament', new_tournament_path %> +<%= link_to 'New Tournament', new_tournament_path, :class => "btn btn-warning btn-lg" %> diff --git a/app/views/tournaments/join.html.erb b/app/views/tournaments/join.html.erb new file mode 100644 index 0000000..1d38d68 --- /dev/null +++ b/app/views/tournaments/join.html.erb @@ -0,0 +1,2 @@ + <%= @user.name %> + diff --git a/app/views/tournaments/new.html.erb b/app/views/tournaments/new.html.erb index 2a60539..8c74068 100644 --- a/app/views/tournaments/new.html.erb +++ b/app/views/tournaments/new.html.erb @@ -1,5 +1,16 @@ -<h1>New tournament</h1> +<h1>New Tournament</h1> -<%= render 'form' %> +<%= form_tag(new_tournament_path, method: "get") do %> + <%= select_tag('game', + options_from_collection_for_select(@games, 'id', 'name', @tournament.game.nil? || @tournament.game.id), + :prompt => "Select a Game Type") %> + <%= submit_tag("Select", :class => "btn btn-success btn-xs") %> +<% end %> + +<div id='ajax-form'> + <% if not @tournament.game.nil? %> + <%= render 'selected' %> + <% end %> +</div> <%= link_to 'Back', tournaments_path %> diff --git a/app/views/tournaments/show.html.erb b/app/views/tournaments/show.html.erb index 3cb6179..3de0623 100644 --- a/app/views/tournaments/show.html.erb +++ b/app/views/tournaments/show.html.erb @@ -1,5 +1,19 @@ -<p id="notice"><%= notice %></p> +<% if @tournament.joinable_by?(current_user) %> + <%= form_tag(tournament_path(@tournament), method: "put") do %> + <input type="hidden" name="update_action" value="join"> + <%= current_user.name %><%= submit_tag("Join") %> + <% end %> +<% end %> + +<div class="progress"> + <%= tag("div", {:class => "progress-bar progress-bar-warning", :style => "width: " +(@tournament.players.count * 100 / (@tournament.min_players_per_team * @tournament.min_teams_per_match)).to_s + "%", "aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => (@tournament.players.count * 100 / (@tournament.min_players_per_team * @tournament.min_teams_per_match)).to_s, "role" => "progressbar"}) %> + <span class="sr-only">60% Complete (warning)</span> + </div> +</div> +<p><%= @tournament.players.count %> have signed up. <%= @tournament.min_players_per_team * @tournament.min_teams_per_match %> needed. </p> + +<% if current_user.in_group?(:host) %> <p> <strong>Name:</strong> <%= @tournament.name %> @@ -7,7 +21,7 @@ <p> <strong>Game:</strong> - <%= @tournament.game %> + <%= @tournament.id %> </p> <p> @@ -45,5 +59,22 @@ <%= @tournament.randomized_teams %> </p> +<p> + <strong>Status:</strong> + <%= @tournament.status %> +</p> + +<%= form_tag(tournaments_path.to_s + "/" + @tournament.id.to_s + "/edit", method: "get") do %> + <input type="hidden" name="close_action" value="close"> + <% if @tournament.players.count >= @tournament.min_players_per_team * @tournament.min_teams_per_match %> + <%= submit_tag("Close Tournament Registration") %> + <% else %> + <%= submit_tag("Close Tournament Registration", disabled: true) %> + <% end %> +<% end %> + <%= link_to 'Edit', edit_tournament_path(@tournament) %> | <%= link_to 'Back', tournaments_path %> + +<% end %> + diff --git a/app/views/users/already_signed_in.html.erb b/app/views/users/already_signed_in.html.erb new file mode 100644 index 0000000..04b4248 --- /dev/null +++ b/app/views/users/already_signed_in.html.erb @@ -0,0 +1 @@ +<h1>You are currently signed in</h1> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 3692112..89e369a 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,8 +1,9 @@ <h1>Listing users</h1> -<table> +<table class="table table-hover"> <thead> <tr> + <th>Username</th> <th>Name</th> <th>Email</th> <th>User name</th> @@ -15,8 +16,9 @@ <tbody> <% @users.each do |user| %> <tr> + <td><%= link_to("#{user.user_name}", user, nil) %></td> <td><%= user.name %></td> - <td><%= user.email %></td> + <td> ******* </td> <td><%= user.user_name %></td> <td><%= link_to 'Show', user %></td> <td><%= link_to 'Edit', edit_user_path(user) %></td> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index efc0404..c23f76d 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,5 +1,32 @@ -<h1>New user</h1> +<h1> Sign Up </h1> -<%= render 'form' %> +<%= form_for @user do |f| %> + <%= render "common/error_messages", :target => @user %> + <p> + <%= f.label :name %><br> + <%= f.text_field :name %> + </p> + <p> + <%= f.label :email %><br> + <%= f.text_field :email %> + </p> + <p> + <%= f.label :user_name %><br> + <%= f.text_field :user_name %> + </p> + <p> + <%= f.label :password %><br> + <%= f.password_field :password %> + </p> + <p> + <%= f.label(:password_confirmation, "Confirm Password") %><br> + <%= f.password_field :password_confirmation %> + </p> + <p> + <%= f.submit("Be a Leaguer", :class => "signup") %> + </p> +<% end %> + + +<%= link_to 'Already Have an Account? Log in', new_session_path, :class => "signin" %> -<%= link_to 'Back', users_path %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 9455a3c..d8cc82b 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,5 +1,3 @@ -<p id="notice"><%= notice %></p> - <p> <strong>Name:</strong> <%= @user.name %> |