CSC/ECE 517 Spring 2023 E2318: Reimplement Participants Controller: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(36 intermediate revisions by 3 users not shown)
Line 4: Line 4:


== Background ==
== Background ==
In expertiza, there are three different types of users - normal users (typically students), administrators, super administrators. A normal user can participate in a course or an assignment or both. Courses and assignments are different entities in the system which allow enrollment of users. While a course is an independent entity, an assignment is part of a course.
In expertiza, there are two different models: Course and Assignment. Although an Assignment is a part of a Course, students can participate in a Course or an Assignment independently.


The participants controller manages the participants across these courses and assignments by providing functionalities like listing all participants, adding a participant to a course or an assignment, updating the authorizations of a participant (can_submit, can_review, can_take_quiz), deleting a participant, inheriting participants from a course to an assignment, bequeath assignment participants to the corresponding course, changing the handle name of a participant in an assignment, and deleting a participant from an assignment.
The ParticipantsController provides functionalities for listing the participants of a course or an assignment, adding a participant to a course or an assignment, updating the authorizations of a participant (can_submit, can_review, can_take_quiz), updating the handle of a participant for an assignment, inheriting course participants to its assignment, bequeathing assignment participants to its course and deleting a participant from a course or an assignment.
 
== Project Goals ==
Reimplement the Expertiza Participants Controller as a Rails API while maintaining the existing functionality of the controller.


== Implementation ==
== Implementation ==
As part of the re-implementation, the objective is to employ an API-first approach while maintaining all the existing functionality in an efficient, robust and simple manner. Specifically for the participants controller, we've added seven different API endpoints to extend the current functionalities while modifying the code to support these APIs. The details for these endpoints can be found below.
=== Assumptions ===
#The Participant model implements an instance method <code>team</code> which checks if a participant is on a team. This functionality is used in the destroy method
#The CourseParticipant and AssignmentParticipant models implement the <code>copy</code> method which copies participants from the course to assignment and vice-versa. This functionality is used in the inherit and bequeath methods.


As part of the re-implementation, the objective is to employ an API-first approach while maintaining all the existing functionality in an efficient, robust and simple manner. Specifically for the participants controller, we've added seven different API endpoints to extend the current functionalities while modifying the code to support these APIs. The details for these endpoints can be found below.
=== API documentation ===


{| class="wikitable" style="width: 100%;
{| class="wikitable" style="width: 100%;
Line 16: Line 24:
|-
|-
|1
|1
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Index Index]
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Index index]
|GET <code>/participants/index/:model/:id</code>
|GET <code>/participants/index/:model/:id</code>
|Returns a list of participants of an assignment or a course
|returns a list of participants of an assignment or a course
|-
|-
|2
|2
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Create Create]
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Create create]
|POST <code>/participants/:model/:id/:authorization</code>
|POST <code>/participants/:model/:id</code>
|Creates a participant in an assignment or a course
|creates a participant in an assignment or a course
|-
|-
|3
|3
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Update_Handle Update Handle]
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Update_Handle update_handle]
|POST <code>/participants/change_handle/:id</code>
|PATCH <code>/participants/change_handle/:id</code>
|Updates the participant's handle for an assignment
|updates the participant's handle for an assignment
|-
|-
|4
|4
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Update_Authorizations Update Authorizations]
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Update_Authorizations update_authorizations]
|POST <code>/participants/update_authorizations/:id/:authorization</code>
|PATCH <code>/participants/update_authorizations/:id</code>
|Updates the participant's permissions for an assignment or a course depending on the role
|updates the participant's permissions for an assignment or a course depending on the role
|-
|-
|5
|5
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Delete Delete]
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Delete delete]
|DELETE <code>/participants/:id</code>
|DELETE <code>/participants/:id</code>
|Deletes a participant from an assignment or a course
|deletes a participant from an assignment or a course
|-
|-
|6
|6
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Inherit Inherit]
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Inherit inherit]
|GET <code>/participants/inherit/:id</code>
|GET <code>/participants/inherit/:id</code>
|Copies existing participants from a course down to its assignment
|copies existing participants from a course down to its assignment
|-
|-
|7
|7
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Bequeath Bequeath]
|[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2023_E2318:_Reimplement_Participants_Controller#Bequeath bequeath]
|GET <code>/participants/bequeath/:id</code>
|GET <code>/participants/bequeath/:id</code>
|Copies existing participants from an assignment up to its course
|copies existing participants from an assignment up to its course
|}
|}


