mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-03 20:26:05 +00:00
Merge remote-tracking branch 'origin' into groups
This commit is contained in:
@@ -19,7 +19,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
.min(1)
|
.min(1)
|
||||||
.trim()
|
.trim()
|
||||||
.refine(
|
.refine(
|
||||||
(val) => Object.keys(OrgMembershipRole).includes(val),
|
(val) => !Object.keys(OrgMembershipRole).includes(val),
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.refine((v) => slugify(v) === v, {
|
.refine((v) => slugify(v) === v, {
|
||||||
|
|||||||
+2
-1
@@ -9,6 +9,7 @@ import jmespath from "jmespath";
|
|||||||
import knex from "knex";
|
import knex from "knex";
|
||||||
|
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
|
import { getDbConnectionHost } from "@app/lib/knex";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
|
|
||||||
import { TAssignOp, TDbProviderClients, TDirectAssignOp, THttpProviderFunction } from "../templates/types";
|
import { TAssignOp, TDbProviderClients, TDirectAssignOp, THttpProviderFunction } from "../templates/types";
|
||||||
@@ -89,7 +90,7 @@ export const secretRotationDbFn = async ({
|
|||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
|
|
||||||
const ssl = ca ? { rejectUnauthorized: false, ca } : undefined;
|
const ssl = ca ? { rejectUnauthorized: false, ca } : undefined;
|
||||||
if (host === "localhost" || host === "127.0.0.1" || appCfg.DB_CONNECTION_URI.includes(host))
|
if (host === "localhost" || host === "127.0.0.1" || getDbConnectionHost(appCfg.DB_CONNECTION_URI) === host)
|
||||||
throw new Error("Invalid db host");
|
throw new Error("Invalid db host");
|
||||||
|
|
||||||
const db = knex({
|
const db = knex({
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { URL } from "url"; // Import the URL class
|
||||||
|
|
||||||
|
export const getDbConnectionHost = (urlString: string) => {
|
||||||
|
try {
|
||||||
|
const url = new URL(urlString);
|
||||||
|
// Split hostname and port (if provided)
|
||||||
|
return url.hostname.split(":")[0];
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -4,6 +4,7 @@ import { Tables } from "knex/types/tables";
|
|||||||
|
|
||||||
import { DatabaseError } from "../errors";
|
import { DatabaseError } from "../errors";
|
||||||
|
|
||||||
|
export * from "./connection";
|
||||||
export * from "./join";
|
export * from "./join";
|
||||||
export * from "./select";
|
export * from "./select";
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ export const fastifySwagger = fp(async (fastify) => {
|
|||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
},
|
},
|
||||||
servers: [
|
servers: [
|
||||||
{
|
|
||||||
url: "http://localhost:8080",
|
|
||||||
description: "Local server"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
url: "https://app.infisical.com",
|
url: "https://app.infisical.com",
|
||||||
description: "Production server"
|
description: "Production server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "http://localhost:8080",
|
||||||
|
description: "Local server"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
components: {
|
components: {
|
||||||
|
|||||||
@@ -150,8 +150,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
message: "Slug must be a valid slug"
|
message: "Slug must be a valid slug"
|
||||||
})
|
})
|
||||||
.optional()
|
.optional()
|
||||||
.describe(PROJECTS.CREATE.slug),
|
.describe(PROJECTS.CREATE.slug)
|
||||||
organizationSlug: z.string().trim().describe(PROJECTS.CREATE.organizationSlug)
|
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -166,7 +165,6 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
orgSlug: req.body.organizationSlug,
|
|
||||||
workspaceName: req.body.projectName,
|
workspaceName: req.body.projectName,
|
||||||
slug: req.body.slug
|
slug: req.body.slug
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ export const projectServiceFactory = ({
|
|||||||
* Create workspace. Make user the admin
|
* Create workspace. Make user the admin
|
||||||
* */
|
* */
|
||||||
const createProject = async ({
|
const createProject = async ({
|
||||||
orgSlug,
|
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
@@ -100,13 +99,7 @@ export const projectServiceFactory = ({
|
|||||||
workspaceName,
|
workspaceName,
|
||||||
slug: projectSlug
|
slug: projectSlug
|
||||||
}: TCreateProjectDTO) => {
|
}: TCreateProjectDTO) => {
|
||||||
if (!orgSlug) {
|
const organization = await orgDAL.findOne({ id: actorOrgId });
|
||||||
throw new BadRequestError({
|
|
||||||
message: "Must provide organization slug to create project"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const organization = await orgDAL.findOne({ slug: orgSlug });
|
|
||||||
|
|
||||||
const { permission, membership: orgMembership } = await permissionService.getOrgPermission(
|
const { permission, membership: orgMembership } = await permissionService.getOrgPermission(
|
||||||
actor,
|
actor,
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ export type TCreateProjectDTO = {
|
|||||||
actorAuthMethod: ActorAuthMethod;
|
actorAuthMethod: ActorAuthMethod;
|
||||||
actorId: string;
|
actorId: string;
|
||||||
actorOrgId?: string;
|
actorOrgId?: string;
|
||||||
orgSlug: string;
|
|
||||||
workspaceName: string;
|
workspaceName: string;
|
||||||
slug?: string;
|
slug?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ This guide walks through how you can use these paid features in Infisical.
|
|||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
<Step title="Purchase a license">
|
<Step title="Purchase a license">
|
||||||
Start by either signing up for a free demo [here](https://infisical.com/schedule-demo) or contacting team@infisical.com to purchase a license.
|
Start by either signing up for a free demo [here](https://infisical.com/schedule-demo) or contacting sales@infisical.com to purchase a license.
|
||||||
|
|
||||||
Once purchased, you will be issued a license key.
|
Once purchased, you will be issued a license key.
|
||||||
</Step>
|
</Step>
|
||||||
@@ -25,4 +25,4 @@ This guide walks through how you can use these paid features in Infisical.
|
|||||||
Once the license expires, Infisical will continue to run, but EE features will be disabled until the license is renewed or a new one is purchased.
|
Once the license expires, Infisical will continue to run, but EE features will be disabled until the license is renewed or a new one is purchased.
|
||||||
</Note>
|
</Note>
|
||||||
</Step>
|
</Step>
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|||||||
@@ -196,10 +196,8 @@ export default function UserInfoStep({
|
|||||||
|
|
||||||
const userOrgs = await fetchOrganizations();
|
const userOrgs = await fetchOrganizations();
|
||||||
|
|
||||||
const orgSlug = userOrgs[0]?.slug;
|
|
||||||
const orgId = userOrgs[0]?.id;
|
const orgId = userOrgs[0]?.id;
|
||||||
const project = await ProjectService.initProject({
|
const project = await ProjectService.initProject({
|
||||||
organizationSlug: orgSlug,
|
|
||||||
projectName: "Example Project"
|
projectName: "Example Project"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
/* eslint-disable vars-on-top */
|
/* eslint-disable vars-on-top */
|
||||||
/* eslint-disable no-var */
|
/* eslint-disable no-var */
|
||||||
/* eslint-disable func-names */
|
/* eslint-disable func-names */
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|
||||||
import { INTERCOMid as APPid } from "@app/components/utilities/config";
|
import { INTERCOMid as APPid } from "@app/components/utilities/config";
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
/* eslint-disable import/no-extraneous-dependencies */
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
/* eslint-disable global-require */
|
/* eslint-disable global-require */
|
||||||
|
|||||||
@@ -77,18 +77,11 @@ const secretsToBeAdded = [
|
|||||||
* @param {String} obj.projectName - name of new project
|
* @param {String} obj.projectName - name of new project
|
||||||
* @returns {Project} project - new project
|
* @returns {Project} project - new project
|
||||||
*/
|
*/
|
||||||
const initProjectHelper = async ({
|
const initProjectHelper = async ({ projectName }: { projectName: string }) => {
|
||||||
organizationSlug,
|
|
||||||
projectName
|
|
||||||
}: {
|
|
||||||
organizationSlug: string;
|
|
||||||
projectName: string;
|
|
||||||
}) => {
|
|
||||||
// create new project
|
// create new project
|
||||||
const {
|
const {
|
||||||
data: { project }
|
data: { project }
|
||||||
} = await createWorkspace({
|
} = await createWorkspace({
|
||||||
organizationSlug,
|
|
||||||
projectName
|
projectName
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -199,19 +199,17 @@ export const useGetWorkspaceIntegrations = (workspaceId: string) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const createWorkspace = ({
|
export const createWorkspace = ({
|
||||||
organizationSlug,
|
|
||||||
projectName
|
projectName
|
||||||
}: CreateWorkspaceDTO): Promise<{ data: { project: Workspace } }> => {
|
}: CreateWorkspaceDTO): Promise<{ data: { project: Workspace } }> => {
|
||||||
return apiRequest.post("/api/v2/workspace", { projectName, organizationSlug });
|
return apiRequest.post("/api/v2/workspace", { projectName });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCreateWorkspace = () => {
|
export const useCreateWorkspace = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation<{ data: { project: Workspace } }, {}, CreateWorkspaceDTO>({
|
return useMutation<{ data: { project: Workspace } }, {}, CreateWorkspaceDTO>({
|
||||||
mutationFn: async ({ organizationSlug, projectName }) =>
|
mutationFn: async ({ projectName }) =>
|
||||||
createWorkspace({
|
createWorkspace({
|
||||||
organizationSlug,
|
|
||||||
projectName
|
projectName
|
||||||
}),
|
}),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@@ -325,7 +323,13 @@ export const useDeleteUserFromWorkspace = () => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({ usernames, workspaceId }: { workspaceId: string; usernames: string[] }) => {
|
mutationFn: async ({
|
||||||
|
usernames,
|
||||||
|
workspaceId
|
||||||
|
}: {
|
||||||
|
workspaceId: string;
|
||||||
|
usernames: string[];
|
||||||
|
}) => {
|
||||||
const {
|
const {
|
||||||
data: { deletedMembership }
|
data: { deletedMembership }
|
||||||
} = await apiRequest.delete(`/api/v2/workspace/${workspaceId}/memberships`, {
|
} = await apiRequest.delete(`/api/v2/workspace/${workspaceId}/memberships`, {
|
||||||
@@ -391,11 +395,7 @@ export const useAddIdentityToWorkspace = () => {
|
|||||||
export const useUpdateIdentityWorkspaceRole = () => {
|
export const useUpdateIdentityWorkspaceRole = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({ identityId, workspaceId, roles }: TUpdateWorkspaceIdentityRoleDTO) => {
|
||||||
identityId,
|
|
||||||
workspaceId,
|
|
||||||
roles
|
|
||||||
}:TUpdateWorkspaceIdentityRoleDTO)=> {
|
|
||||||
const {
|
const {
|
||||||
data: { identityMembership }
|
data: { identityMembership }
|
||||||
} = await apiRequest.patch(
|
} = await apiRequest.patch(
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ export type TGetUpgradeProjectStatusDTO = {
|
|||||||
// mutation dto
|
// mutation dto
|
||||||
export type CreateWorkspaceDTO = {
|
export type CreateWorkspaceDTO = {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
organizationSlug: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RenameWorkspaceDTO = { workspaceID: string; newWorkspaceName: string };
|
export type RenameWorkspaceDTO = { workspaceID: string; newWorkspaceName: string };
|
||||||
@@ -82,16 +81,16 @@ export type TUpdateWorkspaceUserRoleDTO = {
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
roles: (
|
roles: (
|
||||||
| {
|
| {
|
||||||
role: string;
|
role: string;
|
||||||
isTemporary?: false;
|
isTemporary?: false;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
role: string;
|
role: string;
|
||||||
isTemporary: true;
|
isTemporary: true;
|
||||||
temporaryMode: ProjectUserMembershipTemporaryMode;
|
temporaryMode: ProjectUserMembershipTemporaryMode;
|
||||||
temporaryRange: string;
|
temporaryRange: string;
|
||||||
temporaryAccessStartTime: string;
|
temporaryAccessStartTime: string;
|
||||||
}
|
}
|
||||||
)[];
|
)[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -100,15 +99,15 @@ export type TUpdateWorkspaceIdentityRoleDTO = {
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
roles: (
|
roles: (
|
||||||
| {
|
| {
|
||||||
role: string;
|
role: string;
|
||||||
isTemporary?: false;
|
isTemporary?: false;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
role: string;
|
role: string;
|
||||||
isTemporary: true;
|
isTemporary: true;
|
||||||
temporaryMode: ProjectUserMembershipTemporaryMode;
|
temporaryMode: ProjectUserMembershipTemporaryMode;
|
||||||
temporaryRange: string;
|
temporaryRange: string;
|
||||||
temporaryAccessStartTime: string;
|
temporaryAccessStartTime: string;
|
||||||
}
|
}
|
||||||
)[];
|
)[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
/* eslint-disable vars-on-top */
|
/* eslint-disable vars-on-top */
|
||||||
/* eslint-disable no-var */
|
/* eslint-disable no-var */
|
||||||
/* eslint-disable func-names */
|
/* eslint-disable func-names */
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -91,7 +92,7 @@ export const AdminLayout = ({ children }: LayoutProps) => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="dark hidden h-screen w-full flex-col overflow-x-hidden md:flex">
|
<div className="dark hidden h-screen w-full flex-col overflow-x-hidden md:flex">
|
||||||
|
|||||||
@@ -236,7 +236,6 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
project: { id: newProjectId }
|
project: { id: newProjectId }
|
||||||
}
|
}
|
||||||
} = await createWs.mutateAsync({
|
} = await createWs.mutateAsync({
|
||||||
organizationSlug: currentOrg.slug,
|
|
||||||
projectName: name
|
projectName: name
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
||||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
||||||
import { useCallback, useEffect } from "react";
|
import { useCallback, useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
@@ -54,42 +52,40 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
const handleSelectOrganization = useCallback(
|
const handleSelectOrganization = useCallback(
|
||||||
async (organization: Organization) => {
|
async (organization: Organization) => {
|
||||||
|
const callbackPort = queryParams.get("callback_port");
|
||||||
|
|
||||||
if (organization.authEnforced) {
|
if (organization.authEnforced) {
|
||||||
// org has an org-level auth method enabled (e.g. SAML)
|
// org has an org-level auth method enabled (e.g. SAML)
|
||||||
// -> logout + redirect to SAML SSO
|
// -> logout + redirect to SAML SSO
|
||||||
|
let samlUrl = `/api/v1/sso/redirect/saml2/organizations/${organization.slug}`;
|
||||||
|
|
||||||
|
if (callbackPort) {
|
||||||
|
samlUrl += `?callback_port=${callbackPort}`;
|
||||||
|
}
|
||||||
|
|
||||||
await logout.mutateAsync();
|
await logout.mutateAsync();
|
||||||
window.open(`/api/v1/sso/redirect/saml2/organizations/${organization.slug}`);
|
window.open(samlUrl);
|
||||||
window.close();
|
window.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { token } = await selectOrg.mutateAsync({ organizationId: organization.id });
|
const { token } = await selectOrg.mutateAsync({ organizationId: organization.id });
|
||||||
|
|
||||||
const callbackPort = queryParams.get("callback_port");
|
|
||||||
|
|
||||||
if (callbackPort) {
|
if (callbackPort) {
|
||||||
const privateKey = localStorage.getItem("PRIVATE_KEY");
|
const privateKey = localStorage.getItem("PRIVATE_KEY");
|
||||||
|
|
||||||
if (!privateKey) {
|
let error: string | null = null;
|
||||||
createNotification({
|
|
||||||
text: "Private key not found",
|
|
||||||
type: "error"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.email) {
|
if (!privateKey) error = "Private key not found";
|
||||||
createNotification({
|
if (!user.email) error = "User email not found";
|
||||||
text: "User email not found",
|
if (!token) error = "No token found";
|
||||||
type: "error"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!token) {
|
if (error) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "No token found",
|
text: error,
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
@@ -172,33 +168,22 @@ export default function LoginPage() {
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
organizations.data?.map((org) => (
|
organizations.data?.map((org) => (
|
||||||
|
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
||||||
<div
|
<div
|
||||||
onClick={() => handleSelectOrganization(org)}
|
onClick={() => handleSelectOrganization(org)}
|
||||||
key={org.id}
|
key={org.id}
|
||||||
className="group flex cursor-pointer items-center justify-between rounded-md bg-mineshaft-700 px-4 py-3 capitalize text-gray-200 shadow-md transition-colors hover:bg-mineshaft-600"
|
className="group flex cursor-pointer items-center justify-between rounded-md bg-mineshaft-700 px-4 py-3 capitalize text-gray-200 shadow-md transition-colors hover:bg-mineshaft-600"
|
||||||
>
|
>
|
||||||
<p className="transition-colors">{org.name}</p>
|
<p className="truncate transition-colors">{org.name}</p>
|
||||||
|
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={faArrowRight}
|
icon={faArrowRight}
|
||||||
className="text-gray-400 transition-colors group-hover:text-primary-500"
|
className="text-gray-400 transition-all group-hover:translate-x-2 group-hover:text-primary-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
|
||||||
className="mt-8"
|
|
||||||
colorSchema="primary"
|
|
||||||
isLoading={logout.isLoading}
|
|
||||||
isDisabled={logout.isLoading}
|
|
||||||
variant="solid"
|
|
||||||
size="lg"
|
|
||||||
onClick={handleLogout}
|
|
||||||
>
|
|
||||||
Logout
|
|
||||||
</Button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -454,7 +454,12 @@ const LearningItemSquare = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const formSchema = yup.object({
|
const formSchema = yup.object({
|
||||||
name: yup.string().required().label("Project Name").trim().max(64, "Too long, maximum length is 64 characters"),
|
name: yup
|
||||||
|
.string()
|
||||||
|
.required()
|
||||||
|
.label("Project Name")
|
||||||
|
.trim()
|
||||||
|
.max(64, "Too long, maximum length is 64 characters"),
|
||||||
addMembers: yup.bool().required().label("Add Members")
|
addMembers: yup.bool().required().label("Add Members")
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -507,7 +512,6 @@ const OrganizationPage = withPermission(
|
|||||||
project: { id: newProjectId }
|
project: { id: newProjectId }
|
||||||
}
|
}
|
||||||
} = await createWs.mutateAsync({
|
} = await createWs.mutateAsync({
|
||||||
organizationSlug: currentOrg.slug,
|
|
||||||
projectName: name
|
projectName: name
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -631,22 +635,21 @@ const OrganizationPage = withPermission(
|
|||||||
{orgWorkspaces
|
{orgWorkspaces
|
||||||
.filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
|
.filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
|
||||||
.map((workspace) => (
|
.map((workspace) => (
|
||||||
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
|
||||||
<div
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
router.push(`/project/${workspace.id}/secrets/overview`);
|
||||||
|
localStorage.setItem("projectData.id", workspace.id);
|
||||||
|
}}
|
||||||
key={workspace.id}
|
key={workspace.id}
|
||||||
className="min-w-72 flex h-40 flex-col justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
|
className="min-w-72 group flex h-40 cursor-pointer flex-col justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
|
||||||
>
|
>
|
||||||
<div className="mt-0 truncate text-lg text-mineshaft-100">{workspace.name}</div>
|
<div className="mt-0 truncate text-lg text-mineshaft-100">{workspace.name}</div>
|
||||||
<div className="mt-0 pb-6 text-sm text-mineshaft-300">
|
<div className="mt-0 pb-6 text-sm text-mineshaft-300">
|
||||||
{workspace.environments?.length || 0} environments
|
{workspace.environments?.length || 0} environments
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button type="button">
|
||||||
type="button"
|
<div className="group ml-auto w-max cursor-pointer rounded-full border border-mineshaft-600 bg-mineshaft-900 py-2 px-4 text-sm text-mineshaft-300 transition-all group-hover:border-primary-500/80 group-hover:bg-primary-800/20 group-hover:text-mineshaft-200">
|
||||||
onClick={() => {
|
|
||||||
router.push(`/project/${workspace.id}/secrets/overview`);
|
|
||||||
localStorage.setItem("projectData.id", workspace.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="group ml-auto w-max cursor-pointer rounded-full border border-mineshaft-600 bg-mineshaft-900 py-2 px-4 text-sm text-mineshaft-300 hover:border-primary-500/80 hover:bg-primary-800/20 hover:text-mineshaft-200">
|
|
||||||
Explore{" "}
|
Explore{" "}
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={faArrowRight}
|
icon={faArrowRight}
|
||||||
@@ -693,7 +696,7 @@ const OrganizationPage = withPermission(
|
|||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="group ml-auto w-max cursor-default rounded-full border border-mineshaft-600 bg-mineshaft-900 py-2 px-4 text-sm text-mineshaft-300 hover:border-primary-500/80 hover:bg-primary-800/20 hover:text-mineshaft-200"
|
className="group ml-auto w-max cursor-default rounded-full border border-mineshaft-600 bg-mineshaft-900 py-2 px-4 text-sm text-mineshaft-300 transition-all hover:border-primary-500/80 hover:bg-primary-800/20 hover:text-mineshaft-200"
|
||||||
href={feature.link}
|
href={feature.link}
|
||||||
>
|
>
|
||||||
Learn more{" "}
|
Learn more{" "}
|
||||||
|
|||||||
@@ -9,15 +9,8 @@ class ProjectService {
|
|||||||
* @param {String} obj.projectName - name of new project
|
* @param {String} obj.projectName - name of new project
|
||||||
* @returns {Project} project - new project
|
* @returns {Project} project - new project
|
||||||
*/
|
*/
|
||||||
static async initProject({
|
static async initProject({ projectName }: { projectName: string }) {
|
||||||
organizationSlug,
|
|
||||||
projectName
|
|
||||||
}: {
|
|
||||||
organizationSlug: string;
|
|
||||||
projectName: string;
|
|
||||||
}) {
|
|
||||||
return initProjectHelper({
|
return initProjectHelper({
|
||||||
organizationSlug,
|
|
||||||
projectName
|
projectName
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,14 +189,12 @@ export const UserInfoSSOStep = ({
|
|||||||
|
|
||||||
const userOrgs = await fetchOrganizations();
|
const userOrgs = await fetchOrganizations();
|
||||||
const orgId = userOrgs[0]?.id;
|
const orgId = userOrgs[0]?.id;
|
||||||
const orgSlug = userOrgs[0]?.slug;
|
|
||||||
|
|
||||||
await selectOrganization({
|
await selectOrganization({
|
||||||
organizationId: orgId
|
organizationId: orgId
|
||||||
});
|
});
|
||||||
|
|
||||||
const project = await ProjectService.initProject({
|
const project = await ProjectService.initProject({
|
||||||
organizationSlug: orgSlug,
|
|
||||||
projectName: "Example Project"
|
projectName: "Example Project"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user