create a user repository base to handle contexts

This commit is contained in:
Mads Rasmussen
2023-10-25 10:25:48 +02:00
parent c3d01e48e9
commit cfd476da73
8 changed files with 97 additions and 165 deletions

View File

@@ -1,39 +1,27 @@
import { UmbUserCollectionFilterModel } from '../../types.js';
import { UMB_USER_STORE_CONTEXT_TOKEN, UmbUserStore } from '../../repository/user.store.js';
import { UmbUserRepositoryBase } from '../../repository/user-repository-base.js';
import { UmbUserCollectionServerDataSource } from './user-collection.server.data.js';
import { UserResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbCollectionDataSource, UmbCollectionRepository } from '@umbraco-cms/backoffice/repository';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
export class UmbUserCollectionRepository implements UmbCollectionRepository {
#host: UmbControllerHostElement;
#init;
#detailStore?: UmbUserStore;
export class UmbUserCollectionRepository extends UmbUserRepositoryBase implements UmbCollectionRepository {
#collectionSource: UmbCollectionDataSource<UserResponseModel>;
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#collectionSource = new UmbUserCollectionServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_USER_STORE_CONTEXT_TOKEN, (instance) => {
this.#detailStore = instance;
}).asPromise(),
]);
super(host);
this.#collectionSource = new UmbUserCollectionServerDataSource(this.host);
}
async requestCollection(filter: UmbUserCollectionFilterModel = { skip: 0, take: 100 }) {
await this.#init;
await this.init;
const { data, error } = await this.#collectionSource.filterCollection(filter);
if (data) {
this.#detailStore?.appendItems(data.items);
this.detailStore!.appendItems(data.items);
}
return { data, error, asObservable: () => this.#detailStore!.all() };
return { data, error, asObservable: () => this.detailStore!.all() };
}
}

View File

