Source

infohub/Licence.js

// $Id$
// @ts-check

'use strict';

import { RestServices } from '../tools/RestServices.js';
import { ApiResponse } from '../tools/ApiResponse.js';
import { Context } from './Context.js';

/**
 *
 * @category COLNEO infohub
 *
 * @classdesc
 *  COLNEO infohub Licence
 *
 *  Information about an infohub user licence. Contains licencee information
 *  as well as modules and information about permissions.
 *
 * @example {
 *   "contract": "",
 *   "created": "2025-01-01T00:00:00Z",
 *   "createdby": "user@example.com",
 *   "expirated": null,
 *   "id": "00000000-0000-0000-0000-000000000000",
 *   "licenced_userids": ["user@example.com"],
 *   "licencee": {
 *     "address": "{\"street\":\"...\", \"city\":\"...\", \"zip\":\"...\"}",
 *     "email": "info@example.com",
 *     "name": "ACME"
 *   },
 *   "maxpermissions": 50,
 *   "maxseats": 0,
 *   "module": "objecttypes",
 *   "scope": "cn_dv",
 *   "startdate": "2025-01-01T00:00:00Z",
 *   "updated": "2025-01-01T00:00:00Z",
 *   "updatedby": "user@example.com"
 * }
 */
export class Licence {
  /**
   * Create a licence from a JSON object
   * @param {object} data - The licence data
   */
  constructor(data = /** @type {object} */ ({})) {
    Object.assign(this, data);
  }
  /**
   * Set the licence data
   * @param {object} data - The licence data
   * @returns {void}
   */
  setData(data = /** @type {object} */ ({})) {
    Object.assign(this, data);
  }
  /**
   * Get the licence data
   * @returns {object}
   */
  getData() {
    return Object.fromEntries(Object.entries(this).filter(([_, v]) => typeof v !== 'function'));
  }

  /**
   * Get licencee
   * @returns {any}
   */
  getLicencee() {
    return /** @type {any} */ (this)['licencee'];
  }
  /**
   * Get licenced user IDs
   * @returns {string[]}
   */
  getLicencedUserIds() {
    const ids = /** @type {any} */ (this)['licenced_userid'];
    return Array.isArray(ids) ? ids : typeof ids === 'string' ? [ids] : [];
  }
}

/**
 * @category COLNEO infohub
 * @classdesc
 *  COLNEO infohub Licence Services
 */
export class LicenceServices {
  /**
   * @param {Context} ctx - The context
   */
  constructor(ctx = /** @type {Context} */ ({})) {
    this._ctx = ctx;
  }

