'use strict';

var pluginPermissionCommon = require('@backstage/plugin-permission-common');

class ServerPermissionClient {
  #auth;
  #permissionClient;
  #permissionEnabled;
  static fromConfig(config, options) {
    const { auth, discovery } = options;
    const permissionClient = new pluginPermissionCommon.PermissionClient({ discovery, config });
    const permissionEnabled = config.getOptionalBoolean("permission.enabled") ?? false;
    return new ServerPermissionClient({
      auth,
      permissionClient,
      permissionEnabled
    });
  }
  constructor(options) {
    this.#auth = options.auth;
    this.#permissionClient = options.permissionClient;
    this.#permissionEnabled = options.permissionEnabled;
  }
  async authorizeConditional(queries, options) {
    const credentials = await this.#getIncomingCredentials(options);
    if (credentials && this.#auth.isPrincipal(credentials, "service")) {
      return this.#servicePrincipalDecision(queries, credentials);
    } else if (!this.#permissionEnabled) {
      return queries.map((_) => ({ result: pluginPermissionCommon.AuthorizeResult.ALLOW }));
    }
    return this.#permissionClient.authorizeConditional(
      queries,
      await this.#getRequestOptions(options)
    );
  }
  async authorize(requests, options) {
    const credentials = await this.#getIncomingCredentials(options);
    if (credentials && this.#auth.isPrincipal(credentials, "service")) {
      return this.#servicePrincipalDecision(requests, credentials);
    } else if (!this.#permissionEnabled) {
      return requests.map((_) => ({ result: pluginPermissionCommon.AuthorizeResult.ALLOW }));
    }
    return this.#permissionClient.authorize(
      requests,
      await this.#getRequestOptions(options)
    );
  }
  async #getRequestOptions(options) {
    if (options && "credentials" in options) {
      if (this.#auth.isPrincipal(options.credentials, "none")) {
        return {};
      }
      return this.#auth.getPluginRequestToken({
        onBehalfOf: options.credentials,
        targetPluginId: "permission"
      });
    }
    return options;
  }
  async #getIncomingCredentials(options) {
    if (options && "credentials" in options) {
      return options.credentials;
    }
    return void 0;
  }
  /**
   * For service principals, we can always make an immediate definitive decision
   * based on their associated access restrictions (if any).
   */
  #servicePrincipalDecision(input, credentials) {
    const { permissionNames, permissionAttributes } = credentials.principal.accessRestrictions ?? {};
    return input.map((item) => {
      if (permissionNames && !permissionNames.includes(item.permission.name)) {
        return { result: pluginPermissionCommon.AuthorizeResult.DENY };
      }
      if (permissionAttributes?.action) {
        const action = item.permission.attributes?.action;
        if (!action || !permissionAttributes.action.includes(action)) {
          return { result: pluginPermissionCommon.AuthorizeResult.DENY };
        }
      }
      return { result: pluginPermissionCommon.AuthorizeResult.ALLOW };
    });
  }
}

exports.ServerPermissionClient = ServerPermissionClient;
//# sourceMappingURL=ServerPermissionClient.cjs.js.map
