refactor duplicated code #20

Open
opened 2025-04-15 07:00:34 +00:00 by douzeb · 4 comments
Owner

There are several duplicated pieces of code that need to be factorized into shared functions.
For example the retrieval of the number of invitations of a user.

There are several duplicated pieces of code that need to be factorized into shared functions. For example the retrieval of the number of invitations of a user.
Author
Owner

analysis of teams_pages.rs by cursor :





Okay, I've analyzed the code in `src/controllers/teams_pages.rs` and found several areas with duplicated logic:

1.  **Authentication Check:** Almost every handler function starts with the same block to check if the user is authenticated via `JWTWithUserOpt` and redirects to `/auth/login` if not. This pattern is repeated extensively.
    ```rust
    let user = if let Some(user) = auth.user {
        user
    } else {
        return redirect("/auth/login", headers);
    };
    ```

2.  **Fetching Pending Invitation Count:** The logic to query the database for the count of pending invitations for the current user is duplicated in `create_team_page`, `list_teams`, `team_details`, `invite_member_page`, and `edit_team_page`.
    ```rust
    // Get pending invitations count
    let invitations_result = team_memberships::Entity::find()
        .find_with_related(teams::Entity)
        .all(&ctx.db)
        .await;

    let invitations = match invitations_result {
        Ok(data) => data
            .into_iter()
            .filter(|(membership, _)| membership.user_id == user.id && membership.pending)
            .count(),
        Err(e) => {
            // ... error handling ...
        }
    };
    ```

3.  **Finding Team by PID:** Many handlers need to find a `teams::Model` using its `pid`. The pattern of calling `teams::Model::find_by_pid` and handling the `Result` (often returning `error_page` or `error_fragment` on failure) is repeated in functions like `team_details`, `invite_member_page`, `edit_team_page`, `update_team_handler`, `cancel_invitation`, `update_member_role`, `remove_member`, `delete_team`, and `invite_member_handler`.

4.  **Permission Checks (Admin/Owner):** Several handlers check if the current user has an "Administrator" or "Owner" role within a specific team. This involves fetching the user's `team_memberships` record for that team and checking the `role` field. While the exact role being checked might vary, the pattern of querying and checking is similar across `team_details`, `invite_member_page`, `edit_team_page`, `update_team_handler`, `cancel_invitation`, `update_member_role`, `remove_member`. The `has_role` method on `teams::Model` is used in a few places (`delete_team`, `invite_member_handler`), which is a good step towards reducing this duplication, but it's not used consistently.

5.  **Finding Invitation by Token:** The logic to find a `team_memberships` record by its `invitation_token` is duplicated in `accept_invitation`, `decline_invitation`, and `cancel_invitation`.

6.  **Finding User by PID:** The pattern to find a `users::Model` by `pid` and handle errors appears in `update_member_role` and `remove_member`.

7.  **Fetching Specific Membership:** Querying the `team_memberships` table to get the record for a specific `user_id` and `team_id` is a common operation, often done as part of permission checks (see point 4) but also standalone in places like `team_details`.

These duplicated blocks could potentially be refactored into helper functions or middleware to improve maintainability and reduce redundancy.

analysis of teams_pages.rs by cursor : ``` Okay, I've analyzed the code in `src/controllers/teams_pages.rs` and found several areas with duplicated logic: 1. **Authentication Check:** Almost every handler function starts with the same block to check if the user is authenticated via `JWTWithUserOpt` and redirects to `/auth/login` if not. This pattern is repeated extensively. ```rust let user = if let Some(user) = auth.user { user } else { return redirect("/auth/login", headers); }; ``` 2. **Fetching Pending Invitation Count:** The logic to query the database for the count of pending invitations for the current user is duplicated in `create_team_page`, `list_teams`, `team_details`, `invite_member_page`, and `edit_team_page`. ```rust // Get pending invitations count let invitations_result = team_memberships::Entity::find() .find_with_related(teams::Entity) .all(&ctx.db) .await; let invitations = match invitations_result { Ok(data) => data .into_iter() .filter(|(membership, _)| membership.user_id == user.id && membership.pending) .count(), Err(e) => { // ... error handling ... } }; ``` 3. **Finding Team by PID:** Many handlers need to find a `teams::Model` using its `pid`. The pattern of calling `teams::Model::find_by_pid` and handling the `Result` (often returning `error_page` or `error_fragment` on failure) is repeated in functions like `team_details`, `invite_member_page`, `edit_team_page`, `update_team_handler`, `cancel_invitation`, `update_member_role`, `remove_member`, `delete_team`, and `invite_member_handler`. 4. **Permission Checks (Admin/Owner):** Several handlers check if the current user has an "Administrator" or "Owner" role within a specific team. This involves fetching the user's `team_memberships` record for that team and checking the `role` field. While the exact role being checked might vary, the pattern of querying and checking is similar across `team_details`, `invite_member_page`, `edit_team_page`, `update_team_handler`, `cancel_invitation`, `update_member_role`, `remove_member`. The `has_role` method on `teams::Model` is used in a few places (`delete_team`, `invite_member_handler`), which is a good step towards reducing this duplication, but it's not used consistently. 5. **Finding Invitation by Token:** The logic to find a `team_memberships` record by its `invitation_token` is duplicated in `accept_invitation`, `decline_invitation`, and `cancel_invitation`. 6. **Finding User by PID:** The pattern to find a `users::Model` by `pid` and handle errors appears in `update_member_role` and `remove_member`. 7. **Fetching Specific Membership:** Querying the `team_memberships` table to get the record for a specific `user_id` and `team_id` is a common operation, often done as part of permission checks (see point 4) but also standalone in places like `team_details`. These duplicated blocks could potentially be refactored into helper functions or middleware to improve maintainability and reduce redundancy. ```
Author
Owner

