@memberjunction/core-entities
Advanced tools
Comparing version 2.7.1 to 2.8.0
@@ -30,3 +30,33 @@ import { BaseInfo, EntityInfo, EntityFieldInfo, UserInfo, EntitySaveOptions } from "@memberjunction/core"; | ||
LoadFromData(data: any): boolean; | ||
/** | ||
* This property determines if the specified user can edit the view object. All of the below assumes the user has base Create/Update permissions on the "User Views" entity. | ||
* The flow of the logic is: | ||
* 1) The view is a new record, by definition the user can edit this because it is new | ||
* 2) The user is the owner of the current view - e.g. UserID in the view record matches the ID of the user provided, allowed | ||
* 3) The user is a sysadmin (Type === 'Owner' in the User object), allowed | ||
* 4) If neither of the above conditions are met, the Resource Permissions are checked to see if the user, directly or via Roles, has either Edit or Owner permissions on the current view | ||
* @returns | ||
*/ | ||
get UserCanEdit(): boolean; | ||
private _cachedCanUserEdit; | ||
/** | ||
* This property determines if the specified user can delete the view object. All of the below assumes the user has base Delete permissions on the "User Views" entity. | ||
* The flow of the logic is: | ||
* 1) The view is a new record, by definition the user can't delete this because it is new | ||
* 2) The user is the owner of the current view - e.g. UserID in the view record matches the ID of the user provided, allowed | ||
* 3) The user is a sysadmin (Type === 'Owner' in the User object), allowed | ||
* 4) If neither of the above conditions are met, the Resource Permissions are checked to see if the user, directly or via Roles, has OWNER permissions on the current view | ||
*/ | ||
get UserCanDelete(): boolean; | ||
private _cachedUserCanDelete; | ||
protected ResetCachedCanUserSettings(): void; | ||
private CalculateUserCanDelete; | ||
private CalculateUserCanEdit; | ||
/** | ||
* Returns the ID of the Resource Type metadata record that corresponds to the User Views entity | ||
*/ | ||
get ViewResourceTypeID(): string; | ||
private _ViewResourceTypeID; | ||
Load(ID: string, EntityRelationshipsToLoad?: string[]): Promise<boolean>; | ||
Delete(): Promise<boolean>; | ||
Save(options?: EntitySaveOptions): Promise<boolean>; | ||
@@ -33,0 +63,0 @@ SetDefaultsFromEntity(e: EntityInfo): Promise<void>; |
@@ -13,2 +13,3 @@ "use strict"; | ||
const entity_subclasses_1 = require("../generated/entity_subclasses"); | ||
const ResourcePermissionEngine_1 = require("./ResourcePermissions/ResourcePermissionEngine"); | ||
let UserViewEntityExtended = class UserViewEntityExtended extends entity_subclasses_1.UserViewEntity { | ||
@@ -18,2 +19,5 @@ constructor() { | ||
this._ViewEntityInfo = null; | ||
this._cachedCanUserEdit = null; | ||
this._cachedUserCanDelete = null; | ||
this._ViewResourceTypeID = null; | ||
} | ||
@@ -114,2 +118,86 @@ /** | ||
} | ||
/** | ||
* This property determines if the specified user can edit the view object. All of the below assumes the user has base Create/Update permissions on the "User Views" entity. | ||
* The flow of the logic is: | ||
* 1) The view is a new record, by definition the user can edit this because it is new | ||
* 2) The user is the owner of the current view - e.g. UserID in the view record matches the ID of the user provided, allowed | ||
* 3) The user is a sysadmin (Type === 'Owner' in the User object), allowed | ||
* 4) If neither of the above conditions are met, the Resource Permissions are checked to see if the user, directly or via Roles, has either Edit or Owner permissions on the current view | ||
* @returns | ||
*/ | ||
get UserCanEdit() { | ||
if (this._cachedCanUserEdit === null) { | ||
this._cachedCanUserEdit = this.CalculateUserCanEdit(); | ||
} | ||
return this._cachedCanUserEdit; | ||
} | ||
/** | ||
* This property determines if the specified user can delete the view object. All of the below assumes the user has base Delete permissions on the "User Views" entity. | ||
* The flow of the logic is: | ||
* 1) The view is a new record, by definition the user can't delete this because it is new | ||
* 2) The user is the owner of the current view - e.g. UserID in the view record matches the ID of the user provided, allowed | ||
* 3) The user is a sysadmin (Type === 'Owner' in the User object), allowed | ||
* 4) If neither of the above conditions are met, the Resource Permissions are checked to see if the user, directly or via Roles, has OWNER permissions on the current view | ||
*/ | ||
get UserCanDelete() { | ||
if (this._cachedUserCanDelete === null) { | ||
this._cachedUserCanDelete = this.CalculateUserCanDelete(); | ||
} | ||
return this._cachedUserCanDelete; | ||
} | ||
ResetCachedCanUserSettings() { | ||
this._cachedCanUserEdit = null; | ||
this._cachedUserCanDelete = null; | ||
} | ||
CalculateUserCanDelete() { | ||
if (!this.IsSaved) | ||
return false; // new records can't be deleted | ||
else { | ||
// EXISTING record in the database | ||
// check to see if the current user is the OWNER of this view via the UserID property in the record, if there's a match, the user OWNS this views | ||
const md = new core_1.Metadata(); | ||
const user = this.ContextCurrentUser || md.CurrentUser; // take the context current user if it is set, otherwise use the global current user | ||
if (this.UserID === user.ID || user.Type.trim().toLowerCase() === 'owner') { | ||
return this.CheckPermissions(core_1.EntityPermissionType.Delete, false); // exsiting records OWNED by current user, can be edited so long as we have Update permissions; | ||
} | ||
else { | ||
// if the user is not an admin, and they are NOT the owner of the view, we check the permissions on the resource | ||
const perms = ResourcePermissionEngine_1.ResourcePermissionEngine.Instance.GetUserResourcePermissionLevel(this.ViewResourceTypeID, this.ID, user); | ||
return perms === 'Owner'; // this is the only level that can delete a view | ||
} | ||
} | ||
} | ||
CalculateUserCanEdit() { | ||
if (!this.IsSaved) { | ||
return this.CheckPermissions(core_1.EntityPermissionType.Create, false); // new records an be edited so long as we have Create permissions | ||
} | ||
else { | ||
// EXISTING record in the database | ||
// check to see if the current user is the OWNER of this view via the UserID property in the record, if there's a match, the user OWNS this views | ||
// so of course they can save it | ||
const md = new core_1.Metadata(); | ||
const user = this.ContextCurrentUser || md.CurrentUser; // take the context current user if it is set, otherwise use the global current user | ||
if (this.UserID === user.ID || user.Type.trim().toLowerCase() === 'owner') { | ||
return this.CheckPermissions(core_1.EntityPermissionType.Update, false); // exsiting records OWNED by current user, can be edited so long as we have Update permissions; | ||
} | ||
else { | ||
// if the user is not an admin, and they are NOT the owner of the view, we check the permissions on the resource | ||
const perms = ResourcePermissionEngine_1.ResourcePermissionEngine.Instance.GetUserResourcePermissionLevel(this.ViewResourceTypeID, this.ID, user); | ||
return perms === 'Owner' || perms === 'Edit'; // these are the only two levels that can save a view | ||
} | ||
} | ||
} | ||
/** | ||
* Returns the ID of the Resource Type metadata record that corresponds to the User Views entity | ||
*/ | ||
get ViewResourceTypeID() { | ||
if (!this._ViewResourceTypeID) { | ||
const rt = ResourcePermissionEngine_1.ResourcePermissionEngine.Instance.ResourceTypes; | ||
const rtUV = rt.find(r => r.Entity === 'User Views'); | ||
if (!rtUV) | ||
throw new Error('Unable to find Resource Type for User Views entity'); | ||
this._ViewResourceTypeID = rtUV.ID; | ||
} | ||
return this._ViewResourceTypeID; | ||
} | ||
async Load(ID, EntityRelationshipsToLoad) { | ||
@@ -127,16 +215,55 @@ // first load up the view info, use the superclass to do this | ||
} | ||
this.ResetCachedCanUserSettings(); | ||
return result; | ||
} | ||
async Delete() { | ||
if (this.UserCanDelete) { | ||
// if we get here, the user can delete the view, so we delete it | ||
if (super.Delete()) { | ||
this.ResetCachedCanUserSettings(); | ||
return true; | ||
} | ||
else | ||
return false; | ||
} | ||
else { | ||
// if we get here, the user can't delete the view, so we don't delete it, add a last error and return false | ||
const res = new core_1.BaseEntityResult(); | ||
res.Success = false; | ||
res.Message = 'User does not have permission to delete this view'; | ||
res.StartedAt = new Date(); | ||
res.EndedAt = new Date(); | ||
this.ResultHistory.push(res); | ||
return false; | ||
} | ||
} | ||
async Save(options) { | ||
// we want to preprocess the Save() call because we need to regenerate the WhereClause in some situations | ||
if (!this.ID || | ||
options?.IgnoreDirtyState || | ||
this.Fields.find(c => c.Name.toLowerCase() == 'filterstate')?.Dirty || | ||
this.Fields.find(c => c.Name.toLowerCase() == 'smartfilterenabled')?.Dirty || | ||
this.Fields.find(c => c.Name.toLowerCase() == 'smartfilterprompt')?.Dirty) { | ||
// either we're ignoring dirty state or the filter state is dirty, so we need to update the where clause | ||
await this.UpdateWhereClause(options?.IgnoreDirtyState); | ||
if (this.UserCanEdit) { | ||
// we want to preprocess the Save() call because we need to regenerate the WhereClause in some situations | ||
if (!this.ID || | ||
options?.IgnoreDirtyState || | ||
this.Fields.find(c => c.Name.toLowerCase() == 'filterstate')?.Dirty || | ||
this.Fields.find(c => c.Name.toLowerCase() == 'smartfilterenabled')?.Dirty || | ||
this.Fields.find(c => c.Name.toLowerCase() == 'smartfilterprompt')?.Dirty) { | ||
// either we're ignoring dirty state or the filter state is dirty, so we need to update the where clause | ||
await this.UpdateWhereClause(options?.IgnoreDirtyState); | ||
} | ||
// now call our superclass to do the actual save() | ||
if (super.Save(options)) { | ||
this.ResetCachedCanUserSettings(); | ||
return true; | ||
} | ||
else | ||
return false; | ||
} | ||
// now just call our superclass to do the actual save() | ||
return super.Save(options); | ||
else { | ||
// if we get here, the user can't edit the view, so we don't save it, add a last error and return false | ||
const res = new core_1.BaseEntityResult(); | ||
res.Success = false; | ||
res.Message = this.ID ? 'User does not have permission to edit this view' : 'User does not have permission to create a new view'; | ||
res.StartedAt = new Date(); | ||
res.EndedAt = new Date(); | ||
this.ResultHistory.push(res); | ||
return false; | ||
} | ||
} | ||
@@ -183,2 +310,3 @@ async SetDefaultsFromEntity(e) { | ||
} | ||
this.ResetCachedCanUserSettings(); | ||
return result; | ||
@@ -185,0 +313,0 @@ } |
@@ -8,2 +8,3 @@ export * from './generated/entity_subclasses'; | ||
export * from './custom/ScheduledActionExtended'; | ||
export * from './custom/ResourcePermissions/ResourcePermissionEngine'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -24,2 +24,3 @@ "use strict"; | ||
__exportStar(require("./custom/ScheduledActionExtended"), exports); | ||
__exportStar(require("./custom/ResourcePermissions/ResourcePermissionEngine"), exports); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@memberjunction/core-entities", | ||
"version": "2.7.1", | ||
"version": "2.8.0", | ||
"description": "Entity subclasses for the metadata layer of MemberJunction defined in the MJ_CORE schema (usually 'admin'), distributed as part of each release of MemberJunction", | ||
@@ -22,6 +22,6 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@memberjunction/core": "2.7.1", | ||
"@memberjunction/global": "2.7.1", | ||
"@memberjunction/core": "2.8.0", | ||
"@memberjunction/global": "2.8.0", | ||
"zod": "^3.23.8" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
2525981
38
56587
+ Added@memberjunction/core@2.8.0(transitive)
+ Added@memberjunction/global@2.8.0(transitive)
- Removed@memberjunction/core@2.7.1(transitive)
- Removed@memberjunction/global@2.7.1(transitive)
Updated@memberjunction/core@2.8.0
Updated@memberjunction/global@2.8.0