Source: client/tenant.js

  1. /*
  2. * Copyright 2023, TeamDev. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Redistribution and use in source and/or binary forms, with or without
  11. * modification, must retain the above copyright notice and the following
  12. * disclaimer.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  15. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  16. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  18. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  20. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. import {TenantId} from "../proto/spine/core/tenant_id_pb";
  27. import {EmailAddress} from "../proto/spine/net/email_address_pb";
  28. import {InternetDomain} from "../proto/spine/net/internet_domain_pb";
  29. import {isProtobufMessage, Type} from "./typed-message";
  30. /**
  31. * A factory of `TenantId` instances.
  32. *
  33. * Exposes methods that are "shortcuts" for the convenient creation of `TenantId` message
  34. * instances.
  35. */
  36. export class TenantIds {
  37. /**
  38. * Constructs a `TenantId` which represents an internet domain.
  39. *
  40. * @param {!string} domainName the domain name as a plain string
  41. * @return {TenantId} a new `TenantId` instance
  42. */
  43. static internetDomain(domainName) {
  44. if (!domainName) {
  45. throw new Error('Expected a non-empty internet domain name.');
  46. }
  47. const domain = new InternetDomain();
  48. domain.setValue(domainName);
  49. const result = new TenantId();
  50. result.setDomain(domain);
  51. return result;
  52. }
  53. /**
  54. * Constructs a `TenantId` which represents an email address.
  55. *
  56. * @param {!string} address the email address as a plain string
  57. * @return {TenantId} a new `TenantId` instance
  58. */
  59. static emailAddress(address) {
  60. if (!address) {
  61. throw new Error('Expected a non-empty email address value.');
  62. }
  63. const emailAddress = new EmailAddress();
  64. emailAddress.setValue(address);
  65. const result = new TenantId();
  66. result.setEmail(emailAddress);
  67. return result;
  68. }
  69. /**
  70. * Constructs a `TenantId` which is a plain string value.
  71. *
  72. * @param {!string} tenantIdValue the tenant ID
  73. * @return {TenantId} a new `TenantId` instance
  74. */
  75. static plainString(tenantIdValue) {
  76. if (!tenantIdValue) {
  77. throw new Error('Expected a valid tenant ID value.');
  78. }
  79. const result = new TenantId();
  80. result.setValue(tenantIdValue);
  81. return result;
  82. }
  83. }
  84. /**
  85. * The current tenant provider.
  86. *
  87. * This object is passed to the `ActorRequestFactory` and is used during creation of all
  88. * client-side requests.
  89. *
  90. * The current tenant ID can be switched dynamically with the help of the `update` method.
  91. *
  92. * If it is necessary to update the current ID to a "no tenant" value (to work in a single-tenant
  93. * environment), pass the default tenant ID to the `update` method as follows:
  94. * `tenantProvider.update(new TenantId())`.
  95. */
  96. export class TenantProvider {
  97. /**
  98. * Creates a new `TenantProvider` configured with the passed tenant ID.
  99. *
  100. * The argument may be omitted but until the `_tenantId` is assigned some non-default value, the
  101. * application is considered single-tenant.
  102. *
  103. * @param {?TenantId} tenantId the ID of the currently active tenant
  104. */
  105. constructor(tenantId) {
  106. if (tenantId) {
  107. TenantProvider._checkIsValidTenantId(tenantId);
  108. this._tenantId = tenantId;
  109. }
  110. }
  111. /**
  112. * @param {!TenantId} tenantId the ID of the currently active tenant
  113. */
  114. update(tenantId) {
  115. TenantProvider._checkIsValidTenantId(tenantId);
  116. this._tenantId = tenantId;
  117. }
  118. /**
  119. * Returns the currently active tenant ID.
  120. *
  121. * @return {TenantId}
  122. */
  123. tenantId() {
  124. return this._tenantId;
  125. }
  126. /**
  127. * Checks that the passed object represents a `TenantId` message.
  128. *
  129. * @param {!object} tenantId the object to check
  130. * @private
  131. */
  132. static _checkIsValidTenantId(tenantId) {
  133. if (!tenantId
  134. || !isProtobufMessage(tenantId)
  135. || Type.forMessage(tenantId).url().value() !== 'type.spine.io/spine.core.TenantId') {
  136. throw new Error(`Expected a valid instance of the 'TenantId' message.`
  137. + `The '${tenantId}' was passed instead.`);
  138. }
  139. }
  140. }