=== Index ===
==== Index ====
'''Purpose''': Returns a list of participants of an assignment or a course
 
'''Description''': This endpoint allows the user to request a list of all participants for the provided assignment ID or course ID. A success response renders a JSON with a list of participants that can be parsed by the front-end.
'''Description''': This endpoint allows the user to request a list of all participants for the provided assignment ID or course ID. A success response renders a JSON with a list of participants that can be parsed by the front-end.


'''Path''': <code>/participants/index/:model/:id</code>
'''Path''': GET <code>/participants/index/:model/:id</code>
 
'''API method''': GET


'''Parameters''':
'''Parameters''':
Line 73: Line 77:
|}
|}


* '''Success response'''
'''Response''':
<pre>
<pre>
{
{
Line 80: Line 84:
}
}
status: :ok
status: :ok
</pre>


* '''Failure response'''
<pre>
{  
{  
   error: "Missing or invalid required parameters"  
   error: "Missing or invalid required parameters"  
Line 90: Line 91:
</pre>
</pre>


'''Changes''':
==== Create ====
<TBD>
 
=== Create ===
'''Purpose''': Creates a participant in an assignment or a course
 
'''Description''': This endpoint allows the user to create a new participant for the provided assignment ID or course ID. A success response renders a JSON with the participant details. The user is required to provide a valid username as well as the appropriate permissions for the new participant. These permissions are <code>[can_submit, can_review, can_take_quiz]</code>. Depending on whether the request is for an <code>Assignment</code> or a <code>Course</code>, a participant type is determined between an <code>AssignmentParticipant</code> or a <code>CourseParticipant</code> and an entry is made into the database accordingly.  
'''Description''': This endpoint allows the user to create a new participant for the provided assignment ID or course ID. A success response renders a JSON with the participant details. The user is required to provide a valid username as well as the appropriate permissions for the new participant. These permissions are <code>[can_submit, can_review, can_take_quiz]</code>. Depending on whether the request is for an <code>Assignment</code> or a <code>Course</code>, a participant type is determined between an <code>AssignmentParticipant</code> or a <code>CourseParticipant</code> and an entry is made into the database accordingly.  


'''Path''': <code>/participants/:model/:id/:authorization</code>
'''Path''': POST <code>/participants/:model/:id</code>
 
'''API method''': POST


'''Parameters''':
'''Parameters''':
Line 108: Line 102:
|1
|1
|<code>model</code>
|<code>model</code>
|One of these two strings: <code>['Assignment', 'Course']</code>
|One of <code>['Assignment', 'Course']</code>
|-
|-
|2
|2
|<code>id</code>
|<code>id</code>
|The unique identifier for an assignment or a course depending on the value of <code>:model</code>
|The id of the course or assignment
|-
|3
|<code>username</code>
|The unique username of the new participant being requested</code>
|-
|4
|<code>authorization</code>
|A list of required permissions for the requested new particpant</code>
|}
|}
'''Request Body''':
<pre>
content:
  application/json:
    schema:
      type: object
      properties:
        user:
          type: object
          properties:
          name: string
        participant:
          type: object
          properties:
            can_submit:
              type: boolean
            can_review:
              type: boolean
            can_take_quiz:
              type: boolean
</pre>


'''Response''':
'''Response''':
* '''Success response'''
<pre>
<pre>
Success
{
{
   "participant": participant,
   "participant": participant,
}
}
status: :created
status: :created
</pre>


* '''Failure responses'''
When user does not exist
When user does not exist
<pre>
{  
{  
   error: "User #{params[:user][:name]} does not exist"  
   error: "User #{params[:user][:name]} does not exist"  
}
}
status: :not_found
status: :not_found
</pre>


