diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 81f718a90..dea5fb3ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,21 +1,21 @@ # Contributing When contributing to this repository, please first discuss the change you wish to make via issue, -email, or any other method with the owners of this repository before making a change. +email, or any other method with the owners of this repository before making a change. Please note we have a code of conduct, please follow it in all your interactions with the project. ## Pull Request Process 1. When making commits, make sure you are using [Gitmoji](https://github.com/carloscuesta/gitmoji). -2. Ensure any install or build dependencies are removed before the end of the layer when doing a +2. Ensure any install or build dependencies are removed before the end of the layer when doing a build. -3. Update the README.md with details of changes to the interface, this includes new environment +3. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. -4. Increase the version numbers in any examples files and the README.md to the new version that this +4. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. We increase the patch version in every commit to ensure people using Staart are always on the most recent version using our internal update system. -5. You may merge the Pull Request in once you have the review sign-off of Anand Chowdhary, or if you +5. You may merge the Pull Request in once you have the review sign-off of Anand Chowdhary, or if you do not have permission to do that, you may request a reviewer to merge it for you. ## Code of Conduct @@ -34,21 +34,21 @@ orientation. Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a +- Other conduct which could reasonably be considered inappropriate in a professional setting ### Our Responsibilities diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 828e3c213..26f86a03d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,13 +1,13 @@ trigger: -- master + - master pool: vmImage: "ubuntu-latest" steps: -- task: NodeTool@0 - inputs: - versionSpec: "12.x" - displayName: "Install Node.js" -- script: | - npm install - npm run build - displayName: "npm install and build" + - task: NodeTool@0 + inputs: + versionSpec: "12.x" + displayName: "Install Node.js" + - script: | + npm install + npm run build + displayName: "npm install and build" diff --git a/prisma/migrations/20200402221641-init/README.md b/prisma/migrations/20200402221641-init/README.md index f8b4db54e..2d1a772dd 100644 --- a/prisma/migrations/20200402221641-init/README.md +++ b/prisma/migrations/20200402221641-init/README.md @@ -28,7 +28,7 @@ CREATE TABLE `staart`.`users` ( `updatedAt` datetime(3) NOT NULL , `username` varchar(191) NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`organizations` ( @@ -44,7 +44,7 @@ CREATE TABLE `staart`.`organizations` ( `updatedAt` datetime(3) NOT NULL , `username` varchar(191) NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`emails` ( @@ -55,7 +55,7 @@ CREATE TABLE `staart`.`emails` ( `updatedAt` datetime(3) NOT NULL , `userId` int NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`access-tokens` ( @@ -69,7 +69,7 @@ CREATE TABLE `staart`.`access-tokens` ( `updatedAt` datetime(3) NOT NULL , `userId` int NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`api-keys` ( @@ -85,7 +85,7 @@ CREATE TABLE `staart`.`api-keys` ( `scopes` varchar(191) , `updatedAt` datetime(3) NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`approved-locations` ( @@ -94,7 +94,7 @@ CREATE TABLE `staart`.`approved-locations` ( `subnet` varchar(191) NOT NULL , `userId` int NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`backup-codes` ( @@ -105,7 +105,7 @@ CREATE TABLE `staart`.`backup-codes` ( `updatedAt` datetime(3) NOT NULL , `userId` int NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`domains` ( @@ -117,7 +117,7 @@ CREATE TABLE `staart`.`domains` ( `updatedAt` datetime(3) NOT NULL , `verificationCode` varchar(191) NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`identities` ( @@ -129,7 +129,7 @@ CREATE TABLE `staart`.`identities` ( `updatedAt` datetime(3) NOT NULL , `userId` int NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`memberships` ( @@ -140,7 +140,7 @@ CREATE TABLE `staart`.`memberships` ( `updatedAt` datetime(3) NOT NULL , `userId` int NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`sessions` ( @@ -156,7 +156,7 @@ CREATE TABLE `staart`.`sessions` ( `userAgent` varchar(191) NOT NULL , `userId` int NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE TABLE `staart`.`webhooks` ( @@ -171,7 +171,7 @@ CREATE TABLE `staart`.`webhooks` ( `updatedAt` datetime(3) NOT NULL , `url` varchar(191) NOT NULL , PRIMARY KEY (`id`) -) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CREATE UNIQUE INDEX `users.username` ON `staart`.`users`(`username`) @@ -461,5 +461,3 @@ migration ..20200402221641-init + @@index([organizationId], name: "organizationId") +} ``` - - diff --git a/prisma/migrations/20200402221641-init/steps.json b/prisma/migrations/20200402221641-init/steps.json index 66b0cc742..f3652407f 100644 --- a/prisma/migrations/20200402221641-init/steps.json +++ b/prisma/migrations/20200402221641-init/steps.json @@ -4,56 +4,32 @@ { "tag": "CreateEnum", "enum": "Gender", - "values": [ - "MALE", - "FEMALE", - "NONBINARY", - "UNKNOWN" - ] + "values": ["MALE", "FEMALE", "NONBINARY", "UNKNOWN"] }, { "tag": "CreateEnum", "enum": "NotificationEmails", - "values": [ - "ACCOUNT", - "UPDATES", - "PROMOTIONS" - ] + "values": ["ACCOUNT", "UPDATES", "PROMOTIONS"] }, { "tag": "CreateEnum", "enum": "PrefersColorScheme", - "values": [ - "NO_PREFERENCE", - "LIGHT", - "DARK" - ] + "values": ["NO_PREFERENCE", "LIGHT", "DARK"] }, { "tag": "CreateEnum", "enum": "PrefersReducedMotion", - "values": [ - "NO_PREFERENCE", - "REDUCE" - ] + "values": ["NO_PREFERENCE", "REDUCE"] }, { "tag": "CreateEnum", "enum": "UserRole", - "values": [ - "SUDO", - "USER" - ] + "values": ["SUDO", "USER"] }, { "tag": "CreateEnum", "enum": "MembershipRole", - "values": [ - "OWNER", - "ADMIN", - "RESELLER", - "MEMBER" - ] + "values": ["OWNER", "ADMIN", "RESELLER", "MEMBER"] }, { "tag": "CreateSource", @@ -3412,4 +3388,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/controllers/admin/index.ts b/src/controllers/admin/index.ts index 0ec407113..f8cbf04ad 100644 --- a/src/controllers/admin/index.ts +++ b/src/controllers/admin/index.ts @@ -4,13 +4,13 @@ import { Controller, Get, Request, - Response + Response, } from "@staart/server"; import { authHandler } from "../../helpers/middleware"; import { getAllOrganizationForUser, getAllUsersForUser, - getServerLogsForUser + getServerLogsForUser, } from "../../rest/admin"; @Controller("admin") @@ -41,7 +41,7 @@ export class AdminController { async info() { return { success: true, - message: "admin-info-success" + message: "admin-info-success", }; } } diff --git a/src/controllers/auth/index.ts b/src/controllers/auth/index.ts index 14b4660e9..3fc6d0a5f 100644 --- a/src/controllers/auth/index.ts +++ b/src/controllers/auth/index.ts @@ -3,7 +3,7 @@ import { RESOURCE_CREATED, RESOURCE_SUCCESS, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ChildControllers, @@ -11,14 +11,14 @@ import { Middleware, Post, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { verifyToken } from "../../helpers/jwt"; import { authHandler, bruteForceHandler, - validator + validator, } from "../../helpers/middleware"; import { approveLocation, @@ -30,7 +30,7 @@ import { sendPasswordReset, updatePassword, validateRefreshToken, - verifyEmail + verifyEmail, } from "../../rest/auth"; import { AuthOAuthController } from "./oauth"; import { addInvitationCredits } from "../../rest/user"; @@ -43,9 +43,7 @@ export class AuthController { @Middleware( validator( { - email: Joi.string() - .email() - .required(), + email: Joi.string().email().required(), name: Joi.string() .min(3) .regex(/^[a-zA-Z ]*$/) @@ -53,11 +51,9 @@ export class AuthController { countryCode: Joi.string().length(2), password: Joi.string().min(6), gender: Joi.string().length(1), - preferredLanguage: Joi.string() - .min(2) - .max(5), + preferredLanguage: Joi.string().min(2).max(5), timezone: Joi.string(), - invitedByUser: Joi.string().optional() + invitedByUser: Joi.string().optional(), }, "body" ) @@ -88,12 +84,8 @@ export class AuthController { @Middleware( validator( { - email: Joi.string() - .email() - .required(), - password: Joi.string() - .min(6) - .required() + email: Joi.string().email().required(), + password: Joi.string().min(6).required(), }, "body" ) @@ -107,9 +99,7 @@ export class AuthController { validator( { token: Joi.string().required(), - code: Joi.number() - .min(5) - .required() + code: Joi.number().min(5).required(), }, "body" ) @@ -125,7 +115,7 @@ export class AuthController { validator( { token: Joi.string().required(), - subject: Joi.string().required() + subject: Joi.string().required(), }, "body" ) @@ -163,9 +153,7 @@ export class AuthController { @Middleware( validator( { - email: Joi.string() - .email() - .required() + email: Joi.string().email().required(), }, "body" ) @@ -184,9 +172,7 @@ export class AuthController { joiValidate( { token: Joi.string().required(), - password: Joi.string() - .min(6) - .required() + password: Joi.string().min(6).required(), }, { token, password } ); diff --git a/src/controllers/auth/oauth.ts b/src/controllers/auth/oauth.ts index f9af08d06..1bdeb01d5 100644 --- a/src/controllers/auth/oauth.ts +++ b/src/controllers/auth/oauth.ts @@ -5,7 +5,7 @@ import { Request, RequestHandler, Response, - Wrapper + Wrapper, } from "@staart/server"; import { stringify } from "querystring"; import { BASE_URL, FRONTEND_URL } from "../../config"; @@ -17,7 +17,7 @@ import { github, google, microsoft, - salesforce + salesforce, } from "../../rest/oauth"; const OAuthRedirector = (action: RequestHandler) => ( @@ -30,7 +30,7 @@ const OAuthRedirector = (action: RequestHandler) => ( `${FRONTEND_URL}/errors/oauth?${stringify({ ...args[0].params, ...args[0].query, - error: error.toString().replace("Error: ", "") + error: error.toString().replace("Error: ", ""), })}` ); }); @@ -45,7 +45,7 @@ const OAuthRedirect = ( res, `${FRONTEND_URL}/auth/token?${stringify({ ...response, - subject: Tokens.LOGIN + subject: Tokens.LOGIN, })}` ); }; diff --git a/src/controllers/organization/api-keys.ts b/src/controllers/organization/api-keys.ts index 30898460d..9e3b66725 100644 --- a/src/controllers/organization/api-keys.ts +++ b/src/controllers/organization/api-keys.ts @@ -2,7 +2,7 @@ import { RESOURCE_CREATED, RESOURCE_DELETED, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ClassMiddleware, @@ -13,13 +13,13 @@ import { Patch, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { createApiKeyForUser, @@ -27,7 +27,7 @@ import { getOrganizationApiKeyForUser, getOrganizationApiKeyLogsForUser, getOrganizationApiKeysForUser, - updateApiKeyForUser + updateApiKeyForUser, } from "../../rest/organization"; @Controller(":id/api-keys") @@ -41,7 +41,7 @@ export class OrganizationApiKeysController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, apiKeyParams ); @@ -60,7 +60,7 @@ export class OrganizationApiKeysController { ipRestrictions: Joi.string(), referrerRestrictions: Joi.string(), name: Joi.string(), - description: Joi.string() + description: Joi.string(), }, "body" ) @@ -84,7 +84,7 @@ export class OrganizationApiKeysController { joiValidate( { id: Joi.string().required(), - apiKeyId: Joi.string().required() + apiKeyId: Joi.string().required(), }, { id, apiKeyId } ); @@ -99,7 +99,7 @@ export class OrganizationApiKeysController { ipRestrictions: Joi.string().allow(), referrerRestrictions: Joi.string().allow(), name: Joi.string().allow(), - description: Joi.string().allow() + description: Joi.string().allow(), }, "body" ) @@ -110,7 +110,7 @@ export class OrganizationApiKeysController { joiValidate( { id: Joi.string().required(), - apiKeyId: Joi.string().required() + apiKeyId: Joi.string().required(), }, { id, apiKeyId } ); @@ -131,7 +131,7 @@ export class OrganizationApiKeysController { joiValidate( { id: Joi.string().required(), - apiKeyId: Joi.string().required() + apiKeyId: Joi.string().required(), }, { id, apiKeyId } ); @@ -151,7 +151,7 @@ export class OrganizationApiKeysController { joiValidate( { id: Joi.string().required(), - apiKeyId: Joi.string().required() + apiKeyId: Joi.string().required(), }, { id, apiKeyId } ); diff --git a/src/controllers/organization/billing.ts b/src/controllers/organization/billing.ts index 8e30eaf4b..2592bbc03 100644 --- a/src/controllers/organization/billing.ts +++ b/src/controllers/organization/billing.ts @@ -4,18 +4,18 @@ import { Get, Patch, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { getOrganizationBillingForUser, getOrganizationPricingPlansForUser, - updateOrganizationBillingForUser + updateOrganizationBillingForUser, } from "../../rest/organization"; @Controller(":id") @@ -55,7 +55,7 @@ export class OrganizationBillingController { const organizationId = await organizationUsernameToId(req.params.id); joiValidate( { - organizationId: Joi.string().required() + organizationId: Joi.string().required(), }, { organizationId } ); diff --git a/src/controllers/organization/domains.ts b/src/controllers/organization/domains.ts index a793ab3da..799d60c73 100644 --- a/src/controllers/organization/domains.ts +++ b/src/controllers/organization/domains.ts @@ -3,7 +3,7 @@ import { RESOURCE_DELETED, RESOURCE_SUCCESS, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ClassMiddleware, @@ -15,13 +15,13 @@ import { Post, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { createDomainForUser, @@ -29,7 +29,7 @@ import { getOrganizationDomainForUser, getOrganizationDomainsForUser, updateDomainForUser, - verifyDomainForUser + verifyDomainForUser, } from "../../rest/organization"; @Controller(":id/domains") @@ -43,7 +43,7 @@ export class OrganizationDomainsController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, domainParams ); @@ -58,7 +58,7 @@ export class OrganizationDomainsController { @Middleware( validator( { - domain: Joi.string() + domain: Joi.string(), }, "body" ) @@ -82,7 +82,7 @@ export class OrganizationDomainsController { joiValidate( { id: Joi.string().required(), - domainId: Joi.string().required() + domainId: Joi.string().required(), }, { id, domainId } ); @@ -93,7 +93,7 @@ export class OrganizationDomainsController { @Middleware( validator( { - domain: Joi.string() + domain: Joi.string(), }, "body" ) @@ -104,7 +104,7 @@ export class OrganizationDomainsController { joiValidate( { id: Joi.string().required(), - domainId: Joi.string().required() + domainId: Joi.string().required(), }, { id, domainId } ); @@ -125,7 +125,7 @@ export class OrganizationDomainsController { joiValidate( { id: Joi.string().required(), - domainId: Joi.string().required() + domainId: Joi.string().required(), }, { id, domainId } ); @@ -147,9 +147,7 @@ export class OrganizationDomainsController { { id: Joi.string().required(), domainId: Joi.string().required(), - method: Joi.string() - .allow(["file", "dns"]) - .only() + method: Joi.string().allow(["file", "dns"]).only(), }, { id, domainId, method } ); diff --git a/src/controllers/organization/index.ts b/src/controllers/organization/index.ts index c032eb452..c1474b6b4 100644 --- a/src/controllers/organization/index.ts +++ b/src/controllers/organization/index.ts @@ -2,7 +2,7 @@ import { RESOURCE_CREATED, RESOURCE_DELETED, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ChildControllers, @@ -14,20 +14,20 @@ import { Patch, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { deleteOrganizationForUser, getAllOrganizationDataForUser, getOrganizationForUser, newOrganizationForUser, - updateOrganizationForUser + updateOrganizationForUser, } from "../../rest/organization"; import { OrganizationApiKeysController } from "./api-keys"; import { OrganizationBillingController } from "./billing"; @@ -49,7 +49,7 @@ import { OrganizationTransactionsController } from "./transactions"; new OrganizationSourcesController(), new OrganizationSubscriptionsController(), new OrganizationWebhooksController(), - new OrganizationTransactionsController() + new OrganizationTransactionsController(), ]) @ClassMiddleware(authHandler) export class OrganizationController { @@ -57,7 +57,7 @@ export class OrganizationController { @Middleware( validator( { - name: Joi.string().required() + name: Joi.string().required(), }, "body" ) @@ -88,7 +88,7 @@ export class OrganizationController { autoJoinDomain: Joi.boolean(), onlyAllowDomain: Joi.boolean(), ipRestrictions: Joi.string(), - profilePicture: Joi.string() + profilePicture: Joi.string(), }, "body" ) diff --git a/src/controllers/organization/invoices.ts b/src/controllers/organization/invoices.ts index 47c419824..532361bde 100644 --- a/src/controllers/organization/invoices.ts +++ b/src/controllers/organization/invoices.ts @@ -3,17 +3,17 @@ import { Controller, Get, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { getOrganizationInvoiceForUser, - getOrganizationInvoicesForUser + getOrganizationInvoicesForUser, } from "../../rest/organization"; @Controller(":id/invoices") @@ -33,7 +33,7 @@ export class OrganizationInvoicesController { billing: Joi.string().valid("charge_automatically", "send_invoice"), itemsPerPage: Joi.number(), plan: Joi.string(), - status: Joi.string() + status: Joi.string(), }, subscriptionParams ); @@ -51,7 +51,7 @@ export class OrganizationInvoicesController { joiValidate( { organizationId: Joi.string().required(), - invoiceId: Joi.string().required() + invoiceId: Joi.string().required(), }, { organizationId, invoiceId } ); diff --git a/src/controllers/organization/memberships.ts b/src/controllers/organization/memberships.ts index 5bafbffca..115b1a2cc 100644 --- a/src/controllers/organization/memberships.ts +++ b/src/controllers/organization/memberships.ts @@ -2,7 +2,7 @@ import { RESOURCE_CREATED, RESOURCE_DELETED, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ClassMiddleware, @@ -13,20 +13,20 @@ import { Patch, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { deleteOrganizationMembershipForUser, getOrganizationMembershipForUser, getOrganizationMembershipsForUser, inviteMemberToOrganization, - updateOrganizationMembershipForUser + updateOrganizationMembershipForUser, } from "../../rest/organization"; import { MembershipRole } from "@prisma/client"; @@ -56,19 +56,15 @@ export class OrganizationMembershipsController { joiValidate( { organizationId: Joi.string().required(), - newMemberName: Joi.string() - .min(6) - .required(), - newMemberEmail: Joi.string() - .email() - .required(), - role: Joi.number() + newMemberName: Joi.string().min(6).required(), + newMemberEmail: Joi.string().email().required(), + role: Joi.number(), }, { organizationId, newMemberName, newMemberEmail, - role + role, } ); await inviteMemberToOrganization( @@ -89,7 +85,7 @@ export class OrganizationMembershipsController { joiValidate( { organizationId: Joi.string().required(), - membershipId: Joi.string().required() + membershipId: Joi.string().required(), }, { organizationId, membershipId } ); @@ -104,9 +100,7 @@ export class OrganizationMembershipsController { @Middleware( validator( { - role: Joi.number() - .min(1) - .max(5) + role: Joi.number().min(1).max(5), }, "body" ) @@ -117,7 +111,7 @@ export class OrganizationMembershipsController { joiValidate( { organizationId: Joi.string().required(), - membershipId: Joi.string().required() + membershipId: Joi.string().required(), }, { organizationId, membershipId } ); @@ -137,7 +131,7 @@ export class OrganizationMembershipsController { joiValidate( { organizationId: Joi.string().required(), - membershipId: Joi.string().required() + membershipId: Joi.string().required(), }, { organizationId, membershipId } ); diff --git a/src/controllers/organization/sources.ts b/src/controllers/organization/sources.ts index cbc80d110..a89b44e28 100644 --- a/src/controllers/organization/sources.ts +++ b/src/controllers/organization/sources.ts @@ -2,7 +2,7 @@ import { RESOURCE_CREATED, RESOURCE_DELETED, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ClassMiddleware, @@ -12,20 +12,20 @@ import { Patch, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { createOrganizationSourceForUser, deleteOrganizationSourceForUser, getOrganizationSourceForUser, getOrganizationSourcesForUser, - updateOrganizationSourceForUser + updateOrganizationSourceForUser, } from "../../rest/organization"; @Controller(":id/sources") @@ -42,7 +42,7 @@ export class OrganizationSourcesController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, subscriptionParams ); @@ -76,7 +76,7 @@ export class OrganizationSourcesController { joiValidate( { organizationId: Joi.string().required(), - sourceId: Joi.string().required() + sourceId: Joi.string().required(), }, { organizationId, sourceId } ); @@ -94,7 +94,7 @@ export class OrganizationSourcesController { joiValidate( { organizationId: Joi.string().required(), - sourceId: Joi.string().required() + sourceId: Joi.string().required(), }, { organizationId, sourceId } ); @@ -115,7 +115,7 @@ export class OrganizationSourcesController { joiValidate( { organizationId: Joi.string().required(), - sourceId: Joi.string().required() + sourceId: Joi.string().required(), }, { organizationId, sourceId } ); diff --git a/src/controllers/organization/subscriptions.ts b/src/controllers/organization/subscriptions.ts index 4a38a6f36..6904e6144 100644 --- a/src/controllers/organization/subscriptions.ts +++ b/src/controllers/organization/subscriptions.ts @@ -6,19 +6,19 @@ import { Patch, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { createOrganizationSubscriptionForUser, getOrganizationSubscriptionForUser, getOrganizationSubscriptionsForUser, - updateOrganizationSubscriptionForUser + updateOrganizationSubscriptionForUser, } from "../../rest/organization"; @Controller(":id/subscriptions") @@ -38,7 +38,7 @@ export class OrganizationSubscriptionsController { billing: Joi.string().valid("charge_automatically", "send_invoice"), itemsPerPage: Joi.number(), plan: Joi.string(), - status: Joi.string() + status: Joi.string(), }, subscriptionParams ); @@ -62,7 +62,7 @@ export class OrganizationSubscriptionsController { plan: Joi.string().required(), billing: Joi.string().valid("charge_automatically", "send_invoice"), tax_percent: Joi.number(), - number_of_seats: Joi.number() + number_of_seats: Joi.number(), }, subscriptionParams ); @@ -82,7 +82,7 @@ export class OrganizationSubscriptionsController { joiValidate( { organizationId: Joi.string().required(), - subscriptionId: Joi.string().required() + subscriptionId: Joi.string().required(), }, { organizationId, subscriptionId } ); @@ -101,7 +101,7 @@ export class OrganizationSubscriptionsController { joiValidate( { organizationId: Joi.string().required(), - subscriptionId: Joi.string().required() + subscriptionId: Joi.string().required(), }, { organizationId, subscriptionId } ); @@ -110,7 +110,7 @@ export class OrganizationSubscriptionsController { billing: Joi.string().valid("charge_automatically", "send_invoice"), cancel_at_period_end: Joi.boolean(), coupon: Joi.string(), - default_source: Joi.string() + default_source: Joi.string(), }, data ); diff --git a/src/controllers/organization/transactions.ts b/src/controllers/organization/transactions.ts index 365417873..ffbfc397c 100644 --- a/src/controllers/organization/transactions.ts +++ b/src/controllers/organization/transactions.ts @@ -4,18 +4,18 @@ import { Get, Request, Response, - Put + Put, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { getOrganizationTransactionForUser, getOrganizationTransactionsForUser, - applyCouponToOrganizationForUser + applyCouponToOrganizationForUser, } from "../../rest/organization"; @Controller(":id/transactions") @@ -32,7 +32,7 @@ export class OrganizationTransactionsController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, transactionParams ); @@ -50,7 +50,7 @@ export class OrganizationTransactionsController { joiValidate( { organizationId: Joi.string().required(), - couponCode: Joi.string().required() + couponCode: Joi.string().required(), }, { organizationId, couponCode } ); @@ -68,7 +68,7 @@ export class OrganizationTransactionsController { joiValidate( { organizationId: Joi.string().required(), - transactionId: Joi.string().required() + transactionId: Joi.string().required(), }, { organizationId, transactionId } ); diff --git a/src/controllers/organization/webhooks.ts b/src/controllers/organization/webhooks.ts index a43b8203e..f80c563da 100644 --- a/src/controllers/organization/webhooks.ts +++ b/src/controllers/organization/webhooks.ts @@ -2,7 +2,7 @@ import { RESOURCE_CREATED, RESOURCE_DELETED, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ClassMiddleware, @@ -13,20 +13,20 @@ import { Patch, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; import { localsToTokenOrKey, - organizationUsernameToId + organizationUsernameToId, } from "../../helpers/utils"; import { createWebhookForUser, deleteWebhookForUser, getOrganizationWebhookForUser, getOrganizationWebhooksForUser, - updateWebhookForUser + updateWebhookForUser, } from "../../rest/organization"; @Controller(":id/webhooks") @@ -40,7 +40,7 @@ export class OrganizationWebhooksController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, webhookParams ); @@ -59,7 +59,7 @@ export class OrganizationWebhooksController { url: Joi.string().required(), contentType: Joi.string(), secret: Joi.string().allow(), - isActive: Joi.boolean() + isActive: Joi.boolean(), }, "body" ) @@ -83,7 +83,7 @@ export class OrganizationWebhooksController { joiValidate( { id: Joi.string().required(), - webhookId: Joi.string().required() + webhookId: Joi.string().required(), }, { id, webhookId } ); @@ -102,7 +102,7 @@ export class OrganizationWebhooksController { url: Joi.string(), contentType: Joi.string(), secret: Joi.string(), - isActive: Joi.boolean() + isActive: Joi.boolean(), }, "body" ) @@ -113,7 +113,7 @@ export class OrganizationWebhooksController { joiValidate( { id: Joi.string().required(), - webhookId: Joi.string().required() + webhookId: Joi.string().required(), }, { id, webhookId } ); @@ -134,7 +134,7 @@ export class OrganizationWebhooksController { joiValidate( { id: Joi.string().required(), - webhookId: Joi.string().required() + webhookId: Joi.string().required(), }, { id, webhookId } ); diff --git a/src/controllers/user/access-tokens.ts b/src/controllers/user/access-tokens.ts index ad07c00f1..6a5c10275 100644 --- a/src/controllers/user/access-tokens.ts +++ b/src/controllers/user/access-tokens.ts @@ -2,7 +2,7 @@ import { RESOURCE_CREATED, RESOURCE_DELETED, RESOURCE_UPDATED, - respond + respond, } from "@staart/messages"; import { ClassMiddleware, @@ -13,7 +13,7 @@ import { Patch, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; @@ -23,7 +23,7 @@ import { deleteAccessTokenForUser, getUserAccessTokenForUser, getUserAccessTokensForUser, - updateAccessTokenForUser + updateAccessTokenForUser, } from "../../rest/user"; @Controller(":id/access-tokens") @@ -37,7 +37,7 @@ export class UserAccessTokensController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, accessTokenParams ); @@ -54,7 +54,7 @@ export class UserAccessTokensController { { scopes: Joi.string(), name: Joi.string(), - description: Joi.string() + description: Joi.string(), }, "body" ) @@ -78,7 +78,7 @@ export class UserAccessTokensController { joiValidate( { id: Joi.string().required(), - accessTokenId: Joi.string().required() + accessTokenId: Joi.string().required(), }, { id, accessTokenId } ); @@ -91,7 +91,7 @@ export class UserAccessTokensController { { scopes: Joi.string().allow(), name: Joi.string().allow(), - description: Joi.string().allow() + description: Joi.string().allow(), }, "body" ) @@ -102,7 +102,7 @@ export class UserAccessTokensController { joiValidate( { id: Joi.string().required(), - accessTokenId: Joi.string().required() + accessTokenId: Joi.string().required(), }, { id, accessTokenId } ); @@ -123,7 +123,7 @@ export class UserAccessTokensController { joiValidate( { id: Joi.string().required(), - accessTokenId: Joi.string().required() + accessTokenId: Joi.string().required(), }, { id, accessTokenId } ); diff --git a/src/controllers/user/emails.ts b/src/controllers/user/emails.ts index cff74f264..c1b28b70f 100644 --- a/src/controllers/user/emails.ts +++ b/src/controllers/user/emails.ts @@ -2,7 +2,7 @@ import { RESOURCE_CREATED, RESOURCE_DELETED, RESOURCE_SUCCESS, - respond + respond, } from "@staart/messages"; import { ClassMiddleware, @@ -12,7 +12,7 @@ import { Post, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; @@ -22,7 +22,7 @@ import { addEmailToUserForUser, getEmailForUser, resendEmailVerificationForUser, - deleteEmailFromUserForUser + deleteEmailFromUserForUser, } from "../../rest/user"; @Controller(":id/emails") @@ -42,9 +42,7 @@ export class UserEmailsController { joiValidate( { id: Joi.string().required(), - email: Joi.string() - .email() - .required() + email: Joi.string().email().required(), }, { id, email } ); @@ -59,7 +57,7 @@ export class UserEmailsController { joiValidate( { id: Joi.string().required(), - emailId: Joi.string().required() + emailId: Joi.string().required(), }, { id, emailId } ); @@ -73,7 +71,7 @@ export class UserEmailsController { joiValidate( { id: Joi.string().required(), - emailId: Joi.string().required() + emailId: Joi.string().required(), }, { id, emailId } ); @@ -88,7 +86,7 @@ export class UserEmailsController { joiValidate( { id: Joi.string().required(), - emailId: Joi.string().required() + emailId: Joi.string().required(), }, { id, emailId } ); diff --git a/src/controllers/user/identities.ts b/src/controllers/user/identities.ts index 7c42da54a..caf01dbfa 100644 --- a/src/controllers/user/identities.ts +++ b/src/controllers/user/identities.ts @@ -7,7 +7,7 @@ import { Post, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; @@ -17,7 +17,7 @@ import { createUserIdentityForUser, deleteIdentityForUser, getUserIdentitiesForUser, - getUserIdentityForUser + getUserIdentityForUser, } from "../../rest/user"; @Controller(":id/identities") @@ -31,7 +31,7 @@ export class UserIdentitiesController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, identityParams ); @@ -66,7 +66,7 @@ export class UserIdentitiesController { joiValidate( { id: Joi.string().required(), - identityId: Joi.string().required() + identityId: Joi.string().required(), }, { id, identityId } ); @@ -80,7 +80,7 @@ export class UserIdentitiesController { joiValidate( { id: Joi.string().required(), - identityId: Joi.string().required() + identityId: Joi.string().required(), }, { id, identityId } ); diff --git a/src/controllers/user/index.ts b/src/controllers/user/index.ts index 6a1fae9b5..946a03fa6 100644 --- a/src/controllers/user/index.ts +++ b/src/controllers/user/index.ts @@ -8,7 +8,7 @@ import { Middleware, Patch, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; @@ -16,7 +16,7 @@ import { userUsernameToId } from "../../helpers/utils"; import { deleteUserForUser, getUserFromId, - updateUserForUser + updateUserForUser, } from "../../rest/user"; import { UserAccessTokensController } from "./access-tokens"; import { UserEmailsController } from "./emails"; @@ -32,7 +32,7 @@ import { UserSessionsController } from "./sessions"; new UserSecurityController(), new UserAccessTokensController(), new UserSessionsController(), - new UserIdentitiesController() + new UserIdentitiesController(), ]) @ClassMiddleware(authHandler) export class UserController { @@ -56,15 +56,13 @@ export class UserController { countryCode: Joi.string().length(2), password: Joi.string().min(6), gender: Joi.string().length(1), - preferredLanguage: Joi.string() - .min(2) - .max(5), + preferredLanguage: Joi.string().min(2).max(5), timezone: Joi.string(), notificationEmails: Joi.number(), prefersReducedMotion: Joi.boolean(), prefersColorSchemeDark: Joi.boolean(), profilePicture: Joi.string(), - checkLocationOnLogin: Joi.boolean() + checkLocationOnLogin: Joi.boolean(), }, "body" ) diff --git a/src/controllers/user/memberships.ts b/src/controllers/user/memberships.ts index fec4a7a7c..d676887bf 100644 --- a/src/controllers/user/memberships.ts +++ b/src/controllers/user/memberships.ts @@ -6,7 +6,7 @@ import { Get, Patch, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; @@ -15,7 +15,7 @@ import { getMembershipsForUser, getMembershipDetailsForUser, deleteMembershipForUser, - updateMembershipForUser + updateMembershipForUser, } from "../../rest/user"; @Controller(":id/memberships") @@ -35,7 +35,7 @@ export class UserMembershipsController { joiValidate( { id: Joi.string().required(), - membershipId: Joi.string().required() + membershipId: Joi.string().required(), }, { id, membershipId } ); @@ -49,7 +49,7 @@ export class UserMembershipsController { joiValidate( { id: Joi.string().required(), - membershipId: Joi.string().required() + membershipId: Joi.string().required(), }, { id, membershipId } ); @@ -64,7 +64,7 @@ export class UserMembershipsController { joiValidate( { id: Joi.string().required(), - membershipId: Joi.string().required() + membershipId: Joi.string().required(), }, { id, membershipId } ); diff --git a/src/controllers/user/security.ts b/src/controllers/user/security.ts index fc1fe9af3..2534bf00c 100644 --- a/src/controllers/user/security.ts +++ b/src/controllers/user/security.ts @@ -8,7 +8,7 @@ import { Post, Put, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler, validator } from "../../helpers/middleware"; @@ -20,7 +20,7 @@ import { getBackupCodesForUser, regenerateBackupCodesForUser, updatePasswordForUser, - verify2FAForUser + verify2FAForUser, } from "../../rest/user"; @Controller(":id") @@ -30,12 +30,8 @@ export class UserSecurityController { @Middleware( validator( { - oldPassword: Joi.string() - .min(6) - .required(), - newPassword: Joi.string() - .min(6) - .required() + oldPassword: Joi.string().min(6).required(), + newPassword: Joi.string().min(6).required(), }, "body" ) @@ -46,7 +42,7 @@ export class UserSecurityController { const newPassword = req.body.newPassword; joiValidate( { - id: Joi.string().required() + id: Joi.string().required(), }, { id } ); @@ -81,9 +77,7 @@ export class UserSecurityController { joiValidate( { id: Joi.string().required(), - code: Joi.number() - .min(5) - .required() + code: Joi.number().min(5).required(), }, { id, code } ); diff --git a/src/controllers/user/sessions.ts b/src/controllers/user/sessions.ts index 7391d737e..cb03d524c 100644 --- a/src/controllers/user/sessions.ts +++ b/src/controllers/user/sessions.ts @@ -5,7 +5,7 @@ import { Delete, Get, Request, - Response + Response, } from "@staart/server"; import { Joi, joiValidate } from "@staart/validate"; import { authHandler } from "../../helpers/middleware"; @@ -13,7 +13,7 @@ import { userUsernameToId } from "../../helpers/utils"; import { deleteSessionForUser, getUserSessionForUser, - getUserSessionsForUser + getUserSessionsForUser, } from "../../rest/user"; @Controller(":id/sessions") @@ -27,7 +27,7 @@ export class UserSessionsController { joiValidate( { start: Joi.string(), - itemsPerPage: Joi.number() + itemsPerPage: Joi.number(), }, sessionParams ); @@ -41,7 +41,7 @@ export class UserSessionsController { joiValidate( { id: Joi.string().required(), - sessionId: Joi.string().required() + sessionId: Joi.string().required(), }, { id, sessionId } ); @@ -55,7 +55,7 @@ export class UserSessionsController { joiValidate( { id: Joi.string().required(), - sessionId: Joi.string().required() + sessionId: Joi.string().required(), }, { id, sessionId } ); diff --git a/src/crons/hourly.ts b/src/crons/hourly.ts index 5b915c867..eca862f5f 100644 --- a/src/crons/hourly.ts +++ b/src/crons/hourly.ts @@ -18,8 +18,8 @@ const deleteExpiredSessions = async () => { await prisma.sessions.deleteMany({ where: { createdAt: { - lte: new Date(new Date().getTime() - ms(TOKEN_EXPIRY_REFRESH)) - } - } + lte: new Date(new Date().getTime() - ms(TOKEN_EXPIRY_REFRESH)), + }, + }, }); }; diff --git a/src/helpers/__tests__/utils.ts b/src/helpers/__tests__/utils.ts index 526f5fce6..95e38741f 100644 --- a/src/helpers/__tests__/utils.ts +++ b/src/helpers/__tests__/utils.ts @@ -5,7 +5,7 @@ test("Remove sensitive info", () => { deleteSensitiveInfoUser({ id: "wiuhoeijpaoe", name: "Anand Chowdhary", - password: "1abc9c" + password: "1abc9c", }).password ).toBeUndefined(); }); diff --git a/src/helpers/authorization.ts b/src/helpers/authorization.ts index 46464dd6e..76fce0ed9 100644 --- a/src/helpers/authorization.ts +++ b/src/helpers/authorization.ts @@ -1,7 +1,7 @@ import { ORGANIZATION_NOT_FOUND, USER_NOT_FOUND, - INVALID_TOKEN + INVALID_TOKEN, } from "@staart/errors"; import { OrgScopes, Tokens, UserScopes, SudoScopes } from "../interfaces/enum"; import { ApiKeyResponse, AccessTokenResponse } from "./jwt"; @@ -10,7 +10,7 @@ import { organizations, memberships, access_tokens, - api_keys + api_keys, } from "@prisma/client"; import { prisma } from "./prisma"; @@ -25,23 +25,23 @@ const canUserUser = async (user: users, action: UserScopes, target: users) => { if (user.id === target.id) return true; const userMemberships = await prisma.memberships.findMany({ - where: { user: user } + where: { user: user }, }); const targetMemberships = await prisma.memberships.findMany({ - where: { user: target } + where: { user: target }, }); let allowed = false; const similarMemberships: Array = []; userMemberships.forEach((userMembership, index) => { - targetMemberships.forEach(targetMembership => { + targetMemberships.forEach((targetMembership) => { if (userMembership.id && userMembership.id === targetMembership.id) similarMemberships.push(index); }); }); - similarMemberships.forEach(similarMembership => { + similarMemberships.forEach((similarMembership) => { // A user can read another user in the same organization, as long as they're not a basic member if (action === UserScopes.READ_USER) if (userMemberships[similarMembership].role) allowed = true; @@ -80,11 +80,11 @@ const canUserOrganization = async ( const memberships = await prisma.memberships.findMany({ where: { user } }); const targetMemberships = memberships.filter( - m => m.organizationId === target.id + (m) => m.organizationId === target.id ); let allowed = false; - targetMemberships.forEach(membership => { + targetMemberships.forEach((membership) => { // An organization owner can do anything if (membership.role === "OWNER") allowed = true; @@ -125,7 +125,7 @@ const canUserMembership = async ( const memberships = await prisma.memberships.findMany({ where: { user } }); let allowed = false; - memberships.forEach(membership => { + memberships.forEach((membership) => { // An admin, owner, or reseller can edit if ( membership.organizationId === target.organizationId && @@ -199,7 +199,7 @@ export const can = async ( } } else { const result = await prisma.users.findOne({ - where: { id: parseInt(user) } + where: { id: parseInt(user) }, }); if (!result) throw new Error(USER_NOT_FOUND); user = result; @@ -213,20 +213,20 @@ export const can = async ( if (typeof target === "string") { if (targetType === "membership") { const membership = await prisma.memberships.findOne({ - where: { id: parseInt(target) } + where: { id: parseInt(target) }, }); if (!membership) throw new Error(USER_NOT_FOUND); target = membership; } else if (targetType === "organization") { const organization = await prisma.organizations.findOne({ - where: { id: parseInt(target) } + where: { id: parseInt(target) }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); target = organization; } else { // Target is a user const user = await prisma.users.findOne({ - where: { id: parseInt(target) } + where: { id: parseInt(target) }, }); if (!user) throw new Error(USER_NOT_FOUND); target = user; @@ -235,7 +235,7 @@ export const can = async ( if (requestFromType === "api_keys") { const apiKeyDetails = await prisma.api_keys.findOne({ - where: { id: parseInt((user as ApiKeyResponse).id) } + where: { id: parseInt((user as ApiKeyResponse).id) }, }); if (!apiKeyDetails || !target) throw new Error(INVALID_TOKEN); return canApiKeyOrganization( @@ -245,7 +245,7 @@ export const can = async ( ); } else if (requestFromType === "access_tokens") { const accessTokenDetails = await prisma.access_tokens.findOne({ - where: { id: parseInt((user as ApiKeyResponse).id) } + where: { id: parseInt((user as ApiKeyResponse).id) }, }); if (!accessTokenDetails || !target) throw new Error(INVALID_TOKEN); return canAccessTokenUser( diff --git a/src/helpers/jwt.ts b/src/helpers/jwt.ts index b25235aa9..6f1fdb640 100644 --- a/src/helpers/jwt.ts +++ b/src/helpers/jwt.ts @@ -4,7 +4,7 @@ import { REVOKED_TOKEN, UNAPPROVED_LOCATION, UNVERIFIED_EMAIL, - USER_NOT_FOUND + USER_NOT_FOUND, } from "@staart/errors"; import redis from "@staart/redis"; import { ipRangeCheck, randomString } from "@staart/text"; @@ -17,7 +17,7 @@ import { TOKEN_EXPIRY_EMAIL_VERIFICATION, TOKEN_EXPIRY_LOGIN, TOKEN_EXPIRY_PASSWORD_RESET, - TOKEN_EXPIRY_REFRESH + TOKEN_EXPIRY_REFRESH, } from "../config"; import { EventType, Templates, Tokens } from "../interfaces/enum"; import { Locals } from "../interfaces/general"; @@ -26,20 +26,20 @@ import { mail } from "./mail"; import { deleteSensitiveInfoUser, includesDomainInCommaList, - removeFalsyValues + removeFalsyValues, } from "./utils"; import { access_tokensCreateInput, access_tokensUpdateInput, users, api_keysCreateInput, - api_keysUpdateInput + api_keysUpdateInput, } from "@prisma/client"; import { prisma } from "./prisma"; import { updateSessionByJwt, checkApprovedLocation, - getUserPrimaryEmail + getUserPrimaryEmail, } from "../services/user.service"; /** @@ -59,7 +59,7 @@ export const generateToken = ( expiresIn, subject, issuer: JWT_ISSUER, - jwtid: randomString({ length: 12 }) + jwtid: randomString({ length: 12 }), }, (error, token) => { if (error) return reject(error); @@ -214,18 +214,18 @@ export const postLoginTokens = async ( jwtToken, ipAddress: locals.ipAddress || "unknown-ip-address", userAgent: locals.userAgent || "unknown-user-agent", - user: { connect: { id: user.id } } - } + user: { connect: { id: user.id } }, + }, }); } else { await updateSessionByJwt(user.id, refreshTokenString, {}); } return { token: await loginToken({ - ...deleteSensitiveInfoUser(user) + ...deleteSensitiveInfoUser(user), // email: (await getUserBestEmail(user.id)).email }), - refresh: !refreshTokenString ? refresh : undefined + refresh: !refreshTokenString ? refresh : undefined, }; }; @@ -246,7 +246,7 @@ export const getLoginResponse = async ( ): Promise => { if (!user.id) throw new Error(USER_NOT_FOUND); const verifiedEmails = await prisma.emails.findMany({ - where: { userId: user.id, isVerified: true } + where: { userId: user.id, isVerified: true }, }); if (!verifiedEmails.length) throw new Error(UNVERIFIED_EMAIL); if (locals) { @@ -260,7 +260,7 @@ export const getLoginResponse = async ( location: location ? location.city || location.region_name || location.country_code : "Unknown location", - token: await approveLocationToken(user.id, locals.ipAddress) + token: await approveLocationToken(user.id, locals.ipAddress), } ); throw new Error(UNAPPROVED_LOCATION); @@ -268,7 +268,7 @@ export const getLoginResponse = async ( } if (user.twoFactorEnabled) return { - twoFactorToken: await twoFactorToken(user) + twoFactorToken: await twoFactorToken(user), }; return postLoginTokens(user, locals); }; @@ -302,7 +302,7 @@ export const invalidateToken = async (token: string) => { "1", details.exp && [ "EX", - Math.floor((details.exp - new Date().getTime()) / 1000) + Math.floor((details.exp - new Date().getTime()) / 1000), ] ); }; @@ -312,7 +312,7 @@ export const checkIpRestrictions = (apiKey: ApiKeyResponse, locals: Locals) => { if ( !ipRangeCheck( locals.ipAddress, - apiKey.ipRestrictions.split(",").map(range => range.trim()) + apiKey.ipRestrictions.split(",").map((range) => range.trim()) ) ) throw new Error(IP_RANGE_CHECK_FAIL); diff --git a/src/helpers/location.ts b/src/helpers/location.ts index 768930c9a..8ada8cd8a 100644 --- a/src/helpers/location.ts +++ b/src/helpers/location.ts @@ -17,7 +17,7 @@ export interface GeoLocation { let lookup: Reader | undefined = undefined; const getLookup = async () => { if (lookup) return lookup; - lookup = await geolite2.open("GeoLite2-City", path => { + lookup = await geolite2.open("GeoLite2-City", (path) => { return maxmind.open(path); }); success("Opened GeoIP2 database reader"); diff --git a/src/helpers/mail.ts b/src/helpers/mail.ts index 051abc55e..d8671d4a9 100644 --- a/src/helpers/mail.ts +++ b/src/helpers/mail.ts @@ -20,14 +20,14 @@ const setupQueue = async () => { export const receiveEmailMessage = async () => { await setupQueue(); const result = await redisQueue.receiveMessageAsync({ - qname: MAIL_QUEUE + qname: MAIL_QUEUE, }); if ("id" in result) { const { to, template, data, - tryNumber + tryNumber, }: { to: string; template: string; @@ -38,7 +38,7 @@ export const receiveEmailMessage = async () => { logError("Email", `Unable to send email: ${to}`); return redisQueue.deleteMessageAsync({ qname: MAIL_QUEUE, - id: result.id + id: result.id, }); } try { @@ -50,13 +50,13 @@ export const receiveEmailMessage = async () => { to, template, data, - tryNumber: tryNumber + 1 - }) + tryNumber: tryNumber + 1, + }), }); } await redisQueue.deleteMessageAsync({ qname: MAIL_QUEUE, - id: result.id + id: result.id, }); receiveEmailMessage(); } @@ -69,7 +69,7 @@ export const mail = async (to: string, template: string, data: any = {}) => { await setupQueue(); await redisQueue.sendMessageAsync({ qname: MAIL_QUEUE, - message: JSON.stringify({ to, template, data, tryNumber: 1 }) + message: JSON.stringify({ to, template, data, tryNumber: 1 }), }); }; @@ -88,6 +88,6 @@ const safeSendEmail = async (to: string, template: string, data: any = {}) => { to: to.toString(), subject: result[1].split("\n", 1)[0].replace(/<\/?[^>]+(>|$)/g, ""), message, - altText + altText, }); }; diff --git a/src/helpers/middleware.ts b/src/helpers/middleware.ts index e7ddde1ae..e4f2a93cf 100644 --- a/src/helpers/middleware.ts +++ b/src/helpers/middleware.ts @@ -1,7 +1,7 @@ import { INVALID_SIGNATURE, MISSING_SIGNATURE, - MISSING_TOKEN + MISSING_TOKEN, } from "@staart/errors"; import { constructWebhookEvent } from "@staart/payments"; import { @@ -9,7 +9,7 @@ import { RateLimit, Request, Response, - slowDown + slowDown, } from "@staart/server"; import { RawRequest } from "@staart/server"; import { ms } from "@staart/text"; @@ -26,7 +26,7 @@ import { RATE_LIMIT_TIME, SPEED_LIMIT_COUNT, SPEED_LIMIT_DELAY, - SPEED_LIMIT_TIME + SPEED_LIMIT_TIME, } from "../config"; import { Tokens } from "../interfaces/enum"; import { StripeLocals } from "../interfaces/general"; @@ -38,7 +38,7 @@ import { checkIpRestrictions, checkReferrerRestrictions, TokenResponse, - verifyToken + verifyToken, } from "./jwt"; import { trackUrl } from "./tracking"; import { includesDomainInCommaList } from "./utils"; @@ -46,20 +46,20 @@ import { includesDomainInCommaList } from "./utils"; const bruteForce = slowDown({ windowMs: BRUTE_FORCE_TIME, delayAfter: BRUTE_FORCE_COUNT, - delayMs: BRUTE_FORCE_DELAY + delayMs: BRUTE_FORCE_DELAY, }); const rateLimiter = RateLimit({ windowMs: RATE_LIMIT_TIME, - max: RATE_LIMIT_MAX + max: RATE_LIMIT_MAX, }); const publicRateLimiter = RateLimit({ windowMs: PUBLIC_RATE_LIMIT_TIME, - max: PUBLIC_RATE_LIMIT_MAX + max: PUBLIC_RATE_LIMIT_MAX, }); const speedLimiter = slowDown({ windowMs: SPEED_LIMIT_TIME, delayAfter: SPEED_LIMIT_COUNT, - delayMs: SPEED_LIMIT_DELAY + delayMs: SPEED_LIMIT_DELAY, }); /** diff --git a/src/helpers/tracking.ts b/src/helpers/tracking.ts index c08a23a61..97f8d310a 100644 --- a/src/helpers/tracking.ts +++ b/src/helpers/tracking.ts @@ -38,7 +38,7 @@ export const trackUrl = async (req: Request, res: Response) => { headers: req.headers, url: req.url, ipCountry: (req.get("cf-ipcountry") || "").toLowerCase(), - ...res.locals + ...res.locals, }; if (trackingObject.apiKey) { try { @@ -54,7 +54,7 @@ export const trackUrl = async (req: Request, res: Response) => { return; } } - Object.keys(trackingObject).forEach(key => { + Object.keys(trackingObject).forEach((key) => { if ( typeof trackingObject[key] === "object" && !Array.isArray(trackingObject[key]) && diff --git a/src/helpers/webhooks.ts b/src/helpers/webhooks.ts index 5c28bda4f..3dc7516b6 100644 --- a/src/helpers/webhooks.ts +++ b/src/helpers/webhooks.ts @@ -27,7 +27,12 @@ export const queueWebhook = ( .then(() => redisQueue.sendMessageAsync({ qname: WEBHOOK_QUEUE, - message: JSON.stringify({ organizationId, webhook, data, tryNumber: 1 }) + message: JSON.stringify({ + organizationId, + webhook, + data, + tryNumber: 1, + }), }) ) .then(() => {}) @@ -37,14 +42,14 @@ export const queueWebhook = ( export const receiveWebhookMessage = async () => { await setupQueue(); const result = await redisQueue.receiveMessageAsync({ - qname: WEBHOOK_QUEUE + qname: WEBHOOK_QUEUE, }); if ("id" in result) { const { organizationId, webhook, data, - tryNumber + tryNumber, }: { tryNumber: number; organizationId: string; @@ -55,7 +60,7 @@ export const receiveWebhookMessage = async () => { logError("Webhook", `Unable to fire: ${organizationId} ${webhook}`); return redisQueue.deleteMessageAsync({ qname: WEBHOOK_QUEUE, - id: result.id + id: result.id, }); } try { @@ -67,13 +72,13 @@ export const receiveWebhookMessage = async () => { organizationId, webhook, data, - tryNumber: tryNumber + 1 - }) + tryNumber: tryNumber + 1, + }), }); } await redisQueue.deleteMessageAsync({ qname: WEBHOOK_QUEUE, - id: result.id + id: result.id, }); receiveWebhookMessage(); } @@ -85,7 +90,7 @@ const safeFireWebhook = async ( data?: any ) => { const webhooksToFire = await prisma.webhooks.findMany({ - where: { organizationId: parseInt(organizationId), event: webhook } + where: { organizationId: parseInt(organizationId), event: webhook }, }); for await (const hook of webhooksToFire) { try { @@ -109,18 +114,18 @@ export const fireSingleWebhook = async ( headers: { "User-Agent": `${JWT_ISSUER}-webhook-service`, "X-Signature": secret, - "Content-Type": webhook.contentType + "Content-Type": webhook.contentType, }, data: { hookType, - data - } + data, + }, }; const result = await axios.post(webhook.url, options); if (webhook.id) await prisma.webhooks.update({ where: { id: webhook.id }, - data: { lastFiredAt: new Date() } + data: { lastFiredAt: new Date() }, }); return result; }; diff --git a/src/interfaces/enum.ts b/src/interfaces/enum.ts index 0eadba582..544b96bda 100644 --- a/src/interfaces/enum.ts +++ b/src/interfaces/enum.ts @@ -23,7 +23,7 @@ export enum EventType { BILLING_UPDATED = "billing.updated", API_KEY_CREATED = "apiKey.created", API_KEY_UPDATED = "apiKey.updated", - API_KEY_DELETED = "apiKey.deleted" + API_KEY_DELETED = "apiKey.deleted", } export enum Templates { @@ -33,7 +33,7 @@ export enum Templates { INVITED_TO_TEAM = "invited", UNAPPROVED_LOCATION = "unapproved-location", CREDITS_NEW_USER = "credits-new-user", - CREDITS_INVITED_BY = "credits-invited-by" + CREDITS_INVITED_BY = "credits-invited-by", } export enum Tokens { @@ -45,7 +45,7 @@ export enum Tokens { PASSWORD_RESET = "password-reset", EMAIL_VERIFY = "email-verify", APPROVE_LOCATION = "approve-location", - COUPON = "coupon" + COUPON = "coupon", } export enum OrgScopes { @@ -84,11 +84,11 @@ export enum OrgScopes { READ_ORG_TRANSACTIONS = "org:transactions:read", UPDATE_ORG_TRANSACTIONS = "org:transactions:update", DELETE_ORG_TRANSACTIONS = "org:transactions:delete", - CREATE_ORG_TRANSACTIONS = "org:transactions:create" + CREATE_ORG_TRANSACTIONS = "org:transactions:create", } export enum SudoScopes { - READ = "read" + READ = "read", } export enum UserScopes { @@ -117,7 +117,7 @@ export enum UserScopes { DELETE_USER_SESSION = "user:sessions:delete", CREATE_USER_IDENTITY = "user:identities:create", READ_USER_IDENTITY = "user:identities:read", - DELETE_USER_IDENTITY = "user:identities:delete" + DELETE_USER_IDENTITY = "user:identities:delete", } export enum Webhooks { @@ -140,5 +140,5 @@ export enum Webhooks { TEST_WEBHOOK = "test-webhook", UPDATE_WEBHOOK = "update-webhook", CREATE_WEBHOOK = "create-webhook", - DELETE_WEBHOOK = "delete-webhook" + DELETE_WEBHOOK = "delete-webhook", } diff --git a/src/rest/oauth.ts b/src/rest/oauth.ts index 4cf02feed..358000080 100644 --- a/src/rest/oauth.ts +++ b/src/rest/oauth.ts @@ -12,7 +12,7 @@ import { MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, SALESFORCE_CLIENT_ID, - SALESFORCE_CLIENT_SECRET + SALESFORCE_CLIENT_SECRET, } from "../config"; import { getLoginResponse } from "../helpers/jwt"; import { EventType } from "../interfaces/enum"; @@ -32,7 +32,7 @@ export const loginWithOAuth2Service = async ( if (!name) throw new Error(OAUTH_NO_NAME); if (!email) throw new Error(OAUTH_NO_EMAIL); const allUsers = await prisma.users.findMany({ - where: { emails: { some: { email } } } + where: { emails: { some: { email } } }, }); if (allUsers.length) return getLoginResponse( @@ -50,7 +50,7 @@ export const loginWithOAuth2Service = async ( true ); const loggedInUser = await prisma.users.findOne({ - where: { id: newUser.userId } + where: { id: newUser.userId }, }); if (!loggedInUser) throw new Error(USER_NOT_FOUND); return getLoginResponse( @@ -68,20 +68,20 @@ export const salesforce = { redirectUri: getRedirectUri("salesforce"), authorizationUri: "https://login.salesforce.com/services/oauth2/authorize", accessTokenUri: "https://login.salesforce.com/services/oauth2/token", - scopes: ["id"] + scopes: ["id"], }), callback: async (url: string, locals: Locals) => { const token = (await salesforce.client.code.getToken(url)).accessToken; const data = ( await axios.get("https://login.salesforce.com/services/oauth2/userinfo", { headers: { - Authorization: `Bearer ${token}` - } + Authorization: `Bearer ${token}`, + }, }) ).data; if (!data.email_verified) throw new Error(OAUTH_NO_EMAIL); return loginWithOAuth2Service("salesforce", data.name, data.email, locals); - } + }, }; export const github = { client: new ClientOAuth2({ @@ -90,19 +90,19 @@ export const github = { redirectUri: getRedirectUri("github"), authorizationUri: "https://github.com/login/oauth/authorize", accessTokenUri: "https://github.com/login/oauth/access_token", - scopes: ["read:user", "user:email"] + scopes: ["read:user", "user:email"], }), callback: async (url: string, locals: Locals) => { const token = (await github.client.code.getToken(url)).accessToken; const data = ( await axios.get("https://api.github.com/user", { headers: { - Authorization: `token ${token}` - } + Authorization: `token ${token}`, + }, }) ).data; return loginWithOAuth2Service("github", data.name, data.email, locals); - } + }, }; export const facebook = { client: new ClientOAuth2({ @@ -111,7 +111,7 @@ export const facebook = { redirectUri: getRedirectUri("facebook"), authorizationUri: "https://www.facebook.com/v3.3/dialog/oauth", accessTokenUri: "https://graph.facebook.com/v3.3/oauth/access_token", - scopes: ["email"] + scopes: ["email"], }), callback: async (url: string, locals: Locals) => { const token = (await facebook.client.code.getToken(url)).accessToken; @@ -121,7 +121,7 @@ export const facebook = { ) ).data; return loginWithOAuth2Service("facebook", data.name, data.email, locals); - } + }, }; export const google = { client: new ClientOAuth2({ @@ -130,7 +130,7 @@ export const google = { redirectUri: getRedirectUri("google"), authorizationUri: "https://accounts.google.com/o/oauth2/v2/auth", accessTokenUri: "https://www.googleapis.com/oauth2/v4/token", - scopes: ["https://www.googleapis.com/auth/userinfo.email"] + scopes: ["https://www.googleapis.com/auth/userinfo.email"], }), callback: async (url: string, locals: Locals) => { // const token = (await google.client.code.getToken(url)); @@ -142,7 +142,7 @@ export const google = { // } // })).data; // return loginWithOAuth2Service("google", data.name, data.email, locals); - } + }, }; export const microsoft = { client: new ClientOAuth2({ @@ -152,15 +152,15 @@ export const microsoft = { authorizationUri: "https://login.microsoftonline.com/common/oauth2/authorize", accessTokenUri: "https://login.microsoftonline.com/common/oauth2/token", - scopes: ["user.read", "mail.read"] + scopes: ["user.read", "mail.read"], }), callback: async (url: string, locals: Locals) => { const token = (await microsoft.client.code.getToken(url)).accessToken; const data = ( await axios.get("https://graph.microsoft.com/v1.0/me", { headers: { - Authorization: `Bearer ${token}` - } + Authorization: `Bearer ${token}`, + }, }) ).data; console.log(JSON.stringify(data)); @@ -170,5 +170,5 @@ export const microsoft = { data.mail, locals ); - } + }, }; diff --git a/src/rest/organization.ts b/src/rest/organization.ts index 702ff63ee..c8a025941 100644 --- a/src/rest/organization.ts +++ b/src/rest/organization.ts @@ -11,7 +11,7 @@ import { USER_IS_MEMBER_ALREADY, USER_NOT_FOUND, ORGANIZATION_NOT_FOUND, - RESOURCE_NOT_FOUND + RESOURCE_NOT_FOUND, } from "@staart/errors"; import { createCustomer, @@ -32,7 +32,7 @@ import { updateSubscription, createCustomerBalanceTransaction, getCustomBalanceTransactions, - getCustomBalanceTransaction + getCustomBalanceTransaction, } from "@staart/payments"; import axios from "axios"; import { JWT_ISSUER } from "../config"; @@ -41,7 +41,7 @@ import { ApiKeyResponse, verifyToken, checkInvalidatedToken, - invalidateToken + invalidateToken, } from "../helpers/jwt"; import { mail } from "../helpers/mail"; import { trackEvent } from "../helpers/tracking"; @@ -78,12 +78,12 @@ import { webhooksInclude, webhooksOrderByInput, webhooksWhereUniqueInput, - webhooksUpdateInput + webhooksUpdateInput, } from "@prisma/client"; import { getDomainByDomainName, getApiKeyLogs, - checkDomainAvailability + checkDomainAvailability, } from "../services/organization.service"; import { fireSingleWebhook } from "../helpers/webhooks"; @@ -96,8 +96,8 @@ export const getOrganizationForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -109,7 +109,7 @@ export const newOrganizationForUser = async ( ) => { if (!organization.name) { const user = await prisma.users.findOne({ - where: { id: parseInt(userId) } + where: { id: parseInt(userId) }, }); if (!user) throw new Error(USER_NOT_FOUND); organization.name = user.name; @@ -121,10 +121,10 @@ export const newOrganizationForUser = async ( create: { organization: {}, user: { connect: { id: parseInt(userId) } }, - role: "OWNER" - } - } - } + role: "OWNER", + }, + }, + }, }); }; @@ -139,9 +139,9 @@ export const updateOrganizationForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) + ), }, - data: {} + data: {}, }); queueWebhook(organizationId, Webhooks.UPDATE_ORGANIZATION, data); trackEvent({ organizationId, type: Webhooks.UPDATE_ORGANIZATION }, locals); @@ -160,8 +160,8 @@ export const deleteOrganizationForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organizationDetails) throw new Error(ORGANIZATION_NOT_FOUND); if (organizationDetails.stripeCustomerId) @@ -170,8 +170,8 @@ export const deleteOrganizationForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); queueWebhook(organizationId, Webhooks.DELETE_ORGANIZATION); trackEvent({ organizationId, type: Webhooks.DELETE_ORGANIZATION }, locals); @@ -196,8 +196,8 @@ export const getOrganizationBillingForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -225,8 +225,8 @@ export const updateOrganizationBillingForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); let result; @@ -241,9 +241,9 @@ export const updateOrganizationBillingForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) + ), }, - data + data, }) ); } @@ -274,8 +274,8 @@ export const getOrganizationInvoicesForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -302,8 +302,8 @@ export const getOrganizationInvoiceForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -330,8 +330,8 @@ export const getOrganizationSourcesForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -358,8 +358,8 @@ export const getOrganizationSourceForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -386,8 +386,8 @@ export const getOrganizationSubscriptionsForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -414,8 +414,8 @@ export const getOrganizationSubscriptionForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -444,8 +444,8 @@ export const updateOrganizationSubscriptionForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) { @@ -488,8 +488,8 @@ export const createOrganizationSubscriptionForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) { @@ -542,8 +542,8 @@ export const deleteOrganizationSourceForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) { @@ -586,8 +586,8 @@ export const updateOrganizationSourceForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) { @@ -626,8 +626,8 @@ export const createOrganizationSourceForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) { @@ -660,14 +660,14 @@ export const getAllOrganizationDataForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) + ), }, include: { api_keys: true, domains: true, memberships: true, - webhooks: true - } + webhooks: true, + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); return { @@ -680,9 +680,9 @@ export const getAllOrganizationDataForUser = async ( {} ), invoices: await getInvoices(organization.stripeCustomerId, {}), - sources: await getSources(organization.stripeCustomerId, {}) + sources: await getSources(organization.stripeCustomerId, {}), } - : {}) + : {}), }; } throw new Error(INSUFFICIENT_PERMISSION); @@ -699,7 +699,7 @@ export const getOrganizationMembershipsForUser = async ( after, before, first, - last + last, }: { select?: membershipsSelect; include?: membershipsInclude; @@ -728,7 +728,7 @@ export const getOrganizationMembershipsForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -748,7 +748,7 @@ export const getOrganizationMembershipForUser = async ( ) return prisma.memberships.findOne({ where: { id: parseInt(membershipId) }, - include: { user: true } + include: { user: true }, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -769,7 +769,7 @@ export const updateOrganizationMembershipForUser = async ( ) return prisma.memberships.update({ where: { id: parseInt(membershipId) }, - data + data, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -788,7 +788,7 @@ export const deleteOrganizationMembershipForUser = async ( ) ) { const members = await prisma.memberships.findMany({ - where: { organizationId: parseInt(organizationId) } + where: { organizationId: parseInt(organizationId) }, }); if (members.length === 1) throw new Error(CANNOT_DELETE_SOLE_MEMBER); return prisma.memberships.delete({ where: { id: parseInt(membershipId) } }); @@ -816,8 +816,8 @@ export const inviteMemberToOrganization = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.onlyAllowDomain) { @@ -836,7 +836,7 @@ export const inviteMemberToOrganization = async ( const checkUser = await prisma.users.findMany({ where: { emails: { some: { email: newMemberEmail } } }, - first: 1 + first: 1, }); if (checkUser.length) { newUser = checkUser[0]; @@ -849,8 +849,8 @@ export const inviteMemberToOrganization = async ( await prisma.memberships.findMany({ where: { userId: newUser.id, - organizationId: parseInt(organizationId) - } + organizationId: parseInt(organizationId), + }, }) ).length !== 0; createdUserId = newUser.id; @@ -859,8 +859,8 @@ export const inviteMemberToOrganization = async ( data: { user: { connect: { id: newUser.id } }, organization: { connect: { id: parseInt(organizationId) } }, - role - } + role, + }, }); } else { const newAccount = await register( @@ -879,12 +879,12 @@ export const inviteMemberToOrganization = async ( ?.name ?? "Someone" : "Someone"; const userDetails = prisma.users.findOne({ - where: { id: createdUserId } + where: { id: createdUserId }, }); mail(newMemberEmail, Templates.INVITED_TO_TEAM, { ...userDetails, team: organization.name, - inviter + inviter, }) .then(() => {}) .catch(() => {}); @@ -905,7 +905,7 @@ export const getOrganizationApiKeysForUser = async ( after, before, first, - last + last, }: { select?: api_keysSelect; include?: api_keysInclude; @@ -934,7 +934,7 @@ export const getOrganizationApiKeysForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -994,7 +994,7 @@ export const updateApiKeyForUser = async ( ) { const result = await prisma.api_keys.update({ where: { id: parseInt(apiKeyId) }, - data + data, }); queueWebhook(organizationId, Webhooks.UPDATE_API_KEY, data); trackEvent({ organizationId, type: Webhooks.UPDATE_API_KEY }, locals); @@ -1024,10 +1024,10 @@ export const createApiKeyForUser = async ( connect: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } - } - } + ), + }, + }, + }, }); queueWebhook(organizationId, Webhooks.CREATE_API_KEY, apiKey); trackEvent({ organizationId, type: Webhooks.CREATE_API_KEY }, locals); @@ -1051,7 +1051,7 @@ export const deleteApiKeyForUser = async ( ) ) { const result = await prisma.api_keys.delete({ - where: { id: parseInt(apiKeyId) } + where: { id: parseInt(apiKeyId) }, }); queueWebhook(organizationId, Webhooks.DELETE_API_KEY, apiKeyId); trackEvent({ organizationId, type: Webhooks.DELETE_API_KEY }, locals); @@ -1071,7 +1071,7 @@ export const getOrganizationDomainsForUser = async ( after, before, first, - last + last, }: { select?: domainsSelect; include?: domainsInclude; @@ -1100,7 +1100,7 @@ export const getOrganizationDomainsForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -1139,7 +1139,7 @@ export const updateDomainForUser = async ( ) { const result = await prisma.domains.update({ where: { id: parseInt(domainId) }, - data + data, }); queueWebhook(organizationId, Webhooks.UPDATE_DOMAIN, data); trackEvent({ organizationId, type: Webhooks.UPDATE_DOMAIN }, locals); @@ -1171,10 +1171,10 @@ export const createDomainForUser = async ( connect: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } - } - } + ), + }, + }, + }, }); queueWebhook(organizationId, Webhooks.CREATE_DOMAIN, domain); trackEvent({ organizationId, type: Webhooks.CREATE_DOMAIN }, locals); @@ -1198,7 +1198,7 @@ export const deleteDomainForUser = async ( ) ) { const result = await prisma.domains.delete({ - where: { id: parseInt(domainId) } + where: { id: parseInt(domainId) }, }); queueWebhook(organizationId, Webhooks.DELETE_DOMAIN, domainId); trackEvent({ organizationId, type: Webhooks.DELETE_DOMAIN }, locals); @@ -1223,7 +1223,7 @@ export const verifyDomainForUser = async ( ) ) { const domain = await prisma.domains.findOne({ - where: { id: parseInt(domainId) } + where: { id: parseInt(domainId) }, }); if (!domain) throw new Error(RESOURCE_NOT_FOUND); if (domain.isVerified) throw new Error(DOMAIN_ALREADY_VERIFIED); @@ -1238,11 +1238,11 @@ export const verifyDomainForUser = async ( if (file.replace(/\r?\n|\r/g, "").trim() === domain.verificationCode) { const result = await prisma.domains.update({ where: { id: parseInt(domainId) }, - data: { isVerified: true } + data: { isVerified: true }, }); queueWebhook(organizationId, Webhooks.VERIFY_DOMAIN, { domainId, - method + method, }); trackEvent({ organizationId, type: Webhooks.VERIFY_DOMAIN }, locals); return result; @@ -1255,11 +1255,11 @@ export const verifyDomainForUser = async ( if (JSON.stringify(dns).includes(domain.verificationCode)) { const result = await prisma.domains.update({ where: { id: parseInt(domainId) }, - data: { isVerified: true } + data: { isVerified: true }, }); queueWebhook(organizationId, Webhooks.VERIFY_DOMAIN, { domainId, - method + method, }); trackEvent({ organizationId, type: Webhooks.VERIFY_DOMAIN }, locals); return result; @@ -1283,7 +1283,7 @@ export const getOrganizationWebhooksForUser = async ( after, before, first, - last + last, }: { select?: webhooksSelect; include?: webhooksInclude; @@ -1312,7 +1312,7 @@ export const getOrganizationWebhooksForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -1351,7 +1351,7 @@ export const updateWebhookForUser = async ( ) { const result = await prisma.webhooks.update({ where: { id: parseInt(webhookId) }, - data + data, }); queueWebhook(organizationId, Webhooks.UPDATE_WEBHOOK, data); trackEvent({ organizationId, type: Webhooks.UPDATE_WEBHOOK }, locals); @@ -1381,10 +1381,10 @@ export const createWebhookForUser = async ( connect: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } - } - } + ), + }, + }, + }, }); fireSingleWebhook(result, Webhooks.TEST_WEBHOOK) .then(() => {}) @@ -1411,7 +1411,7 @@ export const deleteWebhookForUser = async ( ) ) { const result = prisma.webhooks.delete({ - where: { id: parseInt(webhookId) } + where: { id: parseInt(webhookId) }, }); queueWebhook(organizationId, Webhooks.DELETE_WEBHOOK, webhookId); trackEvent({ organizationId, type: Webhooks.DELETE_WEBHOOK }, locals); @@ -1453,8 +1453,8 @@ export const applyCouponToOrganizationForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (amount && currency && organization.stripeCustomerId) { @@ -1463,7 +1463,7 @@ export const applyCouponToOrganizationForUser = async ( { amount, currency, - description + description, } ); await invalidateToken(coupon); @@ -1491,8 +1491,8 @@ export const getOrganizationTransactionsForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) @@ -1522,8 +1522,8 @@ export const getOrganizationTransactionForUser = async ( where: { id: parseInt( typeof userId === "object" ? userId.organizationId : userId - ) - } + ), + }, }); if (!organization) throw new Error(ORGANIZATION_NOT_FOUND); if (organization.stripeCustomerId) diff --git a/src/rest/user.ts b/src/rest/user.ts index 59b443c5d..243dbbd44 100644 --- a/src/rest/user.ts +++ b/src/rest/user.ts @@ -11,7 +11,7 @@ import { CANNOT_DELETE_SOLE_MEMBER, CANNOT_DELETE_SOLE_OWNER, CANNOT_UPDATE_SOLE_OWNER, - MEMBERSHIP_NOT_FOUND + MEMBERSHIP_NOT_FOUND, } from "@staart/errors"; import { compare } from "@staart/text"; import { authenticator } from "otplib"; @@ -21,7 +21,7 @@ import { createBackupCodes, getUserPrimaryEmail, getUserBestEmail, - resendEmailVerification + resendEmailVerification, } from "../services/user.service"; import { can } from "../helpers/authorization"; import { trackEvent } from "../helpers/tracking"; @@ -55,7 +55,7 @@ import { emailsInclude, emailsOrderByInput, emailsWhereUniqueInput, - membershipsUpdateInput + membershipsUpdateInput, } from "@prisma/client"; import { ALLOW_DISPOSABLE_EMAILS } from "../config"; import { checkIfDisposableEmail } from "@staart/disposable-email"; @@ -64,7 +64,7 @@ import { ApiKeyResponse } from "../helpers/jwt"; export const getUserFromId = async (userId: string, tokenUserId: string) => { if (await can(tokenUserId, UserScopes.READ_USER, "user", userId)) { const user = await prisma.users.findOne({ - where: { id: parseInt(userId) } + where: { id: parseInt(userId) }, }); if (user) return user; throw new Error(USER_NOT_FOUND); @@ -82,13 +82,13 @@ export const updateUserForUser = async ( if (await can(tokenUserId, UserScopes.UPDATE_USER, "user", updateUserId)) { const user = await prisma.users.update({ data, - where: { id: parseInt(updateUserId) } + where: { id: parseInt(updateUserId) }, }); trackEvent( { userId: tokenUserId, type: EventType.USER_UPDATED, - data: { id: updateUserId, data } + data: { id: updateUserId, data }, }, locals ); @@ -108,7 +108,7 @@ export const updatePasswordForUser = async ( await can(tokenUserId, UserScopes.CHANGE_PASSWORD, "user", updateUserId) ) { const user = await prisma.users.findOne({ - where: { id: parseInt(updateUserId) } + where: { id: parseInt(updateUserId) }, }); if (!user) throw new Error(USER_NOT_FOUND); if (!user.password) throw new Error(MISSING_PASSWORD); @@ -116,13 +116,13 @@ export const updatePasswordForUser = async ( if (!correctPassword) throw new Error(INCORRECT_PASSWORD); const result = await prisma.users.update({ data: { password: newPassword }, - where: { id: parseInt(updateUserId) } + where: { id: parseInt(updateUserId) }, }); trackEvent( { userId: tokenUserId, type: EventType.AUTH_PASSWORD_CHANGED, - data: { id: updateUserId } + data: { id: updateUserId }, }, locals ); @@ -138,20 +138,20 @@ export const deleteUserForUser = async ( ) => { if (await can(tokenUserId, UserScopes.DELETE_USER, "user", updateUserId)) { await prisma.emails.deleteMany({ - where: { userId: parseInt(updateUserId) } + where: { userId: parseInt(updateUserId) }, }); await prisma.memberships.deleteMany({ - where: { userId: parseInt(updateUserId) } + where: { userId: parseInt(updateUserId) }, }); await prisma.approved_locations.deleteMany({ - where: { userId: parseInt(updateUserId) } + where: { userId: parseInt(updateUserId) }, }); await prisma.users.deleteMany({ where: { id: parseInt(updateUserId) } }); trackEvent( { userId: tokenUserId, type: EventType.USER_DELETED, - data: { id: updateUserId } + data: { id: updateUserId }, }, locals ); @@ -171,7 +171,7 @@ export const getMembershipsForUser = async ( after, before, first, - last + last, }: { select?: membershipsSelect; include?: membershipsInclude; @@ -195,7 +195,7 @@ export const getMembershipsForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -215,8 +215,8 @@ export const getAllDataForUser = async ( backup_codes: true, identities: true, memberships: true, - sessions: true - } + sessions: true, + }, }); }; @@ -226,7 +226,7 @@ export const enable2FAForUser = async (tokenUserId: string, userId: string) => { const secret = authenticator.generateSecret(); await prisma.users.update({ where: { id: parseInt(userId) }, - data: { twoFactorSecret: secret } + data: { twoFactorSecret: secret }, }); const authPath = authenticator.keyuri(`user-${userId}`, SERVICE_2FA, secret); const qrCode = await toDataURL(authPath); @@ -244,7 +244,7 @@ export const verify2FAForUser = async ( const secret = ( await prisma.users.findOne({ select: { twoFactorSecret: true }, - where: { id: parseInt(userId) } + where: { id: parseInt(userId) }, }) )?.twoFactorSecret; if (!secret) throw new Error(NOT_ENABLED_2FA); @@ -253,7 +253,7 @@ export const verify2FAForUser = async ( await createBackupCodes(userId, 10); return prisma.users.update({ where: { id: parseInt(userId) }, - data: { twoFactorEnabled: true } + data: { twoFactorEnabled: true }, }); }; @@ -268,8 +268,8 @@ export const disable2FAForUser = async ( where: { id: parseInt(userId) }, data: { twoFactorEnabled: false, - twoFactorSecret: null - } + twoFactorSecret: null, + }, }); }; @@ -313,7 +313,7 @@ export const getUserAccessTokensForUser = async ( after, before, first, - last + last, }: { select?: access_tokensSelect; include?: access_tokensInclude; @@ -337,7 +337,7 @@ export const getUserAccessTokensForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -351,7 +351,7 @@ export const getUserAccessTokenForUser = async ( await can(tokenUserId, UserScopes.READ_USER_ACCESS_TOKENS, "user", userId) ) return prisma.access_tokens.findOne({ - where: { id: parseInt(accessTokenId) } + where: { id: parseInt(accessTokenId) }, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -368,7 +368,7 @@ export const updateAccessTokenForUser = async ( ) return prisma.access_tokens.update({ where: { id: parseInt(accessTokenId) }, - data + data, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -383,7 +383,7 @@ export const createAccessTokenForUser = async ( await can(tokenUserId, UserScopes.CREATE_USER_ACCESS_TOKENS, "user", userId) ) return prisma.access_tokens.create({ - data: { ...accessToken, user: { connect: { id: parseInt(userId) } } } + data: { ...accessToken, user: { connect: { id: parseInt(userId) } } }, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -398,7 +398,7 @@ export const deleteAccessTokenForUser = async ( await can(tokenUserId, UserScopes.DELETE_USER_ACCESS_TOKENS, "user", userId) ) return prisma.access_tokens.delete({ - where: { id: parseInt(accessTokenId) } + where: { id: parseInt(accessTokenId) }, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -414,7 +414,7 @@ export const getUserSessionsForUser = async ( after, before, first, - last + last, }: { select?: sessionsSelect; include?: sessionsInclude; @@ -436,7 +436,7 @@ export const getUserSessionsForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -474,7 +474,7 @@ export const getUserIdentitiesForUser = async ( after, before, first, - last + last, }: { select?: identitiesSelect; include?: identitiesInclude; @@ -496,7 +496,7 @@ export const getUserIdentitiesForUser = async ( after, before, first, - last + last, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -508,7 +508,7 @@ export const createUserIdentityForUser = async ( ) => { if (await can(tokenUserId, UserScopes.CREATE_USER_IDENTITY, "user", userId)) return prisma.identities.create({ - data: { ...identity, user: { connect: { id: parseInt(userId) } } } + data: { ...identity, user: { connect: { id: parseInt(userId) } } }, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -552,18 +552,18 @@ export const addInvitationCredits = async ( const invitedByUserId = ( await prisma.users.findOne({ select: { username: true }, - where: { id: parseInt(invitedBy) } + where: { id: parseInt(invitedBy) }, }) )?.username; if (!invitedByUserId) return; const invitedByDetails = await prisma.users.findOne({ - where: { id: parseInt(invitedByUserId) } + where: { id: parseInt(invitedByUserId) }, }); if (!invitedByDetails) return; const invitedByEmail = await getUserPrimaryEmail(invitedByUserId); const newUserEmail = await getUserBestEmail(newUserId); const newUserDetails = await prisma.users.findOne({ - where: { id: parseInt(newUserId) } + where: { id: parseInt(newUserId) }, }); if (!newUserDetails) return; const emailData = { @@ -578,7 +578,7 @@ export const addInvitationCredits = async ( 500, "usd", `Invite credits from ${invitedByDetails.name}` - ) + ), }; await mail(invitedByEmail.email, Templates.CREDITS_INVITED_BY, emailData); await mail(newUserEmail.email, Templates.CREDITS_NEW_USER, emailData); @@ -595,7 +595,7 @@ export const getAllEmailsForUser = async ( after, before, first, - last + last, }: { select?: emailsSelect; include?: emailsInclude; @@ -617,7 +617,7 @@ export const getAllEmailsForUser = async ( after, before, first, - last + last, }); } throw new Error(INSUFFICIENT_PERMISSION); @@ -663,7 +663,7 @@ export const addEmailToUserForUser = async ( (await prisma.emails.findMany({ where: { email } })).length !== 0; if (emailExistsAlready) throw new Error(EMAIL_EXISTS); const result = await prisma.emails.create({ - data: { email, user: { connect: { id: parseInt(userId) } } } + data: { email, user: { connect: { id: parseInt(userId) } } }, }); trackEvent( { userId, type: EventType.EMAIL_CREATED, data: { email } }, @@ -681,28 +681,28 @@ export const deleteEmailFromUserForUser = async ( if (!(await can(tokenUserId, UserScopes.DELETE_USER_EMAILS, "user", userId))) throw new Error(INSUFFICIENT_PERMISSION); const email = await prisma.emails.findOne({ - where: { id: parseInt(userId) } + where: { id: parseInt(userId) }, }); if (!email) throw new Error(RESOURCE_NOT_FOUND); if (email.userId !== parseInt(userId)) throw new Error(INSUFFICIENT_PERMISSION); const verifiedEmails = await prisma.emails.findMany({ - where: { id: parseInt(userId) } + where: { id: parseInt(userId) }, }); if (verifiedEmails.length === 1 && email.isVerified) throw new Error(EMAIL_CANNOT_DELETE); const currentPrimaryEmailId = (await getUserPrimaryEmail(userId)).id; if (currentPrimaryEmailId === parseInt(emailId)) { const nextVerifiedEmail = verifiedEmails.filter( - emailObject => emailObject.id !== parseInt(emailId) + (emailObject) => emailObject.id !== parseInt(emailId) )[0]; await prisma.users.update({ where: { id: parseInt(userId) }, - data: { primaryEmail: nextVerifiedEmail.id } + data: { primaryEmail: nextVerifiedEmail.id }, }); } const result = await prisma.emails.delete({ - where: { id: parseInt(emailId) } + where: { id: parseInt(emailId) }, }); trackEvent( { userId, type: EventType.EMAIL_DELETED, data: { email: email.email } }, @@ -725,7 +725,7 @@ export const getMembershipDetailsForUser = async ( ) return prisma.memberships.findOne({ where: { id: parseInt(membershipId) }, - include: { user: true, organization: true } + include: { user: true, organization: true }, }); throw new Error(INSUFFICIENT_PERMISSION); }; @@ -736,7 +736,7 @@ export const deleteMembershipForUser = async ( locals: Locals ) => { const membership = await prisma.memberships.findOne({ - where: { id: parseInt(membershipId) } + where: { id: parseInt(membershipId) }, }); if (!membership) throw new Error(MEMBERSHIP_NOT_FOUND); if ( @@ -748,11 +748,11 @@ export const deleteMembershipForUser = async ( ) ) { const organizationMembers = await prisma.memberships.findMany({ - where: { organizationId: membership.organizationId } + where: { organizationId: membership.organizationId }, }); if (membership.role === "OWNER") { const currentMembers = organizationMembers.filter( - member => member.role === "OWNER" + (member) => member.role === "OWNER" ); if (currentMembers.length < 2) throw new Error(CANNOT_DELETE_SOLE_OWNER); } @@ -761,7 +761,7 @@ export const deleteMembershipForUser = async ( trackEvent( { userId: membershipId, - type: EventType.MEMBERSHIP_DELETED + type: EventType.MEMBERSHIP_DELETED, }, locals ); @@ -785,16 +785,16 @@ export const updateMembershipForUser = async ( ) ) { const membership = await prisma.memberships.findOne({ - where: { id: parseInt(membershipId) } + where: { id: parseInt(membershipId) }, }); if (!membership) throw new Error(MEMBERSHIP_NOT_FOUND); if (data.role !== membership.role) { if (membership.role === "OWNER") { const organizationMembers = await prisma.memberships.findMany({ - where: { organizationId: membership.organizationId } + where: { organizationId: membership.organizationId }, }); const currentMembers = organizationMembers.filter( - member => member.role === "OWNER" + (member) => member.role === "OWNER" ); if (currentMembers.length < 2) throw new Error(CANNOT_UPDATE_SOLE_OWNER); @@ -803,13 +803,13 @@ export const updateMembershipForUser = async ( trackEvent( { userId: membershipId, - type: EventType.MEMBERSHIP_UPDATED + type: EventType.MEMBERSHIP_UPDATED, }, locals ); return prisma.memberships.update({ where: { id: parseInt(membershipId) }, - data + data, }); } throw new Error(INSUFFICIENT_PERMISSION); diff --git a/src/server.ts b/src/server.ts index 71df15c40..5cb1fd1c3 100644 --- a/src/server.ts +++ b/src/server.ts @@ -6,7 +6,7 @@ import { errorHandler, rateLimitHandler, speedLimitHandler, - trackingHandler + trackingHandler, } from "./helpers/middleware"; @Controller("v1") @@ -16,7 +16,7 @@ class RootController { return { repository: "https://github.com/staart/api", docs: "https://staart.js.org", - madeBy: ["https://o15y.com", "https://anandchowdhary.com"] + madeBy: ["https://o15y.com", "https://anandchowdhary.com"], }; } } diff --git a/src/services/user.service.ts b/src/services/user.service.ts index cf8f4ae81..ee0490b00 100644 --- a/src/services/user.service.ts +++ b/src/services/user.service.ts @@ -2,14 +2,14 @@ import { USERNAME_EXISTS, USER_NOT_FOUND, RESOURCE_NOT_FOUND, - MISSING_PRIMARY_EMAIL + MISSING_PRIMARY_EMAIL, } from "@staart/errors"; import { anonymizeIpAddress, capitalizeFirstAndLastLetter, createSlug, hash, - slugify + slugify, } from "@staart/text"; import { createHash } from "crypto"; import randomInt from "random-int"; @@ -24,7 +24,7 @@ import { emailsCreateInput, access_tokensCreateInput, sessionsUpdateInput, - usersCreateInput + usersCreateInput, } from "@prisma/client"; import { decode } from "jsonwebtoken"; import { emailVerificationToken } from "../helpers/jwt"; @@ -65,7 +65,7 @@ export const checkUserUsernameAvailability = async (username: string) => { return ( ( await prisma.users.findMany({ - where: { username } + where: { username }, }) ).length === 0 ); @@ -88,7 +88,7 @@ export const createUser = async ( .digest("hex")}.png`; // Create user const result = await prisma.users.create({ - data: user + data: user, }); return result; }; @@ -98,7 +98,7 @@ export const createUser = async ( */ export const getUserByEmail = async (email: string, secureOrigin = false) => { const emailObject = await prisma.emails.findMany({ - where: { email, isVerified: true } + where: { email, isVerified: true }, }); if (!emailObject.length) throw new Error(USER_NOT_FOUND); const user = await prisma.users.findOne({ where: { id: emailObject[0].id } }); @@ -115,12 +115,12 @@ export const updateUser = async (id: string, user: KeyValue) => { // If you're updating your primary email, your Gravatar should reflect it if (user.primaryEmail) { const originalUser = await prisma.users.findOne({ - where: { id: parseInt(id) } + where: { id: parseInt(id) }, }); if (!originalUser) throw new Error(USER_NOT_FOUND); if ((originalUser.profilePicture || "").includes("api.adorable.io")) { const emailDetails = await prisma.emails.findOne({ - where: { id: user.primaryEmail } + where: { id: user.primaryEmail }, }); if (emailDetails) user.profilePicture = `https://www.gravatar.com/avatar/${createHash( @@ -137,11 +137,11 @@ export const updateUser = async (id: string, user: KeyValue) => { // If you're updating your username, make sure it's available if (user.username) { const originalUser = await prisma.users.findOne({ - where: { id: parseInt(id) } + where: { id: parseInt(id) }, }); if (!originalUser) throw new Error(USER_NOT_FOUND); const currentOwnerOfUsername = await prisma.users.findMany({ - where: { username: user.username } + where: { username: user.username }, }); if ( currentOwnerOfUsername.length && @@ -166,8 +166,8 @@ export const addApprovedLocation = async ( data: { user: { connect: { id: parseInt(userId) } }, subnet, - createdAt: new Date() - } + createdAt: new Date(), + }, }); }; @@ -187,7 +187,7 @@ export const checkApprovedLocation = async ( return ( ( await prisma.approved_locations.findMany({ - where: { userId: parseInt(userId), subnet } + where: { userId: parseInt(userId), subnet }, }) ).length !== 0 ); @@ -206,8 +206,8 @@ export const createBackupCodes = async (userId: string | number, count = 1) => { code: randomInt(100000, 999999).toString(), user: { connect: { id: parseInt(userId) } }, createdAt: now, - updatedAt: now - } + updatedAt: now, + }, }); } return; @@ -230,7 +230,7 @@ export const updateAccessToken = async ( data: access_tokens ) => { const newAccessToken = await prisma.access_tokens.findOne({ - where: { id: parseInt(accessTokenId) } + where: { id: parseInt(accessTokenId) }, }); if (!newAccessToken) throw new Error(RESOURCE_NOT_FOUND); if (newAccessToken.jwtAccessToken) @@ -238,7 +238,7 @@ export const updateAccessToken = async ( data.jwtAccessToken = await accessToken({ ...newAccessToken, ...data }); return prisma.access_tokens.update({ data, - where: { id: parseInt(accessTokenId) } + where: { id: parseInt(accessTokenId) }, }); }; @@ -247,13 +247,13 @@ export const updateAccessToken = async ( */ export const deleteAccessToken = async (accessTokenId: string) => { const currentAccessToken = await prisma.access_tokens.findOne({ - where: { id: parseInt(accessTokenId) } + where: { id: parseInt(accessTokenId) }, }); if (!currentAccessToken) throw new Error(RESOURCE_NOT_FOUND); if (currentAccessToken.jwtAccessToken) await invalidateToken(currentAccessToken.jwtAccessToken); return prisma.access_tokens.delete({ - where: { id: parseInt(accessTokenId) } + where: { id: parseInt(accessTokenId) }, }); }; @@ -266,12 +266,12 @@ export const getUserPrimaryEmail = async (userId: string | number) => { const primaryEmailId = ( await prisma.users.findOne({ select: { primaryEmail: true }, - where: { id: parseInt(userId) } + where: { id: parseInt(userId) }, }) )?.primaryEmail; if (!primaryEmailId) throw new Error(MISSING_PRIMARY_EMAIL); const primaryEmail = await prisma.emails.findOne({ - where: { id: primaryEmailId } + where: { id: primaryEmailId }, }); if (!primaryEmail) throw new Error(MISSING_PRIMARY_EMAIL); return primaryEmail; @@ -289,7 +289,7 @@ export const getUserBestEmail = async (userId: string | number) => { const emails = await prisma.emails.findMany({ where: { userId: parseInt(userId) }, orderBy: { isVerified: "desc" }, - first: 1 + first: 1, }); if (!emails.length) throw new Error(RESOURCE_NOT_FOUND); return emails[0]; @@ -313,7 +313,7 @@ export const updateSessionByJwt = async ( } } catch (error) {} const currentSession = await prisma.sessions.findMany({ - where: { jwtToken: sessionJwt, userId } + where: { jwtToken: sessionJwt, userId }, }); if (!currentSession.length) throw new Error(RESOURCE_NOT_FOUND); return prisma.sessions.update({ where: { id: currentSession[0].id }, data }); @@ -331,7 +331,7 @@ export const createEmail = async ( sendPasswordSet = false ) => { const result = await prisma.emails.create({ - data: { ...email, user: { connect: { id: userId } } } + data: { ...email, user: { connect: { id: userId } } }, }); if (sendVerification) { const user = await prisma.users.findOne({ where: { id: userId } }); @@ -363,12 +363,12 @@ export const resendEmailVerification = async (id: string | number) => { if (typeof id === "number") id = id.toString(); const token = await emailVerificationToken(id); const emailObject = await prisma.emails.findOne({ - where: { id: parseInt(id) } + where: { id: parseInt(id) }, }); if (!emailObject) throw new Error(RESOURCE_NOT_FOUND); const email = emailObject.email; const user = await prisma.users.findOne({ - where: { id: emailObject.userId } + where: { id: emailObject.userId }, }); if (!user) throw new Error(USER_NOT_FOUND); await mail(email, Templates.EMAIL_VERIFY, { name: user.name, email, token }); diff --git a/src/templates/template.html b/src/templates/template.html index 5647ddb36..1395e3909 100644 --- a/src/templates/template.html +++ b/src/templates/template.html @@ -1,33 +1,234 @@ - + - - - + + + - - + +
-
  -
- - +
+
+ {{ introLine }} + -
- +
+

Text

- +
-
- +
+ - @@ -36,19 +237,59 @@
- {{ ctaText }} + + {{ ctaText }}
-

More text

+

More text

-