This commit is contained in:
Simon Larsen
2023-02-27 20:54:37 +00:00
parent 0707892dd0
commit 741e72996c

View File

@@ -32,7 +32,7 @@ import { JSONObject } from 'Common/Types/JSON';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { getAllEnvVars, IsBillingEnabled } from '../Config';
import SubscriptionPlan from 'Common/Types/Billing/SubscriptionPlan';
import NotAuthenticatedException from "Common/Types/Exception/NotAuthenticatedException";
import NotAuthenticatedException from 'Common/Types/Exception/NotAuthenticatedException';
export interface CheckReadPermissionType<TBaseModel extends BaseModel> {
query: Query<TBaseModel>;
@@ -42,7 +42,7 @@ export interface CheckReadPermissionType<TBaseModel extends BaseModel> {
export default class ModelPermission {
public static async checkDeletePermission<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
query: Query<TBaseModel>,
props: DatabaseCommonInteractionProps
): Promise<Query<TBaseModel>> {
@@ -65,7 +65,7 @@ export default class ModelPermission {
}
public static async checkUpdatePermissions<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
query: Query<TBaseModel>,
data: QueryDeepPartialEntity<TBaseModel>,
props: DatabaseCommonInteractionProps
@@ -96,7 +96,7 @@ export default class ModelPermission {
}
public static checkCreatePermissions<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
data: TBaseModel,
props: DatabaseCommonInteractionProps
): void {
@@ -120,7 +120,7 @@ export default class ModelPermission {
}
private static checkDataColumnPermissions<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
data: TBaseModel,
props: DatabaseCommonInteractionProps,
requestType: DatabaseRequestType
@@ -178,7 +178,7 @@ export default class ModelPermission {
}
public static async checkReadPermission<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
query: Query<TBaseModel>,
select: Select<TBaseModel> | null,
populate: Populate<TBaseModel> | null,
@@ -187,9 +187,12 @@ export default class ModelPermission {
const model: BaseModel = new modelType();
if (!props.isRoot) {
//check if the user is logged in.
this.checkIfUserIsLoggedIn(modelType, props, DatabaseRequestType.Read);
//check if the user is logged in.
this.checkIfUserIsLoggedIn(
modelType,
props,
DatabaseRequestType.Read
);
// add tenant scope.
query = await this.addTenantScopeToQuery(
@@ -242,7 +245,7 @@ export default class ModelPermission {
tableColumnMetadata.modelType &&
(tableColumnMetadata.type === TableColumnType.Entity ||
tableColumnMetadata.type ===
TableColumnType.EntityArray)
TableColumnType.EntityArray)
) {
const accessControlIds: Array<ObjectID> =
this.getAccessControlIdsForQuery(
@@ -294,7 +297,7 @@ export default class ModelPermission {
}
private static serializeQuery<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
query: Query<TBaseModel>
): Query<TBaseModel> {
const model: BaseModel = new modelType();
@@ -445,7 +448,7 @@ export default class ModelPermission {
}
private static getAccessControlIdsForQuery<TBaseModel extends BaseModel>(
modelType: { new(): BaseModel },
modelType: { new (): BaseModel },
query: Query<TBaseModel>,
select: Select<TBaseModel> | null,
props: DatabaseCommonInteractionProps
@@ -492,7 +495,7 @@ export default class ModelPermission {
for (const accessControlPermission of accessControlPermissions) {
if (
accessControlPermission.permission ===
readPermissions &&
readPermissions &&
accessControlPermission.labelIds.length > 0
) {
labelIds = [
@@ -534,7 +537,7 @@ export default class ModelPermission {
}
private static checkPopulatePermission<TBaseModel extends BaseModel>(
modelType: { new(): BaseModel },
modelType: { new (): BaseModel },
populate: Populate<TBaseModel>,
props: DatabaseCommonInteractionProps
): void {
@@ -556,10 +559,10 @@ export default class ModelPermission {
if (!tableColumnMetadata.modelType) {
throw new BadDataException(
'Populate not supported on ' +
key +
' of ' +
model.singularName +
' because this column modelType is not found.'
key +
' of ' +
model.singularName +
' because this column modelType is not found.'
);
}
@@ -625,8 +628,10 @@ export default class ModelPermission {
}
throw new NotAuthorizedException(
`You do not have permissions to read ${relatedModel.singularName
} on ${model.singularName
`You do not have permissions to read ${
relatedModel.singularName
} on ${
model.singularName
}. You need one of these permissions: ${PermissionHelper.getPermissionTitles(
readPermissions
).join(', ')}`
@@ -637,10 +642,10 @@ export default class ModelPermission {
} else {
throw new BadDataException(
'Populate not supported on ' +
key +
' of ' +
model.singularName +
' because this column is not of type Entity or EntityArray'
key +
' of ' +
model.singularName +
' because this column is not of type Entity or EntityArray'
);
}
}
@@ -660,7 +665,7 @@ export default class ModelPermission {
}
private static checkQueryPermission<TBaseModel extends BaseModel>(
modelType: { new(): BaseModel },
modelType: { new (): BaseModel },
query: Query<TBaseModel>,
props: DatabaseCommonInteractionProps
): void {
@@ -707,14 +712,12 @@ export default class ModelPermission {
}
private static async addTenantScopeToQuery<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
query: Query<TBaseModel>,
select: Select<TBaseModel> | null,
populate: Populate<TBaseModel> | null,
props: DatabaseCommonInteractionProps
): Promise<Query<TBaseModel>> {
const model: BaseModel = new modelType();
const tenantColumn: string | null = model.getTenantColumn();
@@ -727,22 +730,18 @@ export default class ModelPermission {
// If this model has a tenantColumn, and request has tenantId, and is multiTenantQuery null then add tenantId to query.
if (tenantColumn && props.tenantId && !props.isMultiTenantRequest) {
(query as any)[tenantColumn] = props.tenantId;
} else if (
model.isUserQueryWithoutTenantAllowed() &&
model.getUserColumn() &&
props.userId
) {
(query as any)[model.getUserColumn() as string] = props.userId;
} else if (
tenantColumn &&
!props.tenantId &&
props.userGlobalAccessPermission
) {
// for each of these projectIds,
// check if they have valid permissions for these projects
// and if they do, include them in the query.
@@ -792,11 +791,10 @@ export default class ModelPermission {
if (queries.length === 0) {
throw new NotAuthorizedException(
lastException?.message ||
'Does not have permission to read ' + model.singularName
'Does not have permission to read ' + model.singularName
);
}
return queries as any;
}
@@ -804,7 +802,7 @@ export default class ModelPermission {
}
private static getModelColumnsByPermissions<TBaseModel extends BaseModel>(
modelType: { new(): TBaseModel },
modelType: { new (): TBaseModel },
userPermissions: Array<UserPermission>,
requestType: DatabaseRequestType
): Columns {
@@ -854,7 +852,7 @@ export default class ModelPermission {
}
private static checkSelectPermission<TBaseModel extends BaseModel>(
modelType: { new(): BaseModel },
modelType: { new (): BaseModel },
select: Select<TBaseModel>,
props: DatabaseCommonInteractionProps
): void {
@@ -900,7 +898,7 @@ export default class ModelPermission {
}
private static getModelPermissions(
modelType: { new(): BaseModel },
modelType: { new (): BaseModel },
type: DatabaseRequestType
): Array<Permission> {
let modelPermissions: Array<Permission> = [];
@@ -926,7 +924,7 @@ export default class ModelPermission {
}
private static isPublicPermissionAllowed(
modelType: { new(): BaseModel },
modelType: { new (): BaseModel },
type: DatabaseRequestType
): boolean {
let isPublicAllowed: boolean = false;
@@ -936,26 +934,28 @@ export default class ModelPermission {
return isPublicAllowed;
}
public static checkIfUserIsLoggedIn(modelType: { new(): BaseModel },
public static checkIfUserIsLoggedIn(
modelType: { new (): BaseModel },
props: DatabaseCommonInteractionProps,
type: DatabaseRequestType): void {
type: DatabaseRequestType
): void {
// 1 CHECK: PUBLIC check -- Check if this is a public request and if public is allowed.
if (!this.isPublicPermissionAllowed(modelType, type) && !props.userId) {
// this means the record is not publicly createable and the user is not logged in.
throw new NotAuthenticatedException(
`A user should be logged in to ${type} record of ${new modelType().singularName
`A user should be logged in to ${type} record of ${
new modelType().singularName
}.`
);
}
}
private static checkModelLevelPermissions(
modelType: { new(): BaseModel },
modelType: { new (): BaseModel },
props: DatabaseCommonInteractionProps,
type: DatabaseRequestType
): void {
this.checkIfUserIsLoggedIn(modelType, props, type);
// 2nd CHECK: Does user have access to CRUD data on this model.
@@ -975,7 +975,8 @@ export default class ModelPermission {
)
) {
throw new NotAuthorizedException(
`You do not have permissions to ${type} ${new modelType().singularName
`You do not have permissions to ${type} ${
new modelType().singularName
}. You need one of these permissions: ${PermissionHelper.getPermissionTitles(
modelPermissions
).join(', ')}`
@@ -1009,8 +1010,8 @@ export default class ModelPermission {
) {
throw new PaymentRequiredException(
'Please upgrade your plan to ' +
model.createBillingPlan +
' to access this feature'
model.createBillingPlan +
' to access this feature'
);
}
}
@@ -1028,8 +1029,8 @@ export default class ModelPermission {
) {
throw new PaymentRequiredException(
'Please upgrade your plan to ' +
model.createBillingPlan +
' to access this feature'
model.createBillingPlan +
' to access this feature'
);
}
}
@@ -1047,8 +1048,8 @@ export default class ModelPermission {
) {
throw new PaymentRequiredException(
'Please upgrade your plan to ' +
model.createBillingPlan +
' to access this feature'
model.createBillingPlan +
' to access this feature'
);
}
}
@@ -1063,8 +1064,8 @@ export default class ModelPermission {
) {
throw new PaymentRequiredException(
'Please upgrade your plan to ' +
model.createBillingPlan +
' to access this feature'
model.createBillingPlan +
' to access this feature'
);
}
}