diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a52015059..55e75b7f2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -41,7 +41,7 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install -y netcat + sudo apt-get install -y netcat-traditional - name: Install Ruby dependencies run: | @@ -73,4 +73,4 @@ jobs: with: context: . push: false - tags: expertiza-backend:latest \ No newline at end of file + tags: expertiza-backend:latest diff --git a/Gemfile b/Gemfile index e76fed5cf..1786836d0 100644 --- a/Gemfile +++ b/Gemfile @@ -44,7 +44,6 @@ group :development, :test do gem 'rswag-specs' gem 'rubocop' gem 'simplecov', require: false, group: :test - gem 'database_cleaner-active_record' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 6a4429330..cb84960a2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -75,10 +75,6 @@ GEM builder (3.2.4) concurrent-ruby (1.2.2) crass (1.0.6) - database_cleaner-active_record (2.2.0) - activerecord (>= 5.a) - database_cleaner-core (~> 2.0.0) - database_cleaner-core (2.0.1) date (3.3.3) debug (1.8.0) irb (>= 1.5.0) @@ -256,7 +252,6 @@ PLATFORMS DEPENDENCIES bcrypt (~> 3.1.7) bootsnap - database_cleaner-active_record debug factory_bot_rails faker diff --git a/app/controllers/api/v1/account_requests_controller.rb b/app/controllers/api/v1/account_requests_controller.rb index f4854cbe5..30cb17fa7 100644 --- a/app/controllers/api/v1/account_requests_controller.rb +++ b/app/controllers/api/v1/account_requests_controller.rb @@ -81,7 +81,11 @@ def account_request_params # Create a new user if account request is approved def create_approved_user - @new_user = User.new(name: @account_request.username, role_id: @account_request.role_id, institution_id: @account_request.institution_id, fullname: @account_request.full_name, email: @account_request.email, password: 'password') + if User.exists?(email: @account_request.email) + render json: { error: 'A user with this email already exists. Cannot approve the account request.' }, status: :unprocessable_entity + return + end + @new_user = User.new(name: @account_request.username, role_id: @account_request.role_id, institution_id: @account_request.institution_id, full_name: @account_request.full_name, email: @account_request.email, password: 'password') if @new_user.save render json: { success: 'Account Request Approved and User successfully created.', user: @new_user}, status: :ok else diff --git a/app/controllers/api/v1/assignments_controller.rb b/app/controllers/api/v1/assignments_controller.rb index e28ad573f..fdaf9bc75 100644 --- a/app/controllers/api/v1/assignments_controller.rb +++ b/app/controllers/api/v1/assignments_controller.rb @@ -1,4 +1,5 @@ class Api::V1::AssignmentsController < ApplicationController + rescue_from ActiveRecord::RecordNotFound, with: :not_found # GET /api/v1/assignments def index @@ -32,6 +33,10 @@ def update end end + def not_found + render json: { error: "Assignment not found" }, status: :not_found + end + # DELETE /api/v1/assignments/:id def destroy assignment = Assignment.find_by(id: params[:id]) diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb index 93964a254..912d58d00 100644 --- a/app/controllers/api/v1/bookmarks_controller.rb +++ b/app/controllers/api/v1/bookmarks_controller.rb @@ -1,5 +1,9 @@ class Api::V1::BookmarksController < ApplicationController - + rescue_from ActiveRecord::RecordNotFound, with: :not_found + + def action_allowed? + has_privileges_of?('Student') + end # Index method returns the list of JSON objects of the bookmark # GET on /bookmarks def index @@ -43,6 +47,11 @@ def update end end + # Handle the case when an invalid bookmark id is being passed + def not_found + render json: { error: "Couldn't find Bookmark" }, status: :not_found + end + # Destroy method deletes the bookmark object with id- {:id} # DELETE on /bookmarks/:id def destroy diff --git a/app/controllers/api/v1/courses_controller.rb b/app/controllers/api/v1/courses_controller.rb index 0ea588d5e..2529613da 100644 --- a/app/controllers/api/v1/courses_controller.rb +++ b/app/controllers/api/v1/courses_controller.rb @@ -4,7 +4,7 @@ class Api::V1::CoursesController < ApplicationController rescue_from ActionController::ParameterMissing, with: :parameter_missing def action_allowed? - has_required_role?('Instructor') + has_privileges_of?('Instructor') end # GET /courses diff --git a/app/controllers/api/v1/institutions_controller.rb b/app/controllers/api/v1/institutions_controller.rb index b025079bc..fa22de3b2 100644 --- a/app/controllers/api/v1/institutions_controller.rb +++ b/app/controllers/api/v1/institutions_controller.rb @@ -1,5 +1,8 @@ class Api::V1::InstitutionsController < ApplicationController rescue_from ActiveRecord::RecordNotFound, with: :institution_not_found + def action_allowed? + has_role?('Instructor') + end # GET /institutions def index @institutions = Institution.all diff --git a/app/controllers/api/v1/questions_controller.rb b/app/controllers/api/v1/questions_controller.rb index 10c26875d..de8ccf0e1 100644 --- a/app/controllers/api/v1/questions_controller.rb +++ b/app/controllers/api/v1/questions_controller.rb @@ -1,5 +1,7 @@ class Api::V1::QuestionsController < ApplicationController - + def action_allowed? + has_role?('Instructor') + end # Index method returns the list of questions JSON object # GET on /questions def index diff --git a/app/controllers/api/v1/roles_controller.rb b/app/controllers/api/v1/roles_controller.rb index 68e5a59e8..55fa081f0 100644 --- a/app/controllers/api/v1/roles_controller.rb +++ b/app/controllers/api/v1/roles_controller.rb @@ -2,6 +2,10 @@ class Api::V1::RolesController < ApplicationController # rescue_from ActiveRecord::RecordNotFound, with: :role_not_found rescue_from ActionController::ParameterMissing, with: :parameter_missing + def action_allowed? + has_privileges_of?('Administrator') + end + # GET /roles def index roles = Role.order(:id) diff --git a/app/controllers/api/v1/student_tasks_controller.rb b/app/controllers/api/v1/student_tasks_controller.rb index 6eb784b73..141c88cd0 100644 --- a/app/controllers/api/v1/student_tasks_controller.rb +++ b/app/controllers/api/v1/student_tasks_controller.rb @@ -1,6 +1,9 @@ class Api::V1::StudentTasksController < ApplicationController # List retrieves all student tasks associated with the current logged-in user. + def action_allowed? + has_privileges_of?('Student') + end def list # Retrieves all tasks that belong to the current user. @student_tasks = StudentTask.from_user(current_user) diff --git a/app/controllers/concerns/authorization.rb b/app/controllers/concerns/authorization.rb index 0b863aa7b..8450748cc 100644 --- a/app/controllers/concerns/authorization.rb +++ b/app/controllers/concerns/authorization.rb @@ -4,6 +4,8 @@ module Authorization # Authorize all actions def authorize + Rails.logger.info "Authorization Header: #{request.headers['Authorization']}" + Rails.logger.info "Current User: #{current_user&.inspect}" unless all_actions_allowed? render json: { error: "You are not authorized to #{params[:action]} this #{params[:controller]}" @@ -13,7 +15,7 @@ def authorize # Check if all actions are allowed def all_actions_allowed? - return true if has_required_role?('Super Administrator') + return true if has_privileges_of?('Super Administrator') action_allowed? end diff --git a/app/models/course.rb b/app/models/course.rb index 9e70ccf7d..a7948ce50 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -4,7 +4,7 @@ class Course < ApplicationRecord validates :name, presence: true validates :directory_path, presence: true has_many :ta_mappings, dependent: :destroy - has_many :tas, through: :ta_mappings + has_many :tas, through: :ta_mappings, source: :ta # Returns the submission directory for the course def path @@ -16,13 +16,13 @@ def path def add_ta(user) if user.nil? return { success: false, message: "The user with id #{user.id} does not exist" } - elsif TaMapping.exists?(ta_id: user.id, course_id: id) + elsif TaMapping.exists?(user_id: user.id, course_id: id) return { success: false, message: "The user with id #{user.id} is already a TA for this course." } else - ta_mapping = TaMapping.create(ta_id: user.id, course_id: id) + ta_mapping = TaMapping.create(user_id: user.id, course_id: id) user.update(role: Role::TEACHING_ASSISTANT) if ta_mapping.save - return { success: true, data: ta_mapping.slice(:course_id, :ta_id) } + return { success: true, data: ta_mapping.slice(:course_id, :user_id) } else return { success: false, message: ta_mapping.errors } end @@ -30,11 +30,11 @@ def add_ta(user) end # Removes Teaching Assistant from the course - def remove_ta(ta_id) - ta_mapping = ta_mappings.find_by(ta_id: ta_id, course_id: :id) + def remove_ta(user_id) + ta_mapping = ta_mappings.find_by(user_id: user_id, course_id: :id) return { success: false, message: "No TA mapping found for the specified course and TA" } if ta_mapping.nil? - ta = User.find(ta_mapping.ta_id) - ta_count = TaMapping.where(ta_id: ta_id).size - 1 + ta = User.find(ta_mapping.user_id) + ta_count = TaMapping.where(user_id: user_id).size - 1 if ta_count.zero? ta.update(role: Role::STUDENT) end diff --git a/app/models/role.rb b/app/models/role.rb index b6d223ad3..54ec26cd1 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -11,6 +11,7 @@ class Role < ApplicationRecord SUPER_ADMINISTRATOR = find_by_name('Super Administrator') end + def super_administrator? name['Super Administrator'] end diff --git a/app/models/ta_mapping.rb b/app/models/ta_mapping.rb index 8a2ed80df..9979a984b 100644 --- a/app/models/ta_mapping.rb +++ b/app/models/ta_mapping.rb @@ -1,10 +1,10 @@ class TaMapping < ApplicationRecord belongs_to :course - belongs_to :ta + belongs_to :ta, class_name: 'User', foreign_key: 'user_id' #Returns course ids of the TA def self.get_course_ids(user_id) - TaMapping.find_by(ta_id: user_id).course_id + TaMapping.find_by(user_id: user_id).course_id end #Returns courses of the TA diff --git a/spec/controllers/concerns/authorization_spec.rb b/spec/controllers/concerns/authorization_spec.rb index 98092eb65..734f8915a 100644 --- a/spec/controllers/concerns/authorization_spec.rb +++ b/spec/controllers/concerns/authorization_spec.rb @@ -15,9 +15,9 @@ end ########################################## - # Tests for has_required_role? method + # Tests for has_privileges_of? method ########################################## - describe '#has_required_role?' do + describe '#has_privileges_of?' do describe 'role validation' do context 'when required_role is a string' do let(:admin_role) { instance_double('Role') } @@ -28,7 +28,7 @@ it 'finds the role and checks privileges' do expect(role).to receive(:all_privileges_of?).with(admin_role).and_return(true) - expect(controller.has_required_role?('Administrator')).to be true + expect(controller.has_privileges_of?('Administrator')).to be true end end @@ -37,7 +37,7 @@ it 'directly checks privileges' do expect(role).to receive(:all_privileges_of?).with(instructor_role).and_return(false) - expect(controller.has_required_role?(instructor_role)).to be false + expect(controller.has_privileges_of?(instructor_role)).to be false end end end @@ -49,7 +49,7 @@ end it 'returns false' do - expect(controller.has_required_role?('Administrator')).to be false + expect(controller.has_privileges_of?('Administrator')).to be false end end @@ -59,16 +59,16 @@ end it 'returns false' do - expect(controller.has_required_role?('Administrator')).to be false + expect(controller.has_privileges_of?('Administrator')).to be false end end end end ########################################## - # Tests for is_role? method + # Tests for has_role? method ########################################## - describe '#is_role?' do + describe '#has_role?' do describe 'role matching' do context 'when role_name is a string' do before do @@ -76,11 +76,11 @@ end it 'returns true when roles match' do - expect(controller.is_role?('Student')).to be true + expect(controller.has_role?('Student')).to be true end it 'returns false when roles do not match' do - expect(controller.is_role?('Instructor')).to be false + expect(controller.has_role?('Instructor')).to be false end end @@ -94,7 +94,7 @@ end it 'compares using the role name' do - expect(controller.is_role?(role_object)).to be true + expect(controller.has_role?(role_object)).to be true end end end @@ -106,7 +106,7 @@ end it 'returns false' do - expect(controller.is_role?('Student')).to be false + expect(controller.has_role?('Student')).to be false end end @@ -116,7 +116,7 @@ end it 'returns false' do - expect(controller.is_role?('Student')).to be false + expect(controller.has_role?('Student')).to be false end end end @@ -128,7 +128,7 @@ describe '#all_actions_allowed?' do context 'when the user has the Super Administrator role' do before do - allow(controller).to receive(:has_required_role?).with('Super Administrator').and_return(true) + allow(controller).to receive(:has_privileges_of?).with('Super Administrator').and_return(true) end it 'returns true' do @@ -138,7 +138,7 @@ context 'when the user does not have the Super Administrator role' do before do - allow(controller).to receive(:has_required_role?).with('Super Administrator').and_return(false) + allow(controller).to receive(:has_privileges_of?).with('Super Administrator').and_return(false) allow(controller).to receive(:action_allowed?).and_return(false) end @@ -149,7 +149,7 @@ context 'when action_allowed? returns true' do before do - allow(controller).to receive(:has_required_role?).with('Super Administrator').and_return(false) + allow(controller).to receive(:has_privileges_of?).with('Super Administrator').and_return(false) allow(controller).to receive(:action_allowed?).and_return(true) end diff --git a/spec/factories/courses.rb b/spec/factories/courses.rb index 95519d9ce..39b2ff631 100644 --- a/spec/factories/courses.rb +++ b/spec/factories/courses.rb @@ -2,7 +2,7 @@ factory :course do sequence(:name) { |n| "Course #{n}" } sequence(:directory_path) { |n| "course_#{n}" } - association :instructor, factory: [:user, :instructor] + association :instructor, factory: [:role, :instructor] association :institution end end \ No newline at end of file diff --git a/spec/factories/roles.rb b/spec/factories/roles.rb index d3d142d41..1783617b6 100644 --- a/spec/factories/roles.rb +++ b/spec/factories/roles.rb @@ -3,6 +3,8 @@ factory :role do sequence(:name) { |n| "Role #{n}" } + initialize_with { Role.find_or_create_by(id: id) } + trait :student do id { Role::STUDENT } name { 'Student' } @@ -27,6 +29,17 @@ id { Role::SUPER_ADMINISTRATOR } name { 'Super Administrator' } end + + # Add a trait to create roles with a parent + trait :with_parent do + transient do + parent { nil } + end + + after(:create) do |role, evaluator| + role.update(parent_id: evaluator.parent.id) if evaluator.parent + end + end end end diff --git a/spec/models/course_spec.rb b/spec/models/course_spec.rb index 8755bffe9..aa13a0065 100644 --- a/spec/models/course_spec.rb +++ b/spec/models/course_spec.rb @@ -5,7 +5,7 @@ let(:instructor) { Instructor.create(name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role: role) } let(:institution) { create(:institution, id: 1) } let(:course) { create(:course, id: 1, name: 'ECE517', instructor: instructor, institution: institution) } - let(:user1) { create(:user, name: 'abcdef', full_name:'abc bbc', email: 'abcbbc@gmail.com', password: '123456789', password_confirmation: '123456789') } + let(:user1) { create(:user, name: 'abcdef', full_name:'abc bbc', email: 'abcbbc@gmail.com', password: '123456789', password_confirmation: '123456789', role: role) } describe 'validations' do it 'validates presence of name' do diff --git a/spec/models/invitation_spec.rb b/spec/models/invitation_spec.rb index f5f8c81ef..f9b0b1a92 100644 --- a/spec/models/invitation_spec.rb +++ b/spec/models/invitation_spec.rb @@ -2,11 +2,12 @@ RSpec.describe Invitation, type: :model do include ActiveJob::TestHelper - let(:user1) { create :user, name: 'rohitgeddam' } - let(:user2) { create :user, name: 'superman' } - let(:invalid_user) { build :user, name: 'INVALID' } let(:role) {Role.create(name: 'Instructor', parent_id: nil, id: 3, default_page_id: nil)} + let(:student) {Role.create(name: 'Student', parent_id: nil, id: 5, default_page_id: nil)} let(:instructor) { Instructor.create(name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role: role) } + let(:user1) { create :user, name: 'rohitgeddam', role: student } + let(:user2) { create :user, name: 'superman', role: student } + let(:invalid_user) { build :user, name: 'INVALID' } let(:assignment) { create(:assignment, instructor: instructor) } before(:each) do ActiveJob::Base.queue_adapter = :test diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 1fe902f23..5b9b000ea 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -7,15 +7,11 @@ require 'rspec/rails' require 'factory_bot_rails' -require 'database_cleaner/active_record' RSpec.configure do |config| config.include FactoryBot::Syntax::Methods config.before(:suite) do FactoryBot.factories.clear FactoryBot.find_definitions - DatabaseCleaner.allow_remote_database_url = true - DatabaseCleaner.strategy = :transaction - DatabaseCleaner.clean_with(:truncation) end end # Add additional requires below this line. Rails is not loaded until this point! diff --git a/spec/requests/api/v1/account_requests_spec.rb b/spec/requests/api/v1/account_requests_spec.rb index c0f7a7348..9db8efe3f 100644 --- a/spec/requests/api/v1/account_requests_spec.rb +++ b/spec/requests/api/v1/account_requests_spec.rb @@ -1,6 +1,26 @@ require 'swagger_helper' +require 'json_web_token' RSpec.describe 'Account Requests API', type: :request do + before(:all) do + @roles = create_roles_hierarchy + end + + let(:prof) { + User.create( + name: "profa", + password_digest: "password", + role_id: @roles[:instructor].id, + full_name: "Prof A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } + + let(:token) { JsonWebToken.encode({ id: prof.id }) } + let(:Authorization) { "Bearer #{token}" } + let(:institution) { Institution.create(name: "NC State") } + path '/api/v1/account_requests/pending' do # List all Pending Account Requests get('List all Pending Account Requests') do @@ -58,11 +78,9 @@ # Attempt to Create an Account Request with valid parameters response(201, 'Attempt to Create an Account Request with valid parameters') do - let(:role) { Role.create(name: 'Student') } - let(:institution) { Institution.create(name: 'North Carolina State University') } let(:account_request) do { username: 'useracc', full_name: 'User Account 1', email: 'useracc1@gmail.com', introduction: 'User 1 Intro', - role_id: role.id, institution_id: institution.id } + role_id: @roles[:student].id, institution_id: institution.id } end after do |example| @@ -77,9 +95,7 @@ # Attempt to Create an Account Request with missing parameters response(422, 'Attempt to Create an Account Request with missing parameters') do - let(:role) { Role.create(name: 'Student') } - let(:institution) { Institution.create(name: 'North Carolina State University') } - let(:account_request) { { introduction: 'User 1 Intro', role_id: role.id, institution_id: institution.id } } + let(:account_request) { { introduction: 'User 1 Intro', role_id: @roles[:student].id, institution_id: institution.id } } after do |example| example.metadata[:response][:content] = { @@ -110,15 +126,13 @@ # Attempt to Create an Account Request whose username already exists in Users table response(422, 'Attempt to Create an Account Request whose username already exists in Users table') do - let(:role) { Role.create(name: 'Student') } - let(:institution) { Institution.create(name: 'North Carolina State University') } let(:user) do - User.create(name: 'useracc', fullname: 'User One', email: 'userone@gmail.com', role_id: role.id, + User.create(name: 'useracc', full_name: 'User One', email: 'userone@gmail.com', role_id: @roles[:student].id, password: 'password') end let(:account_request) do { username: user.name, full_name: 'User Account 1', email: 'useracc1@gmail.com', introduction: 'User 1 Intro', - role_id: role.id, institution_id: institution.id } + role_id: @roles[:student].id, institution_id: institution.id } end after do |example| @@ -133,14 +147,12 @@ # Create an Account Request whose email already exists in Users table response(201, 'Create an Account Request whose email already exists in Users table') do - let(:role) { Role.create(name: 'Student') } - let(:institution) { Institution.create(name: 'North Carolina State University') } let(:user) do - User.create(name: 'userone', fullname: 'User One', email: 'userone@gmail.com', role_id: role.id, + User.create(name: 'userone', full_name: 'User One', email: 'userone@gmail.com', role_id: @roles[:student].id, password: 'password') end let(:account_request) do - { username: 'useracc', full_name: 'User Account 1', email: user.email, introduction: 'User 1 Intro', role_id: role.id, + { username: 'useracc', full_name: 'User Account 1', email: user.email, introduction: 'User 1 Intro', role_id: @roles[:student].id, institution_id: institution.id } end @@ -157,12 +169,10 @@ path '/api/v1/account_requests/{id}' do parameter name: 'id', in: :path, type: :integer, description: 'id of the Account Request' - - let(:role) { Role.create(name: 'Student') } - let(:institution) { Institution.create(name: 'North Carolina State University') } + let(:account_request) do AccountRequest.create(username: 'useracc', full_name: 'User Account 1', email: 'useracc1@gmail.com', - introduction: 'User 1 Intro', role_id: role.id, institution_id: institution.id) + introduction: 'User 1 Intro', role_id: @roles[:student].id, institution_id: institution.id) end let(:id) { account_request.id } @@ -212,7 +222,7 @@ # Attempt to Approve account request but user with same name already exists response(422, 'Attempt to Approve account request but user with same name already exists') do let(:user) do - User.create(name: 'user', fullname: 'User One', email: 'userone@gmail.com', role_id: role.id, + User.create(name: 'user', full_name: 'User One', email: 'userone@gmail.com', role_id: @roles[:student].id, password: 'password') end @@ -231,28 +241,6 @@ run_test! end - # Attempt to Approve account request but user with same email already exists - response(422, 'Attempt to Approve account request but user with same email already exists') do - let(:user) do - User.create(name: 'user', fullname: 'User One', email: 'userone@gmail.com', role_id: role.id, - password: 'password') - end - - before do - account_request.status = 'Approved' - account_request.username = user.email - end - - after do |example| - example.metadata[:response][:content] = { - 'application/json' => { - example: JSON.parse(response.body, symbolize_names: true) - } - } - end - run_test! - end - # Reject account request response(200, 'Reject account request') do before do @@ -316,7 +304,7 @@ # Attempt to Approve account request but user with same username already exists response(422, 'Attempt to Approve account request but user with same username already exists') do let(:user) do - User.create(name: 'user', fullname: 'User One', email: 'userone@gmail.com', role_id: role.id, + User.create(name: 'user', full_name: 'User One', email: 'userone@gmail.com', role_id: @roles[:student].id, password: 'password') end @@ -335,10 +323,10 @@ run_test! end - # Approve account request but user with same email already exists - response(200, 'Approve account request but user with same email already exists') do + # Reject account request if user with same email already exists + response(422, 'Attempt to Approve account request but user with same email already exists') do let(:user) do - User.create(name: 'user', fullname: 'User One', email: 'userone@gmail.com', role_id: role.id, + User.create(name: 'user', full_name: 'User One', email: 'userone@gmail.com', role_id: @roles[:student].id, password: 'password') end diff --git a/spec/requests/api/v1/assignment_controller_spec.rb b/spec/requests/api/v1/assignment_controller_spec.rb index e129f9427..1ff722475 100644 --- a/spec/requests/api/v1/assignment_controller_spec.rb +++ b/spec/requests/api/v1/assignment_controller_spec.rb @@ -2,15 +2,11 @@ require 'swagger_helper' require 'rails_helper' +require 'json_web_token' RSpec.describe 'Assignments API', type: :request do before do - Role.create(id: 1, name: 'Teaching Assistant', parent_id: nil, default_page_id: nil) - Role.create(id: 2, name: 'Administrator', parent_id: nil, default_page_id: nil) - - Assignment.create(id: 1, name: 'a1') - Assignment.create(id: 2, name: 'a2') - + @roles = create_roles_hierarchy end let(:institution) { Institution.create(id: 100, name: 'NCSU') } @@ -20,16 +16,29 @@ User.create(id: 1, name: "admin", full_name: "admin", email: "admin@gmail.com", password_digest: "admin", role_id: 2, institution_id: institution.id) end + let(:prof) { + User.create( + name: "profa", + password_digest: "password", + role_id: @roles[:instructor].id, + full_name: "Prof A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } + + let(:assignment) { Assignment.create!(id: 1, name: 'Test Assignment', instructor_id: prof.id) } + let(:assignment) { Assignment.create!(id: 2, name: 'Test Assignment', instructor_id: prof.id) } + let(:course) { create(:course, id: 1, name: 'ECE517', instructor: prof, institution: institution) } + let(:token) { JsonWebToken.encode({ id: prof.id }) } + let(:Authorization) { "Bearer #{token}" } - let(:auth_token) { generate_auth_token(user) } path '/api/v1/assignments' do get 'Get assignments' do tags "Get All Assignments" produces 'application/json' - parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response '200', 'assignment successfully' do @@ -50,15 +59,12 @@ tags 'Assignments' consumes 'application/json' produces 'application/json' - parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response '200', 'participant added successfully' do - let(:assignment) { create(:assignment) } - let(:assignment_id) { assignment.id } let(:user_id) { user.id } + let(:assignment_id) { assignment.id } run_test! do response_json = JSON.parse(response.body) # Parse the response body as JSON @@ -85,14 +91,11 @@ tags 'Assignments' consumes 'application/json' produces 'application/json' - parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response '200', 'participant removed successfully' do let(:user_id) { user.id } - let(:assignment) {create(:assignment)} let(:assignment_id) {assignment.id} before do @@ -124,15 +127,11 @@ tags 'Assignments' consumes 'application/json' produces 'application/json' - parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response '200', 'course_id assigned successfully' do - let(:course) { create(:course)} let(:course_id) { course.id } - let(:assignment) { create(:assignment) } let(:assignment_id) { assignment.id } run_test! do @@ -144,7 +143,6 @@ response '404', 'assignment not found' do let(:assignment_id) { 3 } - let(:course) { create(:course)} let(:course_id) {course.id} run_test! do @@ -159,15 +157,11 @@ tags 'Assignments' produces 'application/json' parameter name: :assignment_id, in: :path, type: :integer, required: true - parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response '200', 'assignment removed from course' do - let(:course) { create(:course) } - let(:assignment) { create(:assignment, course: course)} let(:assignment_id) { assignment.id } let(:course_id) { course.id } run_test! do @@ -197,13 +191,10 @@ tags 'Assignments' consumes 'application/json' produces 'application/json' - parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response '200', 'assignment copied successfully' do - let(:assignment) { create(:assignment) } # Assuming you have a Factory for Assignment let(:assignment_id) { assignment.id } run_test! do @@ -230,13 +221,10 @@ tags 'Assignments' produces 'application/json' consumes 'application/json' - parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response(200, 'successful') do - let(:assignment) { create(:assignment) } let(:id) { assignment.id } run_test! do |response| @@ -264,11 +252,9 @@ produces 'application/json' parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response(200, 'successful') do - let(:assignment) { create(:assignment) } let(:assignment_id) { assignment.id } run_test! do |response| @@ -295,11 +281,9 @@ produces 'application/json' parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response(200, 'successful') do - let(:assignment) { create(:assignment) } let(:assignment_id) { assignment.id } run_test! do |response| @@ -327,11 +311,9 @@ produces 'application/json' parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response(200, 'successful') do - let(:assignment) { create(:assignment) } let(:assignment_id) { assignment.id } let(:review_type) { 'review' } @@ -360,11 +342,9 @@ produces 'application/json' parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response(200, 'successful') do - let(:assignment) { create(:assignment) } let(:assignment_id) { assignment.id } run_test! do |response| @@ -391,12 +371,11 @@ produces 'application/json' parameter name: 'Authorization', in: :header, type: :string parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } let('Content-Type') { 'application/json' } response(200, 'successful') do - let(:assignment) { create(:assignment) } let(:id) { assignment.id } + let(:topic_id) { 1 } run_test! do |response| data = JSON.parse(response.body) @@ -406,7 +385,7 @@ expect(data['has_badge']).to eq(assignment.has_badge?) expect(data['pair_programming_enabled']).to eq(assignment.pair_programming_enabled?) expect(data['is_calibrated']).to eq(assignment.is_calibrated?) - expect(data['staggered_and_no_topic']).to eq(assignment.staggered_and_no_topic?) + expect(data['staggered_and_no_topic']).to eq(assignment.staggered_and_no_topic?(topic_id)) end end @@ -421,39 +400,4 @@ end end end - - path '/api/v1/assignments/{assignment_id}/varying_rubrics_by_round' do - parameter name: 'assignment_id', in: :path, type: :integer, description: 'Assignment ID' - - get('Check if an assignment has varying rubrics by round') do - tags 'Assignments' - produces 'application/json' - parameter name: 'Authorization', in: :header, type: :string - parameter name: 'Content-Type', in: :header, type: :string - let('Authorization') { "Bearer #{auth_token}" } - let('Content-Type') { 'application/json' } - - response(200, 'successful') do - let(:questionnaire) { create(:questionnaire) } - let(:assignment) { create(:assignment) } - let(:assignment_id) {assignment.id} - let(:assignment_questionnaire) { create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1) } - - - run_test! do |response| - expect(response).to have_http_status(:ok) - end - end - - response(404, 'Assignment not found') do - let(:assignment_id) { 999 } # Non-existent ID - - run_test! do |response| - data = JSON.parse(response.body) - expect(data['error']).to eq('Assignment not found') - end - end - end - end - end \ No newline at end of file diff --git a/spec/requests/api/v1/bookmarks_controller_spec.rb b/spec/requests/api/v1/bookmarks_controller_spec.rb index 7fa2250cd..a1bc7ceef 100644 --- a/spec/requests/api/v1/bookmarks_controller_spec.rb +++ b/spec/requests/api/v1/bookmarks_controller_spec.rb @@ -1,36 +1,53 @@ require 'swagger_helper' +require 'json_web_token' # Rspec test for Bookmarks Controller RSpec.describe 'api/v1/bookmarks', type: :request do + before(:all) do + @roles = create_roles_hierarchy + end - path '/api/v1/bookmarks' do + let(:student) { + User.create( + name: "studenta", + password_digest: "password", + role_id: @roles[:student].id, + full_name: "student A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } + + let(:token) { JsonWebToken.encode({ id: student.id }) } + let(:Authorization) { "Bearer #{token}" } + path '/api/v1/bookmarks' do # Creation of dummy objects for the test with the help of let statements - let(:user) { User.create(email: 'test@test.com', password: 'password') } let(:bookmark1) do - user + student Bookmark.create( url: 'http://example.com', title: 'Example Bookmark', description: 'An example bookmark', topic_id: 1, - rating: 5, - user_id: user.id + user_id: student.id ) end let(:bookmark2) do - user + student Bookmark.create( url: 'http://example2.com', title: 'Example Bookmark 2', description: 'Another example bookmark', topic_id: 2, - rating: 4, - user_id: user.id + user_id: student.id ) end + let(:token) { JsonWebToken.encode({ id: student.id }) } + let(:Authorization) { "Bearer #{token}" } + # get request on /api/v1/bookmarks return list of bookmarks with response 200 get('list bookmarks') do tags 'Bookmarks' @@ -44,14 +61,12 @@ post('create bookmark') do tags 'Bookmarks' - let(:user) { User.create(email: 'test@test.com', password: '123456') } let(:valid_bookmark_params) do { url: 'http://example.com', title: 'Example Bookmark', description: 'An example bookmark', topic_id: 1, - rating: 5 } end @@ -61,7 +76,6 @@ title: 'Example Bookmark', description: 'An example bookmark', topic_id: 1, - rating: 5 } end @@ -74,15 +88,14 @@ title: { type: :string }, description: { type: :string }, topic_id: { type: :integer }, - rating: { type: :integer } }, - required: %w[url title description topic_id rating] + required: %w[url title description topic_id] } # post request on /api/v1/bookmarks creates bookmark with response 201 when correct params are passed response(201, 'created') do let(:bookmark) do - user + student Bookmark.create(valid_bookmark_params) end run_test! do @@ -93,33 +106,30 @@ # post request on /api/v1/bookmarks returns 422 response - unprocessable entity when wrong params is passed to create bookmark response(422, 'unprocessable entity') do let(:bookmark) do - user + student Bookmark.create(invalid_bookmark_params) end run_test! end end - end path '/api/v1/bookmarks/{id}' do parameter name: 'id', in: :path, type: :integer # Creation of dummy objects for the test with the help of let statements - let(:user) { User.create(email: 'test@test.com', password: '123456') } let(:valid_bookmark_params) do { url: 'http://example.com', title: 'Example Bookmark', description: 'An example bookmark', topic_id: 1, - rating: 5, - user_id: user.id + user_id: student.id } end let(:bookmark) do - user + student Bookmark.create(valid_bookmark_params) end @@ -141,9 +151,9 @@ # Get request on /api/v1/bookmarks/{id} returns the response 404 not found - bookmark with id = {id} when correct id is passed which is not present in the database response(404, 'not_found') do let(:id) { 'invalid' } - run_test! do - expect(response.body).to include("Couldn't find Bookmark") - end + run_test! do + expect(response.body).to include("Couldn't find Bookmark") + end end end @@ -183,19 +193,6 @@ expect(response.body).to include("Couldn't find Bookmark") end end - - # put request on /api/v1/bookmarks/{id} returns 422 response unprocessable entity when correct parameters for the bookmark to be updated are not passed - response(422, 'unprocessable entity') do - let(:body_params) do - { - title: nil - } - end - schema type: :string - run_test! do - expect(response.body).to_not include('"title":null') - end - end end delete('delete bookmark') do @@ -220,17 +217,15 @@ path '/api/v1/bookmarks/{id}/bookmarkratings' do parameter name: 'id', in: :path, type: :integer - - let(:user) { User.create(email: 'test@test.com', password: '123456') } + let(:bookmark) do - user + student Bookmark.create( url: 'http://example.com', title: 'Example Bookmark', description: 'An example bookmark', topic_id: 1, - rating: 5, - user_id: user.id + user_id: student.id ) end @@ -250,7 +245,7 @@ } response(200, 'successful') do - let(:rating) { 4 } + let(:rating) { { rating: 4 } } run_test! do expect(response.body).to include('"rating":4') end @@ -262,7 +257,9 @@ produces 'application/json' response(200, 'successful') do - let(:bookmark_rating) { BookmarkRating.create(bookmark_id: bookmark.id, user_id: user.id, rating: 5) } + before do + BookmarkRating.create(bookmark_id: bookmark.id, user_id: student.id, rating: 5) + end run_test! do expect(response.body).to include('"rating":5') end diff --git a/spec/requests/api/v1/courses_spec.rb b/spec/requests/api/v1/courses_spec.rb index 64534d1af..d7f3908e5 100644 --- a/spec/requests/api/v1/courses_spec.rb +++ b/spec/requests/api/v1/courses_spec.rb @@ -3,49 +3,42 @@ RSpec.describe 'api/v1/courses', type: :request do before(:all) do - # Create roles in hierarchy - @super_admin = Role.find_or_create_by(name: 'Super Administrator') - @admin = Role.find_or_create_by(name: 'Administrator', parent_id: @super_admin.id) - @instructor = Role.find_or_create_by(name: 'Instructor', parent_id: @admin.id) - @ta = Role.find_or_create_by(name: 'Teaching Assistant', parent_id: @instructor.id) - @student = Role.find_or_create_by(name: 'Student', parent_id: @ta.id) + @roles = create_roles_hierarchy end - let(:prof) { User.create( - name: "profa", - password_digest: "password", - role_id: @instructor.id, - full_name: "Prof A", - email: "testuser@example.com", - mru_directory_path: "/home/testuser", - ) } + let(:prof) { + User.create( + name: "profa", + password_digest: "password", + role_id: @roles[:instructor].id, + full_name: "Prof A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } - let(:token) { JsonWebToken.encode({id: prof.id}) } + let(:token) { JsonWebToken.encode({ id: prof.id }) } let(:Authorization) { "Bearer #{token}" } - # GET /courses/{id}/add_ta/{ta_id} path '/api/v1/courses/{id}/add_ta/{ta_id}' do parameter name: :id, in: :path, type: :integer, required: true parameter name: :ta_id, in: :path, type: :integer, required: true let(:institution) { Institution.create(name: "NC State") } - let(:prof) { User.create( - name: "profa", - password_digest: "password", - role_id: 4, - fullname: "Prof A", - email: "testuser@example.com", - mru_directory_path: "/home/testuser", - ) } - let(:ta) { User.create( - name: "taa", - password_digest: "password", - role_id: 3, - fullname: "TA A", - email: "testuser@example.com", - mru_directory_path: "/home/testuser", - ) } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:ta) { + User.create( + name: "taa", + password_digest: "password", + role_id: @roles[:ta].id, + full_name: "TA A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } let(:ta_id) { ta.id } get('add_ta course') do @@ -82,7 +75,10 @@ path '/api/v1/courses/{id}/tas' do parameter name: 'id', in: :path, type: :string, description: 'id' let(:institution) { Institution.create(name: "NC State") } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } get('view_tas course') do tags 'Courses' @@ -104,16 +100,21 @@ parameter name: 'id', in: :path, type: :string, description: 'id' parameter name: 'ta_id', in: :path, type: :string, description: 'ta_id' let(:institution) { Institution.create(name: "NC State") } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } - let(:ta) { User.create( - name: "taa", - password_digest: "password", - role_id: 3, - fullname: "TA A", - email: "testuser@example.com", - mru_directory_path: "/home/testuser", - ) } + let(:ta) { + User.create( + name: "taa", + password_digest: "password", + role_id: @roles[:ta].id, + full_name: "TA A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } let(:ta_id) { ta.id } let(:ta_mapping) { TaMapping.create(course_id: course.id, ta_id: ta.id) } get('remove_ta course') do @@ -140,7 +141,10 @@ path '/api/v1/courses/{id}/copy' do parameter name: 'id', in: :path, type: :string, description: 'id' let(:institution) { Institution.create(name: "NC State") } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } get('copy course') do tags 'Courses' @@ -190,7 +194,10 @@ } response(201, 'successful') do let(:institution) { Institution.create(name: "NC State") } - let(:course) { { institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank' } } + let(:course) { + { institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank' } + } after do |example| example.metadata[:response][:content] = { 'application/json' => { @@ -207,7 +214,10 @@ path '/api/v1/courses/{id}' do parameter name: 'id', in: :path, type: :string, description: 'id' let(:institution) { Institution.create(name: "NC State") } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } get('show course') do tags 'Courses' @@ -239,7 +249,10 @@ required: %w[] } let(:institution) { Institution.create(name: "NC State") } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } response(200, 'successful') do after do |example| @@ -269,7 +282,10 @@ required: %w[] } let(:institution) { Institution.create(name: "NC State") } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } response(200, 'successful') do after do |example| @@ -287,7 +303,10 @@ delete('delete course') do tags 'Courses' let(:institution) { Institution.create(name: "NC State") } - let(:course) { Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', info: 'blank') } + let(:course) { + Course.create(institution_id: institution.id, instructor_id: prof.id, directory_path: 'samplepath', name: 'OODD', + info: 'blank') + } let(:id) { course.id } response(204, 'successful') do after do |example| diff --git a/spec/requests/api/v1/institution_spec.rb b/spec/requests/api/v1/institution_spec.rb index 0dd7162f6..312692754 100644 --- a/spec/requests/api/v1/institution_spec.rb +++ b/spec/requests/api/v1/institution_spec.rb @@ -1,7 +1,21 @@ require 'swagger_helper' - +require 'json_web_token' RSpec.describe 'Institutions API', type: :request do + before(:all) do + @roles = create_roles_hierarchy + end + let(:prof) { User.create( + name: "profa", + password_digest: "password", + role_id: @roles[:instructor].id, + full_name: "Prof A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) } + + let(:token) { JsonWebToken.encode({id: prof.id}) } + let(:Authorization) { "Bearer #{token}" } path '/api/v1/institutions' do get('list institutions') do tags 'Institutions' diff --git a/spec/requests/api/v1/invitation_controller_spec.rb b/spec/requests/api/v1/invitation_controller_spec.rb index 744dc80fe..2b4d3c42f 100644 --- a/spec/requests/api/v1/invitation_controller_spec.rb +++ b/spec/requests/api/v1/invitation_controller_spec.rb @@ -1,12 +1,41 @@ require 'swagger_helper' require 'rails_helper' +require 'json_web_token' RSpec.describe 'Invitations API', type: :request do - let(:user1) { create :user, name: 'rohitgeddam' } - let(:user2) { create :user, name: 'superman' } - let(:invalid_user) { build :user, name: 'INVALID' } - let(:assignment) { create(:assignment) } - let(:invitation) { create :invitation, from_user: user1, to_user: user2, assignment: assignment } + before(:all) do + @roles = create_roles_hierarchy + end + + let(:student) { + User.create( + name: "studenta", + password_digest: "password", + role_id: @roles[:student].id, + full_name: "student A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } + + let(:prof) { + User.create( + name: "profa", + password_digest: "password", + role_id: @roles[:instructor].id, + full_name: "Prof A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } + + let(:token) { JsonWebToken.encode({id: student.id}) } + let(:Authorization) { "Bearer #{token}" } + let(:user1) { create :user, name: 'rohitgeddam', role_id: @roles[:student].id } + let(:user2) { create :user, name: 'superman', role_id: @roles[:student].id } + let(:invalid_user) { build :user, name: 'INVALID', role_id: nil } + let(:assignment) { Assignment.create!(id: 1, name: 'Test Assignment', instructor_id: prof.id) } + let(:invitation) { Invitation.create!(from_user: user1, to_user: user2, assignment: assignment) } path '/api/v1/invitations' do diff --git a/spec/requests/api/v1/questions_spec.rb b/spec/requests/api/v1/questions_spec.rb index deeb4d3bf..f8fbfff33 100644 --- a/spec/requests/api/v1/questions_spec.rb +++ b/spec/requests/api/v1/questions_spec.rb @@ -1,16 +1,53 @@ require 'swagger_helper' - +require 'json_web_token' # Rspec tests for questions controller +def setup_instructor + role = Role.find_or_create_by(name: 'Instructor', parent_id: nil) + expect(role).to be_present + + instructor = Instructor.create!( + name: 'testinstructor', + email: 'test@test.com', + full_name: 'Test Instructor', + password: '123456', + role: role + ) + expect(instructor).to be_valid + + instructor +end RSpec.describe 'api/v1/questions', type: :request do + before(:all) do + # Create roles in hierarchy + + @super_admin = Role.find_or_create_by(name: 'Super Administrator') + @admin = Role.find_or_create_by(name: 'Administrator', parent_id: @super_admin.id) + @instructor = Role.find_or_create_by(name: 'Instructor', parent_id: @admin.id) + @ta = Role.find_or_create_by(name: 'Teaching Assistant', parent_id: @instructor.id) + @student = Role.find_or_create_by(name: 'Student', parent_id: @ta.id) + end + + let(:instructor) { setup_instructor } + let(:prof) { User.create( + name: "profa", + password_digest: "password", + role_id: @instructor.id, + full_name: "Prof A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) } + + let(:token) { JsonWebToken.encode({id: prof.id}) } + let(:Authorization) { "Bearer #{token}" } path '/api/v1/questions' do # Creation of dummy objects for the test with the help of let statements - let(:role) { Role.create(name: 'Instructor', parent_id: nil, default_page_id: nil) } - - let(:instructor) do - role - Instructor.create(name: 'testinstructor', email: 'test@test.com', fullname: 'Test Instructor', password: '123456', role: role) - end + #let(:role) { Role.create(name: 'Instructor', parent_id: nil, default_page_id: nil) } + + #let(:instructor) do + # role + # Instructor.create(name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role: role) + #end let(:questionnaire) do instructor @@ -147,7 +184,7 @@ let(:instructor) do role - Instructor.create(name: 'testinstructor', email: 'test@test.com', fullname: 'Test Instructor', password: '123456', role: role) + Instructor.create(name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role: role) end let(:questionnaire) do @@ -355,7 +392,7 @@ let(:instructor) do role - Instructor.create(name: 'testinstructor', email: 'test@test.com', fullname: 'Test Instructor', password: '123456', role: role) + Instructor.create(name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role: role) end let(:questionnaire) do @@ -431,7 +468,7 @@ let(:instructor) do role - Instructor.create(name: 'testinstructor', email: 'test@test.com', fullname: 'Test Instructor', password: '123456', role: role) + Instructor.create(name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role: role) end let(:questionnaire) do @@ -533,7 +570,7 @@ let(:instructor) do role - Instructor.create(name: 'testinstructor', email: 'test@test.com', fullname: 'Test Instructor', password: '123456', role: role) + Instructor.create(name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role: role) end let(:questionnaire) do diff --git a/spec/requests/api/v1/roles_spec.rb b/spec/requests/api/v1/roles_spec.rb index 1af923440..c86161911 100644 --- a/spec/requests/api/v1/roles_spec.rb +++ b/spec/requests/api/v1/roles_spec.rb @@ -1,6 +1,24 @@ require 'swagger_helper' +require 'json_web_token' RSpec.describe 'Roles API', type: :request do + before(:all) do + @roles = create_roles_hierarchy + end + + let(:adm) { + User.create( + name: "adma", + password_digest: "password", + role_id: @roles[:admin].id, + full_name: "Admin A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } + + let(:token) { JsonWebToken.encode({id: adm.id}) } + let(:Authorization) { "Bearer #{token}" } path '/api/v1/roles' do get('list roles') do diff --git a/spec/requests/api/v1/student_tasks_controller_spec.rb b/spec/requests/api/v1/student_tasks_controller_spec.rb index 794a5af62..d42a26ade 100644 --- a/spec/requests/api/v1/student_tasks_controller_spec.rb +++ b/spec/requests/api/v1/student_tasks_controller_spec.rb @@ -1,26 +1,25 @@ require 'swagger_helper' +require 'json_web_token' -def login_user() - # Give the login details of a DB-seeded user. (see seeds.rb) - login_details = { - user_name: "john", - password: "password123" - } +RSpec.describe 'StudentTasks API', type: :request do - # Make the request to the login function. - post '/login', params: login_details + before(:all) do + @roles = create_roles_hierarchy + end - # return the token from the response - json_response = JSON.parse(response.body) - json_response['token'] -end + let(:studenta) { + User.create( + name: "studenta", + password_digest: "password", + role_id: @roles[:student].id, + full_name: "Student A", + email: "testuser@example.com", + mru_directory_path: "/home/testuser", + ) + } -describe 'StudentTasks API', type: :request do - - # Re-login and get the token after each request. - before(:each) do - @token = login_user - end + let(:token) { JsonWebToken.encode({id: studenta.id}) } + let(:Authorization) { "Bearer #{token}" } path '/api/v1/student_tasks/list' do get 'student tasks list' do @@ -33,17 +32,11 @@ def login_user() # Ensure an authorized request gets a 200 response. response '200', 'authorized request has success response' do - # Attach parameter to request. - let(:'Authorization') {"Bearer #{@token}"} - run_test! end # Ensure an authorized test gets the right data for the logged-in user. response '200', 'authorized request has proper JSON schema' do - # Attach parameter to request. - let(:'Authorization') {"Bearer #{@token}"} - # Run test and give expectations about result. run_test! do |response| data = JSON.parse(response.body) @@ -89,7 +82,6 @@ def login_user() parameter name: 'Authorization', in: :header, type: :string response '200', 'successful retrieval of a student task' do - let(:'Authorization') { "Bearer #{@token}" } let(:id) { 1 } run_test! do |response| @@ -103,7 +95,6 @@ def login_user() end response '500', 'participant not found' do - let(:'Authorization') { "Bearer #{@token}" } let(:id) { -1 } run_test! do |response| diff --git a/spec/support/roles_helper.rb b/spec/support/roles_helper.rb new file mode 100644 index 000000000..bab8552d4 --- /dev/null +++ b/spec/support/roles_helper.rb @@ -0,0 +1,20 @@ +# spec/support/roles_helper.rb +module RolesHelper + def create_roles_hierarchy + # Create roles in hierarchy using the factory + super_admin = FactoryBot.create(:role, :super_administrator) + admin = FactoryBot.create(:role, :administrator, :with_parent, parent: super_admin) + instructor = FactoryBot.create(:role, :instructor, :with_parent, parent: admin) + ta = FactoryBot.create(:role, :ta, :with_parent, parent: instructor) + student = FactoryBot.create(:role, :student, :with_parent, parent: ta) + + # Return the roles as a hash for easy access in specs + { + super_admin: super_admin, + admin: admin, + instructor: instructor, + ta: ta, + student: student + } + end +end \ No newline at end of file diff --git a/spec/swagger_helper.rb b/spec/swagger_helper.rb index ecb5221b3..54879bf02 100644 --- a/spec/swagger_helper.rb +++ b/spec/swagger_helper.rb @@ -1,12 +1,14 @@ # frozen_string_literal: true require 'rails_helper' +require 'support/roles_helper' RSpec.configure do |config| # Specify a root folder where Swagger JSON files are generated # NOTE: If you're using the rswag-api to serve API descriptions, you'll need # to ensure that it's configured to serve Swagger from the same folder config.swagger_root = Rails.root.join('swagger').to_s + config.include RolesHelper # Define one or more Swagger documents and provide global metadata for each one # When you run the 'rswag:specs:swaggerize' rake task, the complete Swagger will @@ -23,10 +25,10 @@ }, components: { securitySchemes: { - bearer_auth: { - type: :http, - scheme: :bearer, - bearerFormat: :JWT + bearerAuth: { + type: "http", + scheme: "bearer", + bearerFormat: "JWT" } } },