bcgov/common-forms-toolkit

View on GitHub
app/src/forms/teammanagement/service.js

Summary

Maintainability
A
0 mins
Test Coverage
const keycloakAdminService = require('../../components').keycloakAdminService;

const DEFAULT_REQUEST_ROLE = require('../common/constants').DEFAULT_REQUEST_ROLE;

const notFoundProblem = keycloakAdminService._notFoundProblem;
const throwProblem = keycloakAdminService._problem;

class Service {
  constructor(resourceAccess) {
    this._resourceAccess = resourceAccess;
    this._clientName = `comfort-${this._resourceAccess}`;
    this._clientId = null;
  }

  async processAccessRequest(accessRequest, user) {
    if (!user || !user.id) {
      throwProblem(401,'Unauthorized','No current user in request.');
    }
    const requestAccessRole = accessRequest ? (accessRequest.role || DEFAULT_REQUEST_ROLE)  : DEFAULT_REQUEST_ROLE;
    // ok, get this client and the role we want to place user in.
    const client = await this.getClient();
    const role = await keycloakAdminService.getClientRoleByName(client.id, requestAccessRole);
    // put them in the role!
    await keycloakAdminService.addClientRoleMappings(this._clientId, [user], [role]);
    return await this.getUser(user.id);
  }


  async getClient(includeRoles = false, includeUsers = false, includeUserRoles = false) {
    if (!this._clientId) {
      const clients = await keycloakAdminService.findClients(this._clientName);
      if (!clients || !clients.length) {
        notFoundProblem('client', this._clientName);
      }
      this._clientId = clients[0].id;
    }
    const client = await keycloakAdminService.getClient(this._clientId, includeRoles, includeUsers, includeUserRoles);
    // from roles... only return the roles that we use for assignment.
    client.roles = client.roles.filter(x => x.composite);
    return client;
  }

  async getUsers(includeRoles = false) {
    const client = await this.getClient(true, true, includeRoles );
    const users = new Map();
    client.roles.forEach(r => {
      r.users.forEach(u => users.set(u.id, u));
    });
    return [...users.values()];
  }

  async getUser(id) {
    const client = await this.getClient();
    const user = await keycloakAdminService.getClientUser(client.id, id, true);
    if (!user) {
      notFoundProblem('user', id);
    }
    return user;
  }

  async getUserRoles(id) {
    const user = await this.getUser(id);
    return user.roles;
  }

  async updateUserRoles(id, roles) {
    const user = await this.getUser(id);

    if (!Array.isArray(roles)) {
      roles = [roles];
    }
    if (roles.length > 1) {
      throwProblem(422, 'Validation Error', 'User can only be in a single role.');
    }

    // since a user can be in only one role, we remove them from their current roles
    await keycloakAdminService.removeClientRoleMappings(this._clientId, [user], user.roles);

    // now we put them in the new role (if specified)
    let assignedRoles = [];
    if (roles.length) {
      assignedRoles = [await this.getRole(roles[0].id)];
    }
    await keycloakAdminService.addClientRoleMappings(this._clientId, [user], assignedRoles);

    // return their current set of roles...
    return await this.getUserRoles(id);
  }

  async getRoles(includeUsers = false) {
    const client = await this.getClient(true, includeUsers);
    return client.roles;
  }

  async getRole(id) {
    const roles = await this.getRoles(true);
    const role = roles.find(x => x.id === id);
    if (!role) {
      notFoundProblem('role', id);
    }
    return role;
  }

  async getRoleUsers(id) {
    const role = await this.getRole(id);
    return role.users;
  }

  async updateRoleUsers(id, users) {
    // here we limit the users to a single role...
    const allRoles = await this.getRoles(false);
    const role = await this.getRole(id);

    // remove all the current users from this role...
    const currentRoleUsers = await this.getRoleUsers(id);
    await keycloakAdminService.removeClientRoleMappings(this._clientId, currentRoleUsers, [role]);

    // remove these users from all other roles (they can have only one role)
    await keycloakAdminService.removeClientRoleMappings(this._clientId, users, allRoles);

    // now, add the specified users to this role
    await keycloakAdminService.addClientRoleMappings(this._clientId, users, [role]);

    // return the current set of users in this role.
    return await this.getRoleUsers(id);
  }

}

module.exports = Service;