When participant already exists in the assignment/course
When participant already exists in the assignment/course
<pre>
{  
{  
   error: "Participant #{params[:user][:name]} already exists for this #{params[:model]}"  
   error: "Participant #{params[:user][:name]} already exists for this #{params[:model]}"  
Line 149: Line 152:
</pre>
</pre>


'''Changes''':
==== Update Handle ====
<TBD>
 
=== Update Handle ===
'''Purpose''': Updates the participant's handle for an assignment
 
'''Description''': This endpoint allows the user to change their handle name for a given <code>AssignmentParticipant</code>. An <code>AssignmentParticipant</code> is one who is already enrolled in the assignment. A success response renders a JSON with the updated participant details. The user is required to provide a valid and available handle name.  
'''Description''': This endpoint allows the user to change their handle name for a given <code>AssignmentParticipant</code>. An <code>AssignmentParticipant</code> is one who is already enrolled in the assignment. A success response renders a JSON with the updated participant details. The user is required to provide a valid and available handle name.  


'''Path''': <code>/participants/change_handle/:id</code>
'''Path''': POST <code>/participants/change_handle/:id</code>
 
'''API method''': POST


'''Parameters''':
'''Parameters''':
Line 167: Line 163:
|1
|1
|<code>id</code>
|<code>id</code>
|The unique identifier for an <code>AssignmentParticipant</code>
|The id of the <code>AssignmentParticipant</code>
|-
|2
|<code>handle</code>
|A valid, available handle name for the participant
|}
|}
'''Request Body''':
<pre>
content:
  application/json:
    schema:
      type: object
      properties:
        participant:
          type: object
          properties:
          handle:
            type: integer
</pre>


'''Response''':
'''Response''':
* '''Success responses'''
 
<pre>
When handle change was successful
When handle change was successful
<pre>
{
{
   "participant": participant,
   "participant": participant,
}
}
status: :ok
status: :ok
</pre>


When handle is already in use
When handle is already in use
<pre>
{  
{  
   note: "Handle already in use"  
   note: "Handle already in use"  
}
}
status: :ok
status: :ok
</pre>


* '''Failure response'''
Failure
<pre>
{  
{  
   error: participant.errors
   error: participant.errors
Line 200: Line 202:
</pre>
</pre>


'''Changes''':
==== Update authorizations ====
<TBD>
 
=== Update authorizations ===
'''Purpose''': Updates the participant's permissions for an assignment or a course depending on the role
 
'''Description''': This endpoint allows the user to change the permissions for a given <code>Participant</code>. The appropriate permissions for any participant are <code>[can_submit, can_review, can_take_quiz]</code>. A <code>Participant</code> is one who is already enrolled in an assignment or a course. A success response renders a JSON with the updated participant details and permissions.  
'''Description''': This endpoint allows the user to change the permissions for a given <code>Participant</code>. The appropriate permissions for any participant are <code>[can_submit, can_review, can_take_quiz]</code>. A <code>Participant</code> is one who is already enrolled in an assignment or a course. A success response renders a JSON with the updated participant details and permissions.  


'''Path''': <code>/participants/update_authorizations/:id/:authorization</code>
'''Path''': POST <code>/participants/update_authorizations/:id</code>
 
'''API method''': POST


'''Parameters''':
'''Parameters''':
Line 218: Line 213:
|1
|1
|<code>id</code>
|<code>id</code>
|The unique identifier for a <code>Participant</code>
|The id of the <code>Participant</code>
|-
|2
|<code>authorization</code>
|A list of permissions being requested for the participant
|-
|3
|<code>can_submit</code>
|A value for whether the participant can make submissions or not.
|-
|4
|<code>can_review</code>
|A value for whether the participant can create reviews or not.
|-
|5
|<code>can_take_quiz</code>
|A value for whether the participant can take quizzes or not.
|}
|}
'''Request Body''':
<pre>
content:
  application/json:
    schema:
      type: object
      properties:
        participant:
          type: object
          properties:
            can_submit:
              type: boolean
            can_review:
              type: boolean
            can_take_quiz:
              type: boolean
</pre>


'''Response''':
'''Response''':
* '''Success response'''
 
<pre>
<pre>
Success
{
{
   "participant": participant,
   "participant": participant,
}
}
status: :ok
status: :ok
</pre>
 
