diff --git a/app.rb b/app.rb index 5e55474..0445a68 100755 --- a/app.rb +++ b/app.rb @@ -22,9 +22,9 @@ require 'json' require 'jwt' -require_relative 'helpers/init' -require_relative 'routes/init' -require_relative 'models/init' +require_relative './models/init' +require_relative './routes/init' +require_relative './helpers/init' class GrootRecruiterService < Sinatra::Base register Sinatra::AuthsRoutes @@ -38,40 +38,34 @@ class GrootRecruiterService < Sinatra::Base enable :logging end - configure :development do - enable :unsecure - - db = Config.load_config("development") - DataMapper::Logger.new($stdout, :debug) + configure :development, :production do + db = Config.load_config("database") DataMapper.setup( :default, "mysql://" + db["user"] + ":" + db["password"] + "@" + db["hostname"]+ "/" + db["name"] ) - use BetterErrors::Middleware - - # you need to set the application root in order to abbreviate filenames - # within the application: - BetterErrors.application_root = File.expand_path('..', __FILE__) - DataMapper.auto_upgrade! end configure :test do - db = Config.load_config("test") + db = Config.load_config("test_database") DataMapper.setup( :default, "mysql://" + db["user"] + ":" + db["password"] + "@" + db["hostname"]+ "/" + db["name"] ) + end + + configure :development do + enable :unsecure + + DataMapper::Logger.new($stdout, :debug) + use BetterErrors::Middleware + + BetterErrors.application_root = File.expand_path('..', __FILE__) DataMapper.auto_upgrade! end configure :production do disable :unsecure - - db = Config.load_config("production") - DataMapper.setup( - :default, - "mysql://" + db["user"] + ":" + db["password"] + "@" + db["hostname"]+ "/" + db["name"] - ) end DataMapper.finalize diff --git a/config/database.yaml.template b/config/database.yaml.template deleted file mode 100755 index b3c70fd..0000000 --- a/config/database.yaml.template +++ /dev/null @@ -1,11 +0,0 @@ -development: - user: root - password: "" - hostname: localhost - name: groot_recruiter_service_dev - -test: - user: root - password: "" - hostname: localhost - name: groot_recruiter_service_test \ No newline at end of file diff --git a/config/secrets.yaml.template b/config/secrets.yaml.template index 76434d7..738d10a 100755 --- a/config/secrets.yaml.template +++ b/config/secrets.yaml.template @@ -9,13 +9,13 @@ groot: jwt: secret: 'SECRET_JWT_TOKEN' -development: +database: user: root password: "" hostname: localhost - name: groot_recruiter_service_dev + name: groot_recruiter_service -test: +test_database: user: root password: "" hostname: localhost diff --git a/helpers/auth.rb b/helpers/auth.rb index 575e955..db7dfcc 100755 --- a/helpers/auth.rb +++ b/helpers/auth.rb @@ -10,13 +10,9 @@ require 'pry' module Auth - VERIFY_CORPORATE_URL = '/groups/committees/corporate?isMember=' + VERIFY_COMMITTEE_URL = '/groups/committees/' VALIDATE_SESSION_URL = '/session/' - def self.verify_request(request) - Config.load_config("groot")["request_key"] == request['HTTP_AUTHORIZATION'] - end - def self.services_url Config.load_config("groot")["host"] end @@ -26,17 +22,16 @@ def self.groot_access_key end # Verifies that an admin (defined by groups service) originated this request - def self.verify_corporate(request) + def self.verify_credentials(type, request) netid = request['HTTP_NETID'] - uri = URI.parse("#{Auth.services_url}#{VERIFY_CORPORATE_URL}#{netid}") + uri = URI.parse("#{Auth.services_url}#{VERIFY_COMMITTEE_URL}#{type}?isMember=#{netid}") http = Net::HTTP.new(uri.host, uri.port) request = Net::HTTP::Get.new(uri.request_uri) - request['Authorization'] = self.groot_access_key + request['Authorization'] = Auth.groot_access_key response = http.request(request) - return false unless response.code == "200" - JSON.parse(response.body)["isValid"] + return response.code == "200" end # Verifies that the session (validated by users service) is active @@ -61,7 +56,11 @@ def self.verify_session(request) JSON.parse(response.body)["token"] == session_token end - def self.verify_corporate_session(request) - self.verify_session(request) && self.verify_corporate(request) + def self.verify_admin_session(request) + self.verify_session(request) && ( + self.verify_credentials('admin', request) || + self.verify_credentials('top4', request) || + self.verify_credentials('corporate', request) + ) end end \ No newline at end of file diff --git a/helpers/config.rb b/helpers/config.rb index 5689c97..fb40d97 100755 --- a/helpers/config.rb +++ b/helpers/config.rb @@ -5,7 +5,6 @@ # The Groot Project is open source software, released under the University of # Illinois/NCSA Open Source License. You should have received a copy of # this license in a file with the distribution. -require 'yaml' module Config def self.load_config(section) diff --git a/helpers/errors.rb b/helpers/errors.rb index ade0161..406950f 100755 --- a/helpers/errors.rb +++ b/helpers/errors.rb @@ -11,8 +11,7 @@ module Errors ACCOUNT_EXPIRED = ResponseFormat.error "Your account has expired! Please reach out to corporate@acm.illinois.edu so that your account can be renewed!" DUPLICATE_ACCOUNT = ResponseFormat.error "An account with these credentials already exists." - VERIFY_CORPORATE_SESSION = ResponseFormat.error "Corporate session could not be verified" - VERIFY_GROOT = ResponseFormat.error "Request did not originate from groot" + VERIFY_ADMIN_SESSION = ResponseFormat.error "Corporate session could not be verified" FUTURE_DATE = ResponseFormat.error "You entered a date from the future" INVALID_DATE = ResponseFormat.error "Date was not in a readable format" diff --git a/routes/auth.rb b/routes/auth.rb index 160b512..8495d96 100755 --- a/routes/auth.rb +++ b/routes/auth.rb @@ -12,21 +12,17 @@ def self.registered(app) app.set port: 4567 app.set bind: '0.0.0.0' - app.before do - halt(401, Errors::VERIFY_GROOT) unless Auth.verify_request(env) || GrootRecruiterService.unsecure - end - app.get '/status' do ResponseFormat.message("OK") end app.get '/status/corporate' do - halt(403, Errors::VERIFY_CORPORATE_SESSION) unless Auth.verify_corporate(env) + halt(403, Errors::VERIFY_ADMIN_SESSION) unless Auth.verify_corporate(env) ResponseFormat.message("OK") end app.get '/status/session' do - halt(403, Errors::VERIFY_CORPORATE_SESSION) unless Auth.verify_session(env) + halt(403, Errors::VERIFY_ADMIN_SESSION) unless Auth.verify_session(env) ResponseFormat.message("OK") end diff --git a/routes/jobs.rb b/routes/jobs.rb index 84bc106..6fbec17 100755 --- a/routes/jobs.rb +++ b/routes/jobs.rb @@ -38,7 +38,7 @@ def self.registered(app) end app.put '/jobs/:job_id/approve' do - halt(400, Errors::VERIFY_CORPORATE_SESSION) unless Auth.verify_corporate_session(env) + halt(400, Errors::VERIFY_ADMIN_SESSION) unless Auth.verify_admin_session(env) status, error = Job.validate(params, [:job_id]) halt(status, ResponseFormat.error(error)) if error @@ -51,7 +51,7 @@ def self.registered(app) end app.delete '/jobs/:job_id' do - halt(400, Errors::VERIFY_CORPORATE_SESSION) unless Auth.verify_corporate_session(env) + halt(400, Errors::VERIFY_ADMIN_SESSION) unless Auth.verify_admin_session(env) status, error = Job.validate(params, [:job_id]) halt(status, ResponseFormat.error(error)) if error diff --git a/routes/recruiters.rb b/routes/recruiters.rb index 6591049..8e26bc3 100755 --- a/routes/recruiters.rb +++ b/routes/recruiters.rb @@ -12,7 +12,7 @@ module Sinatra module RecruitersRoutes def self.registered(app) app.get '/recruiters' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) conditions = {}.tap do |conditions| conditions[:type] = params[:type] if params[:type] && Recruiter.validate(params, [:type]) @@ -49,7 +49,7 @@ def self.registered(app) end app.post '/recruiters' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) params = ResponseFormat.get_params(request.body.read) @@ -83,14 +83,14 @@ def self.registered(app) end app.get '/recruiters/:recruiter_id' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) recruiter = Recruiter.get(params[:recruiter_id]) || halt(404, Errors::RECRUITER_NOT_FOUND) ResponseFormat.data(recruiter) end app.put '/recruiters/:recruiter_id' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) recruiter_id = params[:recruiter_id] params = ResponseFormat.get_params(request.body.read) @@ -138,7 +138,7 @@ def self.registered(app) end app.get '/recruiters/:recruiter_id/invite' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) recruiter = Recruiter.get(params[:recruiter_id]) halt 404, Errors::RECRUITER_NOT_FOUND unless recruiter @@ -155,7 +155,7 @@ def self.registered(app) end app.post '/recruiters/:recruiter_id/invite' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) recruiter_id = params[:recruiter_id] params = ResponseFormat.get_params(request.body.read) @@ -176,7 +176,7 @@ def self.registered(app) end app.put '/recruiters/:recruiter_id/renew' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) recruiter = Recruiter.get(params[:recruiter_id]) halt 404, Errors::RECRUITER_NOT_FOUND unless recruiter @@ -187,14 +187,14 @@ def self.registered(app) end app.post '/recruiters/reset' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) Recruiter.update(invited: false) ResponseFormat.message("Reset all recruiter invitations. You can now invite recruiters to fairs again") end app.delete '/recruiters/:recruiter_id' do - halt(400, Errors::VERIFY_CORPORATE_SESSION) unless Auth.verify_corporate_session(env) + halt(400, Errors::VERIFY_ADMIN_SESSION) unless Auth.verify_admin_session(env) recruiter = Recruiter.get(params[:recruiter_id]) halt 404, Errors::RECRUITER_NOT_FOUND unless recruiter diff --git a/routes/students.rb b/routes/students.rb index 9cb3bc6..9a47471 100755 --- a/routes/students.rb +++ b/routes/students.rb @@ -16,7 +16,7 @@ module StudentsRoutes def self.registered(app) app.get '/students' do payload = JWTAuth.decode(env) - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) || (payload[:code] == 200) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) || (payload[:code] == 200) graduation_start_date = Date.parse(params[:graduationStart]) rescue nil graduation_end_date = Date.parse(params[:graduationEnd]) rescue nil @@ -78,7 +78,7 @@ def self.registered(app) end app.put '/students/:netid/approve' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) status, error = Student.validate(params, [:netid]) halt status, ResponseFormat.error(error) if error @@ -98,7 +98,7 @@ def self.registered(app) end app.delete '/students/:netid' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) student = Student.first(netid: params[:netid]) || halt(404, Errors::STUDENT_NOT_FOUND) AWS.delete_resume(student.netid, student.resume_url) @@ -108,7 +108,7 @@ def self.registered(app) end app.post '/students/remind' do - halt 401, Errors::VERIFY_CORPORATE_SESSION unless Auth.verify_corporate_session(env) + halt 401, Errors::VERIFY_ADMIN_SESSION unless Auth.verify_admin_session(env) params = ResponseFormat.get_params(request.body.read) status, error = Student.validate(params, [:email, :last_updated_at]) diff --git a/spec/helpers/auth_spec.rb b/spec/helpers/auth_spec.rb index 682f446..97b9ef5 100755 --- a/spec/helpers/auth_spec.rb +++ b/spec/helpers/auth_spec.rb @@ -13,14 +13,6 @@ .to receive(:request) .and_return(double(code: "200", body: {token: token, isValid: 'true' }.to_json)) end - - describe 'self.verify_request' do - it 'should verify the token on the header' do - get "/status", {}, { "HTTP_AUTHORIZATION" => "#{token}" } - - expect(last_response).to be_ok - end - end describe 'self.verify_corporate' do it 'should make a post request to the right service' do diff --git a/spec/routes/jobs_spec.rb b/spec/routes/jobs_spec.rb index 208eefd..3b4fee7 100755 --- a/spec/routes/jobs_spec.rb +++ b/spec/routes/jobs_spec.rb @@ -2,8 +2,7 @@ RSpec.describe Sinatra::JobsRoutes do before :each do - expect(Auth).to receive(:verify_request).and_return(true) - allow(Auth).to receive(:verify_corporate_session).and_return(true) + allow(Auth).to receive(:verify_admin_session).and_return(true) end def match_job(datum, job) @@ -99,12 +98,12 @@ def match_job(datum, job) describe "PUT /jobs/:job_id/approve" do it 'should not allow a non-corporate user to access this route' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) put "/jobs/#{job.id}/approve" expect(last_response).not_to be_ok json_data = JSON.parse(last_response.body) - expect_error(json_data, Errors::VERIFY_CORPORATE_SESSION) + expect_error(json_data, Errors::VERIFY_ADMIN_SESSION) end it 'should approve an unapproved job' do @@ -133,12 +132,12 @@ def match_job(datum, job) describe "DELETE /jobs/:job_id" do it 'should not allow a non-corporate user to access this route' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) delete "/jobs/#{job.id}" expect(last_response).not_to be_ok json_data = JSON.parse(last_response.body) - expect_error(json_data, Errors::VERIFY_CORPORATE_SESSION) + expect_error(json_data, Errors::VERIFY_ADMIN_SESSION) end it 'should return an error if it cannot find the job by id' do diff --git a/spec/routes/recruiters_spec.rb b/spec/routes/recruiters_spec.rb index 8b7e8ae..e278b26 100755 --- a/spec/routes/recruiters_spec.rb +++ b/spec/routes/recruiters_spec.rb @@ -21,8 +21,7 @@ def match_recruiter(datum, recruiter) } before :each do - expect(Auth).to receive(:verify_request).and_return(true) - allow(Auth).to receive(:verify_corporate_session).and_return(true) + allow(Auth).to receive(:verify_admin_session).and_return(true) allow(Mailer).to receive(:email).and_return(true) end @@ -30,13 +29,13 @@ def match_recruiter(datum, recruiter) describe "GET /recruiters" do context 'for invalid parameters' do it 'should not allow a non-corporate user to access this route' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) get "/recruiters", {}.to_json expect(last_response).not_to be_ok json_data = JSON.parse(last_response.body) - expect_error(json_data, Errors::VERIFY_CORPORATE_SESSION) + expect_error(json_data, Errors::VERIFY_ADMIN_SESSION) end end @@ -183,12 +182,12 @@ def match_recruiter(datum, recruiter) describe "GET /recruiters/:recruiter_id" do it 'should return an error if the corporate session cannot be verified' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) get "/recruiters/#{recruiter.id}" expect(last_response).not_to be_ok json_response = JSON.parse(last_response.body) - expect(json_response.to_json).to eq Errors::VERIFY_CORPORATE_SESSION + expect(json_response.to_json).to eq Errors::VERIFY_ADMIN_SESSION end it 'should return an error if it cannot find a recruiter by id' do @@ -295,12 +294,12 @@ def match_recruiter(datum, recruiter) describe "GET /recruiters/:recruiter_id/invite" do it 'should return an error if the corporate session cannot be verified' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) get "/recruiters/#{recruiter.id}/invite" expect(last_response).not_to be_ok json_response = JSON.parse(last_response.body) - expect(json_response.to_json).to eq Errors::VERIFY_CORPORATE_SESSION + expect(json_response.to_json).to eq Errors::VERIFY_ADMIN_SESSION end it 'should return an error if it cannot find a recruiter by id' do @@ -337,12 +336,12 @@ def match_recruiter(datum, recruiter) include_examples "invalid parameters", [:to, :subject, :body, :email], "/recruiters/1/invite", "post" it 'should return an error if the corporate session cannot be verified' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) post "/recruiters/#{recruiter.id}/invite", valid_params.to_json expect(last_response).not_to be_ok json_response = JSON.parse(last_response.body) - expect(json_response.to_json).to eq Errors::VERIFY_CORPORATE_SESSION + expect(json_response.to_json).to eq Errors::VERIFY_ADMIN_SESSION end it 'should return an error if it cannot find a recruiter by id' do @@ -375,13 +374,13 @@ def match_recruiter(datum, recruiter) describe "PUT /recruiters/:recruiter_id/renew" do context 'for invalid parameters' do it 'should not allow a non-corporate user to access this route' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) put "/recruiters/#{recruiter.id}/renew", {}.to_json expect(last_response).not_to be_ok json_data = JSON.parse(last_response.body) - expect_error(json_data, Errors::VERIFY_CORPORATE_SESSION) + expect_error(json_data, Errors::VERIFY_ADMIN_SESSION) end it 'should return an error if the recruiter does not exist' do @@ -413,13 +412,13 @@ def match_recruiter(datum, recruiter) describe "POST /recruiters/reset" do context 'for invalid parameters' do it 'should not allow a non-corporate user to access this route' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) post "/recruiters/reset", {}.to_json expect(last_response).not_to be_ok json_data = JSON.parse(last_response.body) - expect_error(json_data, Errors::VERIFY_CORPORATE_SESSION) + expect_error(json_data, Errors::VERIFY_ADMIN_SESSION) end end @@ -435,13 +434,13 @@ def match_recruiter(datum, recruiter) describe "DELETE /recruiters/:recruiter_id" do context 'for invalid parameters' do it 'should not allow a non-corporate user to access this route' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) delete "/recruiters/#{recruiter.id}", {}.to_json expect(last_response).not_to be_ok json_data = JSON.parse(last_response.body) - expect_error(json_data, Errors::VERIFY_CORPORATE_SESSION) + expect_error(json_data, Errors::VERIFY_ADMIN_SESSION) end it 'should return an error if the recruiter does not exist' do diff --git a/spec/routes/students_spec.rb b/spec/routes/students_spec.rb index d6810d7..e9622f8 100755 --- a/spec/routes/students_spec.rb +++ b/spec/routes/students_spec.rb @@ -8,8 +8,7 @@ def match_student(datum, student) end before :each do - expect(Auth).to receive(:verify_request).and_return(true) - allow(Auth).to receive(:verify_corporate_session).and_return(true) + allow(Auth).to receive(:verify_admin_session).and_return(true) end let!(:netid) { "jsmith2" } @@ -29,13 +28,13 @@ def match_student(datum, student) describe 'GET /students' do context 'for invalid authentication' do it 'should not allow a non-corporate user to access this route' do - allow(Auth).to receive(:verify_corporate_session).and_return(false) + allow(Auth).to receive(:verify_admin_session).and_return(false) get "/students", {}.to_json expect(last_response).not_to be_ok json_data = JSON.parse(last_response.body) - expect_error(json_data, Errors::VERIFY_CORPORATE_SESSION) + expect_error(json_data, Errors::VERIFY_ADMIN_SESSION) end end