prompt to refactor the code used to build base layout template parameters with RA.AID :

we need to refactor the code of the html controllers ( src/controllers/*_pages.rs ) that is building the parameters for the layout.html that is the base tera template that is extended byt most of the pages of the application. Currently, each controller handler has its own code to build the parameters of this base template. Which means there is a lot of duplicated code. Also the code is not consistent among all handlers. Some new parameters of the base layout, related to the recent new feature of the administration page, are not implemented everywhere. 
The code that is building these parameters should be factorized into the users model to minimize code duplication and ensure all controller handlers call the same implementation. Care must be taken to keep the code factorized in the users model independent of html views. This code will later also be shared with API controllers and other processes.

Resultat : Après 3 heures, et plus de 30€ de crédits d'API Gemini dépensés, l'agent déclare qu'il à fini mais il y a plus de 500 erreurs de build qui restent a corriger. (heureusement que c'etait des crédits gratuits offerts par Google)

prompt to refactor the code used to build base layout template parameters with RA.AID : ``` we need to refactor the code of the html controllers ( src/controllers/*_pages.rs ) that is building the parameters for the layout.html that is the base tera template that is extended byt most of the pages of the application. Currently, each controller handler has its own code to build the parameters of this base template. Which means there is a lot of duplicated code. Also the code is not consistent among all handlers. Some new parameters of the base layout, related to the recent new feature of the administration page, are not implemented everywhere. The code that is building these parameters should be factorized into the users model to minimize code duplication and ensure all controller handlers call the same implementation. Care must be taken to keep the code factorized in the users model independent of html views. This code will later also be shared with API controllers and other processes. ``` Resultat : Après 3 heures, et plus de 30€ de crédits d'API Gemini dépensés, l'agent déclare qu'il à fini mais il y a plus de 500 erreurs de build qui restent a corriger. (heureusement que c'etait des crédits gratuits offerts par Google)
Author
Owner

version du prompt pour Cursor :

we need to refactor the parts of code of the html controllers ( src/controllers/*_pages.rs ) that are building the parameters for @layout.html that is the base tera template that is extended by the templates user to render most of the pages of the application (all the authenticated pages).
Currently, each controller handler has its own code to build these parameters of this base template.
Which means there is a lot of duplicated code. Also the implementations are not consistent among all handlers. Some new parameters of the base layout, related to the recent new feature of the administration page, are not implemented everywhere. 
The code that is building these parameters should be factorized into the users model to minimize code duplication and ensure all controller handlers call the same implementation. Care must be taken to keep the code factorized in the users model independent of html views. This code will later also be shared with API controllers and other backround processes.

Resultat : Après pas mal de temps et 4 crédits Cursor utilisé, l'agent à encore plus de 200 erreurs de build a corriger. Moins pire que RA.AID, mais => poubelle quand même)

version du prompt pour Cursor : ``` we need to refactor the parts of code of the html controllers ( src/controllers/*_pages.rs ) that are building the parameters for @layout.html that is the base tera template that is extended by the templates user to render most of the pages of the application (all the authenticated pages). Currently, each controller handler has its own code to build these parameters of this base template. Which means there is a lot of duplicated code. Also the implementations are not consistent among all handlers. Some new parameters of the base layout, related to the recent new feature of the administration page, are not implemented everywhere. The code that is building these parameters should be factorized into the users model to minimize code duplication and ensure all controller handlers call the same implementation. Care must be taken to keep the code factorized in the users model independent of html views. This code will later also be shared with API controllers and other backround processes. ``` Resultat : Après pas mal de temps et 4 crédits Cursor utilisé, l'agent à encore plus de 200 erreurs de build a corriger. Moins pire que RA.AID, mais => poubelle quand même)
Author
Owner

implemented that part manually

implemented that part manually
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
NixiN/hosting-farm#20
No description provided.