* '''Failure response'''
Failure
<pre>
{  
{  
   error: participant.errors
   error: participant.errors
Line 253: Line 250:
</pre>
</pre>


'''Changes''':
==== Delete ====
<TBD>
 
=== Delete ===
'''Purpose''': Deletes a participant from an assignment or a course
 
'''Description''': This endpoint allows the user to delete an existing participant from an assignment or a course. The user is expected to provide the valid participant ID. The participant is only deleted if they are not part of another team for a different assignment/course. This is to ensure that a participant enrolled in two different teams is not deleted from the list of participants. Deletion is only possible if the participant is only enrolled in only one team. A success response renders a JSON with a confirmation of the deletion.
'''Description''': This endpoint allows the user to delete an existing participant from an assignment or a course. The user is expected to provide the valid participant ID. The participant is only deleted if they are not part of another team for a different assignment/course. This is to ensure that a participant enrolled in two different teams is not deleted from the list of participants. Deletion is only possible if the participant is only enrolled in only one team. A success response renders a JSON with a confirmation of the deletion.


'''Path''': <code>/participants/:id</code>
'''Path''': DELETE <code>/participants/:id</code>
 
'''API method''': DELETE


'''Parameters''':
'''Parameters''':
Line 271: Line 261:
|1
|1
|<code>id</code>
|<code>id</code>
|The unique identifier for a <code>Participant</code>
|The id of the <code>Participant</code>
|}
|}


'''Response''':
'''Response''':
* '''Success response'''
 
<pre>
<pre>
Success
{
{
   message: "#{participant.user.name} was successfully removed as a participant"
   message: "#{participant.user.name} was successfully removed as a participant"
}
}
status: :ok
status: :ok
</pre>


* '''Failure responses'''
When the participant is on another team
When the participant is on another team
<pre>
{  
{  
   error: "This participant is on a team"  
   error: "This participant is on a team"  
}
}
status: :unprocessable_entity
status: :unprocessable_entity
</pre>


<pre>
Failure
{  
{  
   error: "Failed to remove participant"  
   error: "Failed to remove participant"  
Line 299: Line 286:
</pre>
</pre>


'''Changes''':
==== Inherit ====
<TBD>
'''Description''': This endpoint allows the user to copy the existing participants from a course to the provided assignment in a single operation. Before this is carried out, validations are performed on 1) the existence of a course for the provided assignment and 2) non-empty list of participants already registered in the course. After these checks, the participants are copied from the course to the given assignment with the help of a private method <code>copy_participants_from_source_to_target</code>. A success response renders a JSON with a confirmation of the copy.
 
=== Inherit ===
'''Purpose''': Copies existing participants from a course down to its assignment


'''Description''': This endpoint allows the user to copy the existing participants from a course to the provided assignment in a single operation. Before this is carried out, validations are performed on 1) the existence of a course for the provided assignment and 2) non-empty list of participants already registered in the course. After these checks, the participants are copied from the course to the given assignment. A success response renders a JSON with a confirmation of the copy.
'''Path''': GET <code>/participants/inherit/:id</code>
 
'''Path''': <code>/participants/inherit/:id</code>
 
'''API method''': GET


'''Parameters''':
'''Parameters''':
Line 317: Line 297:
|1
|1
|<code>id</code>
|<code>id</code>
|The unique identifier for an <code>Assignment</code>
|The id of the <code>Assignment</code>
|}
|}


'''Response''':
'''Response''':
* '''Success responses'''
 
<pre>
When copy was successful
When copy was successful
<pre>
{
{
   message: "The participants from #{source.name} were copied to #{target.name}"
   message: "The participants from #{source.name} were copied to #{target.name}"
}
}
status: :created
status: :created
</pre>


When all the participants already existed in the assignment(no-op)
When all the participants already existed in the assignment(no-op)
<pre>
{
{
   note: "All of #{source.name} participants are already in #{target.name}"
   note: "All of #{source.name} participants are already in #{target.name}"
}
}
status: :ok
status: :ok
</pre>


When there were no participants for the course
When there were no participants for the course
<pre>
{
{
   note: "No participants were found for this #{source.name}"
   note: "No participants were found for this #{source.name}"
}
}
status: :ok
status: :ok
</pre>


