<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mayyapp</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mayyapp"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Mayyapp"/>
	<updated>2026-05-18T06:21:20Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152485</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152485"/>
		<updated>2023-12-05T02:49:08Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Pull Request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We have converted the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. We have reimplemented the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertiza can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
&lt;br /&gt;
This is not the only file that we have edited. We also needed to edit users.rb file to add some functionality regarding the impersonation criteria. We have used JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code works work to change the current user as and when necessary in the API. We also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We have also ensured that we have the supporting methods in the User class implemented. One such example of a method that we have reimplemented is the “can_impersonate?” method within the User class.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  def check_if_input_is_valid&lt;br /&gt;
    if params[:impersonate].blank? || warn_for_special_chars(params[:impersonate], 'Username')&lt;br /&gt;
      # render json: { success: false, error: 'Please enter valid user name' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  def warn_for_special_chars(str, field_name)&lt;br /&gt;
    puts str&lt;br /&gt;
    if contains_special_chars? str&lt;br /&gt;
      render json: { success: false, error: field_name + &amp;quot; must not contain special characters '&amp;quot; + special_chars + &amp;quot;'.&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
      return true&lt;br /&gt;
    end&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def contains_special_chars?(str)&lt;br /&gt;
    special = special_chars&lt;br /&gt;
    regex = /[#{Regexp.escape(special)}]/&lt;br /&gt;
    !str.match(regex).nil?&lt;br /&gt;
  end&lt;br /&gt;
    def special_chars&lt;br /&gt;
      '/\\?&amp;lt;&amp;gt;|&amp;amp;$#'&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This new method checks and warns about special characters used in the input. The special characters it checks for are /\\?&amp;lt;&amp;gt;|&amp;amp;$#&lt;br /&gt;
&lt;br /&gt;
 '''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We changed the session to a JWT token in this method.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&amp;lt;pre&amp;gt; def check_if_user_impersonatable?&lt;br /&gt;
      user = User.find_by(name: params[:impersonate] )&lt;br /&gt;
      if user&lt;br /&gt;
        return @current_user.can_impersonate? user&lt;br /&gt;
      end&lt;br /&gt;
      false&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original''' &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Modified code using JWT tokens&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
      if check_if_user_impersonatable?&lt;br /&gt;
        user = User.find_by(name: params[:impersonate])&lt;br /&gt;
&lt;br /&gt;
        if user&lt;br /&gt;
          impersonate_payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name,&lt;br /&gt;
                          institution_id: user.institution.id, impersonate: true, original_user: @current_user }&lt;br /&gt;
          impersonate_token = JsonWebToken.encode(impersonate_payload, 24.hours.from_now)&lt;br /&gt;
  &lt;br /&gt;
          render json: { success: true, token: impersonate_token, message: &amp;quot;Successfully impersonated #{user.name}&amp;quot; }&lt;br /&gt;
        else&lt;br /&gt;
          render json: { success: false, error: 'User not found' }, status: :not_found&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        render json: { success: false, error: &amp;quot;You don't have permission to impersonate this user&amp;quot; }, status: :forbidden&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
In order to check if the user can be impersonated, we delegate it to the user class. The user class now handles this part of checking&lt;br /&gt;
&lt;br /&gt;
'''Modified code in user.rb'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_administrator?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless ta?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    ta.managed_users.each { |user|&lt;br /&gt;
      if user.id == student.id&lt;br /&gt;
        return true&lt;br /&gt;
      end&lt;br /&gt;
    }&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_administrator?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
'''IMPORTANT'''&lt;br /&gt;
We believe that this project is a mix of frontend and backend. So the assumption we have made is that when a user wants to impersonate any other user, the JWT token for the current user is stored in the frontend. And when the 'session' for impersonation is over, the user is assigned their previous JWT token retrieved from the frontend.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we first tested all functionality using the Postman API. &lt;br /&gt;
&lt;br /&gt;
We test by creating tokens for each user logged in and check if the logged in user (current user) can impersonate any other user or not. &lt;br /&gt;
We also check if adding special characters in the URL lets us impersonate other users or throws an appropriate error.&lt;br /&gt;
&lt;br /&gt;
The working of the Postman testing is included in the vidoe link below. &lt;br /&gt;
&lt;br /&gt;
Later we moved on to testing our program using the RSwag tool. This allowed us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods - https://drive.google.com/file/d/19BTXHedw4iUgbIQf8c5cWdKpnnNUVm6k/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;br /&gt;
&lt;br /&gt;
Link - https://github.com/expertiza/reimplementation-back-end/pull/68&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152484</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152484"/>
		<updated>2023-12-05T02:46:43Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We have converted the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. We have reimplemented the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertiza can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
&lt;br /&gt;
This is not the only file that we have edited. We also needed to edit users.rb file to add some functionality regarding the impersonation criteria. We have used JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code works work to change the current user as and when necessary in the API. We also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We have also ensured that we have the supporting methods in the User class implemented. One such example of a method that we have reimplemented is the “can_impersonate?” method within the User class.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  def check_if_input_is_valid&lt;br /&gt;
    if params[:impersonate].blank? || warn_for_special_chars(params[:impersonate], 'Username')&lt;br /&gt;
      # render json: { success: false, error: 'Please enter valid user name' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  def warn_for_special_chars(str, field_name)&lt;br /&gt;
    puts str&lt;br /&gt;
    if contains_special_chars? str&lt;br /&gt;
      render json: { success: false, error: field_name + &amp;quot; must not contain special characters '&amp;quot; + special_chars + &amp;quot;'.&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
      return true&lt;br /&gt;
    end&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def contains_special_chars?(str)&lt;br /&gt;
    special = special_chars&lt;br /&gt;
    regex = /[#{Regexp.escape(special)}]/&lt;br /&gt;
    !str.match(regex).nil?&lt;br /&gt;
  end&lt;br /&gt;
    def special_chars&lt;br /&gt;
      '/\\?&amp;lt;&amp;gt;|&amp;amp;$#'&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This new method checks and warns about special characters used in the input. The special characters it checks for are /\\?&amp;lt;&amp;gt;|&amp;amp;$#&lt;br /&gt;
&lt;br /&gt;
 '''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We changed the session to a JWT token in this method.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&amp;lt;pre&amp;gt; def check_if_user_impersonatable?&lt;br /&gt;
      user = User.find_by(name: params[:impersonate] )&lt;br /&gt;
      if user&lt;br /&gt;
        return @current_user.can_impersonate? user&lt;br /&gt;
      end&lt;br /&gt;
      false&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original''' &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Modified code using JWT tokens&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
      if check_if_user_impersonatable?&lt;br /&gt;
        user = User.find_by(name: params[:impersonate])&lt;br /&gt;
&lt;br /&gt;
        if user&lt;br /&gt;
          impersonate_payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name,&lt;br /&gt;
                          institution_id: user.institution.id, impersonate: true, original_user: @current_user }&lt;br /&gt;
          impersonate_token = JsonWebToken.encode(impersonate_payload, 24.hours.from_now)&lt;br /&gt;
  &lt;br /&gt;
          render json: { success: true, token: impersonate_token, message: &amp;quot;Successfully impersonated #{user.name}&amp;quot; }&lt;br /&gt;
        else&lt;br /&gt;
          render json: { success: false, error: 'User not found' }, status: :not_found&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        render json: { success: false, error: &amp;quot;You don't have permission to impersonate this user&amp;quot; }, status: :forbidden&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
In order to check if the user can be impersonated, we delegate it to the user class. The user class now handles this part of checking&lt;br /&gt;
&lt;br /&gt;
'''Modified code in user.rb'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_administrator?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless ta?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    ta.managed_users.each { |user|&lt;br /&gt;
      if user.id == student.id&lt;br /&gt;
        return true&lt;br /&gt;
      end&lt;br /&gt;
    }&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_administrator?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
'''IMPORTANT'''&lt;br /&gt;
We believe that this project is a mix of frontend and backend. So the assumption we have made is that when a user wants to impersonate any other user, the JWT token for the current user is stored in the frontend. And when the 'session' for impersonation is over, the user is assigned their previous JWT token retrieved from the frontend.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we first tested all functionality using the Postman API. &lt;br /&gt;
&lt;br /&gt;
We test by creating tokens for each user logged in and check if the logged in user (current user) can impersonate any other user or not. &lt;br /&gt;
We also check if adding special characters in the URL lets us impersonate other users or throws an appropriate error.&lt;br /&gt;
&lt;br /&gt;
The working of the Postman testing is included in the vidoe link below. &lt;br /&gt;
&lt;br /&gt;
Later we moved on to testing our program using the RSwag tool. This allowed us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods - https://drive.google.com/file/d/19BTXHedw4iUgbIQf8c5cWdKpnnNUVm6k/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152480</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152480"/>
		<updated>2023-12-05T02:43:33Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We have converted the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. We have reimplemented the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertiza can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
&lt;br /&gt;
This is not the only file that we have edited. We also needed to edit users.rb file to add some functionality regarding the impersonation criteria. We have used JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code works work to change the current user as and when necessary in the API. We also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We have also ensured that we have the supporting methods in the User class implemented. One such example of a method that we have reimplemented is the “can_impersonate?” method within the User class.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  def check_if_input_is_valid&lt;br /&gt;
    if params[:impersonate].blank? || warn_for_special_chars(params[:impersonate], 'Username')&lt;br /&gt;
      # render json: { success: false, error: 'Please enter valid user name' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  def warn_for_special_chars(str, field_name)&lt;br /&gt;
    puts str&lt;br /&gt;
    if contains_special_chars? str&lt;br /&gt;
      render json: { success: false, error: field_name + &amp;quot; must not contain special characters '&amp;quot; + special_chars + &amp;quot;'.&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
      return true&lt;br /&gt;
    end&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def contains_special_chars?(str)&lt;br /&gt;
    special = special_chars&lt;br /&gt;
    regex = /[#{Regexp.escape(special)}]/&lt;br /&gt;
    !str.match(regex).nil?&lt;br /&gt;
  end&lt;br /&gt;
    def special_chars&lt;br /&gt;
      '/\\?&amp;lt;&amp;gt;|&amp;amp;$#'&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This new method checks and warns about special characters used in the input. The special characters it checks for are /\\?&amp;lt;&amp;gt;|&amp;amp;$#&lt;br /&gt;
&lt;br /&gt;
 '''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We changed the session to a JWT token in this method.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&amp;lt;pre&amp;gt; def check_if_user_impersonatable?&lt;br /&gt;
      user = User.find_by(name: params[:impersonate] )&lt;br /&gt;
      if user&lt;br /&gt;
        return @current_user.can_impersonate? user&lt;br /&gt;
      end&lt;br /&gt;
      false&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original''' &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Modified code using JWT tokens&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
      if check_if_user_impersonatable?&lt;br /&gt;
        user = User.find_by(name: params[:impersonate])&lt;br /&gt;
&lt;br /&gt;
        if user&lt;br /&gt;
          impersonate_payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name,&lt;br /&gt;
                          institution_id: user.institution.id, impersonate: true, original_user: @current_user }&lt;br /&gt;
          impersonate_token = JsonWebToken.encode(impersonate_payload, 24.hours.from_now)&lt;br /&gt;
  &lt;br /&gt;
          render json: { success: true, token: impersonate_token, message: &amp;quot;Successfully impersonated #{user.name}&amp;quot; }&lt;br /&gt;
        else&lt;br /&gt;
          render json: { success: false, error: 'User not found' }, status: :not_found&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        render json: { success: false, error: &amp;quot;You don't have permission to impersonate this user&amp;quot; }, status: :forbidden&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
In order to check if the user can be impersonated, we delegate it to the user class. The user class now handles this part of checking&lt;br /&gt;
&lt;br /&gt;
'''Modified code in user.rb'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_administrator?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless ta?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    ta.managed_users.each { |user|&lt;br /&gt;
      if user.id == student.id&lt;br /&gt;
        return true&lt;br /&gt;
      end&lt;br /&gt;
    }&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_administrator?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
'''IMPORTANT'''&lt;br /&gt;
We believe that this project is a mix of frontend and backend. So the assumption we have made is that when a user wants to impersonate any other user, the JWT token for the current user is stored in the frontend. And when the 'session' for impersonation is over, the user is assigned their previous JWT token retrieved from the frontend.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we first tested all functionality using the Postman API. The working of the Postman testing is included in the vidoe link below. We then tested our program using the RSwag tool. This allowed us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods - https://drive.google.com/file/d/19BTXHedw4iUgbIQf8c5cWdKpnnNUVm6k/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152466</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152466"/>
		<updated>2023-12-05T02:30:30Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We have converted the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. We have reimplemented the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertiza can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
&lt;br /&gt;
This is not the only file that we have edited. We also needed to edit users.rb file to add some functionality regarding the impersonation criteria. We have used JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code works work to change the current user as and when necessary in the API. We also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We have also ensured that we have the supporting methods in the User class implemented. One such example of a method that we have reimplemented is the “can_impersonate?” method within the User class.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  def check_if_input_is_valid&lt;br /&gt;
    if params[:impersonate].blank? || warn_for_special_chars(params[:impersonate], 'Username')&lt;br /&gt;
      # render json: { success: false, error: 'Please enter valid user name' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  def warn_for_special_chars(str, field_name)&lt;br /&gt;
    puts str&lt;br /&gt;
    if contains_special_chars? str&lt;br /&gt;
      render json: { success: false, error: field_name + &amp;quot; must not contain special characters '&amp;quot; + special_chars + &amp;quot;'.&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
      return true&lt;br /&gt;
    end&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def contains_special_chars?(str)&lt;br /&gt;
    special = special_chars&lt;br /&gt;
    regex = /[#{Regexp.escape(special)}]/&lt;br /&gt;
    !str.match(regex).nil?&lt;br /&gt;
  end&lt;br /&gt;
    def special_chars&lt;br /&gt;
      '/\\?&amp;lt;&amp;gt;|&amp;amp;$#'&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This new method checks and warns about special characters used in the input. The special characters it checks for are /\\?&amp;lt;&amp;gt;|&amp;amp;$#&lt;br /&gt;
&lt;br /&gt;
 '''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We changed the session to a JWT token in this method.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&amp;lt;pre&amp;gt; def check_if_user_impersonatable?&lt;br /&gt;
      user = User.find_by(name: params[:impersonate] )&lt;br /&gt;
      if user&lt;br /&gt;
        return @current_user.can_impersonate? user&lt;br /&gt;
      end&lt;br /&gt;
      false&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original''' &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Modified code using JWT tokens&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
      if check_if_user_impersonatable?&lt;br /&gt;
        user = User.find_by(name: params[:impersonate])&lt;br /&gt;
&lt;br /&gt;
        if user&lt;br /&gt;
          impersonate_payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name,&lt;br /&gt;
                          institution_id: user.institution.id, impersonate: true, original_user: @current_user }&lt;br /&gt;
          impersonate_token = JsonWebToken.encode(impersonate_payload, 24.hours.from_now)&lt;br /&gt;
  &lt;br /&gt;
          render json: { success: true, token: impersonate_token, message: &amp;quot;Successfully impersonated #{user.name}&amp;quot; }&lt;br /&gt;
        else&lt;br /&gt;
          render json: { success: false, error: 'User not found' }, status: :not_found&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        render json: { success: false, error: &amp;quot;You don't have permission to impersonate this user&amp;quot; }, status: :forbidden&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
In order to check if the user can be impersonated, we delegate it to the user class. The user class now handles this part of checking&lt;br /&gt;
&lt;br /&gt;
'''Modified code in user.rb'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_administrator?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless ta?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    ta.managed_users.each { |user|&lt;br /&gt;
      if user.id == student.id&lt;br /&gt;
        return true&lt;br /&gt;
      end&lt;br /&gt;
    }&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_administrator?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
'''IMPORTANT'''&lt;br /&gt;
We believe that this project is a mix of frontend and backend. So the assumption we have made is that when a user wants to impersonate any other user, the JWT token for the current user is stored in the frontend. And when the 'session' for impersonation is over, the user is assigned their previous JWT token retrieved from the frontend.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we first tested all functionality using the Postman API. The working of the Postman testing video will be posted here in some time. We then tested our program using the RSwag tool. This allowed us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here soon.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152465</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152465"/>
		<updated>2023-12-05T02:30:14Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We have converted the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. We have reimplemented the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertiza can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we have edited. We also needed to edit users.rb file to add some functionality regarding the impersonation criteria. We have used JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code works work to change the current user as and when necessary in the API. We also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We have also ensured that we have the supporting methods in the User class implemented. One such example of a method that we have reimplemented is the “can_impersonate?” method within the User class.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  def check_if_input_is_valid&lt;br /&gt;
    if params[:impersonate].blank? || warn_for_special_chars(params[:impersonate], 'Username')&lt;br /&gt;
      # render json: { success: false, error: 'Please enter valid user name' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  def warn_for_special_chars(str, field_name)&lt;br /&gt;
    puts str&lt;br /&gt;
    if contains_special_chars? str&lt;br /&gt;
      render json: { success: false, error: field_name + &amp;quot; must not contain special characters '&amp;quot; + special_chars + &amp;quot;'.&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
      return true&lt;br /&gt;
    end&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def contains_special_chars?(str)&lt;br /&gt;
    special = special_chars&lt;br /&gt;
    regex = /[#{Regexp.escape(special)}]/&lt;br /&gt;
    !str.match(regex).nil?&lt;br /&gt;
  end&lt;br /&gt;
    def special_chars&lt;br /&gt;
      '/\\?&amp;lt;&amp;gt;|&amp;amp;$#'&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This new method checks and warns about special characters used in the input. The special characters it checks for are /\\?&amp;lt;&amp;gt;|&amp;amp;$#&lt;br /&gt;
&lt;br /&gt;
 '''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We changed the session to a JWT token in this method.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&amp;lt;pre&amp;gt; def check_if_user_impersonatable?&lt;br /&gt;
      user = User.find_by(name: params[:impersonate] )&lt;br /&gt;
      if user&lt;br /&gt;
        return @current_user.can_impersonate? user&lt;br /&gt;
      end&lt;br /&gt;
      false&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original''' &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Modified code using JWT tokens&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
      if check_if_user_impersonatable?&lt;br /&gt;
        user = User.find_by(name: params[:impersonate])&lt;br /&gt;
&lt;br /&gt;
        if user&lt;br /&gt;
          impersonate_payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name,&lt;br /&gt;
                          institution_id: user.institution.id, impersonate: true, original_user: @current_user }&lt;br /&gt;
          impersonate_token = JsonWebToken.encode(impersonate_payload, 24.hours.from_now)&lt;br /&gt;
  &lt;br /&gt;
          render json: { success: true, token: impersonate_token, message: &amp;quot;Successfully impersonated #{user.name}&amp;quot; }&lt;br /&gt;
        else&lt;br /&gt;
          render json: { success: false, error: 'User not found' }, status: :not_found&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        render json: { success: false, error: &amp;quot;You don't have permission to impersonate this user&amp;quot; }, status: :forbidden&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
In order to check if the user can be impersonated, we delegate it to the user class. The user class now handles this part of checking&lt;br /&gt;
&lt;br /&gt;
'''Modified code in user.rb'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_administrator?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless ta?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    ta.managed_users.each { |user|&lt;br /&gt;
      if user.id == student.id&lt;br /&gt;
        return true&lt;br /&gt;
      end&lt;br /&gt;
    }&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_administrator?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
'''IMPORTANT'''&lt;br /&gt;
We believe that this project is a mix of frontend and backend. So the assumption we have made is that when a user wants to impersonate any other user, the JWT token for the current user is stored in the frontend. And when the 'session' for impersonation is over, the user is assigned their previous JWT token retrieved from the frontend.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we first tested all functionality using the Postman API. The working of the Postman testing video will be posted here in some time. We then tested our program using the RSwag tool. This allowed us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here soon.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152344</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152344"/>
		<updated>2023-12-04T20:25:04Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  def check_if_input_is_valid&lt;br /&gt;
    if params[:impersonate].blank? || warn_for_special_chars(params[:impersonate], 'Username')&lt;br /&gt;
      # render json: { success: false, error: 'Please enter valid user name' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  def warn_for_special_chars(str, field_name)&lt;br /&gt;
    puts str&lt;br /&gt;
    if contains_special_chars? str&lt;br /&gt;
      render json: { success: false, error: field_name + &amp;quot; must not contain special characters '&amp;quot; + special_chars + &amp;quot;'.&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
      return true&lt;br /&gt;
    end&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def contains_special_chars?(str)&lt;br /&gt;
    special = special_chars&lt;br /&gt;
    regex = /[#{Regexp.escape(special)}]/&lt;br /&gt;
    !str.match(regex).nil?&lt;br /&gt;
  end&lt;br /&gt;
    def special_chars&lt;br /&gt;
      '/\\?&amp;lt;&amp;gt;|&amp;amp;$#'&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This new method checks and warns about special characters used in the input. The special characters it checks for are /\\?&amp;lt;&amp;gt;|&amp;amp;$#&lt;br /&gt;
&lt;br /&gt;
 '''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We changed the session to a JWT token in this method.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&amp;lt;pre&amp;gt; def check_if_user_impersonatable?&lt;br /&gt;
      user = User.find_by(name: params[:impersonate] )&lt;br /&gt;
      if user&lt;br /&gt;
        return @current_user.can_impersonate? user&lt;br /&gt;
      end&lt;br /&gt;
      false&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original''' &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Modified code using JWT tokens&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
      if check_if_user_impersonatable?&lt;br /&gt;
        user = User.find_by(name: params[:impersonate])&lt;br /&gt;
&lt;br /&gt;
        if user&lt;br /&gt;
          impersonate_payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name,&lt;br /&gt;
                          institution_id: user.institution.id, impersonate: true, original_user: @current_user }&lt;br /&gt;
          impersonate_token = JsonWebToken.encode(impersonate_payload, 24.hours.from_now)&lt;br /&gt;
  &lt;br /&gt;
          render json: { success: true, token: impersonate_token, message: &amp;quot;Successfully impersonated #{user.name}&amp;quot; }&lt;br /&gt;
        else&lt;br /&gt;
          render json: { success: false, error: 'User not found' }, status: :not_found&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        render json: { success: false, error: &amp;quot;You don't have permission to impersonate this user&amp;quot; }, status: :forbidden&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
In order to check if the user can be impersonated, we delegate it to the user class. The user class now handles this part of checking&lt;br /&gt;
&lt;br /&gt;
'''Modified code in user.rb'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_administrator?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless ta?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    ta.managed_users.each { |user|&lt;br /&gt;
      if user.id == student.id&lt;br /&gt;
        return true&lt;br /&gt;
      end&lt;br /&gt;
    }&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_administrator?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
'''IMPORTANT'''&lt;br /&gt;
We believe that this project is a mix of frontend and backend. So the assumption we have made is that when a user wants to impersonate any other user, the JWT token for the current user is stored in the frontend. And when the 'session' for impersonation is over, the user is assigned their previous JWT token retrieved from the frontend.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we first tested all functionality using the Postman API. The working of the Postman testing video will be posted here in some time. We then tested our program using the RSwag tool. This allowed us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here soon.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152280</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152280"/>
		<updated>2023-12-04T16:34:36Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Methods Reimplemented */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  def check_if_input_is_valid&lt;br /&gt;
    if params[:impersonate].blank? || warn_for_special_chars(params[:impersonate], 'Username')&lt;br /&gt;
      # render json: { success: false, error: 'Please enter valid user name' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  def warn_for_special_chars(str, field_name)&lt;br /&gt;
    puts str&lt;br /&gt;
    if contains_special_chars? str&lt;br /&gt;
      render json: { success: false, error: field_name + &amp;quot; must not contain special characters '&amp;quot; + special_chars + &amp;quot;'.&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
      return true&lt;br /&gt;
    end&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def contains_special_chars?(str)&lt;br /&gt;
    special = special_chars&lt;br /&gt;
    regex = /[#{Regexp.escape(special)}]/&lt;br /&gt;
    !str.match(regex).nil?&lt;br /&gt;
  end&lt;br /&gt;
    def special_chars&lt;br /&gt;
      '/\\?&amp;lt;&amp;gt;|&amp;amp;$#'&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
This new method checks and warns about special characters used in the input. The special characters it checks for are /\\?&amp;lt;&amp;gt;|&amp;amp;$#&lt;br /&gt;
&lt;br /&gt;
 '''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
We changed the session to a JWT token in this method.&lt;br /&gt;
&lt;br /&gt;
'''Modified code'''&lt;br /&gt;
&amp;lt;pre&amp;gt; def check_if_user_impersonatable?&lt;br /&gt;
      user = User.find_by(name: params[:impersonate] )&lt;br /&gt;
      if user&lt;br /&gt;
        return @current_user.can_impersonate? user&lt;br /&gt;
      end&lt;br /&gt;
      false&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Original''' &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
Modified code using JWT tokens&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
      if check_if_user_impersonatable?&lt;br /&gt;
        user = User.find_by(name: params[:impersonate])&lt;br /&gt;
&lt;br /&gt;
        if user&lt;br /&gt;
          impersonate_payload = { id: user.id, name: user.name, full_name: user.full_name, role: user.role.name,&lt;br /&gt;
                          institution_id: user.institution.id, impersonate: true, original_user: @current_user }&lt;br /&gt;
          impersonate_token = JsonWebToken.encode(impersonate_payload, 24.hours.from_now)&lt;br /&gt;
  &lt;br /&gt;
          render json: { success: true, token: impersonate_token, message: &amp;quot;Successfully impersonated #{user.name}&amp;quot; }&lt;br /&gt;
        else&lt;br /&gt;
          render json: { success: false, error: 'User not found' }, status: :not_found&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        render json: { success: false, error: &amp;quot;You don't have permission to impersonate this user&amp;quot; }, status: :forbidden&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
In order to check if the user can be impersonated, we delegate it to the user class. The user class now handles this part of checking&lt;br /&gt;
&lt;br /&gt;
'''Modified code in user.rb'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_administrator?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless ta?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    ta.managed_users.each { |user|&lt;br /&gt;
      if user.id == student.id&lt;br /&gt;
        return true&lt;br /&gt;
      end&lt;br /&gt;
    }&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_administrator?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original'''&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Modification''' :&lt;br /&gt;
'''IMPORTANT'''&lt;br /&gt;
We believe that this project is a mix of frontend and backend. So the assumption we have made is that when a user wants to impersonate any other user, the JWT token for the current user is stored in the frontend. And when the 'session' for impersonation is over, the user is assigned their previous JWT token retrieved from the frontend.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152147</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152147"/>
		<updated>2023-12-04T03:29:05Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Methods Reimplemented */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Update&lt;br /&gt;
We have removed the session and stored the user with a JWT token to authenticate. So this method is no longer required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Update&lt;br /&gt;
&lt;br /&gt;
Instead of using session we just access the current user, and since this is a frontend task we decided to not keep it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
We removed the flash error as it will not work in the our new implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
This method is now called inside the 'impersonate' method using JWT token&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
We got rid of this method as we now authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
We have changed the number of parameters for this method. Instead of two, this method now only takes one parameter which is the username of the user we wish to impersonate. We also have removed the flash errors.&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
Original &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_admin?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_admin?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless teaching_assistant?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    return true if ta.courses_assisted_with.any? do |c|&lt;br /&gt;
      c.assignments.map(&amp;amp;:participants).flatten.map(&amp;amp;:user_id).include? student.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152116</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152116"/>
		<updated>2023-12-04T00:01:52Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_diagram_E2377.png|900px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
Original &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_admin?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_admin?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless teaching_assistant?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    return true if ta.courses_assisted_with.any? do |c|&lt;br /&gt;
      c.assignments.map(&amp;amp;:participants).flatten.map(&amp;amp;:user_id).include? student.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:UML_diagram_E2377.png&amp;diff=152114</id>
		<title>File:UML diagram E2377.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:UML_diagram_E2377.png&amp;diff=152114"/>
		<updated>2023-12-03T23:58:36Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: Mayyapp uploaded a new version of File:UML diagram E2377.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152113</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152113"/>
		<updated>2023-12-03T23:58:18Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
UML Diagram&lt;br /&gt;
[[File:UML_diagram_E2377.png|700px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
Original &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_admin?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_admin?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless teaching_assistant?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    return true if ta.courses_assisted_with.any? do |c|&lt;br /&gt;
      c.assignments.map(&amp;amp;:participants).flatten.map(&amp;amp;:user_id).include? student.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:UML_diagram_E2377.png&amp;diff=152110</id>
		<title>File:UML diagram E2377.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:UML_diagram_E2377.png&amp;diff=152110"/>
		<updated>2023-12-03T23:54:51Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152099</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=152099"/>
		<updated>2023-12-03T23:40:43Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
UML Diagram&lt;br /&gt;
[[File:UML_E2377.jpeg|600px|UML Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Hierarchy_diagram_E2377.png|500px|hierarchy_diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
Original &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_admin?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_admin?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless teaching_assistant?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    return true if ta.courses_assisted_with.any? do |c|&lt;br /&gt;
      c.assignments.map(&amp;amp;:participants).flatten.map(&amp;amp;:user_id).include? student.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Hierarchy_diagram_E2377.png&amp;diff=152095</id>
		<title>File:Hierarchy diagram E2377.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Hierarchy_diagram_E2377.png&amp;diff=152095"/>
		<updated>2023-12-03T23:38:18Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151360</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151360"/>
		<updated>2023-11-14T22:47:00Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Methods Reimplemented */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_E2377.jpeg|600px|UML Diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
Original &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_admin?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def recursively_parent_of(user)&lt;br /&gt;
    p = user.parent&lt;br /&gt;
    return false if p.nil?&lt;br /&gt;
    return true if p == self&lt;br /&gt;
    return false if p.role.super_admin?&lt;br /&gt;
&lt;br /&gt;
    recursively_parent_of(p)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def teaching_assistant_for?(student)&lt;br /&gt;
    return false unless teaching_assistant?&lt;br /&gt;
    return false unless student.role.name == 'Student'&lt;br /&gt;
&lt;br /&gt;
    # We have to use the Ta object instead of User object&lt;br /&gt;
    # because single table inheritance is not currently functioning&lt;br /&gt;
    ta = Ta.find(id)&lt;br /&gt;
    return true if ta.courses_assisted_with.any? do |c|&lt;br /&gt;
      c.assignments.map(&amp;amp;:participants).flatten.map(&amp;amp;:user_id).include? student.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151358</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151358"/>
		<updated>2023-11-14T22:44:10Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
[[File:UML_E2377.jpeg|600px|UML Diagram]]&lt;br /&gt;
&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
Original &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_admin?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:UML_E2377.jpeg&amp;diff=151357</id>
		<title>File:UML E2377.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:UML_E2377.jpeg&amp;diff=151357"/>
		<updated>2023-11-14T22:41:36Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151354</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151354"/>
		<updated>2023-11-14T22:29:42Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Methods Reimplemented */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
We plan to convert the impersonate users functionality from the MVC pattern in Expertiza to match the Rails API specification for the reimplementation backend repository. To do this we will reimplement the impersonate_controller.rb file located within expertiza/app/controllers/. The link to the original controller within expertizsa can be found at this link: [https://github.com/expertiza/expertiza/blob/main/app/controllers/impersonate_controller.rb Original Controller] &lt;br /&gt;
This is not the only file that we will be editing. We will be using JWT Tokens for authentication. The front end will still be responsible for storing the original user to get the original user back in function. Our code will work to change the current user as and when necessary in the API. Will also ensure that user privileges are checked to authorize only the relevant users to impersonate student users. Users that are super admin, TAs for other users or recursively parents of the user they are trying to impersonate can impersonate the user. &lt;br /&gt;
We will also ensure that we have the supporting methods in the User class are implemented. One such example of a method that we may need to reimplement is “can_impersonate?” within the User class. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
Original &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def can_impersonate?(user)&lt;br /&gt;
    return true if role.super_admin?&lt;br /&gt;
    return true if teaching_assistant_for?(user)&lt;br /&gt;
    return true if recursively_parent_of(user)&lt;br /&gt;
&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-- We will reimplement these methods to work with our JWT based authentication system&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151350</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151350"/>
		<updated>2023-11-14T22:15:00Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
== Design ==&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Original &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests. &amp;lt;br&amp;gt;&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151348</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151348"/>
		<updated>2023-11-14T22:14:47Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
== Design ==&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def action_allowed?&lt;br /&gt;
    # Check for TA privileges first since TA's also have student privileges.&lt;br /&gt;
    if ['Student'].include? current_role_name&lt;br /&gt;
      !session[:super_user].nil?&lt;br /&gt;
    else&lt;br /&gt;
      ['Super-Administrator',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Instructor',&lt;br /&gt;
       'Teaching Assistant'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
-- we will remove the session and store the user with a JWT token to authenticate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def auto_complete_for_user_name&lt;br /&gt;
    @users = session[:user].get_available_users(params[:user][:name])&lt;br /&gt;
    render inline: &amp;quot;&amp;lt;%= auto_complete_result @users, 'name' %&amp;gt;&amp;quot;, layout: false&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
&lt;br /&gt;
--instead of using session we will just access the current user&lt;br /&gt;
-- we will remove the inline rendering and return a JSON instead&lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
  def start&lt;br /&gt;
    flash[:error] = &amp;quot;This page doesn't take any query string.&amp;quot; unless request.GET.empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--we will remove the flash error as it will not work in the new implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
 &amp;lt;pre&amp;gt; def generate_session(user)&lt;br /&gt;
    AuthController.clear_user_info(session, nil)&lt;br /&gt;
    session[:original_user] = @original_user&lt;br /&gt;
    session[:impersonate] = true&lt;br /&gt;
    session[:user] = user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- We will not be using sessions so we will be using JWT tokens to authenticate users instead of making a traditional session&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def overwrite_session&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      session[:super_user] = session[:user] if session[:super_user].nil?&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    elsif !params[:impersonate][:name].empty?&lt;br /&gt;
      user = real_user(params[:impersonate][:name])&lt;br /&gt;
      generate_session(user)&lt;br /&gt;
    else&lt;br /&gt;
      session[:user] = session[:super_user]&lt;br /&gt;
      session[:super_user] = nil&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated&lt;br /&gt;
--instead, we will just update the current User but we will authenticate the user with a JWT token instead. &lt;br /&gt;
&lt;br /&gt;
Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_input_is_valid&lt;br /&gt;
    if params[:user] &amp;amp;&amp;amp; warn_for_special_chars(params[:user][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    elsif params[:impersonate] &amp;amp;&amp;amp; warn_for_special_chars(params[:impersonate][:name], 'Username')&lt;br /&gt;
      flash[:error] = 'Please enter valid user name'&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- in this method we will remove the flash errors&lt;br /&gt;
&lt;br /&gt;
 Original&lt;br /&gt;
  &amp;lt;pre&amp;gt;def check_if_user_impersonateable&lt;br /&gt;
    if params[:impersonate].nil?&lt;br /&gt;
      user = real_user(params[:user][:name])&lt;br /&gt;
      unless @original_user.can_impersonate? user&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        temp&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
      else&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      unless params[:impersonate][:name].empty?&lt;br /&gt;
        overwrite_session&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
Updated:&lt;br /&gt;
&lt;br /&gt;
--we will change the session to a JWT token in this method&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;pre&amp;gt;&lt;br /&gt;
def impersonate&lt;br /&gt;
    begin&lt;br /&gt;
      @original_user = session[:super_user] || session[:user]&lt;br /&gt;
      if params[:impersonate].nil?&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:user][:name]}'.&amp;quot;&lt;br /&gt;
        @message = 'User name cannot be empty' if params[:user][:name].empty?&lt;br /&gt;
        user = real_user(params[:user][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      elsif !params[:impersonate][:name].empty?&lt;br /&gt;
        # Impersonate a new account&lt;br /&gt;
        @message = &amp;quot;You cannot impersonate '#{params[:impersonate][:name]}'.&amp;quot;&lt;br /&gt;
        user = real_user(params[:impersonate][:name])&lt;br /&gt;
        check_if_user_impersonateable if user&lt;br /&gt;
      # Revert to original account when currently in the impersonated session&lt;br /&gt;
      elsif !session[:super_user].nil?&lt;br /&gt;
        AuthController.clear_user_info(session, nil)&lt;br /&gt;
        session[:user] = session[:super_user]&lt;br /&gt;
        user = session[:user]&lt;br /&gt;
        session[:super_user] = nil&lt;br /&gt;
      end&lt;br /&gt;
      # Navigate to user's home location as the default landing page after impersonating or reverting&lt;br /&gt;
      AuthController.set_current_role(user.role_id, session)&lt;br /&gt;
      redirect_to action: AuthHelper.get_home_action(session[:user]),&lt;br /&gt;
                  controller: AuthHelper.get_home_controller(session[:user])&lt;br /&gt;
    rescue StandardError&lt;br /&gt;
      flash[:error] = @message&lt;br /&gt;
      redirect_back fallback_location: root_path&lt;br /&gt;
    end&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will change the session to a JWT token and flash message from this method. &lt;br /&gt;
&lt;br /&gt;
Original:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;pre&amp;gt;def real_user(name)&lt;br /&gt;
    if User.anonymized_view?(session[:ip])&lt;br /&gt;
      user = User.real_user_from_anonymized_name(name)&lt;br /&gt;
    else&lt;br /&gt;
      user = User.find_by(name: name)&lt;br /&gt;
    end&lt;br /&gt;
    return user&lt;br /&gt;
  end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Updated:&lt;br /&gt;
-- we will implement a JWT token instead of using a session here&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
For the testing of this project, we will first test all functionality using the Postman API. If everything works as expected, we will then start testing our program using the RSwag tool. This will allow us to test and explore operations using a UI and directly from the rspec integration tests.&lt;br /&gt;
The video links for these testing methods will be posted here when we complete it.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151341</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151341"/>
		<updated>2023-11-14T22:04:26Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: /* Problem Statement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
The current expertiza platform allows authorized users to impersonate others, utilizing session-based authentication. The challenge is to reimplement this feature in the new expertiza backend (https://github.com/expertiza/reimplementation-back-end), which employs JWT token authentication.&lt;br /&gt;
&lt;br /&gt;
Key challenges include adapting the existing session-based logic to work seamlessly with JWT tokens and transitioning from a Model-View-Controller (MVC) architecture to an API-only setup, requiring responses in JSON format. The goal is to ensure the smooth integration of the impersonation feature into the new backend while addressing authentication changes and architectural shifts.&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
== Design ==&lt;br /&gt;
== Methods Reimplemented ==&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151330</id>
		<title>CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate controller.rb)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2377._Reimplement_impersonating_users_(functionality_within_impersonate_controller.rb)&amp;diff=151330"/>
		<updated>2023-11-14T20:33:38Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: Created page with &amp;quot;==Expertiza==  [http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects,...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=151329</id>
		<title>CSC/ECE 517 Fall 2023</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=151329"/>
		<updated>2023-11-14T20:30:58Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[CSC/ECE 517 Fall 2023 - E2350. Allow reviewers to bid on what to review]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2351. Finish mentor management for assignments without topics]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2352. Fix &amp;quot;Back&amp;quot; link on “New Late Policy” page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2353. Further refactoring and improvement of review mapping helper]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2355. Improving Search Facility In Expertiza]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2356. Refactor review_mapping_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2357. Refactor sign_up_sheet_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2358. Refactor student_quizzes_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2359. Refactor user_controller.rb, user.rb, and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2360. View for Results of Bidding]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2361. Create a page to create and update a Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2362. Create a page to edit an Assignment's due date in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2363. Create a UI for Assignment Edit page &amp;quot;Etc&amp;quot; tab in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2364. Create a UI for Course's &amp;amp; Assignment's &amp;quot;Add Participants&amp;quot; page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2365. Create a user interface for Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2367. Reimplement participants_controller.rb, participants.rb and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2368. Reimplement of due_date.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2369. Reimplement duties controller.rb and badges controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2371. Reimplement quiz_questionnaires_controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2373. Reimplementation of teams controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2374. Reimplement the Question hierarchy]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2375. Reimplement Waitlists]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2376. Reimplement student_quizzes_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2379. Reimplement authorization_helper.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2383. Grading Audit Trail]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate_controller.rb)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-2 Observability and Debuggability]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-4 Extend NDB Operator capabilities to support Postgres HA]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - G2350. Add GitLab support for using GraphQL to query user metrics 1]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - G2352. Add GitLab support for using GraphQL to query repository information]]&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151105</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151105"/>
		<updated>2023-11-03T19:10:45Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
'''#app/controllers/join_team_requests_controller.rb''' &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The original code has variables like 'P', 'D' and 'A' which lead to ambiguity and they had to be changed to &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Api::V1::JoinTeamRequestsController &amp;lt; ApplicationController&lt;br /&gt;
  # Constants used to indicate status for the request&lt;br /&gt;
  # The datatype for status is string&lt;br /&gt;
  PENDING = 'P'&lt;br /&gt;
  DECLINED = 'D'&lt;br /&gt;
  ACCEPTED = 'A'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also added new methods to the controller for Create, Read, Update and Delete functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
For example &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create&lt;br /&gt;
&lt;br /&gt;
    @join_team_request = JoinTeamRequest.new&lt;br /&gt;
    @join_team_request.comments = params[:comments]&lt;br /&gt;
    @join_team_request.status = PENDING&lt;br /&gt;
    @join_team_request.team_id = params[:team_id]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    participant = Participant.where(user_id: @current_user.id, assignment_id: params[:assignment_id]).first&lt;br /&gt;
&lt;br /&gt;
    team = Team.find(params[:team_id])&lt;br /&gt;
    if team.participants.include?(participant)&lt;br /&gt;
      render json: { error: 'You already belong to the team' }, status: :unprocessable_entity&lt;br /&gt;
    else&lt;br /&gt;
    if participant&lt;br /&gt;
      @join_team_request.participant_id = participant.id&lt;br /&gt;
      if @join_team_request.save&lt;br /&gt;
        render json: @join_team_request, status: :created&lt;br /&gt;
      else&lt;br /&gt;
        render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: &amp;quot;Participant not found&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def show&lt;br /&gt;
    render json: @join_team_request&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def update&lt;br /&gt;
    if @join_team_request.update(join_team_request_params)&lt;br /&gt;
      render json: { message: 'JoinTeamRequest was successfully updated' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def destroy&lt;br /&gt;
     @join_team_request.destroy&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apart from this, we added the 'decline' methods to handle accept/decline requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def decline&lt;br /&gt;
    @join_team_request.status = DECLINED&lt;br /&gt;
&lt;br /&gt;
    if @join_team_request.save&lt;br /&gt;
      render json: { message: 'JoinTeamRequest declined successfully' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have added additional functionality like &amp;lt;br&amp;gt;&lt;br /&gt;
1. Checking if the team is already full &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def check_team_status&lt;br /&gt;
    team = Team.find(params[:team_id])&lt;br /&gt;
    if team.full?&lt;br /&gt;
      render json: { message: 'This team is full.' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Checking if the student is already a part of some team&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if team.participants.include?(participant)&lt;br /&gt;
      render json: { error: 'You already belong to the team' }, status: :unprocessable_entity&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#app/models/join_team_requests.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
We have added the model file to handle join team requests coming from one student to the other. &lt;br /&gt;
&lt;br /&gt;
'''#spec/requests/api/v1/join_team_requests_spec.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
This spec file was added to handle the testing for our controller. More information about testing is given in the testing section.&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
'''#app/models/participant.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
  has_many   :join_team_requests, dependent: :destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#config/routes.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      resources :join_team_requests do&lt;br /&gt;
        collection do&lt;br /&gt;
          post 'decline/:id', to:'join_team_requests#decline'&lt;br /&gt;
          post 'accept/:id', to:'join_team_requests#accept'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly as shown below. &amp;lt;br&amp;gt;&lt;br /&gt;
Here is the '''video''' which shows testing the controller using Postman -&amp;lt;br&amp;gt;&lt;br /&gt;
https://drive.google.com/file/d/1hS8vjWwHznWks9Qj7S-YIWdCfqqcsyhe/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the '''video''' for Rswag testing &amp;lt;br&amp;gt;&lt;br /&gt;
https://drive.google.com/file/d/1SizhiJhaTIC1bZPgxVoHN8MtfhC3Lcbc/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Following is a link to the Swagger test file - &amp;lt;br&amp;gt;&lt;br /&gt;
https://github.com/manoj-ayyappan/csc517_program3_E2370/blob/main/spec/requests/api/v1/join_team_requests_spec.rb&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
We've successfully reimplemented the Join Teams Request Controller, achieving a more comprehensive feature set by introducing new methods for CRUD functionality, facilitating the acceptance and rejection of join requests, and adopting meaningful status constants like 'PENDING,' 'ACCEPTED,' and 'DECLINED' in place of less intuitive single-character codes. These improvements not only expand the controller's capabilities but also enhance its readability and maintainability,&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151065</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151065"/>
		<updated>2023-11-03T02:41:55Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
'''#app/controllers/join_team_requests_controller.rb''' &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The original code has variables like 'P', 'D' and 'A' which lead to ambiguity and they had to be changed to &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Api::V1::JoinTeamRequestsController &amp;lt; ApplicationController&lt;br /&gt;
  # Constants used to indicate status for the request&lt;br /&gt;
  # The datatype for status is string&lt;br /&gt;
  PENDING = 'P'&lt;br /&gt;
  DECLINED = 'D'&lt;br /&gt;
  ACCEPTED = 'A'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also added new methods to the controller for Create, Read, Update and Delete functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
For example &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create&lt;br /&gt;
&lt;br /&gt;
    @join_team_request = JoinTeamRequest.new&lt;br /&gt;
    @join_team_request.comments = params[:comments]&lt;br /&gt;
    @join_team_request.status = PENDING&lt;br /&gt;
    @join_team_request.team_id = params[:team_id]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    participant = Participant.where(user_id: @current_user.id, assignment_id: params[:assignment_id]).first&lt;br /&gt;
&lt;br /&gt;
    team = Team.find(params[:team_id])&lt;br /&gt;
    if team.participants.include?(participant)&lt;br /&gt;
      render json: { error: 'You already belong to the team' }, status: :unprocessable_entity&lt;br /&gt;
    else&lt;br /&gt;
    if participant&lt;br /&gt;
      @join_team_request.participant_id = participant.id&lt;br /&gt;
      if @join_team_request.save&lt;br /&gt;
        render json: @join_team_request, status: :created&lt;br /&gt;
      else&lt;br /&gt;
        render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: &amp;quot;Participant not found&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def show&lt;br /&gt;
    render json: @join_team_request&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def update&lt;br /&gt;
    if @join_team_request.update(join_team_request_params)&lt;br /&gt;
      render json: { message: 'JoinTeamRequest was successfully updated' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def destroy&lt;br /&gt;
     @join_team_request.destroy&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apart from this, we added the 'decline' methods to handle accept/decline requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def decline&lt;br /&gt;
    @join_team_request.status = DECLINED&lt;br /&gt;
&lt;br /&gt;
    if @join_team_request.save&lt;br /&gt;
      render json: { message: 'JoinTeamRequest declined successfully' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have added additional functionality like &amp;lt;br&amp;gt;&lt;br /&gt;
1. Checking if the team is already full &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def check_team_status&lt;br /&gt;
    team = Team.find(params[:team_id])&lt;br /&gt;
    if team.full?&lt;br /&gt;
      render json: { message: 'This team is full.' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Checking if the student is already a part of some team&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if team.participants.include?(participant)&lt;br /&gt;
      render json: { error: 'You already belong to the team' }, status: :unprocessable_entity&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#app/models/join_team_requests.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
We have added the model file to handle join team requests coming from one student to the other. &lt;br /&gt;
&lt;br /&gt;
'''#spec/requests/api/v1/join_team_requests_spec.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
This spec file was added to handle the testing for our controller. More information about testing is given in the testing section.&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
'''#app/models/participant.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
  has_many   :join_team_requests, dependent: :destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#config/routes.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      resources :join_team_requests do&lt;br /&gt;
        collection do&lt;br /&gt;
          post 'decline/:id', to:'join_team_requests#decline'&lt;br /&gt;
          post 'accept/:id', to:'join_team_requests#accept'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly as shown below. &amp;lt;br&amp;gt;&lt;br /&gt;
Here is the '''video''' which shows testing the controller using Postman -&amp;lt;br&amp;gt;&lt;br /&gt;
https://drive.google.com/file/d/1hS8vjWwHznWks9Qj7S-YIWdCfqqcsyhe/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the '''video''' for Rswag testing &amp;lt;br&amp;gt;&lt;br /&gt;
https://drive.google.com/file/d/1SizhiJhaTIC1bZPgxVoHN8MtfhC3Lcbc/view?usp=sharing &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Following is a link to the Swagger test file - &amp;lt;br&amp;gt;&lt;br /&gt;
https://github.com/manoj-ayyappan/csc517_program3_E2370/blob/main/swagger/v1/swagger.yaml &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
We've successfully reimplemented the Join Teams Request Controller, achieving a more comprehensive feature set by introducing new methods for CRUD functionality, facilitating the acceptance and rejection of join requests, and adopting meaningful status constants like 'PENDING,' 'ACCEPTED,' and 'DECLINED' in place of less intuitive single-character codes. These improvements not only expand the controller's capabilities but also enhance its readability and maintainability,&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151064</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151064"/>
		<updated>2023-11-02T20:27:54Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
'''#app/controllers/join_team_requests_controller.rb''' &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The original code has variables like 'P', 'D' and 'A' which lead to ambiguity and they had to be changed to &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Api::V1::JoinTeamRequestsController &amp;lt; ApplicationController&lt;br /&gt;
  # Constants used to indicate status for the request&lt;br /&gt;
  # The datatype for status is string&lt;br /&gt;
  PENDING = 'P'&lt;br /&gt;
  DECLINED = 'D'&lt;br /&gt;
  ACCEPTED = 'A'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also added new methods to the controller for Create, Read, Update and Delete functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
For example &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create&lt;br /&gt;
&lt;br /&gt;
    @join_team_request = JoinTeamRequest.new&lt;br /&gt;
    @join_team_request.comments = params[:comments]&lt;br /&gt;
    @join_team_request.status = PENDING&lt;br /&gt;
    @join_team_request.team_id = params[:team_id]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    participant = Participant.where(user_id: @current_user.id, assignment_id: params[:assignment_id]).first&lt;br /&gt;
&lt;br /&gt;
    team = Team.find(params[:team_id])&lt;br /&gt;
    if team.participants.include?(participant)&lt;br /&gt;
      render json: { error: 'You already belong to the team' }, status: :unprocessable_entity&lt;br /&gt;
    else&lt;br /&gt;
    if participant&lt;br /&gt;
      @join_team_request.participant_id = participant.id&lt;br /&gt;
      if @join_team_request.save&lt;br /&gt;
        render json: @join_team_request, status: :created&lt;br /&gt;
      else&lt;br /&gt;
        render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: &amp;quot;Participant not found&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def show&lt;br /&gt;
    render json: @join_team_request&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def update&lt;br /&gt;
    if @join_team_request.update(join_team_request_params)&lt;br /&gt;
      render json: { message: 'JoinTeamRequest was successfully updated' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def destroy&lt;br /&gt;
     @join_team_request.destroy&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apart from this, we added the 'decline' methods to handle accept/decline requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def decline&lt;br /&gt;
    @join_team_request.status = DECLINED&lt;br /&gt;
&lt;br /&gt;
    if @join_team_request.save&lt;br /&gt;
      render json: { message: 'JoinTeamRequest declined successfully' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have added additional functionality like &amp;lt;br&amp;gt;&lt;br /&gt;
1. Checking if the team is already full &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def check_team_status&lt;br /&gt;
    team = Team.find(params[:team_id])&lt;br /&gt;
    if team.full?&lt;br /&gt;
      render json: { message: 'This team is full.' }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Checking if the student is already a part of some team&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if team.participants.include?(participant)&lt;br /&gt;
      render json: { error: 'You already belong to the team' }, status: :unprocessable_entity&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#app/models/join_team_requests.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
We have added the model file to handle join team requests coming from one student to the other. &lt;br /&gt;
&lt;br /&gt;
'''#spec/requests/api/v1/join_team_requests_spec.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
This spec file was added to handle the testing for our controller. More information about testing is given in the testing section.&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
'''#app/models/participant.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
  has_many   :join_team_requests, dependent: :destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#config/routes.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      resources :join_team_requests do&lt;br /&gt;
        collection do&lt;br /&gt;
          post 'decline/:id', to:'join_team_requests#decline'&lt;br /&gt;
          post 'accept/:id', to:'join_team_requests#accept'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly as shown below. &amp;lt;br&amp;gt;&lt;br /&gt;
Here is the '''video''' which shows testing the controller using Postman -&amp;lt;br&amp;gt;&lt;br /&gt;
https://drive.google.com/file/d/1hS8vjWwHznWks9Qj7S-YIWdCfqqcsyhe/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Following is a link to the Swagger test file - &amp;lt;br&amp;gt;&lt;br /&gt;
https://github.com/manoj-ayyappan/csc517_program3_E2370/blob/main/swagger/v1/swagger.yaml &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
We've successfully reimplemented the Join Teams Request Controller, achieving a more comprehensive feature set by introducing new methods for CRUD functionality, facilitating the acceptance and rejection of join requests, and adopting meaningful status constants like 'PENDING,' 'ACCEPTED,' and 'DECLINED' in place of less intuitive single-character codes. These improvements not only expand the controller's capabilities but also enhance its readability and maintainability,&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151063</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=151063"/>
		<updated>2023-11-02T20:12:42Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
'''#app/controllers/join_team_requests_controller.rb''' &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The original code has variables like 'P', 'D' and 'A' which lead to ambiguity and they had to be changed to &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Api::V1::JoinTeamRequestsController &amp;lt; ApplicationController&lt;br /&gt;
  # Constants used to indicate status for the request&lt;br /&gt;
  # The datatype for status is string&lt;br /&gt;
  PENDING = 'P'&lt;br /&gt;
  DECLINED = 'D'&lt;br /&gt;
  ACCEPTED = 'A'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also added new methods to the controller for Create, Read, Update and Delete functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
For example &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def update&lt;br /&gt;
    if @join_team_request.update(join_team_request_params)&lt;br /&gt;
      render json: { message: 'JoinTeamRequest was successfully updated' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apart from this, we added the 'accept' and 'decline' methods to handle accept/decline requests&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def accept&lt;br /&gt;
    @join_team_request.status = ACCEPTED&lt;br /&gt;
&lt;br /&gt;
    if @join_team_request.save&lt;br /&gt;
      render json: { message: 'JoinTeamRequest accepted successfully' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def decline&lt;br /&gt;
    @join_team_request.status = DECLINED&lt;br /&gt;
&lt;br /&gt;
    if @join_team_request.save&lt;br /&gt;
      render json: { message: 'JoinTeamRequest declined successfully' }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { errors: @join_team_request.errors.full_messages }, status: :unprocessable_entity&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#app/models/join_team_requests.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
We have added the model file to handle join team requests coming from one student to the other. &lt;br /&gt;
&lt;br /&gt;
'''#spec/requests/api/v1/join_team_requests_spec.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
This spec file was added to handle the testing for our controller. More information about testing is given in the testing section.&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
'''#app/models/participant.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
  has_many   :join_team_requests, dependent: :destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#config/routes.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      resources :join_team_requests do&lt;br /&gt;
        collection do&lt;br /&gt;
          post 'decline/:id', to:'join_team_requests#decline'&lt;br /&gt;
          post 'accept/:id', to:'join_team_requests#accept'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly as shown below. &amp;lt;br&amp;gt;&lt;br /&gt;
Here is the video which shows testing the controller using Postman -&amp;lt;br&amp;gt;&lt;br /&gt;
https://drive.google.com/file/d/1hS8vjWwHznWks9Qj7S-YIWdCfqqcsyhe/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Following is a link to the Swagger test file - &amp;lt;br&amp;gt;&lt;br /&gt;
https://github.com/manoj-ayyappan/csc517_program3_E2370/blob/main/swagger/v1/swagger.yaml &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
We've successfully reimplemented the Join Teams Request Controller, achieving a more comprehensive feature set by introducing new methods for CRUD functionality, facilitating the acceptance and rejection of join requests, and adopting meaningful status constants like 'PENDING,' 'ACCEPTED,' and 'DECLINED' in place of less intuitive single-character codes. These improvements not only expand the controller's capabilities but also enhance its readability and maintainability,&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150781</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150781"/>
		<updated>2023-10-31T01:24:07Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
#app/controllers/join_team_requests_controller.rb&lt;br /&gt;
#app/models/join_team_requests.rb&lt;br /&gt;
#spec/requests/api/v1/join_team_requests_spec.rb&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
'''#app/models/participant.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
  has_many   :join_team_requests, dependent: :destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#config/routes.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      resources :join_team_requests do&lt;br /&gt;
        collection do&lt;br /&gt;
          post 'decline/:id', to:'join_team_requests#decline'&lt;br /&gt;
          post 'accept/:id', to:'join_team_requests#accept'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly. &amp;lt;br&amp;gt;&lt;br /&gt;
Following is a link to the Swagger test file - &amp;lt;br&amp;gt;&lt;br /&gt;
https://github.com/manoj-ayyappan/csc517_program3_E2370/blob/main/swagger/v1/swagger.yaml&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
We've successfully reimplemented the Join Teams Request Controller, achieving a more comprehensive feature set by introducing new methods for CRUD functionality, facilitating the acceptance and rejection of join requests, and adopting meaningful status constants like 'PENDING,' 'ACCEPTED,' and 'DECLINED' in place of less intuitive single-character codes. These improvements not only expand the controller's capabilities but also enhance its readability and maintainability,&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150772</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150772"/>
		<updated>2023-10-31T01:16:11Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ 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.&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
#app/controllers/join_team_requests_controller.rb&lt;br /&gt;
#app/models/join_team_requests.rb&lt;br /&gt;
#spec/requests/api/v1/join_team_requests_spec.rb&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
'''#app/models/participant.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Participant &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :user&lt;br /&gt;
  belongs_to :assignment, foreign_key: 'assignment_id', inverse_of: false&lt;br /&gt;
  has_many   :join_team_requests, dependent: :destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''#config/routes.rb'''&amp;lt;br&amp;gt;&lt;br /&gt;
Original code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modified code&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rails.application.routes.draw do&lt;br /&gt;
&lt;br /&gt;
  mount Rswag::Api::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  mount Rswag::Ui::Engine =&amp;gt; 'api-docs'&lt;br /&gt;
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html&lt;br /&gt;
          post '/sign_up_student', to: 'signed_up_teams#sign_up_student'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      resources :join_team_requests do&lt;br /&gt;
        collection do&lt;br /&gt;
          post 'decline/:id', to:'join_team_requests#decline'&lt;br /&gt;
          post 'accept/:id', to:'join_team_requests#accept'&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly. &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150762</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150762"/>
		<updated>2023-10-31T01:01:53Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
#app/controllers/join_team_requests_controller.rb&lt;br /&gt;
#app/models/join_team_requests.rb&lt;br /&gt;
#spec/requests/api/v1/join_team_requests_spec.rb&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
#app/models/participant.rb&lt;br /&gt;
#config/routes.rb&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly. &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
'''Mentor''' &amp;lt;br&amp;gt;&lt;br /&gt;
Renji Joseph Sabu &amp;lt;rsabu@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Students'''&amp;lt;br&amp;gt;&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150758</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150758"/>
		<updated>2023-10-31T00:57:00Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The controller join_team_requests_controller.rb contains functions to create, list, update, delete, and decline requests to join teams. This is a fairly straightforward controller with basic functionalities which is easily tested using Postman. The objective of this project was to change the operation of this controller to suit our API.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
#app/controllers/join_team_requests_controller.rb&lt;br /&gt;
#app/models/join_team_requests.rb&lt;br /&gt;
#spec/requests/api/v1/join_team_requests_spec.rb&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
#app/models/participant.rb&lt;br /&gt;
#config/routes.rb&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
We have thoroughly tested our code using Postman and the controller works flawlessly. &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
- Created new methods for the Join Team Requests Controller to support CRUD functionality.&amp;lt;br&amp;gt;&lt;br /&gt;
- Added an accept and decline method.&amp;lt;br&amp;gt;&lt;br /&gt;
- Modified the status to use constants such as 'PENDING', 'ACCEPTED', and 'DECLINED' instead of 'P', 'D', 'A'.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150625</id>
		<title>CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2370._Reimplement_join_team_requests_controller&amp;diff=150625"/>
		<updated>2023-10-30T20:32:50Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: Added some initial content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New Files==&lt;br /&gt;
#app/controllers/join_team_requests_controller.rb&lt;br /&gt;
#app/models/join_team_requests.rb&lt;br /&gt;
#spec/requests/api/v1/join_team_requests_spec.rb&lt;br /&gt;
&lt;br /&gt;
==File Changes==&lt;br /&gt;
#app/models/participant.rb&lt;br /&gt;
#config/routes.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Test Plan==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Modifications==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
Manoj Ayyappan &amp;lt;mayyapp@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Pradeep Patil &amp;lt;papatil@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Maya Patel &amp;lt;mdpatel2@ncsu.edu&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
Changes for this project are under Expertiza Pull Request https://github.com/expertiza/reimplementation-back-end/pull/50&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=150598</id>
		<title>CSC/ECE 517 Fall 2023</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=150598"/>
		<updated>2023-10-30T19:40:00Z</updated>

		<summary type="html">&lt;p&gt;Mayyapp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[CSC/ECE 517 Fall 2023 - E2358. Refactor student_quizzes_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2351. Finish mentor management for assignments without topics]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2359. Refactor user_controller.rb, user.rb, and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2367. Reimplement participants_controller.rb, participants.rb and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2355. Improving Search Facility In Expertiza]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2365. Create a user interface for Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2364. Create a UI for Course's &amp;amp; Assignment's &amp;quot;Add Participants&amp;quot; page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2361. Create a page to create and update a Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2362. Create a page to edit an Assignment's due date in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2363. Create a UI for Assignment Edit page &amp;quot;Etc&amp;quot; tab in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2375. Reimplement Waitlists]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2357. Refactor sign_up_sheet_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller]]&lt;/div&gt;</summary>
		<author><name>Mayyapp</name></author>
	</entry>
</feed>