@authup/server-core 1.0.0-beta.37 → 1.0.0-beta.39
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.
- package/dist/adapters/database/data-source/options/module.mjs +16 -16
- package/dist/adapters/database/domains/client/index.d.ts +0 -1
- package/dist/adapters/database/domains/client/index.d.ts.map +1 -1
- package/dist/adapters/database/domains/client/index.mjs +1 -2
- package/dist/adapters/database/domains/index.mjs +26 -28
- package/dist/adapters/database/domains/policy/repository.mjs +1 -1
- package/dist/adapters/database/domains/robot/index.d.ts +0 -1
- package/dist/adapters/database/domains/robot/index.d.ts.map +1 -1
- package/dist/adapters/database/domains/robot/index.mjs +1 -2
- package/dist/adapters/database/domains/role/repository.d.ts +0 -6
- package/dist/adapters/database/domains/role/repository.d.ts.map +1 -1
- package/dist/adapters/database/domains/role/repository.mjs +1 -58
- package/dist/adapters/database/domains/role/repository.mjs.map +1 -1
- package/dist/adapters/database/domains/role-permission/entity.mjs +1 -1
- package/dist/adapters/database/domains/user/repository.d.ts +1 -5
- package/dist/adapters/database/domains/user/repository.d.ts.map +1 -1
- package/dist/adapters/database/domains/user/repository.mjs +0 -60
- package/dist/adapters/database/domains/user/repository.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/repository.d.ts.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/repository.mjs +1 -0
- package/dist/adapters/database/extra-attribute-repository/tree/repository.mjs.map +1 -1
- package/dist/adapters/database/index.mjs +18 -20
- package/dist/adapters/http/adapters/index.mjs +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.d.ts +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.mjs +10 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/client-credentials.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/client-credentials.mjs +5 -13
- package/dist/adapters/http/adapters/oauth2/grant-types/client-credentials.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/index.mjs +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/password.d.ts +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/password.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/password.mjs +11 -2
- package/dist/adapters/http/adapters/oauth2/grant-types/password.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.d.ts +5 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs +19 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/types.d.ts +6 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/types.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.d.ts +15 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.d.ts.map +1 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.mjs +57 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.mjs.map +1 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/guess.mjs +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/index.d.ts +1 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/index.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/index.mjs +2 -1
- package/dist/adapters/http/adapters/oauth2/index.mjs +2 -1
- package/dist/adapters/http/controllers/entities/client/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/client/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/client/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/permission/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/attributes-validator.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/validation.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/validation.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/validation.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/robot/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/robot/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/robot/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs +5 -6
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.mjs +4 -1
- package/dist/adapters/http/controllers/workflows/token/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/types.d.ts +2 -1
- package/dist/adapters/http/controllers/workflows/token/types.d.ts.map +1 -1
- package/dist/adapters/http/index.mjs +2 -1
- package/dist/adapters/http/middleware/built-in/assets.mjs +3 -3
- package/dist/adapters/http/middleware/built-in/assets.mjs.map +1 -1
- package/dist/app/modules/database/repositories/bindings.d.ts +17 -0
- package/dist/app/modules/database/repositories/bindings.d.ts.map +1 -0
- package/dist/app/modules/database/repositories/bindings.mjs +40 -0
- package/dist/app/modules/database/repositories/bindings.mjs.map +1 -0
- package/dist/app/modules/database/repositories/client/repository.d.ts +5 -1
- package/dist/app/modules/database/repositories/client/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/client/repository.mjs +69 -1
- package/dist/app/modules/database/repositories/client/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/permission/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/permission/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/policy/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/policy/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/realm/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/realm/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/robot/repository.d.ts +5 -1
- package/dist/app/modules/database/repositories/robot/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/robot/repository.mjs +61 -1
- package/dist/app/modules/database/repositories/robot/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/role/repository.d.ts +3 -0
- package/dist/app/modules/database/repositories/role/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/role/repository.mjs +17 -1
- package/dist/app/modules/database/repositories/role/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/scope/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/scope/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/user/repository.d.ts +4 -1
- package/dist/app/modules/database/repositories/user/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/user/repository.mjs +31 -2
- package/dist/app/modules/database/repositories/user/repository.mjs.map +1 -1
- package/dist/app/modules/http/modules/controller.d.ts +1 -2
- package/dist/app/modules/http/modules/controller.d.ts.map +1 -1
- package/dist/app/modules/http/modules/controller.mjs +32 -34
- package/dist/app/modules/http/modules/controller.mjs.map +1 -1
- package/dist/app/modules/http/modules/middleware.d.ts.map +1 -1
- package/dist/app/modules/http/modules/middleware.mjs +2 -15
- package/dist/app/modules/http/modules/middleware.mjs.map +1 -1
- package/dist/app/modules/identity/constants.d.ts +3 -1
- package/dist/app/modules/identity/constants.d.ts.map +1 -1
- package/dist/app/modules/identity/constants.mjs +2 -0
- package/dist/app/modules/identity/constants.mjs.map +1 -1
- package/dist/app/modules/identity/module.d.ts.map +1 -1
- package/dist/app/modules/identity/module.mjs +42 -5
- package/dist/app/modules/identity/module.mjs.map +1 -1
- package/dist/app/modules/identity/repositories/client.d.ts +2 -2
- package/dist/app/modules/identity/repositories/client.d.ts.map +1 -1
- package/dist/app/modules/identity/repositories/client.mjs.map +1 -1
- package/dist/app/modules/identity/repositories/robot.d.ts +2 -2
- package/dist/app/modules/identity/repositories/robot.d.ts.map +1 -1
- package/dist/app/modules/identity/repositories/robot.mjs.map +1 -1
- package/dist/app/modules/oauth2/module.d.ts.map +1 -1
- package/dist/app/modules/oauth2/module.mjs +5 -2
- package/dist/app/modules/oauth2/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/module.mjs +14 -9
- package/dist/app/modules/provisioning/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/default/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/sources/default/module.mjs +66 -10
- package/dist/app/modules/provisioning/sources/default/module.mjs.map +1 -1
- package/dist/components/database/unique-entries/module.mjs +1 -1
- package/dist/core/entities/client/service.d.ts +1 -1
- package/dist/core/entities/client/service.d.ts.map +1 -1
- package/dist/core/entities/client/service.mjs +27 -23
- package/dist/core/entities/client/service.mjs.map +1 -1
- package/dist/core/entities/client/types.d.ts +6 -2
- package/dist/core/entities/client/types.d.ts.map +1 -1
- package/dist/core/entities/client-scope/service.d.ts.map +1 -1
- package/dist/core/entities/client-scope/service.mjs +2 -0
- package/dist/core/entities/client-scope/service.mjs.map +1 -1
- package/dist/core/entities/identity-provider-role-mapping/service.d.ts.map +1 -1
- package/dist/core/entities/identity-provider-role-mapping/service.mjs +2 -0
- package/dist/core/entities/identity-provider-role-mapping/service.mjs.map +1 -1
- package/dist/core/entities/permission/service.mjs +1 -1
- package/dist/core/entities/policy/attributes-validator.mjs +1 -1
- package/dist/core/entities/policy/service.mjs +1 -1
- package/dist/core/entities/realm/service.mjs +1 -1
- package/dist/core/entities/robot/service.d.ts +1 -1
- package/dist/core/entities/robot/service.d.ts.map +1 -1
- package/dist/core/entities/robot/service.mjs +41 -26
- package/dist/core/entities/robot/service.mjs.map +1 -1
- package/dist/core/entities/robot/types.d.ts +6 -2
- package/dist/core/entities/robot/types.d.ts.map +1 -1
- package/dist/core/entities/role/service.mjs +1 -1
- package/dist/core/entities/role/types.d.ts +3 -0
- package/dist/core/entities/role/types.d.ts.map +1 -1
- package/dist/core/entities/role-attribute/service.d.ts +2 -0
- package/dist/core/entities/role-attribute/service.d.ts.map +1 -1
- package/dist/core/entities/role-attribute/service.mjs +7 -3
- package/dist/core/entities/role-attribute/service.mjs.map +1 -1
- package/dist/core/entities/scope/service.mjs +1 -1
- package/dist/core/entities/user/service.d.ts.map +1 -1
- package/dist/core/entities/user/service.mjs +20 -25
- package/dist/core/entities/user/service.mjs.map +1 -1
- package/dist/core/entities/user/types.d.ts +4 -1
- package/dist/core/entities/user/types.d.ts.map +1 -1
- package/dist/core/entities/user-attribute/service.d.ts +3 -1
- package/dist/core/entities/user-attribute/service.d.ts.map +1 -1
- package/dist/core/entities/user-attribute/service.mjs +44 -17
- package/dist/core/entities/user-attribute/service.mjs.map +1 -1
- package/dist/core/identity/index.d.ts +1 -0
- package/dist/core/identity/index.d.ts.map +1 -1
- package/dist/core/identity/index.mjs +2 -1
- package/dist/core/identity/password-recovery/service.d.ts.map +1 -1
- package/dist/core/identity/password-recovery/service.mjs +4 -4
- package/dist/core/identity/password-recovery/service.mjs.map +1 -1
- package/dist/core/identity/permission/module.d.ts +12 -6
- package/dist/core/identity/permission/module.d.ts.map +1 -1
- package/dist/core/identity/permission/module.mjs +11 -19
- package/dist/core/identity/permission/module.mjs.map +1 -1
- package/dist/core/identity/permission/types.d.ts +11 -13
- package/dist/core/identity/permission/types.d.ts.map +1 -1
- package/dist/core/identity/provider/account/module.d.ts.map +1 -1
- package/dist/core/identity/provider/account/module.mjs +3 -2
- package/dist/core/identity/provider/account/module.mjs.map +1 -1
- package/dist/core/identity/role/index.d.ts +3 -0
- package/dist/core/identity/role/index.d.ts.map +1 -0
- package/dist/core/identity/role/index.mjs +2 -0
- package/dist/core/identity/role/module.d.ts +15 -0
- package/dist/core/identity/role/module.d.ts.map +1 -0
- package/dist/core/identity/role/module.mjs +27 -0
- package/dist/core/identity/role/module.mjs.map +1 -0
- package/dist/core/identity/role/types.d.ts +14 -0
- package/dist/core/identity/role/types.d.ts.map +1 -0
- package/dist/core/identity/role/types.mjs +1 -0
- package/dist/core/index.mjs +3 -1
- package/dist/core/oauth2/authorization/code/verifier/module.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code/verifier/module.mjs +8 -4
- package/dist/core/oauth2/authorization/code/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/authorization/code/verifier/types.d.ts +2 -0
- package/dist/core/oauth2/authorization/code/verifier/types.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs +7 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/client/authenticator.d.ts +17 -0
- package/dist/core/oauth2/client/authenticator.d.ts.map +1 -0
- package/dist/core/oauth2/client/authenticator.mjs +34 -0
- package/dist/core/oauth2/client/authenticator.mjs.map +1 -0
- package/dist/core/oauth2/client/index.d.ts +1 -0
- package/dist/core/oauth2/client/index.d.ts.map +1 -1
- package/dist/core/oauth2/client/index.mjs +2 -1
- package/dist/core/oauth2/grant-types/password.d.ts +7 -3
- package/dist/core/oauth2/grant-types/password.d.ts.map +1 -1
- package/dist/core/oauth2/grant-types/password.mjs +9 -7
- package/dist/core/oauth2/grant-types/password.mjs.map +1 -1
- package/dist/core/oauth2/index.mjs +3 -1
- package/dist/core/oauth2/token/issuer/access/module.d.ts +4 -1
- package/dist/core/oauth2/token/issuer/access/module.d.ts.map +1 -1
- package/dist/core/oauth2/token/issuer/access/module.mjs +24 -2
- package/dist/core/oauth2/token/issuer/access/module.mjs.map +1 -1
- package/dist/core/oauth2/token/issuer/base.d.ts.map +1 -1
- package/dist/core/oauth2/token/issuer/base.mjs +3 -2
- package/dist/core/oauth2/token/issuer/base.mjs.map +1 -1
- package/dist/core/provisioning/entities/permission/types.d.ts +8 -0
- package/dist/core/provisioning/entities/permission/types.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/permission/module.d.ts +5 -1
- package/dist/core/provisioning/synchronizer/permission/module.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/permission/module.mjs +23 -0
- package/dist/core/provisioning/synchronizer/permission/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/permission/types.d.ts +4 -1
- package/dist/core/provisioning/synchronizer/permission/types.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/policy/module.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/policy/module.mjs +4 -2
- package/dist/core/provisioning/synchronizer/policy/module.mjs.map +1 -1
- package/dist/index.mjs +19 -20
- package/dist/path.d.ts +2 -1
- package/dist/path.d.ts.map +1 -1
- package/dist/path.mjs +3 -2
- package/dist/path.mjs.map +1 -1
- package/dist/swagger.json +14 -0
- package/dist/ui/client/.vite/ssr-manifest.json +2777 -0
- package/dist/ui/client/assets/fa-brands-400-BP5tdqmh.woff2 +0 -0
- package/dist/ui/client/assets/fa-regular-400-nyy7hhHF.woff2 +0 -0
- package/dist/ui/client/assets/fa-solid-900-DRAAbZTg.woff2 +0 -0
- package/dist/ui/client/assets/index-BVfayRKv.css +1 -0
- package/dist/ui/client/assets/index-Noe7uiOY.js +41 -0
- package/dist/ui/client/index.html +22 -0
- package/dist/ui/server/assets/multipart-parser-pHQi-kA6.js +166 -0
- package/dist/ui/server/server.js +79116 -0
- package/package.json +30 -13
- package/dist/adapters/database/domains/client/repository.d.ts +0 -13
- package/dist/adapters/database/domains/client/repository.d.ts.map +0 -1
- package/dist/adapters/database/domains/client/repository.mjs +0 -75
- package/dist/adapters/database/domains/client/repository.mjs.map +0 -1
- package/dist/adapters/database/domains/robot/repository.d.ts +0 -13
- package/dist/adapters/database/domains/robot/repository.d.ts.map +0 -1
- package/dist/adapters/database/domains/robot/repository.mjs +0 -75
- package/dist/adapters/database/domains/robot/repository.mjs.map +0 -1
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.d.ts +0 -4
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.d.ts.map +0 -1
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.mjs +0 -35
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.mjs.map +0 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { AbstractEntityService } from "../service.mjs";
|
|
2
2
|
import { PermissionName } from "@authup/core-kit";
|
|
3
3
|
import { BuiltInPolicyType, PolicyData } from "@authup/access";
|
|
4
|
-
import { NotFoundError } from "@ebec/http";
|
|
4
|
+
import { BadRequestError, NotFoundError } from "@ebec/http";
|
|
5
5
|
//#region src/core/entities/role-attribute/service.ts
|
|
6
6
|
var RoleAttributeService = class extends AbstractEntityService {
|
|
7
7
|
repository;
|
|
8
|
+
reservedNames;
|
|
8
9
|
constructor(ctx) {
|
|
9
10
|
super();
|
|
10
11
|
this.repository = ctx.repository;
|
|
12
|
+
this.reservedNames = ctx.reservedNames ?? /* @__PURE__ */ new Set();
|
|
11
13
|
}
|
|
12
14
|
async getMany(query, actor) {
|
|
13
15
|
await actor.permissionEvaluator.preEvaluateOneOf({ name: [
|
|
@@ -60,11 +62,12 @@ var RoleAttributeService = class extends AbstractEntityService {
|
|
|
60
62
|
async create(data, actor) {
|
|
61
63
|
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_UPDATE });
|
|
62
64
|
await this.repository.validateJoinColumns(data);
|
|
65
|
+
if (typeof data.name === "string" && this.reservedNames.has(data.name)) throw new BadRequestError(`The role-attribute name '${data.name}' collides with a Role entity column.`);
|
|
63
66
|
data.realm_id = data.role.realm_id;
|
|
64
67
|
const entity = this.repository.create(data);
|
|
65
68
|
await actor.permissionEvaluator.evaluate({
|
|
66
69
|
name: PermissionName.ROLE_UPDATE,
|
|
67
|
-
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]:
|
|
70
|
+
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [data.name]: data.value } })
|
|
68
71
|
});
|
|
69
72
|
await this.repository.save(entity);
|
|
70
73
|
return entity;
|
|
@@ -72,12 +75,13 @@ var RoleAttributeService = class extends AbstractEntityService {
|
|
|
72
75
|
async update(id, data, actor) {
|
|
73
76
|
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_UPDATE });
|
|
74
77
|
await this.repository.validateJoinColumns(data);
|
|
78
|
+
if (typeof data.name === "string" && this.reservedNames.has(data.name)) throw new BadRequestError(`The role-attribute name '${data.name}' collides with a Role entity column.`);
|
|
75
79
|
let entity = await this.repository.findOneBy({ id });
|
|
76
80
|
if (!entity) throw new NotFoundError();
|
|
77
81
|
entity = this.repository.merge(entity, data);
|
|
78
82
|
await actor.permissionEvaluator.evaluate({
|
|
79
83
|
name: PermissionName.ROLE_UPDATE,
|
|
80
|
-
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity })
|
|
84
|
+
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [entity.name]: entity.value } })
|
|
81
85
|
});
|
|
82
86
|
await this.repository.save(entity);
|
|
83
87
|
return entity;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","PolicyData","NotFoundError","PermissionName","AbstractEntityService","RoleAttributeService","repository","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","ROLE_READ","ROLE_UPDATE","ROLE_DELETE","data","entities","meta","findMany","total","entity","evaluateOneOf","input","ATTRIBUTES","push","getOne","id","findOneBy","create","preEvaluate","validateJoinColumns","realm_id","role","evaluate","save","update","merge","delete","entityId","remove"],"sources":["../../../../src/core/entities/role-attribute/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, PolicyData } from '@authup/access';\nimport { NotFoundError } from '@ebec/http';\nimport { PermissionName } from '@authup/core-kit';\nimport type { RoleAttribute } from '@authup/core-kit';\nimport type { ActorContext } from '../actor/types.ts';\nimport { AbstractEntityService } from '../service.ts';\nimport type { EntityRepositoryFindManyResult } from '../types.ts';\nimport type { IRoleAttributeRepository, IRoleAttributeService } from './types.ts';\n\nexport type RoleAttributeServiceContext = {\n repository: IRoleAttributeRepository;\n};\n\nexport class RoleAttributeService extends AbstractEntityService implements IRoleAttributeService {\n protected repository: IRoleAttributeRepository;\n\n constructor(ctx: RoleAttributeServiceContext) {\n super();\n this.repository = ctx.repository;\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<RoleAttribute>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n });\n\n const {\n data: entities, \n meta, \n } = await this.repository.findMany(query);\n\n const data: RoleAttribute[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n try {\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n data.push(entity);\n } catch {\n total--;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total, \n }, \n };\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<RoleAttribute> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<RoleAttribute> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_UPDATE });\n\n await this.repository.validateJoinColumns(data);\n\n data.realm_id = data.role.realm_id;\n\n const entity = this.repository.create(data);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]:
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","PolicyData","BadRequestError","NotFoundError","PermissionName","AbstractEntityService","RoleAttributeService","repository","reservedNames","ctx","Set","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","ROLE_READ","ROLE_UPDATE","ROLE_DELETE","data","entities","meta","findMany","total","entity","evaluateOneOf","input","ATTRIBUTES","push","getOne","id","findOneBy","create","preEvaluate","validateJoinColumns","has","realm_id","role","evaluate","value","save","update","merge","delete","entityId","remove"],"sources":["../../../../src/core/entities/role-attribute/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, PolicyData } from '@authup/access';\nimport { BadRequestError, NotFoundError } from '@ebec/http';\nimport { PermissionName } from '@authup/core-kit';\nimport type { RoleAttribute } from '@authup/core-kit';\nimport type { ActorContext } from '../actor/types.ts';\nimport { AbstractEntityService } from '../service.ts';\nimport type { EntityRepositoryFindManyResult } from '../types.ts';\nimport type { IRoleAttributeRepository, IRoleAttributeService } from './types.ts';\n\nexport type RoleAttributeServiceContext = {\n repository: IRoleAttributeRepository;\n reservedNames?: ReadonlySet<string>;\n};\n\nexport class RoleAttributeService extends AbstractEntityService implements IRoleAttributeService {\n protected repository: IRoleAttributeRepository;\n\n protected reservedNames: ReadonlySet<string>;\n\n constructor(ctx: RoleAttributeServiceContext) {\n super();\n this.repository = ctx.repository;\n this.reservedNames = ctx.reservedNames ?? new Set();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<RoleAttribute>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n });\n\n const {\n data: entities, \n meta, \n } = await this.repository.findMany(query);\n\n const data: RoleAttribute[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n try {\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n data.push(entity);\n } catch {\n total--;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total, \n }, \n };\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<RoleAttribute> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.ROLE_READ,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n ],\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<RoleAttribute> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_UPDATE });\n\n await this.repository.validateJoinColumns(data);\n\n if (typeof data.name === 'string' && this.reservedNames.has(data.name)) {\n throw new BadRequestError(`The role-attribute name '${data.name}' collides with a Role entity column.`);\n }\n\n data.realm_id = data.role.realm_id;\n\n const entity = this.repository.create(data);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [data.name]: data.value } }),\n });\n\n await this.repository.save(entity);\n\n return entity;\n }\n\n async update(\n id: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<RoleAttribute> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_UPDATE });\n\n await this.repository.validateJoinColumns(data);\n\n if (typeof data.name === 'string' && this.reservedNames.has(data.name)) {\n throw new BadRequestError(`The role-attribute name '${data.name}' collides with a Role entity column.`);\n }\n\n let entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n entity = this.repository.merge(entity, data);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [entity.name]: entity.value } }),\n });\n\n await this.repository.save(entity);\n\n return entity;\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<RoleAttribute> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_UPDATE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AbstractEntityService } from "../service.mjs";
|
|
2
2
|
import { PermissionName, ScopeValidator, ValidatorGroup } from "@authup/core-kit";
|
|
3
|
-
import { BuiltInPolicyType, PolicyData } from "@authup/access";
|
|
4
3
|
import { isPropertySet, isUUID } from "@authup/kit";
|
|
4
|
+
import { BuiltInPolicyType, PolicyData } from "@authup/access";
|
|
5
5
|
import { NotFoundError } from "@ebec/http";
|
|
6
6
|
//#region src/core/entities/scope/service.ts
|
|
7
7
|
var ScopeService = class extends AbstractEntityService {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user/service.ts"],"names":[],"mappings":"AAUA,OAAO,EAEH,aAAa,EAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,MAAM,kBAAkB,GAAG;IAC7B,UAAU,EAAE,eAAe,CAAC;IAC5B,eAAe,EAAE,gBAAgB,CAAC;CACrC,CAAC;AAEF,qBAAa,WAAY,SAAQ,qBAAsB,YAAW,YAAY;IAC1E,SAAS,CAAC,UAAU,EAAE,eAAe,CAAC;IAEtC,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAE5C,SAAS,CAAC,SAAS,EAAE,aAAa,CAAC;gBAEvB,GAAG,EAAE,kBAAkB;IAO7B,OAAO,CACT,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,8BAA8B,CAAC,IAAI,CAAC,CAAC;IAoD1C,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user/service.ts"],"names":[],"mappings":"AAUA,OAAO,EAEH,aAAa,EAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,MAAM,kBAAkB,GAAG;IAC7B,UAAU,EAAE,eAAe,CAAC;IAC5B,eAAe,EAAE,gBAAgB,CAAC;CACrC,CAAC;AAEF,qBAAa,WAAY,SAAQ,qBAAsB,YAAW,YAAY;IAC1E,SAAS,CAAC,UAAU,EAAE,eAAe,CAAC;IAEtC,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAE5C,SAAS,CAAC,SAAS,EAAE,aAAa,CAAC;gBAEvB,GAAG,EAAE,kBAAkB;IAO7B,OAAO,CACT,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,8BAA8B,CAAC,IAAI,CAAC,CAAC;IAoD1C,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAsCV,MAAM,CACR,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC;IAKV,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC;IAKV,IAAI,CACN,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAO,GACvC,OAAO,CAAC;QACP,MAAM,EAAE,IAAI,CAAC;QACb,OAAO,EAAE,OAAO,CAAA;KACnB,CAAC;IAqII,MAAM,CACR,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC;CA2BnB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { UserCredentialsService } from "../../authentication/credential/entities/user/module.mjs";
|
|
2
2
|
import { AbstractEntityService } from "../service.mjs";
|
|
3
3
|
import { PermissionName, UserValidator, ValidatorGroup } from "@authup/core-kit";
|
|
4
|
+
import { isUUID } from "@authup/kit";
|
|
4
5
|
import { BuiltInPolicyType, PolicyData } from "@authup/access";
|
|
5
|
-
import { isUUID, removeObjectProperty } from "@authup/kit";
|
|
6
6
|
import { BadRequestError, NotFoundError } from "@ebec/http";
|
|
7
7
|
//#region src/core/entities/user/service.ts
|
|
8
8
|
var UserService = class extends AbstractEntityService {
|
|
@@ -52,24 +52,21 @@ var UserService = class extends AbstractEntityService {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
async getOne(idOrName, actor, query, realmId) {
|
|
55
|
-
|
|
56
|
-
if (actor.identity && actor.identity.type === "user") {
|
|
57
|
-
if (actor.identity.data.id === idOrName || actor.identity.data.name === idOrName) isMe = true;
|
|
58
|
-
}
|
|
59
|
-
if (!isMe) await actor.permissionEvaluator.preEvaluateOneOf({ name: [
|
|
55
|
+
const permissionNames = [
|
|
60
56
|
PermissionName.USER_READ,
|
|
61
57
|
PermissionName.USER_UPDATE,
|
|
62
58
|
PermissionName.USER_DELETE
|
|
63
|
-
]
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
];
|
|
60
|
+
let isMe = !!actor.identity && actor.identity.type === "user" && (actor.identity.data.id === idOrName || actor.identity.data.name === idOrName);
|
|
61
|
+
if (!isMe) await actor.permissionEvaluator.preEvaluateOneOf({ name: permissionNames });
|
|
62
|
+
const entity = await this.repository.findOne(idOrName, query, realmId);
|
|
66
63
|
if (!entity) throw new NotFoundError();
|
|
64
|
+
if (isMe && actor.identity.data.id !== entity.id) {
|
|
65
|
+
isMe = false;
|
|
66
|
+
await actor.permissionEvaluator.preEvaluateOneOf({ name: permissionNames });
|
|
67
|
+
}
|
|
67
68
|
if (!isMe) await actor.permissionEvaluator.evaluateOneOf({
|
|
68
|
-
name:
|
|
69
|
-
PermissionName.USER_READ,
|
|
70
|
-
PermissionName.USER_UPDATE,
|
|
71
|
-
PermissionName.USER_DELETE
|
|
72
|
-
],
|
|
69
|
+
name: permissionNames,
|
|
73
70
|
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity })
|
|
74
71
|
});
|
|
75
72
|
return entity;
|
|
@@ -94,38 +91,36 @@ var UserService = class extends AbstractEntityService {
|
|
|
94
91
|
entity = await this.repository.findOneBy(where);
|
|
95
92
|
if (!entity && options.updateOnly) throw new NotFoundError();
|
|
96
93
|
} else if (options.updateOnly) throw new NotFoundError();
|
|
97
|
-
let
|
|
94
|
+
let isSelfEdit = false;
|
|
98
95
|
if (entity) {
|
|
99
96
|
try {
|
|
100
97
|
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_UPDATE });
|
|
101
|
-
hasAbility = true;
|
|
102
98
|
} catch (e) {
|
|
103
99
|
if (!actor.identity || actor.identity.type !== "user" || actor.identity.data.id !== entity.id) throw e;
|
|
100
|
+
isSelfEdit = true;
|
|
101
|
+
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_SELF_MANAGE });
|
|
104
102
|
}
|
|
105
103
|
group = ValidatorGroup.UPDATE;
|
|
106
104
|
} else {
|
|
107
105
|
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_CREATE });
|
|
108
|
-
hasAbility = true;
|
|
109
106
|
group = ValidatorGroup.CREATE;
|
|
110
107
|
}
|
|
111
108
|
const validated = await this.validator.run(data, { group });
|
|
112
109
|
await this.repository.validateJoinColumns(validated);
|
|
113
|
-
if (!hasAbility) {
|
|
114
|
-
removeObjectProperty(validated, "name_locked");
|
|
115
|
-
removeObjectProperty(validated, "active");
|
|
116
|
-
removeObjectProperty(validated, "status");
|
|
117
|
-
removeObjectProperty(validated, "status_message");
|
|
118
|
-
}
|
|
119
110
|
const credentialsService = new UserCredentialsService();
|
|
120
111
|
if (entity) {
|
|
121
112
|
const originalName = entity.name;
|
|
122
113
|
const originalNameLocked = entity.name_locked;
|
|
114
|
+
if (isSelfEdit) await actor.permissionEvaluator.evaluate({
|
|
115
|
+
name: PermissionName.USER_SELF_MANAGE,
|
|
116
|
+
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: validated })
|
|
117
|
+
});
|
|
123
118
|
entity = this.repository.merge(entity, validated);
|
|
124
119
|
if (validated.name && validated.name !== originalName) {
|
|
125
120
|
if (validated.name_locked) entity.name_locked = validated.name_locked;
|
|
126
121
|
if (originalNameLocked && validated.name_locked !== false) entity.name = originalName;
|
|
127
122
|
}
|
|
128
|
-
if (
|
|
123
|
+
if (!isSelfEdit) await actor.permissionEvaluator.evaluate({
|
|
129
124
|
name: PermissionName.USER_UPDATE,
|
|
130
125
|
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: {
|
|
131
126
|
...entity,
|
|
@@ -144,7 +139,7 @@ var UserService = class extends AbstractEntityService {
|
|
|
144
139
|
if (actorRealmId) validated.realm_id = actorRealmId;
|
|
145
140
|
}
|
|
146
141
|
entity = this.repository.create(validated);
|
|
147
|
-
|
|
142
|
+
await actor.permissionEvaluator.evaluate({
|
|
148
143
|
name: PermissionName.USER_CREATE,
|
|
149
144
|
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity })
|
|
150
145
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","PolicyData","isUUID","removeObjectProperty","BadRequestError","NotFoundError","PermissionName","UserValidator","ValidatorGroup","AbstractEntityService","UserCredentialsService","UserService","repository","realmRepository","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","USER_READ","USER_UPDATE","USER_DELETE","data","entities","meta","findMany","total","entity","identity","type","id","push","evaluateOneOf","input","ATTRIBUTES","getOne","idOrName","realmId","isMe","resolvedId","findOne","create","save","undefined","update","updateOnly","options","group","realm","realm_id","resolve","where","findOneBy","hasAbility","preEvaluate","e","UPDATE","USER_CREATE","CREATE","validated","run","validateJoinColumns","credentialsService","originalName","originalNameLocked","name_locked","merge","evaluate","password","protect","created","actorRealmId","getActorRealmId","delete","entityId","remove"],"sources":["../../../../src/core/entities/user/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, PolicyData } from '@authup/access';\nimport { isUUID, removeObjectProperty } from '@authup/kit';\nimport { BadRequestError, NotFoundError } from '@ebec/http';\nimport {\n PermissionName,\n UserValidator,\n ValidatorGroup,\n} from '@authup/core-kit';\nimport type { User } from '@authup/core-kit';\nimport type { ActorContext } from '../actor/types.ts';\nimport type { IRealmRepository } from '../realm/types.ts';\nimport { AbstractEntityService } from '../service.ts';\nimport type { EntityRepositoryFindManyResult } from '../types.ts';\nimport { UserCredentialsService } from '../../authentication/credential/entities/user/module.ts';\nimport type { IUserRepository, IUserService } from './types.ts';\n\nexport type UserServiceContext = {\n repository: IUserRepository;\n realmRepository: IRealmRepository;\n};\n\nexport class UserService extends AbstractEntityService implements IUserService {\n protected repository: IUserRepository;\n\n protected realmRepository: IRealmRepository;\n\n protected validator: UserValidator;\n\n constructor(ctx: UserServiceContext) {\n super();\n this.repository = ctx.repository;\n this.realmRepository = ctx.realmRepository;\n this.validator = new UserValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<User>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_READ,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n ],\n });\n\n const {\n data: entities, \n meta, \n } = await this.repository.findMany(query);\n\n const data: User[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n if (\n actor.identity &&\n actor.identity.type === 'user' &&\n actor.identity.data.id === entity.id\n ) {\n data.push(entity);\n continue;\n }\n\n try {\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.USER_READ,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n ],\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n data.push(entity);\n } catch {\n total -= 1;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total, \n }, \n };\n }\n\n async getOne(\n idOrName: string,\n actor: ActorContext,\n query?: Record<string, any>,\n realmId?: string,\n ): Promise<User> {\n let isMe = false;\n if (actor.identity && actor.identity.type === 'user') {\n if (\n actor.identity.data.id === idOrName ||\n actor.identity.data.name === idOrName\n ) {\n isMe = true;\n }\n }\n\n if (!isMe) {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_READ,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n ],\n });\n }\n\n const resolvedId = isMe ? actor.identity!.data.id : idOrName;\n const entity = await this.repository.findOne(resolvedId, query, realmId);\n if (!entity) {\n throw new NotFoundError();\n }\n\n if (!isMe) {\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.USER_READ,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n ],\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<User> {\n const { entity } = await this.save(undefined, data, actor);\n return entity;\n }\n\n async update(\n idOrName: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<User> {\n const { entity } = await this.save(idOrName, data, actor, { updateOnly: true });\n return entity;\n }\n\n async save(\n idOrName: string | undefined,\n data: Record<string, any>,\n actor: ActorContext,\n options: { updateOnly?: boolean } = {},\n ): Promise<{\n entity: User,\n created: boolean \n }> {\n let group: string;\n\n const realm = typeof data.realm_id === 'string' ?\n await this.realmRepository.resolve(data.realm_id) :\n undefined;\n\n let entity: User | null | undefined;\n if (idOrName) {\n const where: Record<string, any> = {};\n if (isUUID(idOrName)) {\n where.id = idOrName;\n } else {\n where.name = idOrName;\n }\n\n if (realm) {\n where.realm_id = realm.id;\n }\n\n entity = await this.repository.findOneBy(where);\n if (!entity && options.updateOnly) {\n throw new NotFoundError();\n }\n } else if (options.updateOnly) {\n throw new NotFoundError();\n }\n\n let hasAbility: boolean | undefined;\n if (entity) {\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_UPDATE });\n hasAbility = true;\n } catch (e) {\n if (\n !actor.identity ||\n actor.identity.type !== 'user' ||\n actor.identity.data.id !== entity.id\n ) {\n throw e;\n }\n }\n\n group = ValidatorGroup.UPDATE;\n } else {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_CREATE });\n hasAbility = true;\n\n group = ValidatorGroup.CREATE;\n }\n\n const validated = await this.validator.run(data, { group });\n\n await this.repository.validateJoinColumns(validated);\n\n if (!hasAbility) {\n removeObjectProperty(validated, 'name_locked');\n removeObjectProperty(validated, 'active');\n removeObjectProperty(validated, 'status');\n removeObjectProperty(validated, 'status_message');\n }\n\n const credentialsService = new UserCredentialsService();\n\n if (entity) {\n const originalName = entity.name;\n const originalNameLocked = entity.name_locked;\n\n entity = this.repository.merge(entity, validated);\n\n if (\n validated.name &&\n validated.name !== originalName\n ) {\n if (validated.name_locked) {\n entity.name_locked = validated.name_locked;\n }\n\n if (originalNameLocked && validated.name_locked !== false) {\n entity.name = originalName;\n }\n }\n\n if (hasAbility) {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_UPDATE,\n input: new PolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: {\n ...entity,\n ...validated,\n },\n }),\n });\n }\n\n if (validated.password) {\n entity.password = await credentialsService.protect(validated.password);\n }\n\n await this.repository.save(entity);\n\n return {\n entity,\n created: false, \n };\n }\n\n if (!validated.realm_id) {\n const actorRealmId = this.getActorRealmId(actor);\n if (actorRealmId) {\n validated.realm_id = actorRealmId;\n }\n }\n\n entity = this.repository.create(validated);\n\n if (hasAbility) {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_CREATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n }\n\n if (validated.password) {\n entity.password = await credentialsService.protect(validated.password);\n }\n\n await this.repository.save(entity);\n\n return {\n entity,\n created: true, \n };\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<User> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_DELETE });\n\n if (\n actor.identity &&\n actor.identity.type === 'user' &&\n actor.identity.data.id === id\n ) {\n throw new BadRequestError('The own user can not be deleted.');\n }\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_DELETE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","PolicyData","isUUID","BadRequestError","NotFoundError","PermissionName","UserValidator","ValidatorGroup","AbstractEntityService","UserCredentialsService","UserService","repository","realmRepository","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","USER_READ","USER_UPDATE","USER_DELETE","data","entities","meta","findMany","total","entity","identity","type","id","push","evaluateOneOf","input","ATTRIBUTES","getOne","idOrName","realmId","permissionNames","isMe","findOne","create","save","undefined","update","updateOnly","options","group","realm","realm_id","resolve","where","findOneBy","isSelfEdit","preEvaluate","e","USER_SELF_MANAGE","UPDATE","USER_CREATE","CREATE","validated","run","validateJoinColumns","credentialsService","originalName","originalNameLocked","name_locked","evaluate","merge","password","protect","created","actorRealmId","getActorRealmId","delete","entityId","remove"],"sources":["../../../../src/core/entities/user/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, PolicyData } from '@authup/access';\nimport { isUUID } from '@authup/kit';\nimport { BadRequestError, NotFoundError } from '@ebec/http';\nimport {\n PermissionName,\n UserValidator,\n ValidatorGroup,\n} from '@authup/core-kit';\nimport type { User } from '@authup/core-kit';\nimport type { ActorContext } from '../actor/types.ts';\nimport type { IRealmRepository } from '../realm/types.ts';\nimport { AbstractEntityService } from '../service.ts';\nimport type { EntityRepositoryFindManyResult } from '../types.ts';\nimport { UserCredentialsService } from '../../authentication/credential/entities/user/module.ts';\nimport type { IUserRepository, IUserService } from './types.ts';\n\nexport type UserServiceContext = {\n repository: IUserRepository;\n realmRepository: IRealmRepository;\n};\n\nexport class UserService extends AbstractEntityService implements IUserService {\n protected repository: IUserRepository;\n\n protected realmRepository: IRealmRepository;\n\n protected validator: UserValidator;\n\n constructor(ctx: UserServiceContext) {\n super();\n this.repository = ctx.repository;\n this.realmRepository = ctx.realmRepository;\n this.validator = new UserValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<User>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_READ,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n ],\n });\n\n const {\n data: entities, \n meta, \n } = await this.repository.findMany(query);\n\n const data: User[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n if (\n actor.identity &&\n actor.identity.type === 'user' &&\n actor.identity.data.id === entity.id\n ) {\n data.push(entity);\n continue;\n }\n\n try {\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.USER_READ,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n ],\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n data.push(entity);\n } catch {\n total -= 1;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total, \n }, \n };\n }\n\n async getOne(\n idOrName: string,\n actor: ActorContext,\n query?: Record<string, any>,\n realmId?: string,\n ): Promise<User> {\n const permissionNames = [\n PermissionName.USER_READ,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n ];\n\n let isMe = !!actor.identity &&\n actor.identity.type === 'user' &&\n (\n actor.identity.data.id === idOrName ||\n actor.identity.data.name === idOrName\n );\n\n if (!isMe) {\n await actor.permissionEvaluator.preEvaluateOneOf({ name: permissionNames });\n }\n\n const entity = await this.repository.findOne(idOrName, query, realmId);\n if (!entity) {\n throw new NotFoundError();\n }\n\n if (isMe && actor.identity!.data.id !== entity.id) {\n isMe = false;\n await actor.permissionEvaluator.preEvaluateOneOf({ name: permissionNames });\n }\n\n if (!isMe) {\n await actor.permissionEvaluator.evaluateOneOf({\n name: permissionNames,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<User> {\n const { entity } = await this.save(undefined, data, actor);\n return entity;\n }\n\n async update(\n idOrName: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<User> {\n const { entity } = await this.save(idOrName, data, actor, { updateOnly: true });\n return entity;\n }\n\n async save(\n idOrName: string | undefined,\n data: Record<string, any>,\n actor: ActorContext,\n options: { updateOnly?: boolean } = {},\n ): Promise<{\n entity: User,\n created: boolean \n }> {\n let group: string;\n\n const realm = typeof data.realm_id === 'string' ?\n await this.realmRepository.resolve(data.realm_id) :\n undefined;\n\n let entity: User | null | undefined;\n if (idOrName) {\n const where: Record<string, any> = {};\n if (isUUID(idOrName)) {\n where.id = idOrName;\n } else {\n where.name = idOrName;\n }\n\n if (realm) {\n where.realm_id = realm.id;\n }\n\n entity = await this.repository.findOneBy(where);\n if (!entity && options.updateOnly) {\n throw new NotFoundError();\n }\n } else if (options.updateOnly) {\n throw new NotFoundError();\n }\n\n let isSelfEdit = false;\n if (entity) {\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_UPDATE });\n } catch (e) {\n if (\n !actor.identity ||\n actor.identity.type !== 'user' ||\n actor.identity.data.id !== entity.id\n ) {\n throw e;\n }\n isSelfEdit = true;\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_SELF_MANAGE });\n }\n\n group = ValidatorGroup.UPDATE;\n } else {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_CREATE });\n\n group = ValidatorGroup.CREATE;\n }\n\n const validated = await this.validator.run(data, { group });\n\n await this.repository.validateJoinColumns(validated);\n\n const credentialsService = new UserCredentialsService();\n\n if (entity) {\n const originalName = entity.name;\n const originalNameLocked = entity.name_locked;\n\n if (isSelfEdit) {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_SELF_MANAGE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: validated }),\n });\n }\n\n entity = this.repository.merge(entity, validated);\n\n if (\n validated.name &&\n validated.name !== originalName\n ) {\n if (validated.name_locked) {\n entity.name_locked = validated.name_locked;\n }\n\n if (originalNameLocked && validated.name_locked !== false) {\n entity.name = originalName;\n }\n }\n\n if (!isSelfEdit) {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_UPDATE,\n input: new PolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: {\n ...entity,\n ...validated,\n },\n }),\n });\n }\n\n if (validated.password) {\n entity.password = await credentialsService.protect(validated.password);\n }\n\n await this.repository.save(entity);\n\n return {\n entity,\n created: false, \n };\n }\n\n if (!validated.realm_id) {\n const actorRealmId = this.getActorRealmId(actor);\n if (actorRealmId) {\n validated.realm_id = actorRealmId;\n }\n }\n\n entity = this.repository.create(validated);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_CREATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n if (validated.password) {\n entity.password = await credentialsService.protect(validated.password);\n }\n\n await this.repository.save(entity);\n\n return {\n entity,\n created: true, \n };\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<User> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_DELETE });\n\n if (\n actor.identity &&\n actor.identity.type === 'user' &&\n actor.identity.data.id === id\n ) {\n throw new BadRequestError('The own user can not be deleted.');\n }\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_DELETE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { User } from '@authup/core-kit';
|
|
1
|
+
import type { Role, User } from '@authup/core-kit';
|
|
2
|
+
import type { PermissionPolicyBinding } from '@authup/access';
|
|
2
3
|
import type { ActorContext } from '../actor/types.ts';
|
|
3
4
|
import type { EntityRepositoryFindManyResult, IEntityRepository } from '../types.ts';
|
|
4
5
|
export interface IUserRepository extends IEntityRepository<User> {
|
|
5
6
|
checkUniqueness(data: Partial<User>, existing?: User): Promise<void>;
|
|
6
7
|
findOne(id: string, query?: Record<string, any>, realm?: string): Promise<User | null>;
|
|
7
8
|
findOneByWithEmail(where: Record<string, any>): Promise<User | null>;
|
|
9
|
+
getBoundRoles(entity: string | User): Promise<Role[]>;
|
|
10
|
+
getBoundPermissions(entity: string | User): Promise<PermissionPolicyBinding[]>;
|
|
8
11
|
}
|
|
9
12
|
export interface IUserService {
|
|
10
13
|
getMany(query: Record<string, any>, actor: ActorContext): Promise<EntityRepositoryFindManyResult<User>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,8BAA8B,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErF,MAAM,WAAW,eAAgB,SAAQ,iBAAiB,CAAC,IAAI,CAAC;IAC5D,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAEvF,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAErE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAEtD,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAC;CAClF;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC;IACxG,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5G,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxF,IAAI,CACA,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GACnC,OAAO,CAAC;QACP,MAAM,EAAE,IAAI,CAAC;QACb,OAAO,EAAE,OAAO,CAAA;KACnB,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D"}
|
|
@@ -5,15 +5,17 @@ import type { EntityRepositoryFindManyResult } from '../types.ts';
|
|
|
5
5
|
import type { IUserAttributeRepository, IUserAttributeService } from './types.ts';
|
|
6
6
|
export type UserAttributeServiceContext = {
|
|
7
7
|
repository: IUserAttributeRepository;
|
|
8
|
+
reservedNames?: ReadonlySet<string>;
|
|
8
9
|
};
|
|
9
10
|
export declare class UserAttributeService extends AbstractEntityService implements IUserAttributeService {
|
|
10
11
|
protected repository: IUserAttributeRepository;
|
|
12
|
+
protected reservedNames: ReadonlySet<string>;
|
|
11
13
|
constructor(ctx: UserAttributeServiceContext);
|
|
12
14
|
getMany(query: Record<string, any>, actor: ActorContext): Promise<EntityRepositoryFindManyResult<UserAttribute>>;
|
|
13
15
|
getOne(id: string, actor: ActorContext): Promise<UserAttribute>;
|
|
14
16
|
create(data: Record<string, any>, actor: ActorContext): Promise<UserAttribute>;
|
|
15
17
|
update(id: string, data: Record<string, any>, actor: ActorContext): Promise<UserAttribute>;
|
|
16
18
|
delete(id: string, actor: ActorContext): Promise<UserAttribute>;
|
|
17
|
-
private
|
|
19
|
+
private canReadUserAttribute;
|
|
18
20
|
}
|
|
19
21
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user-attribute/service.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,MAAM,2BAA2B,GAAG;IACtC,UAAU,EAAE,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user-attribute/service.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,MAAM,2BAA2B,GAAG;IACtC,UAAU,EAAE,wBAAwB,CAAC;IACrC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC;AAEF,qBAAa,oBAAqB,SAAQ,qBAAsB,YAAW,qBAAqB;IAC5F,SAAS,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAE/C,SAAS,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;gBAEjC,GAAG,EAAE,2BAA2B;IAMtC,OAAO,CACT,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,8BAA8B,CAAC,aAAa,CAAC,CAAC;IAkCnD,MAAM,CACR,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC;IAqBnB,MAAM,CACR,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC;IAwDnB,MAAM,CACR,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC;IA8CnB,MAAM,CACR,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC;YAyBX,oBAAoB;CAuBrC"}
|
|
@@ -6,16 +6,18 @@ import { buildErrorMessageForAttribute } from "validup";
|
|
|
6
6
|
//#region src/core/entities/user-attribute/service.ts
|
|
7
7
|
var UserAttributeService = class extends AbstractEntityService {
|
|
8
8
|
repository;
|
|
9
|
+
reservedNames;
|
|
9
10
|
constructor(ctx) {
|
|
10
11
|
super();
|
|
11
12
|
this.repository = ctx.repository;
|
|
13
|
+
this.reservedNames = ctx.reservedNames ?? /* @__PURE__ */ new Set();
|
|
12
14
|
}
|
|
13
15
|
async getMany(query, actor) {
|
|
14
16
|
await actor.permissionEvaluator.preEvaluateOneOf({ name: [PermissionName.USER_UPDATE, PermissionName.USER_SELF_MANAGE] });
|
|
15
17
|
const { data: entities, meta } = await this.repository.findMany(query);
|
|
16
18
|
const data = [];
|
|
17
19
|
let { total } = meta;
|
|
18
|
-
for (const entity of entities) if (await this.
|
|
20
|
+
for (const entity of entities) if (await this.canReadUserAttribute(actor, entity)) data.push(entity);
|
|
19
21
|
else total--;
|
|
20
22
|
return {
|
|
21
23
|
data,
|
|
@@ -29,29 +31,62 @@ var UserAttributeService = class extends AbstractEntityService {
|
|
|
29
31
|
await actor.permissionEvaluator.preEvaluateOneOf({ name: [PermissionName.USER_UPDATE, PermissionName.USER_SELF_MANAGE] });
|
|
30
32
|
const entity = await this.repository.findOneBy({ id });
|
|
31
33
|
if (!entity) throw new NotFoundError();
|
|
32
|
-
if (!await this.
|
|
34
|
+
if (!await this.canReadUserAttribute(actor, entity)) throw new ForbiddenError();
|
|
33
35
|
return entity;
|
|
34
36
|
}
|
|
35
37
|
async create(data, actor) {
|
|
36
|
-
|
|
38
|
+
const targetUserId = data.user_id || data.user && data.user.id;
|
|
39
|
+
const isSelfTarget = !!actor.identity && actor.identity.type === "user" && (!targetUserId || targetUserId === actor.identity.data.id);
|
|
40
|
+
let isSelfFallback = false;
|
|
41
|
+
try {
|
|
42
|
+
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_UPDATE });
|
|
43
|
+
} catch (e) {
|
|
44
|
+
if (!isSelfTarget) throw e;
|
|
45
|
+
isSelfFallback = true;
|
|
46
|
+
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_SELF_MANAGE });
|
|
47
|
+
}
|
|
37
48
|
await this.repository.validateJoinColumns(data);
|
|
49
|
+
if (typeof data.name === "string" && this.reservedNames.has(data.name)) throw new BadRequestError(`The user-attribute name '${data.name}' collides with a User entity column.`);
|
|
38
50
|
if (data.user) data.realm_id = data.user.realm_id;
|
|
39
51
|
else if (actor.identity && actor.identity.type === "user") {
|
|
40
52
|
data.user_id = actor.identity.data.id;
|
|
41
53
|
data.realm_id = actor.identity.data.realm_id;
|
|
42
54
|
} else throw new BadRequestError(buildErrorMessageForAttribute("user_id"));
|
|
43
55
|
const entity = this.repository.create(data);
|
|
44
|
-
if (
|
|
56
|
+
if (isSelfFallback) await actor.permissionEvaluator.evaluate({
|
|
57
|
+
name: PermissionName.USER_SELF_MANAGE,
|
|
58
|
+
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [data.name]: data.value } })
|
|
59
|
+
});
|
|
60
|
+
else await actor.permissionEvaluator.evaluate({
|
|
61
|
+
name: PermissionName.USER_UPDATE,
|
|
62
|
+
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity })
|
|
63
|
+
});
|
|
45
64
|
await this.repository.save(entity);
|
|
46
65
|
return entity;
|
|
47
66
|
}
|
|
48
67
|
async update(id, data, actor) {
|
|
49
|
-
await actor.permissionEvaluator.evaluateOneOf({ name: [PermissionName.USER_UPDATE, PermissionName.USER_SELF_MANAGE] });
|
|
50
68
|
await this.repository.validateJoinColumns(data);
|
|
69
|
+
if (typeof data.name === "string" && this.reservedNames.has(data.name)) throw new BadRequestError(`The user-attribute name '${data.name}' collides with a User entity column.`);
|
|
51
70
|
let entity = await this.repository.findOneBy({ id });
|
|
52
71
|
if (!entity) throw new NotFoundError();
|
|
72
|
+
const isSelfTarget = !!actor.identity && actor.identity.type === "user" && actor.identity.data.id === entity.user_id;
|
|
73
|
+
let isSelfFallback = false;
|
|
74
|
+
try {
|
|
75
|
+
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_UPDATE });
|
|
76
|
+
} catch (e) {
|
|
77
|
+
if (!isSelfTarget) throw e;
|
|
78
|
+
isSelfFallback = true;
|
|
79
|
+
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_SELF_MANAGE });
|
|
80
|
+
}
|
|
53
81
|
entity = this.repository.merge(entity, data);
|
|
54
|
-
if (
|
|
82
|
+
if (isSelfFallback) await actor.permissionEvaluator.evaluate({
|
|
83
|
+
name: PermissionName.USER_SELF_MANAGE,
|
|
84
|
+
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [entity.name]: entity.value } })
|
|
85
|
+
});
|
|
86
|
+
else await actor.permissionEvaluator.evaluate({
|
|
87
|
+
name: PermissionName.USER_UPDATE,
|
|
88
|
+
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity })
|
|
89
|
+
});
|
|
55
90
|
await this.repository.save(entity);
|
|
56
91
|
return entity;
|
|
57
92
|
}
|
|
@@ -59,22 +94,14 @@ var UserAttributeService = class extends AbstractEntityService {
|
|
|
59
94
|
await actor.permissionEvaluator.preEvaluateOneOf({ name: [PermissionName.USER_UPDATE, PermissionName.USER_SELF_MANAGE] });
|
|
60
95
|
const entity = await this.repository.findOneBy({ id });
|
|
61
96
|
if (!entity) throw new NotFoundError();
|
|
62
|
-
if (!await this.
|
|
97
|
+
if (!await this.canReadUserAttribute(actor, entity)) throw new ForbiddenError();
|
|
63
98
|
const { id: entityId } = entity;
|
|
64
99
|
await this.repository.remove(entity);
|
|
65
100
|
entity.id = entityId;
|
|
66
101
|
return entity;
|
|
67
102
|
}
|
|
68
|
-
async
|
|
69
|
-
if (actor.identity && actor.identity.type === "user" && actor.identity.data.id === entity.user_id)
|
|
70
|
-
await actor.permissionEvaluator.evaluate({
|
|
71
|
-
name: PermissionName.USER_SELF_MANAGE,
|
|
72
|
-
input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity })
|
|
73
|
-
});
|
|
74
|
-
return true;
|
|
75
|
-
} catch {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
103
|
+
async canReadUserAttribute(actor, entity) {
|
|
104
|
+
if (actor.identity && actor.identity.type === "user" && actor.identity.data.id === entity.user_id) return true;
|
|
78
105
|
try {
|
|
79
106
|
await actor.permissionEvaluator.evaluate({
|
|
80
107
|
name: PermissionName.USER_UPDATE,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","PolicyData","BadRequestError","ForbiddenError","NotFoundError","PermissionName","buildErrorMessageForAttribute","AbstractEntityService","UserAttributeService","repository","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","USER_UPDATE","USER_SELF_MANAGE","data","entities","meta","findMany","total","entity","canManage","canManageUserAttribute","push","getOne","id","findOneBy","create","validateJoinColumns","user","realm_id","identity","type","user_id","save","update","evaluateOneOf","merge","delete","entityId","remove","isMe","evaluate","input","ATTRIBUTES"],"sources":["../../../../src/core/entities/user-attribute/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, PolicyData } from '@authup/access';\nimport { BadRequestError, ForbiddenError, NotFoundError } from '@ebec/http';\nimport { PermissionName } from '@authup/core-kit';\nimport type { UserAttribute } from '@authup/core-kit';\nimport { buildErrorMessageForAttribute } from 'validup';\nimport type { ActorContext } from '../actor/types.ts';\nimport { AbstractEntityService } from '../service.ts';\nimport type { EntityRepositoryFindManyResult } from '../types.ts';\nimport type { IUserAttributeRepository, IUserAttributeService } from './types.ts';\n\nexport type UserAttributeServiceContext = {\n repository: IUserAttributeRepository;\n};\n\nexport class UserAttributeService extends AbstractEntityService implements IUserAttributeService {\n protected repository: IUserAttributeRepository;\n\n constructor(ctx: UserAttributeServiceContext) {\n super();\n this.repository = ctx.repository;\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<UserAttribute>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n const {\n data: entities, \n meta, \n } = await this.repository.findMany(query);\n\n const data: UserAttribute[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n const canManage = await this.canManageUserAttribute(actor, entity);\n if (canManage) {\n data.push(entity);\n } else {\n total--;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total, \n }, \n };\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n const canManage = await this.canManageUserAttribute(actor, entity);\n if (!canManage) {\n throw new ForbiddenError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n await this.repository.validateJoinColumns(data);\n\n if (data.user) {\n data.realm_id = data.user.realm_id;\n } else if (\n actor.identity &&\n actor.identity.type === 'user'\n ) {\n data.user_id = actor.identity.data.id;\n data.realm_id = actor.identity.data.realm_id;\n } else {\n throw new BadRequestError(buildErrorMessageForAttribute('user_id'));\n }\n\n const entity = this.repository.create(data);\n\n const canManage = await this.canManageUserAttribute(actor, entity);\n if (!canManage) {\n throw new ForbiddenError();\n }\n\n await this.repository.save(entity);\n\n return entity;\n }\n\n async update(\n id: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n await actor.permissionEvaluator.evaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n await this.repository.validateJoinColumns(data);\n\n let entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n entity = this.repository.merge(entity, data);\n\n const canManage = await this.canManageUserAttribute(actor, entity);\n if (!canManage) {\n throw new ForbiddenError();\n }\n\n await this.repository.save(entity);\n\n return entity;\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n const canManage = await this.canManageUserAttribute(actor, entity);\n if (!canManage) {\n throw new ForbiddenError();\n }\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n\n private async canManageUserAttribute(\n actor: ActorContext,\n entity: UserAttribute,\n ): Promise<boolean> {\n const isMe = actor.identity &&\n actor.identity.type === 'user' &&\n actor.identity.data.id === entity.user_id;\n\n if (isMe) {\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_SELF_MANAGE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n return true;\n } catch {\n return false;\n }\n }\n\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n return true;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","PolicyData","BadRequestError","ForbiddenError","NotFoundError","PermissionName","buildErrorMessageForAttribute","AbstractEntityService","UserAttributeService","repository","reservedNames","ctx","Set","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","USER_UPDATE","USER_SELF_MANAGE","data","entities","meta","findMany","total","entity","canRead","canReadUserAttribute","push","getOne","id","findOneBy","create","targetUserId","user_id","user","isSelfTarget","identity","type","isSelfFallback","preEvaluate","e","validateJoinColumns","has","realm_id","evaluate","input","ATTRIBUTES","value","save","update","merge","delete","entityId","remove","isMe"],"sources":["../../../../src/core/entities/user-attribute/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, PolicyData } from '@authup/access';\nimport { BadRequestError, ForbiddenError, NotFoundError } from '@ebec/http';\nimport { PermissionName } from '@authup/core-kit';\nimport type { UserAttribute } from '@authup/core-kit';\nimport { buildErrorMessageForAttribute } from 'validup';\nimport type { ActorContext } from '../actor/types.ts';\nimport { AbstractEntityService } from '../service.ts';\nimport type { EntityRepositoryFindManyResult } from '../types.ts';\nimport type { IUserAttributeRepository, IUserAttributeService } from './types.ts';\n\nexport type UserAttributeServiceContext = {\n repository: IUserAttributeRepository;\n reservedNames?: ReadonlySet<string>;\n};\n\nexport class UserAttributeService extends AbstractEntityService implements IUserAttributeService {\n protected repository: IUserAttributeRepository;\n\n protected reservedNames: ReadonlySet<string>;\n\n constructor(ctx: UserAttributeServiceContext) {\n super();\n this.repository = ctx.repository;\n this.reservedNames = ctx.reservedNames ?? new Set();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<UserAttribute>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n const {\n data: entities,\n meta,\n } = await this.repository.findMany(query);\n\n const data: UserAttribute[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n const canRead = await this.canReadUserAttribute(actor, entity);\n if (canRead) {\n data.push(entity);\n } else {\n total--;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total,\n },\n };\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n const canRead = await this.canReadUserAttribute(actor, entity);\n if (!canRead) {\n throw new ForbiddenError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n const targetUserId: string | undefined = data.user_id ||\n (data.user && data.user.id);\n\n const isSelfTarget = !!actor.identity &&\n actor.identity.type === 'user' &&\n (!targetUserId || targetUserId === actor.identity.data.id);\n\n let isSelfFallback = false;\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_UPDATE });\n } catch (e) {\n if (!isSelfTarget) {\n throw e;\n }\n isSelfFallback = true;\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_SELF_MANAGE });\n }\n\n await this.repository.validateJoinColumns(data);\n\n if (typeof data.name === 'string' && this.reservedNames.has(data.name)) {\n throw new BadRequestError(`The user-attribute name '${data.name}' collides with a User entity column.`);\n }\n\n if (data.user) {\n data.realm_id = data.user.realm_id;\n } else if (\n actor.identity &&\n actor.identity.type === 'user'\n ) {\n data.user_id = actor.identity.data.id;\n data.realm_id = actor.identity.data.realm_id;\n } else {\n throw new BadRequestError(buildErrorMessageForAttribute('user_id'));\n }\n\n const entity = this.repository.create(data);\n\n if (isSelfFallback) {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_SELF_MANAGE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [data.name]: data.value } }),\n });\n } else {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n }\n\n await this.repository.save(entity);\n\n return entity;\n }\n\n async update(\n id: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n await this.repository.validateJoinColumns(data);\n\n if (typeof data.name === 'string' && this.reservedNames.has(data.name)) {\n throw new BadRequestError(`The user-attribute name '${data.name}' collides with a User entity column.`);\n }\n\n let entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n const isSelfTarget = !!actor.identity &&\n actor.identity.type === 'user' &&\n actor.identity.data.id === entity.user_id;\n\n let isSelfFallback = false;\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_UPDATE });\n } catch (e) {\n if (!isSelfTarget) {\n throw e;\n }\n isSelfFallback = true;\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.USER_SELF_MANAGE });\n }\n\n entity = this.repository.merge(entity, data);\n\n if (isSelfFallback) {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_SELF_MANAGE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: { [entity.name]: entity.value } }),\n });\n } else {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n }\n\n await this.repository.save(entity);\n\n return entity;\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<UserAttribute> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.USER_UPDATE,\n PermissionName.USER_SELF_MANAGE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new NotFoundError();\n }\n\n const canRead = await this.canReadUserAttribute(actor, entity);\n if (!canRead) {\n throw new ForbiddenError();\n }\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n\n private async canReadUserAttribute(\n actor: ActorContext,\n entity: UserAttribute,\n ): Promise<boolean> {\n const isMe = actor.identity &&\n actor.identity.type === 'user' &&\n actor.identity.data.id === entity.user_id;\n\n if (isMe) {\n return true;\n }\n\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.USER_UPDATE,\n input: new PolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity }),\n });\n\n return true;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/identity/index.ts"],"names":[],"mappings":"AAOA,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/identity/index.ts"],"names":[],"mappings":"AAOA,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
|
|
@@ -24,4 +24,5 @@ import { RegistrationService } from "./registration/service.mjs";
|
|
|
24
24
|
import "./registration/index.mjs";
|
|
25
25
|
import { IdentityResolver } from "./resolver/module.mjs";
|
|
26
26
|
import "./resolver/index.mjs";
|
|
27
|
-
|
|
27
|
+
import { IdentityRoleProvider } from "./role/module.mjs";
|
|
28
|
+
export { IDENTITY_PROVIDER_LDAP_COLLECTION_AUTHENTICATOR_TOKEN, IdentityPermissionProvider, IdentityProviderAccountBaseMapper, IdentityProviderAccountManager, IdentityProviderAttributeMapper, IdentityProviderFacebookAuthenticator, IdentityProviderGithubAuthenticator, IdentityProviderGoogleAuthenticator, IdentityProviderInstagramAuthenticator, IdentityProviderLdapAuthenticator, IdentityProviderLdapCollectionAuthenticator, IdentityProviderMapperOperation, IdentityProviderOAuth2Authenticator, IdentityProviderOpenIDAuthenticator, IdentityProviderPaypalAuthenticator, IdentityProviderPermissionMapper, IdentityProviderRoleMapper, IdentityResolver, IdentityRoleProvider, PasswordRecoveryService, RegistrationService, createIdentityProviderOAuth2Authenticator };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/password-recovery/service.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACR,wBAAwB,EACxB,oBAAoB,EACpB,8BAA8B,EAC9B,8BAA8B,EAC9B,mBAAmB,EACtB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEjF,qBAAa,uBAAwB,YAAW,wBAAwB;IACpE,SAAS,CAAC,OAAO,EAAE,8BAA8B,CAAC;IAElD,SAAS,CAAC,UAAU,EAAE,eAAe,CAAC;IAEtC,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAE5C,SAAS,CAAC,UAAU,EAAE,WAAW,CAAC;gBAEtB,GAAG,EAAE,8BAA8B;IAOzC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAsDxE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;YA0C9D,0BAA0B;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/password-recovery/service.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACR,wBAAwB,EACxB,oBAAoB,EACpB,8BAA8B,EAC9B,8BAA8B,EAC9B,mBAAmB,EACtB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEjF,qBAAa,uBAAwB,YAAW,wBAAwB;IACpE,SAAS,CAAC,OAAO,EAAE,8BAA8B,CAAC;IAElD,SAAS,CAAC,UAAU,EAAE,eAAe,CAAC;IAEtC,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAE5C,SAAS,CAAC,UAAU,EAAE,WAAW,CAAC;gBAEtB,GAAG,EAAE,8BAA8B;IAOzC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAsDxE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;YA0C9D,0BAA0B;YA8C1B,yBAAyB;CA2E1C"}
|
|
@@ -79,10 +79,10 @@ var PasswordRecoveryService = class {
|
|
|
79
79
|
const validator = new Container({});
|
|
80
80
|
const oneOfContainer = new Container({ oneOf: true });
|
|
81
81
|
oneOfContainer.mount("email", createValidator(() => {
|
|
82
|
-
return createValidationChain().exists().notEmpty().isEmail();
|
|
82
|
+
return createValidationChain().exists().notEmpty().trim().toLowerCase().isEmail().matches(/^[^A-Z]+$/).withMessage("Email must be lowercase.");
|
|
83
83
|
}));
|
|
84
84
|
oneOfContainer.mount("name", createValidator(() => {
|
|
85
|
-
return createValidationChain().exists().notEmpty().isString();
|
|
85
|
+
return createValidationChain().exists().notEmpty().isString().trim().toLowerCase();
|
|
86
86
|
}));
|
|
87
87
|
validator.mount(oneOfContainer);
|
|
88
88
|
validator.mount("realm_id", { optional: true }, createValidator(() => {
|
|
@@ -94,10 +94,10 @@ var PasswordRecoveryService = class {
|
|
|
94
94
|
const validator = new Container({});
|
|
95
95
|
const oneOfContainer = new Container({ oneOf: true });
|
|
96
96
|
oneOfContainer.mount("email", createValidator(() => {
|
|
97
|
-
return createValidationChain().exists().notEmpty().isEmail();
|
|
97
|
+
return createValidationChain().exists().notEmpty().trim().toLowerCase().isEmail().matches(/^[^A-Z]+$/).withMessage("Email must be lowercase.");
|
|
98
98
|
}));
|
|
99
99
|
oneOfContainer.mount("name", createValidator(() => {
|
|
100
|
-
return createValidationChain().exists().notEmpty().isString();
|
|
100
|
+
return createValidationChain().exists().notEmpty().isString().trim().toLowerCase();
|
|
101
101
|
}));
|
|
102
102
|
validator.mount(oneOfContainer);
|
|
103
103
|
validator.mount("realm_id", { optional: true }, createValidator(() => {
|