* '''Failure response'''
When there is no course for the given assignment
When there is no course for the given assignment
<pre>
{  
{  
   error: "No course was found for this assignment"
   error: "No course was found for this assignment"
Line 355: Line 328:
</pre>
</pre>


'''Changes''':
==== Bequeath ====
<TBD>
'''Description''': This endpoint allows the user to copy the existing participants from the provided assignment to its associated course in a single operation. Before this is carried out, validations are performed on 1) the existence of a course for the provided assignment and 2) non-empty list of participants already registered in the assignment. After these checks, the participants are copied from the given assignment to its course with the help of a private method <code>copy_participants_from_source_to_target</code>. A success response renders a JSON with a confirmation of the copy.
 
=== Bequeath ===
'''Purpose''': Copies existing participants from an assignment up to its course
 
'''Description''': This endpoint allows the user to copy the existing participants from the provided assignment to its associated course in a single operation. Before this is carried out, validations are performed on 1) the existence of a course for the provided assignment and 2) non-empty list of participants already registered in the assignment. After these checks, the participants are copied from the given assignment to its course. A success response renders a JSON with a confirmation of the copy.
 
 
'''Path''': <code>/participants/bequeath/:id</code>


'''API method''': GET
'''Path''': GET <code>/participants/bequeath/:id</code>


'''Parameters''':
'''Parameters''':
Line 374: Line 339:
|1
|1
|<code>id</code>
|<code>id</code>
|The unique identifier for an <code>Assignment</code>
|The id of the <code>Assignment</code>
|}
|}


'''Response''':
'''Response''':
* '''Success responses'''
 
<pre>
When copy was successful
When copy was successful
<pre>
{
{
   message: "The participants from #{source.name} were copied to #{target.name}"
   message: "The participants from #{source.name} were copied to #{target.name}"
}
}
status: :created
status: :created
</pre>


When all the participants already existed in the course(no-op)
When all the participants already existed in the course(no-op)
<pre>
{
{
   note: "All of #{source.name} participants are already in #{target.name}"
   note: "All of #{source.name} participants are already in #{target.name}"
}
}
status: :ok
status: :ok
</pre>


When there were no participants for the assignment
When there were no participants for the assignment
<pre>
{
{
   note: "No participants were found for this #{source.name}"
   note: "No participants were found for this #{source.name}"
}
}
status: :ok
status: :ok
</pre>


