Skip to content

Commit

Permalink
feat: Do not automatically assign demoUsers the teamEditor role w…
Browse files Browse the repository at this point in the history
…ithin the Templates team (#3878)
  • Loading branch information
DafyddLlyr authored Oct 30, 2024
1 parent e4900c9 commit a318850
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ Feature: Database triggers

@regression @add-user-trigger
Scenario: Adding a user to Planx - with Templates team
Given the Templates team exists
Given the "Templates" team exists
When a new user is added
Then they are granted access to the Templates team
And have the teamEditor role

@regression @add-user-trigger
Scenario: Adding a user to Planx - with Templates team
Given the "Templates" team exists
Given the "Demo" team exists
When a new demoUser is added
Then they are not granted access to the Templates team

@regression @add-user-trigger
Scenario: Adding a user to Planx - without Templates team
Given the Templates team does not exist
Expand Down
42 changes: 42 additions & 0 deletions e2e/tests/api-driven/src/hasuraTriggers/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,48 @@
import { TEST_EMAIL } from "../../../ui-driven/src/helpers/globalHelpers";
import { $admin } from "../client";
import { safely } from "../globalHelpers";
import gql from "graphql-tag";

export const cleanup = async () => {
await $admin.user._destroyAll();
await $admin.team._destroyAll();
};

export async function createDemoUser(demoTeamId: number) {
const variables = {
firstName: "Test",
lastName: "Test",
email: TEST_EMAIL,
teamId: demoTeamId,
role: "demoUser",
};

const response = await safely(() =>
$admin.client.request<{ insertUsersOne: { id: number } }>(
gql`
mutation CreateAndAddUserToTeam(
$email: String!
$firstName: String!
$lastName: String!
$teamId: Int!
$role: user_roles_enum!
) {
insertUsersOne: insert_users_one(
object: {
email: $email
first_name: $firstName
last_name: $lastName
teams: { data: { role: $role, team_id: $teamId } }
}
) {
id
}
}
`,
variables,
),
);

const userId = response.insertUsersOne.id;
return userId;
}
26 changes: 20 additions & 6 deletions e2e/tests/api-driven/src/hasuraTriggers/steps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { After, Given, Then, When, World } from "@cucumber/cucumber";
import { cleanup } from "./helpers";
import { cleanup, createDemoUser } from "./helpers";
import { User } from "@opensystemslab/planx-core/types";
import { $admin } from "../client";
import assert from "assert";
Expand All @@ -8,18 +8,20 @@ import { createTeam, createUser } from "../globalHelpers";
export class CustomWorld extends World {
user!: User;
templatesTeamId!: number;
demoTeamId!: number;
}

After("@add-user-trigger", async function () {
await cleanup();
});

Given("the Templates team exists", async function (this) {
const templatesTeamId = await createTeam({ slug: "templates" });
Given("the {string} team exists", async function (this, input) {
const teamSlug = input.toLowerCase();
const teamId = await createTeam({ slug: teamSlug });

assert.ok(templatesTeamId, "Templates team is not defined");
assert.ok(teamId, `${teamSlug} team is not defined`);

this.templatesTeamId = templatesTeamId;
this[`${teamSlug}TeamId`] = teamId;
});

Given("the Templates team does not exist", async function (this) {
Expand All @@ -41,6 +43,15 @@ When<CustomWorld>("a new user is added", async function (this) {
this.user = user;
});

When<CustomWorld>("a new demoUser is added", async function (this) {
const userId = await createDemoUser(this.demoTeamId);
const demoUser = await $admin.user.getById(userId);

assert.ok(demoUser, "Demo user is not defined");

this.user = demoUser;
});

Then<CustomWorld>(
"they are granted access to the Templates team",
async function (this) {
Expand All @@ -57,6 +68,9 @@ Then<CustomWorld>("have the teamEditor role", async function (this) {
Then<CustomWorld>(
"they are not granted access to the Templates team",
async function (this) {
assert.strictEqual(this.user.teams.length, 0);
const userTeamSlugs = this.user.teams.map((userTeam) => userTeam.team.slug);
const isTemplateTeamMember = userTeamSlugs.includes("templates");

assert.strictEqual(isTemplateTeamMember, false);
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-- Previous definition from 1696884217237_grant_new_user_template_team_access/up.sql

CREATE OR REPLACE FUNCTION grant_new_user_template_team_access() RETURNS trigger AS $$
DECLARE
templates_team_id INT;
BEGIN
SELECT id INTO templates_team_id FROM teams WHERE slug = 'templates';
IF templates_team_id IS NOT NULL THEN
INSERT INTO team_members (user_id, team_id, role) VALUES (NEW.id, templates_team_id, 'teamEditor');
END IF;

RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER grant_new_user_template_team_access ON users;

CREATE TRIGGER grant_new_user_template_team_access AFTER INSERT ON users
FOR EACH ROW EXECUTE PROCEDURE grant_new_user_template_team_access();

COMMENT ON TRIGGER grant_new_user_template_team_access ON users
IS 'Automatically grant all new users teamEditor access to the shared Templates team';
36 changes: 36 additions & 0 deletions hasura.planx.uk/migrations/1730277860890_run_sql_migration/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
CREATE OR REPLACE FUNCTION grant_new_user_template_access() RETURNS trigger AS $$
DECLARE
templates_team_id INT;
is_demo_user BOOLEAN;
BEGIN
SELECT EXISTS (
SELECT 1
FROM team_members
WHERE user_id = NEW.id
AND role = 'demoUser'
) INTO is_demo_user;

-- Demo user should not get access as a teamEditor for the templates team...
IF is_demo_user THEN
RETURN NULL;
END IF;

-- ...but all other users should
SELECT id INTO templates_team_id FROM teams WHERE slug = 'templates';
IF templates_team_id IS NOT NULL THEN
INSERT INTO team_members (user_id, team_id, role)
VALUES (NEW.id, templates_team_id, 'teamEditor');
END IF;

RETURN NULL;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS grant_new_user_template_team_access ON users;

CREATE CONSTRAINT TRIGGER grant_new_user_template_team_access
AFTER INSERT ON users
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW EXECUTE FUNCTION grant_new_user_template_access();

COMMENT ON TRIGGER grant_new_user_template_team_access ON users IS 'Automatically grant all new users teamEditor access to the shared Templates team (apart from users with the demoUser role)';

0 comments on commit a318850

Please sign in to comment.