@backstage/plugin-permission-common
Advanced tools
Comparing version 0.0.0-nightly-20240820021901 to 0.0.0-nightly-20241116023418
# @backstage/plugin-permission-common | ||
## 0.0.0-nightly-20240820021901 | ||
## 0.0.0-nightly-20241116023418 | ||
### Patch Changes | ||
- 4e58bc7: Upgrade to uuid v11 internally | ||
- Updated dependencies | ||
- @backstage/config@1.2.0 | ||
- @backstage/errors@1.2.4 | ||
- @backstage/types@1.1.1 | ||
## 0.8.1 | ||
### Patch Changes | ||
- df784fe: Add the MetadataResponse type from @backstage/plugin-permission-node, since this | ||
@@ -8,0 +18,0 @@ type might be used in frontend code. |
'use strict'; | ||
var errors = require('@backstage/errors'); | ||
var fetch = require('cross-fetch'); | ||
var uuid = require('uuid'); | ||
var zod = require('zod'); | ||
var api = require('./types/api.cjs.js'); | ||
var util = require('./permissions/util.cjs.js'); | ||
var createPermission = require('./permissions/createPermission.cjs.js'); | ||
var PermissionClient = require('./PermissionClient.cjs.js'); | ||
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } | ||
function _interopNamespaceCompat(e) { | ||
if (e && typeof e === 'object' && 'default' in e) return e; | ||
var n = Object.create(null); | ||
if (e) { | ||
Object.keys(e).forEach(function (k) { | ||
if (k !== 'default') { | ||
var d = Object.getOwnPropertyDescriptor(e, k); | ||
Object.defineProperty(n, k, d.get ? d : { | ||
enumerable: true, | ||
get: function () { return e[k]; } | ||
}); | ||
} | ||
}); | ||
} | ||
n.default = e; | ||
return Object.freeze(n); | ||
} | ||
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch); | ||
var uuid__namespace = /*#__PURE__*/_interopNamespaceCompat(uuid); | ||
var AuthorizeResult = /* @__PURE__ */ ((AuthorizeResult2) => { | ||
AuthorizeResult2["DENY"] = "DENY"; | ||
AuthorizeResult2["ALLOW"] = "ALLOW"; | ||
AuthorizeResult2["CONDITIONAL"] = "CONDITIONAL"; | ||
return AuthorizeResult2; | ||
})(AuthorizeResult || {}); | ||
function isPermission(permission, comparedPermission) { | ||
return permission.name === comparedPermission.name; | ||
} | ||
function isResourcePermission(permission, resourceType) { | ||
if (!("resourceType" in permission)) { | ||
return false; | ||
} | ||
return !resourceType || permission.resourceType === resourceType; | ||
} | ||
function isCreatePermission(permission) { | ||
return permission.attributes.action === "create"; | ||
} | ||
function isReadPermission(permission) { | ||
return permission.attributes.action === "read"; | ||
} | ||
function isUpdatePermission(permission) { | ||
return permission.attributes.action === "update"; | ||
} | ||
function isDeletePermission(permission) { | ||
return permission.attributes.action === "delete"; | ||
} | ||
function toPermissionEvaluator(permissionAuthorizer) { | ||
return { | ||
authorize: async (requests, options) => { | ||
const response = await permissionAuthorizer.authorize(requests, options); | ||
return response; | ||
}, | ||
authorizeConditional(requests, options) { | ||
const parsedRequests = requests; | ||
return permissionAuthorizer.authorize(parsedRequests, options); | ||
} | ||
}; | ||
} | ||
function createPermission({ | ||
name, | ||
attributes, | ||
resourceType | ||
}) { | ||
if (resourceType) { | ||
return { | ||
type: "resource", | ||
name, | ||
attributes, | ||
resourceType | ||
}; | ||
} | ||
return { | ||
type: "basic", | ||
name, | ||
attributes | ||
}; | ||
} | ||
const permissionCriteriaSchema = zod.z.lazy( | ||
() => zod.z.object({ | ||
rule: zod.z.string(), | ||
resourceType: zod.z.string(), | ||
params: zod.z.record(zod.z.any()).optional() | ||
}).or(zod.z.object({ anyOf: zod.z.array(permissionCriteriaSchema).nonempty() })).or(zod.z.object({ allOf: zod.z.array(permissionCriteriaSchema).nonempty() })).or(zod.z.object({ not: permissionCriteriaSchema })) | ||
); | ||
const authorizePermissionResponseSchema = zod.z.object({ | ||
result: zod.z.literal(AuthorizeResult.ALLOW).or(zod.z.literal(AuthorizeResult.DENY)) | ||
}); | ||
const queryPermissionResponseSchema = zod.z.union([ | ||
zod.z.object({ | ||
result: zod.z.literal(AuthorizeResult.ALLOW).or(zod.z.literal(AuthorizeResult.DENY)) | ||
}), | ||
zod.z.object({ | ||
result: zod.z.literal(AuthorizeResult.CONDITIONAL), | ||
pluginId: zod.z.string(), | ||
resourceType: zod.z.string(), | ||
conditions: permissionCriteriaSchema | ||
}) | ||
]); | ||
const responseSchema = (itemSchema, ids) => zod.z.object({ | ||
items: zod.z.array( | ||
zod.z.intersection( | ||
zod.z.object({ | ||
id: zod.z.string() | ||
}), | ||
itemSchema | ||
) | ||
).refine( | ||
(items) => items.length === ids.size && items.every(({ id }) => ids.has(id)), | ||
{ | ||
message: "Items in response do not match request" | ||
} | ||
) | ||
}); | ||
class PermissionClient { | ||
enabled; | ||
discovery; | ||
constructor(options) { | ||
this.discovery = options.discovery; | ||
this.enabled = options.config.getOptionalBoolean("permission.enabled") ?? false; | ||
} | ||
/** | ||
* {@inheritdoc PermissionEvaluator.authorize} | ||
*/ | ||
async authorize(requests, options) { | ||
return this.makeRequest( | ||
requests, | ||
authorizePermissionResponseSchema, | ||
options | ||
); | ||
} | ||
/** | ||
* {@inheritdoc PermissionEvaluator.authorizeConditional} | ||
*/ | ||
async authorizeConditional(queries, options) { | ||
return this.makeRequest(queries, queryPermissionResponseSchema, options); | ||
} | ||
async makeRequest(queries, itemSchema, options) { | ||
if (!this.enabled) { | ||
return queries.map((_) => ({ result: AuthorizeResult.ALLOW })); | ||
} | ||
const request = { | ||
items: queries.map((query) => ({ | ||
id: uuid__namespace.v4(), | ||
...query | ||
})) | ||
}; | ||
const permissionApi = await this.discovery.getBaseUrl("permission"); | ||
const response = await fetch__default.default(`${permissionApi}/authorize`, { | ||
method: "POST", | ||
body: JSON.stringify(request), | ||
headers: { | ||
...this.getAuthorizationHeader(options?.token), | ||
"content-type": "application/json" | ||
} | ||
}); | ||
if (!response.ok) { | ||
throw await errors.ResponseError.fromResponse(response); | ||
} | ||
const responseBody = await response.json(); | ||
const parsedResponse = responseSchema( | ||
itemSchema, | ||
new Set(request.items.map(({ id }) => id)) | ||
).parse(responseBody); | ||
const responsesById = parsedResponse.items.reduce((acc, r) => { | ||
acc[r.id] = r; | ||
return acc; | ||
}, {}); | ||
return request.items.map((query) => responsesById[query.id]); | ||
} | ||
getAuthorizationHeader(token) { | ||
return token ? { Authorization: `Bearer ${token}` } : {}; | ||
} | ||
} | ||
exports.AuthorizeResult = AuthorizeResult; | ||
exports.PermissionClient = PermissionClient; | ||
exports.createPermission = createPermission; | ||
exports.isCreatePermission = isCreatePermission; | ||
exports.isDeletePermission = isDeletePermission; | ||
exports.isPermission = isPermission; | ||
exports.isReadPermission = isReadPermission; | ||
exports.isResourcePermission = isResourcePermission; | ||
exports.isUpdatePermission = isUpdatePermission; | ||
exports.toPermissionEvaluator = toPermissionEvaluator; | ||
exports.AuthorizeResult = api.AuthorizeResult; | ||
exports.isCreatePermission = util.isCreatePermission; | ||
exports.isDeletePermission = util.isDeletePermission; | ||
exports.isPermission = util.isPermission; | ||
exports.isReadPermission = util.isReadPermission; | ||
exports.isResourcePermission = util.isResourcePermission; | ||
exports.isUpdatePermission = util.isUpdatePermission; | ||
exports.toPermissionEvaluator = util.toPermissionEvaluator; | ||
exports.createPermission = createPermission.createPermission; | ||
exports.PermissionClient = PermissionClient.PermissionClient; | ||
//# sourceMappingURL=index.cjs.js.map |
{ | ||
"name": "@backstage/plugin-permission-common", | ||
"version": "0.0.0-nightly-20240820021901", | ||
"version": "0.0.0-nightly-20241116023418", | ||
"description": "Isomorphic types and client for Backstage permissions and authorization", | ||
@@ -51,7 +51,7 @@ "backstage": { | ||
"dependencies": { | ||
"@backstage/config": "^1.2.0", | ||
"@backstage/errors": "^1.2.4", | ||
"@backstage/types": "^1.1.1", | ||
"@backstage/config": "1.2.0", | ||
"@backstage/errors": "1.2.4", | ||
"@backstage/types": "1.1.1", | ||
"cross-fetch": "^4.0.0", | ||
"uuid": "^9.0.0", | ||
"uuid": "^11.0.0", | ||
"zod": "^3.22.4", | ||
@@ -61,7 +61,14 @@ "zod-to-json-schema": "^3.20.4" | ||
"devDependencies": { | ||
"@backstage/cli": "^0.0.0-nightly-20240820021901", | ||
"@backstage/cli": "0.0.0-nightly-20241116023418", | ||
"msw": "^1.0.0" | ||
}, | ||
"configSchema": "config.d.ts", | ||
"typesVersions": { | ||
"*": { | ||
"index": [ | ||
"dist/index.d.ts" | ||
] | ||
} | ||
}, | ||
"module": "dist/index.esm.js" | ||
} |
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
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 4 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
96477
25
832
8
+ Added@backstage/config@1.2.0(transitive)
+ Added@backstage/errors@1.2.4(transitive)
+ Added@backstage/types@1.1.1(transitive)
+ Addeduuid@11.0.5(transitive)
- Removed@backstage/config@1.3.2(transitive)
- Removed@backstage/errors@1.2.7(transitive)
- Removed@backstage/types@1.2.1(transitive)
- Removedms@2.1.3(transitive)
- Removeduuid@9.0.1(transitive)
Updated@backstage/config@1.2.0
Updated@backstage/errors@1.2.4
Updated@backstage/types@1.1.1
Updateduuid@^11.0.0