@stacksjs/auth 0.75.236 → 0.75.237

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/gate.js +1 -1
  2. package/package.json +14 -14
package/dist/gate.js CHANGED
@@ -1 +1 @@
1
- export function defineGates(definition){return definition}const RESERVED_POLICY_MEMBERS=new Set(["before","allow","deny","denyIf","denyUnless","allowIf","constructor"]);export class AuthorizationResponse{isAllowed;message;code;constructor(allowed,message,code){this.isAllowed=allowed;this.message=message;this.code=code}static allow(message){return new AuthorizationResponse(!0,message)}static deny(message,code){return new AuthorizationResponse(!1,message||"This action is unauthorized.",code)}allowed(){return this.isAllowed}denied(){return!this.isAllowed}authorize(){if(!this.isAllowed)throw new AuthorizationException(this.message||"This action is unauthorized.",this.code)}}export class AuthorizationException extends Error{code;status;constructor(message="This action is unauthorized.",code,status=403){super(message);this.code=code;this.status=status;this.name="AuthorizationException"}}const state={gates:new Map,policies:new Map,beforeCallbacks:[],afterCallbacks:[]};export function define(ability,callback){state.gates.set(ability,callback)}export function policy(model,policyClass){const modelName=typeof model==="string"?model:model.name;state.policies.set(modelName,policyClass)}export function before(callback){state.beforeCallbacks.push(callback)}export function after(callback){state.afterCallbacks.push(callback)}export async function allows(ability,user,...args){return check(ability,user,...args)}export async function denies(ability,user,...args){return!await check(ability,user,...args)}export async function can(ability,user,...args){return check(ability,user,...args)}export async function cannot(ability,user,...args){return!await check(ability,user,...args)}export async function any(abilities,user,...args){for(const ability of abilities)if(await check(ability,user,...args))return!0;return!1}export async function all(abilities,user,...args){for(const ability of abilities)if(!await check(ability,user,...args))return!1;return!0}export async function none(abilities,user,...args){return!await any(abilities,user,...args)}export async function authorize(ability,user,...args){const result=await inspect(ability,user,...args);if(!result.isAllowed)throw new AuthorizationException(result.message,result.code);return result}export async function inspect(ability,user,...args){let response=null;for(const callback of state.beforeCallbacks){const beforeResult=await callback(user,ability,args);if(beforeResult===!0){response=AuthorizationResponse.allow();break}if(beforeResult===!1){response=AuthorizationResponse.deny();break}}if(!response)response=await resolveAbility(ability,user,args);for(const callback of state.afterCallbacks){const afterResult=await callback(user,ability,response.isAllowed,args);if(typeof afterResult==="boolean")return afterResult?AuthorizationResponse.allow():AuthorizationResponse.deny()}return response}async function resolveAbility(ability,user,args){const model=args[0];if(model&&typeof model==="object"){const policyClass=state.policies.get(model.constructor?.name);if(policyClass){const response=await runPolicy(policyClass,ability,user,args);if(response)return response}}const gate=state.gates.get(ability);if(gate)return normalizeResponse(await gate(user,...args));return AuthorizationResponse.deny(`No gate or policy defined for ability: ${ability}`)}async function runPolicy(policyClass,ability,user,args){const policyInstance=new policyClass;if(policyInstance.before){const beforeResult=await policyInstance.before(user,ability);if(beforeResult===!0)return AuthorizationResponse.allow();if(beforeResult===!1)return AuthorizationResponse.deny()}const method=RESERVED_POLICY_MEMBERS.has(ability)?void 0:policyInstance[ability];if(typeof method!=="function")return null;const result=await method.call(policyInstance,user,...args);return normalizeResponse(result??!1)}export async function inspectFor(model,ability,user,...args){const modelName=typeof model==="string"?model:model.name,policyClass=state.policies.get(modelName);if(!policyClass)return null;let response=null;for(const callback of state.beforeCallbacks){const beforeResult=await callback(user,ability,args);if(beforeResult===!0){response=AuthorizationResponse.allow();break}if(beforeResult===!1){response=AuthorizationResponse.deny();break}}response??=await runPolicy(policyClass,ability,user,args)??AuthorizationResponse.deny(`${modelName}'s policy defines no ${String(ability)} ability`);for(const callback of state.afterCallbacks){const afterResult=await callback(user,ability,response.isAllowed,args);if(typeof afterResult==="boolean")return afterResult?AuthorizationResponse.allow():AuthorizationResponse.deny()}return response}export async function allowsFor(model,ability,user,...args){const response=await inspectFor(model,ability,user,...args);return response?response.isAllowed:!0}async function check(ability,user,...args){return(await inspect(ability,user,...args)).isAllowed}function normalizeResponse(result){if(result instanceof AuthorizationResponse)return result;if(typeof result!=="boolean")throw TypeError(`[gate] Policy must return boolean or AuthorizationResponse; got ${typeof result}. If you returned a model/value by mistake, return \`true\`/\`false\` instead.`);return result?AuthorizationResponse.allow():AuthorizationResponse.deny()}export function getPolicyFor(model){if(!model||typeof model!=="object")return null;const modelName=model.constructor?.name,policyClass=state.policies.get(modelName);if(policyClass)return new policyClass;return null}export function has(ability){return state.gates.has(ability)}export function hasPolicy(model){const modelName=typeof model==="string"?model:model.name;return state.policies.has(modelName)}export function abilities(){return Array.from(state.gates.keys())}export function flush(){state.gates.clear();state.policies.clear();state.beforeCallbacks=[];state.afterCallbacks=[]}export const Gate={define,policy,before,after,allows,allowsFor,denies,can,cannot,any,all,none,authorize,inspect,inspectFor,has,hasPolicy,abilities,getPolicyFor,flush,AuthorizationResponse,AuthorizationException};export default Gate;
1
+ export function defineGates(definition){return definition}const RESERVED_POLICY_MEMBERS=new Set(["before","allow","deny","denyIf","denyUnless","allowIf","constructor"]);export class AuthorizationResponse{isAllowed;message;code;constructor(allowed,message,code){this.isAllowed=allowed;this.message=message;this.code=code;WeakSet.prototype.add.call(state.responses,this)}static allow(message){return new AuthorizationResponse(!0,message)}static deny(message,code){return new AuthorizationResponse(!1,message||"This action is unauthorized.",code)}allowed(){return this.isAllowed}denied(){return!this.isAllowed}authorize(){if(!this.isAllowed)throw new AuthorizationException(this.message||"This action is unauthorized.",this.code)}}export class AuthorizationException extends Error{code;status;constructor(message="This action is unauthorized.",code,status=403){super(message);this.code=code;this.status=status;this.name="AuthorizationException"}}const GATE_PROCESS_STATE=Symbol.for("@stacksjs/auth:gate-process-state");function ownValue(object,key){const descriptor=Object.getOwnPropertyDescriptor(object,key);return descriptor&&"value"in descriptor?descriptor.value:void 0}function callbackArray(value){if(!Array.isArray(value))return!1;for(let index=0;index<value.length;index++)if(typeof ownValue(value,String(index))!=="function")return!1;return!0}function processGateState(){const descriptor=Object.getOwnPropertyDescriptor(globalThis,GATE_PROCESS_STATE);if(!descriptor){const created={version:1,gates:new Map,policies:new Map,beforeCallbacks:[],afterCallbacks:[],responses:new WeakSet};Object.defineProperty(globalThis,GATE_PROCESS_STATE,{value:created});return created}const candidate="value"in descriptor?descriptor.value:void 0;if(candidate&&typeof candidate==="object"&&ownValue(candidate,"version")===1){const gates=ownValue(candidate,"gates"),policies=ownValue(candidate,"policies"),responses=ownValue(candidate,"responses");try{Map.prototype.has.call(gates,"");Map.prototype.has.call(policies,"");WeakSet.prototype.has.call(responses,candidate);if(callbackArray(ownValue(candidate,"beforeCallbacks"))&&callbackArray(ownValue(candidate,"afterCallbacks")))return candidate}catch{}}throw TypeError("[gate] Incompatible shared Gate process state")}const state=processGateState();export function define(ability,callback){state.gates.set(ability,callback)}export function policy(model,policyClass){const modelName=typeof model==="string"?model:model.name;state.policies.set(modelName,policyClass)}export function before(callback){state.beforeCallbacks.push(callback)}export function after(callback){state.afterCallbacks.push(callback)}export async function allows(ability,user,...args){return check(ability,user,...args)}export async function denies(ability,user,...args){return!await check(ability,user,...args)}export async function can(ability,user,...args){return check(ability,user,...args)}export async function cannot(ability,user,...args){return!await check(ability,user,...args)}export async function any(abilities,user,...args){for(const ability of abilities)if(await check(ability,user,...args))return!0;return!1}export async function all(abilities,user,...args){for(const ability of abilities)if(!await check(ability,user,...args))return!1;return!0}export async function none(abilities,user,...args){return!await any(abilities,user,...args)}export async function authorize(ability,user,...args){const result=await inspect(ability,user,...args);if(!result.isAllowed)throw new AuthorizationException(result.message,result.code);return result}export async function inspect(ability,user,...args){let response=null;for(const callback of state.beforeCallbacks){const beforeResult=await callback(user,ability,args);if(beforeResult===!0){response=AuthorizationResponse.allow();break}if(beforeResult===!1){response=AuthorizationResponse.deny();break}}if(!response)response=await resolveAbility(ability,user,args);for(const callback of state.afterCallbacks){const afterResult=await callback(user,ability,response.isAllowed,args);if(typeof afterResult==="boolean")return afterResult?AuthorizationResponse.allow():AuthorizationResponse.deny()}return response}async function resolveAbility(ability,user,args){const model=args[0];if(model&&typeof model==="object"){const policyClass=state.policies.get(model.constructor?.name);if(policyClass){const response=await runPolicy(policyClass,ability,user,args);if(response)return response}}const gate=state.gates.get(ability);if(gate)return normalizeResponse(await gate(user,...args));return AuthorizationResponse.deny(`No gate or policy defined for ability: ${ability}`)}async function runPolicy(policyClass,ability,user,args){const policyInstance=new policyClass;if(policyInstance.before){const beforeResult=await policyInstance.before(user,ability);if(beforeResult===!0)return AuthorizationResponse.allow();if(beforeResult===!1)return AuthorizationResponse.deny()}const method=RESERVED_POLICY_MEMBERS.has(ability)?void 0:policyInstance[ability];if(typeof method!=="function")return null;const result=await method.call(policyInstance,user,...args);return normalizeResponse(result??!1)}export async function inspectFor(model,ability,user,...args){const modelName=typeof model==="string"?model:model.name,policyClass=state.policies.get(modelName);if(!policyClass)return null;let response=null;for(const callback of state.beforeCallbacks){const beforeResult=await callback(user,ability,args);if(beforeResult===!0){response=AuthorizationResponse.allow();break}if(beforeResult===!1){response=AuthorizationResponse.deny();break}}response??=await runPolicy(policyClass,ability,user,args)??AuthorizationResponse.deny(`${modelName}'s policy defines no ${String(ability)} ability`);for(const callback of state.afterCallbacks){const afterResult=await callback(user,ability,response.isAllowed,args);if(typeof afterResult==="boolean")return afterResult?AuthorizationResponse.allow():AuthorizationResponse.deny()}return response}export async function allowsFor(model,ability,user,...args){const response=await inspectFor(model,ability,user,...args);return response?response.isAllowed:!0}async function check(ability,user,...args){return(await inspect(ability,user,...args)).isAllowed}function normalizeResponse(result){if(result&&typeof result==="object"&&WeakSet.prototype.has.call(state.responses,result)){const allowed=Object.getOwnPropertyDescriptor(result,"isAllowed"),message=Object.getOwnPropertyDescriptor(result,"message"),code=Object.getOwnPropertyDescriptor(result,"code");if(allowed&&"value"in allowed&&typeof allowed.value==="boolean"&&message&&"value"in message&&(message.value===void 0||typeof message.value==="string")&&code&&"value"in code&&(code.value===void 0||typeof code.value==="string"))return result}if(typeof result!=="boolean")throw TypeError(`[gate] Policy must return boolean or AuthorizationResponse; got ${typeof result}. If you returned a model/value by mistake, return \`true\`/\`false\` instead.`);return result?AuthorizationResponse.allow():AuthorizationResponse.deny()}export function getPolicyFor(model){if(!model||typeof model!=="object")return null;const modelName=model.constructor?.name,policyClass=state.policies.get(modelName);if(policyClass)return new policyClass;return null}export function has(ability){return state.gates.has(ability)}export function hasPolicy(model){const modelName=typeof model==="string"?model:model.name;return state.policies.has(modelName)}export function abilities(){return Array.from(state.gates.keys())}export function flush(){state.gates.clear();state.policies.clear();state.beforeCallbacks=[];state.afterCallbacks=[]}export const Gate={define,policy,before,after,allows,allowsFor,denies,can,cannot,any,all,none,authorize,inspect,inspectFor,has,hasPolicy,abilities,getPolicyFor,flush,AuthorizationResponse,AuthorizationException};export default Gate;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/auth",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.236",
5
+ "version": "0.75.237",
6
6
  "description": "A more simplistic way to authenticate.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -59,19 +59,19 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@stacksjs/bun-router": "^0.1.24",
