CSC/ECE 517 Fall 2022 - E2252. Refactor auth controller.rb & password retrieval controller.rb: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
m (Added descriptions of each section to guide group members when contributing)
 
(31 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== Overview of Expertiza ==
== Overview of Expertiza ==
TODO: Add description of general expertiza system and how our controllers relate to the overall functionality.
Expertiza is an open source software written using Ruby on Rails which functions as a learning management software system. It has man different functions and abilities including the ability to create assignments, quizzes, assignment groups and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. Part of its functionality is a system for user authentication with different user roles and permissions that determine how each user interacts with the content. The <code>auth_controller.rb</code> and <code>password_retrieval_controller.rb</code> which are the files primarily addressed in this project are both critical controllers in providing this functionality.
== Description of Project ==
== Description of Project ==
TODO: Describe the objectives of the project and what issues we were attempting to address.
<code>auth_controller</code> is used for authentication purposes. The controller completes a variety of tasks including handling the correct user logins, incorrect passwords, unknown users, and making sure the session and role information is updated at all points in that process. The original problem description listed three issues, two of which had since been corrected by other code changes since the document was written. The remaining problem was that some logger messages were included in methods that could be placed more cleanly in <code>before_action</code> methods. Also, I personally noticed that there was a few lines of repeated code involved in resetting the role cache that needed to be combined into a shared private method.
 
The <code>password_retrieval_controller</code> deals with the process of updating and resetting a user password. The <code>send_password</code> method generates a token and appends it to a password reset URL. If a user submits a valid email address on the <code>password_retrieval/forgotten</code> view, the URL is sent to the user's email. When a user goes to the password reset URL, the token parameter is decrypted and checked for expiration. Next, the <code>password_retrieval/reset_password</code> view is loaded where a user enters an updated password and is sent back to the home page. In this project, the method was refactored in the following ways: to adhere to DRY principles, removal of hardwired constants, renaming of methods and variables, and enhanced comments. In addition, RSpec testing coverage of the controller was improved from 63.33% to 91.8% through a series of new tests that validate the functionality of the <code>update_password</code> and <code>send_password</code> methods.
 
== Files Modified ==
== Files Modified ==
TODO: List all files that were modified and the changes made to them. Include what principle was violated/what the problem was and how the change fixed it.
=== Changes to <code>app/controllers/password_retrieval_controller.rb</code> ===
{| class="wikitable" style="width: 100%;
! &nbsp;#&nbsp; !! Change !! Rationale !! Commit Link
|-
|1
|Updated <code>check_reset_url</code> method name to <code>check_token_validity</code>
|The method validates that the password reset token is valid and present. The updated method name provides a more functionally descriptive name.
|[https://github.com/expertiza/expertiza/commit/3f9f63ab51e90743dfab0b860574aa9b673f2717 Commit]
|-
|2
|style="width: 30%"| Replaced repeated code in lines 35-36 and 62-63
|The use of repeated code violates the DRY principle and so it was moved to a new method.
|[https://github.com/expertiza/expertiza/commit/5429abd6fcb39f7bdbb0aaa1813f19c8101d7e25 Commit]
|-
|3
|Change token expiration time to constant in line 41
|This time should not be hardwired; it should be a constant or a parameter.
|[https://github.com/expertiza/expertiza/commit/3f0b51f6f2f106df8338483396a95d4068e39c7f Commit]
|-
|4
|Bugfix: Reload page if email is nil or empty on <code>password_retrieval/forgotten</code> view
|An empty email parameter was causing the send password button to freeze. This was beyond the scope of our work but we wanted to improve the page functionality.
|[https://github.com/expertiza/expertiza/commit/70f77ac851b234f840709859dc1ee9d6725c34fc Commit]
|-
|5
|Improve overall comments and rewrite error messages
|The comments and error messages in the controller need to be more meaningful, specific and clear.
|[https://github.com/expertiza/expertiza/commit/1af745dc3b59641cb0266ebe49ee996718381fd0 Commit]
|}
 
=== Changes to <code>spec/controllers/password_retrieval_controller_spec.rb</code> ===
{| class="wikitable" style="width: 100%;
! &nbsp;#&nbsp; !! Change !! Rationale !! Commit Link
|-
|1
|Added two new RSpec tests for the <code>update_password</code> method
|There were no tests for the <code>update_password</code> method. We wanted to enhance the test suite of this controller by increasing the coverage of its Rspec tests.
|[https://github.com/expertiza/expertiza/commit/a90b1aada9878c7cdf7319dd022432cca8eadd2f Commit]
|-
|2
|Added two new RSpec tests for the <code>send_password</code> method to check nil or blank input for email
|There were no tests for the <code>send_password</code> method pertaining to checking invalid inputs in the request params
|[https://github.com/greyfiles/expertiza/commit/1d2d2d94ef730ab427bb326049bc5ec800a0dfc9 Commit]<br>[https://github.com/greyfiles/expertiza/commit/781d6f42ca37829e0e514de8bcef1c85b2a035a2 Commit]
|-
|3
|Added <code>User</code> and <code>PasswordReset</code> factories and removed hardcoded variables
|Cleaned up hardcoded <code>User</code> and <code>PasswordReset</code> models with premade factories to improve readability of the code
|[https://github.com/expertiza/expertiza/commit/e946533235846a853ee42908b15e75d628552f9e Commit]<br>[https://github.com/expertiza/expertiza/commit/96376e0b633e6b6e08d472a4cb4600d20e0c024f Commit]
|-
|}
 
=== Changes to <code>spec/factories/password_retrieval_factory.rb</code> ===
{| class="wikitable" style="width: 100%;
! &nbsp;#&nbsp; !! Change !! Rationale !! Commit Link
|-
|1
|Created a file to host the <code>password_retrieval_controller_spec.rb</code> fixtures
|We implemented factories in the rspec test file to improve modularity and code readability.
|[https://github.com/expertiza/expertiza/commit/e946533235846a853ee42908b15e75d628552f9e Commit]
|-
|}
 
=== Changes to <code>config/routes.rb</code> ===
{| class="wikitable" style="width: 100%;
! &nbsp;#&nbsp; !! Change !! Rationale !! Commit Link
|-
|1
|Updated URL path and controller action to updated method name <code>check_token_validity</code>
|The action and URL path must be renamed to generate pathing to the controller method and views.
|[https://github.com/expertiza/expertiza/commit/3f9f63ab51e90743dfab0b860574aa9b673f2717 Commit]
|-
|}
 
=== Changes to <code>app/controllers/auth_controller.rb</code> ===
{| class="wikitable" style="width: 100%;
! &nbsp;#&nbsp; !! Change !! Rationale !! Commit Link
|-
|1
|Move logger messages to <code>before_action</code> blocks wherever possible
|Logger messages are inserted to log important events occurring in the code and do not relate directly to the logic. When possible, moving them to either <code>before_action</code> or <code>after_action</code> blocks makes the code more readable and easier to understand. It also separates the functionality of the method itself and the logging functionality.
|[https://github.com/greyfiles/expertiza/commit/7069f5d3cbfa2b7259e85e39dbfbf6fb41a0ce1d Commit]
|-
|2
|*Not in required chagnes* Replaced repeated code for re-caching the user role
|We noticed that although not listed on the recommended changes, this action involved exactly repeated code in the controller. The use of repeated code violates the DRY principle and so it was moved to a new method called <code>self.rebuild_role_cache</code>.
|[https://github.com/greyfiles/expertiza/commit/9ef20cffa0fe7b8440b97856a6db4b5351eece35 Commit]
|-
|3
|Improved helper function names
|Originally we made the new helper functions used in logging have unhelpful, confusing names. Making them more clear helps the code to be more understandable.
|[https://github.com/greyfiles/expertiza/commit/32f8435255add7b44b38fd747f81f435d331d14d Commit]
|}
 
=== Changes to <code>spec/controllers/auth_controller_spec.rb</code> ===
{| class="wikitable" style="width: 100%;
! &nbsp;#&nbsp; !! Change !! Rationale !! Commit Link
|-
|1
|Improved existing tests for <code>after_login</code> to explicitly test for a redirect
|When looking over the existing test cases, I noticed that the test that was verifying that the <code>after_login</code> method would redirect the user only "allowed" the redirect and did not "expect" it. I changed it to "expect" the redirect to ensure that functionality is working.
|[https://github.com/greyfiles/expertiza/commit/23b3eaa888810f93a4af18c2ca6904ab21580a4b Commit]
|-
|2
|Added a test for <code>set_current_role</code> when the role is found to make sure it rebuilds the role cache
|In the unit tests for the <code>set_current_role</code> method, my new addition of a private helper method allowed us to ensure that the role cache was being rebuilt when the current role was set.
|[https://github.com/greyfiles/expertiza/commit/23b3eaa888810f93a4af18c2ca6904ab21580a4b Commit]
|-
|3
|Added a test for <code>clear_user_info</code> to make sure it rebuilds the role cache
|In the unit tests for the <code>clear_user_info</code> method, my new addition of a private helper method allowed us to ensure that the role cache was being rebuilt when the user's info was cleared.
|[https://github.com/greyfiles/expertiza/commit/23b3eaa888810f93a4af18c2ca6904ab21580a4b Commit]
|}
 
== Testing ==
== Testing ==
TODO: Show how the existing testing suite was passing before and after our refactoring - preserving functionality.
 
'''Everything in the testing segment was beyond the scope of our work. However, we wanted to validate our code through RSpec testing before merging into the <code>main</code> Expertiza branch. In the second submission phase, we plan to further enhance the testing suite of the <code>auth_controller.rb</code> and <code>password_retrieval_controller.rb</code> through factories and fixtures.'''
 
=== Test Plan - Manual/System Test Cases ===
Along with the unit tests that we have written to test our files, we conducted a few system tests manually to verify the functionality works as expected. The <code>password_retrieval_controller.rb</code> is difficult for us to test because we don't have access to the email used to make the sample account, but the <code>auth_controller.rb</code> is very testable. Below is the tests we completed listed in the order of completion.
 
==== 1) Test instructor login & redirect to home page ====
When navigating to the expertiza website, our branch correctly displayed the login page as shown below.
[[File:before_login.png|center|border|Form shown to the user before logging in to expertiza]]
After typing in the sample login credentials of "instructor6" and "password," the user is then correctly logged in and redirected to the home page for instructors shown below.
[[File:after_login.png|center|border|1400px|Page shown to the user after logging in to expertiza]]
==== 2) Test instructor logout & redirect to login page ====
Then, when the user clicks the logout button, they are correctly logged out and redirected once again to the login page as shown below.
[[File:after_logout.png|center|border|Form shown to the user after logging out of expertiza]]
==== 3) Test incorrect login ====
When the user attempts to login but enters the incorrect login information of "instructor6" and "incorrect," the user is shown the error message and then correctly redirected to the forgot password page shown below.
[[File:after_incorrect_login.png|center|border|1400px|Form shown to the user after an incorrect login attempt to expertiza]]
 
 
=== Automated Testing of <code>auth_controller_.rb</code> ===
Before any refactoring to <code>auth_controller.rb</code> was done, we ran the rspec tests created for the controller with the following command: <code>rspec spec/controllers/auth_controller_spec.rb</code>
 
[[File:before_refactor_auth_controller.png|center|frame|rspec tests all passing before the refactoring was completed]]
 
After making all of the above changes to <code>auth_controller.rb</code>, we ran the rspec tests for the controller again with the command: <code>rspec spec/controllers/auth_controller_spec.rb</code>
 
[[File:after_refactor_auth_controller.png|center|frame|rspec tests continuing to all pass after completing the refactoring]]
 
We have successfully preserved the passing tests after the improvements we made to the <code>auth_controller.rb</code>. Next we looked at the existing tests to see if they could be improved. As listed in the files changed above, there were a few improvements to be made to <code>auth_controller_spec.rb</code>. We improved a check for redirecting the user after logging in and added two tests to make sure the role cache was being rebuilt after both setting the current role and clearing the user info. We ran the tests again with the command: <code>rspec spec/controllers/auth_controller_spec.rb</code>
 
[[File:after_improving_auth_controller_spec.png|center|frame|rspec tests continuing to all pass after improving and adding to the auth_controller tests]]
 
Tests prior to the changes covered 91.94% of <code>auth_controller.rb</code>.
[[File:coverage_before.png|center|frame|rspec test coverage report before the improvements to the auth_controller unit tests]]
 
This is already a good coverage but after my changes I wanted to ensure my changes were also tested thoroughly. After adding tests, the tests covered 95.24% of <code>auth_controller.rb</code>. It improved slightly to be an even better coverage.
[[File:coverage_after.png|center|frame|rspec test coverage report after the improvements to the auth_controller unit tests]]
 
=== Automated Testing of <code>password_retrieval_controller.rb</code> ===
Before any refactoring to <code>passsword_retrieval_controller.rb</code> was done, we ran the rspec tests created for the controller with the following command: <code>rspec spec/controllers/password_retrieval_controller_spec.rb</code>
 
[[File:before_refactor_password_retrieval_controller.png|center|frame|rspec tests all passing before the refactoring was completed]]
 
Tests prior to the changes covered 63.3% of <code>password_retrieval_controller.rb</code>.
[[File:E2252_password_retrieval_coverage_report_before.png|center|frame|rspec test coverage report before the refactoring was completed]]
 
After adding tests, the tests covered 91.1% of <code>password_retrieval_controller.rb</code>.
[[File:E2252_password_retrieval_coverage_report_after.png|center|frame|rspec test coverage report after the refactoring was completed]]
 
We implemented factories in the rspec test file to improve modularity and code readability. Factories provide more flexibility in generating models to meet the requirements of the test, as opposed to fixtures. As you can see from the below images, the code is significantly cleaner as many lines of hardcoded strings have been removed.
[[File:prefactory.png|center|frame|rspec tests before factories were implemented]] <br>
[[File:postfactory.png|center|frame|rspec tests after factories were implemented]]
 
The below image shows the output of the following command after all tests were added: <code>rspec spec/controllers/password_retrieval_controller_spec.rb</code>
 
[[File:After refactor password retrieval controller.png|center|frame|rspec tests all passing after the refactoring was completed]]
 
== Relevant Links ==
* '''Github Repository:''' https://github.com/greyfiles/expertiza
* '''Pull Request:''' https://github.com/expertiza/expertiza/pull/2460
* '''VCL Server:''' http://152.7.98.115:8080/
 
== Contributors to this project ==
* Grey Files (unityid: mgfiles, github: greyfiles)
* Colin O'Dowd (unityid: cdodowd, github: colin-odowd)
* Pradyumna Khawas (unityid: ppkhawas, github: therealppk)

Latest revision as of 19:34, 1 November 2022

Overview of Expertiza

Expertiza is an open source software written using Ruby on Rails which functions as a learning management software system. It has man different functions and abilities including the ability to create assignments, quizzes, assignment groups and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. Part of its functionality is a system for user authentication with different user roles and permissions that determine how each user interacts with the content. The auth_controller.rb and password_retrieval_controller.rb which are the files primarily addressed in this project are both critical controllers in providing this functionality.

Description of Project

auth_controller is used for authentication purposes. The controller completes a variety of tasks including handling the correct user logins, incorrect passwords, unknown users, and making sure the session and role information is updated at all points in that process. The original problem description listed three issues, two of which had since been corrected by other code changes since the document was written. The remaining problem was that some logger messages were included in methods that could be placed more cleanly in before_action methods. Also, I personally noticed that there was a few lines of repeated code involved in resetting the role cache that needed to be combined into a shared private method.

The password_retrieval_controller deals with the process of updating and resetting a user password. The send_password method generates a token and appends it to a password reset URL. If a user submits a valid email address on the password_retrieval/forgotten view, the URL is sent to the user's email. When a user goes to the password reset URL, the token parameter is decrypted and checked for expiration. Next, the password_retrieval/reset_password view is loaded where a user enters an updated password and is sent back to the home page. In this project, the method was refactored in the following ways: to adhere to DRY principles, removal of hardwired constants, renaming of methods and variables, and enhanced comments. In addition, RSpec testing coverage of the controller was improved from 63.33% to 91.8% through a series of new tests that validate the functionality of the update_password and send_password methods.

Files Modified

Changes to app/controllers/password_retrieval_controller.rb

 #  Change Rationale Commit Link
1 Updated check_reset_url method name to check_token_validity The method validates that the password reset token is valid and present. The updated method name provides a more functionally descriptive name. Commit
2 Replaced repeated code in lines 35-36 and 62-63 The use of repeated code violates the DRY principle and so it was moved to a new method. Commit
3 Change token expiration time to constant in line 41 This time should not be hardwired; it should be a constant or a parameter. Commit
4 Bugfix: Reload page if email is nil or empty on password_retrieval/forgotten view An empty email parameter was causing the send password button to freeze. This was beyond the scope of our work but we wanted to improve the page functionality. Commit
5 Improve overall comments and rewrite error messages The comments and error messages in the controller need to be more meaningful, specific and clear. Commit

Changes to spec/controllers/password_retrieval_controller_spec.rb

 #  Change Rationale Commit Link
1 Added two new RSpec tests for the update_password method There were no tests for the update_password method. We wanted to enhance the test suite of this controller by increasing the coverage of its Rspec tests. Commit
2 Added two new RSpec tests for the send_password method to check nil or blank input for email There were no tests for the send_password method pertaining to checking invalid inputs in the request params Commit
Commit
3 Added User and PasswordReset factories and removed hardcoded variables Cleaned up hardcoded User and PasswordReset models with premade factories to improve readability of the code Commit
Commit

Changes to spec/factories/password_retrieval_factory.rb

 #  Change Rationale Commit Link
1 Created a file to host the password_retrieval_controller_spec.rb fixtures We implemented factories in the rspec test file to improve modularity and code readability. Commit

Changes to config/routes.rb

 #  Change Rationale Commit Link
1 Updated URL path and controller action to updated method name check_token_validity The action and URL path must be renamed to generate pathing to the controller method and views. Commit

Changes to app/controllers/auth_controller.rb

 #  Change Rationale Commit Link
1 Move logger messages to before_action blocks wherever possible Logger messages are inserted to log important events occurring in the code and do not relate directly to the logic. When possible, moving them to either before_action or after_action blocks makes the code more readable and easier to understand. It also separates the functionality of the method itself and the logging functionality. Commit
2 *Not in required chagnes* Replaced repeated code for re-caching the user role We noticed that although not listed on the recommended changes, this action involved exactly repeated code in the controller. The use of repeated code violates the DRY principle and so it was moved to a new method called self.rebuild_role_cache. Commit
3 Improved helper function names Originally we made the new helper functions used in logging have unhelpful, confusing names. Making them more clear helps the code to be more understandable. Commit

Changes to spec/controllers/auth_controller_spec.rb

 #  Change Rationale Commit Link
1 Improved existing tests for after_login to explicitly test for a redirect When looking over the existing test cases, I noticed that the test that was verifying that the after_login method would redirect the user only "allowed" the redirect and did not "expect" it. I changed it to "expect" the redirect to ensure that functionality is working. Commit
2 Added a test for set_current_role when the role is found to make sure it rebuilds the role cache In the unit tests for the set_current_role method, my new addition of a private helper method allowed us to ensure that the role cache was being rebuilt when the current role was set. Commit
3 Added a test for clear_user_info to make sure it rebuilds the role cache In the unit tests for the clear_user_info method, my new addition of a private helper method allowed us to ensure that the role cache was being rebuilt when the user's info was cleared. Commit

Testing

Everything in the testing segment was beyond the scope of our work. However, we wanted to validate our code through RSpec testing before merging into the main Expertiza branch. In the second submission phase, we plan to further enhance the testing suite of the auth_controller.rb and password_retrieval_controller.rb through factories and fixtures.

Test Plan - Manual/System Test Cases

Along with the unit tests that we have written to test our files, we conducted a few system tests manually to verify the functionality works as expected. The password_retrieval_controller.rb is difficult for us to test because we don't have access to the email used to make the sample account, but the auth_controller.rb is very testable. Below is the tests we completed listed in the order of completion.

1) Test instructor login & redirect to home page

When navigating to the expertiza website, our branch correctly displayed the login page as shown below.

Form shown to the user before logging in to expertiza
Form shown to the user before logging in to expertiza

After typing in the sample login credentials of "instructor6" and "password," the user is then correctly logged in and redirected to the home page for instructors shown below.

Page shown to the user after logging in to expertiza
Page shown to the user after logging in to expertiza

2) Test instructor logout & redirect to login page

Then, when the user clicks the logout button, they are correctly logged out and redirected once again to the login page as shown below.

Form shown to the user after logging out of expertiza
Form shown to the user after logging out of expertiza

3) Test incorrect login

When the user attempts to login but enters the incorrect login information of "instructor6" and "incorrect," the user is shown the error message and then correctly redirected to the forgot password page shown below.

Form shown to the user after an incorrect login attempt to expertiza
Form shown to the user after an incorrect login attempt to expertiza


Automated Testing of auth_controller_.rb

Before any refactoring to auth_controller.rb was done, we ran the rspec tests created for the controller with the following command: rspec spec/controllers/auth_controller_spec.rb

rspec tests all passing before the refactoring was completed

After making all of the above changes to auth_controller.rb, we ran the rspec tests for the controller again with the command: rspec spec/controllers/auth_controller_spec.rb

rspec tests continuing to all pass after completing the refactoring

We have successfully preserved the passing tests after the improvements we made to the auth_controller.rb. Next we looked at the existing tests to see if they could be improved. As listed in the files changed above, there were a few improvements to be made to auth_controller_spec.rb. We improved a check for redirecting the user after logging in and added two tests to make sure the role cache was being rebuilt after both setting the current role and clearing the user info. We ran the tests again with the command: rspec spec/controllers/auth_controller_spec.rb

rspec tests continuing to all pass after improving and adding to the auth_controller tests

Tests prior to the changes covered 91.94% of auth_controller.rb.

rspec test coverage report before the improvements to the auth_controller unit tests

This is already a good coverage but after my changes I wanted to ensure my changes were also tested thoroughly. After adding tests, the tests covered 95.24% of auth_controller.rb. It improved slightly to be an even better coverage.

rspec test coverage report after the improvements to the auth_controller unit tests

Automated Testing of password_retrieval_controller.rb

Before any refactoring to passsword_retrieval_controller.rb was done, we ran the rspec tests created for the controller with the following command: rspec spec/controllers/password_retrieval_controller_spec.rb

rspec tests all passing before the refactoring was completed

Tests prior to the changes covered 63.3% of password_retrieval_controller.rb.

rspec test coverage report before the refactoring was completed

After adding tests, the tests covered 91.1% of password_retrieval_controller.rb.

rspec test coverage report after the refactoring was completed

We implemented factories in the rspec test file to improve modularity and code readability. Factories provide more flexibility in generating models to meet the requirements of the test, as opposed to fixtures. As you can see from the below images, the code is significantly cleaner as many lines of hardcoded strings have been removed.

rspec tests before factories were implemented


rspec tests after factories were implemented

The below image shows the output of the following command after all tests were added: rspec spec/controllers/password_retrieval_controller_spec.rb

rspec tests all passing after the refactoring was completed

Relevant Links

Contributors to this project

  • Grey Files (unityid: mgfiles, github: greyfiles)
  • Colin O'Dowd (unityid: cdodowd, github: colin-odowd)
  • Pradyumna Khawas (unityid: ppkhawas, github: therealppk)