Skip to content

Commit

Permalink
Release 0.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dennemark committed Sep 24, 2024
1 parent 7130a33 commit 7874048
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 27 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@


## [0.6.0](https://github.com/dennemark/prisma-extension-casl/compare/0.5.20...0.6.0) (2024-09-24)


### Features

* :sparkles: add possibility to store simplified crud rights on model ([7130a33](https://github.com/dennemark/prisma-extension-casl/commit/7130a3367c9fe0810cc5406f861eee1e0991098c))

## [0.5.20](https://github.com/dennemark/prisma-extension-casl/compare/0.5.19...0.5.20) (2024-09-23)


Expand Down
4 changes: 2 additions & 2 deletions dist/index.d.mts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type PrismaCaslOperation = 'create' | 'createMany' | 'createManyAndReturn' | 'up
* @param model Prisma model
* @returns Enriched query with casl authorization
*/
declare function applyCaslToQuery(operation: PrismaCaslOperation, args: any, abilities: PureAbility<AbilityTuple, PrismaQuery>, model: Prisma.ModelName): {
declare function applyCaslToQuery(operation: PrismaCaslOperation, args: any, abilities: PureAbility<AbilityTuple, PrismaQuery>, model: Prisma.ModelName, queryAllRuleRelations?: boolean): {
creationTree: CreationTree | undefined;
args: any;
mask: Record<string, any>;
Expand All @@ -42,7 +42,7 @@ declare function applyCaslToQuery(operation: PrismaCaslOperation, args: any, abi
* - this is a function call to instantiate abilities on each prisma query to allow adding i.e. context or claims
* @returns enriched prisma client
*/
declare function useCaslAbilities(getAbilityFactory: () => AbilityBuilder<PureAbility<AbilityTuple, PrismaQuery>>): (client: any) => {
declare function useCaslAbilities(getAbilityFactory: () => AbilityBuilder<PureAbility<AbilityTuple, PrismaQuery>>, permissionField?: string): (client: any) => {
$extends: {
extArgs: {
result: {};
Expand Down
4 changes: 2 additions & 2 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type PrismaCaslOperation = 'create' | 'createMany' | 'createManyAndReturn' | 'up
* @param model Prisma model
* @returns Enriched query with casl authorization
*/
declare function applyCaslToQuery(operation: PrismaCaslOperation, args: any, abilities: PureAbility<AbilityTuple, PrismaQuery>, model: Prisma.ModelName): {
declare function applyCaslToQuery(operation: PrismaCaslOperation, args: any, abilities: PureAbility<AbilityTuple, PrismaQuery>, model: Prisma.ModelName, queryAllRuleRelations?: boolean): {
creationTree: CreationTree | undefined;
args: any;
mask: Record<string, any>;
Expand All @@ -42,7 +42,7 @@ declare function applyCaslToQuery(operation: PrismaCaslOperation, args: any, abi
* - this is a function call to instantiate abilities on each prisma query to allow adding i.e. context or claims
* @returns enriched prisma client
*/
declare function useCaslAbilities(getAbilityFactory: () => AbilityBuilder<PureAbility<AbilityTuple, PrismaQuery>>): (client: any) => {
declare function useCaslAbilities(getAbilityFactory: () => AbilityBuilder<PureAbility<AbilityTuple, PrismaQuery>>, permissionField?: string): (client: any) => {
$extends: {
extArgs: {
result: {};
Expand Down
47 changes: 36 additions & 11 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,7 @@ function getNestedQueryRelations(args, abilities, action, model, creationSelectQ
const ability = e3(abilities.rules.filter((rule) => rule.conditions).map((rule) => {
return {
...rule,
action: action === "all" ? action : rule.action,
inverted: false
};
}));
Expand Down Expand Up @@ -1239,7 +1240,7 @@ function transformDataToWhereQuery(args, model) {
}

// src/applyCaslToQuery.ts
function applyCaslToQuery(operation, args, abilities, model) {
function applyCaslToQuery(operation, args, abilities, model, queryAllRuleRelations) {
const operationAbility = caslOperationDict[operation];
m5(abilities, operationAbility.action)[model];
let creationTree = void 0;
Expand All @@ -1263,12 +1264,35 @@ function applyCaslToQuery(operation, args, abilities, model) {
delete args.include;
delete args.select;
}
const result = operationAbility.includeSelectQuery ? applyRuleRelationsQuery(args, abilities, operationAbility.action, model, creationTree) : { args, mask: void 0, creationTree };
const result = operationAbility.includeSelectQuery ? applyRuleRelationsQuery(args, abilities, queryAllRuleRelations ? "all" : operationAbility.action, model, creationTree) : { args, mask: void 0, creationTree };
return result;
}

// src/storePermissions.ts
function storePermissions(result, abilities, model, prop) {
if (prop === void 0) {
return result;
}
const actions = ["create", "read", "update", "delete"];
const storeProp = (entry) => {
entry[prop] = [];
actions.forEach((action) => {
if (abilities.can(action, getSubject(model, entry))) {
entry[prop].push(action);
}
});
return entry;
};
if (Array.isArray(result)) {
const res = result.map(storeProp);
return res;
} else {
return storeProp(result);
}
}

// src/filterQueryResults.ts
function filterQueryResults(result, mask, creationTree, abilities, model) {
function filterQueryResults(result, mask, creationTree, abilities, model, permissionField) {
if (typeof result === "number") {
return result;
}
Expand All @@ -1291,7 +1315,7 @@ function filterQueryResults(result, mask, creationTree, abilities, model) {
}
const permittedFields = getPermittedFields(abilities, "read", model, entry);
let hasKeys = false;
Object.keys(entry).forEach((field) => {
Object.keys(entry).filter((field) => field !== permissionField).forEach((field) => {
const relationField = relationFieldsByModel[model][field];
if (relationField) {
const nestedCreationTree = creationTree && field in creationTree.children ? creationTree.children[field] : void 0;
Expand All @@ -1311,15 +1335,16 @@ function filterQueryResults(result, mask, creationTree, abilities, model) {
});
return hasKeys && Object.keys(entry).length > 0 ? entry : null;
};
if (Array.isArray(result)) {
return result.map((entry) => filterPermittedFields(entry)).filter((x5) => x5);
const permissionResult = storePermissions(result, abilities, model, permissionField);
if (Array.isArray(permissionResult)) {
return permissionResult.map((entry) => filterPermittedFields(entry)).filter((x5) => x5);
} else {
return filterPermittedFields(result);
return filterPermittedFields(permissionResult);
}
}

// src/index.ts
function useCaslAbilities(getAbilityFactory) {
function useCaslAbilities(getAbilityFactory, permissionField) {
return import_client2.Prisma.defineExtension((client) => {
let getAbilities = () => getAbilityFactory();
return client.$extends({
Expand Down Expand Up @@ -1366,13 +1391,13 @@ function useCaslAbilities(getAbilityFactory) {
}
getAbilities = () => getAbilityFactory();
perf?.mark("prisma-casl-extension-1");
const caslQuery = applyCaslToQuery(operation, args, abilities, model);
const caslQuery = applyCaslToQuery(operation, args, abilities, model, permissionField ? true : false);
perf?.mark("prisma-casl-extension-2");
logger?.log("Query Args", JSON.stringify(caslQuery.args));
logger?.log("Query Mask", JSON.stringify(caslQuery.mask));
const cleanupResults = (result) => {
perf?.mark("prisma-casl-extension-3");
const res = filterQueryResults(result, caslQuery.mask, caslQuery.creationTree, abilities, getFluentModel(model, rest));
const filteredResult = filterQueryResults(result, caslQuery.mask, caslQuery.creationTree, abilities, getFluentModel(model, rest), permissionField);
if (perf) {
perf.mark("prisma-casl-extension-4");
logger?.log(
Expand All @@ -1387,7 +1412,7 @@ function useCaslAbilities(getAbilityFactory) {
})
);
}
return operation === "createMany" ? { count: res.length } : res;
return operation === "createMany" ? { count: filteredResult.length } : filteredResult;
};
const operationAbility = caslOperationDict[operation];
if (operationAbility.action === "update" || operationAbility.action === "create") {
Expand Down
47 changes: 36 additions & 11 deletions dist/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,7 @@ function getNestedQueryRelations(args, abilities, action, model, creationSelectQ
const ability = e3(abilities.rules.filter((rule) => rule.conditions).map((rule) => {
return {
...rule,
action: action === "all" ? action : rule.action,
inverted: false
};
}));
Expand Down Expand Up @@ -1214,7 +1215,7 @@ function transformDataToWhereQuery(args, model) {
}

// src/applyCaslToQuery.ts
function applyCaslToQuery(operation, args, abilities, model) {
function applyCaslToQuery(operation, args, abilities, model, queryAllRuleRelations) {
const operationAbility = caslOperationDict[operation];
m5(abilities, operationAbility.action)[model];
let creationTree = void 0;
Expand All @@ -1238,12 +1239,35 @@ function applyCaslToQuery(operation, args, abilities, model) {
delete args.include;
delete args.select;
}
const result = operationAbility.includeSelectQuery ? applyRuleRelationsQuery(args, abilities, operationAbility.action, model, creationTree) : { args, mask: void 0, creationTree };
const result = operationAbility.includeSelectQuery ? applyRuleRelationsQuery(args, abilities, queryAllRuleRelations ? "all" : operationAbility.action, model, creationTree) : { args, mask: void 0, creationTree };
return result;
}

// src/storePermissions.ts
function storePermissions(result, abilities, model, prop) {
if (prop === void 0) {
return result;
}
const actions = ["create", "read", "update", "delete"];
const storeProp = (entry) => {
entry[prop] = [];
actions.forEach((action) => {
if (abilities.can(action, getSubject(model, entry))) {
entry[prop].push(action);
}
});
return entry;
};
if (Array.isArray(result)) {
const res = result.map(storeProp);
return res;
} else {
return storeProp(result);
}
}

// src/filterQueryResults.ts
function filterQueryResults(result, mask, creationTree, abilities, model) {
function filterQueryResults(result, mask, creationTree, abilities, model, permissionField) {
if (typeof result === "number") {
return result;
}
Expand All @@ -1266,7 +1290,7 @@ function filterQueryResults(result, mask, creationTree, abilities, model) {
}
const permittedFields = getPermittedFields(abilities, "read", model, entry);
let hasKeys = false;
Object.keys(entry).forEach((field) => {
Object.keys(entry).filter((field) => field !== permissionField).forEach((field) => {
const relationField = relationFieldsByModel[model][field];
if (relationField) {
const nestedCreationTree = creationTree && field in creationTree.children ? creationTree.children[field] : void 0;
Expand All @@ -1286,15 +1310,16 @@ function filterQueryResults(result, mask, creationTree, abilities, model) {
});
return hasKeys && Object.keys(entry).length > 0 ? entry : null;
};
if (Array.isArray(result)) {
return result.map((entry) => filterPermittedFields(entry)).filter((x5) => x5);
const permissionResult = storePermissions(result, abilities, model, permissionField);
if (Array.isArray(permissionResult)) {
return permissionResult.map((entry) => filterPermittedFields(entry)).filter((x5) => x5);
} else {
return filterPermittedFields(result);
return filterPermittedFields(permissionResult);
}
}

// src/index.ts
function useCaslAbilities(getAbilityFactory) {
function useCaslAbilities(getAbilityFactory, permissionField) {
return Prisma2.defineExtension((client) => {
let getAbilities = () => getAbilityFactory();
return client.$extends({
Expand Down Expand Up @@ -1341,13 +1366,13 @@ function useCaslAbilities(getAbilityFactory) {
}
getAbilities = () => getAbilityFactory();
perf?.mark("prisma-casl-extension-1");
const caslQuery = applyCaslToQuery(operation, args, abilities, model);
const caslQuery = applyCaslToQuery(operation, args, abilities, model, permissionField ? true : false);
perf?.mark("prisma-casl-extension-2");
logger?.log("Query Args", JSON.stringify(caslQuery.args));
logger?.log("Query Mask", JSON.stringify(caslQuery.mask));
const cleanupResults = (result) => {
perf?.mark("prisma-casl-extension-3");
const res = filterQueryResults(result, caslQuery.mask, caslQuery.creationTree, abilities, getFluentModel(model, rest));
const filteredResult = filterQueryResults(result, caslQuery.mask, caslQuery.creationTree, abilities, getFluentModel(model, rest), permissionField);
if (perf) {
perf.mark("prisma-casl-extension-4");
logger?.log(
Expand All @@ -1362,7 +1387,7 @@ function useCaslAbilities(getAbilityFactory) {
})
);
}
return operation === "createMany" ? { count: res.length } : res;
return operation === "createMany" ? { count: filteredResult.length } : filteredResult;
};
const operationAbility = caslOperationDict[operation];
if (operationAbility.action === "update" || operationAbility.action === "create") {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "prisma-extension-casl",
"version": "0.5.20",
"version": "0.6.0",
"description": "Enforce casl abilities on prisma client ",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down

0 comments on commit 7874048

Please sign in to comment.