keycloak-typescript
Version:
A user friendly library to use keycloak in nodejs projects
392 lines • 18.6 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
// Interfaces
const IUserManager_1 = require("./Interfaces/IUserManager");
// Models
const UserFields_1 = require("../enums/UserFields");
// Helpers
const headers_factory_1 = require("../helpers/headers-factory");
const request_builder_1 = require("../helpers/request-builder");
class UserManager extends IUserManager_1.IUserManager {
constructor(url, realmManager, clientManager, allowedUserFields) {
super();
this.accessToken = '';
/**
*
* @param queryParameter
* - briefRepresentation: Defines whether brief representations are returned
* - email: User's email
* - emailVerified: whether the email has been verified
* - enabled: User is enabled or not
* - firstName
* - lastName
* @param queryValue
* @returns { User[] }
*/
this.getUsers = (queryParameter, queryValue) => __awaiter(this, void 0, void 0, function* () {
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
const apiConfig = {
url: `${this.url}?${queryParameter}=${queryValue}&exact=true`,
method: 'GET',
headers: headers,
body: {}
};
const response = yield (0, request_builder_1.requestBuilder)(apiConfig);
return response.data;
});
this.getUserId = (username) => __awaiter(this, void 0, void 0, function* () {
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
const apiConfig = {
url: `${this.url}?username=${username}&exact=true`,
method: 'GET',
headers: headers,
body: {}
};
const response = yield (0, request_builder_1.requestBuilder)(apiConfig);
const userId = response.data[0].id;
return userId;
});
this.get = (userId) => __awaiter(this, void 0, void 0, function* () {
var _a;
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
const apiConfig = {
url: `${this.url}/${userId}`,
method: 'GET',
headers: headers,
body: {}
};
const response = yield (0, request_builder_1.requestBuilder)(apiConfig);
const user = this.trimUserInfo(response.data);
if (this.allowedUserFields.has(UserFields_1.UserFields.CLIENT_ROLES) ||
this.allowedUserFields.has(UserFields_1.UserFields.REALM_ROLES)) {
const rolesResponse = yield this.getRoles(userId);
if (rolesResponse) {
if (this.allowedUserFields.has(UserFields_1.UserFields.CLIENT_ROLES) &&
rolesResponse.clientMappings) {
user.clientRoles = user.clientRoles ? user.clientRoles : new Map();
rolesResponse.clientMappings = rolesResponse.clientMappings
? new Map(Object.entries(rolesResponse.clientMappings))
: new Map();
rolesResponse.clientMappings.forEach((value, key) => {
var _a;
(_a = user.clientRoles) === null || _a === void 0 ? void 0 : _a.set(key, []);
value.mappings.forEach((roleRepresentation) => {
var _a, _b;
(_b = (_a = user.clientRoles) === null || _a === void 0 ? void 0 : _a.get(key)) === null || _b === void 0 ? void 0 : _b.push(roleRepresentation.name ? roleRepresentation.name : '');
});
});
}
if (this.allowedUserFields.has(UserFields_1.UserFields.REALM_ROLES) ||
rolesResponse.realmMappings) {
user.realmRoles = user.realmRoles ? user.realmRoles : [];
(_a = rolesResponse.realmMappings) === null || _a === void 0 ? void 0 : _a.forEach((realmMapping) => {
var _a;
(_a = user.realmRoles) === null || _a === void 0 ? void 0 : _a.push(realmMapping.name ? realmMapping.name : '');
});
}
}
}
return user;
});
this.create = (email, username, enabled, firstName, lastName, password, isTemporaryPassword, verifyEmail, attributes) => __awaiter(this, void 0, void 0, function* () {
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
const objectAttributes = JSON.parse(attributes);
const apiConfig = {
url: this.url,
method: 'POST',
headers: headers,
body: {
email: email,
username: username,
firstName: firstName,
lastName: lastName,
enabled: enabled,
attributes: objectAttributes
}
};
const response = yield (0, request_builder_1.requestBuilder)(apiConfig);
const userID = response.headers.location.split('/').pop();
yield this.resetPassword(userID, password, isTemporaryPassword);
if (verifyEmail)
yield this.sendVerificationMail(userID);
return userID;
});
this.resetPassword = (userId, newPassword, isTemporary) => __awaiter(this, void 0, void 0, function* () {
const apiConfig = {
url: `${this.url}/${userId}/reset-password`,
method: 'PUT',
headers: headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken),
body: {
type: 'password',
value: newPassword,
temporary: isTemporary
}
};
yield (0, request_builder_1.requestBuilder)(apiConfig);
});
this.forgotPassword = (userId) => __awaiter(this, void 0, void 0, function* () {
const apiConfig = {
url: `${this.url}/${userId}/execute-actions-email`,
method: 'PUT',
headers: headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken),
body: ['UPDATE_PASSWORD']
};
yield (0, request_builder_1.requestBuilder)(apiConfig);
});
this.sendVerificationMail = (userId) => __awaiter(this, void 0, void 0, function* () {
const apiConfig = {
url: `${this.url}/${userId}/send-verify-email`,
method: 'PUT',
headers: headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken),
body: {}
};
yield (0, request_builder_1.requestBuilder)(apiConfig);
});
this.delete = (userId) => __awaiter(this, void 0, void 0, function* () {
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
const apiConfig = {
url: `${this.url}/${userId}`,
method: 'DELETE',
headers: headers,
body: {}
};
yield (0, request_builder_1.requestBuilder)(apiConfig);
});
this.url = url;
this.allowedUserFields = new Set(allowedUserFields ? allowedUserFields : UserFields_1.UserFields.getDefaultFields());
this.clientManager = clientManager;
this.realmManager = realmManager;
}
modify(userId, user, isReplaceOperation) {
return __awaiter(this, void 0, void 0, function* () {
user = !isReplaceOperation
? this.fuseUsers(user, yield this.get(userId))
: user;
user.attributes = Object.fromEntries(user.attributes ? user.attributes : []);
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
const apiConfig = {
url: `${this.url}/${userId}`,
method: 'PUT',
headers: headers,
body: user
};
yield (0, request_builder_1.requestBuilder)(apiConfig);
//wait for add roles request
yield this.modifyRoles(userId, user.realmRoles, user.clientRoles);
return user;
});
}
update(subject, args) {
if (args.length > 0) {
this.accessToken = args[0];
}
}
trimUserInfo(user) {
return {
id: this.allowedUserFields.has(UserFields_1.UserFields.ID) ? user.id : undefined,
origin: this.allowedUserFields.has(UserFields_1.UserFields.ORIGIN)
? user.origin
: undefined,
createdTimestamp: this.allowedUserFields.has(UserFields_1.UserFields.CREATED_TIMESTAMP)
? user.createdTimestamp
: undefined,
username: this.allowedUserFields.has(UserFields_1.UserFields.USERNAME)
? user.username
: undefined,
enabled: this.allowedUserFields.has(UserFields_1.UserFields.ENABLED)
? user.enabled
: undefined,
totp: this.allowedUserFields.has(UserFields_1.UserFields.TOTP) ? user.totp : undefined,
emailVerified: this.allowedUserFields.has(UserFields_1.UserFields.EMAIL_VERIFIED)
? user.emailVerified
: undefined,
firstName: this.allowedUserFields.has(UserFields_1.UserFields.FIRST_NAME)
? user.firstName
: undefined,
lastName: this.allowedUserFields.has(UserFields_1.UserFields.LAST_NAME)
? user.lastName
: undefined,
email: this.allowedUserFields.has(UserFields_1.UserFields.EMAIL)
? user.email
: undefined,
federationLink: this.allowedUserFields.has(UserFields_1.UserFields.FEDERATION_LINK)
? user.federationLink
: undefined,
serviceAccountClientId: this.allowedUserFields.has(UserFields_1.UserFields.SERVICE_ACCOUNT_CLIENTID)
? user.serviceAccountClientId
: undefined,
attributes: this.allowedUserFields.has(UserFields_1.UserFields.ATTRIBUTES)
? user.attributes
? new Map(Object.entries(user.attributes))
: undefined
: undefined,
credentials: this.allowedUserFields.has(UserFields_1.UserFields.CREDENTIALS)
? user.credentials
: undefined,
disableableCredentialTypes: this.allowedUserFields.has(UserFields_1.UserFields.DISABLE_CREDENTIAL_TYPES)
? user.disableableCredentialTypes
: undefined,
requiredActions: this.allowedUserFields.has(UserFields_1.UserFields.REQUIRED_ACTIONS)
? user.requiredActions
: undefined,
federatedIdentities: this.allowedUserFields.has(UserFields_1.UserFields.FEDERATED_ENTITIES)
? user.federatedIdentities
: undefined,
realmRoles: this.allowedUserFields.has(UserFields_1.UserFields.REALM_ROLES)
? user.realmRoles
: undefined,
clientRoles: this.allowedUserFields.has(UserFields_1.UserFields.CLIENT_ROLES)
? user.clientRoles
? new Map(user.clientRoles)
: undefined
: undefined,
clientConsents: this.allowedUserFields.has(UserFields_1.UserFields.CLIENT_CONSENTS)
? user.clientConsents
: undefined,
notBefore: this.allowedUserFields.has(UserFields_1.UserFields.NOT_BEFORE)
? user.notBefore
: undefined,
applicationRoles: this.allowedUserFields.has(UserFields_1.UserFields.APPLICATION_ROLES)
? user.applicationRoles
? new Map(user.applicationRoles)
: undefined
: undefined,
socialLinks: this.allowedUserFields.has(UserFields_1.UserFields.SOCIAL_LINKS)
? user.socialLinks
: undefined,
groups: this.allowedUserFields.has(UserFields_1.UserFields.GROUPS)
? user.groups
: undefined,
access: this.allowedUserFields.has(UserFields_1.UserFields.ACCESS)
? user.access
? new Map(user.access)
: undefined
: undefined
};
}
fuseUsers(a, b) {
//fuse only types that can be fused ex: append an array to another
if (a.attributes && b.attributes) {
b.attributes.forEach((value, key) => {
if (a.attributes.has(key))
a.attributes.set(key, a.attributes.get(key).concat(value));
else
a.attributes.set(key, value);
});
}
else if (b.attributes) {
a.attributes = b.attributes;
}
a.disableableCredentialTypes = a.disableableCredentialTypes
? b.disableableCredentialTypes
? new Set([
...a.disableableCredentialTypes,
...b.disableableCredentialTypes
])
: a.disableableCredentialTypes
: b.disableableCredentialTypes;
a.realmRoles = a.realmRoles
? b.realmRoles
? a.realmRoles.concat(b.realmRoles)
: b.realmRoles
: a.realmRoles;
if (a.clientRoles && b.clientRoles) {
b.clientRoles.forEach((value, key) => {
if (a.clientRoles.has(key))
a.clientRoles.set(key, a.clientRoles.get(key).concat(value));
else
a.clientRoles.set(key, value);
});
}
else if (b.clientRoles) {
a.clientRoles = b.clientRoles;
}
if (a.applicationRoles && b.applicationRoles) {
b.applicationRoles.forEach((value, key) => {
if (a.applicationRoles.has(key))
a.applicationRoles.set(key, a.applicationRoles.get(key).concat(value));
else
a.applicationRoles.set(key, value);
});
}
else if (b.applicationRoles) {
a.applicationRoles = b.applicationRoles;
}
a.groups = a.groups
? b.groups
? a.groups.concat(b.groups)
: b.groups
: a.groups;
if (a.access && b.access) {
b.access.forEach((value, key) => {
if (!a.access.has(key))
a.access.set(key, value);
});
}
else if (b.access) {
a.access = b.access;
}
return a;
}
getRoles(userId) {
return __awaiter(this, void 0, void 0, function* () {
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
const apiConfig = {
url: `${this.url}/${userId}/role-mappings`,
method: 'GET',
headers: headers,
body: {}
};
const response = yield (0, request_builder_1.requestBuilder)(apiConfig);
return response === null || response === void 0 ? void 0 : response.data;
});
}
modifyRoles(userId, realmRoles, clientRoles) {
return __awaiter(this, void 0, void 0, function* () {
const headers = headers_factory_1.HeadersFactory.instance().authorizationHeader(this.accessToken);
if (realmRoles) {
const realmsBody = [];
const realmRolesList = yield this.realmManager.getRoles('master', realmRoles);
realmRolesList.forEach((role) => {
var _a, _b;
realmsBody.push({ id: (_a = role.id) !== null && _a !== void 0 ? _a : '', name: (_b = role.name) !== null && _b !== void 0 ? _b : '' });
});
const apiConfig = {
url: `${this.url}/${userId}/role-mappings/realm`,
method: 'POST',
headers: headers,
body: realmsBody
};
yield (0, request_builder_1.requestBuilder)(apiConfig);
}
if (clientRoles) {
for (const [key, value] of clientRoles) {
const clientsBody = [];
const clientId = (yield this.clientManager.get('master', key)).id;
for (const role of value) {
const roleId = (yield this.clientManager.getRole('master', clientId, role)).id;
clientsBody.push({ id: roleId ? roleId : '', name: role });
}
const apiConfig = {
url: `${this.url}/${userId}/role-mappings/clients/${clientId}`,
method: 'POST',
headers: headers,
body: clientsBody
};
yield (0, request_builder_1.requestBuilder)(apiConfig);
}
}
});
}
}
exports.default = UserManager;
//# sourceMappingURL=UserManager.js.map