/**
 * Copyright (c) HashiCorp, Inc.
 * SPDX-License-Identifier: BUSL-1.1
 */

import Adapter from './application';
import { inject as service } from '@ember/service';

export default class PermissionAdapter extends Adapter {
  @service('env') env;
  @service('settings') settings;

  requestForAuthorize(request, { dc, ns, partition, resources = [], index }) {
    // the authorize endpoint is slightly different to all others in that it
    // ignores an ns parameter, but accepts a Namespace property on each
    // resource. Here we hide this difference from the rest of the app as
    // currently we never need to ask for permissions/resources for multiple
    // different namespaces in one call so here we use the ns param and add
    // this to the resources instead of passing through on the queryParameter
    //
    // ^ same goes for Partitions

    if (this.env.var('CONSUL_NSPACES_ENABLED')) {
      resources = resources.map((item) => ({ ...item, Namespace: ns }));
    }
    if (this.env.var('CONSUL_PARTITIONS_ENABLED')) {
      resources = resources.map((item) => ({ ...item, Partition: partition }));
    }
    return request`
      POST /v1/internal/acl/authorize?${{ dc }}

      ${resources}
    `;
  }

  authorize(store, type, id, snapshot) {
    return this.rpc(
      async (adapter, request, serialized, unserialized) => {
        // the authorize endpoint does not automatically take into account the
        // default namespace of the token on the backend. This means that we
        // need to add the default namespace of the token on the frontend
        // instead. Decided this is the best place for it as its almost hidden
        // from the rest of the app so from an app eng point of view it almost
        // feels like it does happen on the backend.
        // Same goes ^ for partitions
        const nspacesEnabled = this.env.var('CONSUL_NSPACES_ENABLED');
        const partitionsEnabled = this.env.var('CONSUL_PARTITIONS_ENABLED');
        if (nspacesEnabled || partitionsEnabled) {
          const token = await this.settings.findBySlug('token');
          if (nspacesEnabled) {
            if (typeof serialized.ns === 'undefined' || serialized.ns.length === 0) {
              serialized.ns = token.Namespace;
            }
          }
          if (partitionsEnabled) {
            if (typeof serialized.partition === 'undefined' || serialized.partition.length === 0) {
              serialized.partition = token.Partition;
            }
          }
        }
        return adapter.requestForAuthorize(request, serialized);
      },
      function (serializer, respond, serialized, unserialized) {
        // Completely skip the serializer here
        return respond(function (headers, body) {
          return body;
        });
      },
      snapshot,
      type.modelName
    );
  }
}
