diff --git a/backend/src/controllers/v1/organizationController.ts b/backend/src/controllers/v1/organizationController.ts index 6de5a7c63..f738891a2 100644 --- a/backend/src/controllers/v1/organizationController.ts +++ b/backend/src/controllers/v1/organizationController.ts @@ -260,22 +260,6 @@ export const createOrganizationPortalSession = async ( } }; -/** - * Return organization subscriptions - * @param req - * @param res - * @returns - */ -export const getOrganizationSubscriptions = async ( - req: Request, - res: Response -) => { - return res.status(200).send({ - subscriptions: [] - }); -}; - - /** * Given a org id, return the projects each member of the org belongs to * @param req diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index 13537df9c..23f9a6d0a 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -1,7 +1,7 @@ import { Types } from "mongoose"; import { Request, Response } from "express"; import { ISecret, Secret, ServiceTokenData } from "../../models"; -import { IAction, SecretVersion, EventType, AuditLog } from "../../ee/models"; +import { AuditLog, EventType, IAction, SecretVersion } from "../../ee/models"; import { ACTION_ADD_SECRETS, ACTION_DELETE_SECRETS, @@ -14,7 +14,7 @@ import { import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; import { EventService } from "../../services"; import { eventPushSecrets } from "../../events"; -import { EELogService, EESecretService, EEAuditLogService } from "../../ee/services"; +import { EEAuditLogService, EELogService, EESecretService } from "../../ee/services"; import { SecretService, TelemetryService } from "../../services"; import { getUserAgentType } from "../../utils/posthog"; import { PERMISSION_WRITE_SECRETS } from "../../variables"; diff --git a/backend/src/ee/services/EEAuditLogService.ts b/backend/src/ee/services/EEAuditLogService.ts index 91fbc4252..eb5c1bbb3 100644 --- a/backend/src/ee/services/EEAuditLogService.ts +++ b/backend/src/ee/services/EEAuditLogService.ts @@ -16,7 +16,7 @@ type ValidEventScope = | Required export default class EEAuditLogService { - static async createAuditLog(authData: AuthData, event: Event, eventScope: ValidEventScope, shouldSave: boolean = true) { + static async createAuditLog(authData: AuthData, event: Event, eventScope: ValidEventScope, shouldSave = true) { const MS_IN_DAY = 24 * 60 * 60 * 1000; diff --git a/backend/src/routes/v1/auth.ts b/backend/src/routes/v1/auth.ts index ce21f5136..b633f82ea 100644 --- a/backend/src/routes/v1/auth.ts +++ b/backend/src/routes/v1/auth.ts @@ -8,7 +8,7 @@ import { AuthMode } from "../../variables"; router.post("/token", validateRequest, authController.getNewToken); -router.post( // deprecated (moved to api/v2/auth/login1) +router.post( // TODO endpoint: deprecate (moved to api/v3/auth/login1) "/login1", authLimiter, body("email").exists().trim().notEmpty(), @@ -17,7 +17,7 @@ router.post( // deprecated (moved to api/v2/auth/login1) authController.login1 ); -router.post( // deprecated (moved to api/v2/auth/login2) +router.post( // TODO endpoint: deprecate (moved to api/v3/auth/login2) "/login2", authLimiter, body("email").exists().trim().notEmpty(), @@ -49,7 +49,7 @@ router.get( authController.getCommonPasswords ); -router.delete( +router.delete( // TODO endpoint: deprecate (moved to DELETE v2/users/me/sessions) "/sessions", authLimiter, requireAuth({ diff --git a/backend/src/routes/v1/inviteOrg.ts b/backend/src/routes/v1/inviteOrg.ts index 089c0e53a..f79ce61d1 100644 --- a/backend/src/routes/v1/inviteOrg.ts +++ b/backend/src/routes/v1/inviteOrg.ts @@ -5,6 +5,8 @@ import { requireAuth, validateRequest } from "../../middleware"; import { membershipOrgController } from "../../controllers/v1"; import { AuthMode } from "../../variables"; +// TODO endpoint: consider moving these endpoints to be under /organization to be more RESTful + router.post( "/signup", requireAuth({ diff --git a/backend/src/routes/v1/key.ts b/backend/src/routes/v1/key.ts index a12c8c0bb..a72b508b9 100644 --- a/backend/src/routes/v1/key.ts +++ b/backend/src/routes/v1/key.ts @@ -9,6 +9,8 @@ import { body, param } from "express-validator"; import { ADMIN, AuthMode, MEMBER } from "../../variables"; import { keyController } from "../../controllers/v1"; +// TODO endpoint: consider moving these endpoints to be under /workspaces to be more RESTful + router.post( "/:workspaceId", requireAuth({ @@ -24,7 +26,7 @@ router.post( keyController.uploadKey ); -router.get( +router.get( // TODO endpoint: deprecate (note: move frontend to v2/workspace/key or something) "/:workspaceId/latest", requireAuth({ acceptedAuthModes: [AuthMode.JWT], diff --git a/backend/src/routes/v1/membership.ts b/backend/src/routes/v1/membership.ts index be495b62c..cf38c7cbc 100644 --- a/backend/src/routes/v1/membership.ts +++ b/backend/src/routes/v1/membership.ts @@ -7,8 +7,9 @@ import { membershipController as EEMembershipControllers } from "../../ee/contro import { AuthMode } from "../../variables"; // note: ALL DEPRECIATED (moved to api/v2/workspace/:workspaceId/memberships/:membershipId) +// TODO endpoint: consider moving these endpoints to be under /workspace to be more RESTful -router.get( // used for old CLI (deprecate) +router.get( // TODO endpoint: deprecate - used for old CLI (deprecate) "/:workspaceId/connect", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -18,7 +19,7 @@ router.get( // used for old CLI (deprecate) membershipController.validateMembership ); -router.delete( +router.delete( // TODO endpoint: check dashboard "/:membershipId", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -28,7 +29,7 @@ router.delete( membershipController.deleteMembership ); -router.post( +router.post( // TODO endpoint: check dashboard "/:membershipId/change-role", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -38,7 +39,7 @@ router.post( membershipController.changeMembershipRole ); -router.post( +router.post( // TODO endpoint: check dashboard "/:membershipId/deny-permissions", requireAuth({ acceptedAuthModes: [AuthMode.JWT], diff --git a/backend/src/routes/v1/membershipOrg.ts b/backend/src/routes/v1/membershipOrg.ts index 92472eb03..34899072b 100644 --- a/backend/src/routes/v1/membershipOrg.ts +++ b/backend/src/routes/v1/membershipOrg.ts @@ -5,8 +5,7 @@ import { requireAuth, validateRequest } from "../../middleware"; import { membershipOrgController } from "../../controllers/v1"; import { AuthMode } from "../../variables"; -router.post( - // TODO +router.post( // TODO endpoint: check dashboard "/membershipOrg/:membershipOrgId/change-role", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -17,7 +16,7 @@ router.post( ); router.delete( - "/:membershipOrgId", + "/:membershipOrgId", // TODO endpoint: check dashboard requireAuth({ acceptedAuthModes: [AuthMode.JWT], }), diff --git a/backend/src/routes/v1/organization.ts b/backend/src/routes/v1/organization.ts index 8f4a924e9..78672093d 100644 --- a/backend/src/routes/v1/organization.ts +++ b/backend/src/routes/v1/organization.ts @@ -15,7 +15,7 @@ import { } from "../../variables"; import { organizationController } from "../../controllers/v1"; -router.get( // deprecated (moved to api/v2/users/me/organizations) +router.get( // TODO endpoint: deprecate (moved to api/v2/users/me/organizations) "/", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -47,7 +47,7 @@ router.get( organizationController.getOrganization ); -router.get( // deprecated (moved to api/v2/organizations/:organizationId/memberships) +router.get( // TODO endpoint: deprecate (moved to api/v2/organizations/:organizationId/memberships) "/:organizationId/users", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -61,7 +61,7 @@ router.get( // deprecated (moved to api/v2/organizations/:organizationId/members organizationController.getOrganizationMembers ); -router.get( +router.get( // TODO endpoint: move to /v2/users/me/organizations/:organizationId/workspaces "/:organizationId/my-workspaces", // deprecated (moved to api/v2/organizations/:organizationId/workspaces) requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -135,7 +135,7 @@ router.delete( ); router.post( - "/:organizationId/customer-portal-session", + "/:organizationId/customer-portal-session", // TODO endpoint: move to EE requireAuth({ acceptedAuthModes: [AuthMode.JWT], }), @@ -148,20 +148,6 @@ router.post( organizationController.createOrganizationPortalSession ); -router.get( - "/:organizationId/subscriptions", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - requireOrganizationAuth({ - acceptedRoles: [OWNER, ADMIN, MEMBER], - acceptedStatuses: [ACCEPTED], - }), - param("organizationId").exists().trim(), - validateRequest, - organizationController.getOrganizationSubscriptions -); - router.get( "/:organizationId/workspace-memberships", requireAuth({ diff --git a/backend/src/routes/v1/secret.ts b/backend/src/routes/v1/secret.ts index 10668de34..e2b63e9ef 100644 --- a/backend/src/routes/v1/secret.ts +++ b/backend/src/routes/v1/secret.ts @@ -14,9 +14,9 @@ import { MEMBER } from "../../variables"; -// note to devs: these endpoints will be deprecated in favor of v2 +// note: endpoints deprecated in favor of v3/secrets -router.post( +router.post( // TODO endpoint: deprecate (moved to POST api/v3/secrets) "/:workspaceId", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -34,7 +34,7 @@ router.post( secretController.pushSecrets ); -router.get( +router.get( // TODO endpoint: deprecate (moved to GET api/v3/secrets) "/:workspaceId", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -50,7 +50,7 @@ router.get( secretController.pullSecrets ); -router.get( +router.get( // TODO endpoint: deprecate (moved to GET api/v3/secrets) "/:workspaceId/service-token", requireServiceTokenAuth, query("environment").exists().trim(), diff --git a/backend/src/routes/v1/serviceToken.ts b/backend/src/routes/v1/serviceToken.ts index aaf35e85f..e79d24ffa 100644 --- a/backend/src/routes/v1/serviceToken.ts +++ b/backend/src/routes/v1/serviceToken.ts @@ -16,13 +16,13 @@ import { serviceTokenController } from "../../controllers/v1"; // note: deprecate service-token routes in favor of service-token data routes/structure -router.get( +router.get( // TODO endpoint: deprecate "/", requireServiceTokenAuth, serviceTokenController.getServiceToken ); -router.post( +router.post( // TODO endpoint: deprecate "/", requireAuth({ acceptedAuthModes: [AuthMode.JWT], diff --git a/backend/src/routes/v1/signup.ts b/backend/src/routes/v1/signup.ts index 1b82edd3a..80d250b1a 100644 --- a/backend/src/routes/v1/signup.ts +++ b/backend/src/routes/v1/signup.ts @@ -5,7 +5,9 @@ import { validateRequest } from "../../middleware"; import { signupController } from "../../controllers/v1"; import { authLimiter } from "../../helpers/rateLimiter"; -router.post( +// TODO: consider moving to users/v3/signup + +router.post( // TODO endpoint: consider moving to v3/users/signup/mail "/email/signup", authLimiter, body("email").exists().trim().notEmpty().isEmail(), @@ -14,7 +16,7 @@ router.post( ); router.post( - "/email/verify", + "/email/verify", // TODO endpoint: consider moving to v3/users/signup/verify authLimiter, body("email").exists().trim().notEmpty().isEmail(), body("code").exists().trim().notEmpty(), @@ -22,4 +24,4 @@ router.post( signupController.verifyEmailSignup ); -export default router; +export default router; \ No newline at end of file diff --git a/backend/src/routes/v1/user.ts b/backend/src/routes/v1/user.ts index 73012c1ea..85333db9b 100644 --- a/backend/src/routes/v1/user.ts +++ b/backend/src/routes/v1/user.ts @@ -4,7 +4,7 @@ import { requireAuth } from "../../middleware"; import { userController } from "../../controllers/v1"; import { AuthMode } from "../../variables"; -router.get( +router.get( // TODO endpoint: deprecate (moved to v2/users/me) "/", requireAuth({ acceptedAuthModes: [AuthMode.JWT], diff --git a/backend/src/routes/v1/userAction.ts b/backend/src/routes/v1/userAction.ts index 042f73c10..7fd26f783 100644 --- a/backend/src/routes/v1/userAction.ts +++ b/backend/src/routes/v1/userAction.ts @@ -6,7 +6,7 @@ import { userActionController } from "../../controllers/v1"; import { AuthMode } from "../../variables"; // note: [userAction] will be deprecated in /v2 in favor of [action] -router.post( +router.post( // TODO endpoint: move this into /users/me "/", requireAuth({ acceptedAuthModes: [AuthMode.JWT], diff --git a/backend/src/routes/v1/workspace.ts b/backend/src/routes/v1/workspace.ts index 9a4554be6..f08d92865 100644 --- a/backend/src/routes/v1/workspace.ts +++ b/backend/src/routes/v1/workspace.ts @@ -147,7 +147,7 @@ router.get( ); router.get( - "/:workspaceId/service-tokens", // deprecate + "/:workspaceId/service-tokens", // TODO endpoint: deprecate requireAuth({ acceptedAuthModes: [AuthMode.JWT], }), diff --git a/backend/src/routes/v2/auth.ts b/backend/src/routes/v2/auth.ts index 444819f27..bf348c279 100644 --- a/backend/src/routes/v2/auth.ts +++ b/backend/src/routes/v2/auth.ts @@ -5,7 +5,7 @@ import { requireMfaAuth, validateRequest } from "../../middleware"; import { authController } from "../../controllers/v2"; import { authLimiter } from "../../helpers/rateLimiter"; -router.post( +router.post( // TODO: deprecate (moved to api/v3/auth/login1) "/login1", authLimiter, body("email").isString().trim().notEmpty(), @@ -14,7 +14,7 @@ router.post( authController.login1 ); -router.post( +router.post( // TODO: deprecate (moved to api/v3/auth/login1) "/login2", authLimiter, body("email").isString().trim().notEmpty(), diff --git a/backend/src/routes/v2/organizations.ts b/backend/src/routes/v2/organizations.ts index b305c1c0a..55f8606df 100644 --- a/backend/src/routes/v2/organizations.ts +++ b/backend/src/routes/v2/organizations.ts @@ -85,7 +85,7 @@ router.get( organizationsController.getOrganizationWorkspaces ); -router.get( +router.get( // TODO endpoint: deprecate service accounts "/:organizationId/service-accounts", param("organizationId").exists().trim(), validateRequest, diff --git a/backend/src/routes/v2/secret.ts b/backend/src/routes/v2/secret.ts index d9fedda20..1707a927f 100644 --- a/backend/src/routes/v2/secret.ts +++ b/backend/src/routes/v2/secret.ts @@ -1,4 +1,5 @@ import express from "express"; +const router = express.Router(); import { requireAuth, requireSecretAuth, @@ -16,11 +17,9 @@ import { import { CreateSecretRequestBody, ModifySecretRequestBody } from "../../types/secret"; import { secretController } from "../../controllers/v2"; -// note to devs: stop supporting these routes [deprecated] +// note: endpoints deprecated in favor of v3/secrets -const router = express.Router(); - -router.post( +router.post( // TODO endpoint: deprecate (moved to POST api/v3/secrets) "/batch-create/workspace/:workspaceId/environment/:environment", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -38,7 +37,7 @@ router.post( ); router.post( - "/workspace/:workspaceId/environment/:environment", + "/workspace/:workspaceId/environment/:environment", // TODO endpoint: deprecate (moved to POST api/v3/secrets) requireAuth({ acceptedAuthModes: [AuthMode.JWT], }), @@ -54,7 +53,7 @@ router.post( secretController.createSecret ); -router.get( +router.get( // TODO endpoint: deprecate (moved to GET api/v3/secrets) "/workspace/:workspaceId", param("workspaceId").exists().trim(), query("environment").exists(), @@ -70,7 +69,7 @@ router.get( secretController.getSecrets ); -router.get( +router.get( // TODO endpoint: deprecate (moved to POST api/v3/secrets) "/:secretId", requireAuth({ acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN], @@ -83,7 +82,7 @@ router.get( secretController.getSecret ); -router.delete( +router.delete( // TODO endpoint: deprecate (moved to DELETE api/v3/secrets) "/batch/workspace/:workspaceId/environment/:environmentName", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -99,7 +98,7 @@ router.delete( secretController.deleteSecrets ); -router.delete( +router.delete( // TODO endpoint: deprecate (moved to DELETE api/v3/secrets) "/:secretId", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -113,7 +112,7 @@ router.delete( secretController.deleteSecret ); -router.patch( +router.patch( // TODO endpoint: deprecate (moved to PATCH api/v3/secrets) "/batch-modify/workspace/:workspaceId/environment/:environmentName", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -129,7 +128,7 @@ router.patch( secretController.updateSecrets ); -router.patch( +router.patch( // TODO endpoint: deprecate (moved to PATCH api/v3/secrets) "/workspace/:workspaceId/environment/:environmentName", requireAuth({ acceptedAuthModes: [AuthMode.JWT], diff --git a/backend/src/routes/v2/secrets.ts b/backend/src/routes/v2/secrets.ts index 52196e983..cb60035a7 100644 --- a/backend/src/routes/v2/secrets.ts +++ b/backend/src/routes/v2/secrets.ts @@ -21,7 +21,7 @@ import { } from "../../variables"; import { BatchSecretRequest } from "../../types/secret"; -router.post( +router.post( // TODO endpoint: strongly consider deprecation in favor of a single operation experience on dashboard "/batch", requireAuth({ acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN] @@ -56,7 +56,7 @@ router.post( secretsController.batchSecrets ); -router.post( +router.post( // TODO endpoint: deprecate (moved to POST api/v3/secrets) "/", body("workspaceId").exists().isString().trim(), body("environment").exists().isString().trim(), @@ -117,7 +117,7 @@ router.post( secretsController.createSecrets ); -router.get( +router.get( // TODO endpoint: deprecate (moved to GET api/v3/secrets) "/", query("workspaceId").exists().trim(), query("environment").exists().trim(), @@ -138,7 +138,7 @@ router.get( secretsController.getSecrets ); -router.patch( +router.patch( // TODO endpoint: deprecate (moved to PATCH api/v3/secrets) "/", body("secrets") .exists() @@ -173,7 +173,7 @@ router.patch( secretsController.updateSecrets ); -router.delete( +router.delete( // TODO endpoint: deprecate (moved to DELETE api/v3/secrets) "/", body("secretIds") .exists() diff --git a/backend/src/routes/v2/serviceAccounts.ts b/backend/src/routes/v2/serviceAccounts.ts index daf048a23..85b7c9350 100644 --- a/backend/src/routes/v2/serviceAccounts.ts +++ b/backend/src/routes/v2/serviceAccounts.ts @@ -1,5 +1,8 @@ import express from "express"; const router = express.Router(); + +// TODO endpoint: deprecate all + // import { // requireAuth, // requireOrganizationAuth, diff --git a/backend/src/routes/v2/signup.ts b/backend/src/routes/v2/signup.ts index cc701b034..eb376f56c 100644 --- a/backend/src/routes/v2/signup.ts +++ b/backend/src/routes/v2/signup.ts @@ -6,7 +6,7 @@ import { signupController } from "../../controllers/v2"; import { authLimiter } from "../../helpers/rateLimiter"; router.post( - "/complete-account/signup", + "/complete-account/signup", // TODO endpoint: deprecate (moved to v3/signup/complete/account-signup) authLimiter, requireSignupAuth, body("email").exists().isString().trim().notEmpty().isEmail(), @@ -27,7 +27,7 @@ router.post( ); router.post( - "/complete-account/invite", + "/complete-account/invite", // TODO: consider moving to v3/users/new/complete-account/invite authLimiter, requireSignupAuth, body("email").exists().isString().trim().notEmpty().isEmail(), diff --git a/backend/src/routes/v2/workspace.ts b/backend/src/routes/v2/workspace.ts index 77ed75eb1..fde41d945 100644 --- a/backend/src/routes/v2/workspace.ts +++ b/backend/src/routes/v2/workspace.ts @@ -14,7 +14,7 @@ import { } from "../../variables"; import { workspaceController } from "../../controllers/v2"; -router.post( +router.post( // TODO endpoint: deprecate (moved to POST v3/secrets) "/:workspaceId/secrets", requireAuth({ acceptedAuthModes: [AuthMode.JWT], @@ -32,7 +32,7 @@ router.post( workspaceController.pushWorkspaceSecrets ); -router.get( +router.get( // TODO endpoint: deprecate (moved to GET v3/secrets) "/:workspaceId/secrets", requireAuth({ acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN], @@ -48,7 +48,7 @@ router.get( workspaceController.pullSecrets ); -router.get( +router.get( // TODO endpoint: consider moving to v3/users/me/workspaces/:workspaceId/key "/:workspaceId/encrypted-key", requireAuth({ acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY], diff --git a/backend/src/routes/v3/signup.ts b/backend/src/routes/v3/signup.ts index 52b3a8fa0..bfd0c9c4d 100644 --- a/backend/src/routes/v3/signup.ts +++ b/backend/src/routes/v3/signup.ts @@ -6,7 +6,7 @@ import { authLimiter } from "../../helpers/rateLimiter"; import { validateRequest } from "../../middleware"; router.post( - "/complete-account/signup", + "/complete-account/signup", // TODO: consider moving endpoint to v3/users/new/complete-account/signup authLimiter, body("email").exists().isString().trim().notEmpty().isEmail(), body("firstName").exists().isString().trim().notEmpty(), diff --git a/frontend/src/components/basic/dialog/AddIncidentContactDialog.tsx b/frontend/src/components/basic/dialog/AddIncidentContactDialog.tsx deleted file mode 100644 index e3e8acaa1..000000000 --- a/frontend/src/components/basic/dialog/AddIncidentContactDialog.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { Fragment, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { Dialog, Transition } from "@headlessui/react"; - -import addIncidentContact from "@app/pages/api/organization/addIncidentContact"; - -import Button from "../buttons/Button"; -import InputField from "../InputField"; - -type Props = { - isOpen: boolean; - closeModal: () => void; - incidentContacts: string[]; - setIncidentContacts: (arg: string[]) => void; -}; - -const AddIncidentContactDialog = ({ - isOpen, - closeModal, - incidentContacts, - setIncidentContacts -}: Props) => { - const [incidentContactEmail, setIncidentContactEmail] = useState(""); - const { t } = useTranslation(); - - const submit = () => { - setIncidentContacts( - incidentContacts?.length > 0 - ? incidentContacts.concat([incidentContactEmail]) - : [incidentContactEmail] - ); - addIncidentContact(localStorage.getItem("orgData.id") as string, incidentContactEmail); - closeModal(); - }; - return ( -
- - - -
- - -
-
- - - - {t("section.incident.add-dialog.title")} - -
-

- {t("section.incident.add-dialog.description")} -

-
-
- -
-
-
-
-
-
-
-
-
-
- ); -}; - -export default AddIncidentContactDialog; diff --git a/frontend/src/components/basic/dialog/AddServiceTokenDialog.tsx b/frontend/src/components/basic/dialog/AddServiceTokenDialog.tsx deleted file mode 100644 index 7e7c389d8..000000000 --- a/frontend/src/components/basic/dialog/AddServiceTokenDialog.tsx +++ /dev/null @@ -1,271 +0,0 @@ -import crypto from "crypto"; - -import { Fragment, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Dialog, Transition } from "@headlessui/react"; - -import addServiceToken from "@app/pages/api/serviceToken/addServiceToken"; -import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey"; - -import { decryptAssymmetric, encryptSymmetric } from "../../utilities/cryptography/crypto"; -import Button from "../buttons/Button"; -import InputField from "../InputField"; -import ListBox from "../Listbox"; - -const expiryMapping = { - "1 day": 86400, - "7 days": 604800, - "1 month": 2592000, - "6 months": 15552000, - "12 months": 31104000 -}; - -type Props = { - isOpen: boolean; - closeModal: () => void; - workspaceId: string; - workspaceName: string; - serviceTokens: any[]; - environments: Array<{ name: string; slug: string }>; - setServiceTokens: (arg: any[]) => void; -}; - -const AddServiceTokenDialog = ({ - isOpen, - closeModal, - workspaceId, - workspaceName, - serviceTokens, - environments, - setServiceTokens -}: Props) => { - const [serviceToken, setServiceToken] = useState(""); - const [serviceTokenName, setServiceTokenName] = useState(""); - const [selectedServiceTokenEnv, setSelectedServiceTokenEnv] = useState(environments?.[0]); - const [serviceTokenExpiresIn, setServiceTokenExpiresIn] = useState("1 day"); - const [serviceTokenCopied, setServiceTokenCopied] = useState(false); - const { t } = useTranslation(); - - const generateServiceToken = async () => { - const latestFileKey = await getLatestFileKey({ workspaceId }); - - const key = decryptAssymmetric({ - ciphertext: latestFileKey.latestKey.encryptedKey, - nonce: latestFileKey.latestKey.nonce, - publicKey: latestFileKey.latestKey.sender.publicKey, - privateKey: localStorage.getItem("PRIVATE_KEY") as string - }); - - const randomBytes = crypto.randomBytes(16).toString("hex"); - const { ciphertext, iv, tag } = encryptSymmetric({ - plaintext: key, - key: randomBytes - }); - - console.log( - 1234, - selectedServiceTokenEnv, - environments, - selectedServiceTokenEnv?.slug ? selectedServiceTokenEnv.slug : environments[0]?.slug - ); - const newServiceToken = await addServiceToken({ - name: serviceTokenName, - workspaceId, - environment: selectedServiceTokenEnv?.slug - ? selectedServiceTokenEnv.slug - : environments[0]?.slug, - expiresIn: expiryMapping[serviceTokenExpiresIn as keyof typeof expiryMapping], - encryptedKey: ciphertext, - iv, - tag - }); - - setServiceTokens(serviceTokens.concat([newServiceToken.serviceTokenData])); - setServiceToken(`${newServiceToken.serviceToken}.${randomBytes}`); - }; - - function copyToClipboard() { - // Get the text field - const copyText = document.getElementById("serviceToken") as HTMLInputElement; - - // Select the text field - copyText.select(); - copyText.setSelectionRange(0, 99999); // For mobile devices - - // Copy the text inside the text field - navigator.clipboard.writeText(copyText.value); - - setServiceTokenCopied(true); - setTimeout(() => setServiceTokenCopied(false), 2000); - // Alert the copied text - // alert("Copied the text: " + copyText.value); - } - - const closeAddServiceTokenModal = () => { - closeModal(); - setServiceTokenName(""); - setServiceToken(""); - }; - - return ( -
- - - -
- - -
-
- - {serviceToken === "" ? ( - - - {t("section.token.add-dialog.title", { - target: workspaceName - })} - -
-
-

- {t("section.token.add-dialog.description")} -

-
-
-
- -
-
- name)} - onChange={(envName) => - setSelectedServiceTokenEnv( - environments.find(({ name }) => envName === name) || { - name: "unknown", - slug: "unknown" - } - ) - } - isFull - text={`${t("common.environment")}: `} - /> -
-
- -
-
-
-
-
-
- ) : ( - - - {t("section.token.add-dialog.copy-service-token")} - -
-
-

- {t("section.token.add-dialog.copy-service-token-description")} -

-
-
-
-
- -
- {serviceToken} -
-
- - - {t("common.click-to-copy")} - -
-
-
-
-
-
- )} -
-
-
-
-
-
- ); -}; - -export default AddServiceTokenDialog; diff --git a/frontend/src/components/basic/table/EnvironmentsTable.tsx b/frontend/src/components/basic/table/EnvironmentsTable.tsx deleted file mode 100644 index b9c94534a..000000000 --- a/frontend/src/components/basic/table/EnvironmentsTable.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import { useEffect, useState } from "react"; -import { faPencil, faPlus, faX } from "@fortawesome/free-solid-svg-icons"; -import { plans } from "public/data/frequentConstants"; - -import { usePopUp } from "../../../hooks/usePopUp"; -import getOrganizationSubscriptions from "../../../pages/api/organization/GetOrgSubscription"; -import Button from "../buttons/Button"; -import { AddUpdateEnvironmentDialog } from "../dialog/AddUpdateEnvironmentDialog"; -import DeleteActionModal from "../dialog/DeleteActionModal"; -import UpgradePlanModal from "../dialog/UpgradePlan"; - -type Env = { name: string; slug: string }; - -type Props = { - data: Env[]; - onCreateEnv: (arg0: Env) => Promise; - onUpdateEnv: (oldSlug: string, arg0: Env) => Promise; - onDeleteEnv: (slug: string) => Promise; -}; - -const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }: Props) => { - const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([ - "createUpdateEnv", - "deleteEnv", - "upgradePlan" - ] as const); - const [plan, setPlan] = useState(""); - const host = window.location.origin; - - useEffect(() => { - // on initial load - run auth check - (async () => { - const orgId = localStorage.getItem("orgData.id") as string; - const subscriptions = await getOrganizationSubscriptions({ - orgId - }); - if (subscriptions) { - setPlan(subscriptions.data[0].plan.product) - } - })(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const onEnvCreateCB = async (env: Env) => { - try { - await onCreateEnv(env); - handlePopUpClose("createUpdateEnv"); - } catch (error) { - console.error(error); - } - }; - - const onEnvUpdateCB = async (env: Env) => { - try { - await onUpdateEnv((popUp.createUpdateEnv?.data as Pick)?.slug, env); - handlePopUpClose("createUpdateEnv"); - } catch (error) { - console.error(error); - } - }; - - const onEnvDeleteCB = async () => { - try { - await onDeleteEnv((popUp.deleteEnv?.data as Pick)?.slug); - handlePopUpClose("deleteEnv"); - } catch (error) { - console.error(error); - } - }; - - return ( - <> -
-
-

Project Environments

-

- Choose which environments will show up in your dashboard like development, staging, - production -

-

- Note: the text in slugs shows how these environmant should be accessed in CLI. -

-
-
-
-
-
-
- - - - - - - - - {data?.length > 0 ? ( - data.map(({ name, slug }) => ( - - - - - - )) - ) : ( - - - - )} - -
NameSlug -
{name}{slug} -
-
-
-
-
- No environments found -
- handlePopUpClose("deleteEnv")} - onSubmit={onEnvDeleteCB} - /> - handlePopUpClose("createUpdateEnv")} - onCreateSubmit={onEnvCreateCB} - onEditSubmit={onEnvUpdateCB} - /> - handlePopUpClose("upgradePlan")} - text="You can add custom environments if you switch to Infisical's Team plan." - /> -
- - ); -}; - -export default EnvironmentTable; diff --git a/frontend/src/components/basic/table/ProjectUsersTable.tsx b/frontend/src/components/basic/table/ProjectUsersTable.tsx index 022eda020..5838aaf41 100644 --- a/frontend/src/components/basic/table/ProjectUsersTable.tsx +++ b/frontend/src/components/basic/table/ProjectUsersTable.tsx @@ -4,13 +4,13 @@ import { faEye, faEyeSlash, faPenToSquare, faPlus, faX } from "@fortawesome/free import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { Select, SelectItem } from "@app/components/v2"; -import { useSubscription } from "@app/context"; +import { useSubscription, useWorkspace } from "@app/context"; import updateUserProjectPermission from "@app/ee/api/memberships/UpdateUserProjectPermission"; -import changeUserRoleInWorkspace from "@app/pages/api/workspace/changeUserRoleInWorkspace"; -import deleteUserFromWorkspace from "@app/pages/api/workspace/deleteUserFromWorkspace"; -import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey"; -import getProjectInfo from "@app/pages/api/workspace/getProjectInfo"; -import uploadKeys from "@app/pages/api/workspace/uploadKeys"; +import { + useDeleteUserFromWorkspace, + useGetUserWsKey, + useUpdateUserWorkspaceRole, + useUploadWsKey} from "@app/hooks/api"; import { decryptAssymmetric, encryptAssymmetric } from "../../utilities/cryptography/crypto"; import guidGenerator from "../../utilities/randomId"; @@ -39,10 +39,16 @@ type EnvironmentProps = { * @returns */ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoading }: Props) => { + const { currentWorkspace } = useWorkspace(); const { subscription } = useSubscription(); - const [roleSelected, setRoleSelected] = useState( - Array(userData?.length).fill(userData.map((user) => user.role)) - ); + const { data: wsKey } = useGetUserWsKey(currentWorkspace?._id ?? ""); + + const { mutateAsync: deleteUserFromWorkspaceMutateAsync } = useDeleteUserFromWorkspace(); + const { mutateAsync: uploadWsKeyMutateAsync } = useUploadWsKey(); + const { mutateAsync: updateUserWorkspaceRoleMutateAsync } = useUpdateUserWorkspaceRole(); + // const [roleSelected, setRoleSelected] = useState( + // Array(userData?.length).fill(userData.map((user) => user.role)) + // ); const router = useRouter(); const [myRole, setMyRole] = useState("member"); const [workspaceEnvs, setWorkspaceEnvs] = useState([]); @@ -52,38 +58,15 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa const workspaceId = router.query.id as string; // Delete the row in the table (e.g. a user) // #TODO: Add a pop-up that warns you that the user is going to be deleted. - const handleDelete = (membershipId: string, index: number) => { - // setUserIdToBeDeleted(userId); - // onClick(); - deleteUserFromWorkspace(membershipId); - changeData(userData.filter((v, i) => i !== index)); - setRoleSelected([ - ...roleSelected.slice(0, index), - ...roleSelected.slice(index + 1, userData?.length) - ]); + const handleDelete = async (membershipId: string) => { + await deleteUserFromWorkspaceMutateAsync(membershipId); }; - // Update the rold of a certain user - const handleRoleUpdate = (index: number, e: string) => { - changeUserRoleInWorkspace(userData[index].membershipId, e.toLowerCase()); - changeData([ - ...userData.slice(0, index), - ...[ - { - key: userData[index].key, - firstName: userData[index].firstName, - lastName: userData[index].lastName, - email: userData[index].email, - role: e.toLocaleLowerCase(), - status: userData[index].status, - userId: userData[index].userId, - membershipId: userData[index].membershipId, - publicKey: userData[index].publicKey, - deniedPermissions: userData[index].deniedPermissions - } - ], - ...userData.slice(index + 1, userData?.length) - ]); + const handleRoleUpdate = async (index: number, e: string) => { + await updateUserWorkspaceRoleMutateAsync({ + membershipId: userData[index].membershipId, + role: e.toLowerCase() + }); createNotification({ text: "Successfully changed user role.", type: "success" @@ -163,32 +146,38 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa useEffect(() => { setMyRole(userData.filter((user) => user.email === myUser)[0]?.role); (async () => { - const result = await getProjectInfo({ projectId: workspaceId }); - setWorkspaceEnvs(result.environments); + if (currentWorkspace) { + setWorkspaceEnvs(currentWorkspace.environments); + } })(); - }, [userData, myUser]); + }, [userData, myUser, currentWorkspace]); const grantAccess = async (id: string, publicKey: string) => { - const result = await getLatestFileKey({ workspaceId }); + if (wsKey) { + const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string; - const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string; + // assymmetrically decrypt symmetric key with local private key + const key = decryptAssymmetric({ + ciphertext: wsKey.encryptedKey, + nonce: wsKey.nonce, + publicKey: wsKey.sender.publicKey, + privateKey: PRIVATE_KEY + }); - // assymmetrically decrypt symmetric key with local private key - const key = decryptAssymmetric({ - ciphertext: result.latestKey.encryptedKey, - nonce: result.latestKey.nonce, - publicKey: result.latestKey.sender.publicKey, - privateKey: PRIVATE_KEY - }); + const { ciphertext, nonce } = encryptAssymmetric({ + plaintext: key, + publicKey, + privateKey: PRIVATE_KEY + }); - const { ciphertext, nonce } = encryptAssymmetric({ - plaintext: key, - publicKey, - privateKey: PRIVATE_KEY - }); - - uploadKeys(workspaceId, id, ciphertext, nonce); - router.reload(); + await uploadWsKeyMutateAsync({ + workspaceId, + userId: id, + encryptedKey: ciphertext, + nonce + }); + router.reload(); + } }; const closeUpgradeModal = () => { @@ -372,7 +361,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa myRole !== "member" ? (
-
-
-
- - ); -}; - -export default SideBar; diff --git a/frontend/src/components/integrations/CloudIntegration.tsx b/frontend/src/components/integrations/CloudIntegration.tsx deleted file mode 100644 index 0fa5f4cf3..000000000 --- a/frontend/src/components/integrations/CloudIntegration.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import Image from "next/image"; -import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -import deleteIntegrationAuth from "../../pages/api/integrations/DeleteIntegrationAuth"; - -interface IntegrationOption { - clientId: string; - clientSlug?: string; // vercel-integration specific - docsLink: string; - image: string; - isAvailable: boolean; - name: string; - slug: string; - type: string; -} -interface IntegrationAuth { - _id: string; - integration: string; - workspace: string; - createdAt: string; - updatedAt: string; -} - -interface Props { - cloudIntegrationOption: IntegrationOption; - setSelectedIntegrationOption: (cloudIntegration: IntegrationOption) => void; - integrationOptionPress: (cloudIntegrationOption: IntegrationOption) => void; - integrationAuths: IntegrationAuth[]; - handleDeleteIntegrationAuth: (args: { integrationAuth: IntegrationAuth }) => void; -} - -const CloudIntegration = ({ - cloudIntegrationOption, - setSelectedIntegrationOption, - integrationOptionPress, - integrationAuths, - handleDeleteIntegrationAuth -}: Props) => { - return integrationAuths ? ( -
null} - role="button" - tabIndex={0} - className={`relative ${ - cloudIntegrationOption.isAvailable - ? "cursor-pointer duration-200 hover:bg-mineshaft-700" - : "opacity-50" - } flex h-32 flex-row items-center rounded-md bg-mineshaft-800 border border-mineshaft-600 p-4`} - onClick={() => { - if (!cloudIntegrationOption.isAvailable) return; - setSelectedIntegrationOption(cloudIntegrationOption); - integrationOptionPress(cloudIntegrationOption); - }} - key={cloudIntegrationOption.name} - > - integration logo - {cloudIntegrationOption.name.split(" ").length > 2 ? ( -
-
{cloudIntegrationOption.name.split(" ")[0]}
-
- {cloudIntegrationOption.name.split(" ")[1]} {cloudIntegrationOption.name.split(" ")[2]} -
-
- ) : ( -
- {cloudIntegrationOption.name} -
- )} - {cloudIntegrationOption.isAvailable && - integrationAuths - .map((authorization) => authorization?.integration) - .includes(cloudIntegrationOption.slug) && ( -
-
null} - role="button" - tabIndex={0} - onClick={async (event) => { - event.stopPropagation(); - const deletedIntegrationAuth = await deleteIntegrationAuth({ - integrationAuthId: integrationAuths - .filter( - (authorization) => authorization.integration === cloudIntegrationOption.slug - ) - .map((authorization) => authorization._id)[0] - }); - - handleDeleteIntegrationAuth({ - integrationAuth: deletedIntegrationAuth - }); - }} - className="flex w-max cursor-pointer flex-row items-center rounded-bl-md bg-red py-0.5 px-2 text-xs opacity-30 duration-200 group-hover:opacity-100" - > - - Revoke -
-
- - Authorized -
-
- )} - {!cloudIntegrationOption.isAvailable && ( -
-
- Coming Soon -
-
- )} -
- ) : ( -
- ); -}; - -export default CloudIntegration; diff --git a/frontend/src/components/integrations/CloudIntegrationSection.tsx b/frontend/src/components/integrations/CloudIntegrationSection.tsx deleted file mode 100644 index 841d6c215..000000000 --- a/frontend/src/components/integrations/CloudIntegrationSection.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { useTranslation } from "react-i18next"; - -import CloudIntegration from "./CloudIntegration"; - -interface IntegrationOption { - clientId: string; - clientSlug?: string; // vercel-integration specific - docsLink: string; - image: string; - isAvailable: boolean; - name: string; - slug: string; - type: string; -} - -interface IntegrationAuth { - _id: string; - integration: string; - workspace: string; - createdAt: string; - updatedAt: string; -} - -interface Props { - cloudIntegrationOptions: IntegrationOption[]; - setSelectedIntegrationOption: () => void; - integrationOptionPress: (integrationOption: IntegrationOption) => void; - integrationAuths: IntegrationAuth[]; - handleDeleteIntegrationAuth: (args: { integrationAuth: IntegrationAuth }) => void; -} - -const CloudIntegrationSection = ({ - cloudIntegrationOptions, - setSelectedIntegrationOption, - integrationOptionPress, - integrationAuths, - handleDeleteIntegrationAuth -}: Props) => { - const { t } = useTranslation(); - - return ( - <> -
-

{t("integrations.cloud-integrations")}

-

{t("integrations.click-to-start")}

-
-
- {cloudIntegrationOptions.map((cloudIntegrationOption) => ( - - ))} -
- - ); -}; - -export default CloudIntegrationSection; diff --git a/frontend/src/components/integrations/FrameworkIntegration.tsx b/frontend/src/components/integrations/FrameworkIntegration.tsx deleted file mode 100644 index b76639800..000000000 --- a/frontend/src/components/integrations/FrameworkIntegration.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import Image from "next/image"; - -interface Framework { - name: string; - slug: string; - image: string; - docsLink: string; -} - -const FrameworkIntegration = ({ framework }: { framework: Framework }) => ( - -
1 ? "text-sm px-1" : "text-xl px-2" - } text-center w-full max-w-xs`} - > - {framework?.image && ( - integration logo - )} - {framework?.name && framework?.image &&
} - {framework?.name && framework.name} -
-
-); - -export default FrameworkIntegration; diff --git a/frontend/src/components/integrations/FrameworkIntegrationSection.tsx b/frontend/src/components/integrations/FrameworkIntegrationSection.tsx deleted file mode 100644 index 78e2bf59a..000000000 --- a/frontend/src/components/integrations/FrameworkIntegrationSection.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useTranslation } from "react-i18next"; - -import FrameworkIntegration from "./FrameworkIntegration"; - -interface Framework { - name: string; - image: string; - link: string; - slug: string; - docsLink: string; -} - -interface Props { - frameworks: [Framework]; -} - -const FrameworkIntegrationSection = ({ frameworks }: Props) => { - const { t } = useTranslation(); - - return ( - <> -
-

{t("integrations.framework-integrations")}

-

{t("integrations.click-to-setup")}

-
-
- {frameworks.map((framework) => ( - - ))} -
- - ); -}; - -export default FrameworkIntegrationSection; diff --git a/frontend/src/components/integrations/Integration.tsx b/frontend/src/components/integrations/Integration.tsx deleted file mode 100644 index 34d006847..000000000 --- a/frontend/src/components/integrations/Integration.tsx +++ /dev/null @@ -1,313 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { useEffect, useState } from "react"; -import { useRouter } from "next/router"; -import { faArrowRight, faCheck, faXmark } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -// TODO: This needs to be moved from public folder -import { - contextNetlifyMapping, - integrationSlugNameMapping, - reverseContextNetlifyMapping -} from "public/data/frequentConstants"; - -import Button from "@app/components/basic/buttons/Button"; -import ListBox from "@app/components/basic/Listbox"; - -import deleteIntegration from "../../pages/api/integrations/DeleteIntegration"; -import getIntegrationApps from "../../pages/api/integrations/GetIntegrationApps"; -import updateIntegration from "../../pages/api/integrations/updateIntegration"; - -interface Integration { - _id: string; - isActive: boolean; - app: string | null; - appId: string | null; - path: string | null; - region: string | null; - createdAt: string; - updatedAt: string; - environment: string; - integration: string; - targetEnvironment: string; - workspace: string; - integrationAuth: string; - secretPath: string; -} - -interface IntegrationApp { - name: string; - appId?: string; - owner?: string; -} - -type Props = { - integration: Integration; - integrations: Integration[]; - setIntegrations: any; - bot: any; - setBot: any; - environments: Array<{ name: string; slug: string }>; - handleDeleteIntegration: (args: { integration: Integration }) => void; -}; - -// TODO: refactor -const IntegrationTile = ({ - integration, - integrations, - bot, - setBot, - setIntegrations, - environments = [], - handleDeleteIntegration -}: Props) => { - const [integrationEnvironment, setIntegrationEnvironment] = useState( - environments.find(({ slug }) => slug === integration?.environment) || { - name: "", - slug: "" - } - ); - const router = useRouter(); - const [apps, setApps] = useState([]); // integration app objects - const [integrationApp, setIntegrationApp] = useState(""); // integration app name - const [integrationTargetEnvironment, setIntegrationTargetEnvironment] = useState(""); - - useEffect(() => { - const loadIntegration = async () => { - const tempApps: [IntegrationApp] = await getIntegrationApps({ - integrationAuthId: integration?.integrationAuth - }); - - setApps(tempApps); - - if (integration?.app) { - setIntegrationApp(integration.app); - } else if (integration?.path && integration?.region) { - setIntegrationApp(`${integration.path} (${integration.region})`); - } else if (tempApps.length > 0) { - setIntegrationApp(tempApps[0].name); - } else { - setIntegrationApp(""); - } - - switch (integration.integration) { - case "vercel": - setIntegrationTargetEnvironment( - integration?.targetEnvironment - ? integration.targetEnvironment.charAt(0).toUpperCase() + - integration.targetEnvironment.substring(1) - : "Development" - ); - break; - case "netlify": - setIntegrationTargetEnvironment( - integration?.targetEnvironment - ? contextNetlifyMapping[integration.targetEnvironment] - : "Local development" - ); - break; - default: - break; - } - }; - - loadIntegration(); - }, []); - - const handleStartIntegration = async () => { - const reformatTargetEnvironment = (targetEnvironment: string) => { - switch (integration.integration) { - case "vercel": - return targetEnvironment.toLowerCase(); - case "netlify": - return reverseContextNetlifyMapping[targetEnvironment]; - default: - return null; - } - }; - - try { - const siteApp = apps.find((app) => app.name === integrationApp); // obj or undefined - const appId = siteApp?.appId ?? null; - const owner = siteApp?.owner ?? null; - - // return updated integration - const updatedIntegration = await updateIntegration({ - integrationId: integration._id, - environment: integrationEnvironment.slug, - isActive: true, - app: integrationApp, - appId, - targetEnvironment: reformatTargetEnvironment(integrationTargetEnvironment), - owner - }); - - setIntegrations( - integrations.map((i) => (i._id === updatedIntegration._id ? updatedIntegration : i)) - ); - } catch (err) { - console.error(err); - } - }; - - // eslint-disable-next-line @typescript-eslint/no-shadow - const renderIntegrationSpecificParams = (integration: Integration) => { - try { - switch (integration.integration) { - case "vercel": - return ( -
-
ENVIRONMENT
- -
- ); - case "netlify": - return ( -
-
CONTEXT
- -
- ); - case "railway": - return ( -
-
ENVIRONMENT
- -
- ); - case "gitlab": - return ( -
-
ENVIRONMENT
- -
- ); - default: - return
; - } - } catch (err) { - console.error(err); - } - - return
; - }; - - if (!integrationApp && integration.integration !== "checkly") return
; - - const isSelected = - integration.integration === "hashicorp-vault" - ? `${integration.app} - path: ${integration.path}` - : integrationApp; - - return ( -
-
-
-

ENVIRONMENT

- name) : null} - isSelected={integrationEnvironment.name} - onChange={(envName) => - setIntegrationEnvironment( - environments.find(({ name }) => envName === name) || { - name: "unknown", - slug: "unknown" - } - ) - } - isFull - /> -
-
-

SECRET PATH

-
- {/* {integration.integration.charAt(0).toUpperCase() + integration.integration.slice(1)} */} - {integration.secretPath} -
-
-
- -
-
-

INTEGRATION

-
- {/* {integration.integration.charAt(0).toUpperCase() + integration.integration.slice(1)} */} - {integrationSlugNameMapping[integration.integration]} -
-
-
-
APP
- {integrationApp ? ( -
- app.name) : null} - isSelected={isSelected} - onChange={(app) => { - setIntegrationApp(app); - }} - /> -
- ) : ( -
- - -
- )} -
- {renderIntegrationSpecificParams(integration)} -
-
- {integration.isActive ? ( -
- -
In Sync
-
- ) : ( -
-
-
- ); -}; - -export default IntegrationTile; diff --git a/frontend/src/components/integrations/IntegrationSection.tsx b/frontend/src/components/integrations/IntegrationSection.tsx deleted file mode 100644 index 8ff114e35..000000000 --- a/frontend/src/components/integrations/IntegrationSection.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import IntegrationTile from "./Integration"; - -interface Props { - integrations: any; - setIntegrations: any; - bot: any; - setBot: any; - environments: Array<{ name: string; slug: string }>; - handleDeleteIntegration: (args: { integration: Integration }) => void; -} - -interface Integration { - _id: string; - isActive: boolean; - app: string | null; - appId: string | null; - path: string | null; - region: string | null; - createdAt: string; - updatedAt: string; - environment: string; - integration: string; - targetEnvironment: string; - workspace: string; - integrationAuth: string; - secretPath: string; -} - -const ProjectIntegrationSection = ({ - integrations, - setIntegrations, - bot, - setBot, - environments = [], - handleDeleteIntegration -}: Props) => { - return integrations.length > 0 ? ( -
-
-

Current Integrations

-

Manage integrations with third-party services.

-
- {integrations.map((integration: Integration) => { - return ( - - ); - })} -
- ) : ( -
- ); -}; - -export default ProjectIntegrationSection; diff --git a/frontend/src/components/signup/CodeInputStep.tsx b/frontend/src/components/signup/CodeInputStep.tsx index 7f6c75871..de831bbd2 100644 --- a/frontend/src/components/signup/CodeInputStep.tsx +++ b/frontend/src/components/signup/CodeInputStep.tsx @@ -3,7 +3,9 @@ import React, { useState } from "react"; import ReactCodeInput from "react-code-input"; import { useTranslation } from "react-i18next"; -import sendVerificationEmail from "@app/pages/api/auth/SendVerificationEmail"; +import { + useSendVerificationEmail +} from "@app/hooks/api"; import Error from "../basic/Error"; import { Button } from "../v2"; @@ -70,6 +72,7 @@ export default function CodeInputStep({ codeError, isCodeInputCheckLoading }: CodeInputStepProps): JSX.Element { + const { mutateAsync } = useSendVerificationEmail(); const [isLoading, setIsLoading] = useState(false); const [isResendingVerificationEmail, setIsResendingVerificationEmail] = useState(false); const { t } = useTranslation(); @@ -77,7 +80,7 @@ export default function CodeInputStep({ const resendVerificationEmail = async () => { setIsResendingVerificationEmail(true); setIsLoading(true); - sendVerificationEmail(email); + await mutateAsync({ email }); setTimeout(() => { setIsLoading(false); setIsResendingVerificationEmail(false); diff --git a/frontend/src/components/signup/EnterEmailStep.tsx b/frontend/src/components/signup/EnterEmailStep.tsx index 479c88318..e317a4ea5 100644 --- a/frontend/src/components/signup/EnterEmailStep.tsx +++ b/frontend/src/components/signup/EnterEmailStep.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import Link from "next/link"; -import sendVerificationEmail from "@app/pages/api/auth/SendVerificationEmail"; +import { useSendVerificationEmail } from "@app/hooks/api"; import { Button, Input } from "../v2"; @@ -25,13 +25,14 @@ export default function EnterEmailStep({ setEmail, incrementStep }: DownloadBackupPDFStepProps): JSX.Element { + const { mutateAsync } = useSendVerificationEmail(); const [emailError, setEmailError] = useState(false); const { t } = useTranslation(); /** * Verifies if the entered email "looks" correct */ - const emailCheck = () => { + const emailCheck = async () => { let emailCheckBool = false; if (!email) { setEmailError(true); @@ -45,7 +46,7 @@ export default function EnterEmailStep({ // If everything is correct, go to the next step if (!emailCheckBool) { - sendVerificationEmail(email); + await mutateAsync({ email }); incrementStep(); } }; diff --git a/frontend/src/components/signup/TeamInviteStep.tsx b/frontend/src/components/signup/TeamInviteStep.tsx index 398ccd78d..d1cc6ef7d 100644 --- a/frontend/src/components/signup/TeamInviteStep.tsx +++ b/frontend/src/components/signup/TeamInviteStep.tsx @@ -2,9 +2,9 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { useRouter } from "next/router"; +import { useAddUserToOrg } from "@app/hooks/api"; import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; import { usePopUp } from "@app/hooks/usePopUp"; -import addUserToOrg from "@app/pages/api/organization/addUserToOrg"; import { Button, EmailServiceSetupModal } from "../v2"; @@ -12,10 +12,12 @@ import { Button, EmailServiceSetupModal } from "../v2"; * This is the last step of the signup flow. People can optionally invite their teammates here. */ export default function TeamInviteStep(): JSX.Element { - const [emails, setEmails] = useState(""); const { t } = useTranslation(); const router = useRouter(); + const [emails, setEmails] = useState(""); const { data: serverDetails } = useFetchServerStatus(); + + const { mutateAsync } = useAddUserToOrg(); const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp(["setUpEmail"] as const); // Redirect user to the getting started page @@ -27,7 +29,12 @@ export default function TeamInviteStep(): JSX.Element { inviteEmails .split(",") .map((email) => email.trim()) - .map(async (email) => addUserToOrg(email, String(localStorage.getItem("orgData.id")))); + .map(async (email) => { + mutateAsync({ + inviteeEmail: email, + organizationId: String(localStorage.getItem("orgData.id")) + }); + }); await redirectToHome(); }; diff --git a/frontend/src/components/signup/UserInfoStep.tsx b/frontend/src/components/signup/UserInfoStep.tsx index e0d99548a..db4d040ad 100644 --- a/frontend/src/components/signup/UserInfoStep.tsx +++ b/frontend/src/components/signup/UserInfoStep.tsx @@ -9,8 +9,8 @@ import nacl from "tweetnacl"; import { encodeBase64 } from "tweetnacl-util"; import { useGetCommonPasswords } from "@app/hooks/api"; -import completeAccountInformationSignup from "@app/pages/api/auth/CompleteAccountInformationSignup"; -import getOrganizations from "@app/pages/api/organization/getOrgs"; +import { completeAccountSignup } from "@app/hooks/api/auth/queries"; +import { fetchOrganizations } from "@app/hooks/api/organization/queries"; import ProjectService from "@app/services/ProjectService"; import InputField from "../basic/InputField"; @@ -159,7 +159,7 @@ export default function UserInfoStep({ secret: Buffer.from(derivedKey.hash) }); - const response = await completeAccountInformationSignup({ + const response = await completeAccountSignup({ email, firstName: name.split(" ")[0], lastName: name.split(" ").slice(1).join(" "), @@ -190,7 +190,8 @@ export default function UserInfoStep({ privateKey }); - const userOrgs = await getOrganizations(); + const userOrgs = await fetchOrganizations(); + const orgId = userOrgs[0]?._id; const project = await ProjectService.initProject({ organizationId: orgId, diff --git a/frontend/src/components/utilities/attemptChangePassword.ts b/frontend/src/components/utilities/attemptChangePassword.ts index 5b42e0190..59363129f 100644 --- a/frontend/src/components/utilities/attemptChangePassword.ts +++ b/frontend/src/components/utilities/attemptChangePassword.ts @@ -3,8 +3,9 @@ import crypto from "crypto"; import jsrp from "jsrp"; -import changePassword2 from "@app/pages/api/auth/ChangePassword2"; -import SRP1 from "@app/pages/api/auth/SRP1"; +import { +changePassword, + srp1} from "@app/hooks/api/auth/queries"; import Aes256Gcm from "./cryptography/aes-256-gcm"; import { deriveArgonKey } from "./cryptography/crypto"; @@ -27,7 +28,7 @@ const attemptChangePassword = ({ email, currentPassword, newPassword }: Params): try { const clientPublicKey = clientOldPassword.getPublicKey(); - const res = await SRP1({ clientPublicKey }); + const res = await srp1({ clientPublicKey }); serverPublicKey = res.serverPublicKey; salt = res.salt; @@ -71,7 +72,7 @@ const attemptChangePassword = ({ email, currentPassword, newPassword }: Params): secret: Buffer.from(derivedKey.hash) }); - await changePassword2({ + await changePassword({ clientProof, protectedKey, protectedKeyIV, diff --git a/frontend/src/components/utilities/attemptCliLogin.ts b/frontend/src/components/utilities/attemptCliLogin.ts index 099351baa..b2eeeceea 100644 --- a/frontend/src/components/utilities/attemptCliLogin.ts +++ b/frontend/src/components/utilities/attemptCliLogin.ts @@ -1,10 +1,9 @@ /* eslint-disable prefer-destructuring */ import jsrp from "jsrp"; -import login1 from "@app/pages/api/auth/Login1"; -import login2 from "@app/pages/api/auth/Login2"; -import getOrganizations from "@app/pages/api/organization/getOrgs"; -import getOrganizationUserProjects from "@app/pages/api/organization/GetOrgUserProjects"; +import { login1, login2 } from "@app/hooks/api/auth/queries"; +import { fetchOrganizations } from "@app/hooks/api/organization/queries"; +import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries"; import KeyService from "@app/services/KeyService"; import Telemetry from "./telemetry/Telemetry"; @@ -125,13 +124,11 @@ const attemptLogin = async ( privateKey }); - const userOrgs = await getOrganizations(); + const userOrgs = await fetchOrganizations(); const orgId = userOrgs[0]._id; localStorage.setItem("orgData.id", orgId); - const orgUserProjects = await getOrganizationUserProjects({ - orgId - }); + const orgUserProjects = await fetchMyOrganizationProjects(orgId); if (orgUserProjects.length > 0) { localStorage.setItem("projectData.id", orgUserProjects[0]._id); diff --git a/frontend/src/components/utilities/attemptCliLoginMfa.ts b/frontend/src/components/utilities/attemptCliLoginMfa.ts index cb33d3bad..6681e8464 100644 --- a/frontend/src/components/utilities/attemptCliLoginMfa.ts +++ b/frontend/src/components/utilities/attemptCliLoginMfa.ts @@ -1,10 +1,10 @@ /* eslint-disable prefer-destructuring */ import jsrp from "jsrp"; -import login1 from "@app/pages/api/auth/Login1"; -import verifyMfaToken from "@app/pages/api/auth/verifyMfaToken"; -import getOrganizations from "@app/pages/api/organization/getOrgs"; -import getOrganizationUserProjects from "@app/pages/api/organization/GetOrgUserProjects"; +import { login1 , verifyMfaToken } from "@app/hooks/api/auth/queries"; +import { fetchOrganizations } from "@app/hooks/api/organization/queries"; +import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries"; +// import verifyMfaToken from "@app/pages/api/auth/verifyMfaToken"; import KeyService from "@app/services/KeyService"; import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage"; @@ -65,7 +65,7 @@ const attemptLoginMfa = async ({ tag } = await verifyMfaToken({ email, - mfaToken + mfaCode: mfaToken }); // unset temporary (MFA) JWT token and set JWT token @@ -96,13 +96,11 @@ const attemptLoginMfa = async ({ // TODO: in the future - move this logic elsewhere // because this function is about logging the user in // and not initializing the login details - const userOrgs = await getOrganizations(); + const userOrgs = await fetchOrganizations(); const orgId = userOrgs[0]._id; localStorage.setItem("orgData.id", orgId); - const orgUserProjects = await getOrganizationUserProjects({ - orgId - }); + const orgUserProjects = await fetchMyOrganizationProjects(orgId); localStorage.setItem("projectData.id", orgUserProjects[0]._id); resolve({ diff --git a/frontend/src/components/utilities/attemptLogin.ts b/frontend/src/components/utilities/attemptLogin.ts index b3e4b38be..c4fe91b05 100644 --- a/frontend/src/components/utilities/attemptLogin.ts +++ b/frontend/src/components/utilities/attemptLogin.ts @@ -1,10 +1,9 @@ /* eslint-disable prefer-destructuring */ import jsrp from "jsrp"; -import login1 from "@app/pages/api/auth/Login1"; -import login2 from "@app/pages/api/auth/Login2"; -import getOrganizations from "@app/pages/api/organization/getOrgs"; -import getOrganizationUserProjects from "@app/pages/api/organization/GetOrgUserProjects"; +import { login1, login2 } from "@app/hooks/api/auth/queries"; +import { fetchOrganizations } from "@app/hooks/api/organization/queries"; +import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries"; import KeyService from "@app/services/KeyService"; import Telemetry from "./telemetry/Telemetry"; @@ -36,7 +35,6 @@ const attemptLogin = async ( providerAuthToken?: string; } ): Promise => { - const telemetry = new Telemetry().getInstance(); return new Promise((resolve, reject) => { client.init( @@ -47,12 +45,13 @@ const attemptLogin = async ( async () => { try { const clientPublicKey = client.getPublicKey(); + const { serverPublicKey, salt } = await login1({ email, clientPublicKey, providerAuthToken, }); - + client.setSalt(salt); client.setServerPublicKey(serverPublicKey); const clientProof = client.getProof(); // called M1 @@ -124,14 +123,12 @@ const attemptLogin = async ( // TODO: in the future - move this logic elsewhere // because this function is about logging the user in // and not initializing the login details - const userOrgs = await getOrganizations(); + const userOrgs = await fetchOrganizations(); const orgId = userOrgs[0]._id; localStorage.setItem("orgData.id", orgId); - const orgUserProjects = await getOrganizationUserProjects({ - orgId - }); + const orgUserProjects = await fetchMyOrganizationProjects(orgId); if (orgUserProjects.length > 0) { localStorage.setItem("projectData.id", orgUserProjects[0]._id); diff --git a/frontend/src/components/utilities/attemptLoginMfa.ts b/frontend/src/components/utilities/attemptLoginMfa.ts index 967881357..c588eb965 100644 --- a/frontend/src/components/utilities/attemptLoginMfa.ts +++ b/frontend/src/components/utilities/attemptLoginMfa.ts @@ -1,10 +1,9 @@ /* eslint-disable prefer-destructuring */ import jsrp from "jsrp"; -import login1 from "@app/pages/api/auth/Login1"; -import verifyMfaToken from "@app/pages/api/auth/verifyMfaToken"; -import getOrganizations from "@app/pages/api/organization/getOrgs"; -import getOrganizationUserProjects from "@app/pages/api/organization/GetOrgUserProjects"; +import { login1 , verifyMfaToken } from "@app/hooks/api/auth/queries"; +import { fetchOrganizations } from "@app/hooks/api/organization/queries"; +import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries"; import KeyService from "@app/services/KeyService"; import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage"; @@ -56,7 +55,7 @@ const attemptLoginMfa = async ({ tag } = await verifyMfaToken({ email, - mfaToken + mfaCode: mfaToken }); // unset temporary (MFA) JWT token and set JWT token @@ -87,13 +86,11 @@ const attemptLoginMfa = async ({ // TODO: in the future - move this logic elsewhere // because this function is about logging the user in // and not initializing the login details - const userOrgs = await getOrganizations(); + const userOrgs = await fetchOrganizations(); const orgId = userOrgs[0]._id; localStorage.setItem("orgData.id", orgId); - const orgUserProjects = await getOrganizationUserProjects({ - orgId - }); + const orgUserProjects = await fetchMyOrganizationProjects(orgId); localStorage.setItem("projectData.id", orgUserProjects[0]._id); resolve(true); diff --git a/frontend/src/components/utilities/checks/OnboardingCheck.ts b/frontend/src/components/utilities/checks/OnboardingCheck.ts index 20bb1cd78..01d7a2d55 100644 --- a/frontend/src/components/utilities/checks/OnboardingCheck.ts +++ b/frontend/src/components/utilities/checks/OnboardingCheck.ts @@ -1,5 +1,4 @@ -import getOrganizationUsers from "@app/pages/api/organization/GetOrgUsers"; -import checkUserAction from "@app/pages/api/userActions/checkUserAction"; +import { fetchOrgUsers,fetchUserAction } from "@app/hooks/api/users/queries"; interface OnboardingCheckProps { setTotalOnboardingActionsDone?: (value: number) => void; @@ -20,34 +19,31 @@ const onboardingCheck = async ({ setUsersInOrg }: OnboardingCheckProps) => { let countActions = 0; - const userActionSlack = await checkUserAction({ - action: "slack_cta_clicked" - }); + const userActionSlack = await fetchUserAction( + "slack_cta_clicked" + ); + if (userActionSlack) { countActions += 1; } if (setHasUserClickedSlack) setHasUserClickedSlack(!!userActionSlack); - const userActionSecrets = await checkUserAction({ - action: "first_time_secrets_pushed" - }); + const userActionSecrets = await fetchUserAction("first_time_secrets_pushed"); + if (userActionSecrets) { countActions += 1; } if (setHasUserPushedSecrets) setHasUserPushedSecrets(!!userActionSecrets); - const userActionIntro = await checkUserAction({ - action: "intro_cta_clicked" - }); + const userActionIntro = await fetchUserAction("intro_cta_clicked"); if (userActionIntro) { countActions += 1; } if (setHasUserClickedIntro) setHasUserClickedIntro(!!userActionIntro); const orgId = localStorage.getItem("orgData.id"); - const orgUsers = await getOrganizationUsers({ - orgId: orgId || "" - }); + const orgUsers = await fetchOrgUsers(orgId || ""); + if (orgUsers.length > 1) { countActions += 1; } diff --git a/frontend/src/components/utilities/cryptography/changePassword.ts b/frontend/src/components/utilities/cryptography/changePassword.ts deleted file mode 100644 index 3e7ad22e0..000000000 --- a/frontend/src/components/utilities/cryptography/changePassword.ts +++ /dev/null @@ -1,147 +0,0 @@ -/* eslint-disable new-cap */ -import crypto from "crypto"; - -import jsrp from "jsrp"; - -import changePassword2 from "@app/pages/api/auth/ChangePassword2"; -import SRP1 from "@app/pages/api/auth/SRP1"; - -import { saveTokenToLocalStorage } from "../saveTokenToLocalStorage"; -import Aes256Gcm from "./aes-256-gcm"; -import { deriveArgonKey } from "./crypto"; - -const clientOldPassword = new jsrp.client(); -const clientNewPassword = new jsrp.client(); - -/** - * This function loggs in the user (whether it's right after signup, or a normal login) - * @param {*} email - * @param {*} password - * @param {*} setErrorLogin - * @param {*} router - * @param {*} isSignUp - * @returns - */ -const changePassword = async ( - email: string, - currentPassword: string, - newPassword: string, - setCurrentPasswordError: (arg: boolean) => void, - setPasswordChanged: (arg: boolean) => void, - setCurrentPassword: (arg: string) => void, - setNewPassword: (arg: string) => void -) => { - try { - setPasswordChanged(false); - setCurrentPasswordError(false); - - clientOldPassword.init( - { - username: email, - password: currentPassword - }, - async () => { - const clientPublicKey = clientOldPassword.getPublicKey(); - - let serverPublicKey; - let salt; - try { - const res = await SRP1({ - clientPublicKey - }); - serverPublicKey = res.serverPublicKey; - salt = res.salt; - } catch (err) { - setCurrentPasswordError(true); - console.log("Wrong current password", err, 1); - } - - clientOldPassword.setSalt(salt); - clientOldPassword.setServerPublicKey(serverPublicKey); - const clientProof = clientOldPassword.getProof(); // called M1 - - clientNewPassword.init( - { - username: email, - password: newPassword - }, - async () => { - clientNewPassword.createVerifier(async (err, result) => { - - const derivedKey = await deriveArgonKey({ - password: newPassword, - salt: result.salt, - mem: 65536, - time: 3, - parallelism: 1, - hashLen: 32 - }); - - if (!derivedKey) throw new Error("Failed to derive key from password"); - - const key = crypto.randomBytes(32); - - // create encrypted private key by encrypting the private - // key with the symmetric key [key] - const { - ciphertext: encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag - } = Aes256Gcm.encrypt({ - text: localStorage.getItem("PRIVATE_KEY") as string, - secret: key - }); - - // create the protected key by encrypting the symmetric key - // [key] with the derived key - const { - ciphertext: protectedKey, - iv: protectedKeyIV, - tag: protectedKeyTag - } = Aes256Gcm.encrypt({ - text: key.toString("hex"), - secret: Buffer.from(derivedKey.hash) - }); - - try { - await changePassword2({ - clientProof, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt: result.salt, - verifier: result.verifier - }); - - saveTokenToLocalStorage({ - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag - }); - - setPasswordChanged(true); - setCurrentPassword(""); - setNewPassword(""); - - window.location.href = "/login"; - - // move to login page - } catch (error) { - setCurrentPasswordError(true); - console.log(error); - } - }); - } - ); - } - ); - } catch (error) { - console.log("Something went wrong during changing the password"); - } - return true; -}; - -export default changePassword; diff --git a/frontend/src/components/utilities/cryptography/issueBackupKey.ts b/frontend/src/components/utilities/cryptography/issueBackupKey.ts index 9f503e0c9..4391d027f 100644 --- a/frontend/src/components/utilities/cryptography/issueBackupKey.ts +++ b/frontend/src/components/utilities/cryptography/issueBackupKey.ts @@ -3,8 +3,9 @@ import crypto from "crypto"; import jsrp from "jsrp"; -import issueBackupPrivateKey from "@app/pages/api/auth/IssueBackupPrivateKey"; -import SRP1 from "@app/pages/api/auth/SRP1"; +import { issueBackupPrivateKey , + srp1 +} from "@app/hooks/api/auth/queries"; import generateBackupPDF from "../generateBackupPDF"; import Aes256Gcm from "./aes-256-gcm"; @@ -51,7 +52,7 @@ const issueBackupKey = async ({ let serverPublicKey; let salt; try { - const res = await SRP1({ + const res = await srp1({ clientPublicKey }); serverPublicKey = res.serverPublicKey; @@ -61,8 +62,8 @@ const issueBackupKey = async ({ console.log("Wrong current password", err, 1); } - clientPassword.setSalt(salt); - clientPassword.setServerPublicKey(serverPublicKey); + clientPassword.setSalt(salt as string); + clientPassword.setServerPublicKey(serverPublicKey as string); const clientProof = clientPassword.getProof(); // called M1 const generatedKey = crypto.randomBytes(16).toString("hex"); @@ -80,24 +81,25 @@ const issueBackupKey = async ({ secret: generatedKey }); - const res = await issueBackupPrivateKey({ - encryptedPrivateKey: ciphertext, - iv, - tag, - salt: result.salt, - verifier: result.verifier, - clientProof - }); + try { + await issueBackupPrivateKey({ + encryptedPrivateKey: ciphertext, + iv, + tag, + salt: result.salt, + verifier: result.verifier, + clientProof + }); - if (res?.status === 400) { - setBackupKeyError(true); - } else if (res?.status === 200) { generateBackupPDF({ personalName, personalEmail: email, generatedKey }); setBackupKeyIssued(true); + + } catch { + setBackupKeyError(true); } } ); diff --git a/frontend/src/components/utilities/secrets/encryptSecrets.ts b/frontend/src/components/utilities/secrets/encryptSecrets.ts index 49fcf9736..610e2a6f1 100644 --- a/frontend/src/components/utilities/secrets/encryptSecrets.ts +++ b/frontend/src/components/utilities/secrets/encryptSecrets.ts @@ -2,7 +2,7 @@ import crypto from "crypto"; import { SecretDataProps, Tag } from "public/data/frequentInterfaces"; -import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey"; +import { fetchUserWsKey } from "@app/hooks/api/keys/queries"; import { decryptAssymmetric, encryptSymmetric } from "../cryptography/crypto"; @@ -42,19 +42,21 @@ const encryptSecrets = async ({ }) => { let secrets; try { - const sharedKey = await getLatestFileKey({ workspaceId }); + // const sharedKey = await getLatestFileKey({ workspaceId }); + const wsKey = await fetchUserWsKey(workspaceId); const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string; let randomBytes: string; - if (Object.keys(sharedKey).length > 0) { + if (wsKey) { // case: a (shared) key exists for the workspace randomBytes = decryptAssymmetric({ - ciphertext: sharedKey.latestKey.encryptedKey, - nonce: sharedKey.latestKey.nonce, - publicKey: sharedKey.latestKey.sender.publicKey, + ciphertext: wsKey.encryptedKey, + nonce: wsKey.nonce, + publicKey: wsKey.sender.publicKey, privateKey: PRIVATE_KEY }); + } else { // case: a (shared) key does not exist for the workspace randomBytes = crypto.randomBytes(16).toString("hex"); @@ -114,6 +116,7 @@ const encryptSecrets = async ({ return result; }); + } catch (error) { console.log("Error while encrypting secrets"); } diff --git a/frontend/src/components/utilities/secrets/getSecretsForProject.ts b/frontend/src/components/utilities/secrets/getSecretsForProject.ts deleted file mode 100644 index de1a75369..000000000 --- a/frontend/src/components/utilities/secrets/getSecretsForProject.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { Tag } from "public/data/frequentInterfaces"; - -import getSecrets from "@app/pages/api/files/GetSecrets"; -import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey"; - -import { decryptAssymmetric, decryptSymmetric } from "../cryptography/crypto"; - -interface EncryptedSecretProps { - _id: string; - createdAt: string; - environment: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - type: "personal" | "shared"; - tags: Tag[]; -} - -interface SecretProps { - key: string; - value: string | undefined; - type: "personal" | "shared"; - comment: string; - id: string; - tags: Tag[]; -} - -interface FunctionProps { - env: string; - setIsKeyAvailable?: any; - setData?: any; - workspaceId: string; -} - -/** - * Gets the secrets for a certain project - * @param {object} obj - * @param {string} obj.env - environment for which we are getting secrets - * @param {boolean} obj.isKeyAvailable - if a person is able to create new key pairs - * @param {function} obj.setData - state function that manages the state of secrets in the dashboard - * @param {string} obj.workspaceId - id of a workspace for which we are getting secrets - */ -const getSecretsForProject = async ({ - env, - setIsKeyAvailable, - setData, - workspaceId -}: FunctionProps) => { - try { - let encryptedSecrets; - try { - encryptedSecrets = await getSecrets(workspaceId, env); - } catch (error) { - console.log("ERROR: Not able to access the latest version of secrets"); - } - - const latestKey = await getLatestFileKey({ workspaceId }); - // This is called isKeyAvailable but what it really means is if a person is able to create new key pairs - if (typeof setIsKeyAvailable === "function") { - setIsKeyAvailable(!latestKey ? encryptedSecrets.length === 0 : true); - } - - const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string; - - const tempDecryptedSecrets: SecretProps[] = []; - if (latestKey) { - // assymmetrically decrypt symmetric key with local private key - const key = decryptAssymmetric({ - ciphertext: latestKey.latestKey.encryptedKey, - nonce: latestKey.latestKey.nonce, - publicKey: latestKey.latestKey.sender.publicKey, - privateKey: PRIVATE_KEY - }); - - // decrypt secret keys, values, and comments - encryptedSecrets.forEach((secret: EncryptedSecretProps) => { - const plainTextKey = decryptSymmetric({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - key - }); - - let plainTextValue; - if (secret.secretValueCiphertext !== undefined) { - plainTextValue = decryptSymmetric({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - key - }); - } else { - plainTextValue = undefined; - } - - let plainTextComment; - if (secret.secretCommentCiphertext) { - plainTextComment = decryptSymmetric({ - ciphertext: secret.secretCommentCiphertext, - iv: secret.secretCommentIV, - tag: secret.secretCommentTag, - key - }); - } else { - plainTextComment = ""; - } - - tempDecryptedSecrets.push({ - id: secret._id, - key: plainTextKey, - value: plainTextValue, - type: secret.type, - comment: plainTextComment, - tags: secret.tags - }); - }); - } - - const secretKeys = [...new Set(tempDecryptedSecrets.map((secret) => secret.key))]; - - const result = secretKeys.map((key, index) => ({ - id: tempDecryptedSecrets.filter((secret) => secret.key === key && secret.type === "shared")[0] - ?.id, - idOverride: tempDecryptedSecrets.filter( - (secret) => secret.key === key && secret.type === "personal" - )[0]?.id, - pos: index, - key, - value: tempDecryptedSecrets.filter( - (secret) => secret.key === key && secret.type === "shared" - )[0]?.value, - valueOverride: tempDecryptedSecrets.filter( - (secret) => secret.key === key && secret.type === "personal" - )[0]?.value, - comment: tempDecryptedSecrets.filter( - (secret) => secret.key === key && secret.type === "shared" - )[0]?.comment, - tags: tempDecryptedSecrets.filter( - (secret) => secret.key === key && secret.type === "shared" - )[0]?.tags - })); - - if (typeof setData === "function") { - setData(result); - } - - return result; - } catch (error) { - console.log("Something went wrong during accessing or decripting secrets."); - } - return []; -}; - -export default getSecretsForProject; diff --git a/frontend/src/context/OrganizationContext/OrganizationContext.tsx b/frontend/src/context/OrganizationContext/OrganizationContext.tsx index 69fd7fe38..0c0878fa1 100644 --- a/frontend/src/context/OrganizationContext/OrganizationContext.tsx +++ b/frontend/src/context/OrganizationContext/OrganizationContext.tsx @@ -1,6 +1,6 @@ import { createContext, ReactNode, useContext, useMemo } from "react"; -import { useGetOrganization } from "@app/hooks/api"; +import { useGetOrganizations } from "@app/hooks/api"; import { Organization } from "@app/hooks/api/types"; @@ -17,8 +17,8 @@ type Props = { }; export const OrgProvider = ({ children }: Props): JSX.Element => { - const { data: userOrgs, isLoading } = useGetOrganization(); - + const { data: userOrgs, isLoading } = useGetOrganizations(); + // const currentWsOrgID = currentWorkspace?.organization; const currentWsOrgID = localStorage.getItem("orgData.id"); diff --git a/frontend/src/ee/components/ActivitySideBar.tsx b/frontend/src/ee/components/ActivitySideBar.tsx index 67d673c3d..d1e068177 100644 --- a/frontend/src/ee/components/ActivitySideBar.tsx +++ b/frontend/src/ee/components/ActivitySideBar.tsx @@ -8,7 +8,9 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import getActionData from "@app/ee/api/secrets/GetActionData"; import patienceDiff from "@app/ee/utilities/findTextDifferences"; -import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey"; +import { + useGetUserWsKey +} from "@app/hooks/api"; import { decryptAssymmetric, @@ -59,25 +61,24 @@ const ActivitySideBar = ({ toggleSidebar, currentAction }: SideBarProps) => { const [actionData, setActionData] = useState(); const [actionMetaData, setActionMetaData] = useState(); const [isLoading, setIsLoading] = useState(false); + const { data: wsKey } = useGetUserWsKey(String(router.query.id)); useEffect(() => { const getLogData = async () => { setIsLoading(true); const tempActionData = await getActionData({ actionId: currentAction }); - const latestKey = await getLatestFileKey({ workspaceId: String(router.query.id) }); const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); // #TODO: make this a separate function and reuse across the app let decryptedLatestKey: string; - if (latestKey) { + if (wsKey) { // assymmetrically decrypt symmetric key with local private key decryptedLatestKey = decryptAssymmetric({ - ciphertext: latestKey.latestKey.encryptedKey, - nonce: latestKey.latestKey.nonce, - publicKey: latestKey.latestKey.sender.publicKey, + ciphertext: wsKey.encryptedKey, + nonce: wsKey.nonce, + publicKey: wsKey.sender.publicKey, privateKey: String(PRIVATE_KEY) }); - } const decryptedSecretVersions = tempActionData.payload.secretVersions.map( (encryptedSecretVersion: { @@ -122,9 +123,10 @@ const ActivitySideBar = ({ toggleSidebar, currentAction }: SideBarProps) => { setActionData(decryptedSecretVersions); setActionMetaData({ name: tempActionData.name }); setIsLoading(false); + } }; getLogData(); - }, [currentAction]); + }, [currentAction, wsKey]); return (
void; - setSnapshotData: (value: any) => void; - chosenSnapshot: string; -} - -interface SnaphotProps { - _id: string; - createdAt: string; - secretVersions: string[]; -} - -interface EncrypetedSecretVersionListProps { - _id: string; - createdAt: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - environment: string; - type: "personal" | "shared"; - tags: Tag[]; -} - -/** - * @param {object} obj - * @param {function} obj.toggleSidebar - function that opens or closes the sidebar - * @param {function} obj.setSnapshotData - state manager for snapshot data - * @param {string} obj.chosenSnaphshot - the snapshot id which is currently selected - * @returns the sidebar with the options for point-in-time recovery (commits) - */ -const PITRecoverySidebar = ({ toggleSidebar, setSnapshotData, chosenSnapshot }: SideBarProps) => { - const router = useRouter(); - const [isLoading, setIsLoading] = useState(false); - const [secretSnapshotsMetadata, setSecretSnapshotsMetadata] = useState([]); - const [currentOffset, setCurrentOffset] = useState(0); - const currentLimit = 15; - - const loadMoreSnapshots = () => { - setCurrentOffset(currentOffset + currentLimit); - }; - - useEffect(() => { - const getLogData = async () => { - setIsLoading(true); - const results = await getProjectSecretShanpshots({ - workspaceId: String(router.query.id), - limit: currentLimit, - offset: currentOffset - }); - setSecretSnapshotsMetadata(secretSnapshotsMetadata.concat(results)); - setIsLoading(false); - }; - getLogData(); - }, [currentOffset]); - - const exploreSnapshot = async ({ snapshotId }: { snapshotId: string }) => { - const secretSnapshotData = await getSecretSnapshotData({ secretSnapshotId: snapshotId }); - - const latestKey = await getLatestFileKey({ workspaceId: String(router.query.id) }); - const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); - - let decryptedLatestKey: string; - if (latestKey) { - // assymmetrically decrypt symmetric key with local private key - decryptedLatestKey = decryptAssymmetric({ - ciphertext: latestKey.latestKey.encryptedKey, - nonce: latestKey.latestKey.nonce, - publicKey: latestKey.latestKey.sender.publicKey, - privateKey: String(PRIVATE_KEY) - }); - } - - const decryptedSecretVersions = secretSnapshotData.secretVersions - .filter( - (sv: EncrypetedSecretVersionListProps) => - sv.type !== undefined && sv.environment !== undefined - ) - .map((encryptedSecretVersion: EncrypetedSecretVersionListProps, pos: number) => ({ - id: encryptedSecretVersion._id, - pos, - type: encryptedSecretVersion.type, - environment: encryptedSecretVersion.environment, - tags: encryptedSecretVersion.tags, - key: decryptSymmetric({ - ciphertext: encryptedSecretVersion.secretKeyCiphertext, - iv: encryptedSecretVersion.secretKeyIV, - tag: encryptedSecretVersion.secretKeyTag, - key: decryptedLatestKey - }), - value: decryptSymmetric({ - ciphertext: encryptedSecretVersion.secretValueCiphertext, - iv: encryptedSecretVersion.secretValueIV, - tag: encryptedSecretVersion.secretValueTag, - key: decryptedLatestKey - }) - })); - - const secretKeys = [ - ...new Set( - decryptedSecretVersions - .filter((dsv: any) => dsv.type !== undefined || dsv.environemnt !== undefined) - .map((secret: SecretDataProps) => secret.key) - ) - ]; - - const result = secretKeys.map((key, index) => - decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "shared" - )[0]?.id - ? { - id: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "shared" - )[0].id, - pos: index, - key, - environment: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "shared" - )[0].environment, - tags: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "shared" - )[0].tags, - value: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "shared" - )[0]?.value, - valueOverride: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "personal" - )[0]?.value - } - : { - id: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "personal" - )[0].id, - pos: index, - key, - environment: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "personal" - )[0].environment, - tags: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "personal" - )[0].tags, - value: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "shared" - )[0]?.value, - valueOverride: decryptedSecretVersions.filter( - (secret: SecretDataProps) => secret.key === key && secret.type === "personal" - )[0]?.value - } - ); - - setSnapshotData({ - id: secretSnapshotData._id, - version: secretSnapshotData.version, - createdAt: secretSnapshotData.createdAt, - secretVersions: result, - comment: "" - }); - }; - - return ( -
- {isLoading ? ( -
- infisical loading indicator -
- ) : ( -
-
-

Point In Recovery

-
null} - role="button" - tabIndex={0} - className="p-1" - onClick={() => toggleSidebar(false)} - > - -
-
-
- - Note: This will recover secrets for all enviroments in this project. - - {secretSnapshotsMetadata?.map((snapshot: SnaphotProps, id: number) => ( -
null} - role="button" - tabIndex={0} - key={snapshot._id} - onClick={() => exploreSnapshot({ snapshotId: snapshot._id })} - className={`${ - chosenSnapshot === snapshot._id || (id === 0 && chosenSnapshot === "") - ? "pointer-events-none bg-primary text-black" - : "cursor-pointer bg-mineshaft-700 duration-200 hover:bg-mineshaft-500" - } mb-2 flex flex-row items-center justify-between rounded-md py-3 px-4`} - > -
-
- {timeSince(new Date(snapshot.createdAt))} -
-
{` - ${snapshot.secretVersions.length} Secrets`}
-
-
- {id === 0 - ? "Current Version" - : chosenSnapshot === snapshot._id - ? "Currently Viewing" - : "Explore"} -
-
- ))} -
-
-
-
-
-
- )} -
- ); -}; - -export default PITRecoverySidebar; diff --git a/frontend/src/ee/components/SecretVersionList.tsx b/frontend/src/ee/components/SecretVersionList.tsx deleted file mode 100644 index 41a085082..000000000 --- a/frontend/src/ee/components/SecretVersionList.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import Image from "next/image"; -import { useRouter } from "next/router"; -import { faCircle, faDotCircle } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -import { - decryptAssymmetric, - decryptSymmetric -} from "@app/components/utilities/cryptography/crypto"; -import getSecretVersions from "@app/ee/api/secrets/GetSecretVersions"; -import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey"; - -interface DecryptedSecretVersionListProps { - createdAt: string; - value: string; -} - -interface EncrypetedSecretVersionListProps { - createdAt: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; -} - -/** - * @param {string} secretId - the id of a secret for which are querying version history - * @returns a list of versions for a specific secret - */ -const SecretVersionList = ({ secretId }: { secretId: string }) => { - const router = useRouter(); - const [isLoading, setIsLoading] = useState(false); - const { t } = useTranslation(); - const [secretVersions, setSecretVersions] = useState([]); - - useEffect(() => { - const getSecretVersionHistory = async () => { - setIsLoading(true); - try { - const encryptedSecretVersions = await getSecretVersions({ secretId, offset: 0, limit: 10 }); - const latestKey = await getLatestFileKey({ workspaceId: String(router.query.id) }); - - const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); - - let decryptedLatestKey: string; - if (latestKey) { - // assymmetrically decrypt symmetric key with local private key - decryptedLatestKey = decryptAssymmetric({ - ciphertext: latestKey.latestKey.encryptedKey, - nonce: latestKey.latestKey.nonce, - publicKey: latestKey.latestKey.sender.publicKey, - privateKey: String(PRIVATE_KEY) - }); - } - - const decryptedSecretVersions = encryptedSecretVersions?.secretVersions.map( - (encryptedSecretVersion: EncrypetedSecretVersionListProps) => ({ - createdAt: encryptedSecretVersion.createdAt, - value: decryptSymmetric({ - ciphertext: encryptedSecretVersion.secretValueCiphertext, - iv: encryptedSecretVersion.secretValueIV, - tag: encryptedSecretVersion.secretValueTag, - key: decryptedLatestKey - }) - }) - ); - - setSecretVersions(decryptedSecretVersions); - setIsLoading(false); - } catch (error) { - console.log(error); - } - }; - getSecretVersionHistory(); - }, [secretId]); - - return ( -
-

{t("dashboard.sidebar.version-history")}

-
- {isLoading ? ( -
- infisical loading indicator -
- ) : ( -
- {secretVersions ? ( - secretVersions - ?.sort((a, b) => b.createdAt.localeCompare(a.createdAt)) - .map((version: DecryptedSecretVersionListProps, index: number) => ( -
-
-
- -
-
-
-
-
- {new Date(version.createdAt).toLocaleDateString("en-US", { - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - second: "2-digit" - })} -
-
-

- - Value: - - {version.value} -

-
-
-
- )) - ) : ( -
- No version history yet. -
- )} -
- )} -
-
- ); -}; - -export default SecretVersionList; diff --git a/frontend/src/helpers/project.ts b/frontend/src/helpers/project.ts index 30bd996d9..f0cb8ec4c 100644 --- a/frontend/src/helpers/project.ts +++ b/frontend/src/helpers/project.ts @@ -2,10 +2,10 @@ import crypto from "crypto"; import { encryptAssymmetric } from "@app/components/utilities/cryptography/crypto"; import encryptSecrets from "@app/components/utilities/secrets/encryptSecrets"; -import addSecrets from "@app/pages/api/files/AddSecrets"; -import getUser from "@app/pages/api/user/getUser"; -import createWorkspace from "@app/pages/api/workspace/createWorkspace"; -import uploadKeys from "@app/pages/api/workspace/uploadKeys"; +import { uploadWsKey } from "@app/hooks/api/keys/queries"; +import { createSecret } from "@app/hooks/api/secrets/queries"; +import { fetchUserDetails } from "@app/hooks/api/users/queries"; +import { createWorkspace } from "@app/hooks/api/workspace/queries"; const secretsToBeAdded = [ { @@ -91,49 +91,60 @@ const initProjectHelper = async ({ organizationId: string; projectName: string; }) => { - let project; - try { + // create new project + const { data: { workspace } } = await createWorkspace({ + workspaceName: projectName, + organizationId + }); + + // create and upload new (encrypted) project key + const randomBytes = crypto.randomBytes(16).toString("hex"); + const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); + + if (!PRIVATE_KEY) throw new Error("Failed to find private key"); - // create new project - project = await createWorkspace({ - workspaceName: projectName, - organizationId - }); + const user = await fetchUserDetails(); - // create and upload new (encrypted) project key - const randomBytes = crypto.randomBytes(16).toString("hex"); - const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); - - if (!PRIVATE_KEY) throw new Error("Failed to find private key"); + const { ciphertext, nonce } = encryptAssymmetric({ + plaintext: randomBytes, + publicKey: user.publicKey, + privateKey: PRIVATE_KEY + }); - const user = await getUser(); + await uploadWsKey({ + workspaceId: workspace._id, + userId: user._id, + encryptedKey: ciphertext, + nonce + }); - const { ciphertext, nonce } = encryptAssymmetric({ - plaintext: randomBytes, - publicKey: user.publicKey, - privateKey: PRIVATE_KEY - }); - - await uploadKeys(project._id, user._id, ciphertext, nonce); - - // encrypt and upload secrets to new project - const secrets = await encryptSecrets({ - secretsToEncrypt: secretsToBeAdded, - workspaceId: project._id, - env: "dev" - }); - - await addSecrets({ - secrets: secrets ?? [], - env: "dev", - workspaceId: project._id - }); - - } catch (err) { - console.error("Failed to init project in organization", err); - } - - return project; + // encrypt and upload secrets to new project + const secrets = await encryptSecrets({ + secretsToEncrypt: secretsToBeAdded, + workspaceId: workspace._id, + env: "dev" + }); + + secrets?.forEach((secret) => { + createSecret({ + workspaceId: workspace._id, + environment: secret.environment, + type: secret.type, + secretKey: secret.secretName, + secretKeyCiphertext: secret.secretKeyCiphertext, + secretKeyIV: secret.secretKeyIV, + secretKeyTag: secret.secretKeyTag, + secretValueCiphertext: secret.secretValueCiphertext, + secretValueIV: secret.secretValueIV, + secretValueTag: secret.secretValueTag, + secretCommentCiphertext: secret.secretCommentCiphertext, + secretCommentIV: secret.secretCommentIV, + secretCommentTag: secret.secretCommentTag, + secretPath: "/" + }); + }); + + return workspace; } export { diff --git a/frontend/src/hooks/api/auth/index.tsx b/frontend/src/hooks/api/auth/index.tsx index a4f967888..dbcc77a5a 100644 --- a/frontend/src/hooks/api/auth/index.tsx +++ b/frontend/src/hooks/api/auth/index.tsx @@ -1,6 +1,10 @@ export { useGetAuthToken, useGetCommonPasswords, + useResetPassword, useSendMfaToken, - useVerifyMfaToken -} from "./queries" + useSendPasswordResetEmail, + useSendVerificationEmail, + useVerifyEmailVerificationCode, + useVerifyMfaToken, + useVerifyPasswordResetCode} from "./queries" diff --git a/frontend/src/hooks/api/auth/queries.tsx b/frontend/src/hooks/api/auth/queries.tsx index 57878d2b3..094fd4b61 100644 --- a/frontend/src/hooks/api/auth/queries.tsx +++ b/frontend/src/hooks/api/auth/queries.tsx @@ -4,16 +4,86 @@ import { apiRequest } from "@app/config/request"; import { setAuthToken } from "@app/reactQuery"; import { + ChangePasswordDTO, + CompleteAccountDTO, + CompleteAccountSignupDTO, GetAuthTokenAPI, + GetBackupEncryptedPrivateKeyDTO, + IssueBackupPrivateKeyDTO, + Login1DTO, + Login1Res, + Login2DTO, + Login2Res, + ResetPasswordDTO, SendMfaTokenDTO, + SRP1DTO, + SRPR1Res, VerifyMfaTokenDTO, - VerifyMfaTokenRes} from "./types"; + VerifyMfaTokenRes, + VerifySignupInviteDTO} from "./types"; const authKeys = { getAuthToken: ["token"] as const, commonPasswords: ["common-passwords"] as const }; +export const login1 = async (loginDetails: Login1DTO) => { + const { data } = await apiRequest.post("/api/v3/auth/login1", loginDetails); + return data; +} + +export const login2 = async (loginDetails: Login2DTO) => { + const { data } = await apiRequest.post("/api/v3/auth/login2", loginDetails); + return data; +} + +export const useLogin1 = () => { + return useMutation({ + mutationFn: async (details: { + email: string; + clientPublicKey: string; + providerAuthToken?: string; + }) => { + return login1(details); + } + }); +} + +export const useLogin2 = () => { + return useMutation({ + mutationFn: async (details: { + email: string; + clientProof: string; + providerAuthToken?: string; + }) => { + return login2(details); + } + }); +} + +export const srp1 = async (details: SRP1DTO) => { + const { data } = await apiRequest.post("/api/v1/password/srp1", details); + return data; +} + +export const completeAccountSignup = async (details: CompleteAccountSignupDTO) => { + const { data } = await apiRequest.post("/api/v3/signup/complete-account/signup", details); + return data; +} + +export const completeAccountSignupInvite = async (details: CompleteAccountDTO) => { + const { data } = await apiRequest.post("/api/v2/signup/complete-account/invite", details); + return data; +} + +export const useCompleteAccountSignup = () => { + return useMutation({ + mutationFn: async (details: CompleteAccountSignupDTO) => { + return completeAccountSignup(details); + } + }); +} + export const useSendMfaToken = () => { return useMutation<{}, {}, SendMfaTokenDTO>({ mutationFn: async ({ email }) => { @@ -23,18 +93,161 @@ export const useSendMfaToken = () => { }); } +export const verifyMfaToken = async ({ + email, + mfaCode +}: { + email: string; + mfaCode: string; +}) => { + const { data } = await apiRequest.post("/api/v2/auth/mfa/verify", { + email, + mfaToken: mfaCode + }); + + return data; +} + export const useVerifyMfaToken = () => { return useMutation({ mutationFn: async ({ email, mfaCode }) => { - const { data } = await apiRequest.post("/api/v2/auth/mfa/verify", { + return verifyMfaToken({ email, - mfaToken: mfaCode + mfaCode }); + } + }); +} + +export const verifySignupInvite = async (details: VerifySignupInviteDTO) => { + const { data } = await apiRequest.post("/api/v1/invite-org/verify", details); + return data; +} + +export const useSendVerificationEmail = () => { + return useMutation({ + mutationFn: async ({ + email + }: { + email: string; + }) => { + const { data } = await apiRequest.post("/api/v1/signup/email/signup", { + email + }); + return data; } }); } +export const useVerifyEmailVerificationCode = () => { + return useMutation({ + mutationFn: async ({ + email, + code + }: { + email: string; + code: string; + }) => { + const { data } = await apiRequest.post("/api/v1/signup/email/verify", { + email, + code + }); + + return data; + } + }); +} + +export const useSendPasswordResetEmail = () => { + return useMutation({ + mutationFn: async ({ + email + }: { + email: string; + }) => { + const { data } = await apiRequest.post("/api/v1/password/email/password-reset", { + email + }); + + return data; + } + }); +} + +export const useVerifyPasswordResetCode = () => { + return useMutation({ + mutationFn: async ({ + email, + code + }: { + email: string; + code: string; + }) => { + const { data } = await apiRequest.post("/api/v1/password/email/password-reset-verify", { + email, + code + }); + + return data; + } + }); +} + +export const issueBackupPrivateKey = async (details: IssueBackupPrivateKeyDTO) => { + const { data } = await apiRequest.post("/api/v1/password/backup-private-key", details); + return data; +} + +export const getBackupEncryptedPrivateKey = async ({ + verificationToken +}: GetBackupEncryptedPrivateKeyDTO) => { + const { data } = await apiRequest.get("/api/v1/password/backup-private-key", { + headers: { + Authorization: `Bearer ${verificationToken}` + } + }); + + return data.backupPrivateKey; +} + +export const useResetPassword = () => { + return useMutation({ + mutationFn: async (details: ResetPasswordDTO) => { + const { data } = await apiRequest.post("/api/v1/password/password-reset", { + protectedKey: details.protectedKey, + protectedKeyIV: details.protectedKeyIV, + protectedKeyTag: details.protectedKeyTag, + encryptedPrivateKey: details.encryptedPrivateKey, + encryptedPrivateKeyIV: details.encryptedPrivateKeyIV, + encryptedPrivateKeyTag: details.encryptedPrivateKeyTag, + salt: details.salt, + verifier: details.verifier + }, { + headers: { + Authorization: `Bearer ${details.verificationToken}` + } + }); + + return data; + } + }); +} + +export const changePassword = async (details: ChangePasswordDTO) => { + const { data } = await apiRequest.post("/api/v1/password/change-password", details); + return data; +} + +export const useChangePassword = () => { + // note: use after srp1 + return useMutation({ + mutationFn: async (details: ChangePasswordDTO) => { + return changePassword(details); + } + }); +} + // Refresh token is set as cookie when logged in // Using that we fetch the auth bearer token needed for auth calls const fetchAuthToken = async () => { diff --git a/frontend/src/hooks/api/auth/types.ts b/frontend/src/hooks/api/auth/types.ts index 3d14c19ff..7ed7af566 100644 --- a/frontend/src/hooks/api/auth/types.ts +++ b/frontend/src/hooks/api/auth/types.ts @@ -21,4 +21,107 @@ export type VerifyMfaTokenRes = { encryptedPrivateKey: string; iv: string; tag: string; +} + +export type Login1DTO = { + email: string; + clientPublicKey: string; + providerAuthToken?: string; +} + +export type Login2DTO = { + email: string; + clientProof: string; + providerAuthToken?: string; +} + +export type Login1Res = { + serverPublicKey: string; + salt: string; +} + +export type Login2Res = { + mfaEnabled: boolean; + token: string; + encryptionVersion?: number; + protectedKey?: string; + protectedKeyIV?: string; + protectedKeyTag?: string; + publicKey?: string; + encryptedPrivateKey?: string; + iv?: string; + tag?: string; +} + +export type SRP1DTO = { + clientPublicKey: string; +} + +export type SRPR1Res = { + serverPublicKey: string; + salt: string; +} + +export type CompleteAccountDTO = { + email: string; + firstName: string; + lastName: string; + protectedKey: string; + protectedKeyIV: string; + protectedKeyTag: string; + publicKey: string; + encryptedPrivateKey: string; + encryptedPrivateKeyIV: string; + encryptedPrivateKeyTag: string; + salt: string; + verifier: string; +} + +export type CompleteAccountSignupDTO = CompleteAccountDTO & { + providerAuthToken?: string; + attributionSource?: string; + organizationName: string; +} + +export type VerifySignupInviteDTO = { + email: string; + code: string; + organizationId: string; +} + +export type ChangePasswordDTO = { + clientProof: string; + protectedKey: string; + protectedKeyIV: string; + protectedKeyTag: string; + encryptedPrivateKey: string; + encryptedPrivateKeyIV: string; + encryptedPrivateKeyTag: string; + salt: string; + verifier: string; +} + +export type ResetPasswordDTO = { + protectedKey: string; + protectedKeyIV: string; + protectedKeyTag: string; + encryptedPrivateKey: string; + encryptedPrivateKeyIV: string; + encryptedPrivateKeyTag: string; + salt: string; + verifier: string; + verificationToken: string; +} + +export type IssueBackupPrivateKeyDTO = { + encryptedPrivateKey: string; + iv: string; + tag: string; + salt: string; + verifier: string; + clientProof: string; +} + +export type GetBackupEncryptedPrivateKeyDTO = { + verificationToken: string; } \ No newline at end of file diff --git a/frontend/src/hooks/api/bots/queries.tsx b/frontend/src/hooks/api/bots/queries.tsx index 1c28c9640..3e35a58f0 100644 --- a/frontend/src/hooks/api/bots/queries.tsx +++ b/frontend/src/hooks/api/bots/queries.tsx @@ -8,29 +8,26 @@ const queryKeys = { getBot: (workspaceId: string) => [{ workspaceId }, "bot"] as const }; -const fetchWorkspaceBot = async (workspaceId: string) => { - const { data } = await apiRequest.get<{ bot: TBot }>(`/api/v1/bot/${workspaceId}`); - return data.bot; -}; - export const useGetWorkspaceBot = (workspaceId: string) => useQuery({ queryKey: queryKeys.getBot(workspaceId), - queryFn: () => fetchWorkspaceBot(workspaceId), + queryFn: async () => { + const { data: { bot } } = await apiRequest.get<{ bot: TBot }>(`/api/v1/bot/${workspaceId}`); + return bot; + }, enabled: Boolean(workspaceId) }); -// mutation - export const useUpdateBotActiveStatus = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, TSetBotActiveStatusDto>({ - mutationFn: ({ botId, isActive, botKey }) => - apiRequest.patch(`/api/v1/bot/${botId}/active`, { + mutationFn: ({ botId, isActive, botKey }) => { + return apiRequest.patch(`/api/v1/bot/${botId}/active`, { isActive, botKey - }), + }); + }, onSuccess: (_, { workspaceId }) => { queryClient.invalidateQueries(queryKeys.getBot(workspaceId)); } diff --git a/frontend/src/hooks/api/incidentContacts/queries.tsx b/frontend/src/hooks/api/incidentContacts/queries.tsx index 708aaaf78..aecf56a3e 100644 --- a/frontend/src/hooks/api/incidentContacts/queries.tsx +++ b/frontend/src/hooks/api/incidentContacts/queries.tsx @@ -8,18 +8,16 @@ const incidentContactKeys = { getAllContact: (orgId: string) => ["org-incident-contacts", { orgId }] as const }; -const fetchOrgIncidentContacts = async (orgId: string) => { - const { data } = await apiRequest.get<{ incidentContactsOrg: IncidentContact[] }>( - `/api/v1/organization/${orgId}/incidentContactOrg` - ); - - return data.incidentContactsOrg; -}; - export const useGetOrgIncidentContact = (orgId: string) => useQuery({ queryKey: incidentContactKeys.getAllContact(orgId), - queryFn: () => fetchOrgIncidentContacts(orgId), + queryFn: async () => { + const { data } = await apiRequest.get<{ incidentContactsOrg: IncidentContact[] }>( + `/api/v1/organization/${orgId}/incidentContactOrg` + ); + + return data.incidentContactsOrg; + }, enabled: Boolean(orgId) }); diff --git a/frontend/src/hooks/api/integrationAuth/index.tsx b/frontend/src/hooks/api/integrationAuth/index.tsx index e5e53c808..d6e1b11e3 100644 --- a/frontend/src/hooks/api/integrationAuth/index.tsx +++ b/frontend/src/hooks/api/integrationAuth/index.tsx @@ -1,4 +1,5 @@ export { + useAuthorizeIntegration, useDeleteIntegrationAuth, useGetIntegrationAuthApps, useGetIntegrationAuthBitBucketWorkspaces, @@ -7,4 +8,6 @@ export { useGetIntegrationAuthRailwayEnvironments, useGetIntegrationAuthRailwayServices, useGetIntegrationAuthTeams, - useGetIntegrationAuthVercelBranches} from "./queries"; + useGetIntegrationAuthVercelBranches, + useSaveIntegrationAccessToken +} from "./queries"; diff --git a/frontend/src/hooks/api/integrationAuth/queries.tsx b/frontend/src/hooks/api/integrationAuth/queries.tsx index bf9b5c940..1ec08d839 100644 --- a/frontend/src/hooks/api/integrationAuth/queries.tsx +++ b/frontend/src/hooks/api/integrationAuth/queries.tsx @@ -312,6 +312,69 @@ export const useGetIntegrationAuthNorthflankSecretGroups = ({ }); }; +export const useAuthorizeIntegration = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ + workspaceId, + code, + integration + }: { + workspaceId: string; + code: string; + integration: string; + }) => { + const { data: { integrationAuth } } = await apiRequest.post("/api/v1/integration-auth/oauth-token", { + workspaceId, + code, + integration + }); + + return integrationAuth; + }, + onSuccess: (res) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceAuthorization(res.workspace)); + } + }); +}; + +export const useSaveIntegrationAccessToken = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ + workspaceId, + integration, + accessId, + accessToken, + url, + namespace + }: { + workspaceId: string | null; + integration: string | undefined; + accessId: string | null; + accessToken: string; + url: string | null; + namespace: string | null; + }) => { + const { data: { integrationAuth } } = await apiRequest.post("/api/v1/integration-auth/access-token", { + workspaceId, + integration, + accessId, + accessToken, + url, + namespace + }); + + return integrationAuth; + }, + onSuccess: (res) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceAuthorization(res.workspace)); + } + }); +}; + export const useDeleteIntegrationAuth = () => { const queryClient = useQueryClient(); diff --git a/frontend/src/hooks/api/integrations/index.tsx b/frontend/src/hooks/api/integrations/index.tsx index 3ad1051f4..d0eb50ca6 100644 --- a/frontend/src/hooks/api/integrations/index.tsx +++ b/frontend/src/hooks/api/integrations/index.tsx @@ -1 +1,5 @@ -export { useDeleteIntegration,useGetCloudIntegrations } from "./queries"; +export { + useCreateIntegration, + useDeleteIntegration, + useGetCloudIntegrations +} from "./queries"; diff --git a/frontend/src/hooks/api/integrations/queries.tsx b/frontend/src/hooks/api/integrations/queries.tsx index c1353b6c6..bfca2f407 100644 --- a/frontend/src/hooks/api/integrations/queries.tsx +++ b/frontend/src/hooks/api/integrations/queries.tsx @@ -23,6 +23,63 @@ export const useGetCloudIntegrations = () => queryFn: () => fetchIntegrations() }); +export const useCreateIntegration = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ + integrationAuthId, + isActive, + app, + appId, + sourceEnvironment, + targetEnvironment, + targetEnvironmentId, + targetService, + targetServiceId, + owner, + path, + region, + secretPath + }: { + integrationAuthId: string; + isActive: boolean; + secretPath: string; + app: string | null; + appId: string | null; + sourceEnvironment: string; + targetEnvironment: string | null; + targetEnvironmentId: string | null; + targetService: string | null; + targetServiceId: string | null; + owner: string | null; + path: string | null; + region: string | null; + }) => { + const { data: { integration } } = await apiRequest.post("/api/v1/integration", { + integrationAuthId, + isActive, + app, + appId, + sourceEnvironment, + targetEnvironment, + targetEnvironmentId, + targetService, + targetServiceId, + owner, + path, + region, + secretPath + }); + + return integration; + }, + onSuccess: (res) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceIntegrations(res.workspace)); + } + }); +}; + export const useDeleteIntegration = () => { const queryClient = useQueryClient(); @@ -32,4 +89,4 @@ export const useDeleteIntegration = () => { queryClient.invalidateQueries(workspaceKeys.getWorkspaceIntegrations(workspaceId)); } }); -}; +}; \ No newline at end of file diff --git a/frontend/src/hooks/api/keys/queries.tsx b/frontend/src/hooks/api/keys/queries.tsx index c44047351..143266d40 100644 --- a/frontend/src/hooks/api/keys/queries.tsx +++ b/frontend/src/hooks/api/keys/queries.tsx @@ -8,7 +8,7 @@ const encKeyKeys = { getUserWorkspaceKey: (workspaceID: string) => ["workspace-key-pair", { workspaceID }] as const }; -const fetchUserWsKey = async (workspaceID: string) => { +export const fetchUserWsKey = async (workspaceID: string) => { const { data } = await apiRequest.get<{ latestKey: UserWsKeyPair }>( `/api/v1/key/${workspaceID}/latest` ); @@ -24,8 +24,23 @@ export const useGetUserWsKey = (workspaceID: string) => }); // mutations +export const uploadWsKey = async ({ + workspaceId, + userId, + encryptedKey, + nonce +}: UploadWsKeyDTO) => { + return apiRequest.post(`/api/v1/key/${workspaceId}`, { key: { userId, encryptedKey, nonce } }) +} + export const useUploadWsKey = () => useMutation<{}, {}, UploadWsKeyDTO>({ - mutationFn: ({ encryptedKey, nonce, userId, workspaceId }) => - apiRequest.post(`/api/v1/key/${workspaceId}`, { key: { userId, encryptedKey, nonce } }) + mutationFn: async ({ encryptedKey, nonce, userId, workspaceId }) => { + return uploadWsKey({ + workspaceId, + userId, + encryptedKey, + nonce + }); + } }); diff --git a/frontend/src/hooks/api/organization/index.ts b/frontend/src/hooks/api/organization/index.ts index ded8c3f29..7134d0501 100644 --- a/frontend/src/hooks/api/organization/index.ts +++ b/frontend/src/hooks/api/organization/index.ts @@ -4,7 +4,7 @@ export { useCreateCustomerPortalSession, useDeleteOrgPmtMethod, useDeleteOrgTaxId, - useGetOrganization, + useGetOrganizations, useGetOrgBillingDetails, useGetOrgInvoices, useGetOrgLicenses, diff --git a/frontend/src/hooks/api/organization/queries.tsx b/frontend/src/hooks/api/organization/queries.tsx index 66065c6ef..17f15307b 100644 --- a/frontend/src/hooks/api/organization/queries.tsx +++ b/frontend/src/hooks/api/organization/queries.tsx @@ -12,10 +12,11 @@ import { PmtMethod, ProductsTable, RenameOrgDTO, - TaxID} from "./types"; + TaxID +} from "./types"; const organizationKeys = { - getUserOrganization: ["organization"] as const, + getUserOrganizations: ["organization"] as const, getOrgPlanBillingInfo: (orgId: string) => [{ orgId }, "organization-plan-billing"] as const, getOrgPlanTable: (orgId: string) => [{ orgId }, "organization-plan-table"] as const, getOrgPlansTable: (orgId: string, billingCycle: "monthly" | "yearly") => [{ orgId, billingCycle }, "organization-plans-table"] as const, @@ -26,13 +27,16 @@ const organizationKeys = { getOrgLicenses: (orgId: string) => [{ orgId }, "organization-licenses"] as const }; -export const useGetOrganization = () => { - return useQuery({ - queryKey: organizationKeys.getUserOrganization, - queryFn: async () => { - const { data } = await apiRequest.get<{ organizations: Organization[] }>("/api/v1/organization"); +export const fetchOrganizations = async () => { + const { data: { organizations } } = await apiRequest.get<{ organizations: Organization[] }>("/api/v1/organization"); + return organizations; +} - return data.organizations; +export const useGetOrganizations = () => { + return useQuery({ + queryKey: organizationKeys.getUserOrganizations, + queryFn: async () => { + return fetchOrganizations(); } }); } @@ -41,10 +45,11 @@ export const useRenameOrg = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, RenameOrgDTO>({ - mutationFn: ({ newOrgName, orgId }) => - apiRequest.patch(`/api/v1/organization/${orgId}/name`, { name: newOrgName }), + mutationFn: ({ newOrgName, orgId }) => { + return apiRequest.patch(`/api/v1/organization/${orgId}/name`, { name: newOrgName }); + }, onSuccess: () => { - queryClient.invalidateQueries(organizationKeys.getUserOrganization); + queryClient.invalidateQueries(organizationKeys.getUserOrganizations); } }); }; diff --git a/frontend/src/hooks/api/secrets/queries.tsx b/frontend/src/hooks/api/secrets/queries.tsx index 6f65a8edd..e1c3e10bf 100644 --- a/frontend/src/hooks/api/secrets/queries.tsx +++ b/frontend/src/hooks/api/secrets/queries.tsx @@ -11,13 +11,13 @@ import { apiRequest } from "@app/config/request"; import { secretSnapshotKeys } from "../secretSnapshots/queries"; import { BatchSecretDTO, + CreateSecretDTO, DecryptedSecret, EncryptedSecret, EncryptedSecretVersion, GetProjectSecretsDTO, GetSecretVersionsDTO, - TGetProjectSecretsAllEnvDTO -} from "./types"; + TGetProjectSecretsAllEnvDTO} from "./types"; export const secretKeys = { // this is also used in secretSnapshot part @@ -324,3 +324,24 @@ export const useBatchSecretsOp = () => { } }); }; + +export const createSecret = async (dto: CreateSecretDTO) => { + const { data } = await apiRequest.post(`/api/v3/secrets/${dto.secretKey}`, dto); + return data; +} + +export const useCreateSecret = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, CreateSecretDTO>({ + mutationFn: async (dto) => { + const data = createSecret(dto); + return data; + }, + onSuccess: (_, dto) => { + queryClient.invalidateQueries( + secretKeys.getProjectSecret(dto.workspaceId, dto.environment) + ); + } + }); +}; \ No newline at end of file diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index c317da2c9..964bac6c2 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -147,3 +147,22 @@ export type TDeleteSecretsV3DTO = { secretPath: string; secretName: string; }; + +// --- v3 + +export type CreateSecretDTO = { + workspaceId: string; + environment: string; + type: "shared" | "personal"; + secretKey: string; + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretCommentCiphertext: string; + secretCommentIV: string; + secretCommentTag: string; + secretPath: string; +} \ No newline at end of file diff --git a/frontend/src/hooks/api/serviceTokens/queries.tsx b/frontend/src/hooks/api/serviceTokens/queries.tsx index 8cabdb9b6..4a0241cdf 100644 --- a/frontend/src/hooks/api/serviceTokens/queries.tsx +++ b/frontend/src/hooks/api/serviceTokens/queries.tsx @@ -23,12 +23,13 @@ const fetchWorkspaceServiceTokens = async (workspaceID: string) => { type UseGetWorkspaceServiceTokensProps = { workspaceID: string }; -export const useGetUserWsServiceTokens = ({ workspaceID }: UseGetWorkspaceServiceTokensProps) => - useQuery({ +export const useGetUserWsServiceTokens = ({ workspaceID }: UseGetWorkspaceServiceTokensProps) => { + return useQuery({ queryKey: serviceTokenKeys.getAllWorkspaceServiceToken(workspaceID), queryFn: () => fetchWorkspaceServiceTokens(workspaceID), enabled: Boolean(workspaceID) }); +} // mutation export const useCreateServiceToken = () => { @@ -36,6 +37,7 @@ export const useCreateServiceToken = () => { return useMutation({ mutationFn: async (body) => { + console.log("useCreateServiceToken"); const { data } = await apiRequest.post("/api/v2/service-token/", body); data.serviceToken += `.${body.randomBytes}`; return data; @@ -51,6 +53,7 @@ export const useDeleteServiceToken = () => { return useMutation({ mutationFn: async (serviceTokenId) => { + console.log("useDeleteServiceToken"); const { data } = await apiRequest.delete(`/api/v2/service-token/${serviceTokenId}`); return data; }, diff --git a/frontend/src/hooks/api/tags/queries.tsx b/frontend/src/hooks/api/tags/queries.tsx index 3134884b8..74900da0e 100644 --- a/frontend/src/hooks/api/tags/queries.tsx +++ b/frontend/src/hooks/api/tags/queries.tsx @@ -10,7 +10,6 @@ import { UserWsTags } from "./types"; - const workspaceTags = { getWsTags: (workspaceID: string) => ["workspace-tags", { workspaceID }] as const }; @@ -23,12 +22,13 @@ const fetchWsTag = async (workspaceID: string) => { return data.workspaceTags; }; -export const useGetWsTags = (workspaceID: string) => - useQuery({ +export const useGetWsTags = (workspaceID: string) => { + return useQuery({ queryKey: workspaceTags.getWsTags(workspaceID), queryFn: () => fetchWsTag(workspaceID), enabled: Boolean(workspaceID) }); +} export const useCreateWsTag = () => { const queryClient = useQueryClient(); @@ -59,4 +59,4 @@ export const useDeleteWsTag = () => { queryClient.invalidateQueries(workspaceTags.getWsTags(tagData?.workspace)); } }); -}; +}; \ No newline at end of file diff --git a/frontend/src/hooks/api/users/index.tsx b/frontend/src/hooks/api/users/index.tsx index a209367e2..2eb96d45d 100644 --- a/frontend/src/hooks/api/users/index.tsx +++ b/frontend/src/hooks/api/users/index.tsx @@ -7,6 +7,7 @@ export { useDeleteOrgMembership, useGetMyAPIKeys, useGetMyIp, + useGetMyOrganizationProjects, useGetMySessions, useGetOrgUsers, useGetUser, @@ -14,6 +15,6 @@ export { useLogoutUser, useRegisterUserAction, useRevokeMySessions, + useUpdateMfaEnabled, useUpdateOrgUserRole, - useUpdateUserAuthProvider -} from "./queries"; + useUpdateUserAuthProvider} from "./queries"; diff --git a/frontend/src/hooks/api/users/queries.tsx b/frontend/src/hooks/api/users/queries.tsx index 93d8d41de..a0a8ddc2f 100644 --- a/frontend/src/hooks/api/users/queries.tsx +++ b/frontend/src/hooks/api/users/queries.tsx @@ -19,7 +19,8 @@ import { RenameUserDTO, TokenVersion, UpdateOrgUserRoleDTO, - User} from "./types"; + User +} from "./types"; const userKeys = { getUser: ["user"] as const, @@ -27,7 +28,8 @@ const userKeys = { getOrgUsers: (orgId: string) => [{ orgId }, "user"], myIp: ["ip"] as const, myAPIKeys: ["api-keys"] as const, - mySessions: ["sessions"] as const + mySessions: ["sessions"] as const, + myOrganizationProjects: (orgId: string) => [{ orgId }, "organization-projects"] as const }; export const fetchUserDetails = async () => { @@ -38,7 +40,7 @@ export const fetchUserDetails = async () => { export const useGetUser = () => useQuery(userKeys.getUser, fetchUserDetails); -const fetchUserAction = async (action: string) => { +export const fetchUserAction = async (action: string) => { const { data } = await apiRequest.get<{ userAction: string }>("/api/v1/user-action", { params: { action @@ -146,7 +148,9 @@ export const useAddUserToOrg = () => { } return useMutation({ - mutationFn: (dto) => apiRequest.post("/api/v1/invite-org/signup", dto), + mutationFn: (dto) => { + return apiRequest.post("/api/v1/invite-org/signup", dto); + }, onSuccess: (_, { organizationId }) => { queryClient.invalidateQueries(userKeys.getOrgUsers(organizationId)); } @@ -157,8 +161,9 @@ export const useDeleteOrgMembership = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, DeletOrgMembershipDTO>({ - mutationFn: ({ membershipId, orgId }) => - apiRequest.delete(`/api/v2/organizations/${orgId}/memberships/${membershipId}`), + mutationFn: ({ membershipId, orgId }) => { + return apiRequest.delete(`/api/v2/organizations/${orgId}/memberships/${membershipId}`) + }, onSuccess: (_, { orgId }) => { queryClient.invalidateQueries(userKeys.getOrgUsers(orgId)); } @@ -169,10 +174,11 @@ export const useUpdateOrgUserRole = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, UpdateOrgUserRoleDTO>({ - mutationFn: ({ organizationId, membershipId, role }) => - apiRequest.patch(`/api/v2/organizations/${organizationId}/memberships/${membershipId}`, { + mutationFn: ({ organizationId, membershipId, role }) => { + return apiRequest.patch(`/api/v2/organizations/${organizationId}/memberships/${membershipId}`, { role - }), + }); + }, onSuccess: (_, { organizationId }) => { queryClient.invalidateQueries(userKeys.getOrgUsers(organizationId)); }, @@ -195,7 +201,9 @@ export const useRegisterUserAction = () => { export const useLogoutUser = () => useMutation({ - mutationFn: () => apiRequest.post("/api/v1/auth/logout"), + mutationFn: async () => { + await apiRequest.post("/api/v1/auth/logout"); + }, onSuccess: () => { setAuthToken(""); // Delete the cookie by not setting a value; Alternatively clear the local storage @@ -303,4 +311,45 @@ export const useRevokeMySessions = () => { queryClient.invalidateQueries(userKeys.mySessions); } }); +} + +export const useUpdateMfaEnabled = () => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: async ({ + isMfaEnabled + }: { + isMfaEnabled: boolean; + }) => { + const { data: { user } } = await apiRequest.patch( + "/api/v2/users/me/mfa", + { + isMfaEnabled + } + ); + + return user; + }, + onSuccess() { + queryClient.invalidateQueries(userKeys.getUser); + } + }); +} + +export const fetchMyOrganizationProjects = async (orgId: string) => { + const { data: { workspaces } } = await apiRequest.get( + `/api/v1/organization/${orgId}/my-workspaces` + ); + + return workspaces; +} + +export const useGetMyOrganizationProjects = (orgId: string) => { + return useQuery({ + queryKey: userKeys.myOrganizationProjects(orgId), + queryFn: async () => { + return fetchMyOrganizationProjects(orgId); + }, + enabled: true + }); } \ No newline at end of file diff --git a/frontend/src/hooks/api/users/types.ts b/frontend/src/hooks/api/users/types.ts index 0c312b2b6..fdef407fa 100644 --- a/frontend/src/hooks/api/users/types.ts +++ b/frontend/src/hooks/api/users/types.ts @@ -9,7 +9,7 @@ export enum AuthProvider { export type User = { createdAt: Date; updatedAt: Date; - email?: string; + email: string; firstName?: string; lastName?: string; authProvider?: AuthProvider; diff --git a/frontend/src/hooks/api/workspace/index.tsx b/frontend/src/hooks/api/workspace/index.tsx index bd06fedd3..42d3467d1 100644 --- a/frontend/src/hooks/api/workspace/index.tsx +++ b/frontend/src/hooks/api/workspace/index.tsx @@ -1,6 +1,8 @@ export { + useAddUserToWorkspace, useCreateWorkspace, useCreateWsEnvironment, + useDeleteUserFromWorkspace, useDeleteWorkspace, useDeleteWsEnvironment, useGetUserWorkspaceMemberships, @@ -11,8 +13,9 @@ export { useGetWorkspaceIndexStatus, useGetWorkspaceIntegrations, useGetWorkspaceSecrets, + useGetWorkspaceUsers, useNameWorkspaceSecrets, useRenameWorkspace, useToggleAutoCapitalization, - useUpdateWsEnvironment -} from "./queries"; + useUpdateUserWorkspaceRole, + useUpdateWsEnvironment} from "./queries"; diff --git a/frontend/src/hooks/api/workspace/queries.tsx b/frontend/src/hooks/api/workspace/queries.tsx index 9833c06fd..e5c2d6c96 100644 --- a/frontend/src/hooks/api/workspace/queries.tsx +++ b/frontend/src/hooks/api/workspace/queries.tsx @@ -29,7 +29,8 @@ export const workspaceKeys = { getWorkspaceIntegrations: (workspaceId: string) => [{ workspaceId }, "workspace-integrations"], getAllUserWorkspace: ["workspaces"] as const, getUserWsEnvironments: (workspaceId: string) => ["workspace-env", { workspaceId }] as const, - getWorkspaceAuditLogs: (workspaceId: string) => [{ workspaceId }] as const + getWorkspaceAuditLogs: (workspaceId: string) => [{ workspaceId }] as const, + getWorkspaceUsers: (workspaceId: string) => [{ workspaceId }] as const }; const fetchWorkspaceById = async (workspaceId: string) => { @@ -166,13 +167,21 @@ export const useGetWorkspaceIntegrations = (workspaceId: string) => enabled: Boolean(workspaceId) }); -// mutation +export const createWorkspace = ({ + organizationId, + workspaceName +}: CreateWorkspaceDTO): Promise<{ data: { workspace: Workspace } }> => { + return apiRequest.post("/api/v1/workspace", { workspaceName, organizationId }); +} + export const useCreateWorkspace = () => { const queryClient = useQueryClient(); return useMutation<{ data: { workspace: Workspace } }, {}, CreateWorkspaceDTO>({ - mutationFn: async ({ organizationId, workspaceName }) => - apiRequest.post("/api/v1/workspace", { workspaceName, organizationId }), + mutationFn: async ({ organizationId, workspaceName }) => createWorkspace({ + organizationId, + workspaceName + }), onSuccess: () => { queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace); } @@ -183,8 +192,9 @@ export const useRenameWorkspace = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, RenameWorkspaceDTO>({ - mutationFn: ({ workspaceID, newWorkspaceName }) => - apiRequest.post(`/api/v1/workspace/${workspaceID}/name`, { name: newWorkspaceName }), + mutationFn: ({ workspaceID, newWorkspaceName }) => { + return apiRequest.post(`/api/v1/workspace/${workspaceID}/name`, { name: newWorkspaceName }); + }, onSuccess: () => { queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace); } @@ -209,7 +219,9 @@ export const useDeleteWorkspace = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, DeleteWorkspaceDTO>({ - mutationFn: ({ workspaceID }) => apiRequest.delete(`/api/v1/workspace/${workspaceID}`), + mutationFn: ({ workspaceID }) => { + return apiRequest.delete(`/api/v1/workspace/${workspaceID}`); + }, onSuccess: () => { queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace); } @@ -220,11 +232,12 @@ export const useCreateWsEnvironment = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, CreateEnvironmentDTO>({ - mutationFn: ({ workspaceID, environmentName, environmentSlug }) => - apiRequest.post(`/api/v2/workspace/${workspaceID}/environments`, { + mutationFn: ({ workspaceID, environmentName, environmentSlug }) => { + return apiRequest.post(`/api/v2/workspace/${workspaceID}/environments`, { environmentName, environmentSlug - }), + }); + }, onSuccess: () => { queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace); } @@ -235,12 +248,13 @@ export const useUpdateWsEnvironment = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, UpdateEnvironmentDTO>({ - mutationFn: ({ workspaceID, environmentName, environmentSlug, oldEnvironmentSlug }) => - apiRequest.put(`/api/v2/workspace/${workspaceID}/environments`, { + mutationFn: ({ workspaceID, environmentName, environmentSlug, oldEnvironmentSlug }) => { + return apiRequest.put(`/api/v2/workspace/${workspaceID}/environments`, { environmentName, environmentSlug, oldEnvironmentSlug - }), + }); + }, onSuccess: () => { queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace); } @@ -251,13 +265,85 @@ export const useDeleteWsEnvironment = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, DeleteEnvironmentDTO>({ - mutationFn: ({ workspaceID, environmentSlug }) => - apiRequest.delete(`/api/v2/workspace/${workspaceID}/environments`, { + mutationFn: ({ workspaceID, environmentSlug }) => { + return apiRequest.delete(`/api/v2/workspace/${workspaceID}/environments`, { data: { environmentSlug } - }), + }); + }, onSuccess: () => { queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace); } }); }; +export const useGetWorkspaceUsers = (workspaceId: string) => { + return useQuery({ + queryKey: workspaceKeys.getWorkspaceUsers(workspaceId), + queryFn: async () => { + const { data: { users } } = await apiRequest.get( + `/api/v1/workspace/${workspaceId}/users` + ); + return users; + }, + enabled: true + }); +} + +export const useAddUserToWorkspace = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ + email, + workspaceId + }: { + email: string; + workspaceId: string; + }) => { + const { data: { invitee, latestKey } } = await apiRequest.post(`/api/v1/workspace/${workspaceId}/invite-signup`, { email }); + + return ({ + invitee, + latestKey + }); + }, + onSuccess: (_, dto) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceUsers(dto.workspaceId)); + } + }); +}; + +export const useDeleteUserFromWorkspace = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async (membershipId: string) => { + const { data: { deletedMembership } } = await apiRequest.delete(`/api/v1/membership/${membershipId}`); + return deletedMembership; + }, + onSuccess: (res) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceUsers(res.workspace)); + } + }); +}; + +export const useUpdateUserWorkspaceRole = () => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: async ({ + membershipId, + role + }: { + membershipId: string; + role: string; + }) => { + const { data: { membership } } = await apiRequest.post(`/api/v1/membership/${membershipId}/change-role`, { + role + }); + return membership; + }, + onSuccess: (res) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceUsers(res.workspace)); + } + }); +}; diff --git a/frontend/src/pages/api/auth/ChangePassword2.ts b/frontend/src/pages/api/auth/ChangePassword2.ts deleted file mode 100644 index 8381c13ad..000000000 --- a/frontend/src/pages/api/auth/ChangePassword2.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { apiRequest } from "@app/config/request"; - -interface Props { - clientProof: string; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - salt: string; - verifier: string; -} - -/** - * This is the second step of the change password process (pake) - * @param {*} clientPublicKey - * @returns - */ -const changePassword2 = async ({ - clientProof, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier -}: Props) => { - const { data } = await apiRequest.post("/api/v1/password/change-password", { - clientProof, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - }); - - return data; -} - -export default changePassword2; diff --git a/frontend/src/pages/api/auth/CheckAuth.ts b/frontend/src/pages/api/auth/CheckAuth.ts index 9b39c6933..f1b98f087 100644 --- a/frontend/src/pages/api/auth/CheckAuth.ts +++ b/frontend/src/pages/api/auth/CheckAuth.ts @@ -4,12 +4,13 @@ import SecurityClient from "@app/components/utilities/SecurityClient"; * This function is used to check if the user is authenticated. * To do that, we get their tokens from cookies, and verify if they are good. */ -const checkAuth = async () => - SecurityClient.fetchCall("/api/v1/auth/checkAuth", { +const checkAuth = async () => { + return SecurityClient.fetchCall("/api/v1/auth/checkAuth", { method: "POST", headers: { "Content-Type": "application/json" } }).then((res) => res); +} export default checkAuth; diff --git a/frontend/src/pages/api/auth/CheckEmailVerificationCode.ts b/frontend/src/pages/api/auth/CheckEmailVerificationCode.ts deleted file mode 100644 index 5cbd9dc2b..000000000 --- a/frontend/src/pages/api/auth/CheckEmailVerificationCode.ts +++ /dev/null @@ -1,24 +0,0 @@ -interface Props { - email: string; - code: string; -} - -/** - * This route check the verification code from the email that user just recieved - * @param {object} obj - * @param {string} obj.email - * @param {string} obj.code - * @returns - */ -const checkEmailVerificationCode = ({ email, code }: Props) => fetch("/api/v1/signup/email/verify", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email, - code - }) - }); - -export default checkEmailVerificationCode; diff --git a/frontend/src/pages/api/auth/CompleteAccountInformationSignup.ts b/frontend/src/pages/api/auth/CompleteAccountInformationSignup.ts deleted file mode 100644 index 37ceb4e3a..000000000 --- a/frontend/src/pages/api/auth/CompleteAccountInformationSignup.ts +++ /dev/null @@ -1,79 +0,0 @@ - -import { apiRequest } from "@app/config/request"; - -interface Props { - email: string; - firstName: string; - lastName: string; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - providerAuthToken?: string; - publicKey: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - organizationName: string; - salt: string; - verifier: string; - attributionSource?: string; -} - -/** - * This function is called in the end of the signup process. - * It sends all the necessary nformation to the server. - * @param {object} obj - * @param {string} obj.email - email of the user completing signup - * @param {string} obj.firstName - first name of the user completing signup - * @param {string} obj.lastName - last name of the user completing sign up - * @param {string} obj.protectedKey - protected key in encryption version 2 - * @param {string} obj.protectedKeyIV - IV of protected key in encryption version 2 - * @param {string} obj.protectedKeyTag - tag of protected key in encryption version 2 - * @param {string} obj.organizationName - organization name for this user (usually, [FIRST_NAME]'s organization) - * @param {string} obj.publicKey - public key of the user completing signup - * @param {string} obj.ciphertext - * @param {string} obj.iv - * @param {string} obj.tag - * @param {string} obj.salt - * @param {string} obj.verifier - * @returns - */ -const completeAccountInformationSignup = async ({ - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - organizationName, - providerAuthToken, - attributionSource -}: Props) => { - const { data } = await apiRequest.post("/api/v3/signup/complete-account/signup", { - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - organizationName, - providerAuthToken, - ...(attributionSource ? { attributionSource } : {}) - }); - - return data; -} - -export default completeAccountInformationSignup; diff --git a/frontend/src/pages/api/auth/CompleteAccountInformationSignupInvite.ts b/frontend/src/pages/api/auth/CompleteAccountInformationSignupInvite.ts deleted file mode 100644 index e2264b3d6..000000000 --- a/frontend/src/pages/api/auth/CompleteAccountInformationSignupInvite.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { apiRequest } from "@app/config/request"; - -interface Props { - email: string; - firstName: string; - lastName: string; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - publicKey: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - salt: string; - verifier: string; -} - -// missing token? -// TODO: add to SecurityClient - - -/** - * This function is called in the end of the signup process. - * It sends all the necessary nformation to the server. - * @param {object} obj - * @param {string} obj.email - email of the user completing signupinvite flow - * @param {string} obj.firstName - first name of the user completing signupinvite flow - * @param {string} obj.lastName - last name of the user completing signupinvite flow - * @param {string} obj.publicKey - public key of the user completing signupinvite flow - * @param {string} obj.ciphertext - * @param {string} obj.iv - * @param {string} obj.tag - * @param {string} obj.salt - * @param {string} obj.verifier - * @param {string} obj.token - token that confirms a user's identity - * @returns - */ -const completeAccountInformationSignupInvite = async ({ - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier -}: Props) => { - const { data } = await apiRequest.post("/api/v2/signup/complete-account/invite", { - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - }); - - return data; -} - -export default completeAccountInformationSignupInvite; diff --git a/frontend/src/pages/api/auth/EmailVerifyOnPasswordReset.ts b/frontend/src/pages/api/auth/EmailVerifyOnPasswordReset.ts deleted file mode 100644 index 8e601c6a4..000000000 --- a/frontend/src/pages/api/auth/EmailVerifyOnPasswordReset.ts +++ /dev/null @@ -1,34 +0,0 @@ -interface Props { - email: string; - code: string; -} - -/** - * This is the second part of the account recovery step (a user needs to verify their email). - * A user need to click on a button in a magic link page - * @param {object} obj - * @param {object} obj.email - email of a user that is trying to recover access to their account - * @param {object} obj.code - token that a use received via the magic link - * @returns - */ -const EmailVerifyOnPasswordReset = async ({ email, code }: Props) => { - const response = await fetch("/api/v1/password/email/password-reset-verify", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email, - code - }) - }); - if (response?.status === 200) { - return response; - } - - throw new Error( - "Something went wrong during email verification on password reset." - ); -}; - -export default EmailVerifyOnPasswordReset; diff --git a/frontend/src/pages/api/auth/IssueBackupPrivateKey.ts b/frontend/src/pages/api/auth/IssueBackupPrivateKey.ts deleted file mode 100644 index e5fe18359..000000000 --- a/frontend/src/pages/api/auth/IssueBackupPrivateKey.ts +++ /dev/null @@ -1,51 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - encryptedPrivateKey: string; - iv: string; - tag: string; - salt: string; - verifier: string; - clientProof: string; -} - -/** - * This is the route that issues a backup private key that will afterwards be added into a pdf - * @param {object} obj - * @param {string} obj.encryptedPrivateKey - * @param {string} obj.iv - * @param {string} obj.tag - * @param {string} obj.salt - * @param {string} obj.verifier - * @param {string} obj.clientProof - * @returns - */ -const issueBackupPrivateKey = ({ - encryptedPrivateKey, - iv, - tag, - salt, - verifier, - clientProof -}: Props) => - SecurityClient.fetchCall("/api/v1/password/backup-private-key", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - clientProof, - encryptedPrivateKey, - iv, - tag, - salt, - verifier - }) - }).then((res) => { - if (res?.status !== 200) { - console.log("Failed to issue the backup key"); - } - return res; - }); - -export default issueBackupPrivateKey; diff --git a/frontend/src/pages/api/auth/Login1.ts b/frontend/src/pages/api/auth/Login1.ts deleted file mode 100644 index 85377d34c..000000000 --- a/frontend/src/pages/api/auth/Login1.ts +++ /dev/null @@ -1,33 +0,0 @@ -interface Login1 { - serverPublicKey: string; - salt: string; -} - -/** - * This is the first step of the login process (pake) - * @param {*} email - * @param {*} clientPublicKey - * @returns - */ -const login1 = async (loginDetails: { - email: string; - clientPublicKey: string; - providerAuthToken?: string; -}) => { - const response = await fetch("/api/v3/auth/login1", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(loginDetails), - }); - // need precise error handling about the status code - if (response?.status === 200) { - const data = (await response.json()) as unknown as Login1; - return data; - } - - throw new Error("Wrong password"); -}; - -export default login1; diff --git a/frontend/src/pages/api/auth/Login2.ts b/frontend/src/pages/api/auth/Login2.ts deleted file mode 100644 index ea9df262b..000000000 --- a/frontend/src/pages/api/auth/Login2.ts +++ /dev/null @@ -1,42 +0,0 @@ -interface Login2Response { - mfaEnabled: boolean; - token: string; - encryptionVersion?: number; - protectedKey?: string; - protectedKeyIV?: string; - protectedKeyTag?: string; - publicKey?: string; - encryptedPrivateKey?: string; - iv?: string; - tag?: string; -} - -/** - * This is the second step of the login process - * @param {*} email - * @param {*} clientPublicKey - * @returns - */ -const login2 = async (loginDetails: { - email: string; - clientProof: string; - providerAuthToken?: string; -}) => { - const response = await fetch("/api/v3/auth/login2", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(loginDetails), - credentials: "include" - }); - // need precise error handling about the status code - if (response.status === 200) { - const data = (await response.json()) as unknown as Login2Response; - return data; - } - - throw new Error("Password verification failed"); -}; - -export default login2; diff --git a/frontend/src/pages/api/auth/Logout.ts b/frontend/src/pages/api/auth/Logout.ts deleted file mode 100644 index 343e093ed..000000000 --- a/frontend/src/pages/api/auth/Logout.ts +++ /dev/null @@ -1,41 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route logs the user out. Note: the user should authorized to do this. - * We first try to log out - if the authorization fails (response.status = 401), we refetch the new token, and then retry - */ -const logout = async () => { - try { - const res = await SecurityClient.fetchCall("/api/v1/auth/logout", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - credentials: "include" - }); - - if (res?.status === 200) { - SecurityClient.setToken(""); - // Delete the cookie by not setting a value; Alternatively clear the local storage - localStorage.removeItem("protectedKey"); - localStorage.removeItem("protectedKeyIV"); - localStorage.removeItem("protectedKeyTag"); - localStorage.removeItem("publicKey"); - localStorage.removeItem("encryptedPrivateKey"); - localStorage.removeItem("iv"); - localStorage.removeItem("tag"); - localStorage.removeItem("PRIVATE_KEY"); - localStorage.removeItem("orgData.id"); - localStorage.removeItem("projectData.id"); - - return res; - } - - } catch (error) { - console.log("Error logging out", error); - } - - return undefined; -}; - -export default logout; diff --git a/frontend/src/pages/api/auth/SRP1.ts b/frontend/src/pages/api/auth/SRP1.ts deleted file mode 100644 index 142df3d7c..000000000 --- a/frontend/src/pages/api/auth/SRP1.ts +++ /dev/null @@ -1,29 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - clientPublicKey: string; -} - -/** - * This is the first step of the change password process (pake) - * @param {string} clientPublicKey - * @returns - */ -const SRP1 = ({ clientPublicKey }: Props) => - SecurityClient.fetchCall("/api/v1/password/srp1", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - clientPublicKey - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to do the first step of SRP"); - return undefined; - }); - -export default SRP1; diff --git a/frontend/src/pages/api/auth/SendEmailOnPasswordReset.ts b/frontend/src/pages/api/auth/SendEmailOnPasswordReset.ts deleted file mode 100644 index 37c6d14d2..000000000 --- a/frontend/src/pages/api/auth/SendEmailOnPasswordReset.ts +++ /dev/null @@ -1,33 +0,0 @@ -interface Props { - email: string; -} - -/** - * This is the first of the account recovery step (a user needs to verify their email). - * It will send an email containing a magic link to start the account recovery flow. - * @param {object} obj - * @param {object} obj.email - email of a user that is trying to recover access to their account - * @returns - */ -const SendEmailOnPasswordReset = async ({ email }: Props) => { - const response = await fetch("/api/v1/password/email/password-reset", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email - }) - }); - // need precise error handling about the status code - if (response?.status === 200) { - const data = await response.json(); - return data; - } - - throw new Error( - "Something went wrong while sending the email verification for password reset." - ); -}; - -export default SendEmailOnPasswordReset; diff --git a/frontend/src/pages/api/auth/SendVerificationEmail.ts b/frontend/src/pages/api/auth/SendVerificationEmail.ts deleted file mode 100644 index 92180cc04..000000000 --- a/frontend/src/pages/api/auth/SendVerificationEmail.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * This route send the verification email to the user's email (contains a 6-digit verification code) - * @param {*} email - */ -const sendVerificationEmail = (email: string) => { - fetch("/api/v1/signup/email/signup", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email - }) - }); -}; - -export default sendVerificationEmail; diff --git a/frontend/src/pages/api/auth/Token.ts b/frontend/src/pages/api/auth/Token.ts deleted file mode 100644 index 6bd5b5097..000000000 --- a/frontend/src/pages/api/auth/Token.ts +++ /dev/null @@ -1,16 +0,0 @@ -const token = async () => - fetch("/api/v1/auth/token", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - credentials: "include" - }).then(async (res) => { - if (res.status === 200) { - return (await res.json()).token; - } - console.log("Getting a new token failed"); - return undefined; - }); - -export default token; diff --git a/frontend/src/pages/api/auth/VerifySignupInvite.ts b/frontend/src/pages/api/auth/VerifySignupInvite.ts deleted file mode 100644 index 89dbb4db8..000000000 --- a/frontend/src/pages/api/auth/VerifySignupInvite.ts +++ /dev/null @@ -1,27 +0,0 @@ -interface Props { - email: string; - code: string; - organizationId: string; -} - -/** - * This route verifies the signup invite link - * @param {object} obj - * @param {string} obj.email - email that a user is trying to verify - * @param {string} obj.organizationId - id of organization that a user is trying to verify for - * @param {string} obj.code - code that a user received to the abovementioned email - * @returns - */ -const verifySignupInvite = ({ email, organizationId, code }: Props) => fetch("/api/v1/invite-org/verify", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email, - organizationId, - code - }) - }); - -export default verifySignupInvite; diff --git a/frontend/src/pages/api/auth/getBackupEncryptedPrivateKey.ts b/frontend/src/pages/api/auth/getBackupEncryptedPrivateKey.ts deleted file mode 100644 index f344b575e..000000000 --- a/frontend/src/pages/api/auth/getBackupEncryptedPrivateKey.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * This is the route that get an encrypted private key (will be decrypted with a backup key) - * @param {object} obj - * @param {object} obj.verificationToken - this is the token that confirms that a user is the right one - * @returns - */ -const getBackupEncryptedPrivateKey = ({ - verificationToken -}: { - verificationToken: string; -}) => fetch("/api/v1/password/backup-private-key", { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${ verificationToken}` - } - }).then(async (res) => { - if (res?.status !== 200) { - console.log("Failed to get the backup key"); - } - return (await res?.json())?.backupPrivateKey; - }); - -export default getBackupEncryptedPrivateKey; diff --git a/frontend/src/pages/api/auth/publicKeyInfisical.ts b/frontend/src/pages/api/auth/publicKeyInfisical.ts deleted file mode 100644 index 60caa411a..000000000 --- a/frontend/src/pages/api/auth/publicKeyInfisical.ts +++ /dev/null @@ -1,8 +0,0 @@ -const publicKeyInfisical = () => fetch("/api/v1/key/publicKey/infisical", { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }); - -export default publicKeyInfisical; diff --git a/frontend/src/pages/api/auth/resetPasswordOnAccountRecovery.ts b/frontend/src/pages/api/auth/resetPasswordOnAccountRecovery.ts deleted file mode 100644 index aa93b03ed..000000000 --- a/frontend/src/pages/api/auth/resetPasswordOnAccountRecovery.ts +++ /dev/null @@ -1,57 +0,0 @@ -interface Props { - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - salt: string; - verifier: string; - verificationToken: string; -} - -/** - * This is the route that resets the account password if all the previus steps were passed - * @param {object} obj - * @param {object} obj.verificationToken - this is the token that confirms that a user is the right one - * @param {object} obj.encryptedPrivateKey - the new encrypted private key (encrypted using the new password) - * @param {object} obj.iv - * @param {object} obj.tag - * @param {object} obj.salt - * @param {object} obj.verifier - * @returns - */ -const resetPasswordOnAccountRecovery = ({ - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - verificationToken, -}: Props) => fetch("/api/v1/password/password-reset", { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${verificationToken}` - }, - body: JSON.stringify({ - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - }) - }).then(async (res) => { - if (res?.status !== 200) { - console.log("Failed to get the backup key"); - } - return res; - }); - -export default resetPasswordOnAccountRecovery; diff --git a/frontend/src/pages/api/auth/verifyMfaToken.ts b/frontend/src/pages/api/auth/verifyMfaToken.ts deleted file mode 100644 index fc298d0fe..000000000 --- a/frontend/src/pages/api/auth/verifyMfaToken.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { apiRequest } from "@app/config/request"; - -/** - * Verify MFA token [mfaToken] for user with email [email] - * @param {object} obj - * @param {string} obj.email - email of user - * @param {string} obj.mfaToken - MFA cod/token to verify - * @returns - */ -const verifyMfaToken = async ({ - email, - mfaToken -}: { - email: string; - mfaToken: string; -}) => { - const { data } = await apiRequest.post("/api/v2/auth/mfa/verify", { - email, - mfaToken - }); - - return data; -} - -export default verifyMfaToken; diff --git a/frontend/src/pages/api/bot/getBot.ts b/frontend/src/pages/api/bot/getBot.ts deleted file mode 100644 index 2579db67f..000000000 --- a/frontend/src/pages/api/bot/getBot.ts +++ /dev/null @@ -1,27 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - workspaceId: string; -} - -/** - * This function fetches the bot for a project - * @param {Object} obj - * @param {String} obj.workspaceId - * @returns - */ -const getBot = async ({ workspaceId }: Props) => - SecurityClient.fetchCall(`/api/v1/bot/${workspaceId}`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).bot; - } - console.log("Failed to get bot for project"); - return undefined; - }); - -export default getBot; diff --git a/frontend/src/pages/api/bot/setBotActiveStatus.ts b/frontend/src/pages/api/bot/setBotActiveStatus.ts deleted file mode 100644 index 68852b50c..000000000 --- a/frontend/src/pages/api/bot/setBotActiveStatus.ts +++ /dev/null @@ -1,42 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface BotKey { - encryptedKey: string; - nonce: string; -} - -interface Props { - botId: string; - isActive: boolean; - botKey?: BotKey; -} - -/** - * This function sets the active status of a bot and shares a copy of - * the project key (encrypted under the bot's public key) with the - * project's bot - * @param {Object} obj - * @param {String} obj.botId - * @param {String} obj.isActive - * @param {Object} obj.botKey - * @returns - */ -const setBotActiveStatus = async ({ botId, isActive, botKey }: Props) => - SecurityClient.fetchCall(`/api/v1/bot/${botId}/active`, { - method: "PATCH", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - isActive, - botKey - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to get bot for project"); - return undefined; - }); - -export default setBotActiveStatus; diff --git a/frontend/src/pages/api/environments/createEnvironment.ts b/frontend/src/pages/api/environments/createEnvironment.ts deleted file mode 100644 index 52e7562c9..000000000 --- a/frontend/src/pages/api/environments/createEnvironment.ts +++ /dev/null @@ -1,28 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -type NewEnvironmentInfo = { - environmentSlug: string; - environmentName: string; -}; - -/** - * This route deletes a specified workspace. - * @param {*} workspaceId - * @returns - */ -const createEnvironment = (workspaceId: string, newEnv: NewEnvironmentInfo) => - SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/environments`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(newEnv) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to create environment"); - return undefined; - }); - -export default createEnvironment; diff --git a/frontend/src/pages/api/environments/deleteEnvironment.ts b/frontend/src/pages/api/environments/deleteEnvironment.ts deleted file mode 100644 index d94f411f7..000000000 --- a/frontend/src/pages/api/environments/deleteEnvironment.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; -/** - * This route deletes a specified env. - * @param {*} workspaceId - * @returns - */ -const deleteEnvironment = (workspaceId: string, environmentSlug: string) => - SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/environments`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ environmentSlug }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to delete environment"); - return undefined; - }); - -export default deleteEnvironment; diff --git a/frontend/src/pages/api/environments/updateEnvironment.ts b/frontend/src/pages/api/environments/updateEnvironment.ts deleted file mode 100644 index 2e671de98..000000000 --- a/frontend/src/pages/api/environments/updateEnvironment.ts +++ /dev/null @@ -1,29 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -type EnvironmentInfo = { - oldEnvironmentSlug: string; - environmentSlug: string; - environmentName: string; -}; - -/** - * This route updates a specified environment. - * @param {*} workspaceId - * @returns - */ -const updateEnvironment = (workspaceId: string, env: EnvironmentInfo) => - SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/environments`, { - method: "PUT", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(env) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to update environment"); - return undefined; - }); - -export default updateEnvironment; diff --git a/frontend/src/pages/api/files/AddSecrets.ts b/frontend/src/pages/api/files/AddSecrets.ts deleted file mode 100644 index fe23aa3a0..000000000 --- a/frontend/src/pages/api/files/AddSecrets.ts +++ /dev/null @@ -1,54 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface EncryptedSecretProps { - id: string; - createdAt: string; - environment: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - type: "personal" | "shared"; -} - -/** - * This function adds secrets to a certain project - * @param {object} obj - * @param {EncryptedSecretProps} obj.secrets - the ids of secrets that we want to add - * @param {string} obj.env - the environment to which we are adding secrets - * @param {string} obj.workspaceId - the project to which we are adding secrets - * @returns - */ -const addSecrets = async ({ - secrets, - env, - workspaceId -}: { - secrets: EncryptedSecretProps[]; - env: string; - workspaceId: string; -}) => - SecurityClient.fetchCall("/api/v2/secrets", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - environment: env, - workspaceId, - secrets - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to add certain project secrets"); - return undefined; - }); - -export default addSecrets; diff --git a/frontend/src/pages/api/files/DeleteSecrets.ts b/frontend/src/pages/api/files/DeleteSecrets.ts deleted file mode 100644 index 6ea22b8e4..000000000 --- a/frontend/src/pages/api/files/DeleteSecrets.ts +++ /dev/null @@ -1,25 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function deletes certain secrets from a certain project - * @param {string[]} secretIds - the ids of secrets that we want to be deleted - * @returns - */ -const deleteSecrets = async ({ secretIds }: { secretIds: string[] }) => - SecurityClient.fetchCall("/api/v2/secrets", { - method: "DELETE", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - secretIds - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to delete certain project secrets"); - return undefined; - }); - -export default deleteSecrets; diff --git a/frontend/src/pages/api/files/GetSecrets.ts b/frontend/src/pages/api/files/GetSecrets.ts deleted file mode 100644 index d8e8caa40..000000000 --- a/frontend/src/pages/api/files/GetSecrets.ts +++ /dev/null @@ -1,29 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function fetches the encrypted secrets for a certain project - * @param {string} workspaceId - project is for which a user is trying to get secrets - * @param {string} env - environment of a project for which a user is trying ot get secrets - * @returns - */ -const getSecrets = async (workspaceId: string, env: string) => - SecurityClient.fetchCall( - `/api/v2/secrets?${new URLSearchParams({ - environment: env, - workspaceId - })}`, - { - method: "GET", - headers: { - "Content-Type": "application/json" - } - } - ).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).secrets; - } - console.log("Failed to get project secrets"); - return undefined; - }); - -export default getSecrets; diff --git a/frontend/src/pages/api/files/UpdateSecrets.ts b/frontend/src/pages/api/files/UpdateSecrets.ts deleted file mode 100644 index 03b8a18fb..000000000 --- a/frontend/src/pages/api/files/UpdateSecrets.ts +++ /dev/null @@ -1,42 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface EncryptedSecretProps { - id: string; - createdAt: string; - environment: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - type: "personal" | "shared"; -} - -/** - * This function updates certain secrets in a certain project - * @param {object} obj - * @param {EncryptedSecretProps[]} obj.secrets - the ids of secrets that we want to update - * @returns - */ -const updateSecrets = async ({ secrets }: { secrets: EncryptedSecretProps[] }) => - SecurityClient.fetchCall("/api/v2/secrets", { - method: "PATCH", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - secrets - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to update certain project secrets"); - return undefined; - }); - -export default updateSecrets; diff --git a/frontend/src/pages/api/files/UploadSecrets.ts b/frontend/src/pages/api/files/UploadSecrets.ts deleted file mode 100644 index b23f4e5bb..000000000 --- a/frontend/src/pages/api/files/UploadSecrets.ts +++ /dev/null @@ -1,39 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - workspaceId: string; - secrets: any; - keys: string; - environment: string; -} - -/** - * This function uploads the encrypted .env file - * @param {object} obj - * @param {string} obj.workspaceId - * @param {} obj.secrets - * @param {} obj.keys - * @param {string} obj.environment - * @returns - */ -const uploadSecrets = async ({ workspaceId, secrets, keys, environment }: Props) => - SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/secrets`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - secrets, - keys, - environment, - channel: "web" - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to push secrets"); - return undefined; - }); - -export default uploadSecrets; diff --git a/frontend/src/pages/api/files/batchSecrets.ts b/frontend/src/pages/api/files/batchSecrets.ts deleted file mode 100644 index 69b88a451..000000000 --- a/frontend/src/pages/api/files/batchSecrets.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { apiRequest } from "@app/config/request"; - -interface RequestType { - method: string; - secret: { - type: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[]; - } -} - -const batchSecrets = async ({ - workspaceId, - environment, - requests -}: { - workspaceId: string; - environment: string; - requests: RequestType[]; -}) => { - const { data } = await apiRequest.post("/api/v2/secrets/batch", { - workspaceId, - environment, - requests - }); - - return data; -} - -export default batchSecrets; \ No newline at end of file diff --git a/frontend/src/pages/api/integrations/ChangeHerokuConfigVars.ts b/frontend/src/pages/api/integrations/ChangeHerokuConfigVars.ts deleted file mode 100644 index 5d79ebc64..000000000 --- a/frontend/src/pages/api/integrations/ChangeHerokuConfigVars.ts +++ /dev/null @@ -1,37 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - integrationId: string; - key: { encryptedKey: any; nonce: any }; - secrets: { - ciphertextKey: any; - ivKey: any; - tagKey: any; - hashKey: any; - ciphertextValue: any; - ivValue: any; - tagValue: any; - hashValue: any; - type: string; - }[]; -} - -const changeHerokuConfigVars = ({ integrationId, key, secrets }: Props) => - SecurityClient.fetchCall(`/api/v1/integration/${integrationId}/sync`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - key, - secrets - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to sync secrets to Heroku"); - return undefined; - }); - -export default changeHerokuConfigVars; diff --git a/frontend/src/pages/api/integrations/DeleteIntegration.ts b/frontend/src/pages/api/integrations/DeleteIntegration.ts deleted file mode 100644 index b9253869a..000000000 --- a/frontend/src/pages/api/integrations/DeleteIntegration.ts +++ /dev/null @@ -1,25 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - integrationId: string; -} - -/** - * This route deletes an integration from a certain project - * @param {*} integrationId - * @returns - */ -const deleteIntegration = ({ integrationId }: Props) => - SecurityClient.fetchCall(`/api/v1/integration/${integrationId}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integration; - } - return undefined; - }); - -export default deleteIntegration; diff --git a/frontend/src/pages/api/integrations/DeleteIntegrationAuth.ts b/frontend/src/pages/api/integrations/DeleteIntegrationAuth.ts deleted file mode 100644 index c43de0b3a..000000000 --- a/frontend/src/pages/api/integrations/DeleteIntegrationAuth.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - integrationAuthId: string; -} - -/** - * This route deletes an integration authorization from a certain project - * @param {*} integrationAuthId - * @returns - */ -const deleteIntegrationAuth = ({ integrationAuthId }: Props) => - SecurityClient.fetchCall(`/api/v1/integration-auth/${integrationAuthId}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integrationAuth; - } - console.log("Failed to delete an integration authorization"); - return undefined; - }); - -export default deleteIntegrationAuth; diff --git a/frontend/src/pages/api/integrations/GetIntegrationApps.ts b/frontend/src/pages/api/integrations/GetIntegrationApps.ts deleted file mode 100644 index c1784cf9c..000000000 --- a/frontend/src/pages/api/integrations/GetIntegrationApps.ts +++ /dev/null @@ -1,21 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - integrationAuthId: string; -} - -const getIntegrationApps = ({ integrationAuthId }: Props) => - SecurityClient.fetchCall(`/api/v1/integration-auth/${integrationAuthId}/apps`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).apps; - } - console.log("Failed to get available apps for an integration"); - return undefined; - }); - -export default getIntegrationApps; diff --git a/frontend/src/pages/api/integrations/GetIntegrationOptions.ts b/frontend/src/pages/api/integrations/GetIntegrationOptions.ts deleted file mode 100644 index eacdb9e9d..000000000 --- a/frontend/src/pages/api/integrations/GetIntegrationOptions.ts +++ /dev/null @@ -1,17 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -const getIntegrationOptions = () => - SecurityClient.fetchCall("/api/v1/integration-auth/integration-options", { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integrationOptions; - } - console.log("Failed to get (cloud) integration options"); - return undefined; - }); - -export default getIntegrationOptions; diff --git a/frontend/src/pages/api/integrations/StartIntegration.ts b/frontend/src/pages/api/integrations/StartIntegration.ts deleted file mode 100644 index 9172b378b..000000000 --- a/frontend/src/pages/api/integrations/StartIntegration.ts +++ /dev/null @@ -1,35 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - integrationId: string; - appName: string; - environment: string; -} - -/** - * This route starts the integration after teh default one if gonna set up. - * @param {*} integrationId - * @returns - */ -const startIntegration = ({ integrationId, appName, environment }: Props) => - SecurityClient.fetchCall(`/api/v1/integration/${integrationId}`, { - method: "PATCH", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - update: { - app: appName, - environment, - isActive: true - } - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to start an integration"); - return undefined; - }); - -export default startIntegration; diff --git a/frontend/src/pages/api/integrations/authorizeIntegration.ts b/frontend/src/pages/api/integrations/authorizeIntegration.ts deleted file mode 100644 index b80a6e36d..000000000 --- a/frontend/src/pages/api/integrations/authorizeIntegration.ts +++ /dev/null @@ -1,35 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - workspaceId: string; - code: string; - integration: string; -} -/** - * This is the first step of the change password process (pake) - * @param {object} obj - * @param {object} obj.workspaceId - project id for which we want to authorize the integration - * @param {object} obj.code - * @param {object} obj.integration - integration which a user is trying to turn on - * @returns - */ -const AuthorizeIntegration = ({ workspaceId, code, integration }: Props) => - SecurityClient.fetchCall("/api/v1/integration-auth/oauth-token", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - workspaceId, - code, - integration - }) - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integrationAuth; - } - console.log("Failed to authorize the integration"); - return undefined; - }); - -export default AuthorizeIntegration; diff --git a/frontend/src/pages/api/integrations/createIntegration.ts b/frontend/src/pages/api/integrations/createIntegration.ts deleted file mode 100644 index 9235e7176..000000000 --- a/frontend/src/pages/api/integrations/createIntegration.ts +++ /dev/null @@ -1,67 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - integrationAuthId: string; - isActive: boolean; - secretPath: string; - app: string | null; - appId: string | null; - sourceEnvironment: string; - targetEnvironment: string | null; - targetEnvironmentId: string | null; - targetService: string | null; - targetServiceId: string | null; - owner: string | null; - path: string | null; - region: string | null; -} -/** - * This route creates a new integration based on the integration authorization with id [integrationAuthId] - * @param {Object} obj - * @param {String} obj.accessToken - id of integration authorization for which to create the integration - * @returns - */ -const createIntegration = ({ - integrationAuthId, - isActive, - app, - appId, - sourceEnvironment, - targetEnvironment, - targetEnvironmentId, - targetService, - targetServiceId, - owner, - path, - region, - secretPath, -}: Props) => - SecurityClient.fetchCall("/api/v1/integration", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - integrationAuthId, - isActive, - app, - appId, - sourceEnvironment, - targetEnvironment, - targetEnvironmentId, - targetService, - targetServiceId, - owner, - path, - region, - secretPath, - }) - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integration; - } - console.log("Failed to create integration"); - return undefined; - }); - -export default createIntegration; diff --git a/frontend/src/pages/api/integrations/getWorkspaceAuthorizations.ts b/frontend/src/pages/api/integrations/getWorkspaceAuthorizations.ts deleted file mode 100644 index 2c5822049..000000000 --- a/frontend/src/pages/api/integrations/getWorkspaceAuthorizations.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - workspaceId: string; -} - -/** - * This route gets authorizations of a certain project (Heroku, etc.) - * @param {*} workspaceId - * @returns - */ -const getWorkspaceAuthorizations = ({ workspaceId }: Props) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceId}/authorizations`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).authorizations; - } - console.log("Failed to get project authorizations"); - return undefined; - }); - -export default getWorkspaceAuthorizations; diff --git a/frontend/src/pages/api/integrations/getWorkspaceIntegrations.ts b/frontend/src/pages/api/integrations/getWorkspaceIntegrations.ts deleted file mode 100644 index 19a4b78c9..000000000 --- a/frontend/src/pages/api/integrations/getWorkspaceIntegrations.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - workspaceId: string; -} - -/** - * This route gets integrations of a certain project (Heroku, etc.) - * @param {*} workspaceId - * @returns - */ -const getWorkspaceIntegrations = ({ workspaceId }: Props) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceId}/integrations`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integrations; - } - console.log("Failed to get the project integrations"); - return undefined; - }); - -export default getWorkspaceIntegrations; diff --git a/frontend/src/pages/api/integrations/saveIntegrationAccessToken.ts b/frontend/src/pages/api/integrations/saveIntegrationAccessToken.ts deleted file mode 100644 index 5da617783..000000000 --- a/frontend/src/pages/api/integrations/saveIntegrationAccessToken.ts +++ /dev/null @@ -1,53 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - workspaceId: string | null; - integration: string | undefined; - accessId: string | null; - accessToken: string; - url: string | null; - namespace: string | null; -} -/** - * This route creates a new integration authorization for integration [integration] - * that requires the user to input their access token manually (e.g. Render). It - * saves access token [accessToken] under that integration for workspace with id - * [workspaceId]. - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace to authorize integration for - * @param {String} obj.integration - integration - * @param {String} obj.accessToken - access token to save - * @param {String} obj.url - URL of the Vault instance - * @param {String} obj.namespace - Vault-specific namespace param - * @returns - */ -const saveIntegrationAccessToken = ({ - workspaceId, - integration, - accessId, - accessToken, - url, - namespace -}: Props) => - SecurityClient.fetchCall("/api/v1/integration-auth/access-token", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - workspaceId, - integration, - accessId, - accessToken, - url, - namespace - }) - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integrationAuth; - } - console.log("Failed to save integration access details"); - return undefined; - }); - -export default saveIntegrationAccessToken; diff --git a/frontend/src/pages/api/integrations/updateIntegration.ts b/frontend/src/pages/api/integrations/updateIntegration.ts deleted file mode 100644 index dbcdea899..000000000 --- a/frontend/src/pages/api/integrations/updateIntegration.ts +++ /dev/null @@ -1,55 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route starts the integration after teh default one if gonna set up. - * Update integration with id [integrationId] to sync envars from the project's - * [environment] to the integration [app] with active state [isActive] - * @param {Object} obj - * @param {String} obj.integrationId - id of integration - * @param {Boolean} obj.isActive - active state - * @param {String} obj.environment - project environment to push secrets from - * @param {String} obj.app - name of app - * @param {String} obj.appId - (optional) app ID for integration - * @param {String} obj.targetEnvironment - target environment for integration - * @param {String} obj.owner - (optional) owner login of repo for GitHub integration - * @returns - */ -const updateIntegration = ({ - integrationId, - isActive, - environment, - app, - appId, - targetEnvironment, - owner -}: { - integrationId: string; - isActive: boolean; - environment: string; - app: string; - appId: string | null; - targetEnvironment: string | null; - owner: string | null; -}) => - SecurityClient.fetchCall(`/api/v1/integration/${integrationId}`, { - method: "PATCH", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - app, - environment, - isActive, - appId, - targetEnvironment, - owner - }) - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).integration; - } - console.log("Failed to start an integration"); - return undefined; - }); - -export default updateIntegration; diff --git a/frontend/src/pages/api/organization/GetOrg.ts b/frontend/src/pages/api/organization/GetOrg.ts deleted file mode 100644 index 8009a4b3b..000000000 --- a/frontend/src/pages/api/organization/GetOrg.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get info about a certain org - * @param {string} orgId - the organization ID - * @returns - */ -const getOrganization = ({ orgId }: { orgId: string }) => - SecurityClient.fetchCall(`/api/v1/organization/${orgId}`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).organization; - } - console.log("Failed to get org info"); - return undefined; - }); - -export default getOrganization; diff --git a/frontend/src/pages/api/organization/GetOrgProjectMemberships.ts b/frontend/src/pages/api/organization/GetOrgProjectMemberships.ts deleted file mode 100644 index 72c871c21..000000000 --- a/frontend/src/pages/api/organization/GetOrgProjectMemberships.ts +++ /dev/null @@ -1,24 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get all the project memebrships of users in an org. - * @param {*} req - * @param {*} res - * @returns - */ - -const getOrganizationProjectMemberships = (req: { orgId: string }) => - SecurityClient.fetchCall(`/api/v1/organization/${req.orgId}/workspace-memberships`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to get project memberships for users in an org"); - return undefined; - }); - -export default getOrganizationProjectMemberships; diff --git a/frontend/src/pages/api/organization/GetOrgProjects.ts b/frontend/src/pages/api/organization/GetOrgProjects.ts deleted file mode 100644 index 2e374e031..000000000 --- a/frontend/src/pages/api/organization/GetOrgProjects.ts +++ /dev/null @@ -1,25 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get all the users in an org. - * @param {*} req - * @param {*} res - * @returns - */ - -// TODO: this file is not used anywhere -const getOrganizationProjects = (req: { orgId: string }) => - SecurityClient.fetchCall(`/api/organization/${req.orgId}/workspaces`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).workspaces; - } - console.log("Failed to get projects for an org"); - return undefined; - }); - -export default getOrganizationProjects; diff --git a/frontend/src/pages/api/organization/GetOrgSubscription.ts b/frontend/src/pages/api/organization/GetOrgSubscription.ts deleted file mode 100644 index 9cef7f10a..000000000 --- a/frontend/src/pages/api/organization/GetOrgSubscription.ts +++ /dev/null @@ -1,23 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get the current subscription of an org. - * @param {*} req - * @param {*} res - * @returns - */ -const getOrganizationSubscriptions = (req: { orgId: string }) => - SecurityClient.fetchCall(`/api/v1/organization/${req.orgId}/subscriptions`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).subscriptions; - } - console.log("Failed to get org subscriptions"); - return undefined; - }); - -export default getOrganizationSubscriptions; diff --git a/frontend/src/pages/api/organization/GetOrgUserProjects.ts b/frontend/src/pages/api/organization/GetOrgUserProjects.ts deleted file mode 100644 index d8c87d6c7..000000000 --- a/frontend/src/pages/api/organization/GetOrgUserProjects.ts +++ /dev/null @@ -1,23 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get all the projects of a certain user in an org. - * @param {*} req - * @param {*} res - * @returns - */ -const getOrganizationUserProjects = (req: { orgId: string }) => - SecurityClient.fetchCall(`/api/v1/organization/${req.orgId}/my-workspaces`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).workspaces; - } - console.log("Failed to get projects of a user in an org"); - return undefined; - }); - -export default getOrganizationUserProjects; diff --git a/frontend/src/pages/api/organization/GetOrgUsers.ts b/frontend/src/pages/api/organization/GetOrgUsers.ts deleted file mode 100644 index 9af757e68..000000000 --- a/frontend/src/pages/api/organization/GetOrgUsers.ts +++ /dev/null @@ -1,38 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -export interface IMembershipOrg { - _id: string; - user: { - email: string; - firstName: string; - lastName: string; - _id: string; - publicKey: string; - }; - inviteEmail: string; - organization: string; - role: "owner" | "admin" | "member"; - status: "invited" | "accepted"; - deniedPermissions: any[]; -} -/** - * This route lets us get all the users in an org. - * @param {object} obj - * @param {string} obj.orgId - organization Id - * @returns - */ -const getOrganizationUsers = ({ orgId }: { orgId: string }): Promise => - SecurityClient.fetchCall(`/api/v1/organization/${orgId}/users`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).users; - } - console.log("Failed to get org users"); - return undefined; - }); - -export default getOrganizationUsers; diff --git a/frontend/src/pages/api/organization/StripeRedirect.ts b/frontend/src/pages/api/organization/StripeRedirect.ts deleted file mode 100644 index 50a359b58..000000000 --- a/frontend/src/pages/api/organization/StripeRedirect.ts +++ /dev/null @@ -1,23 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route redirects the user to the right stripe billing page. - * @param {*} req - * @param {*} res - * @returns - */ -const StripeRedirect = ({ orgId }: { orgId: string }) => - SecurityClient.fetchCall(`/api/v1/organization/${orgId}/customer-portal-session`, { - method: "POST", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - window.location.href = (await res.json()).url; - return; - } - console.log("Failed to redirect to Stripe"); - }); - -export default StripeRedirect; diff --git a/frontend/src/pages/api/organization/addIncidentContact.ts b/frontend/src/pages/api/organization/addIncidentContact.ts deleted file mode 100644 index fe3407025..000000000 --- a/frontend/src/pages/api/organization/addIncidentContact.ts +++ /dev/null @@ -1,25 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route add an incident contact email to a certain organization - * @param {*} param0 - * @returns - */ -const addIncidentContact = (organizationId: string, email: string) => - SecurityClient.fetchCall(`/api/v1/organization/${organizationId}/incidentContactOrg`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to add an incident contact"); - return undefined; - }); - -export default addIncidentContact; diff --git a/frontend/src/pages/api/organization/addUserToOrg.ts b/frontend/src/pages/api/organization/addUserToOrg.ts deleted file mode 100644 index 7dbb65da5..000000000 --- a/frontend/src/pages/api/organization/addUserToOrg.ts +++ /dev/null @@ -1,27 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function sends an email invite to a user to join an org - * @param {*} email - * @param {*} orgId - * @returns - */ -const addUserToOrg = (email: string, orgId: string) => - SecurityClient.fetchCall("/api/v1/invite-org/signup", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - inviteeEmail: email, - organizationId: orgId - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to add a user to an org"); - return undefined; - }); - -export default addUserToOrg; diff --git a/frontend/src/pages/api/organization/changeUserRoleInOrganization.ts b/frontend/src/pages/api/organization/changeUserRoleInOrganization.ts deleted file mode 100644 index da9d20e0f..000000000 --- a/frontend/src/pages/api/organization/changeUserRoleInOrganization.ts +++ /dev/null @@ -1,27 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function change the access of a user in a certain organization - * @param {string} organizationId - * @param {string} membershipId - * @param {string} role - * @returns - */ -const changeUserRoleInOrganization = (organizationId: string, membershipId: string, role: string) => - SecurityClient.fetchCall(`/api/v2/organizations/${organizationId}/memberships/${membershipId}`, { - method: "PATCH", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - role - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to change the user role in an org"); - return undefined; - }); - -export default changeUserRoleInOrganization; diff --git a/frontend/src/pages/api/organization/deleteIncidentContact.ts b/frontend/src/pages/api/organization/deleteIncidentContact.ts deleted file mode 100644 index 5375384c6..000000000 --- a/frontend/src/pages/api/organization/deleteIncidentContact.ts +++ /dev/null @@ -1,25 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route deletes an incident Contact from a certain organization - * @param {*} param0 - * @returns - */ -const deleteIncidentContact = (organizationId: string, email: string) => - SecurityClient.fetchCall(`/api/v1/organization/${organizationId}/incidentContactOrg`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to delete an incident contact"); - return undefined; - }); - -export default deleteIncidentContact; diff --git a/frontend/src/pages/api/organization/deleteUserFromOrganization.ts b/frontend/src/pages/api/organization/deleteUserFromOrganization.ts deleted file mode 100644 index 3041b7b71..000000000 --- a/frontend/src/pages/api/organization/deleteUserFromOrganization.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function removes a certain member from a certain organization - * @param {*} membershipId - * @returns - */ -const deleteUserFromOrganization = (membershipId: string) => - SecurityClient.fetchCall(`/api/v1/membership-org/${membershipId}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to delete a user from an org"); - return undefined; - }); - -export default deleteUserFromOrganization; diff --git a/frontend/src/pages/api/organization/getIncidentContacts.ts b/frontend/src/pages/api/organization/getIncidentContacts.ts deleted file mode 100644 index 5ed7760ac..000000000 --- a/frontend/src/pages/api/organization/getIncidentContacts.ts +++ /dev/null @@ -1,27 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -export interface IIncidentContactOrg { - _id: string; - email: string; - organization: string; -} -/** - * This routes gets all the incident contacts of a certain organization - * @param {*} workspaceId - * @returns - */ -const getIncidentContacts = (organizationId: string): Promise => - SecurityClient.fetchCall(`/api/v1/organization/${organizationId}/incidentContactOrg`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).incidentContactsOrg; - } - console.log("Failed to get incident contacts"); - return undefined; - }); - -export default getIncidentContacts; diff --git a/frontend/src/pages/api/organization/getOrgs.ts b/frontend/src/pages/api/organization/getOrgs.ts deleted file mode 100644 index da92206ec..000000000 --- a/frontend/src/pages/api/organization/getOrgs.ts +++ /dev/null @@ -1,21 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get the all the orgs of a certain user. - * @returns - */ -const getOrganizations = () => - SecurityClient.fetchCall("/api/v1/organization", { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).organizations; - } - console.log("Failed to get orgs of a user"); - return undefined; - }); - -export default getOrganizations; diff --git a/frontend/src/pages/api/organization/renameOrg.ts b/frontend/src/pages/api/organization/renameOrg.ts deleted file mode 100644 index 53fb7a51b..000000000 --- a/frontend/src/pages/api/organization/renameOrg.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us rename a certain org. - * @param {*} req - * @param {*} res - * @returns - */ -const renameOrg = (orgId: string, newOrgName: string) => - SecurityClient.fetchCall(`/api/v1/organization/${orgId}/name`, { - method: "PATCH", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - name: newOrgName - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to rename an organization"); - return undefined; - }); - -export default renameOrg; diff --git a/frontend/src/pages/api/serviceToken/addServiceToken.ts b/frontend/src/pages/api/serviceToken/addServiceToken.ts deleted file mode 100644 index f3ecc661d..000000000 --- a/frontend/src/pages/api/serviceToken/addServiceToken.ts +++ /dev/null @@ -1,56 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - name: string; - workspaceId: string; - environment: string; - expiresIn: number; - encryptedKey: string; - iv: string; - tag: string; -} - -/** - * This route adds a service token for a specific user in a project - * @param {object} obj - * @param {string} obj.name - name of the service token - * @param {string} obj.workspaceId - workspace for which we are issuing the token - * @param {string} obj.environment - environment for which we are issuing the token - * @param {string} obj.expiresIn - how soon the service token expires in ms - * @param {string} obj.encryptedKey - encrypted project key through random symmetric encryption - * @param {string} obj.iv - obtained through symmetric encryption - * @param {string} obj.tag - obtained through symmetric encryption - * @returns - */ -const addServiceToken = ({ - name, - workspaceId, - environment, - expiresIn, - encryptedKey, - iv, - tag -}: Props) => - SecurityClient.fetchCall("/api/v2/service-token/", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - name, - workspaceId, - environment, - expiresIn, - encryptedKey, - iv, - tag - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to add service tokens"); - return undefined; - }); - -export default addServiceToken; diff --git a/frontend/src/pages/api/serviceToken/deleteServiceToken.ts b/frontend/src/pages/api/serviceToken/deleteServiceToken.ts deleted file mode 100644 index e2d4b97ec..000000000 --- a/frontend/src/pages/api/serviceToken/deleteServiceToken.ts +++ /dev/null @@ -1,27 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - serviceTokenId: string; -} - -/** - * This route revokes a specific service token - * @param {object} obj - * @param {string} obj.serviceTokenId - id of a cervice token that we want to delete - * @returns - */ -const deleteServiceToken = ({ serviceTokenId }: Props) => - SecurityClient.fetchCall(`/api/v2/service-token/${serviceTokenId}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to delete a service token"); - return undefined; - }); - -export default deleteServiceToken; diff --git a/frontend/src/pages/api/serviceToken/getServiceTokens.ts b/frontend/src/pages/api/serviceToken/getServiceTokens.ts deleted file mode 100644 index 38f02cb52..000000000 --- a/frontend/src/pages/api/serviceToken/getServiceTokens.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route gets service tokens for a specific user in a project - * @param {*} param0 - * @returns - */ -const getServiceTokens = ({ workspaceId }: { workspaceId: string }) => - SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/service-token-data`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).serviceTokenData; - } - console.log("Failed to get service tokens"); - return undefined; - }); - -export default getServiceTokens; diff --git a/frontend/src/pages/api/user/getUser.ts b/frontend/src/pages/api/user/getUser.ts deleted file mode 100644 index afdd268ba..000000000 --- a/frontend/src/pages/api/user/getUser.ts +++ /dev/null @@ -1,20 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route gets the information about a specific user. - */ -const getUser = () => - SecurityClient.fetchCall("/api/v1/user", { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).user; - } - console.log("Failed to get user info"); - return undefined; - }); - -export default getUser; diff --git a/frontend/src/pages/api/user/updateMyMfaEnabled.ts b/frontend/src/pages/api/user/updateMyMfaEnabled.ts deleted file mode 100644 index e22f14958..000000000 --- a/frontend/src/pages/api/user/updateMyMfaEnabled.ts +++ /dev/null @@ -1,32 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Props { - isMfaEnabled: boolean; -} - -/** - * Update the user's MFA-enabled status to [isMfaEnabled] - * @param {Object} obj - * @param {Boolean} obj.isMfaEnabled - whether or not MFA status should be set to enabled or not - * @returns {User} user - user with updated MFA-enabled status - */ -const updateMyMfaEnabled = async ({ - isMfaEnabled -}: Props) => - SecurityClient.fetchCall("/api/v2/users/me/mfa", { - method: "PATCH", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - isMfaEnabled, - }) - }).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).user; - } - console.log("Failed to update MFA status"); - return undefined; - }); - -export default updateMyMfaEnabled; \ No newline at end of file diff --git a/frontend/src/pages/api/userActions/checkUserAction.ts b/frontend/src/pages/api/userActions/checkUserAction.ts deleted file mode 100644 index 5663c2649..000000000 --- a/frontend/src/pages/api/userActions/checkUserAction.ts +++ /dev/null @@ -1,29 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route registers a certain action for a user - * @param {*} email - * @param {*} workspaceId - * @returns - */ -const checkUserAction = ({ action }: { action: string }) => - SecurityClient.fetchCall( - "/api/v1/user-action" + - `?${new URLSearchParams({ - action - })}`, - { - method: "GET", - headers: { - "Content-Type": "application/json" - } - } - ).then(async (res) => { - if (res && res.status === 200) { - return (await res.json()).userAction; - } - console.log("Failed to check a user action"); - return undefined; - }); - -export default checkUserAction; diff --git a/frontend/src/pages/api/userActions/registerUserAction.ts b/frontend/src/pages/api/userActions/registerUserAction.ts deleted file mode 100644 index dd29b7f29..000000000 --- a/frontend/src/pages/api/userActions/registerUserAction.ts +++ /dev/null @@ -1,25 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route registers a certain action for a user - * @param {*} action - * @returns - */ -const registerUserAction = ({ action }: { action: string }) => - SecurityClient.fetchCall("/api/v1/user-action", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - action - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to register a user action"); - return undefined; - }); - -export default registerUserAction; diff --git a/frontend/src/pages/api/workspace/addUserToWorkspace.ts b/frontend/src/pages/api/workspace/addUserToWorkspace.ts deleted file mode 100644 index 19612ec1d..000000000 --- a/frontend/src/pages/api/workspace/addUserToWorkspace.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function adds a user to a project - * @param {*} email - * @param {*} workspaceId - * @returns - */ -const addUserToWorkspace = (email: string, workspaceId: string) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceId}/invite-signup`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - email - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res.json(); - } - console.log("Failed to add a user to project"); - return undefined; - }); - -export default addUserToWorkspace; diff --git a/frontend/src/pages/api/workspace/changeUserRoleInWorkspace.ts b/frontend/src/pages/api/workspace/changeUserRoleInWorkspace.ts deleted file mode 100644 index 21ea91c45..000000000 --- a/frontend/src/pages/api/workspace/changeUserRoleInWorkspace.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function change the access of a user in a certain workspace - * @param {*} membershipId - * @param {*} role - * @returns - */ -const changeUserRoleInWorkspace = (membershipId: string, role: string) => - SecurityClient.fetchCall(`/api/v1/membership/${membershipId}/change-role`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - role - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to change the user role in a project"); - return undefined; - }); - -export default changeUserRoleInWorkspace; diff --git a/frontend/src/pages/api/workspace/createWorkspace.ts b/frontend/src/pages/api/workspace/createWorkspace.ts deleted file mode 100644 index f241a4fe8..000000000 --- a/frontend/src/pages/api/workspace/createWorkspace.ts +++ /dev/null @@ -1,33 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route creates a new workspace for a user within a certain organization. - * @param {string} workspaceName - project Name - * @param {string} organizationId - org ID - * @returns - */ -const createWorkspace = ({ - workspaceName, - organizationId -}: { - workspaceName: string; - organizationId: string; -}) => - SecurityClient.fetchCall("/api/v1/workspace", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - workspaceName, - organizationId - }) - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).workspace; - } - console.log("Failed to create a project"); - return undefined; - }); - -export default createWorkspace; diff --git a/frontend/src/pages/api/workspace/deleteUserFromWorkspace.ts b/frontend/src/pages/api/workspace/deleteUserFromWorkspace.ts deleted file mode 100644 index 33927f1c8..000000000 --- a/frontend/src/pages/api/workspace/deleteUserFromWorkspace.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This function removes a certain member from a certain workspace - * @param {*} membershipId - * @returns - */ -const deleteUserFromWorkspace = (membershipId: string) => - SecurityClient.fetchCall(`/api/v1/membership/${membershipId}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to delete a user from a project"); - return undefined; - }); - -export default deleteUserFromWorkspace; diff --git a/frontend/src/pages/api/workspace/deleteWorkspace.ts b/frontend/src/pages/api/workspace/deleteWorkspace.ts deleted file mode 100644 index 7e1551613..000000000 --- a/frontend/src/pages/api/workspace/deleteWorkspace.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route deletes a specified workspace. - * @param {*} workspaceId - * @returns - */ -const deleteWorkspace = (workspaceId: string) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceId}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to delete a project"); - return undefined; - }); - -export default deleteWorkspace; diff --git a/frontend/src/pages/api/workspace/getAWorkspace.ts b/frontend/src/pages/api/workspace/getAWorkspace.ts deleted file mode 100644 index cf4a3d696..000000000 --- a/frontend/src/pages/api/workspace/getAWorkspace.ts +++ /dev/null @@ -1,30 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Workspace { - __v: number; - _id: string; - name: string; - organization: string; - environments: Array<{ name: string; slug: string }>; -} - -/** - * This route lets us get the workspaces of a certain user - * @returns - */ -const getAWorkspace = (workspaceID: string) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceID}`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - const data = (await res.json()) as unknown as { workspace: Workspace }; - return data.workspace; - } - - throw new Error("Failed to get workspace"); - }); - -export default getAWorkspace; diff --git a/frontend/src/pages/api/workspace/getLatestFileKey.ts b/frontend/src/pages/api/workspace/getLatestFileKey.ts deleted file mode 100644 index 4dcd330d2..000000000 --- a/frontend/src/pages/api/workspace/getLatestFileKey.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { apiRequest } from "@app/config/request"; - -/** - * Get the latest key pairs from a certain workspace - * @param {string} workspaceId - * @returns - */ -const getLatestFileKey = async ({ workspaceId }: { workspaceId: string }) => { - const { data } = await apiRequest.get(`/api/v1/key/${workspaceId}/latest`); - return data; -} - -export default getLatestFileKey; diff --git a/frontend/src/pages/api/workspace/getProjectInfo.ts b/frontend/src/pages/api/workspace/getProjectInfo.ts deleted file mode 100644 index cb1e54c04..000000000 --- a/frontend/src/pages/api/workspace/getProjectInfo.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get the information of a certain project. - * @param {*} projectId - project ID (we renamed workspaces to projects in the app) - * @returns - */ -const getProjectInfo = ({ projectId }: { projectId: string }) => - SecurityClient.fetchCall(`/api/v1/workspace/${projectId}`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).workspace; - } - console.log("Failed to get project info"); - return undefined; - }); - -export default getProjectInfo; diff --git a/frontend/src/pages/api/workspace/getWorkspaceEnvironments.ts b/frontend/src/pages/api/workspace/getWorkspaceEnvironments.ts deleted file mode 100644 index 2d7d9359b..000000000 --- a/frontend/src/pages/api/workspace/getWorkspaceEnvironments.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get the environments that a certain user has acess to in a certain project - * @param {string} workspaceId - * @returns - */ -const getWorkspaceEnvironments = ({ workspaceId }: { workspaceId: string }) => - SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/environments`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).accessibleEnvironments; - } - console.log("Failed to get accessible environments"); - return undefined; - }); - -export default getWorkspaceEnvironments; diff --git a/frontend/src/pages/api/workspace/getWorkspaceKeys.ts b/frontend/src/pages/api/workspace/getWorkspaceKeys.ts deleted file mode 100644 index e4c4475e9..000000000 --- a/frontend/src/pages/api/workspace/getWorkspaceKeys.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get the public keys of everyone in your workspace. - * @param {string} workspaceId - * @returns - */ -const getWorkspaceKeys = ({ workspaceId }: { workspaceId: string }) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceId}/keys`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).publicKeys; - } - console.log("Failed to get the public keys of everyone in the workspace"); - return undefined; - }); - -export default getWorkspaceKeys; diff --git a/frontend/src/pages/api/workspace/getWorkspaceTags.ts b/frontend/src/pages/api/workspace/getWorkspaceTags.ts deleted file mode 100644 index 535731bfb..000000000 --- a/frontend/src/pages/api/workspace/getWorkspaceTags.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get the tags for a certain project - * @param {string} workspaceId - * @returns - */ -const getWorkspaceTags = ({ workspaceId }: { workspaceId: string }) => - SecurityClient.fetchCall(`/api/v2/workspace/${workspaceId}/tags`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).workspaceTags; - } - console.log("Failed to get the tags available in a certain project"); - return undefined; - }); - -export default getWorkspaceTags; diff --git a/frontend/src/pages/api/workspace/getWorkspaceUsers.ts b/frontend/src/pages/api/workspace/getWorkspaceUsers.ts deleted file mode 100644 index 4ef0a8dbc..000000000 --- a/frontend/src/pages/api/workspace/getWorkspaceUsers.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us get all the users in the workspace. - * @param {string} workspaceId - workspace ID - * @returns - */ -const getWorkspaceUsers = ({ workspaceId }: { workspaceId: string }) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceId}/users`, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - return (await res.json()).users; - } - console.log("Failed to get Project Users"); - return undefined; - }); - -export default getWorkspaceUsers; diff --git a/frontend/src/pages/api/workspace/getWorkspaces.ts b/frontend/src/pages/api/workspace/getWorkspaces.ts deleted file mode 100644 index 4a08c9d83..000000000 --- a/frontend/src/pages/api/workspace/getWorkspaces.ts +++ /dev/null @@ -1,31 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -interface Workspace { - __v: number; - _id: string; - name: string; - autoCapitalization: boolean; - organization: string; - environments: Array<{ name: string; slug: string }>; -} - -/** - * This route lets us get the workspaces of a certain user - * @returns - */ -const getWorkspaces = () => - SecurityClient.fetchCall("/api/v1/workspace", { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }).then(async (res) => { - if (res?.status === 200) { - const data = (await res.json()) as unknown as { workspaces: Workspace[] }; - return data.workspaces; - } - - throw new Error("Failed to get projects"); - }); - -export default getWorkspaces; diff --git a/frontend/src/pages/api/workspace/renameWorkspace.ts b/frontend/src/pages/api/workspace/renameWorkspace.ts deleted file mode 100644 index 7e910a42a..000000000 --- a/frontend/src/pages/api/workspace/renameWorkspace.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route lets us rename a certain workspace. - * @param {*} req - * @param {*} res - * @returns - */ -const renameWorkspace = (workspaceId: string, newWorkspaceName: string) => - SecurityClient.fetchCall(`/api/v1/workspace/${workspaceId}/name`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - name: newWorkspaceName - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to rename a project"); - return undefined; - }); - -export default renameWorkspace; diff --git a/frontend/src/pages/api/workspace/uploadKeys.ts b/frontend/src/pages/api/workspace/uploadKeys.ts deleted file mode 100644 index c28fa1fb3..000000000 --- a/frontend/src/pages/api/workspace/uploadKeys.ts +++ /dev/null @@ -1,32 +0,0 @@ -import SecurityClient from "@app/components/utilities/SecurityClient"; - -/** - * This route uplods the keys in an encrypted format. - * @param {*} workspaceId - * @param {*} userId - * @param {*} encryptedKey - * @param {*} nonce - * @returns - */ -const uploadKeys = (workspaceId: string, userId: string, encryptedKey: string, nonce: string) => - SecurityClient.fetchCall(`/api/v1/key/${workspaceId}`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - key: { - userId, - encryptedKey, - nonce - } - }) - }).then(async (res) => { - if (res && res.status === 200) { - return res; - } - console.log("Failed to upload keys for a new user"); - return undefined; - }); - -export default uploadKeys; diff --git a/frontend/src/pages/dashboard.tsx b/frontend/src/pages/dashboard.tsx index fd8a78a31..3f24ab101 100644 --- a/frontend/src/pages/dashboard.tsx +++ b/frontend/src/pages/dashboard.tsx @@ -1,10 +1,11 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; -import getOrganizations from "./api/organization/getOrgs"; +import { useGetOrganizations } from "@app/hooks/api"; export default function DashboardRedirect() { const router = useRouter(); + const { data: userOrgs } = useGetOrganizations(); /** * Here we forward to the default workspace if a user opens this url @@ -16,11 +17,10 @@ export default function DashboardRedirect() { try { if (localStorage.getItem("orgData.id")) { router.push(`/org/${localStorage.getItem("orgData.id")}/overview`); - } else { - const userOrgs = await getOrganizations(); - userOrg = userOrgs[0]._id; - router.push(`/org/${userOrg}/overview`); - } + } else if (userOrgs) { + userOrg = userOrgs[0]._id; + router.push(`/org/${userOrg}/overview`); + } } catch (error) { console.log("Error - Not logged in yet"); } diff --git a/frontend/src/pages/integrations/aws-parameter-store/authorize.tsx b/frontend/src/pages/integrations/aws-parameter-store/authorize.tsx index 230c8b6ea..d71273fa5 100644 --- a/frontend/src/pages/integrations/aws-parameter-store/authorize.tsx +++ b/frontend/src/pages/integrations/aws-parameter-store/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function AWSParameterStoreAuthorizeIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [isLoading, setIsLoading] = useState(false); const [accessKey, setAccessKey] = useState(""); @@ -30,7 +35,7 @@ export default function AWSParameterStoreAuthorizeIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "aws-parameter-store", accessId: accessKey, diff --git a/frontend/src/pages/integrations/aws-parameter-store/create.tsx b/frontend/src/pages/integrations/aws-parameter-store/create.tsx index 6f7f45bc6..b537a9827 100644 --- a/frontend/src/pages/integrations/aws-parameter-store/create.tsx +++ b/frontend/src/pages/integrations/aws-parameter-store/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -13,7 +17,6 @@ import { } from "../../../components/v2"; import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; const awsRegions = [ { name: "US East (Ohio)", slug: "us-east-2" }, @@ -49,6 +52,7 @@ const awsRegions = [ export default function AWSParameterStoreCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -90,7 +94,7 @@ export default function AWSParameterStoreCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: null, diff --git a/frontend/src/pages/integrations/aws-secret-manager/authorize.tsx b/frontend/src/pages/integrations/aws-secret-manager/authorize.tsx index 664a66087..11da85224 100644 --- a/frontend/src/pages/integrations/aws-secret-manager/authorize.tsx +++ b/frontend/src/pages/integrations/aws-secret-manager/authorize.tsx @@ -1,11 +1,14 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { useSaveIntegrationAccessToken } from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function AWSSecretManagerCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [isLoading, setIsLoading] = useState(false); const [accessKey, setAccessKey] = useState(""); @@ -30,7 +33,7 @@ export default function AWSSecretManagerCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "aws-secret-manager", accessId: accessKey, diff --git a/frontend/src/pages/integrations/aws-secret-manager/create.tsx b/frontend/src/pages/integrations/aws-secret-manager/create.tsx index 7baab5813..b919a6daf 100644 --- a/frontend/src/pages/integrations/aws-secret-manager/create.tsx +++ b/frontend/src/pages/integrations/aws-secret-manager/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -13,7 +17,6 @@ import { } from "../../../components/v2"; import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; const awsRegions = [ { name: "US East (Ohio)", slug: "us-east-2" }, @@ -49,6 +52,7 @@ const awsRegions = [ export default function AWSSecretManagerCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -89,7 +93,7 @@ export default function AWSSecretManagerCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetSecretName.trim(), diff --git a/frontend/src/pages/integrations/azure-key-vault/create.tsx b/frontend/src/pages/integrations/azure-key-vault/create.tsx index 963fdf530..7bc6fc9f0 100644 --- a/frontend/src/pages/integrations/azure-key-vault/create.tsx +++ b/frontend/src/pages/integrations/azure-key-vault/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -13,10 +17,10 @@ import { } from "../../../components/v2"; import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function AzureKeyVaultCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -52,7 +56,7 @@ export default function AzureKeyVaultCreateIntegrationPage() { if (!integrationAuth?._id) return; setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: vaultBaseUrl, diff --git a/frontend/src/pages/integrations/azure-key-vault/oauth2/callback.tsx b/frontend/src/pages/integrations/azure-key-vault/oauth2/callback.tsx index 32364d85b..2f23f729f 100644 --- a/frontend/src/pages/integrations/azure-key-vault/oauth2/callback.tsx +++ b/frontend/src/pages/integrations/azure-key-vault/oauth2/callback.tsx @@ -2,10 +2,13 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; -import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; +import { + useAuthorizeIntegration +} from "@app/hooks/api"; export default function AzureKeyVaultOAuth2CallbackPage() { const router = useRouter(); + const { mutateAsync } = useAuthorizeIntegration(); const { code, state } = queryString.parse(router.asPath.split("?")[1]); @@ -16,7 +19,7 @@ export default function AzureKeyVaultOAuth2CallbackPage() { if (state !== localStorage.getItem("latestCSRFToken")) return; localStorage.removeItem("latestCSRFToken"); - const integrationAuth = await AuthorizeIntegration({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id") as string, code: code as string, integration: "azure-key-vault" diff --git a/frontend/src/pages/integrations/bitbucket/create.tsx b/frontend/src/pages/integrations/bitbucket/create.tsx index 6bdc87f0d..1901360af 100644 --- a/frontend/src/pages/integrations/bitbucket/create.tsx +++ b/frontend/src/pages/integrations/bitbucket/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -17,10 +21,10 @@ import { useGetIntegrationAuthById, } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function BitBucketCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const [targetAppId, setTargetAppId] = useState(""); const [targetEnvironmentId, setTargetEnvironmentId] = useState(""); @@ -79,7 +83,7 @@ export default function BitBucketCreateIntegrationPage() { if (!targetApp || !targetApp.appId || !targetEnvironment) return; - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp.name, diff --git a/frontend/src/pages/integrations/bitbucket/oauth2/callback.tsx b/frontend/src/pages/integrations/bitbucket/oauth2/callback.tsx index 43a58bc6f..a7326722a 100644 --- a/frontend/src/pages/integrations/bitbucket/oauth2/callback.tsx +++ b/frontend/src/pages/integrations/bitbucket/oauth2/callback.tsx @@ -2,10 +2,13 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; -import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; +import { + useAuthorizeIntegration +} from "@app/hooks/api"; export default function BitBucketOAuth2CallbackPage() { const router = useRouter(); + const { mutateAsync } = useAuthorizeIntegration(); const { code, state } = queryString.parse(router.asPath.split("?")[1]); useEffect(() => { @@ -15,7 +18,7 @@ export default function BitBucketOAuth2CallbackPage() { if (state !== localStorage.getItem("latestCSRFToken")) return; localStorage.removeItem("latestCSRFToken"); - const integrationAuth = await AuthorizeIntegration({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id") as string, code: code as string, integration: "bitbucket" diff --git a/frontend/src/pages/integrations/checkly/authorize.tsx b/frontend/src/pages/integrations/checkly/authorize.tsx index 73ad821aa..a20084c1b 100644 --- a/frontend/src/pages/integrations/checkly/authorize.tsx +++ b/frontend/src/pages/integrations/checkly/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function ChecklyCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [accessToken, setAccessToken] = useState(""); const [accessTokenErrorText, setAccessTokenErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function ChecklyCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "checkly", accessId: null, diff --git a/frontend/src/pages/integrations/checkly/create.tsx b/frontend/src/pages/integrations/checkly/create.tsx index 2ae0435cf..7f3b5397b 100644 --- a/frontend/src/pages/integrations/checkly/create.tsx +++ b/frontend/src/pages/integrations/checkly/create.tsx @@ -11,16 +11,19 @@ import { Select, SelectItem } from "@app/components/v2"; +import { + useCreateIntegration +} from "@app/hooks/api"; import { useGetIntegrationAuthApps, useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function ChecklyCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -62,7 +65,7 @@ export default function ChecklyCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/circleci/authorize.tsx b/frontend/src/pages/integrations/circleci/authorize.tsx index efb8a0ad9..e2d757897 100644 --- a/frontend/src/pages/integrations/circleci/authorize.tsx +++ b/frontend/src/pages/integrations/circleci/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function CircleCICreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function CircleCICreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "circleci", accessToken: apiKey, diff --git a/frontend/src/pages/integrations/circleci/create.tsx b/frontend/src/pages/integrations/circleci/create.tsx index 162cd565c..199b4bece 100644 --- a/frontend/src/pages/integrations/circleci/create.tsx +++ b/frontend/src/pages/integrations/circleci/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function CircleCICreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -58,7 +62,7 @@ export default function CircleCICreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/cloud-66/authorize.tsx b/frontend/src/pages/integrations/cloud-66/authorize.tsx index 8c6434936..0697e7fd1 100644 --- a/frontend/src/pages/integrations/cloud-66/authorize.tsx +++ b/frontend/src/pages/integrations/cloud-66/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function Cloud66CreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function Cloud66CreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "cloud-66", accessId: null, diff --git a/frontend/src/pages/integrations/cloud-66/create.tsx b/frontend/src/pages/integrations/cloud-66/create.tsx index dbf566464..76e874542 100644 --- a/frontend/src/pages/integrations/cloud-66/create.tsx +++ b/frontend/src/pages/integrations/cloud-66/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById, } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function Cloud66CreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -56,7 +60,7 @@ export default function Cloud66CreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/cloudflare-pages/authorize.tsx b/frontend/src/pages/integrations/cloudflare-pages/authorize.tsx index 6e4b134d1..d63a3de43 100644 --- a/frontend/src/pages/integrations/cloudflare-pages/authorize.tsx +++ b/frontend/src/pages/integrations/cloudflare-pages/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button,Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function CloudflarePagesIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [accessKey, setAccessKey] = useState(""); const [accessKeyErrorText, setAccessKeyErrorText] = useState(""); const [accountId, setAccountId] = useState(""); @@ -24,7 +29,7 @@ export default function CloudflarePagesIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "cloudflare-pages", accessId: accountId, diff --git a/frontend/src/pages/integrations/cloudflare-pages/create.tsx b/frontend/src/pages/integrations/cloudflare-pages/create.tsx index 6b7bc8d3c..49ea9b191 100644 --- a/frontend/src/pages/integrations/cloudflare-pages/create.tsx +++ b/frontend/src/pages/integrations/cloudflare-pages/create.tsx @@ -2,10 +2,12 @@ import { useEffect,useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +, useGetWorkspaceById } from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "../../../components/v2"; -import { useGetWorkspaceById } from "../../../hooks/api"; import { useGetIntegrationAuthApps, useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; -import createIntegration from "../../api/integrations/createIntegration"; const cloudflareEnvironments = [ { name: "Production", slug: "production" }, @@ -14,6 +16,7 @@ const cloudflareEnvironments = [ export default function CloudflarePagesIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? ""); @@ -54,7 +57,7 @@ export default function CloudflarePagesIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/codefresh/authorize.tsx b/frontend/src/pages/integrations/codefresh/authorize.tsx index 17416ffab..67d857bdb 100644 --- a/frontend/src/pages/integrations/codefresh/authorize.tsx +++ b/frontend/src/pages/integrations/codefresh/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function CodefreshCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function CodefreshCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "codefresh", accessId: null, diff --git a/frontend/src/pages/integrations/codefresh/create.tsx b/frontend/src/pages/integrations/codefresh/create.tsx index 214487b6e..550fac89d 100644 --- a/frontend/src/pages/integrations/codefresh/create.tsx +++ b/frontend/src/pages/integrations/codefresh/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function CodefreshCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -56,7 +60,7 @@ export default function CodefreshCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/digital-ocean-app-platform/authorize.tsx b/frontend/src/pages/integrations/digital-ocean-app-platform/authorize.tsx index 9c3912b2e..3d410efd5 100644 --- a/frontend/src/pages/integrations/digital-ocean-app-platform/authorize.tsx +++ b/frontend/src/pages/integrations/digital-ocean-app-platform/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function DigitalOceanAppPlatformCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function DigitalOceanAppPlatformCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "digital-ocean-app-platform", accessId: null, diff --git a/frontend/src/pages/integrations/digital-ocean-app-platform/create.tsx b/frontend/src/pages/integrations/digital-ocean-app-platform/create.tsx index 925729c94..1a5968007 100644 --- a/frontend/src/pages/integrations/digital-ocean-app-platform/create.tsx +++ b/frontend/src/pages/integrations/digital-ocean-app-platform/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function DigitalOceanAppPlatformCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -56,7 +60,7 @@ export default function DigitalOceanAppPlatformCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/flyio/authorize.tsx b/frontend/src/pages/integrations/flyio/authorize.tsx index 9424471ef..b8b0884f6 100644 --- a/frontend/src/pages/integrations/flyio/authorize.tsx +++ b/frontend/src/pages/integrations/flyio/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function FlyioCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [accessToken, setAccessToken] = useState(""); const [accessTokenErrorText, setAccessTokenErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function FlyioCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "flyio", accessId: null, diff --git a/frontend/src/pages/integrations/flyio/create.tsx b/frontend/src/pages/integrations/flyio/create.tsx index 2eeb7f823..b0549cc58 100644 --- a/frontend/src/pages/integrations/flyio/create.tsx +++ b/frontend/src/pages/integrations/flyio/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function FlyioCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -59,7 +63,7 @@ export default function FlyioCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/github/create.tsx b/frontend/src/pages/integrations/github/create.tsx index 9344996ab..885155570 100644 --- a/frontend/src/pages/integrations/github/create.tsx +++ b/frontend/src/pages/integrations/github/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function GitHubCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -63,7 +67,7 @@ export default function GitHubCreateIntegrationPage() { if (!targetApp || !targetApp.owner) return; - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp.name, diff --git a/frontend/src/pages/integrations/github/oauth2/callback.tsx b/frontend/src/pages/integrations/github/oauth2/callback.tsx index 7ad1aa2bb..d93e02478 100644 --- a/frontend/src/pages/integrations/github/oauth2/callback.tsx +++ b/frontend/src/pages/integrations/github/oauth2/callback.tsx @@ -2,10 +2,14 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; -import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; +import { + useAuthorizeIntegration +} from "@app/hooks/api"; export default function GitHubOAuth2CallbackPage() { const router = useRouter(); + const { mutateAsync } = useAuthorizeIntegration(); + const { code, state } = queryString.parse(router.asPath.split("?")[1]); useEffect(() => { @@ -15,7 +19,7 @@ export default function GitHubOAuth2CallbackPage() { if (state !== localStorage.getItem("latestCSRFToken")) return; localStorage.removeItem("latestCSRFToken"); - const integrationAuth = await AuthorizeIntegration({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id") as string, code: code as string, integration: "github" diff --git a/frontend/src/pages/integrations/gitlab/create.tsx b/frontend/src/pages/integrations/gitlab/create.tsx index ca90e3c1a..57524ef1e 100644 --- a/frontend/src/pages/integrations/gitlab/create.tsx +++ b/frontend/src/pages/integrations/gitlab/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -17,7 +21,6 @@ import { useGetIntegrationAuthTeams } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; const gitLabEntities = [ { name: "Individual", value: "individual" }, @@ -26,6 +29,7 @@ const gitLabEntities = [ export default function GitLabCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -87,7 +91,7 @@ export default function GitLabCreateIntegrationPage() { setIsLoading(true); if (!integrationAuth?._id) return; - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: diff --git a/frontend/src/pages/integrations/gitlab/oauth2/callback.tsx b/frontend/src/pages/integrations/gitlab/oauth2/callback.tsx index 27c4c0672..4df89f072 100644 --- a/frontend/src/pages/integrations/gitlab/oauth2/callback.tsx +++ b/frontend/src/pages/integrations/gitlab/oauth2/callback.tsx @@ -2,10 +2,14 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; -import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; +import { + useAuthorizeIntegration +} from "@app/hooks/api"; export default function GitLabOAuth2CallbackPage() { const router = useRouter(); + const { mutateAsync } = useAuthorizeIntegration(); + const { code, state } = queryString.parse(router.asPath.split("?")[1]); useEffect(() => { (async () => { @@ -14,7 +18,7 @@ export default function GitLabOAuth2CallbackPage() { if (state !== localStorage.getItem("latestCSRFToken")) return; localStorage.removeItem("latestCSRFToken"); - const integrationAuth = await AuthorizeIntegration({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id") as string, code: code as string, integration: "gitlab" diff --git a/frontend/src/pages/integrations/hashicorp-vault/authorize.tsx b/frontend/src/pages/integrations/hashicorp-vault/authorize.tsx index 6857fd59e..948e17e0f 100644 --- a/frontend/src/pages/integrations/hashicorp-vault/authorize.tsx +++ b/frontend/src/pages/integrations/hashicorp-vault/authorize.tsx @@ -1,11 +1,15 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function HashiCorpVaultAuthorizeIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); const [vaultURL, setVaultURL] = useState(""); const [vaultURLErrorText, setVaultURLErrorText] = useState(""); @@ -57,7 +61,7 @@ export default function HashiCorpVaultAuthorizeIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "hashicorp-vault", accessId: vaultRoleID, diff --git a/frontend/src/pages/integrations/hashicorp-vault/create.tsx b/frontend/src/pages/integrations/hashicorp-vault/create.tsx index 0287a5c99..0fb973851 100644 --- a/frontend/src/pages/integrations/hashicorp-vault/create.tsx +++ b/frontend/src/pages/integrations/hashicorp-vault/create.tsx @@ -2,6 +2,10 @@ import { useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -13,10 +17,10 @@ import { } from "../../../components/v2"; import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function HashiCorpVaultCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -57,7 +61,7 @@ export default function HashiCorpVaultCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: vaultEnginePath, diff --git a/frontend/src/pages/integrations/heroku/create.tsx b/frontend/src/pages/integrations/heroku/create.tsx index b6f272dbc..9bce95a0d 100644 --- a/frontend/src/pages/integrations/heroku/create.tsx +++ b/frontend/src/pages/integrations/heroku/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function HerokuCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -57,7 +61,7 @@ export default function HerokuCreateIntegrationPage() { if (!integrationAuth?._id) return; - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/heroku/oauth2/callback.tsx b/frontend/src/pages/integrations/heroku/oauth2/callback.tsx index b213b2b1d..a3a978a6a 100644 --- a/frontend/src/pages/integrations/heroku/oauth2/callback.tsx +++ b/frontend/src/pages/integrations/heroku/oauth2/callback.tsx @@ -2,10 +2,13 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; -import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; +import { + useAuthorizeIntegration +} from "@app/hooks/api"; export default function HerokuOAuth2CallbackPage() { const router = useRouter(); + const { mutateAsync } = useAuthorizeIntegration(); const { code, state } = queryString.parse(router.asPath.split("?")[1]); @@ -15,7 +18,7 @@ export default function HerokuOAuth2CallbackPage() { // validate state if (state !== localStorage.getItem("latestCSRFToken")) return; localStorage.removeItem("latestCSRFToken"); - const integrationAuth = await AuthorizeIntegration({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id") as string, code: code as string, integration: "heroku" diff --git a/frontend/src/pages/integrations/laravel-forge/authorize.tsx b/frontend/src/pages/integrations/laravel-forge/authorize.tsx index d69b263e9..98c5569c1 100644 --- a/frontend/src/pages/integrations/laravel-forge/authorize.tsx +++ b/frontend/src/pages/integrations/laravel-forge/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function LaravelForgeCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [serverId, setServerId] = useState(""); @@ -29,7 +34,7 @@ export default function LaravelForgeCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "laravel-forge", accessId: serverId, diff --git a/frontend/src/pages/integrations/laravel-forge/create.tsx b/frontend/src/pages/integrations/laravel-forge/create.tsx index acfeb6932..b1090c442 100644 --- a/frontend/src/pages/integrations/laravel-forge/create.tsx +++ b/frontend/src/pages/integrations/laravel-forge/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function LaravelForgeCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -56,7 +60,7 @@ export default function LaravelForgeCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/netlify/create.tsx b/frontend/src/pages/integrations/netlify/create.tsx index 9d5dbb280..0a729c076 100644 --- a/frontend/src/pages/integrations/netlify/create.tsx +++ b/frontend/src/pages/integrations/netlify/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,7 +20,6 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; const netlifyEnvironments = [ { name: "Local development", slug: "dev" }, @@ -27,6 +30,7 @@ const netlifyEnvironments = [ export default function NetlifyCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -65,7 +69,7 @@ export default function NetlifyCreateIntegrationPage() { if (!integrationAuth?._id) return; - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/netlify/oauth2/callback.tsx b/frontend/src/pages/integrations/netlify/oauth2/callback.tsx index c74e03127..a3d680adc 100644 --- a/frontend/src/pages/integrations/netlify/oauth2/callback.tsx +++ b/frontend/src/pages/integrations/netlify/oauth2/callback.tsx @@ -2,10 +2,13 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; -import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; +import { + useAuthorizeIntegration +} from "@app/hooks/api"; export default function NetlifyOAuth2CallbackPage() { const router = useRouter(); + const { mutateAsync } = useAuthorizeIntegration(); const { code, state } = queryString.parse(router.asPath.split("?")[1]); @@ -16,7 +19,7 @@ export default function NetlifyOAuth2CallbackPage() { if (state !== localStorage.getItem("latestCSRFToken")) return; localStorage.removeItem("latestCSRFToken"); - const integrationAuth = await AuthorizeIntegration({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id") as string, code: code as string, integration: "netlify" diff --git a/frontend/src/pages/integrations/northflank/authorize.tsx b/frontend/src/pages/integrations/northflank/authorize.tsx index 8e2baa3cb..636fb5ad3 100644 --- a/frontend/src/pages/integrations/northflank/authorize.tsx +++ b/frontend/src/pages/integrations/northflank/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function NorthflankCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function NorthflankCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "northflank", accessToken: apiKey, diff --git a/frontend/src/pages/integrations/northflank/create.tsx b/frontend/src/pages/integrations/northflank/create.tsx index 4ebcf95ec..ac6c0f0aa 100644 --- a/frontend/src/pages/integrations/northflank/create.tsx +++ b/frontend/src/pages/integrations/northflank/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -17,10 +21,10 @@ import { useGetIntegrationAuthNorthflankSecretGroups } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function NorthflankCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState(""); const [secretPath, setSecretPath] = useState("/"); @@ -78,7 +82,7 @@ export default function NorthflankCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: integrationAuthApps?.find( diff --git a/frontend/src/pages/integrations/railway/authorize.tsx b/frontend/src/pages/integrations/railway/authorize.tsx index c145048d6..498b86ab1 100644 --- a/frontend/src/pages/integrations/railway/authorize.tsx +++ b/frontend/src/pages/integrations/railway/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function RailwayAuthorizeIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function RailwayAuthorizeIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "railway", accessId: null, diff --git a/frontend/src/pages/integrations/railway/create.tsx b/frontend/src/pages/integrations/railway/create.tsx index 44b5ff232..4029f51a1 100644 --- a/frontend/src/pages/integrations/railway/create.tsx +++ b/frontend/src/pages/integrations/railway/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -18,10 +22,10 @@ import { useGetIntegrationAuthRailwayServices } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function RailwayCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const [targetAppId, setTargetAppId] = useState(""); const [targetEnvironmentId, setTargetEnvironmentId] = useState(""); @@ -96,7 +100,7 @@ export default function RailwayCreateIntegrationPage() { (service) => service.serviceId === targetServiceId ); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp.name, diff --git a/frontend/src/pages/integrations/render/authorize.tsx b/frontend/src/pages/integrations/render/authorize.tsx index 376d8fd8f..e20663a05 100644 --- a/frontend/src/pages/integrations/render/authorize.tsx +++ b/frontend/src/pages/integrations/render/authorize.tsx @@ -1,11 +1,14 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { useSaveIntegrationAccessToken} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function RenderCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +23,7 @@ export default function RenderCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "render", accessId: null, diff --git a/frontend/src/pages/integrations/render/create.tsx b/frontend/src/pages/integrations/render/create.tsx index 087682dde..fc347f835 100644 --- a/frontend/src/pages/integrations/render/create.tsx +++ b/frontend/src/pages/integrations/render/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function RenderCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -56,7 +60,7 @@ export default function RenderCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/supabase/authorize.tsx b/frontend/src/pages/integrations/supabase/authorize.tsx index 1c411a487..f580aacab 100644 --- a/frontend/src/pages/integrations/supabase/authorize.tsx +++ b/frontend/src/pages/integrations/supabase/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function SupabaseCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function SupabaseCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "supabase", accessToken: apiKey, diff --git a/frontend/src/pages/integrations/supabase/create.tsx b/frontend/src/pages/integrations/supabase/create.tsx index a759e2ab9..0b9332918 100644 --- a/frontend/src/pages/integrations/supabase/create.tsx +++ b/frontend/src/pages/integrations/supabase/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function SupabaseCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -57,7 +61,7 @@ export default function SupabaseCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/teamcity/authorize.tsx b/frontend/src/pages/integrations/teamcity/authorize.tsx index b417e3c19..da48730b4 100644 --- a/frontend/src/pages/integrations/teamcity/authorize.tsx +++ b/frontend/src/pages/integrations/teamcity/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function TeamCityCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [serverUrl, setServerUrl] = useState(""); @@ -29,7 +34,7 @@ export default function TeamCityCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "teamcity", accessId: null, diff --git a/frontend/src/pages/integrations/teamcity/create.tsx b/frontend/src/pages/integrations/teamcity/create.tsx index a2aa86db4..a6282af92 100644 --- a/frontend/src/pages/integrations/teamcity/create.tsx +++ b/frontend/src/pages/integrations/teamcity/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function TeamCityCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -56,7 +60,7 @@ export default function TeamCityCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/terraform-cloud/authorize.tsx b/frontend/src/pages/integrations/terraform-cloud/authorize.tsx index c569bdcca..aba5152a0 100644 --- a/frontend/src/pages/integrations/terraform-cloud/authorize.tsx +++ b/frontend/src/pages/integrations/terraform-cloud/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function TerraformCloudCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [workspacesId, setWorkSpacesId] = useState(""); @@ -29,7 +34,7 @@ export default function TerraformCloudCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "terraform-cloud", accessId: workspacesId, diff --git a/frontend/src/pages/integrations/terraform-cloud/create.tsx b/frontend/src/pages/integrations/terraform-cloud/create.tsx index 47c33948c..6245265a0 100644 --- a/frontend/src/pages/integrations/terraform-cloud/create.tsx +++ b/frontend/src/pages/integrations/terraform-cloud/create.tsx @@ -2,6 +2,8 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { useCreateIntegration } from "@app/hooks/api"; + import { Button, Card, @@ -16,7 +18,6 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; const variableTypes = [ { name: "env" }, @@ -25,6 +26,7 @@ const variableTypes = [ export default function TerraformCloudCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -70,7 +72,7 @@ export default function TerraformCloudCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/travisci/authorize.tsx b/frontend/src/pages/integrations/travisci/authorize.tsx index ec285d8aa..8c688c981 100644 --- a/frontend/src/pages/integrations/travisci/authorize.tsx +++ b/frontend/src/pages/integrations/travisci/authorize.tsx @@ -1,11 +1,16 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function TravisCICreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -20,7 +25,7 @@ export default function TravisCICreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "travisci", accessToken: apiKey, diff --git a/frontend/src/pages/integrations/travisci/create.tsx b/frontend/src/pages/integrations/travisci/create.tsx index 5708bea08..5f83b35d2 100644 --- a/frontend/src/pages/integrations/travisci/create.tsx +++ b/frontend/src/pages/integrations/travisci/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function TravisCICreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -56,7 +60,7 @@ export default function TravisCICreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/integrations/vercel/create.tsx b/frontend/src/pages/integrations/vercel/create.tsx index 18c1835f6..39791d6c9 100644 --- a/frontend/src/pages/integrations/vercel/create.tsx +++ b/frontend/src/pages/integrations/vercel/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -17,7 +21,6 @@ import { useGetIntegrationAuthVercelBranches } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; const vercelEnvironments = [ { name: "Development", slug: "development" }, @@ -27,6 +30,7 @@ const vercelEnvironments = [ export default function VercelCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState(""); const [secretPath, setSecretPath] = useState("/"); @@ -81,7 +85,7 @@ export default function VercelCreateIntegrationPage() { const path = targetEnvironment === "preview" && targetBranch !== "" ? targetBranch : null; - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp.name, diff --git a/frontend/src/pages/integrations/vercel/oauth2/callback.tsx b/frontend/src/pages/integrations/vercel/oauth2/callback.tsx index ebde5869a..dd884d8b0 100644 --- a/frontend/src/pages/integrations/vercel/oauth2/callback.tsx +++ b/frontend/src/pages/integrations/vercel/oauth2/callback.tsx @@ -2,10 +2,13 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; -import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; +import { + useAuthorizeIntegration +} from "@app/hooks/api"; export default function VercelOAuth2CallbackPage() { const router = useRouter(); + const { mutateAsync } = useAuthorizeIntegration(); const { code, state } = queryString.parse(router.asPath.split("?")[1]); @@ -15,8 +18,8 @@ export default function VercelOAuth2CallbackPage() { // validate state if (state !== localStorage.getItem("latestCSRFToken")) return; localStorage.removeItem("latestCSRFToken"); - - const integrationAuth = await AuthorizeIntegration({ + + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id") as string, code: code as string, integration: "vercel" diff --git a/frontend/src/pages/integrations/windmill/authorize.tsx b/frontend/src/pages/integrations/windmill/authorize.tsx index f1dbf4a7c..11aece281 100644 --- a/frontend/src/pages/integrations/windmill/authorize.tsx +++ b/frontend/src/pages/integrations/windmill/authorize.tsx @@ -1,12 +1,17 @@ import { useState } from "react"; import { useRouter } from "next/router"; +import { + useSaveIntegrationAccessToken +} from "@app/hooks/api"; + import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; -import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; export default function WindmillCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useSaveIntegrationAccessToken(); + const [apiKey, setApiKey] = useState(""); const [apiKeyErrorText, setApiKeyErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -21,7 +26,7 @@ export default function WindmillCreateIntegrationPage() { setIsLoading(true); - const integrationAuth = await saveIntegrationAccessToken({ + const integrationAuth = await mutateAsync({ workspaceId: localStorage.getItem("projectData.id"), integration: "windmill", accessToken: apiKey, diff --git a/frontend/src/pages/integrations/windmill/create.tsx b/frontend/src/pages/integrations/windmill/create.tsx index a6cb6f8eb..66559d020 100644 --- a/frontend/src/pages/integrations/windmill/create.tsx +++ b/frontend/src/pages/integrations/windmill/create.tsx @@ -2,6 +2,10 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import queryString from "query-string"; +import { + useCreateIntegration +} from "@app/hooks/api"; + import { Button, Card, @@ -16,10 +20,10 @@ import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; -import createIntegration from "../../api/integrations/createIntegration"; export default function WindmillCreateIntegrationPage() { const router = useRouter(); + const { mutateAsync } = useCreateIntegration(); const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); @@ -57,7 +61,7 @@ export default function WindmillCreateIntegrationPage() { setIsLoading(true); - await createIntegration({ + await mutateAsync({ integrationAuthId: integrationAuth?._id, isActive: true, app: targetApp, diff --git a/frontend/src/pages/org/[id]/overview/index.tsx b/frontend/src/pages/org/[id]/overview/index.tsx index 15ce5a9f6..befd75202 100644 --- a/frontend/src/pages/org/[id]/overview/index.tsx +++ b/frontend/src/pages/org/[id]/overview/index.tsx @@ -36,11 +36,10 @@ import { } from "@app/components/v2"; import { TabsObject } from "@app/components/v2/Tabs"; import { useSubscription, useUser, useWorkspace } from "@app/context"; -import { fetchOrgUsers, useAddUserToWs, useCreateWorkspace, useUploadWsKey } from "@app/hooks/api"; +import { fetchOrgUsers, useAddUserToWs, useCreateWorkspace, useRegisterUserAction,useUploadWsKey } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; import { encryptAssymmetric } from "../../../../components/utilities/cryptography/crypto"; -import registerUserAction from "../../../api/userActions/registerUserAction"; const features = [ { @@ -70,6 +69,7 @@ const LearningItem = ({ userAction, link }: ItemProps): JSX.Element => { + const registerUserAction = useRegisterUserAction(); if (link) { return ( { if (userAction && userAction !== "first_time_secrets_pushed") { - await registerUserAction({ - action: userAction - }); + await registerUserAction.mutateAsync( + userAction + ); } }} className={`group relative flex h-[5.5rem] w-full items-center justify-between overflow-hidden rounded-md border ${ @@ -130,9 +130,7 @@ const LearningItem = ({ tabIndex={0} onClick={async () => { if (userAction) { - await registerUserAction({ - action: userAction - }); + await registerUserAction.mutateAsync(userAction); } }} className="relative my-1.5 flex h-[5.5rem] w-full cursor-pointer items-center justify-between overflow-hidden rounded-md border border-dashed border-bunker-400 bg-bunker-700 py-2 pl-2 pr-6 shadow-xl duration-200 hover:bg-bunker-500" @@ -169,6 +167,7 @@ const LearningItemSquare = ({ userAction, link }: ItemProps): JSX.Element => { + const registerUserAction = useRegisterUserAction(); return ( { if (userAction && userAction !== "first_time_secrets_pushed") { - await registerUserAction({ - action: userAction - }); + await registerUserAction.mutateAsync(userAction); } }} className={`group relative flex w-full items-center justify-between overflow-hidden rounded-md border ${ diff --git a/frontend/src/pages/password-reset.tsx b/frontend/src/pages/password-reset.tsx index 30efc2c3b..b38f67c01 100644 --- a/frontend/src/pages/password-reset.tsx +++ b/frontend/src/pages/password-reset.tsx @@ -12,11 +12,10 @@ import Button from "@app/components/basic/buttons/Button"; import InputField from "@app/components/basic/InputField"; import passwordCheck from "@app/components/utilities/checks/PasswordCheck"; import Aes256Gcm from "@app/components/utilities/cryptography/aes-256-gcm"; +import { useResetPassword,useVerifyPasswordResetCode } from "@app/hooks/api"; +import { getBackupEncryptedPrivateKey } from "@app/hooks/api/auth/queries"; import { deriveArgonKey } from "../components/utilities/cryptography/crypto"; -import EmailVerifyOnPasswordReset from "./api/auth/EmailVerifyOnPasswordReset"; -import getBackupEncryptedPrivateKey from "./api/auth/getBackupEncryptedPrivateKey"; -import resetPasswordOnAccountRecovery from "./api/auth/resetPasswordOnAccountRecovery"; // eslint-disable-next-line new-cap const client = new jsrp.client(); @@ -34,6 +33,10 @@ export default function PasswordReset() { const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false); const router = useRouter(); + + const { mutateAsync: verifyPasswordResetCodeMutateAsync } = useVerifyPasswordResetCode(); + const { mutateAsync: resetPasswordMutateAsync } = useResetPassword(); + const parsedUrl = queryString.parse(router.asPath.split("?")[1]); const token = parsedUrl.token as string; const email = (parsedUrl.to as string)?.replace(" ", "+").trim(); @@ -43,7 +46,7 @@ export default function PasswordReset() { e.preventDefault(); try { const result = await getBackupEncryptedPrivateKey({ verificationToken }); - + setPrivateKey( Aes256Gcm.decrypt({ ciphertext: result.encryptedPrivateKey, @@ -53,7 +56,8 @@ export default function PasswordReset() { }) ); setStep(3); - } catch { + } catch(err) { + console.error(err); setBackupKeyError(true); } }; @@ -112,7 +116,7 @@ export default function PasswordReset() { secret: Buffer.from(derivedKey.hash) }); - const response = await resetPasswordOnAccountRecovery({ + await resetPasswordMutateAsync({ protectedKey, protectedKeyIV, protectedKeyTag, @@ -123,11 +127,9 @@ export default function PasswordReset() { verifier: result.verifier, verificationToken }); + + router.push("/login"); - // if everything works, go the main dashboard page. - if (response?.status === 200) { - router.push("/login"); - } setLoading(false) }); } @@ -146,15 +148,16 @@ export default function PasswordReset() { -
- - - - - - - - - - - - {isPermissionsLoading && ( - - )} - {!isPermissionsLoading && - serviceAccountWorkspacePermissions && - serviceAccountWorkspacePermissions.map( - ({ _id, workspace, environment, read, write }) => { - const environmentName = workspace.environments.find( - (env) => env.slug === environment - )?.name; - return ( - - - - - - - - ); - } - )} - {!isPermissionsLoading && serviceAccountWorkspacePermissions?.length === 0 && ( - - - - )} - -
ProjectEnvironmentReadWrite -
{workspace.name}{environmentName} - - {/**/} - - - - {/**/} - - - handlePopUpOpen("removeProjectLevelPermission", { _id })} - > - - -
- -
-
- { - handlePopUpToggle("addProjectLevelPermission", isOpen); - }} - > - -
- {!isUserWorkspacesLoading && userWorkspaces && ( - <> - ( - - - - )} - /> - ( - - - - )} - /> - { - const environments = - userWorkspaces?.find( - /* eslint-disable-next-line no-underscore-dangle */ - (userWorkspace) => userWorkspace._id === control?._formValues?.workspace - )?.environments ?? []; - return ( - - - - ); - }} - /> - - )} - { - const options = [ - { - label: "Read (default)", - value: "read" - }, - { - label: "Write", - value: "write" - } - ]; - - return ( - - <> - {options.map(({ label, value: optionValue }) => { - return ( - { - onChange({ - ...value, - [optionValue]: state - }); - }} - > - {label} - - ); - })} - - - ); - }} - /> -
- - - - -
- -
-
- handlePopUpToggle("removeProjectLevelPermission", isOpen)} - onDeleteApproved={onRemoveProjectLevelPermission} - /> -
- ); -}; diff --git a/frontend/src/views/Settings/CreateServiceAccountPage/components/SAProjectLevelPermissionsTable/index.tsx b/frontend/src/views/Settings/CreateServiceAccountPage/components/SAProjectLevelPermissionsTable/index.tsx deleted file mode 100644 index fee5544ef..000000000 --- a/frontend/src/views/Settings/CreateServiceAccountPage/components/SAProjectLevelPermissionsTable/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { SAProjectLevelPermissionsTable } from "./SAProjectLevelPermissionsTable"; \ No newline at end of file diff --git a/frontend/src/views/Settings/CreateServiceAccountPage/components/ServiceAccountNameChangeSection/ServiceAccountNameChangeSection.tsx b/frontend/src/views/Settings/CreateServiceAccountPage/components/ServiceAccountNameChangeSection/ServiceAccountNameChangeSection.tsx deleted file mode 100644 index 4c6cd64b7..000000000 --- a/frontend/src/views/Settings/CreateServiceAccountPage/components/ServiceAccountNameChangeSection/ServiceAccountNameChangeSection.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { useEffect } from "react"; -import { Controller, useForm } from "react-hook-form"; -import { faCheck } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { yupResolver } from "@hookform/resolvers/yup"; -import * as yup from "yup"; - -import { - Button, - FormControl, - Input} from "@app/components/v2"; -import { - useGetServiceAccountById, - useRenameServiceAccount -} from "@app/hooks/api"; - -const formSchema = yup.object({ - name: yup.string().required().label("Service Account Name") -}); - -type FormData = yup.InferType; - -type Props = { - serviceAccountId: string; -} - -export const ServiceAccountNameChangeSection = ({ - serviceAccountId -}: Props) => { - const { data: serviceAccount, isLoading: isServiceAccountLoading } = useGetServiceAccountById(serviceAccountId); - - const renameServiceAccount = useRenameServiceAccount(); - - const { - handleSubmit, - control, - reset, - formState: { isDirty, isSubmitting } - } = useForm({ resolver: yupResolver(formSchema) }); - - useEffect(() => { - reset({ name: serviceAccount?.name }); - }, [serviceAccount?.name]); - - const onFormSubmit = async ({ name }: FormData) => { - try { - await renameServiceAccount.mutateAsync({ - serviceAccountId, - name - }); - } catch (err) { - console.error(err); - } - } - - return ( -
-

Name

-
- {!isServiceAccountLoading && ( - ( - - - - )} - control={control} - name="name" - /> - )} -
- -
- ); -} diff --git a/frontend/src/views/Settings/CreateServiceAccountPage/components/ServiceAccountNameChangeSection/index.tsx b/frontend/src/views/Settings/CreateServiceAccountPage/components/ServiceAccountNameChangeSection/index.tsx deleted file mode 100644 index bedbfa7a4..000000000 --- a/frontend/src/views/Settings/CreateServiceAccountPage/components/ServiceAccountNameChangeSection/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { ServiceAccountNameChangeSection } from "./ServiceAccountNameChangeSection"; \ No newline at end of file diff --git a/frontend/src/views/Settings/CreateServiceAccountPage/components/index.tsx b/frontend/src/views/Settings/CreateServiceAccountPage/components/index.tsx deleted file mode 100644 index 20d12ed5a..000000000 --- a/frontend/src/views/Settings/CreateServiceAccountPage/components/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export { CopyServiceAccountIDSection } from "./CopyServiceAccountIDSection"; -export { CopyServiceAccountPublicKeySection } from "./CopyServiceAccountPublicKeySection"; -export { SAProjectLevelPermissionsTable } from "./SAProjectLevelPermissionsTable"; -export { ServiceAccountNameChangeSection } from "./ServiceAccountNameChangeSection"; \ No newline at end of file diff --git a/frontend/src/views/Settings/CreateServiceAccountPage/index.tsx b/frontend/src/views/Settings/CreateServiceAccountPage/index.tsx deleted file mode 100644 index 8dfecafb1..000000000 --- a/frontend/src/views/Settings/CreateServiceAccountPage/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { CreateServiceAccountPage } from "./CreateServiceAccountPage"; \ No newline at end of file diff --git a/frontend/src/views/Settings/PersonalSettingsPage/SecuritySection/MFASection.tsx b/frontend/src/views/Settings/PersonalSettingsPage/SecuritySection/MFASection.tsx index 8f9b36db7..6f52b7427 100644 --- a/frontend/src/views/Settings/PersonalSettingsPage/SecuritySection/MFASection.tsx +++ b/frontend/src/views/Settings/PersonalSettingsPage/SecuritySection/MFASection.tsx @@ -1,17 +1,14 @@ -import { useEffect, useState } from "react"; - import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { Checkbox, EmailServiceSetupModal } from "@app/components/v2"; +import { + useGetUser, + useUpdateMfaEnabled} from "@app/hooks/api"; import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; import { usePopUp } from "@app/hooks/usePopUp"; -import { useGetUser } from "../../../../hooks/api"; -import { User } from "../../../../hooks/api/types"; -import updateMyMfaEnabled from "../../../../pages/api/user/updateMyMfaEnabled"; - export const MFASection = () => { - const [isMfaEnabled, setIsMfaEnabled] = useState(false); const { data: user } = useGetUser(); + const { mutateAsync } = useUpdateMfaEnabled(); const { createNotification } = useNotificationContext(); const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp([ "setUpEmail" @@ -19,22 +16,12 @@ export const MFASection = () => { const {data: serverDetails } = useFetchServerStatus() - useEffect(() => { - if (user && typeof user.isMfaEnabled !== "undefined") { - setIsMfaEnabled(user.isMfaEnabled); - } - }, [user]); - const toggleMfa = async (state: boolean) => { try { - const newUser: User = await updateMyMfaEnabled({ + const newUser = await mutateAsync({ isMfaEnabled: state }); - if (newUser) { - setIsMfaEnabled(newUser.isMfaEnabled); - } - createNotification({ text: `${newUser.isMfaEnabled ? "Successfully turned on two-factor authentication." : "Successfully turned off two-factor authentication."}`, type: "success" @@ -55,20 +42,22 @@ export const MFASection = () => {

Two-factor Authentication

- { - if (serverDetails?.emailConfigured){ - toggleMfa(state as boolean); - } else { - handlePopUpOpen("setUpEmail"); - } - }} - > - Enable 2-factor authentication via your personal email. - + {user && ( + { + if (serverDetails?.emailConfigured){ + toggleMfa(state as boolean); + } else { + handlePopUpOpen("setUpEmail"); + } + }} + > + Enable 2-factor authentication via your personal email. + + )}
{ const { currentWorkspace } = useWorkspace(); - const [bot, setBot] = useState(null); - - useEffect(() => { - (async () => { - if (currentWorkspace) { - // get project bot - setBot(await getBot({ - workspaceId: currentWorkspace._id - })); - } - })(); - }, [currentWorkspace]); + const { data: bot } = useGetWorkspaceBot(currentWorkspace?._id ?? ""); + const { mutateAsync: updateBotActiveStatus } = useUpdateBotActiveStatus(); + const { data: wsKey } = useGetUserWsKey(currentWorkspace?._id ?? ""); /** * Activate bot for project by performing the following steps: @@ -38,14 +24,12 @@ export const E2EESection = () => { try { if (!currentWorkspace?._id) return; - if (bot) { + if (bot && wsKey) { // case: there is a bot if (!bot.isActive) { // bot is not active -> activate bot - const key = await getLatestFileKey({ - workspaceId: currentWorkspace._id - }); + const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); if (!PRIVATE_KEY) { @@ -53,9 +37,9 @@ export const E2EESection = () => { } const WORKSPACE_KEY = decryptAssymmetric({ - ciphertext: key.latestKey.encryptedKey, - nonce: key.latestKey.nonce, - publicKey: key.latestKey.sender.publicKey, + ciphertext: wsKey.encryptedKey, + nonce: wsKey.nonce, + publicKey: wsKey.sender.publicKey, privateKey: PRIVATE_KEY }); @@ -69,22 +53,20 @@ export const E2EESection = () => { encryptedKey: ciphertext, nonce }; - - const botx = await setBotActiveStatus({ - botId: bot._id, + + await updateBotActiveStatus({ + workspaceId: currentWorkspace._id, + botKey, isActive: true, - botKey + botId: bot._id }); - - setBot(botx.bot); } else { // bot is active -> deactivate bot - const botx = await setBotActiveStatus({ + await updateBotActiveStatus({ + isActive: false, botId: bot._id, - isActive: false + workspaceId: currentWorkspace._id }); - - setBot(botx.bot); } } } catch (err) { diff --git a/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx b/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx index 032552958..65be231b9 100644 --- a/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx +++ b/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx @@ -17,8 +17,8 @@ import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLo import SecurityClient from "@app/components/utilities/SecurityClient"; import { Button, Input } from "@app/components/v2"; import { useGetCommonPasswords } from "@app/hooks/api"; -import completeAccountInformationSignup from "@app/pages/api/auth/CompleteAccountInformationSignup"; -import getOrganizations from "@app/pages/api/organization/getOrgs"; +import { completeAccountSignup } from "@app/hooks/api/auth/queries"; +import { fetchOrganizations } from "@app/hooks/api/organization/queries"; import ProjectService from "@app/services/ProjectService"; // eslint-disable-next-line new-cap @@ -157,7 +157,7 @@ export const UserInfoSSOStep = ({ secret: Buffer.from(derivedKey.hash) }); - const response = await completeAccountInformationSignup({ + const response = await completeAccountSignup({ email, firstName: name.split(" ")[0], lastName: name.split(" ").slice(1).join(" "), @@ -188,7 +188,7 @@ export const UserInfoSSOStep = ({ privateKey }); - const userOrgs = await getOrganizations(); + const userOrgs = await fetchOrganizations(); const orgId = userOrgs[0]?._id; const project = await ProjectService.initProject({ organizationId: orgId,