62
- "@stacksjs/cache": "0.75.236",
63
- "@stacksjs/config": "0.75.236",
64
- "@stacksjs/database": "0.75.236",
65
- "@stacksjs/email": "0.75.236",
66
- "@stacksjs/env": "0.75.236",
67
- "@stacksjs/error-handling": "0.75.236",
68
- "@stacksjs/logging": "0.75.236",
69
- "@stacksjs/orm": "0.75.236",
70
- "@stacksjs/path": "0.75.236",
71
- "@stacksjs/router": "0.75.236",
72
- "@stacksjs/security": "0.75.236",
73
- "@stacksjs/socials": "0.75.236",
74
- "@stacksjs/storage": "0.75.236",
62
+ "@stacksjs/cache": "0.75.237",
63
+ "@stacksjs/config": "0.75.237",
64
+ "@stacksjs/database": "0.75.237",
65
+ "@stacksjs/email": "0.75.237",
66
+ "@stacksjs/env": "0.75.237",
67
+ "@stacksjs/error-handling": "0.75.237",
68
+ "@stacksjs/logging": "0.75.237",
69
+ "@stacksjs/orm": "0.75.237",
70
+ "@stacksjs/path": "0.75.237",
71
+ "@stacksjs/router": "0.75.237",
72
+ "@stacksjs/security": "0.75.237",
73
+ "@stacksjs/socials": "0.75.237",
74
+ "@stacksjs/storage": "0.75.237",
75
75
  "@stacksjs/ts-auth": "^0.4.7",
76
76
  "ts-qr-codes": "^0.1.8"
77
77
  },