moleculer-iam
Version:
Centralized IAM module for moleculer. Including a certified OIDC provider and an Identity provider for user profile, credentials, and custom claims management. Custom claims could be defined/updated by declarative schema which contains claims validation a
124 lines • 4.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Identity = void 0;
const tslib_1 = require("tslib");
const _ = tslib_1.__importStar(require("lodash"));
const metadata_1 = require("./metadata");
class Identity {
constructor(props) {
this.props = props;
}
get id() {
return this.props.id;
}
get adapter() {
return this.props.provider.adapter;
}
get accountId() {
return this.props.id;
}
/**
* @param use - can either be "id_token" or "userinfo", depending on where the specific claims are intended to be put in.
* @param scope - the intended scope, while oidc-provider will mask
* claims depending on the scope automatically you might want to skip
* loading some claims from external resources etc. based on this detail
* or not return them in id tokens but only userinfo and so on.
* @param claims
* @param rejected
*/
async claims(use = "userinfo", scope = "", claims, rejected) {
return this.adapter.getClaims(this.id, typeof scope === "string" ? scope.split(" ").filter(s => !!s) : scope);
}
async updateClaims(claims, scope = "", transaction, ignoreUndefinedClaims) {
await this.adapter.createOrUpdateClaimsWithValidation(this.id, claims, typeof scope === "string" ? scope.split(" ").filter(s => !!s) : scope, false, transaction, ignoreUndefinedClaims);
}
async deleteClaims(scope = "", transaction) {
// check mandatory scopes
const scopes = (typeof scope === "string" ? scope.split(" ").filter(s => !!s) : scope);
const mandatoryScopes = this.props.provider.claims.mandatoryScopes;
if (scopes.some(s => mandatoryScopes.includes(s))) {
throw new Error(`cannot delete mandatory scopes: ${mandatoryScopes}`);
}
await this.adapter.deleteClaims(this.id, scopes, transaction);
}
/* identity metadata (federation information, etc. not-versioned) */
async metadata() {
const metadata = await this.adapter.getMetadata(this.id);
if (!metadata)
throw new Error(`empty metadata: ${this.id}`);
return metadata;
}
async updateMetadata(metadata, transaction) {
await this.adapter.createOrUpdateMetadata(this.id, _.defaultsDeep(metadata, metadata_1.defaultIdentityMetadata), transaction);
}
/* credentials */
async assertCredentials(credentials) {
return this.adapter.assertCredentials(this.id, credentials);
}
async updateCredentials(credentials, transaction) {
return this.adapter.createOrUpdateCredentialsWithValidation(this.id, credentials, transaction);
}
/* update all */
async update(scope = "", claims, metadata, credentials, transaction, ignoreUndefinedClaims) {
// validate claims and credentials
if (typeof scope === "string") {
scope = scope.split(" ").filter(s => !!s);
}
else if (!scope) {
scope = [];
}
// save metadata, claims, credentials
let isolated = false;
if (!transaction) {
transaction = transaction = await this.adapter.transaction();
isolated = true;
}
try {
if (typeof claims === "object" && claims !== null && Object.keys(claims).length > 0) {
await this.updateClaims(claims, scope, transaction, ignoreUndefinedClaims);
}
if (typeof credentials === "object" && credentials !== null && Object.keys(credentials).length > 0) {
await this.updateCredentials(credentials, transaction);
}
if (typeof metadata === "object" && metadata !== null && Object.keys(metadata).length > 0) {
await this.updateMetadata(metadata, transaction);
}
if (isolated) {
await transaction.commit();
}
}
catch (err) {
if (isolated) {
await transaction.rollback();
}
throw err;
}
return;
}
/* fetch all */
async json(scope = "") {
const [claims, metadata] = await Promise.all([this.claims(undefined, scope), this.metadata()]);
return {
id: this.id,
claims,
metadata,
};
}
/* delete identity */
async delete(permanently = false, transaction) {
if (permanently) {
await this.adapter.delete(this.id, transaction);
}
else {
await this.adapter.createOrUpdateMetadata(this.id, { softDeleted: true }, transaction);
}
}
async isSoftDeleted() {
return this.metadata().then(meta => meta.softDeleted);
}
async restoreSoftDeleted(transaction) {
await this.adapter.createOrUpdateMetadata(this.id, { softDeleted: false }, transaction);
}
}
exports.Identity = Identity;
//# sourceMappingURL=identity.js.map