feat: multiple auth methods for identities

This commit is contained in:
Daniel Hougaard
2024-10-26 23:26:22 +04:00
parent 2ddf75d2e6
commit 741138c4bd
35 changed files with 2200 additions and 2164 deletions
+180 -19
View File
@@ -1,12 +1,52 @@
import { Knex } from "knex";
import { TDbClient } from "@app/db";
import { TableName, TIdentityOrgMemberships, TOrgRoles } from "@app/db/schemas";
import {
IdentityAuthMethod,
TableName,
TIdentityAwsAuths,
TIdentityAzureAuths,
TIdentityGcpAuths,
TIdentityKubernetesAuths,
TIdentityOidcAuths,
TIdentityOrgMemberships,
TIdentityTokenAuths,
TIdentityUniversalAuths,
TOrgRoles
} from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
import { OrderByDirection } from "@app/lib/types";
import { OrgIdentityOrderBy, TListOrgIdentitiesByOrgIdDTO } from "@app/services/identity/identity-types";
const buildAuthMethods = ({
uaId,
gcpId,
awsId,
kubernetesId,
oidcId,
azureId,
tokenId
}: {
uaId?: string;
gcpId?: string;
awsId?: string;
kubernetesId?: string;
oidcId?: string;
azureId?: string;
tokenId?: string;
}) => {
return [
...(uaId ? [IdentityAuthMethod.UNIVERSAL_AUTH] : []),
...(gcpId ? [IdentityAuthMethod.GCP_AUTH] : []),
...(awsId ? [IdentityAuthMethod.AWS_AUTH] : []),
...(kubernetesId ? [IdentityAuthMethod.KUBERNETES_AUTH] : []),
...(oidcId ? [IdentityAuthMethod.OIDC_AUTH] : []),
...(azureId ? [IdentityAuthMethod.AZURE_AUTH] : []),
...(tokenId ? [IdentityAuthMethod.TOKEN_AUTH] : [])
].filter((authMethod) => authMethod);
};
export type TIdentityOrgDALFactory = ReturnType<typeof identityOrgDALFactory>;
export const identityOrgDALFactory = (db: TDbClient) => {
@@ -15,14 +55,73 @@ export const identityOrgDALFactory = (db: TDbClient) => {
const findOne = async (filter: Partial<TIdentityOrgMemberships>, tx?: Knex) => {
try {
const [data] = await (tx || db.replicaNode())(TableName.IdentityOrgMembership)
.where(filter)
.where((queryBuilder) => {
Object.entries(filter).forEach(([key, value]) => {
void queryBuilder.where(`${TableName.IdentityOrgMembership}.${key}`, value);
});
})
.join(TableName.Identity, `${TableName.IdentityOrgMembership}.identityId`, `${TableName.Identity}.id`)
.select(selectAllTableCols(TableName.IdentityOrgMembership))
.select(db.ref("name").withSchema(TableName.Identity))
.select(db.ref("authMethod").withSchema(TableName.Identity));
.leftJoin<TIdentityUniversalAuths>(
TableName.IdentityUniversalAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityUniversalAuth}.identityId`
)
.leftJoin<TIdentityGcpAuths>(
TableName.IdentityGcpAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityGcpAuth}.identityId`
)
.leftJoin<TIdentityAwsAuths>(
TableName.IdentityAwsAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityAwsAuth}.identityId`
)
.leftJoin<TIdentityKubernetesAuths>(
TableName.IdentityKubernetesAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityKubernetesAuth}.identityId`
)
.leftJoin<TIdentityOidcAuths>(
TableName.IdentityOidcAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityOidcAuth}.identityId`
)
.leftJoin<TIdentityAzureAuths>(
TableName.IdentityAzureAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityAzureAuth}.identityId`
)
.leftJoin<TIdentityTokenAuths>(
TableName.IdentityTokenAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityTokenAuth}.identityId`
)
.select(
selectAllTableCols(TableName.IdentityOrgMembership),
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
db.ref("id").as("oidcId").withSchema(TableName.IdentityOidcAuth),
db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth),
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth),
db.ref("name").withSchema(TableName.Identity)
);
if (data) {
const { name, authMethod } = data;
return { ...data, identity: { id: data.identityId, name, authMethod } };
const { name } = data;
return {
...data,
identity: {
id: data.identityId,
name,
authMethods: buildAuthMethods(data)
}
};
}
} catch (error) {
throw new DatabaseError({ error, name: "FindOne" });
@@ -42,7 +141,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
tx?: Knex
) => {
try {
const paginatedIdentity = (tx || db.replicaNode())(TableName.Identity)
const paginatedIdentitySubquery = (tx || db.replicaNode())(TableName.Identity)
.join(
TableName.IdentityOrgMembership,
`${TableName.IdentityOrgMembership}.identityId`,
@@ -51,30 +150,70 @@ export const identityOrgDALFactory = (db: TDbClient) => {
.orderBy(`${TableName.Identity}.${orderBy}`, orderDirection)
.select(
selectAllTableCols(TableName.IdentityOrgMembership),
db.ref("name").withSchema(TableName.Identity).as("identityName"),
db.ref("authMethod").withSchema(TableName.Identity).as("identityAuthMethod")
db.ref("name").withSchema(TableName.Identity).as("identityName")
// db.ref("authMethod").withSchema(TableName.Identity).as("identityAuthMethod")
)
.where(filter)
.as("paginatedIdentity");
if (search?.length) {
void paginatedIdentity.whereILike(`${TableName.Identity}.name`, `%${search}%`);
void paginatedIdentitySubquery.whereILike(`${TableName.Identity}.name`, `%${search}%`);
}
if (limit) {
void paginatedIdentity.offset(offset).limit(limit);
void paginatedIdentitySubquery.offset(offset).limit(limit);
}
const paginatedIdentity = paginatedIdentitySubquery.as("paginatedIdentity");
// akhilmhdh: refer this for pagination with multiple left queries
type TSubquery = Awaited<typeof paginatedIdentity>;
const query = (tx || db.replicaNode())
.from<TSubquery[number], TSubquery>(paginatedIdentity)
.leftJoin<TOrgRoles>(TableName.OrgRoles, `paginatedIdentity.roleId`, `${TableName.OrgRoles}.id`)
.leftJoin(TableName.IdentityMetadata, (queryBuilder) => {
void queryBuilder
.on(`paginatedIdentity.identityId`, `${TableName.IdentityMetadata}.identityId`)
.andOn(`paginatedIdentity.orgId`, `${TableName.IdentityMetadata}.orgId`);
})
.leftJoin<TIdentityUniversalAuths>(
TableName.IdentityUniversalAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityUniversalAuth}.identityId`
)
.leftJoin<TIdentityGcpAuths>(
TableName.IdentityGcpAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityGcpAuth}.identityId`
)
.leftJoin<TIdentityAwsAuths>(
TableName.IdentityAwsAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityAwsAuth}.identityId`
)
.leftJoin<TIdentityKubernetesAuths>(
TableName.IdentityKubernetesAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityKubernetesAuth}.identityId`
)
.leftJoin<TIdentityOidcAuths>(
TableName.IdentityOidcAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityOidcAuth}.identityId`
)
.leftJoin<TIdentityAzureAuths>(
TableName.IdentityAzureAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityAzureAuth}.identityId`
)
.leftJoin<TIdentityTokenAuths>(
TableName.IdentityTokenAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityTokenAuth}.identityId`
)
.select(
db.ref("id").withSchema("paginatedIdentity"),
db.ref("role").withSchema("paginatedIdentity"),
@@ -82,9 +221,16 @@ export const identityOrgDALFactory = (db: TDbClient) => {
db.ref("orgId").withSchema("paginatedIdentity"),
db.ref("createdAt").withSchema("paginatedIdentity"),
db.ref("updatedAt").withSchema("paginatedIdentity"),
db.ref("identityId").withSchema("paginatedIdentity"),
db.ref("identityId").withSchema("paginatedIdentity").as("identityNewId"),
db.ref("identityName").withSchema("paginatedIdentity"),
db.ref("identityAuthMethod").withSchema("paginatedIdentity")
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
db.ref("id").as("oidcId").withSchema(TableName.IdentityOidcAuth),
db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth),
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth)
)
// cr stands for custom role
.select(db.ref("id").as("crId").withSchema(TableName.OrgRoles))
@@ -112,20 +258,27 @@ export const identityOrgDALFactory = (db: TDbClient) => {
crSlug,
crPermission,
crName,
identityId,
identityNewId,
identityName,
identityAuthMethod,
role,
roleId,
id,
orgId,
uaId,
awsId,
gcpId,
kubernetesId,
oidcId,
azureId,
tokenId,
createdAt,
updatedAt
}) => ({
role,
roleId,
identityId,
identityId: identityNewId,
id,
orgId,
createdAt,
updatedAt,
@@ -139,9 +292,17 @@ export const identityOrgDALFactory = (db: TDbClient) => {
}
: undefined,
identity: {
id: identityId,
id: identityNewId,
name: identityName,
authMethod: identityAuthMethod as string
authMethods: buildAuthMethods({
uaId,
awsId,
gcpId,
kubernetesId,
oidcId,
azureId,
tokenId
})
}
}),
childrenMapper: [