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

Programmatic Creation of Roles and Teams #4303

Merged
merged 23 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9c80097
wip: create teams/roles plugins
adrians5j Oct 1, 2024
6f018e3
wip: go through merge changes again
adrians5j Oct 1, 2024
f6976f3
chore: run prettier
adrians5j Oct 1, 2024
30b99bb
wip: go through merge changes again
adrians5j Oct 1, 2024
4b30657
wip: go through merge changes again
adrians5j Oct 1, 2024
772f622
wip: go through merge changes again
adrians5j Oct 1, 2024
b2aa5e1
wip: improve UI
adrians5j Oct 1, 2024
8ee0304
wip: improve UI
adrians5j Oct 1, 2024
40ae9c2
wip: improve types
adrians5j Oct 1, 2024
cba22ba
fix: update exports
adrians5j Oct 1, 2024
1e73643
fix: remove `copyPermissionsButton` feature flag and make the featue …
adrians5j Oct 1, 2024
bc2ef80
chore: run prettier
adrians5j Oct 2, 2024
56ee9f2
test: improve groups/teams-related tests
adrians5j Oct 2, 2024
4c31a46
chore: eslint
adrians5j Oct 2, 2024
2f78454
fix: update dependencies
adrians5j Oct 2, 2024
0e31870
fix: remove `createTestWcpLicense` clones
adrians5j Oct 2, 2024
1bcdd6c
Merge branch 'next' into feat/programmatic-teams-roles
adrians5j Oct 2, 2024
0482d4c
fix: change label to "Copy permissions as JSON"
adrians5j Oct 2, 2024
7392c69
Merge remote-tracking branch 'origin/feat/programmatic-teams-roles' i…
adrians5j Oct 2, 2024
16b681b
Merge branch 'next' into feat/programmatic-teams-roles
adrians5j Oct 3, 2024
588a8aa
fix: apply fixes per review
adrians5j Oct 3, 2024
22035f1
fix: rename files
adrians5j Oct 4, 2024
1861881
Merge branch 'next' into feat/programmatic-teams-roles
adrians5j Oct 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/api-aco/__tests__/utils/useGraphQlHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import { FileManagerStorageOperations } from "@webiny/api-file-manager/types";
import { DecryptedWcpProjectLicense } from "@webiny/wcp/types";
import createAdminUsersApp from "@webiny/api-admin-users";
import { createWcpContext } from "@webiny/api-wcp";
import { createTestWcpLicense } from "~tests/utils/createTestWcpLicense";
import { createTestWcpLicense } from "@webiny/wcp/testing/createTestWcpLicense";
import { AdminUsersStorageOperations } from "@webiny/api-admin-users/types";

