Fix merge conflicts

This commit is contained in:
Tuan Dang
2024-04-11 20:46:14 -07:00
10 changed files with 109 additions and 37 deletions

View File

@@ -192,6 +192,12 @@ export const PROJECTS = {
},
LIST_GROUPS_IN_PROJECT: {
projectSlug: "The slug of the project to list groups for."
},
LIST_INTEGRATION: {
workspaceId: "The ID of the project to list integrations for."
},
LIST_INTEGRATION_AUTHORIZATION: {
workspaceId: "The ID of the project to list integration auths for."
}
} as const;
@@ -553,11 +559,8 @@ export const INTEGRATION_AUTH = {
url: "",
namespace: "",
refreshToken: "The refresh token for integration authorization."
},
LIST_AUTHORIZATION: {
workspaceId: "The ID of the project to list integration auths for."
}
};
} as const;
export const INTEGRATION = {
CREATE: {

View File

@@ -7,7 +7,7 @@ import {
UserEncryptionKeysSchema,
UsersSchema
} from "@app/db/schemas";
import { INTEGRATION_AUTH, PROJECTS } from "@app/lib/api-docs";
import { PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -326,8 +326,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
description: "List integrations for a project.",
security: [
{
bearerAuth: []
}
],
params: z.object({
workspaceId: z.string().trim()
workspaceId: z.string().trim().describe(PROJECTS.LIST_INTEGRATION.workspaceId)
}),
response: {
200: z.object({
@@ -370,7 +376,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}
],
params: z.object({
workspaceId: z.string().trim().describe(INTEGRATION_AUTH.LIST_AUTHORIZATION.workspaceId)
workspaceId: z.string().trim().describe(PROJECTS.LIST_INTEGRATION_AUTHORIZATION.workspaceId)
}),
response: {
200: z.object({

View File

@@ -151,13 +151,11 @@ export const projectDALFactory = (db: TDbClient) => {
const findProjectById = async (id: string) => {
try {
const workspaces = await db(TableName.ProjectMembership)
const workspaces = await db(TableName.Project)
.where(`${TableName.Project}.id`, id)
.join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`)
.join(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
.leftJoin(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
.select(
selectAllTableCols(TableName.Project),
db.ref("id").withSchema(TableName.Project).as("_id"),
db.ref("id").withSchema(TableName.Environment).as("envId"),
db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
db.ref("name").withSchema(TableName.Environment).as("envName")
@@ -166,10 +164,11 @@ export const projectDALFactory = (db: TDbClient) => {
{ column: `${TableName.Project}.name`, order: "asc" },
{ column: `${TableName.Environment}.position`, order: "asc" }
]);
const project = sqlNestRelationships({
data: workspaces,
key: "id",
parentMapper: ({ _id, ...el }) => ({ _id, ...ProjectsSchema.parse(el) }),
parentMapper: ({ ...el }) => ({ _id: el.id, ...ProjectsSchema.parse(el) }),
childrenMapper: [
{
key: "envId",
@@ -199,14 +198,12 @@ export const projectDALFactory = (db: TDbClient) => {
throw new BadRequestError({ message: "Organization ID is required when querying with slugs" });
}
const projects = await db(TableName.ProjectMembership)
const projects = await db(TableName.Project)
.where(`${TableName.Project}.slug`, slug)
.where(`${TableName.Project}.orgId`, orgId)
.join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`)
.join(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
.leftJoin(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
.select(
selectAllTableCols(TableName.Project),
db.ref("id").withSchema(TableName.Project).as("_id"),
db.ref("id").withSchema(TableName.Environment).as("envId"),
db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
db.ref("name").withSchema(TableName.Environment).as("envName")
@@ -219,7 +216,7 @@ export const projectDALFactory = (db: TDbClient) => {
const project = sqlNestRelationships({
data: projects,
key: "id",
parentMapper: ({ _id, ...el }) => ({ _id, ...ProjectsSchema.parse(el) }),
parentMapper: ({ ...el }) => ({ _id: el.id, ...ProjectsSchema.parse(el) }),
childrenMapper: [
{
key: "envId",

View File

@@ -0,0 +1,4 @@
---
title: "List project integrations "
openapi: "GET /api/v1/workspace/{workspaceId}/integrations"
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

View File

@@ -520,7 +520,8 @@
"api-reference/endpoints/integrations/delete-auth-by-id",
"api-reference/endpoints/integrations/create",
"api-reference/endpoints/integrations/update",
"api-reference/endpoints/integrations/delete"
"api-reference/endpoints/integrations/delete",
"api-reference/endpoints/integrations/list-project-integrations"
]
},
{

View File

@@ -121,24 +121,35 @@ Without email configuration, Infisical's core functions like sign-up/login and s
</Accordion>
<Accordion title="AWS SES">
1. Create an account and [configure AWS SES](https://aws.amazon.com/premiumsupport/knowledge-center/ses-set-up-connect-smtp/) to send emails in the Amazon SES console.
2. Create an IAM user for SMTP authentication and obtain SMTP credentials in SMTP settings > Create SMTP credentials
<Steps>
<Step title="Create a verifed identity">
This will be used to verify the email you are sending from.
![Create SES identity](../../images/self-hosting/configuration/email/ses-create-identity.png)
<Info>
If you AWS SES is under sandbox mode, you will only be able to send emails to verified identies.
</Info>
</Step>
<Step title="Create an account and configure AWS SES">
Create an IAM user for SMTP authentication and obtain SMTP credentials in SMTP settings > Create SMTP credentials
![opening AWS SES console](../../images/self-hosting/configuration/email/email-aws-ses-console.png)
![opening AWS SES console](../../images/self-hosting/configuration/email/email-aws-ses-console.png)
![creating AWS IAM SES user](../../images/self-hosting/configuration/email/email-aws-ses-user.png)
![creating AWS IAM SES user](../../images/self-hosting/configuration/email/email-aws-ses-user.png)
</Step>
<Step title="Set up your SMTP environment variables">
With your AWS SES SMTP credentials, you can now set up your SMTP environment variables for your Infisical instance.
3. With your AWS SES SMTP credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=email-smtp.ap-northeast-1.amazonaws.com # SMTP endpoint obtained from SMTP settings
SMTP_USERNAME=xxx # your SMTP username
SMTP_PASSWORD=xxx # your SMTP password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
```
SMTP_HOST=email-smtp.ap-northeast-1.amazonaws.com # SMTP endpoint obtained from SMTP settings
SMTP_USERNAME=xxx # your SMTP username
SMTP_PASSWORD=xxx # your SMTP password
SMTP_PORT=587
SMTP_SECURE=false
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
</Step>
</Steps>
<Info>
Remember that you will need to restart Infisical for this to work properly.

View File

@@ -0,0 +1,29 @@
import { useRouter } from "next/router";
import { Button } from "../v2";
interface IProps {
projectId: string;
}
export const NoEnvironmentsBanner = ({ projectId }: IProps) => {
const router = useRouter();
return (
<div className="mt-4 flex w-full flex-row items-center rounded-md border border-primary-600/70 bg-primary/[.07] p-4 text-base text-white">
<div className="flex w-full flex-col text-sm">
<span className="mb-2 text-lg font-semibold">
No environments in your project was found
</span>
<p className="prose">
In order to use integrations, you need to create at least one environment in your project.
</p>
</div>
<div className="my-2">
<Button onClick={() => router.push(`/project/${projectId}/settings#environments`)}>
Add environments
</Button>
</div>
</div>
);
};

View File

@@ -1,10 +1,17 @@
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { NoEnvironmentsBanner } from "@app/components/integrations/NoEnvironmentsBanner";
import { createNotification } from "@app/components/notifications";
import { DeleteActionModal, Skeleton, Tooltip } from "@app/components/v2";
import { ProjectPermissionActions, ProjectPermissionSub, useProjectPermission } from "@app/context";
import {
ProjectPermissionActions,
ProjectPermissionSub,
useProjectPermission,
useWorkspace
} from "@app/context";
import { usePopUp } from "@app/hooks";
import { IntegrationAuth, TCloudIntegration } from "@app/hooks/api/types";
@@ -31,18 +38,32 @@ export const CloudIntegrationSection = ({
"deleteConfirmation"
] as const);
const { permission } = useProjectPermission();
const { currentWorkspace } = useWorkspace();
const isEmpty = !isLoading && !cloudIntegrations?.length;
const sortedCloudIntegrations = cloudIntegrations.sort((a, b) => a.name.localeCompare(b.name));
const sortedCloudIntegrations = useMemo(() => {
const sortedIntegrations = cloudIntegrations.sort((a, b) => a.name.localeCompare(b.name));
if (currentWorkspace?.environments.length === 0) {
return sortedIntegrations.map((integration) => ({ ...integration, isAvailable: false }));
}
return sortedIntegrations;
}, [cloudIntegrations, currentWorkspace?.environments]);
return (
<div>
<div className="px-5">
{currentWorkspace?.environments.length === 0 && (
<NoEnvironmentsBanner projectId={currentWorkspace.id} />
)}
</div>
<div className="m-4 mt-7 flex max-w-5xl flex-col items-start justify-between px-2 text-xl">
<h1 className="text-3xl font-semibold">{t("integrations.cloud-integrations")}</h1>
<p className="text-base text-gray-400">{t("integrations.click-to-start")}</p>
</div>
<div className="mx-6 grid grid-cols-2 gap-4 lg:grid-cols-3 2xl:grid-cols-4">
{isLoading &&
Array.from({ length: 12 }).map((_, index) => (

View File

@@ -251,7 +251,7 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
<div className="mt-6 flex flex-row text-sm text-bunker-400">
<Link href="/signup">
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
Don&apos;t have an acount yet? {t("login.create-account")}
Don&apos;t have an account yet? {t("login.create-account")}
</span>
</Link>
</div>