CSC/ECE 517 Spring 2024 - E2421. Reimplement impersonating users (within impersonate controller.rb): Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 9: Line 9:
==Implementation==
==Implementation==


===UML Diagram===
The following UML diagram shows the association between models we will be working on
The following UML diagram shows the association between models we will be working on


[[File:Uml reimplement impersonate.png]]
[[File:Uml reimplement impersonate.png]]
===Hierarchy Diagram===
Visualization of the hierarchical structure
[[File:User-hierarchy.jpg]]


===Request===
===Request===
Line 52: Line 60:
     "success": true
     "success": true


===Impersonate Controller===
impersonate_controller.rb file
<pre>
class Api::V1::ImpersonateController < ApplicationController
  # Fetches users to impersonate whose name match the passed parameter
  def get_users_list
    users = current_user.get_available_users(params[:user_name])
    render json: { message: "Successfully Fetched User List!", userList:users, success:true }, status: :ok
  end
  def check_if_user_impersonateable?
    impersonate_user = User.find_by(id: params[:impersonate_id])
    if impersonate_user
      return current_user.can_impersonate? impersonate_user
    end
    false
  end
  # Impersonates a new user and returns new jwt token
  def impersonate
    unless params[:impersonate_id].present?
      render json: { error: "impersonate_id is required", success:false }, status: :unprocessable_entity
      return
    end
    if check_if_user_impersonateable?
      impersonate_user = User.find_by(id: params[:impersonate_id])
      payload = { id: impersonate_user.id, name: impersonate_user.name, full_name: impersonate_user.full_name, role: impersonate_user.role.name,
                  institution_id: impersonate_user.institution.id, impersonated:true, original_user: current_user }
      impersonate_user_token = JsonWebToken.encode(payload, 24.hours.from_now)
      render json: { message: "Successfully Impersonated #{impersonate_user.name}!", token:impersonate_user_token, success:true }, status: :ok
    else
      render json: { error: "You do not have permission to impersonate this user", success:false }, status: :forbidden
    end
  end
end
</pre>





Revision as of 01:15, 24 March 2024

Expertiza

Expertiza is a Ruby on Rails based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.

Project Overview

The objective is to reimplement the backend code for the impersonation feature in the new implementation of Expertiza. The current implementation relies on sessions, which won't be compatible with the new implementation using JWT tokens for authentication and returning JSON responses. The challenge lies in transitioning the logic from session-based management to JWT-based authentication while maintaining the functionality of impersonating users. The reimplementation involves planning how the backend will communicate with the frontend, potentially requiring changes in existing or new files beyond the impersonate_controller.rb.

Implementation

UML Diagram

The following UML diagram shows the association between models we will be working on


Hierarchy Diagram

Visualization of the hierarchical structure


Request

  • GET: {BASE_URL}/api/v1/impersonate/:username
  - Response:
   "message": "Successfully Fetched User List!",
   "userList": [
       {
           "id": 4,
           "name": "Mihir",
           "full_name": "Mihir BHanderi",
           "email": "mbhande@example.com",
           "email_on_review": false,
           "email_on_submission": false,
           "email_on_review_of_review": false,
           "role": {
               "id": 4,
               "name": "Teaching Assistant"
           },
           "institution": {
               "id": 1,
               "name": "North Carolina State University"
           },
           "parent": {
               "id": null,
               "name": null
           }
       }
   ],
   "success": true
  • POST: {BASE_URL}/api/v1/impersonate
  - Payload: impersonate_id
  - Response: 
    "message": "Successfully Impersonated Ketul!",
    "token": "eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MywibmFtZSI6IktldHVsIiwiZnVsbF9uYW1lIjoiS2V0dWwgQ2hheXlhIiwicm9sZSI6Ikluc3RydWN0b3IiLCJpbnN0aXR1dGlvbl9pZCI6MSwiaW1wZXJzb25hdGVkIjp0cnVlLCJvcmlnaW5hbF91c2VyIjoiIzxVc2VyOjB4MDAwMDdmMzVmYTc5YjVmOD4iLCJleHAiOjE3MTEzMjc0MTV9.U9wDOT618UCkf25MnCiK8W3ybeZv5BSQDNTEPOMUDABAvDd0HWSj3kIGccITHaoVsIykZFsyUDY3rL_M32zmfEXvxZuEleWSqUZGxbjQRIFP1bR_Q5sPESoBdlxVJ4QG8sUGQtuhOzMyH3z4R4ruhz1JpsQlalVZQHCbdtJOI9B4WKhNJ98Dls1fefnzYwLMnTr6e3ttbGGGK5Bm8zSpPvIWmCVNoueKHNptFcNejbU4Mt9RHWHLsTwdAtuywNLCu7li7RRNXo00D5JOUMxL7eB5AiQRpxah8BF7b0lM_Xh7bB56WvD5JTjoNZu3c3AK_EJksGXiFxwlPzNRc8Q",
   "success": true