* '''Failure response'''
When there is no course for the given assignment
When there is no course for the given assignment
<pre>
{  
{  
   error: "No course was found for this assignment"
   error: "No course was found for this assignment"
Line 412: Line 370:
</pre>
</pre>


== Test Plan ==
The testing framework is RSpec. The participants_controller.rb has dependencies on models and methods which are yet to be implemented. In the meantime, to test the API, we have used stubs and mocks. We have created some new models and added some associations in them which were required for stubbing.
To run the tests:
1. <code>git clone https://github.com/devashish-vachhani/reimplementation-back-end</code>
2. <code>cd reimplementation-back-end/</code>
3. <code>bundle install</code>
4. <code>bundle exec rspec spec/requests/api/v1/participants_spec.rb</code>


'''Changes''':
====Tests====
<TBD>


== Test Plan ==
{| class="wikitable" style="margin-left:40px"
<TBD>
|-
! Test ID !! Test Description
|-
| 1 || Test to check index with Assignment model and id - Lists Participants
|-
| 2 || Test to check index with Assignment model and id - Invalid Parameters
|-
| 3 || Test to create a new participant - With non existing User
|-
| 4 || Test to create a new participant - When participant already exists
|-
| 5 || Test to create a new participant - Successful creation of participant
|-
| 6 || Test to update handle request for a participant - When handle name already exists
|-
| 7 || Test to update handle request for a participant - Successful update of participant handle
|-
| 8 || Test to update handle request for a participant - Failed update of participant handle
|-
| 9 || Test to update authorizations request for a participant - Successful update of authorizations of a participant
|-
| 10 || Test to update authorizations request for a participant - Failed update of authorizations of a participant
|-
| 11 || Test to inherit participants from a Course to an Assignment - Failure in inherit because Assignment has no Course
|-
| 12 || Test to inherit participants from a Course to an Assignment - Failure for when there are no participants to inherit
|-
| 13 || Test to inherit participants from a Course to an Assignment - Checks if participants in Assignment is already in Course
|-
| 14 || Test to inherit participants from a Course to an Assignment - Successful inherit from Course to Assignment
|-
| 15 || Test to bequeath participants from an Assignment to a Course - Failure in bequeath because Course has no Assignment
|-
| 16 || Test to bequeath participants from an Assignment to a Course - Failure for when there are no participants to inherit
|-
| 17 || Test to bequeath participants from an Assignment to a Course - Checks if participants in Course is already in Assignment
|-
| 18 || Test to bequeath participants from an Assignment to a Course - Successful inherit from Course to Assignment
|-
| 19 || Test to destroy participant - Failure as participant to be deleted is on a team
|-
| 20 || Test to destroy participant - Successful deletion of a participant
|-
| 21 || Test to destroy participant - Failure if there is an error in "participant.destroy"
|}
 
==== Test Screenshot ====
[[File:Test.png]]
==== Swagger UI Screenshot ====
[[File:Swagger.png]]


== Contributors ==
== Contributors ==
Line 426: Line 441:


== Relevant Links ==
== Relevant Links ==
* '''Github Repository:''' https://github.com/devashish-vachhani/reimplementation-back-end
* '''Github Repository for new code:''' https://github.com/devashish-vachhani/reimplementation-back-end
* '''Github Repository for old code:''' https://github.com/expertiza/expertiza/blob/main/app/controllers/participants_controller.rb
* '''Pull Request:''' https://github.com/expertiza/reimplementation-back-end/pull/22
* '''Pull Request:''' https://github.com/expertiza/reimplementation-back-end/pull/22
* '''Testing video:''' https://drive.google.com/file/d/1gUz2brHpN7ay_YRK6TjdqeifDeUtGQQj/view?usp=share_link
* '''VCL Server:''' http://152.7.176.119
* '''VCL Server:''' http://152.7.176.119

Latest revision as of 00:09, 28 March 2023

Introduction

Expertiza is an Open Source Rails application which is used by instructors and students for creating assignments and submitting peer reviews. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and also review each other's assignments. Expertiza supports submissions across various document types, including URLs and wiki pages. The Source code of the application can be cloned from Github.

Background

In expertiza, there are two different models: Course and Assignment. Although an Assignment is a part of a Course, students can participate in a Course or an Assignment independently.

The ParticipantsController provides functionalities for listing the participants of a course or an assignment, adding a participant to a course or an assignment, updating the authorizations of a participant (can_submit, can_review, can_take_quiz), updating the handle of a participant for an assignment, inheriting course participants to its assignment, bequeathing assignment participants to its course and deleting a participant from a course or an assignment.

Project Goals

Reimplement the Expertiza Participants Controller as a Rails API while maintaining the existing functionality of the controller.

Implementation

As part of the re-implementation, the objective is to employ an API-first approach while maintaining all the existing functionality in an efficient, robust and simple manner. Specifically for the participants controller, we've added seven different API endpoints to extend the current functionalities while modifying the code to support these APIs. The details for these endpoints can be found below.

Assumptions

  1. The Participant model implements an instance method team which checks if a participant is on a team. This functionality is used in the destroy method
  2. The CourseParticipant and AssignmentParticipant models implement the copy method which copies participants from the course to assignment and vice-versa. This functionality is used in the inherit and bequeath methods.

API documentation

 #  Method Endpoint Description
1 index GET /participants/index/:model/:id returns a list of participants of an assignment or a course
2 create POST /participants/:model/:id creates a participant in an assignment or a course
3 update_handle PATCH /participants/change_handle/:id updates the participant's handle for an assignment
4 update_authorizations PATCH /participants/update_authorizations/:id updates the participant's permissions for an assignment or a course depending on the role
5 delete DELETE /participants/:id deletes a participant from an assignment or a course
6 inherit GET /participants/inherit/:id copies existing participants from a course down to its assignment
7 bequeath GET /participants/bequeath/:id copies existing participants from an assignment up to its course

Index

Description: This endpoint allows the user to request a list of all participants for the provided assignment ID or course ID. A success response renders a JSON with a list of participants that can be parsed by the front-end.

Path: GET /participants/index/:model/:id

Parameters:

 #  Parameter Expected Value
1 model One of these two strings: ['Assignment', 'Course']
2 id The unique identifier for an assignment or a course depending on the value of :model

Response:

{
  "model_object": model_object,
  "participants": participants,
}
status: :ok

{ 
  error: "Missing or invalid required parameters" 
}
status: :unprocessable_entity

Create

Description: This endpoint allows the user to create a new participant for the provided assignment ID or course ID. A success response renders a JSON with the participant details. The user is required to provide a valid username as well as the appropriate permissions for the new participant. These permissions are [can_submit, can_review, can_take_quiz]. Depending on whether the request is for an Assignment or a Course, a participant type is determined between an AssignmentParticipant or a CourseParticipant and an entry is made into the database accordingly.

Path: POST /participants/:model/:id

Parameters:

 #  Parameter Expected Value
1 model One of ['Assignment', 'Course']
2 id The id of the course or assignment

Request Body:

content:
  application/json:
    schema:
      type: object
      properties:
        user:
          type: object
          properties:
          name: string
        participant:
          type: object
          properties:
            can_submit:
              type: boolean
            can_review:
              type: boolean
            can_take_quiz:
              type: boolean

Response:

Success
{
  "participant": participant,
}
status: :created

When user does not exist
{ 
  error: "User #{params[:user][:name]} does not exist" 
}
status: :not_found

When participant already exists in the assignment/course
{ 
  error: "Participant #{params[:user][:name]} already exists for this #{params[:model]}" 
}
status: :unprocessable_entity

Update Handle

Description: This endpoint allows the user to change their handle name for a given AssignmentParticipant. An AssignmentParticipant is one who is already enrolled in the assignment. A success response renders a JSON with the updated participant details. The user is required to provide a valid and available handle name.

Path: POST /participants/change_handle/:id

Parameters:

 #  Parameter Expected Value
1 id The id of the AssignmentParticipant

Request Body:

content:
  application/json:
    schema:
      type: object
      properties:
        participant:
          type: object
          properties:
          handle: 
            type: integer

Response:

When handle change was successful
{
  "participant": participant,
}
status: :ok

When handle is already in use
{ 
  note: "Handle already in use" 
}
status: :ok

Failure
{ 
  error: participant.errors
}
status: :unprocessable_entity

Update authorizations

Description: This endpoint allows the user to change the permissions for a given Participant. The appropriate permissions for any participant are [can_submit, can_review, can_take_quiz]. A Participant is one who is already enrolled in an assignment or a course. A success response renders a JSON with the updated participant details and permissions.

Path: POST /participants/update_authorizations/:id

Parameters:

 #  Parameter Expected Value
1 id The id of the Participant

Request Body:

content:
  application/json:
    schema:
      type: object
      properties:
        participant:
          type: object
          properties:
            can_submit:
              type: boolean
            can_review:
              type: boolean
            can_take_quiz:
              type: boolean

Response:

Success
{
  "participant": participant,
}
status: :ok

Failure
{ 
  error: participant.errors
}
status: :unprocessable_entity

Delete

Description: This endpoint allows the user to delete an existing participant from an assignment or a course. The user is expected to provide the valid participant ID. The participant is only deleted if they are not part of another team for a different assignment/course. This is to ensure that a participant enrolled in two different teams is not deleted from the list of participants. Deletion is only possible if the participant is only enrolled in only one team. A success response renders a JSON with a confirmation of the deletion.

Path: DELETE /participants/:id

Parameters:

 #  Parameter Expected Value
1 id The id of the Participant

Response:

Success
{
  message: "#{participant.user.name} was successfully removed as a participant"
}
status: :ok

When the participant is on another team
{ 
  error: "This participant is on a team" 
}
status: :unprocessable_entity

Failure
{ 
  error: "Failed to remove participant" 
}
status: :unprocessable_entity

Inherit

Description: This endpoint allows the user to copy the existing participants from a course to the provided assignment in a single operation. Before this is carried out, validations are performed on 1) the existence of a course for the provided assignment and 2) non-empty list of participants already registered in the course. After these checks, the participants are copied from the course to the given assignment with the help of a private method copy_participants_from_source_to_target. A success response renders a JSON with a confirmation of the copy.

