Skip to content

Commit

Permalink
Merge pull request hackclub#338 from hackclub/implement-admin-login
Browse files Browse the repository at this point in the history
Admin dashboard WIP
  • Loading branch information
maxwofford authored Jan 28, 2018
2 parents 0c99d26 + 8b12bdb commit d0bbee1
Show file tree
Hide file tree
Showing 40 changed files with 860 additions and 467 deletions.
2 changes: 1 addition & 1 deletion api/.rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Documentation:
#
# Example: the following test would be invalid with this check enabled.
#
# expect { Applicant.create }.to change { Applicant.count }.by 1
# expect { User.create }.to change { User.count }.by 1
#
Lint/AmbiguousBlockAssociation:
Exclude:
Expand Down
1 change: 1 addition & 0 deletions api/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ gem 'mimemagic', '~> 0.3'
gem 'octokit', '~> 4.7'
gem 'paranoia', '~> 2.4'
gem 'pdfkit', '~> 0.8.2'
gem 'pundit', '~> 1.1'
gem 'rack-cors', require: 'rack/cors'
gem 'redcarpet', '~> 3.4.0'
gem 'redis-rails', '~> 5.0.2'
Expand Down
3 changes: 3 additions & 0 deletions api/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ GEM
method_source (~> 0.9.0)
public_suffix (3.0.1)
puma (3.11.0)
pundit (1.1.0)
activesupport (>= 3.0.0)
rack (2.0.3)
rack-cors (1.0.2)
rack-protection (2.0.0)
Expand Down Expand Up @@ -327,6 +329,7 @@ DEPENDENCIES
pdfkit (~> 0.8.2)
pg (~> 0.18.4)
puma (~> 3.0)
pundit (~> 1.1)
rack-cors
rails (~> 5.1)
redcarpet (~> 3.4.0)
Expand Down
1 change: 1 addition & 0 deletions api/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true

# See V1::ApiController for base controller of API V1.
class ApplicationController < ActionController::API
end
5 changes: 5 additions & 0 deletions api/app/controllers/v1/api_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

module V1
class ApiController < ApplicationController
include Pundit

rescue_from Pundit::NotAuthorizedError, with: :render_access_denied
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found

def render_success(obj = { success: true }, status = 200)
render json: obj, status: status
end
Expand Down
40 changes: 0 additions & 40 deletions api/app/controllers/v1/applicants_controller.rb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# frozen_string_literal: true

# this is tested in spec/controllers/v1/concerns/
module ApplicantAuth
module UserAuth
extend ActiveSupport::Concern

included do
before_action :authenticate_applicant
before_action :authenticate_user
end

def authenticate_applicant
def authenticate_user
auth_header = request.headers['Authorization']
return render_unauthenticated unless auth_header

_auth_type, auth_token = auth_header.split(' ')
return render_invalid_authorization unless auth_token

@applicant = Applicant.find_by(auth_token: auth_token)
@user = User.find_by(auth_token: auth_token)

if @applicant
unless @applicant.auth_token_generation > (Time.current - 1.day)
if @user
unless @user.auth_token_generation > (Time.current - 1.day)
return render_error('auth token expired', 401)
end

Expand All @@ -28,6 +28,10 @@ def authenticate_applicant
end
end

def current_user
@user
end

protected

def render_unauthenticated
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
# frozen_string_literal: true

module V1
class ApplicantProfilesController < ApiController
include ApplicantAuth
class LeaderProfilesController < ApiController
include UserAuth

def show
profile = ApplicantProfile.find_by(id: params[:id])

return render_not_found unless profile
return render_access_denied if profile.applicant != @applicant
profile = LeaderProfile.find(params[:id])
authorize profile

render_success(profile)
end

def update
profile = ApplicantProfile.find_by(id: params[:id])

return render_not_found unless profile
return render_access_denied if profile.applicant != @applicant
profile = LeaderProfile.find(params[:id])
authorize profile

if profile.submitted_at.present?
return render_field_error(:base,
'cannot edit applicant profile after submit')
return render_field_error(
:base, 'cannot edit leader profile after submit'
)
end

# TODO: Check for errors and return them if needed
profile.update_attributes(applicant_profile_params)
profile.update_attributes(leader_profile_params)

render_success(profile)
end

private

