mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 00:29:34 +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) {
|
||||
await knex.schema.createTable(TableName.BackupPrivateKey, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("encryptedPrivateKey").notNullable();
|
||||
t.string("iv").notNullable();
|
||||
t.string("tag").notNullable();
|
||||
t.text("encryptedPrivateKey").notNullable();
|
||||
t.text("iv").notNullable();
|
||||
t.text("tag").notNullable();
|
||||
t.string("algorithm").notNullable();
|
||||
t.string("keyEncoding").notNullable();
|
||||
t.string("salt").notNullable();
|
||||
t.string("verifier").notNullable();
|
||||
t.text("salt").notNullable();
|
||||
t.text("verifier").notNullable();
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId").notNullable().unique();
|
||||
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);
|
||||
});
|
||||
}
|
||||
// environments
|
||||
await createOnUpdateTrigger(knex, TableName.Project);
|
||||
// environments
|
||||
if (!(await knex.schema.hasTable(TableName.Environment))) {
|
||||
await knex.schema.createTable(TableName.Environment, (t) => {
|
||||
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> {
|
||||
await knex.schema.dropTableIfExists(TableName.Environment);
|
||||
await knex.schema.dropTableIfExists(TableName.ProjectKeys);
|
||||
await knex.schema.dropTableIfExists(TableName.Project);
|
||||
await dropOnUpdateTrigger(knex, TableName.Project);
|
||||
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
|
||||
t.timestamps(true, true, true);
|
||||
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: {
|
||||
200: z.object({
|
||||
membership: ProjectMembershipsSchema,
|
||||
permissions: z.any().array()
|
||||
data: z.object({
|
||||
membership: ProjectMembershipsSchema,
|
||||
permissions: z.any().array()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -143,7 +145,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
||||
req.auth.userId,
|
||||
req.params.projectId
|
||||
);
|
||||
return { permissions, membership };
|
||||
return { data: { permissions, membership } };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -11,18 +11,22 @@ export const mergeOneToManyRelation = <
|
||||
childMapper: (arg: T) => C,
|
||||
childKey: Ck
|
||||
) => {
|
||||
const recordFirstVisitIndex: Record<string, number> = {};
|
||||
let prevPkIndex = -1;
|
||||
let prevPkId: null | string = null;
|
||||
|
||||
const groupedRecord: (P & Record<Ck, C[]>)[] = [];
|
||||
for (let i = 0; i < data.length; i += 1) {
|
||||
const pk = data[i][key];
|
||||
const row = data[i];
|
||||
if (typeof recordFirstVisitIndex[pk] === "undefined") {
|
||||
if (pk !== prevPkId) {
|
||||
const parent = parentMapper(row) as any;
|
||||
parent[childKey] = [];
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,8 @@ import { ActorType } from "@app/services/auth/auth-type";
|
||||
export const injectPermission = fp(async (server) => {
|
||||
server.decorateRequest("permission", null);
|
||||
server.addHook("onRequest", async (req) => {
|
||||
if (!req.auth) return;
|
||||
|
||||
if (req.auth.actor === ActorType.USER) {
|
||||
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 { registerV2Routes } from "./v2";
|
||||
import { registerV3Routes } from "./v3";
|
||||
import { injectPermission } from "../plugins/auth/inject-permission";
|
||||
|
||||
export const registerRoutes = async (
|
||||
server: FastifyZodProvider,
|
||||
@@ -149,6 +150,7 @@ export const registerRoutes = async (
|
||||
});
|
||||
|
||||
await server.register(injectIdentity);
|
||||
await server.register(injectPermission);
|
||||
|
||||
server.route({
|
||||
url: "/status",
|
||||
|
||||
@@ -82,7 +82,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string(),
|
||||
backupPrivateKey: BackupPrivateKeySchema
|
||||
backupPrivateKey: BackupPrivateKeySchema.omit({ verifier: true })
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -105,7 +105,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
response: {
|
||||
200: z.object({
|
||||
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 { 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({
|
||||
url: "/:workspaceId/keys",
|
||||
method: "GET",
|
||||
@@ -81,9 +87,7 @@ export const registerProjectRouter = (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
workspaces: ProjectsSchema.merge(
|
||||
z.object({ environments: z.object({ name: z.string(), slug: z.string() }).array() })
|
||||
).array()
|
||||
workspaces: projectWithEnv.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -103,9 +107,7 @@ export const registerProjectRouter = (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
workspace: ProjectsSchema.merge(
|
||||
z.object({ environments: z.object({ name: z.string(), slug: z.string() }).array() })
|
||||
).optional()
|
||||
workspace: projectWithEnv.optional()
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -130,7 +132,7 @@ export const registerProjectRouter = (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
workspace: ProjectsSchema
|
||||
workspace: projectWithEnv
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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 { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -11,7 +11,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
user: UsersSchema
|
||||
user: UsersSchema.merge(UserEncryptionKeysSchema.omit({ verifier: true }))
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
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 { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMethod, AuthMode } from "@app/services/auth/auth-type";
|
||||
@@ -195,7 +200,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
response: {
|
||||
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);
|
||||
await tokenDal.transaction(async (tx) => {
|
||||
await tokenDal.delete({ userId, type, orgId: orgId || null }, tx);
|
||||
const newToken = await tokenDal.create({
|
||||
tokenHash,
|
||||
expiresAt: tkCfg.expiresAt.toUTCString(),
|
||||
type,
|
||||
userId,
|
||||
orgId,
|
||||
triesLeft: tkCfg?.triesLeft
|
||||
});
|
||||
const newToken = await tokenDal.create(
|
||||
{
|
||||
tokenHash,
|
||||
expiresAt: tkCfg.expiresAt.toUTCString(),
|
||||
type,
|
||||
userId,
|
||||
orgId,
|
||||
triesLeft: tkCfg?.triesLeft
|
||||
},
|
||||
tx
|
||||
);
|
||||
return newToken;
|
||||
});
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
TResetPasswordViaBackupKeyDTO
|
||||
} from "./auth-password-type";
|
||||
import { AuthTokenType } from "./auth-type";
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding } from "@app/db/schemas";
|
||||
|
||||
type TAuthPasswordServiceFactoryDep = {
|
||||
authDal: TAuthDalFactory;
|
||||
@@ -212,13 +213,19 @@ export const authPaswordServiceFactory = ({
|
||||
);
|
||||
if (!isValidClientProff) throw new Error("failed to create backup key");
|
||||
const backup = await authDal.transaction(async (tx) => {
|
||||
const backupKey = await authDal.upsertBackupKey(userEnc.userId, {
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier
|
||||
});
|
||||
const backupKey = await authDal.upsertBackupKey(
|
||||
userEnc.userId,
|
||||
{
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
algorithm: SecretEncryptionAlgo.AES_256_GCM,
|
||||
keyEncoding: SecretKeyEncoding.UTF8
|
||||
},
|
||||
tx
|
||||
);
|
||||
|
||||
await userDal.updateUserEncryptionByUserId(
|
||||
userEnc.userId,
|
||||
|
||||
@@ -68,8 +68,11 @@ export const projectRoleServiceFactory = ({
|
||||
if (existingRole && existingRole.id !== roleId)
|
||||
throw new BadRequestError({ name: "Update Role", message: "Duplicate role" });
|
||||
}
|
||||
const [updatedRole] = await projectRoleDal.update({ id: roleId, projectId }, { ...data });
|
||||
if (!updateRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
|
||||
const [updatedRole] = await projectRoleDal.update(
|
||||
{ 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;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ export const projectDalFactory = (db: TDbClient) => {
|
||||
const workspaces = await db(TableName.ProjectMembership)
|
||||
.where({ userId })
|
||||
.join(
|
||||
TableName.Environment,
|
||||
`${TableName.Environment}.projectId`,
|
||||
TableName.Project,
|
||||
`${TableName.ProjectMembership}.projectId`,
|
||||
`${TableName.Project}.id`
|
||||
)
|
||||
.join(
|
||||
TableName.Project,
|
||||
`${TableName.ProjectMembership}.projectId`,
|
||||
TableName.Environment,
|
||||
`${TableName.Environment}.projectId`,
|
||||
`${TableName.Project}.id`
|
||||
)
|
||||
.select(
|
||||
@@ -57,13 +57,13 @@ export const projectDalFactory = (db: TDbClient) => {
|
||||
const workspaces = await db(TableName.ProjectMembership)
|
||||
.where(`${TableName.Project}.id`, id)
|
||||
.join(
|
||||
TableName.Environment,
|
||||
`${TableName.Environment}.projectId`,
|
||||
TableName.Project,
|
||||
`${TableName.ProjectMembership}.projectId`,
|
||||
`${TableName.Project}.id`
|
||||
)
|
||||
.join(
|
||||
TableName.Project,
|
||||
`${TableName.ProjectMembership}.projectId`,
|
||||
TableName.Environment,
|
||||
`${TableName.Environment}.projectId`,
|
||||
`${TableName.Project}.id`
|
||||
)
|
||||
.select(
|
||||
|
||||
@@ -50,11 +50,14 @@ export const projectServiceFactory = ({
|
||||
// TODO(backend-pg): licence server
|
||||
const newProject = projectDal.transaction(async (tx) => {
|
||||
const project = await projectDal.create({ name: workspaceName, orgId }, tx);
|
||||
await projectMembershipDal.create({
|
||||
userId: actorId,
|
||||
role: ProjectMembershipRole.Admin,
|
||||
projectId: project.id
|
||||
});
|
||||
await projectMembershipDal.create(
|
||||
{
|
||||
userId: actorId,
|
||||
role: ProjectMembershipRole.Admin,
|
||||
projectId: project.id
|
||||
},
|
||||
tx
|
||||
);
|
||||
const envs = await projectEnvDal.insertMany(
|
||||
DEFAULT_PROJECT_ENVS.map((el) => ({ ...el, projectId: project.id })),
|
||||
tx
|
||||
|
||||
@@ -37,7 +37,7 @@ export const userDalFactory = (db: TDbClient) => {
|
||||
|
||||
const findUserEncKeyByUserId = async (userId: string) => {
|
||||
try {
|
||||
return await db(TableName.Users)
|
||||
const user = await db(TableName.Users)
|
||||
.where(`${TableName.Users}.id`, userId)
|
||||
.join(
|
||||
TableName.UserEncryptionKey,
|
||||
@@ -45,6 +45,11 @@ export const userDalFactory = (db: TDbClient) => {
|
||||
`${TableName.UserEncryptionKey}.userId`
|
||||
)
|
||||
.first();
|
||||
if (user?.id) {
|
||||
// change to user id
|
||||
user.id = user.userId;
|
||||
}
|
||||
return user;
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Find user enc by user id" });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user