@@ -1,30 +1,21 @@
import { UmbUserRepositoryBase } from '../user-repository-base.js';
import { UmbChangeUserPasswordServerDataSource } from './change-user-password.server.data.js';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
export class UmbChangeUserPasswordRepository {
#host: UmbControllerHostElement;
#init!: Promise<unknown>;
import { type UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
export class UmbChangeUserPasswordRepository extends UmbUserRepositoryBase {
#changePasswordSource: UmbChangeUserPasswordServerDataSource;
#notificationContext?: UmbNotificationContext;
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#changePasswordSource = new UmbChangeUserPasswordServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this.#notificationContext = instance;
}).asPromise(),
]);
super(host);
this.#changePasswordSource = new UmbChangeUserPasswordServerDataSource(this.host);
}
async changePassword(userId: string, newPassword: string) {
if (!userId) throw new Error('User id is missing');
if (!newPassword) throw new Error('New password is missing');
await this.#init;
await this.init;
const { data, error } = await this.#changePasswordSource.changePassword(userId, newPassword);

View File

@@ -1,47 +1,29 @@
import { UMB_USER_STORE_CONTEXT_TOKEN, UmbUserStore } from '../user.store.js';
import { UMB_USER_ITEM_STORE_CONTEXT_TOKEN, UmbUserItemStore } from '../user-item.store.js';
import { UmbUserRepositoryBase } from '../user-repository-base.js';
import { UmbDisableUserServerDataSource } from './disable-user.server.data.js';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
import { UserStateModel } from '@umbraco-cms/backoffice/backend-api';
export class UmbDisableUserRepository {
#host: UmbControllerHostElement;
#init;
export class UmbDisableUserRepository extends UmbUserRepositoryBase {
#disableSource: UmbDisableUserServerDataSource;
#notificationContext?: UmbNotificationContext;
#detailStore?: UmbUserStore;
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#disableSource = new UmbDisableUserServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_USER_STORE_CONTEXT_TOKEN, (instance) => {
this.#detailStore = instance;
}).asPromise(),
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this.#notificationContext = instance;
}).asPromise(),
]);
super(host);
this.#disableSource = new UmbDisableUserServerDataSource(this.host);
}
async disable(ids: Array<string>) {
if (ids.length === 0) throw new Error('User ids are missing');
await this.#init;
await this.init;
const { data, error } = await this.#disableSource.disable(ids);
if (!error) {
ids.forEach((id) => {
this.#detailStore?.updateItem(id, { state: UserStateModel.DISABLED });
this.detailStore?.updateItem(id, { state: UserStateModel.DISABLED });
});
const notification = { data: { message: `User disabled` } };
this.#notificationContext?.peek('positive', notification);
this.notificationContext?.peek('positive', notification);
}
return { data, error };

View File

@@ -1,46 +1,29 @@
import { UMB_USER_STORE_CONTEXT_TOKEN, type UmbUserStore } from '../user.store.js';
import { UmbUserRepositoryBase } from '../user-repository-base.js';
import { UmbEnableUserServerDataSource } from './enable-user.server.data.js';
import { type UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UserStateModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
export class UmbEnableUserRepository {
#host: UmbControllerHostElement;
#init;
export class UmbEnableUserRepository extends UmbUserRepositoryBase {
#enableSource: UmbEnableUserServerDataSource;
#detailStore?: UmbUserStore;
#notificationContext?: UmbNotificationContext;
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#enableSource = new UmbEnableUserServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_USER_STORE_CONTEXT_TOKEN, (instance) => {
this.#detailStore = instance;
}).asPromise(),
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this.#notificationContext = instance;
}).asPromise(),
]);
super(host);
this.#enableSource = new UmbEnableUserServerDataSource(this.host);
}
async enable(ids: Array<string>) {
if (ids.length === 0) throw new Error('User ids are missing');
await this.#init;
await this.init;
const { data, error } = await this.#enableSource.enable(ids);
if (!error) {
ids.forEach((id) => {
this.#detailStore?.updateItem(id, { state: UserStateModel.ACTIVE });
this.detailStore?.updateItem(id, { state: UserStateModel.ACTIVE });
});
const notification = { data: { message: `User disabled` } };
this.#notificationContext?.peek('positive', notification);
this.notificationContext?.peek('positive', notification);
}
return { data, error };

View File

@@ -1,26 +1,15 @@
import { UmbUserRepositoryBase } from '../user-repository-base.js';
import { type UmbInviteUserDataSource } from './types.js';
import { UmbInviteUserServerDataSource } from './invite-user.server.data.js';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
import { InviteUserRequestModel } from '@umbraco-cms/backoffice/backend-api';
export class UmbInviteUserRepository {
#host: UmbControllerHostElement;
#init;
export class UmbInviteUserRepository extends UmbUserRepositoryBase {
#inviteSource: UmbInviteUserDataSource;
#notificationContext?: UmbNotificationContext;
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#inviteSource = new UmbInviteUserServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this.#notificationContext = instance;
}).asPromise(),
]);
super(host);
this.#inviteSource = new UmbInviteUserServerDataSource(this.host);
}
/**
@@ -31,13 +20,13 @@ export class UmbInviteUserRepository {
*/
async invite(requestModel: InviteUserRequestModel) {
if (!requestModel) throw new Error('data is missing');
await this.#init;
await this.init;
const { error } = await this.#inviteSource.invite(requestModel);
if (!error) {
const notification = { data: { message: `Invite sent to user` } };
this.#notificationContext?.peek('positive', notification);
this.notificationContext?.peek('positive', notification);
}
return { error };
@@ -53,13 +42,13 @@ export class UmbInviteUserRepository {
async resendInvite(userId: string, requestModel: any) {
if (!userId) throw new Error('User id is missing');
if (!requestModel) throw new Error('data is missing');
await this.#init;
await this.init;
const { error } = await this.#inviteSource.resendInvite(userId, requestModel);
if (!error) {
const notification = { data: { message: `Invite resent to user` } };
this.#notificationContext?.peek('positive', notification);
this.notificationContext?.peek('positive', notification);
}
return { error };

View File

@@ -1,46 +1,29 @@
import { UMB_USER_STORE_CONTEXT_TOKEN, type UmbUserStore } from '../user.store.js';
import { UmbUserRepositoryBase } from '../user-repository-base.js';
import { UmbUnlockUserServerDataSource } from './unlock-user.server.data.js';
import { type UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UserStateModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
export class UmbUnlockUserRepository {
#host: UmbControllerHostElement;
#init;
export class UmbUnlockUserRepository extends UmbUserRepositoryBase {
#source: UmbUnlockUserServerDataSource;
#detailStore?: UmbUserStore;
#notificationContext?: UmbNotificationContext;
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#source = new UmbUnlockUserServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_USER_STORE_CONTEXT_TOKEN, (instance) => {
this.#detailStore = instance;
}).asPromise(),
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this.#notificationContext = instance;
}).asPromise(),
]);
super(host);
this.#source = new UmbUnlockUserServerDataSource(this.host);
}
async unlock(ids: Array<string>) {
if (ids.length === 0) throw new Error('User ids are missing');
await this.#init;
await this.init;
const { data, error } = await this.#source.unlock(ids);
if (!error) {
ids.forEach((id) => {
this.#detailStore?.updateItem(id, { state: UserStateModel.ACTIVE, failedPasswordAttempts: 0 });
this.detailStore?.updateItem(id, { state: UserStateModel.ACTIVE, failedPasswordAttempts: 0 });
});
const notification = { data: { message: `User unlocked` } };
this.#notificationContext?.peek('positive', notification);
this.notificationContext?.peek('positive', notification);
}
return { data, error };

View File

@@ -0,0 +1,32 @@
import { UMB_USER_STORE_CONTEXT_TOKEN, UmbUserStore } from './user.store.js';
import { UMB_USER_ITEM_STORE_CONTEXT_TOKEN, UmbUserItemStore } from './user-item.store.js';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
export class UmbUserRepositoryBase {
protected host;
protected init;
protected detailStore?: UmbUserStore;
protected itemStore?: UmbUserItemStore;
protected notificationContext?: UmbNotificationContext;
constructor(host: UmbControllerHostElement) {
this.host = host;
this.init = Promise.all([
new UmbContextConsumerController(this.host, UMB_USER_STORE_CONTEXT_TOKEN, (instance) => {
this.detailStore = instance;
}).asPromise(),
new UmbContextConsumerController(this.host, UMB_USER_ITEM_STORE_CONTEXT_TOKEN, (instance) => {
this.itemStore = instance;
}).asPromise(),
new UmbContextConsumerController(this.host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this.notificationContext = instance;
}).asPromise(),
]);
}
}