export interface UseGQLHandlerParams {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { getIntrospectionQuery } from "graphql";
import { APIGatewayEvent, LambdaContext } from "@webiny/handler-aws/types";
import { DecryptedWcpProjectLicense } from "@webiny/wcp/types";
import createAdminUsersApp from "@webiny/api-admin-users";
import { createTestWcpLicense } from "~tests/utils/createTestWcpLicense";
import { createTestWcpLicense } from "@webiny/wcp/testing/createTestWcpLicense";
import { createWcpContext } from "@webiny/api-wcp";
import { AdminUsersStorageOperations } from "@webiny/api-admin-users/types";
import { until } from "@webiny/project-utils/testing/helpers/until";
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { getIntrospectionQuery } from "graphql";
import { APIGatewayEvent, LambdaContext } from "@webiny/handler-aws/types";
import { DecryptedWcpProjectLicense } from "@webiny/wcp/types";
import createAdminUsersApp from "@webiny/api-admin-users";
import { createTestWcpLicense } from "~tests/utils/createTestWcpLicense";
import { createTestWcpLicense } from "@webiny/wcp/testing/createTestWcpLicense";
import { createWcpContext } from "@webiny/api-wcp";
import { AdminUsersStorageOperations } from "@webiny/api-admin-users/types";

Expand Down
75 changes: 75 additions & 0 deletions packages/api-security/__tests__/graphql/teams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const DATA_FIELD = (extra = "") => /* GraphQL */ `
{
name
description
slug
groups {
id
name
}
${extra}
}
`;

const ERROR_FIELD = /* GraphQL */ `
{
code
data
message
}
`;

export const CREATE_SECURITY_TEAM = /* GraphQL */ `
mutation CreateTeam($data: SecurityTeamCreateInput!) {
security {
createTeam(data: $data) {
data ${DATA_FIELD("id")}
error ${ERROR_FIELD}
}
}
}
`;

export const UPDATE_SECURITY_TEAM = /* GraphQL */ `
mutation UpdateTeam($id: ID!, $data: SecurityTeamUpdateInput!) {
security {
updateTeam(id: $id, data: $data) {
data ${DATA_FIELD()}
error ${ERROR_FIELD}
}
}
}
`;

export const DELETE_SECURITY_TEAM = /* GraphQL */ `
mutation DeleteTeam($id: ID!) {
security {
deleteTeam(id: $id) {
data
error ${ERROR_FIELD}
}
}
}
`;

export const LIST_SECURITY_TEAMS = /* GraphQL */ `
query ListTeams {
security {
listTeams {
data ${DATA_FIELD()}
error ${ERROR_FIELD}
}
}
}
`;

export const GET_SECURITY_TEAM = /* GraphQL */ `
query GetTeam($id: ID!) {
security {
getTeam(where: { id: $id }) {
data ${DATA_FIELD()}
error ${ERROR_FIELD}
}
}
}
`;
137 changes: 123 additions & 14 deletions packages/api-security/__tests__/groups.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import useGqlHandler from "./useGqlHandler";
import mocks from "./mocks/securityGroup";
import { createSecurityRolePlugin } from "~/plugins/SecurityRolePlugin";

describe("Security Group CRUD Test", () => {
const { install, securityGroup } = useGqlHandler();
const { install, securityGroup } = useGqlHandler({
plugins: [
createSecurityRolePlugin({
id: "test-role-1",
name: "Test Role 1",
description: "1st test role defined via an extension.",
permissions: [{ name: "cms.*" }]
}),
createSecurityRolePlugin({
id: "test-role-2",
name: "Test Role 2",
description: "2nd test role defined via an extension.",
permissions: [{ name: "pb.*" }]
})
]
});

beforeEach(async () => {
await install.install();
Expand All @@ -23,19 +39,67 @@ describe("Security Group CRUD Test", () => {
// Let's check whether both of the group exists
const [listResponse] = await securityGroup.list();

expect(listResponse.data.security.listGroups).toEqual(
expect.objectContaining({
data: expect.arrayContaining([
{
name: expect.any(String),
description: expect.any(String),
slug: expect.stringMatching(/anonymous|full-access|group-a|group-b/),
permissions: expect.any(Array)
}
]),
error: null
})
);
expect(listResponse.data.security.listGroups).toEqual({
error: null,
data: [
{
name: "Test Role 1",
description: "1st test role defined via an extension.",
slug: "test-role-1",
permissions: [
{
name: "cms.*"
}
]
},
{
name: "Test Role 2",
description: "2nd test role defined via an extension.",
slug: "test-role-2",
permissions: [
{
name: "pb.*"
}
]
},
{
name: "Full Access",
description: "Grants full access to all apps.",
slug: "full-access",
permissions: [
{
name: "*"
}
]
},
{
name: "Anonymous",
description: "Permissions for anonymous users (public access).",
slug: "anonymous",
permissions: []
},
{
name: "Group-A",
description: "A: Dolor odit et quia animi ipsum nostrum nesciunt.",
slug: "group-a",
permissions: [
{
name: "security.*"
}
]
},
{
name: "Group-B",
description: "B: Dolor odit et quia animi ipsum nostrum nesciunt.",
slug: "group-b",
permissions: [
{
name: "security.*"
}
]
}
]
});

// Let's update the "groupB" name
const updatedName = "Group B - updated";
Expand Down Expand Up @@ -131,4 +195,49 @@ describe("Security Group CRUD Test", () => {
}
});
});

test("should not allow update of a group created via a plugin", async () => {
// Creating a group with same "slug" should not be allowed
const [response] = await securityGroup.update({
id: "test-role-1",
data: {
name: "Test Role 1 - updated"
}
});

expect(response).toEqual({
data: {
security: {
updateGroup: {
data: null,
error: {
code: "CANNOT_UPDATE_PLUGIN_GROUPS",
data: null,
message: "Cannot update groups created via plugins."
}
}
}
}
});
});

test("should not allow deletion of a group created via a plugin", async () => {
// Creating a group with same "slug" should not be allowed
const [response] = await securityGroup.delete({ id: "" });

expect(response).toEqual({
data: {
security: {
deleteGroup: {
data: null,
error: {
code: "CANNOT_DELETE_PLUGIN_GROUPS",
data: null,
message: "Cannot delete groups created via plugins."
}
}
}
}
});
});
});
16 changes: 16 additions & 0 deletions packages/api-security/__tests__/mocks/securityTeam.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const mocks = {
teamA: {
name: "Team-A",
slug: "team-a",
description: "A: Dolor odit et quia animi ipsum nostrum nesciunt.",
groups: []
},
teamB: {
name: "Team-B",
slug: "team-b",
description: "B: Dolor odit et quia animi ipsum nostrum nesciunt.",
groups: []
}
};

export default mocks;
Loading
Loading