CSC/ECE 517 Spring 2023 - E2331. Reimplement Account Request module
Project Overview
Background
In Expertiza, Account Creation can only be done by Admins and Super Admins. So, new users first request an account by clicking "Request Account" button on home page and filling out an account request form. After the user submits this form, the Admin or Super Admin is notified of the request and then he can decide to Accept or Reject such requests. If he accepts, then an email with new login details is sent to that user.
The Account Request module is responsible for performing all these functions. In this project, we aim to write RESTful endpoints for the Account Request module CRUD operations along with adding the corresponding controllers and model files. We also add a few other non CRUD custom actions to the controller files which are required for the app to function normally. And, we also aim to write tests for the corresponding model and controller files.
Objectives
1. Write RESTful endpoints of create, show, index, update, destroy to simulate creating and approving new user accounts, listing pending account requests, listing already approved or rejected requests, creating a new account request, and notifying super-admins about new account requests.
2. Add non CRUD custom actions like account_request_params, create_approved_user to support the above RESTful endpoints.
3. Return proper status codes and proper validation for RESTful endpoints.
4. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.
5. Write proper Rspec tests for all APIs, models, controllers.
6. Implement simple Authorization for Swagger simply using session variables instead of complex code.
Team Members
Kaushik Jadhav (unity_id: kajadhav, github: kaushikjadhav01)
Aditi Vakeel (unity_id: avakeel, github: aditi-v79)
Shivesh Madan Nath Jha (unity_id: sjha7, github: ShiveshJha12)
Mentor
Ankur Mundra (unity_id: amundra, github: amundra)
Relevant Links
Github Repository: https://github.com/CSC-517-Spr23-kajadhav-avakeel-sjha7/reimplementation-back-end
Pull Request: https://github.com/expertiza/reimplementation-back-end/pull/29
VCL Server: http://152.7.178.99:3000/
VCL Swagger UI: http://152.7.178.99:3000/api-docs/
Video: https://www.youtube.com/watch?v=pH1opJ1cArc
Files Modified
- app/controllers/api/v1/account_requests_controller.rb
- app/controllers/api/v1/institutions_controller.rb
- app/models/account_request.rb
- config/routes.rb
- db/migrate/20230412013301_create_account_requests.rb
- db/migrate/20230412013310_add_keys_to_account_requests.rb
- spec/models/account_request_spec.rb
- spec/requests/api/v1/account_requests_spec.rb
- spec/requests/api/v1/institution_spec.rb
- spec/requests/api/v1/roles_spec.rb
- swagger/v1/swagger.yaml
Implementation
UML Diagram
Functionality
In this project, we aim to add the following functions:
1. Enable users to create a new Account Request.
2. Enable admins to create a new Account Request.
3. Enable admin to list pending requested accounts.
4. Enable admins to Accept or Reject Account Requests.
5. Enable admins to list previously accepted or rejected account requests.
6. Ensure that data is validated properly in all the above APIs.
7. For Authorization with swagger APIs, we use simply the session variable instead of using extra gems. Check account_requests_controller and users_controller for better understanding.
8. Test cases for all the above.
Controllers
We create a new controller at app/controllers/account_request_controller.rb
with following methods:
Method: index
This method gives a list of all pending account requests or historic, that is previously approved or rejected account requests to Admin or Super Admin.
Method: create
This method allows any user or admin to create a new Account Request. On successful submission, admins are notified.
Method: show
This method enables Admin or Super Admin to view a specific Account Request
Method: update
This method enables Admin or Super Admin to Accept or Reject single or multiple Account Requests simultaneously. If accepted and if the account is not duplicate, the new account is generated for the user and the user is sent an email with the login credentials.
Method: destroy
This method enables Admin or Super Admin to delete a specific Account Request
Method: create_approved_user
If the Account Request is Approved, create a new user if all fields are valid and return it. If any invalid fields present, return error containing it's message.
Method: account_request_params
The params in a controller looks like a Hash, but it's actually an instance of ActionController::Parameters, which provides several methods such as require and permit. The require method ensures that a specific parameter is present, and if it's not provided, the require method throws an error. It returns an instance of ActionController::Parameters for the key passed into require. The permit method returns a copy of the parameters object, returning only the permitted keys and values. When creating a new ActiveRecord model, only the permitted attributes are passed into the model.
Models
We create a new model class AccountRequest
at app/models/account_request.rb
and add validations to all input fields as shown below. For more details, check UML diagram above:
API documentation
Swagger UI screenshot
VCL Swagger URL: http://152.7.178.99:3000/api-docs/
IMPORTANT NOTE: ALL APIs other than POST /account_request
are auth protected. So, on swagger you will first need to sign up as an Administrator using POST /users
API before running such auth protected APIs. Refer testing video below for more insights.
# | Method | Endpoint | Description |
---|---|---|---|
1 | pending_request | GET /pending_request
|
returns a list of pending account requests |
2 | processed_request | GET /processed_request
|
returns previously accepted or rejected account requests |
3 | create | POST /account_request
|
creates a new account request |
4 | show | GET /account_request/:id
|
retreive a specific account request |
5 | update | PATCH /account_request/:id
|
accept or reject an account request |
6 | delete | DELETE /account_request/:id
|
delete a specific account request |
Pending Request
Description: This endpoint gives a list of all pending account requests. A success response renders a JSON with all pending account requests.
Path: GET /pending_request
Response:
Success [ { "id": 1, "name": "userone", "fullname": "User One", "email": "u1@gmail.com", "status": "Under Review", "self_introduction": "I'm an MCS student, request to add my Student account", "created_at": "2023-04-12T19:04:34.769Z", "updated_at": "2023-04-12T19:04:34.769Z", "role_id": 2, "institution_id": 1 }, { "id": 2, "name": "usertwo", "fullname": "User Two", "email": "u2@gmail.com", "status": "Under Review", "self_introduction": "U2's intro", "created_at": "2023-04-12T16:21:28.549Z", "updated_at": "2023-04-12T16:21:28.549Z", "role_id": 2, "institution_id": 1 } ] status: :ok Failure { error: @account_requests.errors } status: :unprocessable_entity
Processed Request
Description: This endpoint gives a list of all previously approved or rejected account requests.
Path: GET /processed_request
Response:
Success [ { "id": 1, "name": "userone", "fullname": "User One", "email": "u1@gmail.com", "status": "Approved", "self_introduction": "I'm an MCS student, request to add my Student account", "created_at": "2023-04-12T19:04:34.769Z", "updated_at": "2023-04-12T19:04:34.769Z", "role_id": 2, "institution_id": 1 }, { "id": 2, "name": "usertwo", "fullname": "User Two", "email": "u2@gmail.com", "status": "Rejcted", "self_introduction": "U2's intro", "created_at": "2023-04-12T16:21:28.549Z", "updated_at": "2023-04-12T16:21:28.549Z", "role_id": 2, "institution_id": 1 } ] status: :ok Failure { error: @account_requests.errors } status: :unprocessable_entity
Create
Description: This endpoint enables any user to create a new account request.
Path: POST /account_request
Request Body:
{ "name": "userthree", "fullname": "User Three", "email": "u3@gmail.com", "self_introduction": "U3 intro", "role_id": 2, "institution_id": 1 }
Response:
Success { "id": 3, "name": "userthree", "fullname": "User Three", "email": "u3@gmail.com", "status": "Under Review", "self_introduction": "U3 intro", "created_at": "2023-04-12T23:54:59.635Z", "updated_at": "2023-04-12T23:54:59.635Z", "role_id": 2, "institution_id": 1 } status: :ok Failure { error: @account_request.errors } status: :unprocessable_entity
Show
Description: This endpoint enables Admin or Super Admin to view a specific Account Request.
Path: GET /account_request/:id
Response:
Success { "id": 1, "name": "userone", "fullname": "User One", "email": "u1@gmail.com", "status": "Under Review", "self_introduction": "I'm an MCS student, request to add my Student account", "created_at": "2023-04-12T19:04:34.769Z", "updated_at": "2023-04-12T19:04:34.769Z", "role_id": 2, "institution_id": 1 } status: :ok Failure { error: @account_request.errors } status: :unprocessable_entity
Update
Description: This endpoint enables Admin or Super Admin to Accept or Reject an Account Request or even Edit it. If accepted and if the account is not duplicate, the new account is generated for the user and the user is sent an email with the login credentials.
Path: PATCH/PATCH /account_request/:id
Request Body:
{ "status": "Approved" }
Response:
Success { "msg": "Account Request Approved and User successfully created.", "user": { "id": 25, "name": "userthree", "fullname": "User Three", "email": "u3@gmail.com", "email_on_review": false, "email_on_submission": false, "email_on_review_of_review": false, "role": { "id": 2, "name": "Student" }, "parent": { "id": 19, "name": "stubbjb" }, "institution": { "id": 1, "name": "North Carolina State University" } } } status: :ok Failure { error: @new_user.errors } status: :unprocessable_entity
Delete
Description: This endpoint enables Admin or Super Admin to delete a specific Account Request.
Path: DELETE /account_request/:id
Response:
Success { "message": "Account Request deleted" } status: :ok Failure { error: @account_request.errors } status: :unprocessable_entity
Design Pattern
A design pattern is a general repeatable solution to a commonly occurring problem in software design. It is a description or template for how to solve a problem that can be used in many different situations.
During the process of refactoring methods as well as method names,Strategy Pattern was used in the implementation. The Strategy pattern is most useful when you want to provide multiple ways of processing a request, without hard-coding knowledge about those different methods into the object that handles the request.
Test Plan
The testing framework is RSpec. To test the RESTful APIs, 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/CSC-517-Spr23-kajadhav-avakeel-sjha7/reimplementation-back-end
2. cd reimplementation-back-end/
3. bundle install
4. bundle exec rspec spec/requests/api/v1/
Tests
Test ID | Test Description |
---|---|
1 | Test to list pending account requests |
2 | Test to list processed account requests |
3 | Test to create a new account request with valid parameters |
4 | Test to create a new account request with invalid or missing parameters |
5 | Test to create a account request twice |
6 | Test to create an account request whose name already exists in Users table |
7 | Test to create an account request whose email already exists in Users table |
8 | Test to Approve account request |
9 | Test to Approve account request but user with same name already exists |
10 | Test to Approve account request but user with same email already exists |
11 | Test to Reject account request |
12 | Test to check invalid status in PATCH /account_requests/:id |
13 | Test to check invalid status in PUT /account_requests/:id |
14 | Test to retrieve a specific account request with valid id |
15 | Test to retrieve a specific account request with invalid id |
16 | Test to delete a specific account request with valid id |
17 | Test to delete a specific account request with invalid id |
18 | Test to check insitituion index |
19 | Test to check insitituion show |
20 | Test to check insitituion create |
21 | Test to check insitituion update |
22 | Test to check insitituion delete |