installations-request-handler.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*! firebase-admin v12.1.1 */
  2. "use strict";
  3. /*!
  4. * @license
  5. * Copyright 2021 Google Inc.
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. Object.defineProperty(exports, "__esModule", { value: true });
  20. exports.FirebaseInstallationsRequestHandler = void 0;
  21. const error_1 = require("../utils/error");
  22. const api_request_1 = require("../utils/api-request");
  23. const utils = require("../utils/index");
  24. const validator = require("../utils/validator");
  25. /** Firebase IID backend host. */
  26. const FIREBASE_IID_HOST = 'console.firebase.google.com';
  27. /** Firebase IID backend path. */
  28. const FIREBASE_IID_PATH = '/v1/';
  29. /** Firebase IID request timeout duration in milliseconds. */
  30. const FIREBASE_IID_TIMEOUT = 10000;
  31. /** HTTP error codes raised by the backend server. */
  32. const ERROR_CODES = {
  33. 400: 'Malformed installation ID argument.',
  34. 401: 'Request not authorized.',
  35. 403: 'Project does not match installation ID or the client does not have sufficient privileges.',
  36. 404: 'Failed to find the installation ID.',
  37. 409: 'Already deleted.',
  38. 429: 'Request throttled out by the backend server.',
  39. 500: 'Internal server error.',
  40. 503: 'Backend servers are over capacity. Try again later.',
  41. };
  42. /**
  43. * Class that provides mechanism to send requests to the FIS backend endpoints.
  44. */
  45. class FirebaseInstallationsRequestHandler {
  46. /**
  47. * @param app - The app used to fetch access tokens to sign API requests.
  48. *
  49. * @constructor
  50. */
  51. constructor(app) {
  52. this.app = app;
  53. this.host = FIREBASE_IID_HOST;
  54. this.timeout = FIREBASE_IID_TIMEOUT;
  55. this.httpClient = new api_request_1.AuthorizedHttpClient(app);
  56. }
  57. deleteInstallation(fid) {
  58. if (!validator.isNonEmptyString(fid)) {
  59. return Promise.reject(new error_1.FirebaseInstallationsError(error_1.InstallationsClientErrorCode.INVALID_INSTALLATION_ID, 'Installation ID must be a non-empty string.'));
  60. }
  61. return this.invokeRequestHandler(new api_request_1.ApiSettings(fid, 'DELETE'));
  62. }
  63. /**
  64. * Invokes the request handler based on the API settings object passed.
  65. *
  66. * @param apiSettings - The API endpoint settings to apply to request and response.
  67. * @returns A promise that resolves when the request is complete.
  68. */
  69. invokeRequestHandler(apiSettings) {
  70. return this.getPathPrefix()
  71. .then((path) => {
  72. const req = {
  73. url: `https://${this.host}${path}${apiSettings.getEndpoint()}`,
  74. method: apiSettings.getHttpMethod(),
  75. timeout: this.timeout,
  76. };
  77. return this.httpClient.send(req);
  78. })
  79. .then(() => {
  80. // return nothing on success
  81. })
  82. .catch((err) => {
  83. if (err instanceof api_request_1.HttpError) {
  84. const response = err.response;
  85. const errorMessage = (response.isJson() && 'error' in response.data) ?
  86. response.data.error : response.text;
  87. const template = ERROR_CODES[response.status];
  88. const message = template ?
  89. `Installation ID "${apiSettings.getEndpoint()}": ${template}` : errorMessage;
  90. throw new error_1.FirebaseInstallationsError(error_1.InstallationsClientErrorCode.API_ERROR, message);
  91. }
  92. // In case of timeouts and other network errors, the HttpClient returns a
  93. // FirebaseError wrapped in the response. Simply throw it here.
  94. throw err;
  95. });
  96. }
  97. getPathPrefix() {
  98. if (this.path) {
  99. return Promise.resolve(this.path);
  100. }
  101. return utils.findProjectId(this.app)
  102. .then((projectId) => {
  103. if (!validator.isNonEmptyString(projectId)) {
  104. // Assert for an explicit projct ID (either via AppOptions or the cert itself).
  105. throw new error_1.FirebaseInstallationsError(error_1.InstallationsClientErrorCode.INVALID_PROJECT_ID, 'Failed to determine project ID for Installations. Initialize the '
  106. + 'SDK with service account credentials or set project ID as an app option. '
  107. + 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.');
  108. }
  109. this.path = FIREBASE_IID_PATH + `project/${projectId}/instanceId/`;
  110. return this.path;
  111. });
  112. }
  113. }
  114. exports.FirebaseInstallationsRequestHandler = FirebaseInstallationsRequestHandler;