View File

@@ -1,10 +1,10 @@
import { UmbUserDetailDataSource, UmbUserSetGroupDataSource } from '../types.js';
import { UMB_USER_STORE_CONTEXT_TOKEN, UmbUserStore } from './user.store.js';
import { UmbUserServerDataSource } from './sources/user.server.data.js';
import { UmbUserItemServerDataSource } from './sources/user-item.server.data.js';
import { UMB_USER_ITEM_STORE_CONTEXT_TOKEN, UmbUserItemStore } from './user-item.store.js';
import { UmbUserItemStore } from './user-item.store.js';
import { UmbUserSetGroupsServerDataSource } from './sources/user-set-group.server.data.js';
import { UmbUserRepositoryBase } from './user-repository-base.js';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbDetailRepository, UmbItemDataSource, UmbItemRepository } from '@umbraco-cms/backoffice/repository';
import {
@@ -14,8 +14,7 @@ import {
UserItemResponseModel,
UserResponseModel,
} from '@umbraco-cms/backoffice/backend-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
import { UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
export type UmbUserDetailRepository = UmbDetailRepository<
CreateUserRequestModel,
@@ -24,12 +23,11 @@ export type UmbUserDetailRepository = UmbDetailRepository<
UserResponseModel
>;
export class UmbUserRepository implements UmbUserDetailRepository, UmbItemRepository<UserItemResponseModel> {
#host: UmbControllerHostElement;
#init;
export class UmbUserRepository
extends UmbUserRepositoryBase
implements UmbUserDetailRepository, UmbItemRepository<UserItemResponseModel>
{
#detailSource: UmbUserDetailDataSource;
#detailStore?: UmbUserStore;
#itemSource: UmbItemDataSource<UserItemResponseModel>;
#itemStore?: UmbUserItemStore;
#setUserGroupsSource: UmbUserSetGroupDataSource;
@@ -37,31 +35,17 @@ export class UmbUserRepository implements UmbUserDetailRepository, UmbItemReposi
#notificationContext?: UmbNotificationContext;
constructor(host: UmbControllerHostElement) {
this.#host = host;
super(host);
this.#detailSource = new UmbUserServerDataSource(this.#host);
this.#itemSource = new UmbUserItemServerDataSource(this.#host);
this.#setUserGroupsSource = new UmbUserSetGroupsServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_USER_STORE_CONTEXT_TOKEN, (instance) => {
this.#detailStore = instance;
}).asPromise(),
new UmbContextConsumerController(this.#host, UMB_USER_ITEM_STORE_CONTEXT_TOKEN, (instance) => {
this.#itemStore = instance;
}).asPromise(),
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this.#notificationContext = instance;
}).asPromise(),
]);
this.#detailSource = new UmbUserServerDataSource(this.host);
this.#itemSource = new UmbUserItemServerDataSource(this.host);
this.#setUserGroupsSource = new UmbUserSetGroupsServerDataSource(this.host);
}
// ITEMS:
async requestItems(ids: Array<string>) {
if (!ids) throw new Error('Ids are missing');
await this.#init;
await this.init;
const { data, error } = await this.#itemSource.getItems(ids);
@@ -73,7 +57,7 @@ export class UmbUserRepository implements UmbUserDetailRepository, UmbItemReposi
}
async items(ids: Array<string>) {
await this.#init;
await this.init;
return this.#itemStore!.items(ids);
}
@@ -85,15 +69,15 @@ export class UmbUserRepository implements UmbUserDetailRepository, UmbItemReposi
async requestById(id: string) {
if (!id) throw new Error('Id is missing');
await this.#init;
await this.init;
const { data, error } = await this.#detailSource.get(id);
if (data) {
this.#detailStore!.append(data);
this.detailStore!.append(data);
}
return { data, error, asObservable: () => this.#detailStore!.byId(id) };
return { data, error, asObservable: () => this.detailStore!.byId(id) };
}
async setUserGroups(userIds: Array<string>, userGroupIds: Array<string>) {
@@ -111,8 +95,8 @@ export class UmbUserRepository implements UmbUserDetailRepository, UmbItemReposi
async byId(id: string) {
if (!id) throw new Error('Key is missing');
await this.#init;
return this.#detailStore!.byId(id);
await this.init;
return this.detailStore!.byId(id);
}
async create(userRequestData: CreateUserRequestModel) {
@@ -121,7 +105,7 @@ export class UmbUserRepository implements UmbUserDetailRepository, UmbItemReposi
const { data, error } = await this.#detailSource.insert(userRequestData);
if (data) {
this.#detailStore?.append(data);
this.detailStore?.append(data);
const notification = { data: { message: `User created` } };
this.#notificationContext?.peek('positive', notification);
@@ -137,12 +121,12 @@ export class UmbUserRepository implements UmbUserDetailRepository, UmbItemReposi
const { data, error } = await this.#detailSource.update(id, user);
if (data) {
this.#detailStore?.append(data);
this.detailStore?.append(data);
}
if (!error) {
const notification = {
data: { message: this.#host.localize?.term('speechBubbles_editUserSaved') ?? 'User saved' },
data: { message: this.host.localize?.term('speechBubbles_editUserSaved') ?? 'User saved' },
};
this.#notificationContext?.peek('positive', notification);
}
@@ -156,7 +140,7 @@ export class UmbUserRepository implements UmbUserDetailRepository, UmbItemReposi
const { error } = await this.#detailSource.delete(id);
if (!error) {
this.#detailStore?.removeItem(id);
this.detailStore?.removeItem(id);
const notification = { data: { message: `User deleted` } };
this.#notificationContext?.peek('positive', notification);