def applicant_profile_params
def leader_profile_params
params.permit(
:leader_name,
:leader_email,
Expand Down
87 changes: 43 additions & 44 deletions api/app/controllers/v1/new_club_applications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,43 @@

module V1
class NewClubApplicationsController < ApiController
include ApplicantAuth
include UserAuth

# All applications
def full_index
return render_access_denied unless @user.admin?
render_success NewClubApplication.all
end

# Applications for a specific user
def index
if params[:applicant_id] == @applicant.id.to_s
render_success(@applicant.new_club_applications)
if params[:user_id] == @user.id.to_s
render_success(@user.new_club_applications)
else
render_access_denied
end
end

def show
application = NewClubApplication.find_by(id: params[:id])

return render_not_found unless application
application = NewClubApplication.find(params[:id])
authorize application

if application.applicants.include? @applicant
render_success(application)
else
render_access_denied
end
render_success(application)
end

def create
c = NewClubApplication.create(applicants: [@applicant],
point_of_contact: @applicant)
c = NewClubApplication.create(users: [@user], point_of_contact: @user)

render_success(c, 201)
end

def update
c = NewClubApplication.find(params[:id])
authorize c

return render_access_denied unless c.applicants.include? @applicant
if c.submitted? && !current_user.admin?
return render_field_error(:base, 'cannot edit application after submit')
end

if c.update_attributes(club_application_params)
render_success(c)
Expand All @@ -43,66 +47,58 @@ def update
end
end

def add_applicant
app = NewClubApplication.find_by(id: params[:new_club_application_id])

return render_not_found unless app
return render_access_denied unless app.applicants.include? @applicant
def add_user
app = NewClubApplication.find(params[:new_club_application_id])
authorize app

if app.submitted_at.present?
if app.submitted?
return render_field_error(:base, 'cannot edit application after submit')
end

to_add = Applicant.find_or_create_by(email: params[:email])
to_add = User.find_or_create_by(email: params[:email])

if app.applicants.include? to_add
if app.users.include? to_add
return render_field_error(:email, 'already added')
end

profile = ApplicantProfile.with_deleted.find_or_create_by(
applicant: to_add,
profile = LeaderProfile.with_deleted.find_or_create_by(
user: to_add,
new_club_application: app
)

profile.restore if profile.deleted?

ApplicantMailer.added_to_application(app, to_add, @applicant)
ApplicantMailer.added_to_application(app, to_add, @user)
.deliver_later

render_success
end

def remove_applicant
app = NewClubApplication.find_by(id: params[:new_club_application_id])
to_remove = Applicant.find_by(id: params[:applicant_id])
def remove_user
app = NewClubApplication.find(params[:new_club_application_id])
to_remove = User.find(params[:user_id])

return render_not_found unless app && to_remove
authorize app

return render_access_denied unless app.applicants.include? @applicant

return render_access_denied unless app.point_of_contact == @applicant

if app.submitted_at.present?
if app.submitted?
return render_field_error(:base, 'cannot edit application after submit')
end

if to_remove == @applicant
return render_field_error(:applicant_id, 'cannot remove self')
if to_remove == @user
return render_field_error(:user_id, 'cannot remove self')
end

unless app.applicants.include? to_remove
return render_field_error(:applicant_id, 'not added to application')
unless app.users.include? to_remove
return render_field_error(:user_id, 'not added to application')
end

app.applicants.delete(to_remove)
app.users.delete(to_remove)
render_success
end

def submit
app = NewClubApplication.find_by(id: params[:new_club_application_id])

return render_not_found unless app
return render_access_denied unless app.applicants.include? @applicant
app = NewClubApplication.find(params[:new_club_application_id])
authorize app

if app.submit!
render_success(app)
Expand Down Expand Up @@ -131,7 +127,10 @@ def club_application_params
:other_surprising_or_amusing_discovery,
:curious_what_convinced,
:curious_how_did_hear,
:point_of_contact_id
:point_of_contact_id,
:interviewed_at,
:interview_duration,
:interview_notes
)
end
end
Expand Down
40 changes: 40 additions & 0 deletions api/app/controllers/v1/users_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module V1
class UsersController < ApiController
def auth
user = User.find_or_initialize_by(email: params[:email])

user.generate_login_code!

if user.save
ApplicantMailer.login_code(user).deliver_later

render_success(user)
else
render_field_errors(user.errors)
end
end

def exchange_login_code
user = User.find_by(id: params[:user_id])
login_code = params[:login_code]

return render_not_found unless user

if !login_code.nil? &&
user.login_code == login_code &&
user.login_code_generation > (Time.current - 15.minutes)

user.generate_auth_token!
user.login_code = nil
user.login_code_generation = nil
user.save

return render_success(auth_token: user.auth_token)
end

render_field_error(:login_code, 'invalid', 401)
end
end
end
Binary file modified api/app/mailers/applicant_mailer.rb
Binary file not shown.
Loading

0 comments on commit d0bbee1

Please sign in to comment.