mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 12:27:28 +00:00
feat(infisical-pg): connected project api changes with frontend
This commit is contained in:
@@ -7,13 +7,13 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
if (!doesTableExist) {
|
if (!doesTableExist) {
|
||||||
await knex.schema.createTable(TableName.BackupPrivateKey, (t) => {
|
await knex.schema.createTable(TableName.BackupPrivateKey, (t) => {
|
||||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
t.string("encryptedPrivateKey").notNullable();
|
t.text("encryptedPrivateKey").notNullable();
|
||||||
t.string("iv").notNullable();
|
t.text("iv").notNullable();
|
||||||
t.string("tag").notNullable();
|
t.text("tag").notNullable();
|
||||||
t.string("algorithm").notNullable();
|
t.string("algorithm").notNullable();
|
||||||
t.string("keyEncoding").notNullable();
|
t.string("keyEncoding").notNullable();
|
||||||
t.string("salt").notNullable();
|
t.text("salt").notNullable();
|
||||||
t.string("verifier").notNullable();
|
t.text("verifier").notNullable();
|
||||||
t.timestamps(true, true, true);
|
t.timestamps(true, true, true);
|
||||||
t.uuid("userId").notNullable().unique();
|
t.uuid("userId").notNullable().unique();
|
||||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
t.timestamps(true, true, true);
|
t.timestamps(true, true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// environments
|
|
||||||
await createOnUpdateTrigger(knex, TableName.Project);
|
await createOnUpdateTrigger(knex, TableName.Project);
|
||||||
|
// environments
|
||||||
if (!(await knex.schema.hasTable(TableName.Environment))) {
|
if (!(await knex.schema.hasTable(TableName.Environment))) {
|
||||||
await knex.schema.createTable(TableName.Environment, (t) => {
|
await knex.schema.createTable(TableName.Environment, (t) => {
|
||||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
@@ -47,7 +47,8 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
|
|
||||||
export async function down(knex: Knex): Promise<void> {
|
export async function down(knex: Knex): Promise<void> {
|
||||||
await knex.schema.dropTableIfExists(TableName.Environment);
|
await knex.schema.dropTableIfExists(TableName.Environment);
|
||||||
|
await knex.schema.dropTableIfExists(TableName.ProjectKeys);
|
||||||
await knex.schema.dropTableIfExists(TableName.Project);
|
await knex.schema.dropTableIfExists(TableName.Project);
|
||||||
await dropOnUpdateTrigger(knex, TableName.Project);
|
|
||||||
await dropOnUpdateTrigger(knex, TableName.ProjectKeys);
|
await dropOnUpdateTrigger(knex, TableName.ProjectKeys);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.Project);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
// does not need update trigger we will do it manually
|
// does not need update trigger we will do it manually
|
||||||
t.timestamps(true, true, true);
|
t.timestamps(true, true, true);
|
||||||
t.uuid("projectId").notNullable();
|
t.uuid("projectId").notNullable();
|
||||||
t.foreign("projectId").references("id").inTable(TableName.ProjectRoles).onDelete("CASCADE");
|
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,8 +132,10 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
membership: ProjectMembershipsSchema,
|
data: z.object({
|
||||||
permissions: z.any().array()
|
membership: ProjectMembershipsSchema,
|
||||||
|
permissions: z.any().array()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -143,7 +145,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
req.auth.userId,
|
req.auth.userId,
|
||||||
req.params.projectId
|
req.params.projectId
|
||||||
);
|
);
|
||||||
return { permissions, membership };
|
return { data: { permissions, membership } };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,18 +11,22 @@ export const mergeOneToManyRelation = <
|
|||||||
childMapper: (arg: T) => C,
|
childMapper: (arg: T) => C,
|
||||||
childKey: Ck
|
childKey: Ck
|
||||||
) => {
|
) => {
|
||||||
const recordFirstVisitIndex: Record<string, number> = {};
|
let prevPkIndex = -1;
|
||||||
|
let prevPkId: null | string = null;
|
||||||
|
|
||||||
const groupedRecord: (P & Record<Ck, C[]>)[] = [];
|
const groupedRecord: (P & Record<Ck, C[]>)[] = [];
|
||||||
for (let i = 0; i < data.length; i += 1) {
|
for (let i = 0; i < data.length; i += 1) {
|
||||||
const pk = data[i][key];
|
const pk = data[i][key];
|
||||||
const row = data[i];
|
const row = data[i];
|
||||||
if (typeof recordFirstVisitIndex[pk] === "undefined") {
|
if (pk !== prevPkId) {
|
||||||
const parent = parentMapper(row) as any;
|
const parent = parentMapper(row) as any;
|
||||||
parent[childKey] = [];
|
parent[childKey] = [];
|
||||||
groupedRecord.push(parent);
|
groupedRecord.push(parent);
|
||||||
recordFirstVisitIndex[pk] = i;
|
prevPkId = pk;
|
||||||
|
prevPkIndex += 1;
|
||||||
}
|
}
|
||||||
groupedRecord[recordFirstVisitIndex[pk]][childKey].push(childMapper(row));
|
console.log(prevPkIndex, prevPkId);
|
||||||
|
groupedRecord[prevPkIndex][childKey].push(childMapper(row));
|
||||||
}
|
}
|
||||||
return groupedRecord;
|
return groupedRecord;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { ActorType } from "@app/services/auth/auth-type";
|
|||||||
export const injectPermission = fp(async (server) => {
|
export const injectPermission = fp(async (server) => {
|
||||||
server.decorateRequest("permission", null);
|
server.decorateRequest("permission", null);
|
||||||
server.addHook("onRequest", async (req) => {
|
server.addHook("onRequest", async (req) => {
|
||||||
|
if (!req.auth) return;
|
||||||
|
|
||||||
if (req.auth.actor === ActorType.USER) {
|
if (req.auth.actor === ActorType.USER) {
|
||||||
req.permission = { type: ActorType.USER, id: req.auth.userId };
|
req.permission = { type: ActorType.USER, id: req.auth.userId };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import { injectIdentity } from "../plugins/auth/inject-identity";
|
|||||||
import { registerV1Routes } from "./v1";
|
import { registerV1Routes } from "./v1";
|
||||||
import { registerV2Routes } from "./v2";
|
import { registerV2Routes } from "./v2";
|
||||||
import { registerV3Routes } from "./v3";
|
import { registerV3Routes } from "./v3";
|
||||||
|
import { injectPermission } from "../plugins/auth/inject-permission";
|
||||||
|
|
||||||
export const registerRoutes = async (
|
export const registerRoutes = async (
|
||||||
server: FastifyZodProvider,
|
server: FastifyZodProvider,
|
||||||
@@ -149,6 +150,7 @@ export const registerRoutes = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
await server.register(injectIdentity);
|
await server.register(injectIdentity);
|
||||||
|
await server.register(injectPermission);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/status",
|
url: "/status",
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
|||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
backupPrivateKey: BackupPrivateKeySchema
|
backupPrivateKey: BackupPrivateKeySchema.omit({ verifier: true })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -105,7 +105,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
|||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
backupPrivateKey: BackupPrivateKeySchema
|
backupPrivateKey: BackupPrivateKeySchema.omit({ verifier: true })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,13 @@ import {
|
|||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
export const registerProjectRouter = (server: FastifyZodProvider) => {
|
const projectWithEnv = ProjectsSchema.merge(
|
||||||
|
z.object({
|
||||||
|
environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:workspaceId/keys",
|
url: "/:workspaceId/keys",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -81,9 +87,7 @@ export const registerProjectRouter = (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
workspaces: ProjectsSchema.merge(
|
workspaces: projectWithEnv.array()
|
||||||
z.object({ environments: z.object({ name: z.string(), slug: z.string() }).array() })
|
|
||||||
).array()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -103,9 +107,7 @@ export const registerProjectRouter = (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
workspace: ProjectsSchema.merge(
|
workspace: projectWithEnv.optional()
|
||||||
z.object({ environments: z.object({ name: z.string(), slug: z.string() }).array() })
|
|
||||||
).optional()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -130,7 +132,7 @@ export const registerProjectRouter = (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
workspace: ProjectsSchema
|
workspace: projectWithEnv
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { UsersSchema } from "@app/db/schemas";
|
import { UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
user: UsersSchema
|
user: UsersSchema.merge(UserEncryptionKeysSchema.omit({ verifier: true }))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { AuthTokenSessionsSchema, OrganizationsSchema, UsersSchema } from "@app/db/schemas";
|
import {
|
||||||
|
AuthTokenSessionsSchema,
|
||||||
|
OrganizationsSchema,
|
||||||
|
UserEncryptionKeysSchema,
|
||||||
|
UsersSchema
|
||||||
|
} from "@app/db/schemas";
|
||||||
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
|
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMethod, AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMethod, AuthMode } from "@app/services/auth/auth-type";
|
||||||
@@ -195,7 +200,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
user: UsersSchema
|
user: UsersSchema.merge(UserEncryptionKeysSchema.omit({ verifier: true }))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -63,14 +63,17 @@ export const tokenServiceFactory = ({ tokenDal }: TAuthTokenServiceFactoryDep) =
|
|||||||
const tokenHash = await bcrypt.hash(token, appCfg.SALT_ROUNDS);
|
const tokenHash = await bcrypt.hash(token, appCfg.SALT_ROUNDS);
|
||||||
await tokenDal.transaction(async (tx) => {
|
await tokenDal.transaction(async (tx) => {
|
||||||
await tokenDal.delete({ userId, type, orgId: orgId || null }, tx);
|
await tokenDal.delete({ userId, type, orgId: orgId || null }, tx);
|
||||||
const newToken = await tokenDal.create({
|
const newToken = await tokenDal.create(
|
||||||
tokenHash,
|
{
|
||||||
expiresAt: tkCfg.expiresAt.toUTCString(),
|
tokenHash,
|
||||||
type,
|
expiresAt: tkCfg.expiresAt.toUTCString(),
|
||||||
userId,
|
type,
|
||||||
orgId,
|
userId,
|
||||||
triesLeft: tkCfg?.triesLeft
|
orgId,
|
||||||
});
|
triesLeft: tkCfg?.triesLeft
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
return newToken;
|
return newToken;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
TResetPasswordViaBackupKeyDTO
|
TResetPasswordViaBackupKeyDTO
|
||||||
} from "./auth-password-type";
|
} from "./auth-password-type";
|
||||||
import { AuthTokenType } from "./auth-type";
|
import { AuthTokenType } from "./auth-type";
|
||||||
|
import { SecretEncryptionAlgo, SecretKeyEncoding } from "@app/db/schemas";
|
||||||
|
|
||||||
type TAuthPasswordServiceFactoryDep = {
|
type TAuthPasswordServiceFactoryDep = {
|
||||||
authDal: TAuthDalFactory;
|
authDal: TAuthDalFactory;
|
||||||
@@ -212,13 +213,19 @@ export const authPaswordServiceFactory = ({
|
|||||||
);
|
);
|
||||||
if (!isValidClientProff) throw new Error("failed to create backup key");
|
if (!isValidClientProff) throw new Error("failed to create backup key");
|
||||||
const backup = await authDal.transaction(async (tx) => {
|
const backup = await authDal.transaction(async (tx) => {
|
||||||
const backupKey = await authDal.upsertBackupKey(userEnc.userId, {
|
const backupKey = await authDal.upsertBackupKey(
|
||||||
encryptedPrivateKey,
|
userEnc.userId,
|
||||||
iv,
|
{
|
||||||
tag,
|
encryptedPrivateKey,
|
||||||
salt,
|
iv,
|
||||||
verifier
|
tag,
|
||||||
});
|
salt,
|
||||||
|
verifier,
|
||||||
|
algorithm: SecretEncryptionAlgo.AES_256_GCM,
|
||||||
|
keyEncoding: SecretKeyEncoding.UTF8
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
|
||||||
await userDal.updateUserEncryptionByUserId(
|
await userDal.updateUserEncryptionByUserId(
|
||||||
userEnc.userId,
|
userEnc.userId,
|
||||||
|
|||||||
@@ -68,8 +68,11 @@ export const projectRoleServiceFactory = ({
|
|||||||
if (existingRole && existingRole.id !== roleId)
|
if (existingRole && existingRole.id !== roleId)
|
||||||
throw new BadRequestError({ name: "Update Role", message: "Duplicate role" });
|
throw new BadRequestError({ name: "Update Role", message: "Duplicate role" });
|
||||||
}
|
}
|
||||||
const [updatedRole] = await projectRoleDal.update({ id: roleId, projectId }, { ...data });
|
const [updatedRole] = await projectRoleDal.update(
|
||||||
if (!updateRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
|
{ id: roleId, projectId },
|
||||||
|
{ ...data, permissions: data.permissions ? JSON.stringify(data.permissions) : undefined }
|
||||||
|
);
|
||||||
|
if (!updatedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
|
||||||
return updatedRole;
|
return updatedRole;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ export const projectDalFactory = (db: TDbClient) => {
|
|||||||
const workspaces = await db(TableName.ProjectMembership)
|
const workspaces = await db(TableName.ProjectMembership)
|
||||||
.where({ userId })
|
.where({ userId })
|
||||||
.join(
|
.join(
|
||||||
TableName.Environment,
|
TableName.Project,
|
||||||
`${TableName.Environment}.projectId`,
|
`${TableName.ProjectMembership}.projectId`,
|
||||||
`${TableName.Project}.id`
|
`${TableName.Project}.id`
|
||||||
)
|
)
|
||||||
.join(
|
.join(
|
||||||
TableName.Project,
|
TableName.Environment,
|
||||||
`${TableName.ProjectMembership}.projectId`,
|
`${TableName.Environment}.projectId`,
|
||||||
`${TableName.Project}.id`
|
`${TableName.Project}.id`
|
||||||
)
|
)
|
||||||
.select(
|
.select(
|
||||||
@@ -57,13 +57,13 @@ export const projectDalFactory = (db: TDbClient) => {
|
|||||||
const workspaces = await db(TableName.ProjectMembership)
|
const workspaces = await db(TableName.ProjectMembership)
|
||||||
.where(`${TableName.Project}.id`, id)
|
.where(`${TableName.Project}.id`, id)
|
||||||
.join(
|
.join(
|
||||||
TableName.Environment,
|
TableName.Project,
|
||||||
`${TableName.Environment}.projectId`,
|
`${TableName.ProjectMembership}.projectId`,
|
||||||
`${TableName.Project}.id`
|
`${TableName.Project}.id`
|
||||||
)
|
)
|
||||||
.join(
|
.join(
|
||||||
TableName.Project,
|
TableName.Environment,
|
||||||
`${TableName.ProjectMembership}.projectId`,
|
`${TableName.Environment}.projectId`,
|
||||||
`${TableName.Project}.id`
|
`${TableName.Project}.id`
|
||||||
)
|
)
|
||||||
.select(
|
.select(
|
||||||
|
|||||||
@@ -50,11 +50,14 @@ export const projectServiceFactory = ({
|
|||||||
// TODO(backend-pg): licence server
|
// TODO(backend-pg): licence server
|
||||||
const newProject = projectDal.transaction(async (tx) => {
|
const newProject = projectDal.transaction(async (tx) => {
|
||||||
const project = await projectDal.create({ name: workspaceName, orgId }, tx);
|
const project = await projectDal.create({ name: workspaceName, orgId }, tx);
|
||||||
await projectMembershipDal.create({
|
await projectMembershipDal.create(
|
||||||
userId: actorId,
|
{
|
||||||
role: ProjectMembershipRole.Admin,
|
userId: actorId,
|
||||||
projectId: project.id
|
role: ProjectMembershipRole.Admin,
|
||||||
});
|
projectId: project.id
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
const envs = await projectEnvDal.insertMany(
|
const envs = await projectEnvDal.insertMany(
|
||||||
DEFAULT_PROJECT_ENVS.map((el) => ({ ...el, projectId: project.id })),
|
DEFAULT_PROJECT_ENVS.map((el) => ({ ...el, projectId: project.id })),
|
||||||
tx
|
tx
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const userDalFactory = (db: TDbClient) => {
|
|||||||
|
|
||||||
const findUserEncKeyByUserId = async (userId: string) => {
|
const findUserEncKeyByUserId = async (userId: string) => {
|
||||||
try {
|
try {
|
||||||
return await db(TableName.Users)
|
const user = await db(TableName.Users)
|
||||||
.where(`${TableName.Users}.id`, userId)
|
.where(`${TableName.Users}.id`, userId)
|
||||||
.join(
|
.join(
|
||||||
TableName.UserEncryptionKey,
|
TableName.UserEncryptionKey,
|
||||||
@@ -45,6 +45,11 @@ export const userDalFactory = (db: TDbClient) => {
|
|||||||
`${TableName.UserEncryptionKey}.userId`
|
`${TableName.UserEncryptionKey}.userId`
|
||||||
)
|
)
|
||||||
.first();
|
.first();
|
||||||
|
if (user?.id) {
|
||||||
|
// change to user id
|
||||||
|
user.id = user.userId;
|
||||||
|
}
|
||||||
|
return user;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new DatabaseError({ error, name: "Find user enc by user id" });
|
throw new DatabaseError({ error, name: "Find user enc by user id" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,123 +1,123 @@
|
|||||||
import { TRole } from "../roles/types";
|
import { TOrgRole, TProjectRole } from "../roles/types";
|
||||||
import { IdentityAuthMethod } from "./enums";
|
import { IdentityAuthMethod } from "./enums";
|
||||||
|
|
||||||
export type IdentityTrustedIp = {
|
export type IdentityTrustedIp = {
|
||||||
id: string;
|
id: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
type: "ipv4" | "ipv6";
|
type: "ipv4" | "ipv6";
|
||||||
prefix?: number;
|
prefix?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type Identity = {
|
export type Identity = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
authMethod?: IdentityAuthMethod;
|
authMethod?: IdentityAuthMethod;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IdentityMembershipOrg = {
|
export type IdentityMembershipOrg = {
|
||||||
id: string;
|
id: string;
|
||||||
identity: Identity;
|
identity: Identity;
|
||||||
organization: string;
|
organization: string;
|
||||||
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
customRole?: TRole<string>;
|
customRole?: TOrgRole;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type IdentityMembership = {
|
export type IdentityMembership = {
|
||||||
id: string;
|
id: string;
|
||||||
identity: Identity;
|
identity: Identity;
|
||||||
organization: string;
|
organization: string;
|
||||||
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
customRole?: TRole<string>;
|
customRole?: TProjectRole;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type CreateIdentityDTO = {
|
export type CreateIdentityDTO = {
|
||||||
name: string;
|
name: string;
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
role?: string;
|
role?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type UpdateIdentityDTO = {
|
export type UpdateIdentityDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
role?: string;
|
role?: string;
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type DeleteIdentityDTO = {
|
export type DeleteIdentityDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type IdentityUniversalAuth = {
|
export type IdentityUniversalAuth = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
clientId: string;
|
clientId: string;
|
||||||
clientSecretTrustedIps: IdentityTrustedIp[];
|
clientSecretTrustedIps: IdentityTrustedIp[];
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
accessTokenNumUsesLimit: number;
|
accessTokenNumUsesLimit: number;
|
||||||
accessTokenTrustedIps: IdentityTrustedIp[];
|
accessTokenTrustedIps: IdentityTrustedIp[];
|
||||||
}
|
};
|
||||||
|
|
||||||
export type AddIdentityUniversalAuthDTO = {
|
export type AddIdentityUniversalAuthDTO = {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
identityId: string;
|
identityId: string;
|
||||||
clientSecretTrustedIps: {
|
clientSecretTrustedIps: {
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
}[];
|
}[];
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
accessTokenNumUsesLimit: number;
|
accessTokenNumUsesLimit: number;
|
||||||
accessTokenTrustedIps: {
|
accessTokenTrustedIps: {
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
};
|
||||||
|
|
||||||
export type UpdateIdentityUniversalAuthDTO = {
|
export type UpdateIdentityUniversalAuthDTO = {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
identityId: string;
|
identityId: string;
|
||||||
clientSecretTrustedIps?: {
|
clientSecretTrustedIps?: {
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
}[];
|
}[];
|
||||||
accessTokenTTL?: number;
|
accessTokenTTL?: number;
|
||||||
accessTokenMaxTTL?: number;
|
accessTokenMaxTTL?: number;
|
||||||
accessTokenNumUsesLimit?: number;
|
accessTokenNumUsesLimit?: number;
|
||||||
accessTokenTrustedIps?: {
|
accessTokenTrustedIps?: {
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
};
|
||||||
|
|
||||||
export type CreateIdentityUniversalAuthClientSecretDTO = {
|
export type CreateIdentityUniversalAuthClientSecretDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
ttl?: number;
|
ttl?: number;
|
||||||
numUsesLimit?: number;
|
numUsesLimit?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type ClientSecretData = {
|
export type ClientSecretData = {
|
||||||
id: string;
|
id: string;
|
||||||
identityUniversalAuth: string;
|
identityUniversalAuth: string;
|
||||||
isClientSecretRevoked: boolean;
|
isClientSecretRevoked: boolean;
|
||||||
description: string;
|
description: string;
|
||||||
clientSecretPrefix: string;
|
clientSecretPrefix: string;
|
||||||
clientSecretNumUses: number;
|
clientSecretNumUses: number;
|
||||||
clientSecretNumUsesLimit: number;
|
clientSecretNumUsesLimit: number;
|
||||||
clientSecretTTL: number;
|
clientSecretTTL: number;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type CreateIdentityUniversalAuthClientSecretRes = {
|
export type CreateIdentityUniversalAuthClientSecretRes = {
|
||||||
clientSecret: string;
|
clientSecret: string;
|
||||||
clientSecretData: ClientSecretData;
|
clientSecretData: ClientSecretData;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type DeleteIdentityUniversalAuthClientSecretDTO = {
|
export type DeleteIdentityUniversalAuthClientSecretDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
clientSecretId: string;
|
clientSecretId: string;
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
export {
|
export {
|
||||||
useCreateOrgRole,
|
useCreateOrgRole,
|
||||||
useCreateRole,
|
useCreateProjectRole,
|
||||||
useDeleteOrgRole,
|
useDeleteOrgRole,
|
||||||
useDeleteRole,
|
useDeleteProjectRole,
|
||||||
useUpdateOrgRole,
|
useUpdateOrgRole,
|
||||||
useUpdateRole
|
useUpdateProjectRole
|
||||||
} from "./mutation";
|
} from "./mutation";
|
||||||
export {
|
export {
|
||||||
useGetOrgRoles,
|
useGetOrgRoles,
|
||||||
useGetRoles,
|
useGetProjectRoles,
|
||||||
useGetUserOrgPermissions,
|
useGetUserOrgPermissions,
|
||||||
useGetUserProjectPermissions
|
useGetUserProjectPermissions
|
||||||
} from "./queries";
|
} from "./queries";
|
||||||
|
|||||||
@@ -6,45 +6,53 @@ import { apiRequest } from "@app/config/request";
|
|||||||
import { roleQueryKeys } from "./queries";
|
import { roleQueryKeys } from "./queries";
|
||||||
import {
|
import {
|
||||||
TCreateOrgRoleDTO,
|
TCreateOrgRoleDTO,
|
||||||
TCreateRoleDTO,
|
TCreateProjectRoleDTO,
|
||||||
TDeleteOrgRoleDTO,
|
TDeleteOrgRoleDTO,
|
||||||
TDeleteRoleDTO,
|
TDeleteProjectRoleDTO,
|
||||||
TUpdateOrgRoleDTO,
|
TUpdateOrgRoleDTO,
|
||||||
TUpdateRoleDTO
|
TUpdateProjectRoleDTO
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export const useCreateRole = <T extends string | undefined>() => {
|
export const useCreateProjectRole = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (dto: TCreateRoleDTO<T>) => apiRequest.post("/api/v1/roles", dto),
|
mutationFn: ({ projectId, permissions, ...dto }: TCreateProjectRoleDTO) =>
|
||||||
onSuccess: (_, { orgId, workspaceId }) => {
|
apiRequest.post(`/api/ee/v1/workspace/${projectId}/roles`, {
|
||||||
queryClient.invalidateQueries(roleQueryKeys.getRoles({ orgId, workspaceId }));
|
...dto,
|
||||||
}
|
permissions: permissions.length ? packRules(permissions) : []
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUpdateRole = <T extends string | undefined>() => {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ id, ...dto }: TUpdateRoleDTO<T>) => apiRequest.patch(`/api/v1/roles/${id}`, dto),
|
|
||||||
onSuccess: (_, { orgId, workspaceId }) => {
|
|
||||||
queryClient.invalidateQueries(roleQueryKeys.getRoles({ orgId, workspaceId }));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useDeleteRole = () => {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ orgId, id }: TDeleteRoleDTO) =>
|
|
||||||
apiRequest.delete(`/api/v1/roles/${id}`, {
|
|
||||||
data: { orgId }
|
|
||||||
}),
|
}),
|
||||||
onSuccess: (_, { orgId, workspaceId }) => {
|
onSuccess: (_, { projectId }) => {
|
||||||
queryClient.invalidateQueries(roleQueryKeys.getRoles({ orgId, workspaceId }));
|
queryClient.invalidateQueries(roleQueryKeys.getProjectRoles(projectId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateProjectRole = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: ({ id, projectId, permissions, ...dto }: TUpdateProjectRoleDTO) =>
|
||||||
|
apiRequest.patch(`/api/ee/v1/workspace/${projectId}/roles/${id}`, {
|
||||||
|
...dto,
|
||||||
|
permissions: permissions?.length ? packRules(permissions) : []
|
||||||
|
}),
|
||||||
|
onSuccess: (_, { projectId }) => {
|
||||||
|
queryClient.invalidateQueries(roleQueryKeys.getProjectRoles(projectId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDeleteProjectRole = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: ({ projectId, id }: TDeleteProjectRoleDTO) =>
|
||||||
|
apiRequest.delete(`/api/ee/v1/workspace/${projectId}/roles/${id}`, {
|
||||||
|
data: { projectId }
|
||||||
|
}),
|
||||||
|
onSuccess: (_, { projectId }) => {
|
||||||
|
queryClient.invalidateQueries(roleQueryKeys.getProjectRoles(projectId));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -71,7 +79,7 @@ export const useUpdateOrgRole = () => {
|
|||||||
mutationFn: ({ id, orgId, permissions, ...dto }: TUpdateOrgRoleDTO) =>
|
mutationFn: ({ id, orgId, permissions, ...dto }: TUpdateOrgRoleDTO) =>
|
||||||
apiRequest.patch(`/api/ee/v1/organization/${orgId}/roles/${id}`, {
|
apiRequest.patch(`/api/ee/v1/organization/${orgId}/roles/${id}`, {
|
||||||
...dto,
|
...dto,
|
||||||
permissions: permissions?.length ? packRules(permissions) : undefined
|
permissions: permissions?.length ? packRules(permissions) : []
|
||||||
}),
|
}),
|
||||||
onSuccess: (_, { orgId }) => {
|
onSuccess: (_, { orgId }) => {
|
||||||
queryClient.invalidateQueries(roleQueryKeys.getOrgRoles(orgId));
|
queryClient.invalidateQueries(roleQueryKeys.getOrgRoles(orgId));
|
||||||
|
|||||||
@@ -10,12 +10,11 @@ import { ProjectPermissionSet } from "@app/context/ProjectPermissionContext/type
|
|||||||
|
|
||||||
import { OrgUser } from "../users/types";
|
import { OrgUser } from "../users/types";
|
||||||
import {
|
import {
|
||||||
TGetRolesDTO,
|
|
||||||
TGetUserOrgPermissionsDTO,
|
TGetUserOrgPermissionsDTO,
|
||||||
TGetUserProjectPermissionDTO,
|
TGetUserProjectPermissionDTO,
|
||||||
TOrgRole,
|
TOrgRole,
|
||||||
TPermission,
|
TPermission,
|
||||||
TRole
|
TProjectRole
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const $glob: FieldInstruction<string> = {
|
const $glob: FieldInstruction<string> = {
|
||||||
@@ -37,7 +36,7 @@ const glob: JsInterpreter<FieldCondition<string>> = (node, object, context) => {
|
|||||||
const conditionsMatcher = buildMongoQueryMatcher({ $glob }, { glob });
|
const conditionsMatcher = buildMongoQueryMatcher({ $glob }, { glob });
|
||||||
|
|
||||||
export const roleQueryKeys = {
|
export const roleQueryKeys = {
|
||||||
getRoles: ({ orgId, workspaceId }: TGetRolesDTO) => ["roles", { orgId, workspaceId }] as const,
|
getProjectRoles: (projectId: string) => ["roles", { projectId }] as const,
|
||||||
getOrgRoles: (orgId: string) => ["org-roles", { orgId }] as const,
|
getOrgRoles: (orgId: string) => ["org-roles", { orgId }] as const,
|
||||||
getUserOrgPermissions: ({ orgId }: TGetUserOrgPermissionsDTO) =>
|
getUserOrgPermissions: ({ orgId }: TGetUserOrgPermissionsDTO) =>
|
||||||
["user-permissions", { orgId }] as const,
|
["user-permissions", { orgId }] as const,
|
||||||
@@ -45,25 +44,21 @@ export const roleQueryKeys = {
|
|||||||
["user-project-permissions", { workspaceId }] as const
|
["user-project-permissions", { workspaceId }] as const
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRoles = async ({ orgId, workspaceId }: TGetRolesDTO) => {
|
const getProjectRoles = async (projectId: string) => {
|
||||||
const { data } = await apiRequest.get<{ data: { roles: TRole<typeof workspaceId>[] } }>(
|
const { data } = await apiRequest.get<{
|
||||||
"/api/v1/roles",
|
data: { roles: Array<Omit<TProjectRole, "permissions"> & { permissions: unknown }> };
|
||||||
{
|
}>(`/api/ee/v1/workspace/${projectId}/roles`);
|
||||||
params: {
|
return data.data.roles.map(({ permissions, ...el }) => ({
|
||||||
workspaceId,
|
...el,
|
||||||
orgId
|
permissions: unpackRules(permissions as PackRule<TPermission>[])
|
||||||
}
|
}));
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return data.data.roles;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetRoles = ({ orgId, workspaceId }: TGetRolesDTO) =>
|
export const useGetProjectRoles = (projectId: string) =>
|
||||||
useQuery({
|
useQuery({
|
||||||
queryKey: roleQueryKeys.getRoles({ orgId, workspaceId }),
|
queryKey: roleQueryKeys.getProjectRoles(projectId),
|
||||||
queryFn: () => getRoles({ orgId, workspaceId }),
|
queryFn: () => getProjectRoles(projectId),
|
||||||
enabled: Boolean(orgId)
|
enabled: Boolean(projectId)
|
||||||
});
|
});
|
||||||
|
|
||||||
const getOrgRoles = async (orgId: string) => {
|
const getOrgRoles = async (orgId: string) => {
|
||||||
@@ -109,7 +104,7 @@ export const useGetUserOrgPermissions = ({ orgId }: TGetUserOrgPermissionsDTO) =
|
|||||||
const getUserProjectPermissions = async ({ workspaceId }: TGetUserProjectPermissionDTO) => {
|
const getUserProjectPermissions = async ({ workspaceId }: TGetUserProjectPermissionDTO) => {
|
||||||
const { data } = await apiRequest.get<{
|
const { data } = await apiRequest.get<{
|
||||||
data: { permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[] };
|
data: { permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[] };
|
||||||
}>(`/api/v1/roles/workspace/${workspaceId}/permissions`, {});
|
}>(`/api/ee/v1/workspace/${workspaceId}/permissions`, {});
|
||||||
|
|
||||||
return data.data.permissions;
|
return data.data.permissions;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
export type TGetRolesDTO = {
|
export type TGetProjectRolesDTO = {
|
||||||
orgId: string;
|
|
||||||
workspaceId?: string;
|
workspaceId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// @depreciated
|
export type TProjectRole = {
|
||||||
export type TRole<T extends string | undefined> = {
|
|
||||||
id: string;
|
|
||||||
organization: string;
|
|
||||||
workspace: T;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
slug: string;
|
slug: string;
|
||||||
permissions: T extends string ? TProjectPermission[] : TPermission[];
|
name: string;
|
||||||
|
projectId: string;
|
||||||
|
id: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
description?: string;
|
||||||
|
permissions: TPermission[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TOrgRole = {
|
export type TOrgRole = {
|
||||||
@@ -36,28 +33,7 @@ export type TPermission = {
|
|||||||
export type TProjectPermission = {
|
export type TProjectPermission = {
|
||||||
conditions?: Record<string, any>;
|
conditions?: Record<string, any>;
|
||||||
action: string;
|
action: string;
|
||||||
subject: string;
|
subject: [string];
|
||||||
};
|
|
||||||
|
|
||||||
export type TCreateRoleDTO<T extends string | undefined> = {
|
|
||||||
orgId: string;
|
|
||||||
workspaceId?: T;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
slug: string;
|
|
||||||
permissions: T extends string ? TProjectPermission[] : TPermission[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TUpdateRoleDTO<T extends string | undefined> = {
|
|
||||||
orgId: string;
|
|
||||||
id: string;
|
|
||||||
workspaceId?: T;
|
|
||||||
} & Partial<Omit<TCreateRoleDTO<T>, "orgId" | "workspaceId">>;
|
|
||||||
|
|
||||||
export type TDeleteRoleDTO = {
|
|
||||||
orgId: string;
|
|
||||||
id: string;
|
|
||||||
workspaceId?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TGetUserOrgPermissionsDTO = {
|
export type TGetUserOrgPermissionsDTO = {
|
||||||
@@ -85,3 +61,21 @@ export type TDeleteOrgRoleDTO = {
|
|||||||
orgId: string;
|
orgId: string;
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TCreateProjectRoleDTO = {
|
||||||
|
projectId: string;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
slug: string;
|
||||||
|
permissions: TPermission[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TUpdateProjectRoleDTO = {
|
||||||
|
projectId: string;
|
||||||
|
id: string;
|
||||||
|
} & Partial<Omit<TCreateOrgRoleDTO, "orgId">>;
|
||||||
|
|
||||||
|
export type TDeleteProjectRoleDTO = {
|
||||||
|
projectId: string;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export const useToggleAutoCapitalization = () => {
|
|||||||
|
|
||||||
return useMutation<{}, {}, ToggleAutoCapitalizationDTO>({
|
return useMutation<{}, {}, ToggleAutoCapitalizationDTO>({
|
||||||
mutationFn: ({ workspaceID, state }) =>
|
mutationFn: ({ workspaceID, state }) =>
|
||||||
apiRequest.patch(`/api/v2/workspace/${workspaceID}/auto-capitalization`, {
|
apiRequest.post(`/api/v1/workspace/${workspaceID}/auto-capitalization`, {
|
||||||
autoCapitalization: state
|
autoCapitalization: state
|
||||||
}),
|
}),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@@ -245,7 +245,7 @@ export const useReorderWsEnvironment = () => {
|
|||||||
otherEnvironmentSlug,
|
otherEnvironmentSlug,
|
||||||
otherEnvironmentName
|
otherEnvironmentName
|
||||||
}) => {
|
}) => {
|
||||||
return apiRequest.patch(`/api/v2/workspace/${workspaceId}/environments`, {
|
return apiRequest.patch(`/api/v1/workspace/${workspaceId}/environments`, {
|
||||||
environmentSlug,
|
environmentSlug,
|
||||||
environmentName,
|
environmentName,
|
||||||
otherEnvironmentSlug,
|
otherEnvironmentSlug,
|
||||||
@@ -263,7 +263,7 @@ export const useUpdateWsEnvironment = () => {
|
|||||||
|
|
||||||
return useMutation<{}, {}, UpdateEnvironmentDTO>({
|
return useMutation<{}, {}, UpdateEnvironmentDTO>({
|
||||||
mutationFn: ({ workspaceId, id, name, slug }) => {
|
mutationFn: ({ workspaceId, id, name, slug }) => {
|
||||||
return apiRequest.put(`/api/v2/workspace/${workspaceId}/environments/${id}`, {
|
return apiRequest.patch(`/api/v1/workspace/${workspaceId}/environments/${id}`, {
|
||||||
name,
|
name,
|
||||||
slug
|
slug
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ export type Workspace = {
|
|||||||
__v: number;
|
__v: number;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
organization: string;
|
orgId: string;
|
||||||
autoCapitalization: boolean;
|
autoCapitalization: boolean;
|
||||||
environments: WorkspaceEnv[];
|
environments: WorkspaceEnv[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
/* 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 */
|
||||||
// @ts-nocheck
|
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
@@ -167,7 +166,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeOrg = async (orgId) => {
|
const changeOrg = async (orgId: string) => {
|
||||||
localStorage.setItem("orgData.id", orgId);
|
localStorage.setItem("orgData.id", orgId);
|
||||||
router.push(`/org/${orgId}/overview`);
|
router.push(`/org/${orgId}/overview`);
|
||||||
};
|
};
|
||||||
@@ -178,15 +177,15 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Put a user in an org if they're not in one yet
|
// Put a user in an org if they're not in one yet
|
||||||
const putUserInOrg = async () => {
|
const putUserInOrg = async () => {
|
||||||
if (tempLocalStorage("orgData.id") === "") {
|
if (tempLocalStorage("orgData.id") === "" && orgs?.[0]?.id) {
|
||||||
localStorage.setItem("orgData.id", orgs[0]?.id);
|
localStorage.setItem("orgData.id", orgs?.[0]?.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
currentOrg &&
|
currentOrg &&
|
||||||
((workspaces?.length === 0 && router.asPath.includes("project")) ||
|
((workspaces?.length === 0 && router.asPath.includes("project")) ||
|
||||||
router.asPath.includes("/project/undefined") ||
|
router.asPath.includes("/project/undefined") ||
|
||||||
(!orgs?.map((org) => org.id)?.includes(router.query.id) &&
|
(!orgs?.map((org) => org.id)?.includes(router.query.id as string) &&
|
||||||
!router.asPath.includes("project") &&
|
!router.asPath.includes("project") &&
|
||||||
!router.asPath.includes("personal") &&
|
!router.asPath.includes("personal") &&
|
||||||
!router.asPath.includes("integration")))
|
!router.asPath.includes("integration")))
|
||||||
@@ -320,7 +319,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
size="xs"
|
size="xs"
|
||||||
className="flex w-full items-center justify-start p-0 font-normal"
|
className="flex w-full items-center justify-start p-0 font-normal"
|
||||||
leftIcon={
|
leftIcon={
|
||||||
currentOrg.id === org.id && (
|
currentOrg?.id === org.id && (
|
||||||
<FontAwesomeIcon icon={faCheck} className="mr-3 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="mr-3 text-primary" />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -433,7 +432,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
>
|
>
|
||||||
<div className="no-scrollbar::-webkit-scrollbar h-full no-scrollbar">
|
<div className="no-scrollbar::-webkit-scrollbar h-full no-scrollbar">
|
||||||
{workspaces
|
{workspaces
|
||||||
.filter((ws) => ws.organization === currentOrg?.id)
|
.filter((ws) => ws.orgId === currentOrg?.id)
|
||||||
.map(({ id, name }) => (
|
.map(({ id, name }) => (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={`ws-layout-list-${id}`}
|
key={`ws-layout-list-${id}`}
|
||||||
@@ -702,7 +701,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start" className="p-1">
|
<DropdownMenuContent align="start" className="p-1">
|
||||||
{supportOptions.map(([icon, text, url]) => (
|
{supportOptions.map(([icon, text, url]) => (
|
||||||
<DropdownMenuItem key={url}>
|
<DropdownMenuItem key={url as string}>
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
|
|||||||
@@ -476,9 +476,8 @@ const OrganizationPage = withPermission(
|
|||||||
|
|
||||||
const { workspaces, isLoading: isWorkspaceLoading } = useWorkspace();
|
const { workspaces, isLoading: isWorkspaceLoading } = useWorkspace();
|
||||||
const orgWorkspaces =
|
const orgWorkspaces =
|
||||||
workspaces?.filter(
|
workspaces?.filter((workspace) => workspace.orgId === localStorage.getItem("orgData.id")) ||
|
||||||
(workspace) => workspace.organization === localStorage.getItem("orgData.id")
|
[];
|
||||||
) || [];
|
|
||||||
const currentOrg = String(router.query.id);
|
const currentOrg = String(router.query.id);
|
||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
const addWsUser = useAddUserToWs();
|
const addWsUser = useAddUserToWs();
|
||||||
|
|||||||
+2
-4
@@ -14,7 +14,7 @@ import {
|
|||||||
SelectItem
|
SelectItem
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { useOrganization } from "@app/context";
|
import { useOrganization } from "@app/context";
|
||||||
import { useCreateIdentity, useGetRoles, useUpdateIdentity } from "@app/hooks/api";
|
import { useCreateIdentity, useGetOrgRoles, useUpdateIdentity } from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
@@ -46,9 +46,7 @@ export const IdentityModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: Pro
|
|||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
const orgId = currentOrg?.id || "";
|
const orgId = currentOrg?.id || "";
|
||||||
|
|
||||||
const { data: roles } = useGetRoles({
|
const { data: roles } = useGetOrgRoles(orgId);
|
||||||
orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
const { mutateAsync: createMutateAsync } = useCreateIdentity();
|
const { mutateAsync: createMutateAsync } = useCreateIdentity();
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentity();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentity();
|
||||||
|
|||||||
+2
-4
@@ -19,7 +19,7 @@ import {
|
|||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||||
import { useGetIdentityMembershipOrgs, useGetRoles, useUpdateIdentity } from "@app/hooks/api";
|
import { useGetIdentityMembershipOrgs, useGetOrgRoles, useUpdateIdentity } from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod, identityAuthToNameMap } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod, identityAuthToNameMap } from "@app/hooks/api/identities";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
@@ -51,9 +51,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentity();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentity();
|
||||||
const { data, isLoading } = useGetIdentityMembershipOrgs(orgId);
|
const { data, isLoading } = useGetIdentityMembershipOrgs(orgId);
|
||||||
|
|
||||||
const { data: roles } = useGetRoles({
|
const { data: roles } = useGetOrgRoles(orgId);
|
||||||
orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleChangeRole = async ({ identityId, role }: { identityId: string; role: string }) => {
|
const handleChangeRole = async ({ identityId, role }: { identityId: string; role: string }) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,6 @@ import {
|
|||||||
useFetchServerStatus,
|
useFetchServerStatus,
|
||||||
useGetOrgRoles,
|
useGetOrgRoles,
|
||||||
useGetOrgUsers,
|
useGetOrgUsers,
|
||||||
useGetRoles,
|
|
||||||
useUpdateOrgUserRole
|
useUpdateOrgUserRole
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -58,6 +57,7 @@ export const OrgMembersTable = ({ handlePopUpOpen, setCompleteInviteLink }: Prop
|
|||||||
const orgId = currentOrg?.id || "";
|
const orgId = currentOrg?.id || "";
|
||||||
|
|
||||||
const { data: roles, isLoading: isRolesLoading } = useGetOrgRoles(orgId);
|
const { data: roles, isLoading: isRolesLoading } = useGetOrgRoles(orgId);
|
||||||
|
console.log(roles);
|
||||||
|
|
||||||
const [searchMemberFilter, setSearchMemberFilter] = useState("");
|
const [searchMemberFilter, setSearchMemberFilter] = useState("");
|
||||||
|
|
||||||
|
|||||||
@@ -61,11 +61,11 @@ import {
|
|||||||
useUpdateOrgUserRole,
|
useUpdateOrgUserRole,
|
||||||
useUploadWsKey
|
useUploadWsKey
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { TRole } from "@app/hooks/api/roles/types";
|
import { TProjectRole } from "@app/hooks/api/roles/types";
|
||||||
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
roles?: TRole<undefined>[];
|
roles?: TProjectRole[];
|
||||||
isRolesLoading?: boolean;
|
isRolesLoading?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -10,7 +10,7 @@ import { useOrganization, useWorkspace } from "@app/context";
|
|||||||
import {
|
import {
|
||||||
useAddIdentityToWorkspace,
|
useAddIdentityToWorkspace,
|
||||||
useGetIdentityMembershipOrgs,
|
useGetIdentityMembershipOrgs,
|
||||||
useGetRoles,
|
useGetProjectRoles,
|
||||||
useGetWorkspaceIdentityMemberships
|
useGetWorkspaceIdentityMemberships
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -40,10 +40,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
const { data: identityMembershipOrgs } = useGetIdentityMembershipOrgs(orgId);
|
const { data: identityMembershipOrgs } = useGetIdentityMembershipOrgs(orgId);
|
||||||
const { data: identityMemberships } = useGetWorkspaceIdentityMemberships(workspaceId);
|
const { data: identityMemberships } = useGetWorkspaceIdentityMemberships(workspaceId);
|
||||||
|
|
||||||
const { data: roles } = useGetRoles({
|
const { data: roles } = useGetProjectRoles(workspaceId);
|
||||||
orgId,
|
|
||||||
workspaceId
|
|
||||||
});
|
|
||||||
|
|
||||||
const { mutateAsync: addIdentityToWorkspaceMutateAsync } = useAddIdentityToWorkspace();
|
const { mutateAsync: addIdentityToWorkspaceMutateAsync } = useAddIdentityToWorkspace();
|
||||||
|
|
||||||
@@ -171,7 +168,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
All identities in your organization have already been added to this project.
|
All identities in your organization have already been added to this project.
|
||||||
</div>
|
</div>
|
||||||
<Link href={`/org/${currentWorkspace?.organization}/members`}>
|
<Link href={`/org/${currentWorkspace?.orgId}/members`}>
|
||||||
<Button variant="outline_bg">Create a new identity</Button>
|
<Button variant="outline_bg">Create a new identity</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+3
-13
@@ -18,14 +18,9 @@ import {
|
|||||||
THead,
|
THead,
|
||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
|
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
import {
|
import {
|
||||||
ProjectPermissionActions,
|
useGetProjectRoles,
|
||||||
ProjectPermissionSub,
|
|
||||||
useOrganization,
|
|
||||||
useWorkspace
|
|
||||||
} from "@app/context";
|
|
||||||
import {
|
|
||||||
useGetRoles,
|
|
||||||
useGetWorkspaceIdentityMemberships,
|
useGetWorkspaceIdentityMemberships,
|
||||||
useUpdateIdentityWorkspaceRole
|
useUpdateIdentityWorkspaceRole
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
@@ -43,16 +38,11 @@ type Props = {
|
|||||||
|
|
||||||
export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
const { currentOrg } = useOrganization();
|
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const orgId = currentOrg?.id || "";
|
|
||||||
const workspaceId = currentWorkspace?.id || "";
|
const workspaceId = currentWorkspace?.id || "";
|
||||||
const { data, isLoading } = useGetWorkspaceIdentityMemberships(currentWorkspace?.id || "");
|
const { data, isLoading } = useGetWorkspaceIdentityMemberships(currentWorkspace?.id || "");
|
||||||
|
|
||||||
const { data: roles } = useGetRoles({
|
const { data: roles } = useGetProjectRoles(workspaceId);
|
||||||
orgId,
|
|
||||||
workspaceId
|
|
||||||
});
|
|
||||||
|
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentityWorkspaceRole();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentityWorkspaceRole();
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import {
|
|||||||
useAddUserToWs,
|
useAddUserToWs,
|
||||||
useDeleteUserFromWorkspace,
|
useDeleteUserFromWorkspace,
|
||||||
useGetOrgUsers,
|
useGetOrgUsers,
|
||||||
useGetRoles,
|
useGetProjectRoles,
|
||||||
useGetUserWsKey,
|
useGetUserWsKey,
|
||||||
useGetWorkspaceUsers,
|
useGetWorkspaceUsers,
|
||||||
useUpdateUserWorkspaceRole,
|
useUpdateUserWorkspaceRole,
|
||||||
@@ -73,10 +73,7 @@ export const MemberListTab = () => {
|
|||||||
const orgId = currentOrg?.id || "";
|
const orgId = currentOrg?.id || "";
|
||||||
const workspaceId = currentWorkspace?.id || "";
|
const workspaceId = currentWorkspace?.id || "";
|
||||||
|
|
||||||
const { data: roles, isLoading: isRolesLoading } = useGetRoles({
|
const { data: roles, isLoading: isRolesLoading } = useGetProjectRoles(workspaceId);
|
||||||
orgId,
|
|
||||||
workspaceId
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: wsKey } = useGetUserWsKey(workspaceId);
|
const { data: wsKey } = useGetUserWsKey(workspaceId);
|
||||||
const { data: members, isLoading: isMembersLoading } = useGetWorkspaceUsers(workspaceId);
|
const { data: members, isLoading: isMembersLoading } = useGetWorkspaceUsers(workspaceId);
|
||||||
@@ -433,7 +430,7 @@ export const MemberListTab = () => {
|
|||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col space-y-4">
|
<div className="flex flex-col space-y-4">
|
||||||
<div>All the users in your organization are already invited.</div>
|
<div>All the users in your organization are already invited.</div>
|
||||||
<Link href={`/org/${currentWorkspace?.organization}/members`}>
|
<Link href={`/org/${currentWorkspace?.orgId}/members`}>
|
||||||
<Button variant="outline_bg">Add users to organization</Button>
|
<Button variant="outline_bg">Add users to organization</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@ import { motion } from "framer-motion";
|
|||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
||||||
import { withProjectPermission } from "@app/hoc";
|
import { withProjectPermission } from "@app/hoc";
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import { TRole } from "@app/hooks/api/roles/types";
|
import { TProjectRole } from "@app/hooks/api/roles/types";
|
||||||
|
|
||||||
import { ProjectRoleList } from "./components/ProjectRoleList";
|
import { ProjectRoleList } from "./components/ProjectRoleList";
|
||||||
import { ProjectRoleModifySection } from "./components/ProjectRoleModifySection";
|
import { ProjectRoleModifySection } from "./components/ProjectRoleModifySection";
|
||||||
@@ -21,7 +21,7 @@ export const ProjectRoleListTab = withProjectPermission(
|
|||||||
exit={{ opacity: 0, translateX: 30 }}
|
exit={{ opacity: 0, translateX: 30 }}
|
||||||
>
|
>
|
||||||
<ProjectRoleModifySection
|
<ProjectRoleModifySection
|
||||||
role={popUp.editRole.data as TRole<string>}
|
role={popUp.editRole.data as TProjectRole}
|
||||||
onGoBack={() => handlePopUpClose("editRole")}
|
onGoBack={() => handlePopUpClose("editRole")}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
+12
-22
@@ -18,42 +18,32 @@ import {
|
|||||||
THead,
|
THead,
|
||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import {
|
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
ProjectPermissionActions,
|
|
||||||
ProjectPermissionSub,
|
|
||||||
useOrganization,
|
|
||||||
useWorkspace
|
|
||||||
} from "@app/context";
|
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import { useDeleteRole, useGetRoles } from "@app/hooks/api";
|
import { useDeleteProjectRole, useGetProjectRoles } from "@app/hooks/api";
|
||||||
import { TRole } from "@app/hooks/api/roles/types";
|
import { TProjectRole } from "@app/hooks/api/roles/types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSelectRole: (role?: TRole<string>) => void;
|
onSelectRole: (role?: TProjectRole) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
||||||
const [searchRoles, setSearchRoles] = useState("");
|
const [searchRoles, setSearchRoles] = useState("");
|
||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp(["deleteRole"] as const);
|
const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp(["deleteRole"] as const);
|
||||||
const { currentOrg } = useOrganization();
|
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const orgId = currentOrg?.id || "";
|
|
||||||
const workspaceId = currentWorkspace?.id || "";
|
const workspaceId = currentWorkspace?.id || "";
|
||||||
|
|
||||||
const { data: roles, isLoading: isRolesLoading } = useGetRoles({
|
const { data: roles, isLoading: isRolesLoading } = useGetProjectRoles(workspaceId);
|
||||||
orgId,
|
console.log(roles);
|
||||||
workspaceId
|
|
||||||
});
|
|
||||||
|
|
||||||
const { mutateAsync: deleteRole } = useDeleteRole();
|
const { mutateAsync: deleteRole } = useDeleteProjectRole();
|
||||||
|
|
||||||
const handleRoleDelete = async () => {
|
const handleRoleDelete = async () => {
|
||||||
const { id } = popUp?.deleteRole?.data as TRole<string>;
|
const { id } = popUp?.deleteRole?.data as TProjectRole;
|
||||||
try {
|
try {
|
||||||
await deleteRole({
|
await deleteRole({
|
||||||
orgId,
|
projectId: workspaceId,
|
||||||
workspaceId,
|
|
||||||
id
|
id
|
||||||
});
|
});
|
||||||
createNotification({ type: "success", text: "Successfully removed the role" });
|
createNotification({ type: "success", text: "Successfully removed the role" });
|
||||||
@@ -99,7 +89,7 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
|||||||
</THead>
|
</THead>
|
||||||
<TBody>
|
<TBody>
|
||||||
{isRolesLoading && <TableSkeleton columns={4} innerKey="org-roles" />}
|
{isRolesLoading && <TableSkeleton columns={4} innerKey="org-roles" />}
|
||||||
{(roles as TRole<string>[])?.map((role) => {
|
{(roles as TProjectRole[])?.map((role) => {
|
||||||
const { id, name, slug } = role;
|
const { id, name, slug } = role;
|
||||||
const isNonMutatable = ["admin", "member", "viewer", "no-access"].includes(slug);
|
const isNonMutatable = ["admin", "member", "viewer", "no-access"].includes(slug);
|
||||||
|
|
||||||
@@ -157,9 +147,9 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
|||||||
<DeleteActionModal
|
<DeleteActionModal
|
||||||
isOpen={popUp.deleteRole.isOpen}
|
isOpen={popUp.deleteRole.isOpen}
|
||||||
title={`Are you sure want to delete ${
|
title={`Are you sure want to delete ${
|
||||||
(popUp?.deleteRole?.data as TRole<string>)?.name || " "
|
(popUp?.deleteRole?.data as TProjectRole)?.name || " "
|
||||||
} role?`}
|
} role?`}
|
||||||
deleteKey={(popUp?.deleteRole?.data as TRole<string>)?.slug || ""}
|
deleteKey={(popUp?.deleteRole?.data as TProjectRole)?.slug || ""}
|
||||||
onClose={() => handlePopUpClose("deleteRole")}
|
onClose={() => handlePopUpClose("deleteRole")}
|
||||||
onDeleteApproved={handleRoleDelete}
|
onDeleteApproved={handleRoleDelete}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+8
-12
@@ -20,9 +20,9 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
|||||||
|
|
||||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||||
import { Button, FormControl, Input } from "@app/components/v2";
|
import { Button, FormControl, Input } from "@app/components/v2";
|
||||||
import { ProjectPermissionSub, useOrganization, useWorkspace } from "@app/context";
|
import { ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
import { useCreateRole, useUpdateRole } from "@app/hooks/api";
|
import { useCreateProjectRole, useUpdateProjectRole } from "@app/hooks/api";
|
||||||
import { TRole } from "@app/hooks/api/roles/types";
|
import { TProjectRole } from "@app/hooks/api/roles/types";
|
||||||
|
|
||||||
import { MultiEnvProjectPermission } from "./MultiEnvProjectPermission";
|
import { MultiEnvProjectPermission } from "./MultiEnvProjectPermission";
|
||||||
import {
|
import {
|
||||||
@@ -111,7 +111,7 @@ const SINGLE_PERMISSION_LIST = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
role?: TRole<string>;
|
role?: TProjectRole;
|
||||||
onGoBack: VoidFunction;
|
onGoBack: VoidFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -120,8 +120,6 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
|||||||
const isNewRole = !role?.slug;
|
const isNewRole = !role?.slug;
|
||||||
|
|
||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
const { currentOrg } = useOrganization();
|
|
||||||
const orgId = currentOrg?.id || "";
|
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const workspaceId = currentWorkspace?.id || "";
|
const workspaceId = currentWorkspace?.id || "";
|
||||||
|
|
||||||
@@ -135,17 +133,16 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
|||||||
defaultValues: role ? { ...role, permissions: rolePermission2Form(role.permissions) } : {},
|
defaultValues: role ? { ...role, permissions: rolePermission2Form(role.permissions) } : {},
|
||||||
resolver: zodResolver(formSchema)
|
resolver: zodResolver(formSchema)
|
||||||
});
|
});
|
||||||
const { mutateAsync: createRole } = useCreateRole();
|
const { mutateAsync: createRole } = useCreateProjectRole();
|
||||||
const { mutateAsync: updateRole } = useUpdateRole();
|
const { mutateAsync: updateRole } = useUpdateProjectRole();
|
||||||
|
|
||||||
const handleRoleUpdate = async (el: TFormSchema) => {
|
const handleRoleUpdate = async (el: TFormSchema) => {
|
||||||
if (!role?.id) return;
|
if (!role?.id) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateRole({
|
await updateRole({
|
||||||
orgId,
|
|
||||||
id: role?.id,
|
id: role?.id,
|
||||||
workspaceId,
|
projectId: workspaceId,
|
||||||
...el,
|
...el,
|
||||||
permissions: formRolePermission2API(el.permissions)
|
permissions: formRolePermission2API(el.permissions)
|
||||||
});
|
});
|
||||||
@@ -165,8 +162,7 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await createRole({
|
await createRole({
|
||||||
orgId,
|
projectId: workspaceId,
|
||||||
workspaceId,
|
|
||||||
...el,
|
...el,
|
||||||
permissions: formRolePermission2API(el.permissions)
|
permissions: formRolePermission2API(el.permissions)
|
||||||
});
|
});
|
||||||
|
|||||||
+5
-2
@@ -33,7 +33,7 @@ export const formSchema = z.object({
|
|||||||
.object({
|
.object({
|
||||||
secrets: z.record(multiEnvPermissionSchema).optional(),
|
secrets: z.record(multiEnvPermissionSchema).optional(),
|
||||||
member: generalPermissionSchema,
|
member: generalPermissionSchema,
|
||||||
"identity": generalPermissionSchema,
|
identity: generalPermissionSchema,
|
||||||
role: generalPermissionSchema,
|
role: generalPermissionSchema,
|
||||||
integrations: generalPermissionSchema,
|
integrations: generalPermissionSchema,
|
||||||
webhooks: generalPermissionSchema,
|
webhooks: generalPermissionSchema,
|
||||||
@@ -90,7 +90,10 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
|
|||||||
const formVal: Record<string, any> = {};
|
const formVal: Record<string, any> = {};
|
||||||
|
|
||||||
permissions.forEach((permission) => {
|
permissions.forEach((permission) => {
|
||||||
const { subject, action } = permission;
|
const {
|
||||||
|
subject: [subject],
|
||||||
|
action
|
||||||
|
} = permission;
|
||||||
if (!formVal?.[subject]) formVal[subject] = {};
|
if (!formVal?.[subject]) formVal[subject] = {};
|
||||||
|
|
||||||
if (subject === "secrets") {
|
if (subject === "secrets") {
|
||||||
|
|||||||
+1
-1
@@ -93,7 +93,7 @@ export const EnvironmentTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
{!isLoading &&
|
{!isLoading &&
|
||||||
currentWorkspace &&
|
currentWorkspace &&
|
||||||
currentWorkspace.environments.map(({ name, slug, id }, pos) => (
|
currentWorkspace.environments.map(({ name, slug, id }, pos) => (
|
||||||
<Tr key={name}>
|
<Tr key={id}>
|
||||||
<Td>{name}</Td>
|
<Td>{name}</Td>
|
||||||
<Td>{slug}</Td>
|
<Td>{slug}</Td>
|
||||||
<Td className="flex items-center justify-end">
|
<Td className="flex items-center justify-end">
|
||||||
|
|||||||
+9
-8
@@ -15,8 +15,8 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const schema = yup.object({
|
const schema = yup.object({
|
||||||
environmentName: yup.string().label("Environment Name").required(),
|
name: yup.string().label("Environment Name").required(),
|
||||||
environmentSlug: yup.string().label("Environment Slug").required()
|
slug: yup.string().label("Environment Slug").required()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FormData = yup.InferType<typeof schema>;
|
export type FormData = yup.InferType<typeof schema>;
|
||||||
@@ -26,19 +26,20 @@ export const UpdateEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpTog
|
|||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { mutateAsync, isLoading } = useUpdateWsEnvironment();
|
const { mutateAsync, isLoading } = useUpdateWsEnvironment();
|
||||||
const { control, handleSubmit, reset } = useForm<FormData>({
|
const { control, handleSubmit, reset } = useForm<FormData>({
|
||||||
resolver: yupResolver(schema)
|
resolver: yupResolver(schema),
|
||||||
|
values: popUp.updateEnv.data as FormData
|
||||||
});
|
});
|
||||||
|
|
||||||
const oldEnvId = (popUp?.updateEnv?.data as { id: string })?.id;
|
const oldEnvId = (popUp?.updateEnv?.data as { id: string })?.id;
|
||||||
|
|
||||||
const onFormSubmit = async ({ environmentName, environmentSlug }: FormData) => {
|
const onFormSubmit = async ({ name, slug }: FormData) => {
|
||||||
try {
|
try {
|
||||||
if (!currentWorkspace?.id) return;
|
if (!currentWorkspace?.id) return;
|
||||||
|
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
workspaceId: currentWorkspace.id,
|
workspaceId: currentWorkspace.id,
|
||||||
name: environmentName,
|
name,
|
||||||
slug: environmentSlug,
|
slug,
|
||||||
id: oldEnvId
|
id: oldEnvId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ export const UpdateEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpTog
|
|||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
defaultValue=""
|
defaultValue=""
|
||||||
name="environmentName"
|
name="name"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Environment Name"
|
label="Environment Name"
|
||||||
@@ -84,7 +85,7 @@ export const UpdateEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpTog
|
|||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
defaultValue=""
|
defaultValue=""
|
||||||
name="environmentSlug"
|
name="slug"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Environment Slug"
|
label="Environment Slug"
|
||||||
|
|||||||
Reference in New Issue
Block a user