Path: GET /participants/inherit/:id

Parameters:

 #  Parameter Expected Value
1 id The id of the Assignment

Response:

When copy was successful
{
  message: "The participants from #{source.name} were copied to #{target.name}"
}
status: :created

When all the participants already existed in the assignment(no-op)
{
  note: "All of #{source.name} participants are already in #{target.name}"
}
status: :ok

When there were no participants for the course
{
  note: "No participants were found for this #{source.name}"
}
status: :ok

When there is no course for the given assignment
{ 
  error: "No course was found for this assignment"
}
status: :unprocessable_entity

Bequeath

Description: This endpoint allows the user to copy the existing participants from the provided assignment to its associated course in a single operation. Before this is carried out, validations are performed on 1) the existence of a course for the provided assignment and 2) non-empty list of participants already registered in the assignment. After these checks, the participants are copied from the given assignment to its course with the help of a private method copy_participants_from_source_to_target. A success response renders a JSON with a confirmation of the copy.

Path: GET /participants/bequeath/:id

Parameters:

 #  Parameter Expected Value
1 id The id of the Assignment

Response:

When copy was successful
{
  message: "The participants from #{source.name} were copied to #{target.name}"
}
status: :created

When all the participants already existed in the course(no-op)
{
  note: "All of #{source.name} participants are already in #{target.name}"
}
status: :ok