Impersonate Controller

impersonate_controller.rb file

 class Api::V1::ImpersonateController < ApplicationController

  # Fetches users to impersonate whose name match the passed parameter
  def get_users_list
    users = current_user.get_available_users(params[:user_name])
    render json: { message: "Successfully Fetched User List!", userList:users, success:true }, status: :ok
  end

  def check_if_user_impersonateable?
    impersonate_user = User.find_by(id: params[:impersonate_id])
    if impersonate_user
      return current_user.can_impersonate? impersonate_user
    end
    false
  end

  # Impersonates a new user and returns new jwt token
  def impersonate
    unless params[:impersonate_id].present?
      render json: { error: "impersonate_id is required", success:false }, status: :unprocessable_entity
      return
    end

    if check_if_user_impersonateable?
      impersonate_user = User.find_by(id: params[:impersonate_id])

      payload = { id: impersonate_user.id, name: impersonate_user.name, full_name: impersonate_user.full_name, role: impersonate_user.role.name,
                  institution_id: impersonate_user.institution.id, impersonated:true, original_user: current_user }
      impersonate_user_token = JsonWebToken.encode(payload, 24.hours.from_now)

      render json: { message: "Successfully Impersonated #{impersonate_user.name}!", token:impersonate_user_token, success:true }, status: :ok

    else
      render json: { error: "You do not have permission to impersonate this user", success:false }, status: :forbidden
    end
  end
end


Files added / modified

  • reimplementation-back-end/app/models/user.rb
  • reimplementation-back-end/app/controllers/api/v1/impersonate_controller.rb
  • reimplementation-back-end/config/routes.rb

List of Users in Database

ID Email Password Role
1 admin2@example.com password123 Super-Administrator
2 jay@example.com password123 Administration
3 k2l@example.com password123 Instructor
4 mbhande@example.com password123 TA
7 dpatesl@example.com password123 Student

Testing on Postman

Postman was used to manually test the additional method in impersonate_controller.rb, as well as the actions and routes of the corresponding controllers. Before testing any of these methods with Postman, submit a request to /login using the user_name and password fields, which will send an authentication token. This token must be added to Postman's 'Authorization' tab as a 'Bearer token' before any further requests can be made. Postman collection link

  • Fetch User List which can be impersonated (For eg: If Instructor fetches list he can see matched TAs and Students only)

  • Login with provided credentials and copy the token

  • In the Expertiza/Authorization paste the token and save

  • Put the id for the user to be impersonated

  • Success message if the user is impersonable

  • Failure message if the user is not impersonable (Here instructor is trying to impersonate admin)

Team

Mentor

  • Chetana Chunduru <cchetan2@ncsu.edu>

Students

  • Devansh Shah <dshah8@ncsu.edu>
  • Jay Patel <jhpatel9@ncsu.edu>
  • Mihir Bhanderi <mbhande2@ncsu.edu>