UNPKG

realm-object-server

Version:

Realm Object Server

962 lines 43.2 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs-extra"); const path = require("path"); const URI = require("urijs"); const moment = require("moment"); const crypto = require("crypto"); const useragent = require("express-useragent"); const Queue = require("js-queue"); const _ = require("lodash"); const util_1 = require("../shared/util"); const decorators_1 = require("../decorators"); const Token_1 = require("../shared/Token"); const errors = require("../errors"); const ConfigurableServiceBase_1 = require("./ConfigurableServiceBase"); const realms_1 = require("../realms"); const Constants_1 = require("../shared/Constants"); const events_1 = require("events"); let AuthService = class AuthService extends ConfigurableServiceBase_1.ConfigurableServiceBase { constructor(config = {}) { super(config); this.providers = []; this.providerQueue = new Queue(); events_1.EventEmitter.call(this); } setConfigCore(config = {}) { this.runtimeConfigurationEnabled = config.enableRuntimeConfiguration; this.refreshTokenTtl = config.refreshTokenTtl || moment.duration(10, "years").asSeconds(); this.userTokenTtl = config.userTokenTtl || moment.duration(1, "hours").asSeconds(); this.accessTokenTtl = config.accessTokenTtl || moment.duration(6, "minutes").asSeconds(); this.allowAnyUserToRetrieveUserInfo = config.allowAnyUserToRetrieveUserInfo; } addProvider(provider) { this.providers.push(provider); } setDefaultProviders(providers) { this.defaultProviders = providers; } getUserByProviderId(provider, providerId) { const accounts = this.adminRealm.objects("Account").filtered("provider = $0 AND providerId = $1", provider, providerId); if (accounts.length > 0) { return accounts[0].users[0]; } return undefined; } createOrUpdateUser(providerId, provider, isAdmin, metadata = {}, userId) { return __awaiter(this, void 0, void 0, function* () { const missingParameters = new Array(); if (!provider) { missingParameters.push("provider"); } if (!providerId) { missingParameters.push("providerId"); } if (missingParameters.length > 0) { throw new errors.realm.MissingParameters(...missingParameters); } if (userId) { const encodedUserId = encodeURIComponent(userId); if (userId !== encodedUserId) { throw new errors.realm.InvalidParameters({ name: "userId", reason: `Realm requires the userId that does not require URI encoding. Supplied: '${userId}', encoded: '${encodedUserId}'`, }); } } let user = this.getUserByProviderId(provider, providerId); if (user && userId && userId !== user.userId) { throw new errors.realm.InvalidParameters({ name: "userId", reason: "userId does not match the user found by provider/providerId" }); } yield util_1.downloadAllServerChanges(this.adminRealm); this.adminRealm.beginTransaction(); if (!user) { user = this.getUserByProviderId(provider, providerId); } let hasChanges = false; if (user) { if (isAdmin !== undefined && user.isAdmin !== isAdmin) { user.isAdmin = isAdmin; hasChanges = true; } user.created = false; } else { hasChanges = true; user = this.adminRealm.create("User", { userId: userId || this.generateUniqueId(), isAdmin: isAdmin || false, }, true); user.accounts.push({ provider: provider, providerId: providerId }); user.created = true; } const totalUsers = this.adminRealm.objects("User").length; hasChanges = this.updateUserMetadataInTransaction(user, metadata) || hasChanges; if (hasChanges) { this.adminRealm.commitTransaction(); yield util_1.uploadAllLocalChanges(this.adminRealm); } else { this.adminRealm.cancelTransaction(); } if (user.created) { this.emit("userCreated", { user, totalUsers }); } return user; }); } updateUserMetadata(user, metadata = {}) { return util_1.writeAsync(this.adminRealm, () => this.updateUserMetadataInTransaction(user, metadata)); } updateUserMetadataInTransaction(user, metadata = {}) { const realmUser = (typeof user === "string") ? this.adminRealm.objectForPrimaryKey("User", user) : user; const oldMetadata = {}; for (const row of realmUser.metadata) { oldMetadata[row.key] = row.value; } if (_.isEqual(oldMetadata, metadata)) { return false; } this.adminRealm.delete(realmUser.metadata); for (const key in metadata) { realmUser.metadata.push({ key: key, value: metadata[key] }); } return true; } startCore(server) { return __awaiter(this, void 0, void 0, function* () { this.logger = server.logger.withContext({ service: "auth" }); this.server = server; this.privateKey = server.privateKey; this.adminRealm = yield server.openRealm(realms_1.AdminRealm); this.tokenRevocationRealm = yield server.openRealm(realms_1.TokenRevocationRealm); this.realmDirectoryClient = server.realmDirectoryClient; this.authCounter = this.stats.counter({ name: "ros_auth_requests_total", help: "Counter of total auth requests, with provider", labelNames: ["provider", "identity"], }); try { let foundUser = this.adminRealm.objectForPrimaryKey("User", Constants_1.Constants.AdminUserId); if (!foundUser) { foundUser = yield this.createOrUpdateUser(Constants_1.Constants.AdminUserId, "realm", true, {}, Constants_1.Constants.AdminUserId); this.logger.info(`Autocreated admin token user: ${Constants_1.Constants.AdminUserId}`); } } catch (err) { this.logger.error("Failed to autocreate admin token user", err); } yield this.pruneRevocationTokens(); this.cleanupInterval = setInterval(this.pruneRevocationTokens.bind(this), 1000 * 60 * 60 * 24); if (this.runtimeConfigurationEnabled === undefined) { const hasSetProviders = !util_1.isArrayEmpty(this.providers); const hasSetDefaultProviders = !util_1.isArrayEmpty(this.defaultProviders); if (hasSetProviders && hasSetDefaultProviders) { throw new Error("Setting providers with addProvider is incompatible with using the runtime configuration API (using setDefaultProviders)."); } this.runtimeConfigurationEnabled = !hasSetProviders; } if (this.runtimeConfigurationEnabled) { const providerConfigs = this.configurationRealm.objects("AuthProviderConfig"); if (providerConfigs.length === 0 || this.defaultProviders.findIndex(p => p.forceCodeConfig) > -1) { const providers = (this.defaultProviders || []).filter(p => providerConfigs.length === 0 || p.forceCodeConfig); let shouldCommitTransaction = false; this.configurationRealm.beginTransaction(); for (const provider of providers) { const name = provider.name || provider.type; const config = provider.config ? JSON.stringify(provider.config) : null; const forceCodeConfig = provider.forceCodeConfig === true; const existing = this.configurationRealm.objectForPrimaryKey("AuthProviderConfig", name); const hasChanges = !existing || existing.name !== name || existing.type !== provider.type || existing.forceCodeConfig !== forceCodeConfig || existing.config !== config; if (hasChanges) { this.configurationRealm.create("AuthProviderConfig", { name: name, type: provider.type, config: config, forceCodeConfig: forceCodeConfig }, true); shouldCommitTransaction = true; } } if (shouldCommitTransaction) { this.configurationRealm.commitTransaction(); } else { this.configurationRealm.cancelTransaction(); } } for (const providerConfig of providerConfigs) { try { const provider = this.createProvider(providerConfig); this.providers.push(provider); } catch (err) { this.logger.error(`Could not initialize auth provider '${providerConfig.name}': ${err.message}`); } } providerConfigs.addListener((collection, changes) => { const containsChanges = changes.deletions.length || changes.modifications.length || changes.insertions.length; if (containsChanges) { this.enqueueProviderOperation(() => __awaiter(this, void 0, void 0, function* () { yield Promise.all(this.providers.map(p => this.stopProvider(p))); this.providers.length = 0; yield Promise.all(providerConfigs.map((config) => __awaiter(this, void 0, void 0, function* () { try { const provider = this.createProvider(config); this.providers.push(provider); yield this.startProvider(provider); } catch (err) { this.logger.error(`Failed to start provider ${config.type}(${config.name}) with config ${config.config}. Error: ${err}`); } }))); })); } }); } yield new Promise((resolve) => { this.enqueueProviderOperation(() => __awaiter(this, void 0, void 0, function* () { const promises = this.providers.map((p) => __awaiter(this, void 0, void 0, function* () { try { this.logger.detail(`Starting auth provider '${p.name}'`); yield this.startProvider(p); } catch (err) { this.logger.error(`Failed to start provider ${p.name} during initial boot. Error: ${err}`); } })); yield Promise.all(promises); resolve(); })); }); }); } stopping() { return __awaiter(this, void 0, void 0, function* () { yield this.stopProviderQueue(); yield Promise.all(this.providers.map(provider => { return this.stopProvider(provider); })); delete (this.providers); }); } stopCore() { return __awaiter(this, void 0, void 0, function* () { if (this.cleanupInterval) { clearInterval(this.cleanupInterval); } if (this.tokenRevocationRealm) { this.tokenRevocationRealm.close(); delete this.tokenRevocationRealm; } if (this.adminRealm) { this.adminRealm.close(); delete this.adminRealm; } }); } authenticate(req, body) { return __awaiter(this, void 0, void 0, function* () { const providerName = body.provider; const appId = body["app_id"] || "io.realm.Auth"; if (!providerName) { throw new errors.realm.MissingParameters("provider"); } if (providerName === "realm") { const data = body.data; if (!data) { throw new errors.realm.MissingParameters("data"); } let refreshToken; try { const token = this.server.tokenValidator.parse(data); if (!(token instanceof Token_1.RefreshToken)) { throw new errors.realm.AccessDenied(); } refreshToken = token; } catch (err) { if (err instanceof errors.realm.RealmProblem) { throw err; } throw new errors.realm.AccessDenied({ title: "Failed to parse token", detail: err.message }); } const user = this.adminRealm.objectForPrimaryKey("User", refreshToken.identity); this.validateStatus(user); this.authCounter.inc({ provider: providerName, identity: refreshToken.identity }); if (body["path"]) { const path = util_1.validateRealmPath(body["path"], refreshToken.identity); return this.accessToken(user, path, refreshToken, data, appId); } return this.userToken(user, refreshToken, appId); } const provider = this.providers.find((p) => p.name === providerName); if (!provider) { throw new errors.realm.InvalidParameters("provider"); } const user = yield provider.authenticateOrCreateUser(body); this.validateStatus(user); const refreshToken = new Token_1.RefreshToken({ appId, identity: user.userId, isAdmin: user.isAdmin, expires: moment().add(this.refreshTokenTtl, "second").unix(), isEmailConfirmed: user.isEmailConfirmed() }); req.socket.identity = refreshToken.identity; this.authCounter.inc({ provider: providerName, identity: user.userId }); return { refresh_token: { token: refreshToken.sign(this.privateKey), token_data: refreshToken.toJSON(), } }; }); } userToken(user, token, app_id) { return __awaiter(this, void 0, void 0, function* () { const userToken = new Token_1.UserToken({ identity: token.identity, isAdmin: user.isAdmin, appId: app_id, expires: moment().add(this.userTokenTtl, "seconds").unix(), }); return { user_token: { token: userToken.sign(this.privateKey), token_data: userToken.toJSON(), } }; }); } accessToken(user, path, token, data, app_id) { return __awaiter(this, void 0, void 0, function* () { path = path.replace("~", token.identity); const partialInfo = util_1.extractPartialInfo(path); if (partialInfo.isPartial) { path = partialInfo.canonicalPath; } let mayRead = false; let mayWrite = false; let mayManage = false; let syncLabel = ""; const shouldCreate = true; if (user.isAdmin) { mayRead = true; mayWrite = true; mayManage = true; if (partialInfo.isPartial) { const realmResponseReference = yield this.server.realmDirectoryClient.findByPath({ realmPath: path, shouldCreate, token: data, realmType: realms_1.RealmType.reference }); util_1.ensureRealmOfType(realms_1.RealmType.reference, realmResponseReference.realmType); const realmResponsePartial = yield this.server.realmDirectoryClient.findByPath({ realmPath: partialInfo.fullPath, shouldCreate, token: data, realmType: realms_1.RealmType.partial }); syncLabel = realmResponsePartial.syncLabel; } else { const realmResponse = yield this.server.realmDirectoryClient.findByPath({ realmPath: path, shouldCreate, token: data, realmType: realms_1.RealmType.full }); syncLabel = realmResponse.syncLabel; } } else { if (partialInfo.isPartial) { mayRead = true; mayWrite = true; const realmResponsePartial = yield this.server.realmDirectoryClient.findByPath({ realmPath: partialInfo.fullPath, shouldCreate, token: data, realmType: realms_1.RealmType.partial }); syncLabel = realmResponsePartial.syncLabel; } else { const realmResponse = yield this.server.realmDirectoryClient.findByPath({ realmPath: path, shouldCreate, token: data, realmType: realms_1.RealmType.full }); util_1.ensureRealmOfType(realms_1.RealmType.full, realmResponse.realmType); syncLabel = realmResponse.syncLabel; yield util_1.downloadAllServerChanges(this.adminRealm); const realmFile = this.adminRealm.objectForPrimaryKey("RealmFile", path); if (!realmFile) { throw new Error(`could not find realmfile: ${path}`); } const permissions = realmFile.permissions.filtered("user = null OR user.userId = $0 DISTINCT (mayRead, mayWrite, mayManage)", token.identity); permissions.forEach(permission => { mayRead = mayRead || permission.mayRead; mayWrite = mayWrite || permission.mayWrite; mayManage = mayManage || permission.mayManage; }); if (!mayRead && !mayWrite && !mayManage) { throw new errors.realm.AccessDenied(); } } } const access = []; if (mayRead) { access.push("download"); } if (mayWrite) { access.push("upload"); } if (mayManage) { access.push("manage"); } const isAskingForTildePermission = path === `/${token.identity}/__permission`; if (isAskingForTildePermission) { yield this.server.permissionsClient.onDemand(data); } const appId = app_id || "io.realm.Auth"; const accessToken = new Token_1.AccessToken({ identity: token.identity, appId, access: access, path: partialInfo.fullPath, expires: moment().add(this.accessTokenTtl, "seconds").unix(), syncLabel: syncLabel, }); return { access_token: { token: accessToken.sign(this.privateKey), token_data: accessToken.toJSON(), } }; }); } validateStatus(user) { if (!user || user.status === realms_1.UserStatus.suspended) { throw new errors.realm.AccessDenied({ title: "User account has been suspended. Please contact us for more information.", detail: `User ${user ? `with Id: '${user.userId}' has been suspended` : "does not exist"}.`, }); } } revokeToken(tokenData, req) { return __awaiter(this, void 0, void 0, function* () { if (!tokenData || tokenData === "") { throw new errors.realm.MissingParameters("token"); } const token = this.server.tokenValidator.parse(tokenData); this.requireAdminOrUserId(req, token.identity); const expires = token.expires ? new Date(token.expires * 1000) : null; yield util_1.writeAsync(this.tokenRevocationRealm, () => { this.tokenRevocationRealm.create("TokenRevocation", { expires, token: token.getRevocationId(), revoked: new Date(), }, true); }); this.logger.detail(`Revoked token for userId ${token.identity}. Token id: ${token.getRevocationId()}`); return {}; }); } getUserById(userId, req) { if (!this.allowAnyUserToRetrieveUserInfo) { this.requireAdminOrUserId(req, userId); } const user = this.adminRealm.objectForPrimaryKey("User", userId); if (!user) { throw new errors.realm.UnknownAccount(); } return user; } getUserByProviderIdApi(provider, providerId, req) { const decodedProviderId = URI.decode(providerId); const user = this.getUserByProviderId(provider, decodedProviderId); if (user && (this.allowAnyUserToRetrieveUserInfo || this.server.tokenValidator.isAdminToken(req.authToken) || user.userId === req.authToken.identity)) { return user; } throw new errors.realm.UnknownAccount(); } createOrUpdateUserApi(req, providerId, provider, isAdmin, metadata = {}, userId) { return __awaiter(this, void 0, void 0, function* () { this.requireAdminOrUserId(req); return this.createOrUpdateUser(providerId, provider, isAdmin, metadata, userId); }); } patchUserApi(req, userId, status) { return __awaiter(this, void 0, void 0, function* () { this.requireAdminOrUserId(req); const user = this.adminRealm.objectForPrimaryKey("User", userId); if (!user) { throw new errors.realm.UnknownUser(); } if (!(status in realms_1.UserStatus)) { throw new errors.realm.InvalidParameters("status"); } if (user.status !== status) { this.adminRealm.write(() => { user.status = status; }); } return user; }); } getProviders(req) { this.requireAdminOrUserId(req); this.requireRuntimeConfiguration(); return this.providers.map(p => { let type; let config; let name; name = p.providerConfigName; const configObject = this.configurationRealm.objectForPrimaryKey("AuthProviderConfig", name); if (configObject) { type = configObject.type; config = configObject.config ? JSON.parse(configObject.config) : {}; } return { name: name, type: type || "unknown", config: config }; }); } addOrUpdateProviderApi(req, type, config, name) { return __awaiter(this, void 0, void 0, function* () { this.requireAdminOrUserId(req); this.requireRuntimeConfiguration(); yield util_1.writeAsync(this.configurationRealm, () => { this.configurationRealm.create("AuthProviderConfig", { name: name || type, type: type, config: config ? JSON.stringify(config) : null, forceCodeConfig: false }, true); }); return {}; }); } removeProviderApi(req, name) { return __awaiter(this, void 0, void 0, function* () { this.requireAdminOrUserId(req); this.requireRuntimeConfiguration(); this.configurationRealm.beginTransaction(); const config = this.configurationRealm.objectForPrimaryKey("AuthProviderConfig", name); if (!config) { this.configurationRealm.cancelTransaction(); throw new errors.JSONError({ status: 404, title: "Provider not found.", detail: `The provider ${name} was not found in the list of active providers.` }); } this.configurationRealm.delete(config); this.configurationRealm.commitTransaction(); return {}; }); } updateProviderData(providerName, userId, data, req) { return __awaiter(this, void 0, void 0, function* () { if (!userId) { userId = req.authToken.identity; } this.requireAdminOrUserId(req, userId); const provider = this.providers.find((p) => p.name === providerName); if (!provider) { throw new errors.realm.InvalidParameters("provider"); } if (!data) { throw new errors.realm.MissingParameters("data"); } const user = this.adminRealm.objectForPrimaryKey("User", userId); if (!user) { throw new errors.realm.UnknownAccount(); } if (provider.update) { return provider.update(user, data); } return {}; }); } updateProviderAccount(providerName, data, req, providerId) { return __awaiter(this, void 0, void 0, function* () { const provider = this.providers.find((p) => p.name === providerName); if (!provider) { throw new errors.realm.InvalidParameters("provider"); } if (!provider.updateProviderAccount) { throw new errors.realm.InvalidParameters({ name: "provider", reason: "this provider does not support updating user accounts." }); } const user = providerId && this.getUserByProviderId(providerName, providerId); const isAuthenticated = !!(req.authToken && (this.server.tokenValidator.isAdminToken(req.authToken) || (user && req.authToken.identity === user.userId))); const userAgent = useragent.parse(req.get("user-agent") || ""); const ip = req.get("x-forwarded-for") || req.connection.remoteAddress; return provider.updateProviderAccount(providerId, user, data, isAuthenticated, userAgent, ip); }); } deleteUser(userId, req) { return __awaiter(this, void 0, void 0, function* () { this.requireAdminOrUserId(req, userId); this.logger.debug(`User ${userId} is requested to be deleted`); yield this.deleteUserWithUserId(userId); this.logger.debug(`User ${userId} has been deleted`); return {}; }); } enhanceLog(getToken, body) { if (getToken("method") === "POST" && getToken("url") === "/auth") { const logSegments = [`provider: ${body.provider}`]; if (body.provider === "realm") { logSegments.push(`path: '${body.path}'`); } else { const provider = this.providers.find(p => p.name === body.provider); if (!provider) { logSegments.push("INVALID"); } else if (provider.enhanceLog) { logSegments.push(provider.enhanceLog(body)); } } return `[${logSegments.filter(l => l).join(", ")}]`; } return null; } createProvider(config) { let parsedConfig; if (!config.config) { parsedConfig = {}; } else { let configString = config.config; const matches = configString.match(/%%[^%]*%%/g); if (matches) { for (const match of matches) { const replacement = process.env[match.replace(/%%/g, "")]; configString = configString.replace(match, replacement); } } parsedConfig = JSON.parse(configString); } const Providers = require("../auth"); const result = new Providers[config.type](parsedConfig); result.providerConfigName = config.name; return result; } startProvider(provider) { return __awaiter(this, void 0, void 0, function* () { Reflect.set(provider, "service", this); if (provider.start) { yield provider.start(); } if (provider.name === "nickname") { this.logger.warn("The 'Nickname' auth provider has been enabled. This provider is not secure and should never be used " + "in production deployments. If you're still developing your application and experimenting, it is not " + "a problem, but if this instance is hosting production data, please disable it immediately."); } }); } stopProvider(provider) { return __awaiter(this, void 0, void 0, function* () { let toStop; if (typeof provider === "string") { const index = this.providers.findIndex(p => p.providerConfigName === provider); if (index !== -1) { toStop = this.providers.splice(index, 1)[0]; } } else { toStop = provider; } if (toStop) { if (toStop.stop) { yield toStop.stop(); } Reflect.set(toStop, "service", undefined); } }); } pruneRevocationTokens() { return __awaiter(this, void 0, void 0, function* () { const deadRevocations = this.tokenRevocationRealm.objects("TokenRevocation").filtered("expires < $0", new Date()); if (deadRevocations.length > 0) { yield util_1.writeAsync(this.tokenRevocationRealm, () => { this.tokenRevocationRealm.delete(deadRevocations); }); } }); } enqueueProviderOperation(operation) { this.providerQueue.add(() => __awaiter(this, void 0, void 0, function* () { try { this.hasPendingProviderOperations = true; yield operation(); } catch (err) { this.logger.log("error", `Provider modification operation failed: ${err}`); } finally { this.hasPendingProviderOperations = false; this.providerQueue.next(); } })); } stopProviderQueue() { return __awaiter(this, void 0, void 0, function* () { this.providerQueue.stop = true; yield util_1.waitAsync(() => this.hasPendingProviderOperations, p => !p, 10000); }); } generateUniqueId() { return crypto.randomBytes(16).toString("hex"); } requireAdminOrUserId(req, userId) { if (!this.server.tokenValidator.isAdminToken(req.authToken)) { if (!userId) { throw new errors.realm.AccessDenied(); } if (userId && userId !== req.authToken.identity) { throw new errors.realm.AccessDenied(); } } } requireRuntimeConfiguration() { if (!this.runtimeConfigurationEnabled) { throw new errors.JSONError({ title: "Runtime configuration disabled", status: 403, detail: "The runtime configuration API has been disabled." }); } } deleteUserWithUserId(userId) { return __awaiter(this, void 0, void 0, function* () { const adminRealm = this.adminRealm; const user = adminRealm.objectForPrimaryKey("User", userId); if (!user) { throw new errors.realm.UnknownUser(); } const filesToDelete = adminRealm.objects("RealmFile") .filtered("owner.userId = $0", userId) .map((realmFile) => { return { path: realmFile.path }; }); let providerNames = []; yield util_1.writeAsync(adminRealm, () => { const user = adminRealm.objectForPrimaryKey("User", userId); if (!user) { throw new errors.realm.UnknownUser(); } adminRealm.delete(user.metadata); providerNames = user.accounts.map((account) => { return account.provider; }); adminRealm.delete(user.accounts); const permissions = adminRealm.objects("Permission") .filtered("user.userId = $0", userId); adminRealm.delete(permissions); adminRealm.delete(user); }); const deleteUserPromises = []; providerNames.forEach((providerName) => { const provider = this.providers.find((p) => p.name === providerName); if (provider) { deleteUserPromises.push(provider.deleteUser(userId)); } }); yield Promise.all(deleteUserPromises); yield Promise.all(filesToDelete.map((file) => __awaiter(this, void 0, void 0, function* () { yield this.server["realmFactory"].forceCloseRealm(file.path, `Force closing Realm at path ${file.path} due to user deletion of ${userId}.`, true); try { yield this.realmDirectoryClient.delete(file.path); } catch (err) { this.logger.error(`Deletion of a Realm on the sync server failed, path = ${file.path}`); } }))); const localUserDir = path.join(this.server.dataPath, "realms", userId); try { yield fs.remove(localUserDir); } catch (err) { this.logger.error(`Unable to remove user directory: '${localUserDir}'`); } }); } }; __decorate([ decorators_1.Stopping(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", Promise) ], AuthService.prototype, "stopping", null); __decorate([ decorators_1.Post("/", { allowAnonymous: true }), __param(0, decorators_1.Request()), __param(1, decorators_1.Body()), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], AuthService.prototype, "authenticate", null); __decorate([ decorators_1.Post("/revoke"), __param(0, decorators_1.Body("token")), __param(1, decorators_1.Request()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object]), __metadata("design:returntype", Promise) ], AuthService.prototype, "revokeToken", null); __decorate([ decorators_1.Get("/users/:user_id"), __param(0, decorators_1.Params("user_id")), __param(1, decorators_1.Request()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object]), __metadata("design:returntype", realms_1.User) ], AuthService.prototype, "getUserById", null); __decorate([ decorators_1.Get("/users/:provider/:provider_id"), __param(0, decorators_1.Params("provider")), __param(1, decorators_1.Params("provider_id")), __param(2, decorators_1.Request()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String, Object]), __metadata("design:returntype", realms_1.User) ], AuthService.prototype, "getUserByProviderIdApi", null); __decorate([ decorators_1.Put("/users"), __param(0, decorators_1.Request()), __param(1, decorators_1.Body("provider_id")), __param(2, decorators_1.Body("provider")), __param(3, decorators_1.Body("is_admin")), __param(4, decorators_1.Body("metadata")), __param(5, decorators_1.Body("user_id")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String, String, Boolean, Object, String]), __metadata("design:returntype", Promise) ], AuthService.prototype, "createOrUpdateUserApi", null); __decorate([ decorators_1.Patch("/users/:user_id"), __param(0, decorators_1.Request()), __param(1, decorators_1.Params("user_id")), __param(2, decorators_1.Body("status")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String, String]), __metadata("design:returntype", Promise) ], AuthService.prototype, "patchUserApi", null); __decorate([ decorators_1.Get("/providers"), __param(0, decorators_1.Request()), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Array) ], AuthService.prototype, "getProviders", null); __decorate([ decorators_1.Post("/providers"), __param(0, decorators_1.Request()), __param(1, decorators_1.Body("type")), __param(2, decorators_1.Body("config")), __param(3, decorators_1.Body("name")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String, Object, String]), __metadata("design:returntype", Promise) ], AuthService.prototype, "addOrUpdateProviderApi", null); __decorate([ decorators_1.Delete("/providers/:name"), __param(0, decorators_1.Request()), __param(1, decorators_1.Params("name")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String]), __metadata("design:returntype", Promise) ], AuthService.prototype, "removeProviderApi", null); __decorate([ decorators_1.Put("/:provider"), __param(0, decorators_1.Params("provider")), __param(1, decorators_1.Body("user_id")), __param(2, decorators_1.Body("data")), __param(3, decorators_1.Request()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String, Object, Object]), __metadata("design:returntype", Promise) ], AuthService.prototype, "updateProviderData", null); __decorate([ decorators_1.Post("/:provider/updateAccount", { allowAnonymous: true }), __param(0, decorators_1.Params("provider")), __param(1, decorators_1.Body("data")), __param(2, decorators_1.Request()), __param(3, decorators_1.Body("provider_id")), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object, Object, String]), __metadata("design:returntype", Promise) ], AuthService.prototype, "updateProviderAccount", null); __decorate([ decorators_1.Delete("/user/:user_id"), decorators_1.Delete("/users/:user_id"), __param(0, decorators_1.Params("user_id")), __param(1, decorators_1.Request()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object]), __metadata("design:returntype", Promise) ], AuthService.prototype, "deleteUser", null); __decorate([ decorators_1.EnhanceLog(), __metadata("design:type", Function), __metadata("design:paramtypes", [Function, Object]), __metadata("design:returntype", String) ], AuthService.prototype, "enhanceLog", null); AuthService = __decorate([ decorators_1.BaseRoute("/auth", { allowAnonymous: false }), decorators_1.ServiceName("auth"), decorators_1.Cors("/"), __metadata("design:paramtypes", [Object]) ], AuthService); exports.AuthService = AuthService; Object.assign(AuthService.prototype, events_1.EventEmitter.prototype); //# sourceMappingURL=AuthService.js.map