Skip to content

Commit

Permalink
Merge pull request #881 from umbraco/feature/permissions
Browse files Browse the repository at this point in the history
Feature: User Permissions WIP part 1
  • Loading branch information
madsrasmussen authored Sep 28, 2023
2 parents 709b3cb + f5fb8ce commit 0ffe56e
Show file tree
Hide file tree
Showing 84 changed files with 1,562 additions and 519 deletions.
3 changes: 3 additions & 0 deletions src/assets/lang/da-dk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1822,6 +1822,9 @@ export default {
permissionsDefault: 'Standardrettigheder',
permissionsGranular: 'Granulære rettigheder',
permissionsGranularHelp: 'Sæt rettigheder for specifikke noder',
permissionsEntityGroup_document: 'Indhold',
permissionsEntityGroup_media: 'Medie',
permissionsEntityGroup_member: 'Medlemmer',
profile: 'Profil',
searchAllChildren: "Søg alle 'børn'",
languagesHelp: 'Tilføj sprog for at give brugerne adgang til at redigere',
Expand Down
3 changes: 3 additions & 0 deletions src/assets/lang/en-us.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1822,6 +1822,9 @@ export default {
permissionsDefault: 'Default permissions',
permissionsGranular: 'Granular permissions',
permissionsGranularHelp: 'Set permissions for specific nodes',
permissionsEntityGroup_document: 'Content',
permissionsEntityGroup_media: 'Media',
permissionsEntityGroup_member: 'Member',
profile: 'Profile',
searchAllChildren: 'Search all children',
languagesHelp: 'Limit the languages users have access to edit',
Expand Down
2 changes: 1 addition & 1 deletion src/mocks/browser-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as serverHandlers from './handlers/server.handlers.js';
import { handlers as upgradeHandlers } from './handlers/upgrade.handlers.js';
import { handlers as userHandlers } from './handlers/user.handlers.js';
import { handlers as telemetryHandlers } from './handlers/telemetry.handlers.js';
import { handlers as userGroupsHandlers } from './handlers/user-group.handlers.js';
import { handlers as userGroupsHandlers } from './handlers/user-group/index.js';
import { handlers as examineManagementHandlers } from './handlers/examine-management.handlers.js';
import { handlers as modelsBuilderHandlers } from './handlers/modelsbuilder.handlers.js';
import { handlers as healthCheckHandlers } from './handlers/health-check.handlers.js';
Expand Down
11 changes: 1 addition & 10 deletions src/mocks/data/entity.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,10 @@ export class UmbEntityData<T extends UmbEntityBase> extends UmbData<T> {
}

delete(ids: Array<string>) {
const deletedKeys = this.data
.filter((item) => {
if (!item.id) throw new Error('Item has no id');
ids.includes(item.id);
})
.map((item) => item.id);

this.data = this.data.filter((item) => {
if (!item.id) throw new Error('Item has no id');
ids.indexOf(item.id) === -1;
return !ids.includes(item.id);
});

return deletedKeys;
}

updateData(updateItem: T) {
Expand Down
19 changes: 18 additions & 1 deletion src/mocks/data/media.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import type { MediaDetails } from '../../packages/media/media/index.js';
import { UmbEntityTreeData } from './entity-tree.data.js';
import { UmbEntityData } from './entity.data.js';
import { createContentTreeItem } from './utils.js';
import { ContentTreeItemResponseModel, PagedMediaTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
import {
ContentTreeItemResponseModel,
MediaItemResponseModel,
PagedMediaTreeItemResponseModel,
} from '@umbraco-cms/backoffice/backend-api';

export const data: Array<MediaDetails> = [
{
Expand Down Expand Up @@ -183,6 +187,14 @@ export const data: Array<MediaDetails> = [
},
];

const createMediaItem = (item: MediaDetails): MediaItemResponseModel => {
return {
id: item.id,
name: item.name,
icon: item.icon,
};
};

// Temp mocked database
// TODO: all properties are optional in the server schema. I don't think this is correct.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand All @@ -194,6 +206,11 @@ class UmbMediaData extends UmbEntityData<MediaDetails> {
super(data);
}

getItems(ids: Array<string>): Array<MediaItemResponseModel> {
const items = this.data.filter((item) => ids.includes(item.id ?? ''));
return items.map((item) => createMediaItem(item));
}

getTreeRoot(): PagedMediaTreeItemResponseModel {
const items = this.data.filter((item) => item.parentId === null);
const treeItems = items.map((item) => createContentTreeItem(item));
Expand Down
78 changes: 78 additions & 0 deletions src/mocks/data/user-group.data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { UmbEntityData } from './entity.data.js';
import {
UMB_USER_PERMISSION_DOCUMENT_CREATE,
UMB_USER_PERMISSION_DOCUMENT_DELETE,
UMB_USER_PERMISSION_DOCUMENT_READ,
} from '@umbraco-cms/backoffice/document';
import {
PagedUserGroupResponseModel,
UserGroupItemResponseModel,
UserGroupResponseModel,
} from '@umbraco-cms/backoffice/backend-api';

const createUserGroupItem = (item: UserGroupResponseModel): UserGroupItemResponseModel => {
return {
name: item.name,
id: item.id,
icon: item.icon,
};
};

// Temp mocked database
class UmbUserGroupData extends UmbEntityData<UserGroupResponseModel> {
constructor(data: Array<UserGroupResponseModel>) {
super(data);
}

getAll(): PagedUserGroupResponseModel {
return {
total: this.data.length,
items: this.data,
};
}

getItems(ids: Array<string>): Array<UserGroupItemResponseModel> {
const items = this.data.filter((item) => ids.includes(item.id ?? ''));
return items.map((item) => createUserGroupItem(item));
}

/**
* Returns a list of permissions for the given user group ids
* @param {string[]} userGroupIds
* @return {*} {string[]}
* @memberof UmbUserGroupData
*/
getPermissions(userGroupIds: string[]): string[] {
const permissions = this.data
.filter((userGroup) => userGroupIds.includes(userGroup.id || ''))
.map((userGroup) => (userGroup.permissions?.length ? userGroup.permissions : []))
.flat();

// Remove duplicates
return [...new Set(permissions)];
}
}

export const data: Array<UserGroupResponseModel> = [
{
id: 'c630d49e-4e7b-42ea-b2bc-edc0edacb6b1',
name: 'Administrators',
icon: 'umb:medal',
documentStartNodeId: 'all-property-editors-document-id',
permissions: [UMB_USER_PERMISSION_DOCUMENT_CREATE, UMB_USER_PERMISSION_DOCUMENT_DELETE],
},
{
id: '9d24dc47-a4bf-427f-8a4a-b900f03b8a12',
name: 'User Group 1',
icon: 'umb:bell',
permissions: [UMB_USER_PERMISSION_DOCUMENT_DELETE],
},
{
id: 'f4626511-b0d7-4ab1-aebc-a87871a5dcfa',
name: 'User Group 2',
icon: 'umb:ball',
permissions: [UMB_USER_PERMISSION_DOCUMENT_READ],
},
];

export const umbUserGroupData = new UmbUserGroupData(data);
26 changes: 0 additions & 26 deletions src/mocks/data/user-groups.data.ts

This file was deleted.

113 changes: 35 additions & 78 deletions src/mocks/data/users.data.ts → src/mocks/data/user.data.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { UmbData } from './data.js';
import { UmbEntityData } from './entity.data.js';
import { umbUserGroupData } from './user-group.data.js';
import { UmbLoggedInUser } from '@umbraco-cms/backoffice/auth';
import { PagedUserResponseModel, UserResponseModel, UserStateModel } from '@umbraco-cms/backoffice/backend-api';
import {
PagedUserResponseModel,
UpdateUserGroupsOnUserRequestModel,
UserItemResponseModel,
UserResponseModel,
UserStateModel,
} from '@umbraco-cms/backoffice/backend-api';

const createUserItem = (item: UserResponseModel): UserItemResponseModel => {
return {
name: item.name,
id: item.id,
};
};

// Temp mocked database
class UmbUsersData extends UmbData<UserResponseModel> {
class UmbUserData extends UmbEntityData<UserResponseModel> {
constructor(data: UserResponseModel[]) {
super(data);
}
Expand All @@ -15,12 +29,21 @@ class UmbUsersData extends UmbData<UserResponseModel> {
};
}

getById(id: string): UserResponseModel | undefined {
return this.data.find((user) => user.id === id);
getItems(ids: Array<string>): Array<UserItemResponseModel> {
const items = this.data.filter((item) => ids.includes(item.id ?? ''));
return items.map((item) => createUserItem(item));
}

setUserGroups(data: UpdateUserGroupsOnUserRequestModel): void {
const users = this.data.filter((user) => data.userIds?.includes(user.id ?? ''));
users.forEach((user) => {
user.userGroupIds = data.userGroupIds;
});
}

getCurrentUser(): UmbLoggedInUser {
const firstUser = this.data[0];
const permissions = firstUser.userGroupIds?.length ? umbUserGroupData.getPermissions(firstUser.userGroupIds) : [];

return {
id: firstUser.id,
Expand All @@ -33,79 +56,9 @@ class UmbUsersData extends UmbData<UserResponseModel> {
languages: [],
contentStartNodeIds: firstUser.contentStartNodeIds,
mediaStartNodeIds: firstUser.mediaStartNodeIds,
permissions: [],
permissions,
};
}

save(id: string, saveItem: UserResponseModel) {
const foundIndex = this.data.findIndex((item) => item.id === id);
if (foundIndex !== -1) {
// update
this.data[foundIndex] = saveItem;
this.updateData(saveItem);
} else {
// new
this.data.push(saveItem);
}

return saveItem;
}

protected updateData(updateItem: UserResponseModel) {
const itemIndex = this.data.findIndex((item) => item.id === updateItem.id);
const item = this.data[itemIndex];

console.log('updateData', updateItem, itemIndex, item);

if (!item) return;

const itemKeys = Object.keys(item);
const newItem = {};

for (const [key] of Object.entries(updateItem)) {
if (itemKeys.indexOf(key) !== -1) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
newItem[key] = updateItem[key];
}
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.data[itemIndex] = newItem;

console.log('updateData', this.data[itemIndex]);
}

// updateUserGroup(ids: string[], userGroup: string) {
// this.data.forEach((user) => {
// if (ids.includes(user.id)) {
// } else {
// }

// this.updateData(user);
// });

// return this.data.map((user) => user.id);
// }

// enable(ids: string[]) {
// const users = this.data.filter((user) => ids.includes(user.id));
// users.forEach((user) => {
// user.status = 'enabled';
// this.updateData(user);
// });
// return users.map((user) => user.id);
// }

// disable(ids: string[]) {
// const users = this.data.filter((user) => ids.includes(user.id));
// users.forEach((user) => {
// user.status = 'disabled';
// this.updateData(user);
// });
// return users.map((user) => user.id);
// }
}

export const data: Array<UserResponseModel & { type: string }> = [
Expand All @@ -124,7 +77,11 @@ export const data: Array<UserResponseModel & { type: string }> = [
updateDate: '2/10/2022',
createDate: '3/13/2022',
failedLoginAttempts: 946,
userGroupIds: ['c630d49e-4e7b-42ea-b2bc-edc0edacb6b1'],
userGroupIds: [
'c630d49e-4e7b-42ea-b2bc-edc0edacb6b1',
'9d24dc47-a4bf-427f-8a4a-b900f03b8a12',
'f4626511-b0d7-4ab1-aebc-a87871a5dcfa',
],
},
{
id: '82e11d3d-b91d-43c9-9071-34d28e62e81d',
Expand Down Expand Up @@ -196,4 +153,4 @@ export const data: Array<UserResponseModel & { type: string }> = [
},
];

export const umbUsersData = new UmbUsersData(data);
export const umbUsersData = new UmbUserData(data);
6 changes: 3 additions & 3 deletions src/mocks/handlers/dictionary.handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ export const handlers = [
const id = req.params.id as string;
if (!id) return;

const deletedKeys = umbDictionaryData.delete([id]);
umbDictionaryData.delete([id]);

return res(ctx.status(200), ctx.json(deletedKeys));
return res(ctx.status(200));
}),

// TODO => handle properly, querystring breaks handler
Expand All @@ -165,7 +165,7 @@ export const handlers = [
const item = umbDictionaryData.getById(id);

alert(
`Downloads file for dictionary "${item?.name}", ${includeChildren === 'true' ? 'with' : 'without'} children.`
`Downloads file for dictionary "${item?.name}", ${includeChildren === 'true' ? 'with' : 'without'} children.`,
);
return res(ctx.status(200));
}),
Expand Down
8 changes: 8 additions & 0 deletions src/mocks/handlers/media.handlers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
const { rest } = window.MockServiceWorker;
import { umbMediaData } from '../data/media.data.js';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';

// TODO: add schema
export const handlers = [
rest.get(umbracoPath('/media/item'), (req, res, ctx) => {
const ids = req.url.searchParams.getAll('id');
if (!ids) return;
const items = umbMediaData.getItems(ids);
return res(ctx.status(200), ctx.json(items));
}),

rest.get('/umbraco/management/api/v1/media/details/:id', (req, res, ctx) => {
console.warn('Please move to schema');
const id = req.params.id as string;
Expand Down
Loading

0 comments on commit 0ffe56e

Please sign in to comment.