user conditions + workspace refactor
This commit is contained in:
@@ -2,12 +2,10 @@ import { UMB_CURRENT_USER_CONTEXT } from '../current-user.context.js';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export const isCurrentUser = async (host: UmbControllerHost, userId: string) => {
|
||||
let currentUserContext: typeof UMB_CURRENT_USER_CONTEXT.TYPE | undefined;
|
||||
export const isCurrentUser = async (host: UmbControllerHost, userUnique: string) => {
|
||||
const ctrl = new UmbContextConsumerController(host, UMB_CURRENT_USER_CONTEXT);
|
||||
const currentUserContext = await ctrl.asPromise();
|
||||
ctrl.destroy();
|
||||
|
||||
await new UmbContextConsumerController(host, UMB_CURRENT_USER_CONTEXT, (context) => {
|
||||
currentUserContext = context;
|
||||
}).asPromise();
|
||||
|
||||
return await currentUserContext!.isUserCurrentUser(userId);
|
||||
return await currentUserContext!.isUserCurrentUser(userUnique);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbUserDetailModel } from '../types.js';
|
||||
import type { UmbUserWorkspaceContext } from '../workspace/user-workspace.context.js';
|
||||
import type { UmbUserStateEnum } from '../types.js';
|
||||
import { UMB_USER_WORKSPACE_CONTEXT } from '../workspace/user-workspace.context.js';
|
||||
import { UmbBaseController } from '@umbraco-cms/backoffice/class-api';
|
||||
import { isCurrentUser } from '@umbraco-cms/backoffice/current-user';
|
||||
import type {
|
||||
@@ -7,28 +7,38 @@ import type {
|
||||
UmbConditionControllerArguments,
|
||||
UmbExtensionCondition,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export class UmbUserActionConditionBase extends UmbBaseController implements UmbExtensionCondition {
|
||||
config: UmbConditionConfigBase;
|
||||
permitted = false;
|
||||
#onChange: () => void;
|
||||
protected userData?: UmbUserDetailModel;
|
||||
protected userUnique?: string;
|
||||
protected userState?: UmbUserStateEnum | null;
|
||||
|
||||
constructor(args: UmbConditionControllerArguments<UmbConditionConfigBase>) {
|
||||
super(args.host);
|
||||
this.config = args.config;
|
||||
this.#onChange = args.onChange;
|
||||
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => {
|
||||
const userContext = context as UmbUserWorkspaceContext;
|
||||
this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (context) => {
|
||||
this.observe(
|
||||
userContext.data,
|
||||
(data) => {
|
||||
this.userData = data;
|
||||
context.unique,
|
||||
(unique) => {
|
||||
this.userUnique = unique;
|
||||
this.onUserDataChange();
|
||||
},
|
||||
'umbUserDataActionConditionObserver',
|
||||
'umbUserUnique',
|
||||
);
|
||||
this.observe(
|
||||
context.state,
|
||||
(state) => {
|
||||
this.userState = state;
|
||||
// TODO: Investigate if we can remove this observation and just use the unique change to trigger the state change. [NL]
|
||||
// Can user state change over time? if not then this observation is not needed and then we just need to retrieve the state when the unique has changed. [NL]
|
||||
// These two could also be combined via the observeMultiple method, that could prevent triggering onUserDataChanged twice. [NL]
|
||||
this.onUserDataChange();
|
||||
},
|
||||
'umbUserState',
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -40,7 +50,7 @@ export class UmbUserActionConditionBase extends UmbBaseController implements Umb
|
||||
* @memberof UmbUserActionConditionBase
|
||||
*/
|
||||
protected async isCurrentUser() {
|
||||
return this.userData?.unique ? isCurrentUser(this._host, this.userData.unique) : false;
|
||||
return this.userUnique ? isCurrentUser(this._host, this.userUnique) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
import { UmbUserActionConditionBase } from './user-allow-action-base.condition.js';
|
||||
import type {
|
||||
ManifestCondition,
|
||||
UmbConditionConfigBase,
|
||||
UmbConditionControllerArguments,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export class UmbUserAllowDeleteActionCondition extends UmbUserActionConditionBase {
|
||||
constructor(args: UmbConditionControllerArguments<UmbConditionConfigBase>) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
async onUserDataChange() {
|
||||
// don't allow the current user to delete themselves
|
||||
if (!this.userData || !this.userData.unique || (await this.isCurrentUser())) {
|
||||
if (!this.userUnique || (await this.isCurrentUser())) {
|
||||
this.permitted = false;
|
||||
} else {
|
||||
this.permitted = true;
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
import { UmbUserStateEnum } from '../types.js';
|
||||
import { UmbUserActionConditionBase } from './user-allow-action-base.condition.js';
|
||||
import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type {
|
||||
ManifestCondition,
|
||||
UmbConditionConfigBase,
|
||||
UmbConditionControllerArguments,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export class UmbUserAllowDisableActionCondition extends UmbUserActionConditionBase {
|
||||
constructor(args: UmbConditionControllerArguments<UmbConditionConfigBase>) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
async onUserDataChange() {
|
||||
// don't allow the current user to disable themselves
|
||||
if (!this.userData || !this.userData.unique || (await this.isCurrentUser())) {
|
||||
if (!this.userUnique || (await this.isCurrentUser())) {
|
||||
this.permitted = false;
|
||||
super.onUserDataChange();
|
||||
return;
|
||||
}
|
||||
|
||||
this.permitted = this.userData?.state !== UserStateModel.DISABLED;
|
||||
this.permitted = this.userState !== UmbUserStateEnum.DISABLED;
|
||||
super.onUserDataChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
import { UmbUserStateEnum } from '../types.js';
|
||||
import { UmbUserActionConditionBase } from './user-allow-action-base.condition.js';
|
||||
import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type {
|
||||
ManifestCondition,
|
||||
UmbConditionConfigBase,
|
||||
UmbConditionControllerArguments,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export class UmbUserAllowEnableActionCondition extends UmbUserActionConditionBase {
|
||||
constructor(args: UmbConditionControllerArguments<UmbConditionConfigBase>) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
async onUserDataChange() {
|
||||
// don't allow the current user to enable themselves
|
||||
if (!this.userData || !this.userData.unique || (await this.isCurrentUser())) {
|
||||
if (!this.userUnique || (await this.isCurrentUser())) {
|
||||
this.permitted = false;
|
||||
super.onUserDataChange();
|
||||
return;
|
||||
}
|
||||
|
||||
this.permitted = this.userData?.state === UserStateModel.DISABLED;
|
||||
this.permitted = this.userState === UmbUserStateEnum.DISABLED;
|
||||
super.onUserDataChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
import { UmbUserStateEnum } from '../types.js';
|
||||
import { UmbUserActionConditionBase } from './user-allow-action-base.condition.js';
|
||||
import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type {
|
||||
ManifestCondition,
|
||||
UmbConditionConfigBase,
|
||||
UmbConditionControllerArguments,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export class UmbUserAllowUnlockActionCondition extends UmbUserActionConditionBase {
|
||||
constructor(args: UmbConditionControllerArguments<UmbConditionConfigBase>) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
async onUserDataChange() {
|
||||
// don't allow the current user to unlock themselves
|
||||
if (!this.userData || !this.userData.unique || (await this.isCurrentUser())) {
|
||||
if (!this.userUnique || (await this.isCurrentUser())) {
|
||||
this.permitted = false;
|
||||
super.onUserDataChange();
|
||||
return;
|
||||
}
|
||||
|
||||
this.permitted = this.userData?.state === UserStateModel.LOCKED_OUT;
|
||||
this.permitted = this.userState === UmbUserStateEnum.LOCKED_OUT;
|
||||
super.onUserDataChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
import { UmbUserActionConditionBase } from '../../../conditions/user-allow-action-base.condition.js';
|
||||
import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type {
|
||||
ManifestCondition,
|
||||
UmbConditionConfigBase,
|
||||
UmbConditionControllerArguments,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export class UmbUserAllowResendInviteActionCondition extends UmbUserActionConditionBase {
|
||||
constructor(args: UmbConditionControllerArguments<UmbConditionConfigBase>) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
async onUserDataChange() {
|
||||
if (!this.userData || !this.userData.unique) {
|
||||
if (!this.userUnique) {
|
||||
this.permitted = false;
|
||||
super.onUserDataChange();
|
||||
return;
|
||||
}
|
||||
|
||||
this.permitted = this.userData?.state === UserStateModel.INVITED;
|
||||
this.permitted = this.userState === UserStateModel.INVITED;
|
||||
super.onUserDataChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { UmbUserEntityType } from './entity.js';
|
||||
import type { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
|
||||
export type UmbUserStateEnum = UserStateModel;
|
||||
export const UmbUserStateEnum = UserStateModel;
|
||||
|
||||
export interface UmbUserDetailModel {
|
||||
entityType: UmbUserEntityType;
|
||||
@@ -12,7 +15,7 @@ export interface UmbUserDetailModel {
|
||||
documentStartNodeUniques: Array<string>;
|
||||
mediaStartNodeUniques: Array<string>;
|
||||
avatarUrls: Array<string>;
|
||||
state: UserStateModel | null;
|
||||
state: UmbUserStateEnum | null;
|
||||
failedLoginAttempts: number;
|
||||
createDate: string | null;
|
||||
updateDate: string | null;
|
||||
|
||||
@@ -57,7 +57,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement {
|
||||
description=${this.localize.term('user_languageHelp')}>
|
||||
<umb-ui-culture-input
|
||||
slot="editor"
|
||||
value=${ifDefined(this._user?.languageIsoCode)}
|
||||
value=${ifDefined(this._user?.languageIsoCode ?? undefined)}
|
||||
@change="${this.#onLanguageChange}"
|
||||
name="language"
|
||||
label="${this.localize.term('user_language')}"></umb-ui-culture-input>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UmbUserDetailModel } from '../types.js';
|
||||
import type { UmbUserDetailModel, UmbUserStateEnum } from '../types.js';
|
||||
import { UMB_USER_ENTITY_TYPE } from '../entity.js';
|
||||
import { UmbUserDetailRepository } from '../repository/index.js';
|
||||
import { UmbUserAvatarRepository } from '../repository/avatar/index.js';
|
||||
@@ -24,12 +24,15 @@ export class UmbUserWorkspaceContext
|
||||
|
||||
#persistedData = new UmbObjectState<EntityType | undefined>(undefined);
|
||||
#currentData = new UmbObjectState<EntityType | undefined>(undefined);
|
||||
//data = this.#currentData.asObservable();
|
||||
readonly data = this.#currentData.asObservable();
|
||||
readonly state = this.#currentData.asObservablePart((x) => x?.state);
|
||||
readonly unique = this.#currentData.asObservablePart((x) => x?.unique);
|
||||
|
||||
async load(unique: string) {
|
||||
const { data, asObservable } = await this.detailRepository.requestByUnique(unique);
|
||||
if (data) {
|
||||
this.setIsNew(false);
|
||||
this.#persistedData.update(data);
|
||||
this.#currentData.update(data);
|
||||
}
|
||||
|
||||
@@ -49,6 +52,9 @@ export class UmbUserWorkspaceContext
|
||||
getUnique(): string | undefined {
|
||||
return this.getData()?.unique;
|
||||
}
|
||||
getState(): UmbUserStateEnum | null | undefined {
|
||||
return this.getData()?.state;
|
||||
}
|
||||
|
||||
getEntityType(): string {
|
||||
return UMB_USER_ENTITY_TYPE;
|
||||
@@ -69,14 +75,15 @@ export class UmbUserWorkspaceContext
|
||||
let newData = undefined;
|
||||
|
||||
if (this.getIsNew()) {
|
||||
const { data } = await this.detailRepository.create(this.#data.value);
|
||||
const { data } = await this.detailRepository.create(this.#currentData.value);
|
||||
newData = data;
|
||||
} else {
|
||||
const { data } = await this.detailRepository.save(this.#data.value);
|
||||
const { data } = await this.detailRepository.save(this.#currentData.value);
|
||||
newData = data;
|
||||
}
|
||||
|
||||
if (newData) {
|
||||
this.#persistedData.setValue(newData);
|
||||
this.#currentData.setValue(newData);
|
||||
this.saveComplete(newData);
|
||||
}
|
||||
@@ -98,6 +105,8 @@ export class UmbUserWorkspaceContext
|
||||
destroy(): void {
|
||||
this.#persistedData.destroy();
|
||||
this.#currentData.destroy();
|
||||
this.detailRepository.destroy();
|
||||
this.avatarRepository.destroy();
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user