Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/permissions #1176

Merged
merged 103 commits into from Oct 31, 2022
Merged

Feature/permissions #1176

merged 103 commits into from Oct 31, 2022

Conversation

bryan-robitaille
Copy link
Contributor

@bryan-robitaille bryan-robitaille commented Oct 25, 2022

Summary | Résumé

This PR modifies the application's access control from a Role Based architecture to an Asset Based architecture.

  • It creates multiple base rules that define user interaction with Asset Objects
  • adds the user's abilities to the authenticated session
  • verifies a user's privileges when accessing pages, and assets, and performing actions on those assets.
  • removes the UserRoles of Administrator and Program Administrator
  • provides a clean database migration from the previous Role Based architecture to the new Asset Based architecture
  • associates Users with ownership of Forms
  • renames the previous Form User to ApiUser
  • ensures permissions are applied in the correct order by applying 'priorities' to permissions sets.

Implements a new User Management Interface:

Before After
Screen Shot 2022-10-24 at 11 54 54 AM Screen Shot 2022-10-24 at 11 49 03 AM
Screen Does not Exist Screen Shot 2022-10-24 at 11 49 11 AM

Pull Request Checklist

Please complete the following items in the checklist before you request a review:

  • Have you completely tested the functionality of change introduced in this PR? Is the PR solving the problem it's meant to solve within the scope of the related issue?
  • The PR does not introduce any new issues such as failed tests, console warnings or new bugs.
  • If this PR adds a package have you ensured its licensed correctly and does not add additional security issues?
  • Is the code clean, readable and maintainable? Is it easy to understand and comprehend.
  • Does your code have adequate comprehensible comments? Do new functions have docstrings?
  • Have you modified the change log and updated any relevant documentation?
  • Is there adequate test coverage? Both unit tests and end-to-end tests where applicable?
  • If your PR is touching any UI is it accessible? Have you tested it with a screen reader? Have you tested it with automated testing tools such as axe?

bryan-robitaille and others added 30 commits September 23, 2022 09:09
…ction (#1137)

* fix: default privileges definition clashes with the interpolation function

* moved interpolation function inside getPrivilegeRulesForUser

* Use FormRecord instead of FormConfiguration in permissions

* change names to plurial in migration

Co-authored-by: Bryan Robitaille <bryan.robitaille.work@gmail.com>
@bryan-robitaille bryan-robitaille marked this pull request as ready for review October 25, 2022 19:35
Copy link
Contributor

@Moro-Code Moro-Code left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First off I want to start off by saying super super fantastic work. The amount of changes made my head spin honestly and I can't imagine it was easy to have to jump between contexts in the code base. I tried my best to be thorough in my review. I still probably missed some things. There is a lot of comments and obviously we have a limited amount of time to deliver this feature. Comments you feel can be addressed at a later date we can create issues for and resolve them that way. I'm happy to pair program on things or go over things in a meeting if there is any confusion. Fantastic work once again !


/*
This file is referenced by the useAccessControl hook so no server-side
only dependencies can be referenced in this file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good comment. Will allow us to avoid some headaches :)

export type Action = "create" | "view" | "update" | "delete";

export type Subject = InferSubjects<CASL_FormRecord | CASL_User | CASL_Privilege | CASL_Flag>;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Spacing here is a little inconsistent between lines. Furthermore there is a jumble of types, variables, classes and interfaces being defined. Better to split them for readability and have consistent spacing between logical groupings of lines of code


export type Abilities = [Action, Subject];
export type AppAbility = MongoAbility<Abilities>;
export const createAbility = (rules: RawRuleOf<AppAbility>[]) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Is there any particular reason why we have a function who's sole purpose is to call another and return its value ?

export const createAbility = (rules: RawRuleOf<AppAbility>[]) =>
createMongoAbility<AppAbility>(rules);
export class AccessControlError extends Error {}
export type Ability = MongoAbility;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Is this for convenience sake ? If so I would argue that it causes more of an inconvenience IMO. If I want to introspect the type I will be bought here and then I would need to introspect the MongoAbility type.

createMongoAbility<AppAbility>(rules);
export class AccessControlError extends Error {}
export type Ability = MongoAbility;
export type Permission = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:This seems like an interface to me

pages/admin/users.tsx Show resolved Hide resolved
<div className="mb-8">{`${t("managePermissionsFor")} ${user.name}`}</div>
<ul className="flex flex-row flex-wrap gap-8 pb-8 pl-0 list-none">
{privileges?.map((privilege) => {
const active = userPrivileges.includes(privilege.id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time one privilege is updated the whole list re-renders. It's not so much of a problem I guess considering it's a small list. Ideally the active state would be managed individually by each of the cards

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future Refactor. No designs exist for this screen, it's just a maintenance screen for now.

pages/admin/privileges.tsx Outdated Show resolved Hide resolved
@@ -1,14 +1,13 @@
import React, { useState, useEffect } from "react";
import { useTranslation } from "next-i18next";
import axios from "axios";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
// import { serverSideTranslations } from "next-i18next/serverSideTranslations";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change ? Doesn't really matter since this page is not really used. Honestly if you want to make changes here you might as well just remove the page

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will delete the file. The original commenting out was to ignore esLint's no-unused-vars.

package.json Outdated Show resolved Hide resolved
Copy link
Contributor

@Moro-Code Moro-Code left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to go now ! Amazing work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants