diff --git a/app/controllers/api/v1/account_requests_controller.rb b/app/controllers/api/v1/account_requests_controller.rb index f4854cbe5..463b02aac 100644 --- a/app/controllers/api/v1/account_requests_controller.rb +++ b/app/controllers/api/v1/account_requests_controller.rb @@ -3,12 +3,14 @@ class Api::V1::AccountRequestsController < ApplicationController # GET /account_requests/pending def pending_requests @account_requests = AccountRequest.where(status: 'Under Review').order('created_at DESC') + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched #{@account_requests.count} pending account requests.", request) render json: @account_requests, status: :ok end # GET /account_requests/processed def processed_requests @account_requests = AccountRequest.where.not(status: 'Under Review').order('updated_at DESC') + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched #{@account_requests.count} processed account requests.", request) render json: @account_requests, status: :ok end @@ -18,25 +20,36 @@ def create if @account_request.save response = { account_request: @account_request } if User.find_by(email: @account_request.email) + # Logging a warning if a user with the same email already exists + ExpertizaLogger.warn LoggerMessage.new(controller_name, @current_user.name, "Account requested with duplicate email: #{@account_request.email}", request) response[:warnings] = 'WARNING: User with this email already exists!' end + + # Logging the successful creation of the account request + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Successfully created account request with ID: #{@account_request.id}.", request) render json: response, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, $ERROR_INFO, request) render json: @account_request.errors, status: :unprocessable_entity end rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Record not found: #{e.message}", request) render json: { error: e.message }, status: :not_found rescue ActionController::ParameterMissing => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Parameter missing: #{e.message}", request) render json: { error: e.message }, status: :parameter_missing rescue StandardError => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "An error occurred: #{e.message}", request) render json: { error: e.message }, status: :unprocessable_entity end # GET /account_requests/:id def show @account_request = AccountRequest.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched account request with ID: #{@account_request.id}.", request) render json: @account_request, status: :ok rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Account request not found: #{e.message}", request) render json: { error: e.message }, status: :not_found end @@ -45,14 +58,19 @@ def show def update @account_request = AccountRequest.find(params[:id]) @account_request.update(account_request_params) + + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated account request with ID: #{@account_request.id}, Status: #{@account_request.status}.", request) + if @account_request.status == 'Approved' create_approved_user else render json: @account_request, status: :ok end rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Account request not found for update: #{e.message}", request) render json: { error: e.message }, status: :not_found rescue StandardError => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "An error occurred while updating account request: #{e.message}", request) render json: { error: e.message }, status: :unprocessable_entity end @@ -60,9 +78,11 @@ def update def destroy @account_request = AccountRequest.find(params[:id]) @account_request.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted account request with ID: #{@account_request.id}.", request) render json: { message: 'Account Request deleted' }, status: :no_content rescue ActiveRecord::RecordNotFound => e - render json: { error: e.message }, status: :not_found + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Account request not found for deletion: #{e.message}", request) + render json: { error: e.message }, status: :not_found end private @@ -74,6 +94,7 @@ def account_request_params params[:account_request][:status] = 'Under Review' # For Approval or Rejection of an existing request, raise error if user sends a status other than Approved or Rejected elsif !['Approved', 'Rejected'].include?(params[:account_request][:status]) + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Invalid status provided: #{params[:account_request][:status]}", request) raise StandardError, 'Status can only be Approved or Rejected' end params.require(:account_request).permit(:username, :full_name, :email, :status, :introduction, :role_id, :institution_id) @@ -83,8 +104,11 @@ def account_request_params 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 @new_user.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Approved account request and created user with ID: #{@new_user.id}.", request) render json: { success: 'Account Request Approved and User successfully created.', user: @new_user}, status: :ok else + errors = @new_user.errors.full_messages.join(', ') + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create user from approved account request ID: #{@account_request.id}. Errors: #{errors}", request) render json: @new_user.errors, status: :unprocessable_entity end end diff --git a/app/controllers/api/v1/assignments_controller.rb b/app/controllers/api/v1/assignments_controller.rb index e28ad573f..1d2c3055d 100644 --- a/app/controllers/api/v1/assignments_controller.rb +++ b/app/controllers/api/v1/assignments_controller.rb @@ -3,12 +3,16 @@ class Api::V1::AssignmentsController < ApplicationController # GET /api/v1/assignments def index assignments = Assignment.all + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all assignments.", request) render json: assignments end # GET /api/v1/assignments/:id def show assignment = Assignment.find(params[:id]) + # For now, just logging success - if error checking is added in the future, please add a log message for that with + # ExpertizaLogger.error + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched assignment with ID: #{assignment.id}.", request) render json: assignment end @@ -16,8 +20,10 @@ def show def create assignment = Assignment.new(assignment_params) if assignment.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Assignment created: #{assignment.as_json}", request) render json: assignment, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create assignment: #{assignment.errors.full_messages.join(', ')}", request) render json: assignment.errors, status: :unprocessable_entity end end @@ -26,8 +32,10 @@ def create def update assignment = Assignment.find(params[:id]) if assignment.update(assignment_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated assignment with ID: #{assignment.id}.", request) render json: assignment, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update assignment ID: #{assignment.id}. Errors: #{assignment.errors.full_messages.join(', ')}", request) render json: assignment.errors, status: :unprocessable_entity end end @@ -37,11 +45,14 @@ def destroy assignment = Assignment.find_by(id: params[:id]) if assignment if assignment.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Assignment #{assignment.id} was deleted.", request) render json: { message: "Assignment deleted successfully!" }, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to delete assignment #{$ERROR_INFO}", request) render json: { error: "Failed to delete assignment", details: assignment.errors.full_messages }, status: :unprocessable_entity end else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for deletion with ID: #{params[:id]}", request) render json: { error: "Assignment not found" }, status: :not_found end end @@ -50,12 +61,15 @@ def destroy def add_participant assignment = Assignment.find_by(id: params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for adding participant. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else new_participant = assignment.add_participant(params[:user_id]) if new_participant.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Added participant with User ID: #{params[:user_id]} to assignment ID: #{assignment.id}.", request) render json: new_participant, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to add participant to assignment ID: #{assignment.id}. Errors: #{new_participant.errors.full_messages.join(', ')}", request) render json: new_participant.errors, status: :unprocessable_entity end end @@ -68,12 +82,15 @@ def remove_participant if user && assignment assignment.remove_participant(user.id) if assignment.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Removed participant with User ID: #{user.id} from assignment ID: #{assignment.id}.", request) render json: { message: "Participant removed successfully!" }, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to remove participant from assignment ID: #{assignment.id}. Errors: #{assignment.errors.full_messages.join(', ')}", request) render json: assignment.errors, status: :unprocessable_entity end else not_found_message = user ? "Assignment not found" : "User not found" + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "#{not_found_message} while removing participant.", request) render json: { error: not_found_message }, status: :not_found end end @@ -83,12 +100,15 @@ def remove_participant def remove_assignment_from_course assignment = Assignment.find(params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for removing from course. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else assignment = assignment.remove_assignment_from_course if assignment.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Removed assignment ID: #{assignment.id} from its course.", request) render json: assignment , status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to remove assignment ID: #{assignment.id} from course. Errors: #{assignment.errors.full_messages.join(', ')}", request) render json: assignment.errors, status: :unprocessable_entity end end @@ -102,12 +122,15 @@ def assign_course if assignment && course assignment = assignment.assign_course(course.id) if assignment.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Assigned course ID: #{course.id} to assignment ID: #{assignment.id}.", request) render json: assignment, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to assign course to assignment ID: #{assignment.id}. Errors: #{assignment.errors.full_messages.join(', ')}", request) render json: assignment.errors, status: :unprocessable_entity end else not_found_message = course ? "Assignment not found" : "Course not found" + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "#{not_found_message} while assigning course.", request) render json: { error: not_found_message }, status: :not_found end end @@ -116,12 +139,15 @@ def assign_course def copy_assignment assignment = Assignment.find_by(id: params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for copying. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else new_assignment = assignment.copy if new_assignment.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Copied assignment ID: #{assignment.id} to new assignment ID: #{new_assignment.id}.", request) render json: new_assignment, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to copy assignment ID: #{assignment.id}. Errors: #{new_assignment.errors.full_messages.join(', ')}", request) render json :new_assignment.errors, status: :unprocessable_entity end end @@ -132,8 +158,10 @@ def copy_assignment def show_assignment_details assignment = Assignment.find_by(id: params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for showing details. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched details for assignment ID: #{assignment.id}.", request) render json: { id: assignment.id, name: assignment.name, @@ -150,9 +178,12 @@ def show_assignment_details def has_topics assignment = Assignment.find_by(id: params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for checking topics. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else - render json: assignment.topics?, status: :ok + result = assignment.topics? + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Checked topics for assignment ID: #{assignment.id}. Has topics: #{result}", request) + render json: result, status: :ok end end @@ -161,9 +192,12 @@ def has_topics def team_assignment assignment = Assignment.find_by(id: params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for checking team assignment. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else - render json: assignment.team_assignment?, status: :ok + result = assignment.team_assignment? + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Checked if assignment ID: #{assignment.id} is a team assignment. Result: #{result}", request) + render json: result, status: :ok end end @@ -173,9 +207,12 @@ def valid_num_review assignment = Assignment.find_by(id: params[:assignment_id]) review_type = params[:review_type] if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for checking valid number of reviews. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else - render json: assignment.valid_num_review(review_type), status: :ok + result = assignment.valid_num_review(review_type) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Checked valid number of reviews for assignment ID: #{assignment.id}, Review type: #{review_type}. Result: #{result}", request) + render json: result, status: :ok end end @@ -184,9 +221,12 @@ def valid_num_review def has_teams assignment = Assignment.find_by(id: params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for checking teams. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else - render json: assignment.teams?, status: :ok + result = assignment.teams? + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Checked teams for assignment ID: #{assignment.id}. Has teams: #{result}", request) + render json: result, status: :ok end end @@ -195,11 +235,15 @@ def has_teams def varying_rubrics_by_round? assignment = Assignment.find_by(id: params[:assignment_id]) if assignment.nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found for checking varying rubrics. ID: #{params[:assignment_id]}", request) render json: { error: "Assignment not found" }, status: :not_found else if AssignmentQuestionnaire.exists?(assignment_id: assignment.id) - render json: assignment.varying_rubrics_by_round?, status: :ok + result = assignment.varying_rubrics_by_round? + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Checked varying rubrics by round for assignment ID: #{assignment.id}. Result: #{result}", request) + render json: result, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "No questionnaire exists for assignment ID: #{assignment.id}.", request) render json: { error: "No questionnaire/rubric exists for this assignment." }, status: :not_found end end diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb index 93964a254..cbccbe80d 100644 --- a/app/controllers/api/v1/bookmarks_controller.rb +++ b/app/controllers/api/v1/bookmarks_controller.rb @@ -4,6 +4,7 @@ class Api::V1::BookmarksController < ApplicationController # GET on /bookmarks def index @bookmarks = Bookmark.order(:id) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all bookmarks.", request) render json: @bookmarks, status: :ok and return end @@ -12,8 +13,10 @@ def index def show begin @bookmark = Bookmark.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched bookmark with ID: #{@bookmark.id}.", request) render json: @bookmark, status: :ok and return - rescue ActiveRecord::RecordNotFound + rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Bookmark not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :not_found and return end end @@ -26,8 +29,10 @@ def create @bookmark = Bookmark.new(bookmark_params) @bookmark.user_id = @current_user.id @bookmark.save! + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created bookmark with ID: #{@bookmark.id}.", request) render json: @bookmark, status: :created and return - rescue ActiveRecord::RecordInvalid + rescue ActiveRecord::RecordInvalid => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create bookmark. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :unprocessable_entity end end @@ -37,8 +42,10 @@ def create def update @bookmark = Bookmark.find(params[:id]) if @bookmark.update(update_bookmark_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated bookmark with ID: #{@bookmark.id}.", request) render json: @bookmark, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update bookmark with ID: #{@bookmark.id}. Errors: #{@bookmark.errors.full_messages.join(', ')}", request) render json: @bookmark.errors.full_messages, status: :unprocessable_entity end end @@ -49,8 +56,10 @@ def destroy begin @bookmark = Bookmark.find(params[:id]) @bookmark.delete - rescue ActiveRecord::RecordNotFound - render json: $ERROR_INFO.to_s, status: :not_found and return + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted bookmark with ID: #{@bookmark.id}.", request) + rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Bookmark not found with ID: #{params[:id]}. Error: #{e.message}", request) + render json: $ERROR_INFO.to_s, status: :not_found and return end end @@ -60,8 +69,10 @@ def get_bookmark_rating_score begin @bookmark = Bookmark.find(params[:id]) @bookmark_rating = BookmarkRating.where(bookmark_id: @bookmark.id, user_id: @current_user.id).first + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched rating for bookmark with ID: #{@bookmark.id}.", request) render json: @bookmark_rating, status: :ok and return - rescue ActiveRecord::RecordNotFound + rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Bookmark not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :not_found and return end end @@ -73,8 +84,10 @@ def save_bookmark_rating_score @bookmark_rating = BookmarkRating.where(bookmark_id: @bookmark.id, user_id: @current_user.id).first if @bookmark_rating.blank? @bookmark_rating = BookmarkRating.create(bookmark_id: @bookmark.id, user_id: @current_user.id, rating: params[:rating]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created bookmark rating with ID: #{@bookmark_rating.id}.", request) else @bookmark_rating.update({'rating': params[:rating].to_i}) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated bookmark rating with ID: #{@bookmark_rating.id}.", request) end render json: {"bookmark": @bookmark, "rating": @bookmark_rating}, status: :ok end diff --git a/app/controllers/api/v1/courses_controller.rb b/app/controllers/api/v1/courses_controller.rb index e4494bc99..bb898f6d0 100644 --- a/app/controllers/api/v1/courses_controller.rb +++ b/app/controllers/api/v1/courses_controller.rb @@ -21,8 +21,10 @@ def show def create course = Course.new(course_params) if course.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Course created: #{course.as_json}.", request) render json: course, status: :created else + ExpertizaLogger.warn LoggerMessage.new(controller_name, @current_user.name, "Error creating new Course: #{$ERROR_INFO}", request) render json: course.errors, status: :unprocessable_entity end end @@ -31,8 +33,10 @@ def create # Update a course def update if @course.update(course_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Course Information Modified: #{course.as_json}.", request) render json: @course, status: :ok else + ExpertizaLogger.warn LoggerMessage.new(controller_name, @current_user.name, "Course Failed to Update: #{$ERROR_INFO}.", request) render json: @course.errors, status: :unprocessable_entity end end @@ -41,6 +45,7 @@ def update # Delete a course def destroy @course.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Course with id #{params[:id]}, deleted", request) render json: { message: "Course with id #{params[:id]}, deleted" }, status: :no_content end @@ -49,8 +54,10 @@ def add_ta user = User.find_by(id: params[:ta_id]) result = @course.add_ta(user) if result[:success] + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Course with id #{params[:id]}, added new TA #{params[:ta_id]}.", request) render json: result[:data], status: :created else + ExpertizaLogger.warn LoggerMessage.new(controller_name, @current_user.name, "Error added TA #{params[:ta_id]} to Course #{params[:id]}.", request) render json: { status: "error", message: result[:message] }, status: :bad_request end end @@ -65,6 +72,7 @@ def view_tas def remove_ta result = @course.remove_ta(params[:ta_id]) if result[:success] + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "TA #{params[:ta_id]} removed from Course #{params[:id]}.", request) render json: { message: "The TA #{result[:ta_name]} has been removed." }, status: :ok else render json: { status: "error", message: result[:message] }, status: :not_found @@ -76,6 +84,7 @@ def copy # existing_course = Course.find(params[:id]) success = @course.copy_course if success + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Course #{params[:id]} copied successfully.", request) render json: { message: "The course #{@course.name} has been successfully copied" }, status: :ok else render json: { message: "The course was not able to be copied" }, status: :unprocessable_entity diff --git a/app/controllers/api/v1/institutions_controller.rb b/app/controllers/api/v1/institutions_controller.rb index b025079bc..5f6f3ad93 100644 --- a/app/controllers/api/v1/institutions_controller.rb +++ b/app/controllers/api/v1/institutions_controller.rb @@ -3,14 +3,17 @@ class Api::V1::InstitutionsController < ApplicationController # GET /institutions def index @institutions = Institution.all + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all institutions.", request) render json: @institutions, status: :ok end # GET /institutions/:id def show @institution = Institution.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched institution with ID: #{@institution.id}.", request) render json: @institution, status: :ok rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Institution not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: { error: e.message }, status: :not_found end @@ -18,8 +21,10 @@ def show def create @institution = Institution.new(institution_params) if @institution.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created institution with ID: #{@institution.id}.", request) render json: @institution, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create institution. Errors: #{@institution.errors.full_messages.join(', ')}", request) render json: @institution.errors, status: :unprocessable_entity end end @@ -28,8 +33,10 @@ def create def update @institution = Institution.find(params[:id]) if @institution.update(institution_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated institution with ID: #{@institution.id}.", request) render json: @institution, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update institution with ID: #{@institution.id}. Errors: #{@institution.errors.full_messages.join(', ')}", request) render json: @institution.errors, status: :unprocessable_entity end end @@ -38,6 +45,7 @@ def update def destroy @institution = Institution.find(params[:id]) @institution.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted institution with ID: #{@institution.id}.", request) render json: { message: 'Institution deleted' }, status: :ok end @@ -49,6 +57,7 @@ def institution_params end def institution_not_found + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Institution not found with ID: #{params[:id]}.", request) render json: { error: 'Institution not found' }, status: :not_found end end \ No newline at end of file diff --git a/app/controllers/api/v1/invitations_controller.rb b/app/controllers/api/v1/invitations_controller.rb index 1b4d88f1e..bd4f6f4df 100644 --- a/app/controllers/api/v1/invitations_controller.rb +++ b/app/controllers/api/v1/invitations_controller.rb @@ -4,6 +4,7 @@ class Api::V1::InvitationsController < ApplicationController # GET /api/v1/invitations def index @invitations = Invitation.all + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all invitations.", request) render json: @invitations, status: :ok end @@ -13,8 +14,10 @@ def create @invitation = Invitation.invitation_factory(invite_params) if @invitation.save @invitation.send_invite_email + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created invitation with ID: #{@invitation.id}.", request) render json: @invitation, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create invitation. Errors: #{@invitation.errors.full_messages.join(', ')}", request) render json: { error: @invitation.errors }, status: :unprocessable_entity end end @@ -22,6 +25,7 @@ def create # GET /api/v1/invitations/:id def show @invitation = Invitation.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched invitation with ID: #{@invitation.id}.", request) render json: @invitation, status: :ok end @@ -31,11 +35,14 @@ def update case params[:reply_status] when InvitationValidator::ACCEPT_STATUS @invitation.accept_invitation(nil) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Accepted invitation with ID: #{@invitation.id}.", request) render json: @invitation, status: :ok when InvitationValidator::REJECT_STATUS @invitation.decline_invitation(nil) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Rejected invitation with ID: #{@invitation.id}.", request) render json: @invitation, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Invalid reply status for invitation with ID: #{@invitation.id}.", request) render json: @invitation.errors, status: :unprocessable_entity end @@ -45,6 +52,7 @@ def update def destroy @invitation = Invitation.find(params[:id]) @invitation.retract_invitation(nil) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted invitation with ID: #{@invitation.id}.", request) render nothing: true, status: :no_content end @@ -53,6 +61,7 @@ def invitations_for_user_assignment begin @user = User.find(params[:user_id]) rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "User not found with ID: #{params[:user_id]}. Error: #{e.message}", request) render json: { error: e.message }, status: :not_found return end @@ -60,11 +69,13 @@ def invitations_for_user_assignment begin @assignment = Assignment.find(params[:assignment_id]) rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment not found with ID: #{params[:assignment_id]}. Error: #{e.message}", request) render json: { error: e.message }, status: :not_found return end @invitations = Invitation.where(to_id: @user.id).where(assignment_id: @assignment.id) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched invitations for user ID: #{@user.id} and assignment ID: #{@assignment.id}.", request) render json: @invitations, status: :ok end @@ -81,6 +92,7 @@ def invite_params # helper method used when invite is not found def invite_not_found + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Invitation not found with ID: #{params[:id]}.", request) render json: { error: "Invitation with id #{params[:id]} not found" }, status: :not_found end diff --git a/app/controllers/api/v1/join_team_requests_controller.rb b/app/controllers/api/v1/join_team_requests_controller.rb index 57a8ed383..4bbd0beb1 100644 --- a/app/controllers/api/v1/join_team_requests_controller.rb +++ b/app/controllers/api/v1/join_team_requests_controller.rb @@ -19,9 +19,11 @@ def action_allowed? # gets a list of all the join team requests def index unless @current_user.administrator? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Unauthorized access to join team requests.", request) return render json: { errors: 'Unauthorized' }, status: :unauthorized end join_team_requests = JoinTeamRequest.all + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all join team requests.", request) render json: join_team_requests, status: :ok end @@ -42,15 +44,19 @@ def create team = Team.find(params[:team_id]) if team.participants.include?(participant) + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "User already belongs to team ID: #{team.id}.", request) render json: { error: 'You already belong to the team' }, status: :unprocessable_entity elsif participant join_team_request.participant_id = participant.id if join_team_request.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created join team request with ID: #{join_team_request.id}.", request) render json: join_team_request, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create join team request. Errors: #{join_team_request.errors.full_messages.join(', ')}", request) render json: { errors: join_team_request.errors.full_messages }, status: :unprocessable_entity end else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Participant not found for user ID: #{@current_user.id}.", request) render json: { errors: 'Participant not found' }, status: :unprocessable_entity end end @@ -59,8 +65,10 @@ def create # Updates a join team request def update if @join_team_request.update(join_team_request_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated join team request with ID: #{@join_team_request.id}.", request) render json: { message: 'JoinTeamRequest was successfully updated' }, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update join team request with ID: #{@join_team_request.id}. Errors: #{@join_team_request.errors.full_messages.join(', ')}", request) render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity end end @@ -69,8 +77,10 @@ def update # delete a join team request def destroy if @join_team_request.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted join team request with ID: #{@join_team_request.id}.", request) render json: { message: 'JoinTeamRequest was successfully deleted' }, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to delete join team request with ID: #{@join_team_request.id}.", request) render json: { errors: 'Failed to delete JoinTeamRequest' }, status: :unprocessable_entity end end @@ -79,8 +89,10 @@ def destroy def decline @join_team_request.status = DECLINED if @join_team_request.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Declined join team request with ID: #{@join_team_request.id}.", request) render json: { message: 'JoinTeamRequest declined successfully' }, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to decline join team request with ID: #{@join_team_request.id}. Errors: #{@join_team_request.errors.full_messages.join(', ')}", request) render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity end end @@ -90,6 +102,7 @@ def decline def check_team_status team = Team.find(params[:team_id]) if team.full? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Attempted to join a full team with ID: #{team.id}.", request) render json: { message: 'This team is full.' }, status: :unprocessable_entity end end @@ -97,6 +110,7 @@ def check_team_status # Finds the join team request by ID def find_request @join_team_request = JoinTeamRequest.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Found join team request with ID: #{@join_team_request.id}.", request) end # Permits specified parameters for join team requests diff --git a/app/controllers/api/v1/questionnaires_controller.rb b/app/controllers/api/v1/questionnaires_controller.rb index 9bc2cd876..0996f91d5 100644 --- a/app/controllers/api/v1/questionnaires_controller.rb +++ b/app/controllers/api/v1/questionnaires_controller.rb @@ -4,6 +4,7 @@ class Api::V1::QuestionnairesController < ApplicationController # GET on /questionnaires def index @questionnaires = Questionnaire.order(:id) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all questionnaires.", request) render json: @questionnaires, status: :ok and return end @@ -12,8 +13,10 @@ def index def show begin @questionnaire = Questionnaire.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched questionnaire with ID: #{@questionnaire.id}.", request) render json: @questionnaire, status: :ok and return - rescue ActiveRecord::RecordNotFound + rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Questionnaire not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :not_found and return end end @@ -26,8 +29,10 @@ def create @questionnaire = Questionnaire.new(questionnaire_params) @questionnaire.display_type = sanitize_display_type(@questionnaire.questionnaire_type) @questionnaire.save! + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created questionnaire with ID: #{@questionnaire.id}.", request) render json: @questionnaire, status: :created and return - rescue ActiveRecord::RecordInvalid + rescue ActiveRecord::RecordInvalid => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create questionnaire. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :unprocessable_entity end end @@ -38,7 +43,9 @@ def destroy begin @questionnaire = Questionnaire.find(params[:id]) @questionnaire.delete - rescue ActiveRecord::RecordNotFound + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted questionnaire with ID: #{@questionnaire.id}.", request) + rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Questionnaire not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :not_found and return end end @@ -49,8 +56,10 @@ def destroy def update @questionnaire = Questionnaire.find(params[:id]) if @questionnaire.update(questionnaire_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated questionnaire with ID: #{@questionnaire.id}.", request) render json: @questionnaire, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update questionnaire with ID: #{@questionnaire.id}. Errors: #{@questionnaire.errors.full_messages.join(', ')}", request) render json: @questionnaire.errors.full_messages, status: :unprocessable_entity end end @@ -59,10 +68,13 @@ def update def copy begin @questionnaire = Questionnaire.copy_questionnaire_details(params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Copied questionnaire with ID: #{params[:id]} to new questionnaire with ID: #{@questionnaire.id}.", request) render json: @questionnaire, status: :ok and return - rescue ActiveRecord::RecordNotFound + rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Questionnaire not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :not_found and return - rescue ActiveRecord::RecordInvalid + rescue ActiveRecord::RecordInvalid => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to copy questionnaire with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :unprocessable_entity end end @@ -75,11 +87,14 @@ def toggle_access @questionnaire = Questionnaire.find(params[:id]) @questionnaire.toggle!(:private) @access = @questionnaire.private ? 'private' : 'public' + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Toggled access for questionnaire with ID: #{@questionnaire.id}. Now it is #{@access}.", request) render json: "The questionnaire \"#{@questionnaire.name}\" has been successfully made #{@access}. ", status: :ok - rescue ActiveRecord::RecordNotFound + rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Questionnaire not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :not_found - rescue ActiveRecord::RecordInvalid + rescue ActiveRecord::RecordInvalid => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to toggle access for questionnaire with ID: #{params[:id]}. Error: #{e.message}", request) render json: $ERROR_INFO.to_s, status: :unprocessable_entity end end diff --git a/app/controllers/api/v1/questions_controller.rb b/app/controllers/api/v1/questions_controller.rb index 10c26875d..fc8d92ae8 100644 --- a/app/controllers/api/v1/questions_controller.rb +++ b/app/controllers/api/v1/questions_controller.rb @@ -4,6 +4,7 @@ class Api::V1::QuestionsController < ApplicationController # GET on /questions def index @questions = Question.order(:id) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all questions.", request) render json: @questions, status: :ok end @@ -12,8 +13,10 @@ def index def show begin @question = Question.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched question with ID: #{@question.id}.", request) render json: @question, status: :ok rescue ActiveRecord::RecordNotFound + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Unable to find Question with ID: #{params[:id]}", request) render json: $ERROR_INFO.to_s, status: :not_found end end @@ -48,11 +51,14 @@ def create end if question.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created question with ID: #{question.id} under questionnaire ID: #{questionnaire.id}.", request) render json: question, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Question not able to be saved: #{question.as_json}", request) render json: question.errors.full_messages.to_sentence, status: :unprocessable_entity end rescue ActiveRecord::RecordNotFound + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Questionnaire not able to found with ID: #{params[:questionnaire_id]}", request) render json: $ERROR_INFO.to_s, status: :not_found and return end @@ -63,7 +69,9 @@ def destroy begin @question = Question.find(params[:id]) @question.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Destroyed Question: #{@question.as_json}", request) rescue ActiveRecord::RecordNotFound + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Question unable to be found with ID: #{params[:id]}", request) render json: $ERROR_INFO.to_s, status: :not_found and return end end @@ -74,8 +82,10 @@ def show_all begin @questionnaire = Questionnaire.find(params[:id]) @questions = @questionnaire.questions + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched #{@questions.count} Questions for Questionnaire with ID: #{params[:id]}", request) render json: @questions, status: :ok rescue ActiveRecord::RecordNotFound + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Questionnaire unable to be found with ID: #{params[:id]}", request) render json: $ERROR_INFO.to_s, status: :not_found end end @@ -88,12 +98,15 @@ def delete_all begin questionnaire = Questionnaire.find(params[:id]) if questionnaire.questions.empty? + ExpertizaLogger.warn LoggerMessage.new(controller_name, @current_user.name, "Questions attempted to be destroyed for Questionnaire with ID #{params[:id]}, but found to already not have any questions", request) render json: "No questions associated with questionnaire ID #{params[:id]}.", status: :unprocessable_entity and return end questionnaire.questions.destroy_all + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Questionnaire with ID #{params[:id]} had all questions deleted", request) render json: "All questions for questionnaire ID #{params[:id]} have been deleted.", status: :ok rescue ActiveRecord::RecordNotFound + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Questionnaire unable to be found with ID: #{params[:id]}", request) render json: "Questionnaire ID #{params[:id]} not found.", status: :not_found and return end end @@ -104,11 +117,14 @@ def update begin @question = Question.find(params[:id]) if @question.update(question_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated question with ID: #{@question.id}.", request) render json: @question, status: :ok and return else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Question unable to be updated with: #{question_params}", request) render json: "Failed to update the question.", status: :unprocessable_entity and return end rescue ActiveRecord::RecordNotFound + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Question unable to be found with ID: #{params[:id]}", request) render json: $ERROR_INFO.to_s, status: :not_found and return end end diff --git a/app/controllers/api/v1/roles_controller.rb b/app/controllers/api/v1/roles_controller.rb index 68e5a59e8..247889df6 100644 --- a/app/controllers/api/v1/roles_controller.rb +++ b/app/controllers/api/v1/roles_controller.rb @@ -5,12 +5,14 @@ class Api::V1::RolesController < ApplicationController # GET /roles def index roles = Role.order(:id) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all roles.", request) render json: roles, status: :ok end # GET /roles/:id def show role = Role.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched role with ID: #{role.id}.", request) render json: role, status: :ok end @@ -18,8 +20,10 @@ def show def create role = Role.new(role_params) if role.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created role with ID: #{role.id}.", request) render json: role, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create role. Errors: #{role.errors.full_messages.join(', ')}", request) render json: role.errors, status: :unprocessable_entity end end @@ -28,8 +32,10 @@ def create def update role = Role.find(params[:id]) if role.update(role_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated role with ID: #{role.id}.", request) render json: role, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update role with ID: #{role.id}. Errors: #{role.errors.full_messages.join(', ')}", request) render json: role.errors, status: :unprocessable_entity end end @@ -39,12 +45,14 @@ def destroy role = Role.find(params[:id]) role_name = role.name role.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted role with ID: #{role.id}, Name: #{role_name}.", request) render json: { message: "Role #{role_name} with id #{params[:id]} deleted successfully!" }, status: :no_content end def subordinate_roles role = current_user.role roles = role.subordinate_roles + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched subordinate roles for role ID: #{role.id}.", request) render json: roles, status: :ok end @@ -60,6 +68,7 @@ def role_params # end def parameter_missing + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Parameter missing.", request) render json: { error: 'Parameter missing' }, status: :unprocessable_entity end end diff --git a/app/controllers/api/v1/sign_up_topics_controller.rb b/app/controllers/api/v1/sign_up_topics_controller.rb index a736f3eaa..4deb6a7ec 100644 --- a/app/controllers/api/v1/sign_up_topics_controller.rb +++ b/app/controllers/api/v1/sign_up_topics_controller.rb @@ -5,12 +5,15 @@ class Api::V1::SignUpTopicsController < ApplicationController # Retrieve SignUpTopics by two query parameters - assignment_id (compulsory) and an array of topic_ids (optional) def index if params[:assignment_id].nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment ID is missing.", request) render json: { message: 'Assignment ID is required!' }, status: :unprocessable_entity elsif params[:topic_ids].nil? @sign_up_topics = SignUpTopic.where(assignment_id: params[:assignment_id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched sign-up topics for assignment ID: #{params[:assignment_id]}.", request) render json: @sign_up_topics, status: :ok else @sign_up_topics = SignUpTopic.where(assignment_id: params[:assignment_id], topic_identifier: params[:topic_ids]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched sign-up topics for assignment ID: #{params[:assignment_id]} with topic IDs: #{params[:topic_ids].join(', ')}.", request) render json: @sign_up_topics, status: :ok end # render json: {message: 'All selected topics have been loaded successfully.', sign_up_topics: @stopics}, status: 200 @@ -26,8 +29,10 @@ def create @sign_up_topic.micropayment = params[:micropayment] if @assignment.microtask? if @sign_up_topic.save # undo_link "The topic: \"#{@sign_up_topic.topic_name}\" has been created successfully. " + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created sign-up topic with ID: #{@sign_up_topic.id} for assignment ID: #{@assignment.id}.", request) render json: { message: "The topic: \"#{@sign_up_topic.topic_name}\" has been created successfully. " }, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create sign-up topic. Errors: #{@sign_up_topic.errors.full_messages.join(', ')}", request) render json: { message: @sign_up_topic.errors }, status: :unprocessable_entity end end @@ -36,8 +41,10 @@ def create # updates parameters present in sign_up_topic_params. def update if @sign_up_topic.update(sign_up_topic_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated sign-up topic with ID: #{@sign_up_topic.id}.", request) render json: { message: "The topic: \"#{@sign_up_topic.topic_name}\" has been updated successfully. " }, status: 200 else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update sign-up topic with ID: #{@sign_up_topic.id}. Errors: #{@sign_up_topic.errors.full_messages.join(', ')}", request) render json: @sign_up_topic.errors, status: :unprocessable_entity end end @@ -54,6 +61,7 @@ def destroy # render json: {message: @sign_up_topic} # filters topics based on assignment id (required) and topic identifiers (optional) if params[:assignment_id].nil? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Assignment ID is missing for destroy action.", request) render json: { message: 'Assignment ID is required!' }, status: :unprocessable_entity elsif params[:topic_ids].nil? @sign_up_topics = SignUpTopic.where(assignment_id: params[:assignment_id]) @@ -64,8 +72,10 @@ def destroy end if @sign_up_topics.each(&:delete) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted sign-up topics.", request) render json: { message: "The topic has been deleted successfully. " }, status: :no_content else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to delete sign-up topics.", request) render json: @sign_up_topic.errors, status: :unprocessable_entity end end diff --git a/app/controllers/api/v1/signed_up_teams_controller.rb b/app/controllers/api/v1/signed_up_teams_controller.rb index 97ada5a24..ee319bbac 100644 --- a/app/controllers/api/v1/signed_up_teams_controller.rb +++ b/app/controllers/api/v1/signed_up_teams_controller.rb @@ -6,6 +6,7 @@ def index # puts params[:topic_id] @sign_up_topic = SignUpTopic.find(params[:topic_id]) @signed_up_team = SignedUpTeam.find_team_participants(@sign_up_topic.assignment_id) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched signed-up team for topic ID: #{@sign_up_topic.id}.", request) render json: @signed_up_team end @@ -16,8 +17,10 @@ def create; end def update @signed_up_team = SignedUpTeam.find(params[:id]) if @signed_up_team.update(signed_up_teams_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated signed-up team with team ID: #{@signed_up_team.team_id}.", request) render json: { message: "The team has been updated successfully. " }, status: 200 else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update signed-up team with team ID: #{@signed_up_team.team_id}. Errors: #{@signed_up_team.errors.full_messages.join(', ')}", request) render json: @signed_up_team.errors, status: :unprocessable_entity end end @@ -29,8 +32,10 @@ def sign_up topic_id = params[:topic_id] @signed_up_team = SignedUpTeam.create_signed_up_team(topic_id, team_id) if @signed_up_team + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Team ID: #{team_id} signed up for topic ID: #{topic_id}.", request) render json: { message: "Signed up team successful!" }, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to sign up team ID: #{team_id} for topic ID: #{topic_id}. Errors: #{@signed_up_team.errors.full_messages.join(', ')}", request) render json: { message: @signed_up_team.errors }, status: :unprocessable_entity end end @@ -48,8 +53,10 @@ def sign_up_student @signed_up_team = SignedUpTeam.create_signed_up_team(topic_id, team_id) # create(topic_id, team_id) if @signed_up_team + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "User ID: #{user_id} (Team ID: #{team_id}) signed up for topic ID: #{topic_id}.", request) render json: { message: "Signed up team successful!" }, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to sign up user ID: #{user_id} (Team ID: #{team_id}) for topic ID: #{topic_id}. Errors: #{@signed_up_team.errors.full_messages.join(', ')}", request) render json: { message: @signed_up_team.errors }, status: :unprocessable_entity end end @@ -58,8 +65,10 @@ def sign_up_student def destroy @signed_up_team = SignedUpTeam.find(params[:id]) if SignedUpTeam.delete_signed_up_team(@signed_up_team.team_id) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted signed-up team with team ID: #{@signed_up_team.team_id}.", request) render json: { message: 'Signed up teams was deleted successfully!' }, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to delete signed-up team with team ID: #{@signed_up_team.team_id}. Errors: #{@signed_up_team.errors.full_messages.join(', ')}", request) render json: @signed_up_team.errors, status: :unprocessable_entity end end diff --git a/app/controllers/api/v1/student_tasks_controller.rb b/app/controllers/api/v1/student_tasks_controller.rb index 6eb784b73..b356a2b47 100644 --- a/app/controllers/api/v1/student_tasks_controller.rb +++ b/app/controllers/api/v1/student_tasks_controller.rb @@ -4,6 +4,7 @@ class Api::V1::StudentTasksController < ApplicationController def list # Retrieves all tasks that belong to the current user. @student_tasks = StudentTask.from_user(current_user) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched student tasks for user ID: #{current_user.id}.", request) # Render the list of student tasks as JSON. render json: @student_tasks, status: :ok end @@ -18,6 +19,7 @@ def view # Retrieves the student task where the participant's ID matches the provided parameter. # This function will be used for clicking on a specific student task to "view" its details. @student_task = StudentTask.from_participant_id(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched student task for participant ID: #{params[:id]}.", request) # Render the found student task as JSON. render json: @student_task, status: :ok end diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb index 086376556..0dc11567c 100644 --- a/app/controllers/api/v1/users_controller.rb +++ b/app/controllers/api/v1/users_controller.rb @@ -4,12 +4,14 @@ class Api::V1::UsersController < ApplicationController def index users = User.all + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched all users.", request) render json: users, status: :ok end # GET /users/:id def show user = User.find(params[:id]) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched user with ID: #{user.id}.", request) render json: user, status: :ok end @@ -19,8 +21,10 @@ def create params[:user][:password] ||= 'password' user = User.new(user_params) if user.save + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Created user with ID: #{user.id}.", request) render json: user, status: :created else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to create user. Errors: #{user.errors.full_messages.join(', ')}", request) render json: user.errors, status: :unprocessable_entity end end @@ -29,8 +33,10 @@ def create def update user = User.find(params[:id]) if user.update(user_params) + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Updated user with ID: #{user.id}.", request) render json: user, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Failed to update user with ID: #{user.id}. Errors: #{user.errors.full_messages.join(', ')}", request) render json: user.errors, status: :unprocessable_entity end end @@ -39,6 +45,7 @@ def update def destroy user = User.find(params[:id]) user.destroy + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Deleted user with ID: #{user.id}.", request) render json: { message: "User #{user.name} with id #{params[:id]} deleted successfully!" }, status: :no_content end @@ -47,8 +54,10 @@ def destroy def institution_users institution = Institution.find(params[:id]) users = institution.users + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched users for institution ID: #{institution.id}.", request) render json: users, status: :ok rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Institution not found with ID: #{params[:id]}. Error: #{e.message}", request) render json: { error: e.message }, status: :not_found end @@ -57,11 +66,13 @@ def institution_users def managed_users parent = User.find(params[:id]) if parent.student? + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "User ID: #{parent.id} is a student and cannot manage users.", request) render json: { error: 'Students do not manage any users' }, status: :unprocessable_entity return end parent = User.instantiate(parent) users = parent.managed_users + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched managed users for user ID: #{parent.id}.", request) render json: users, status: :ok end @@ -71,8 +82,10 @@ def role_users name = params[:name].split('_').map(&:capitalize).join(' ') role = Role.find_by(name:) users = role.users + ExpertizaLogger.info LoggerMessage.new(controller_name, @current_user.name, "Fetched users for role: #{name}.", request) render json: users, status: :ok rescue ActiveRecord::RecordNotFound => e + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Role not found with name: #{name}. Error: #{e.message}", request) render json: { error: e.message }, status: :not_found end @@ -86,10 +99,12 @@ def user_params end def user_not_found + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "User not found with ID: #{params[:id]}.", request) render json: { error: "User with id #{params[:id]} not found" }, status: :not_found end def parameter_missing + ExpertizaLogger.error LoggerMessage.new(controller_name, @current_user.name, "Parameter missing.", request) render json: { error: 'Parameter missing' }, status: :unprocessable_entity end end diff --git a/app/controllers/authentication_controller.rb b/app/controllers/authentication_controller.rb index 32c96a909..785409474 100644 --- a/app/controllers/authentication_controller.rb +++ b/app/controllers/authentication_controller.rb @@ -11,8 +11,12 @@ def login payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name, institution_id: user.institution.id } token = JsonWebToken.encode(payload, 24.hours.from_now) + + ExpertizaLogger.info LoggerMessage.new(controller_name, user.name, 'Login successful') + render json: { token: }, status: :ok else + ExpertizaLogger.error LoggerMessage.new(controller_name, user&.name || '', 'Failed login attempt. Invalid username/password', request) render json: { error: 'Invalid username / password' }, status: :unauthorized end end diff --git a/app/models/expertiza_logger.rb b/app/models/expertiza_logger.rb new file mode 100644 index 000000000..5d01e2a7b --- /dev/null +++ b/app/models/expertiza_logger.rb @@ -0,0 +1,81 @@ +# expertiza_logger.rb +# This file contains the formatter used for the ExpertizaLogger and the ExpertizaLogger. +# ExpertizaLogger provides 5 levels of logging: debug, info, warn, error, and fatal. + +# ExpertizaLogFormatter formats the logs to ensure consistent log message formatting. +class ExpertizaLogFormatter < Logger::Formatter + # This method is invoked when a log event occurs and formats the message. + def call(s, ts, pg, msg) + if msg.is_a?(LoggerMessage) + "TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[#{msg.oip}] RID=[#{msg.req_id}] CTR=[#{msg.generator}] UID=[#{msg.unity_id}] MSG=[#{filter(msg.message)}]\n" + else + "TST=[#{ts}] SVT=[#{s}] PNM=[#{pg}] OIP=[] RID=[] CTR=[] UID=[] MSG=[#{filter(msg)}]\n" + end + end + + # Filter out the newline characters in the message and replace with a space character. + # Reason: + # Each log message should be a single-line entry in a log file to ensure they are easily readable and parsable. + # The presence of newline characters can break log parsers and make logs harder to analyze. + def filter(msg) + msg.tr("\n", ' ') + end +end + +# ExpertizaLogger provides the logging levels and functionality. +# Each level creates its own file (expertiza_info.log or similar) and +# uses the ExpertizaLogFormatter to format and then print the message. +class ExpertizaLogger + + # Logs an informational message. + # + # Use the INFO level to log general application events that confirm things are working as expected. + def self.info(message = nil) + @info_log ||= Logger.new(Rails.root.join('log', 'expertiza_info.log')) + add_formatter @info_log + @info_log.info(message) + end + + # Logs a warning message. + # + # Use the WARN level to log unexpected events that are not immediately harmful but might cause issues later. + def self.warn(message = nil) + @warn_log ||= Logger.new(Rails.root.join('log', 'expertiza_warn.log')) + add_formatter @warn_log + @warn_log.warn(message) + end + + # Logs an error message. + # + # Use the ERROR level to log issues that have caused an operation to fail, such as erroneous database requests. + def self.error(message = nil) + @error_log ||= Logger.new(Rails.root.join('log', 'expertiza_error.log')) + add_formatter @error_log + @error_log.error(message) + end + + # Logs a fatal message. + # + # Use the FATAL level for severe errors that lead to application termination. + def self.fatal(message = nil) + @fatal_log ||= Logger.new(Rails.root.join('log', 'expertiza_fatal.log')) + add_formatter @fatal_log + @fatal_log.fatal(message) + end + + # Logs a debug message. + # + # Use the DEBUG level for diagnostic information useful during development. + def self.debug(message = nil) + @debug_log ||= Logger.new(Rails.root.join('log', 'expertiza_debug.log')) + add_formatter @debug_log + @debug_log.debug(message) + end + + # Adds the custom formatter to the given logger instance. + # Reason: + # Ensures all log messages are consistently formatted using ExpertizaLogFormatter. + def self.add_formatter(log) + log.formatter ||= ExpertizaLogFormatter.new + end +end \ No newline at end of file diff --git a/app/models/logger_message.rb b/app/models/logger_message.rb new file mode 100644 index 000000000..a6af5d61d --- /dev/null +++ b/app/models/logger_message.rb @@ -0,0 +1,11 @@ +# LoggerMessage to provide the fields expected by the ExpertizaLogFormatter +class LoggerMessage + attr_reader :generator, :unity_id, :message, :oip, :req_id + def initialize(generator, unity_id, message, req = nil) + @generator = generator + @unity_id = unity_id + @message = message + @oip = req.remote_ip if req + @req_id = req.uuid if req + end +end \ No newline at end of file diff --git a/spec/logs/expertiza_log_formatter_spec.rb b/spec/logs/expertiza_log_formatter_spec.rb new file mode 100644 index 000000000..4dd012040 --- /dev/null +++ b/spec/logs/expertiza_log_formatter_spec.rb @@ -0,0 +1,49 @@ +require 'rails_helper' +require_relative '../../app/models/expertiza_logger' + +RSpec.describe ExpertizaLogFormatter do + let(:formatter) { ExpertizaLogFormatter.new } + let(:timestamp) { Time.now } + let(:severity) { 'INFO' } + let(:progname) { 'Expertiza' } + + context 'when the message is a plain string' do + let(:message) { 'Test message with more text' } + + it 'formats the message correctly' do + formatted_message = formatter.call(severity, timestamp, progname, message) + expect(formatted_message).to include("TST=[#{timestamp}] SVT=[#{severity}] PNM=[#{progname}] OIP=[] RID=[] CTR=[] UID=[] MSG=[Test message with more text]") + end + end + + context 'when the message is a plain string with newline' do + let(:message) { "Test message with newline\nto more text" } + + it 'formats the message correctly' do + formatted_message = formatter.call(severity, timestamp, progname, message) + expect(formatted_message).to include("TST=[#{timestamp}] SVT=[#{severity}] PNM=[#{progname}] OIP=[] RID=[] CTR=[] UID=[] MSG=[Test message with newline to more text]") + end + end + + context 'when the message is a LoggerMessage object' do + let(:logger_message) do + LoggerMessage.new('gen1', 'unityid1', 'Test message') + end + + it 'formats the message correctly' do + formatted_message = formatter.call(severity, timestamp, progname, logger_message) + expect(formatted_message).to include("TST=[#{timestamp}] SVT=[#{severity}] PNM=[#{progname}] OIP=[] RID=[] CTR=[gen1] UID=[unityid1] MSG=[Test message]") + end + end + + context 'when the message is a LoggerMessage object with request' do + let(:logger_message) do + LoggerMessage.new('gen1', 'unityid1', 'Test message', double("request", remote_ip: "192.168.1.1", uuid: "12345")) + end + + it 'formats the message correctly' do + formatted_message = formatter.call(severity, timestamp, progname, logger_message) + expect(formatted_message).to include("TST=[#{timestamp}] SVT=[#{severity}] PNM=[#{progname}] OIP=[192.168.1.1] RID=[12345] CTR=[gen1] UID=[unityid1] MSG=[Test message]") + end + end +end diff --git a/spec/logs/expertiza_logger_spec.rb b/spec/logs/expertiza_logger_spec.rb new file mode 100644 index 000000000..9cf5a47be --- /dev/null +++ b/spec/logs/expertiza_logger_spec.rb @@ -0,0 +1,63 @@ +RSpec.describe ExpertizaLogger do + let(:message) { 'Test message' } + let(:timestamp) { Time.now } + + # Create a mock logger instance + let(:mock_logger) { instance_double(Logger) } + + before do + allow(Logger).to receive(:new).and_return(mock_logger) + allow(mock_logger).to receive(:formatter) + allow(mock_logger).to receive(:formatter=).with(an_instance_of(ExpertizaLogFormatter)) + allow(mock_logger).to receive(:info) + allow(mock_logger).to receive(:warn) + allow(mock_logger).to receive(:error) + allow(mock_logger).to receive(:fatal) + allow(mock_logger).to receive(:debug) + end + + describe '.info' do + it 'logs the message to the correct file with info severity' do + ExpertizaLogger.info(message) + expect(Logger).to have_received(:new).with(Rails.root.join('log', 'expertiza_info.log')) + expect(mock_logger).to have_received(:formatter=).with(an_instance_of(ExpertizaLogFormatter)) + expect(mock_logger).to have_received(:info).with(message) + end + end + + describe '.warn' do + it 'logs the message to the correct file with warn severity' do + ExpertizaLogger.warn(message) + expect(Logger).to have_received(:new).with(Rails.root.join('log', 'expertiza_warn.log')) + expect(mock_logger).to have_received(:formatter=).with(an_instance_of(ExpertizaLogFormatter)) + expect(mock_logger).to have_received(:warn).with(message) + end + end + + describe '.error' do + it 'logs the message to the correct file with error severity' do + ExpertizaLogger.error(message) + expect(Logger).to have_received(:new).with(Rails.root.join('log', 'expertiza_error.log')) + expect(mock_logger).to have_received(:formatter=).with(an_instance_of(ExpertizaLogFormatter)) + expect(mock_logger).to have_received(:error).with(message) + end + end + + describe '.fatal' do + it 'logs the message to the correct file with fatal severity' do + ExpertizaLogger.fatal(message) + expect(Logger).to have_received(:new).with(Rails.root.join('log', 'expertiza_fatal.log')) + expect(mock_logger).to have_received(:formatter=).with(an_instance_of(ExpertizaLogFormatter)) + expect(mock_logger).to have_received(:fatal).with(message) + end + end + + describe '.debug' do + it 'logs the message to the correct file with debug severity' do + ExpertizaLogger.debug(message) + expect(Logger).to have_received(:new).with(Rails.root.join('log', 'expertiza_debug.log')) + expect(mock_logger).to have_received(:formatter=).with(an_instance_of(ExpertizaLogFormatter)) + expect(mock_logger).to have_received(:debug).with(message) + end + end +end diff --git a/spec/logs/user_logs_spec.rb b/spec/logs/user_logs_spec.rb new file mode 100644 index 000000000..0f583b007 --- /dev/null +++ b/spec/logs/user_logs_spec.rb @@ -0,0 +1,24 @@ +require 'rails_helper' + +RSpec.describe Api::V1::UsersController, type: :controller do + let(:user) { build(:user, name: "Jane", email: "jdoe@ncsu.edu", full_name: "Jane Doe") } + let(:params) do { user: { + "name": "Jane Doe", + "full_name": "Jane Doe", + "email": "jane.doe@example.com", + "role_id": 1, + "institution_id": 1, + "password": "password", + "password_confirmation": "password" } } + end + + # https://everydayrails.com/2020/08/10/rails-log-message-testing-rspec + # Rails testing + it "logs when user is created" do + allow(Rails.logger).to receive(:info) + expect(Rails.logger).to receive(:info) + + post :create, params: params + end + +end