When there were no participants for the assignment
{
  note: "No participants were found for this #{source.name}"
}
status: :ok

When there is no course for the given assignment
{ 
  error: "No course was found for this assignment"
}
status: :unprocessable_entity

Test Plan

The testing framework is RSpec. The participants_controller.rb has dependencies on models and methods which are yet to be implemented. In the meantime, to test the API, we have used stubs and mocks. We have created some new models and added some associations in them which were required for stubbing.

To run the tests: 1. git clone https://github.com/devashish-vachhani/reimplementation-back-end 2. cd reimplementation-back-end/ 3. bundle install 4. bundle exec rspec spec/requests/api/v1/participants_spec.rb

Tests

Test ID Test Description
1 Test to check index with Assignment model and id - Lists Participants
2 Test to check index with Assignment model and id - Invalid Parameters
3 Test to create a new participant - With non existing User
4 Test to create a new participant - When participant already exists
5 Test to create a new participant - Successful creation of participant
6 Test to update handle request for a participant - When handle name already exists
7 Test to update handle request for a participant - Successful update of participant handle
8 Test to update handle request for a participant - Failed update of participant handle
9 Test to update authorizations request for a participant - Successful update of authorizations of a participant
10 Test to update authorizations request for a participant - Failed update of authorizations of a participant
11 Test to inherit participants from a Course to an Assignment - Failure in inherit because Assignment has no Course
12 Test to inherit participants from a Course to an Assignment - Failure for when there are no participants to inherit
13 Test to inherit participants from a Course to an Assignment - Checks if participants in Assignment is already in Course
14 Test to inherit participants from a Course to an Assignment - Successful inherit from Course to Assignment
15 Test to bequeath participants from an Assignment to a Course - Failure in bequeath because Course has no Assignment
16 Test to bequeath participants from an Assignment to a Course - Failure for when there are no participants to inherit
17 Test to bequeath participants from an Assignment to a Course - Checks if participants in Course is already in Assignment
18 Test to bequeath participants from an Assignment to a Course - Successful inherit from Course to Assignment
19 Test to destroy participant - Failure as participant to be deleted is on a team
20 Test to destroy participant - Successful deletion of a participant
21 Test to destroy participant - Failure if there is an error in "participant.destroy"

Test Screenshot

Swagger UI Screenshot

Contributors

  1. Saksham Pandey (spandey5@ncsu.edu)
  2. Devashish Vachhani (dvachha@ncsu.edu)
  3. Karthik K Jayakumar (kkunnum@ncsu.edu)

Mentor: Rucha Kolekar (rbkoleka@ncsu.edu)

Relevant Links