  // LicenceServices
  /**
   * List licences with optional filters (all can be combined).
   * like
   * ```js
   * const licences = await LicenceServices.getLicences({ scope: 'cn_dv', module: 'objecttypes', contract: 'contract_1', licencee: 'licencee_1', licence: 'licence_1' });
   * ```
   * @param {Record<string, string>} filters - The filters
   * @returns {Promise<ApiResponse>} Licence
   *
   * @since 09.2025, aab
   */
  async getLicences(filters = /** @type {Record<string, string>} */ ({})) {
    const base = this._ctx.getServiceUrl(Context.SERVICE.IDP);

    // generic query builder: keeps only non-empty values
    const q = new URLSearchParams();
    for (const [key, value] of Object.entries(filters)) {
      const v = String(value ?? '').trim();
      if (v) q.append(key, v);
    }
    const url = `${base}/admin/licences${q.toString() ? `?${q}` : ''}`;

    const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.GET, url);
    const arr = Array.isArray(res.data) ? /** @type {any[]} */ (res.data) : [];
    const list = arr.map((d) => new Licence(d));
    return new ApiResponse(res.status < 300 ? 200 : res.status, res.status < 300 ? list : null);
  }

  /**
   * Get a licence by ID
   * @param {string} licenceid - The licence ID
   * @returns {Promise<ApiResponse>} Licence
   * @since 09.2025, aab
   */
  async getLicenceById(licenceid) {
    if (!licenceid) {
      return new ApiResponse(400, null);
    }
    try {
      const url = `${this._ctx.getServiceUrl(Context.SERVICE.IDP)}/admin/licences/${licenceid}`;
      const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.GET, url);
      return res.status < 300 ? new ApiResponse(200, new Licence(res.data)) : new ApiResponse(res.status, null, res.message);
    } catch (error) {
      return new ApiResponse(500, null);
    }
  }

  /**
   * Get licences of a user
   * @param {string} userid - The user ID
   * @returns {Promise<ApiResponse>} Licence
   * @since 09.2025, aab
   */
  async getLicencesOfUser(userid) {
    if (!userid) {
      return new ApiResponse(400, null);
    }
    try {
      const url = `${this._ctx.getServiceUrl(Context.SERVICE.IDP)}/users/${userid}/licences`;
      const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.GET, url);
      const arr = Array.isArray(res.data) ? /** @type {any[]} */ (res.data) : [];
      const list = arr.map((d) => new Licence(d));
      return res.status < 300 ? new ApiResponse(200, list) : new ApiResponse(res.status, null, res.message);
    } catch (error) {
      return new ApiResponse(500, null);
    }
  }

  /**
   * Create a licence
   * @param {object} licence_data - The licence data
   * @param {string} [licence_data.contract] - The contract
   * @param {string} [licence_data.licencee] - The licencee
   * @param {string} [licence_data.scope] - The scope
   * @param {string} [licence_data.module] - The module
   * @param {string} [licence_data.maxpermissions] - The max permissions
   * @param {string} [licence_data.maxseats] - The max seats
   * @param {string} [licence_data.startdate] - The start date
   * @param {string} [licence_data.expirated] - The expirated date
   * @returns {Promise<ApiResponse>} Licence
   * @since 09.2025, aab
   */
  async createLicence(licence_data) {
    if (!licence_data) {
      return new ApiResponse(400, null);
    }
    try {
      const url = `${this._ctx.getServiceUrl(Context.SERVICE.IDP)}/admin/licences`;
      const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.POST, url, licence_data);
      return res.status < 300 ? new ApiResponse(200, new Licence(res.data)) : new ApiResponse(res.status, null, res.message);
    } catch (error) {
      return new ApiResponse(500, null);
    }
  }

  /**
   * Update a licence
   * @param {string} licenceid - The licence ID
   * @param {object} licence_data - The licence data
   * @param {string} [licence_data.contract] - The contract
   * @param {string} [licence_data.licencee] - The licencee
   * @param {string} [licence_data.scope] - The scope
   * @param {string} [licence_data.module] - The module
   * @param {string} [licence_data.maxpermissions] - The max permissions
   * @param {string} [licence_data.maxseats] - The max seats
   * @param {string} [licence_data.startdate] - The start date
   * @param {string} [licence_data.expirated] - The expirated date
   * @returns {Promise<ApiResponse>} Licence
   * @since 09.2025, aab
   */
  async updateLicence(licenceid, licence_data) {
    if (!licenceid || !licence_data) {
      return new ApiResponse(400, null);
    }
    try {
      const url = `${this._ctx.getServiceUrl(Context.SERVICE.IDP)}/admin/licences/${licenceid}`;
      const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.PATCH, url, licence_data);
      return res.status < 300 ? new ApiResponse(200, new Licence(res.data)) : new ApiResponse(res.status, null, res.message);
    } catch (error) {
      return new ApiResponse(500, null);
    }
  }

  /**
   * Delete a licence
   * @param {string} licenceid - The licence ID
   * @returns {Promise<ApiResponse>} message
   * @since 09.2025, aab
   */
  async deleteLicence(licenceid) {
    if (!licenceid) {
      return new ApiResponse(400, null);
    }
    try {
      const url = `${this._ctx.getServiceUrl(Context.SERVICE.IDP)}/admin/licences/${licenceid}`;
      const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.DELETE, url);
      return res.status < 300 ? new ApiResponse(200, res.data) : new ApiResponse(res.status, null, res.message);
    } catch (error) {
      return new ApiResponse(500, null);
    }
  }

  /**
   * Assign a licence to a user
   * @param {string[]} licenceids - The licence IDs
   * @param {string} userid - The user ID
   * @returns {Promise<ApiResponse>} message
   * @since 09.2025, aab
   */
  async assignLicenceToUser(licenceids, userid) {
    if (!licenceids || !userid) {
      return new ApiResponse(400, null);
    }
    const reqBody = {
      userid: userid,
      add_licences: licenceids,
    };
    try {
      const url = `${this._ctx.getServiceUrl(Context.SERVICE.IDP)}/admin/users`;
      const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.POST, url, reqBody);
      return res.status < 300 ? new ApiResponse(200, res.data, res.message) : new ApiResponse(res.status, null, res.message);
    } catch (error) {
      return new ApiResponse(500, null, error.message);
    }
  }

  /**
   * Unassign a licence from a user
   * @param {string} licenceid - The licence ID
   * @param {string} userid - The user ID
   * @returns {Promise<ApiResponse>} message
   * @since 09.2025, aab
   */
  async unassignLicenceFromUser(licenceid, userid) {
    if (!licenceid || !userid) {
      return new ApiResponse(400, null);
    }
    const reqBody = {
      userid: userid,
      remove_licences: [licenceid],
    };
    try {
      const url = `${this._ctx.getServiceUrl(Context.SERVICE.IDP)}/admin/users`;
      const res = await RestServices.makeApiCall(this._ctx.getToken(), RestServices.METHODS.POST, url, reqBody);
      return res.status < 300 ? new ApiResponse(200, res.data, res.message) : new ApiResponse(res.status, null, res.message);
    } catch (error) {
      return new ApiResponse(500, null, error.message);
    }
  }
}