Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,273 @@
|
||||
import {
|
||||
createLegacyApiKeyLog,
|
||||
createLegacyApiKey,
|
||||
countLegacyApiKeyLogsForKey,
|
||||
deleteLegacyApiKey,
|
||||
adminFindLegacyApiKeyById,
|
||||
findFirstLegacyActiveApiKey,
|
||||
findLegacyApiKeyByAlias,
|
||||
findLegacyApiKeyById,
|
||||
findLegacyApiKeyByKey,
|
||||
getAllLegacyApiKeys,
|
||||
rotateLegacyApiKey,
|
||||
getLegacyApiKeyLogsForKey,
|
||||
getLegacyApiKeysForTenant,
|
||||
type LegacyApiKeyLogWithDetails,
|
||||
type LegacyApiKeySimple,
|
||||
type LegacyApiKeyWithDetails,
|
||||
updateLegacyApiKey,
|
||||
} from "@toolctrl/db/api-keys.server";
|
||||
import { db } from "../db.server";
|
||||
import { getClientIPAddress } from "~/utils/server/IpUtils";
|
||||
import { PaginationDto } from "~/application/dtos/data/PaginationDto";
|
||||
import { FiltersDto } from "~/application/dtos/data/FiltersDto";
|
||||
import RowFiltersHelper from "../helpers/RowFiltersHelper";
|
||||
import { cachified, clearCacheKey } from "../cache.server";
|
||||
import { loadRequiredWebConfig } from "@toolctrl/config";
|
||||
import { getApiKeyLookupCacheKey, serializeApiLogSearchParams } from "../api/apiKeySecurity.server";
|
||||
|
||||
export type ApiKeyWithDetails = LegacyApiKeyWithDetails;
|
||||
export type RedactedApiKeyWithDetails = Omit<LegacyApiKeyWithDetails, "key">;
|
||||
|
||||
export function redactApiKeyForDisplay(apiKey: LegacyApiKeyWithDetails): RedactedApiKeyWithDetails {
|
||||
const redactedApiKey = { ...apiKey };
|
||||
delete (redactedApiKey as Partial<LegacyApiKeyWithDetails>).key;
|
||||
return redactedApiKey;
|
||||
}
|
||||
|
||||
export function redactApiKeysForDisplay(apiKeys: LegacyApiKeyWithDetails[]): RedactedApiKeyWithDetails[] {
|
||||
return apiKeys.map(redactApiKeyForDisplay);
|
||||
}
|
||||
|
||||
export type ApiKeyLogWithDetails = LegacyApiKeyLogWithDetails;
|
||||
export type ApiKeyLogSimple = { apiKeyId: string | null; status: number | null };
|
||||
|
||||
export type ApiKeySimple = LegacyApiKeySimple;
|
||||
|
||||
export async function getAllApiKeys(): Promise<RedactedApiKeyWithDetails[]> {
|
||||
const apiKeys = await getAllLegacyApiKeys();
|
||||
return redactApiKeysForDisplay(apiKeys);
|
||||
}
|
||||
|
||||
export async function getAllApiKeyLogs(
|
||||
pagination: { page: number; pageSize: number },
|
||||
filters: FiltersDto
|
||||
): Promise<{ items: ApiKeyLogWithDetails[]; pagination: PaginationDto }> {
|
||||
const where = RowFiltersHelper.getFiltersCondition(filters);
|
||||
const items = await db.apiKeyLog.findMany({
|
||||
take: pagination.pageSize,
|
||||
skip: pagination.pageSize * (pagination.page - 1),
|
||||
where,
|
||||
include: {
|
||||
apiKey: {
|
||||
include: { tenant: true },
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
});
|
||||
const totalItems = await db.apiKeyLog.count({
|
||||
where,
|
||||
});
|
||||
|
||||
return {
|
||||
items,
|
||||
pagination: {
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
totalItems,
|
||||
totalPages: Math.ceil(totalItems / pagination.pageSize),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function getAllApiKeyLogsSimple(tenantId?: string): Promise<ApiKeyLogSimple[]> {
|
||||
let where: any = {};
|
||||
if (tenantId) {
|
||||
where = {
|
||||
apiKey: {
|
||||
tenantId,
|
||||
},
|
||||
};
|
||||
}
|
||||
return await db.apiKeyLog.findMany({
|
||||
where,
|
||||
select: {
|
||||
apiKeyId: true,
|
||||
status: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function getTenantApiKeyLogs(
|
||||
tenantId: string,
|
||||
pagination: { page: number; pageSize: number },
|
||||
filters: FiltersDto
|
||||
): Promise<{ items: ApiKeyLogWithDetails[]; pagination: PaginationDto }> {
|
||||
const where = {
|
||||
AND: [RowFiltersHelper.getFiltersCondition(filters), { apiKey: { tenantId } }],
|
||||
};
|
||||
const items = await db.apiKeyLog.findMany({
|
||||
take: pagination.pageSize,
|
||||
skip: pagination.pageSize * (pagination.page - 1),
|
||||
where,
|
||||
include: { apiKey: { include: { tenant: true } } },
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
const totalItems = await db.apiKeyLog.count({ where });
|
||||
return {
|
||||
items,
|
||||
pagination: {
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
totalItems,
|
||||
totalPages: Math.ceil(totalItems / pagination.pageSize),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function getApiKeys(tenantId: string): Promise<RedactedApiKeyWithDetails[]> {
|
||||
const apiKeys = await getLegacyApiKeysForTenant(tenantId);
|
||||
return redactApiKeysForDisplay(apiKeys);
|
||||
}
|
||||
|
||||
export async function adminGetApiKeyById(id: string): Promise<RedactedApiKeyWithDetails | null> {
|
||||
const apiKey = await adminFindLegacyApiKeyById(id);
|
||||
return apiKey ? redactApiKeyForDisplay(apiKey) : null;
|
||||
}
|
||||
|
||||
export async function getTenantApiKeyById(id: string, tenantId: string): Promise<RedactedApiKeyWithDetails | null> {
|
||||
const apiKey = await findLegacyApiKeyById({ id, tenantId });
|
||||
return apiKey ? redactApiKeyForDisplay(apiKey) : null;
|
||||
}
|
||||
|
||||
export async function adminGetApiKeyByIdWithSecret(id: string): Promise<ApiKeyWithDetails | null> {
|
||||
return adminFindLegacyApiKeyById(id);
|
||||
}
|
||||
|
||||
export async function getTenantApiKeyByIdWithSecret(id: string, tenantId: string): Promise<ApiKeyWithDetails | null> {
|
||||
return findLegacyApiKeyById({ id, tenantId });
|
||||
}
|
||||
|
||||
export async function getApiKey(key: string): Promise<ApiKeySimple | null> {
|
||||
return await cachified({
|
||||
key: getApiKeyLookupCacheKey(key),
|
||||
ttl: 1000 * 60 * 60,
|
||||
getFreshValue: () => findLegacyApiKeyByKey(key),
|
||||
});
|
||||
}
|
||||
|
||||
export async function getApiKeyByAlias(tenantId: string, alias: string): Promise<ApiKeyWithDetails | null> {
|
||||
return findLegacyApiKeyByAlias(tenantId, alias);
|
||||
}
|
||||
|
||||
export async function getApiKeyLogs(id: string, tenantId: string): Promise<ApiKeyLogWithDetails[]> {
|
||||
return getLegacyApiKeyLogsForKey({ id, tenantId });
|
||||
}
|
||||
|
||||
export async function countApiKeyLogsForKey(id: string, tenantId: string): Promise<number> {
|
||||
return countLegacyApiKeyLogsForKey({ id, tenantId });
|
||||
}
|
||||
|
||||
export async function getFirstApiKey(tenantId: string | null) {
|
||||
return findFirstLegacyActiveApiKey(tenantId);
|
||||
}
|
||||
|
||||
export async function createApiKey(
|
||||
data: {
|
||||
tenantId: string;
|
||||
createdByUserId: string;
|
||||
alias: string;
|
||||
expires: Date | null;
|
||||
active: boolean;
|
||||
},
|
||||
entities: {
|
||||
entityId: string;
|
||||
create: boolean;
|
||||
read: boolean;
|
||||
update: boolean;
|
||||
delete: boolean;
|
||||
}[]
|
||||
) {
|
||||
return createLegacyApiKey(data, entities, undefined, getApiKeyHashSecret());
|
||||
}
|
||||
|
||||
export async function createApiKeyLog(
|
||||
request: Request,
|
||||
data: {
|
||||
tenantId: string | null;
|
||||
apiKeyId: string | null;
|
||||
endpoint: string;
|
||||
error?: string;
|
||||
status?: number;
|
||||
alias?: string;
|
||||
tenantName?: string;
|
||||
}
|
||||
) {
|
||||
return await createLegacyApiKeyLog({
|
||||
tenantId: data.tenantId,
|
||||
apiKeyId: data.apiKeyId,
|
||||
endpoint: data.endpoint,
|
||||
error: data.error,
|
||||
status: data.status,
|
||||
alias: data.alias,
|
||||
tenantName: data.tenantName,
|
||||
ip: getClientIPAddress(request.headers)?.toString() ?? "",
|
||||
method: request.method,
|
||||
params: serializeApiLogSearchParams(request),
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateApiKey(
|
||||
id: string,
|
||||
data: {
|
||||
tenantId: string;
|
||||
alias: string;
|
||||
expires: Date | null;
|
||||
active: boolean;
|
||||
},
|
||||
entities: {
|
||||
entityId: string;
|
||||
create: boolean;
|
||||
read: boolean;
|
||||
update: boolean;
|
||||
delete: boolean;
|
||||
}[]
|
||||
) {
|
||||
const apiKey = await updateLegacyApiKey(id, data, entities);
|
||||
clearCacheKey(getApiKeyLookupCacheKey(apiKey.key));
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
export async function rotateApiKey(id: string, tenantId: string) {
|
||||
const previousApiKey = await findLegacyApiKeyById({ id, tenantId });
|
||||
if (!previousApiKey) {
|
||||
throw new Error(`API key ${id} not found`);
|
||||
}
|
||||
const apiKey = await rotateLegacyApiKey({ id, tenantId: previousApiKey.tenantId }, undefined, getApiKeyHashSecret());
|
||||
|
||||
if (previousApiKey?.key) {
|
||||
clearCacheKey(getApiKeyLookupCacheKey(previousApiKey.key));
|
||||
}
|
||||
clearCacheKey(getApiKeyLookupCacheKey(apiKey.key));
|
||||
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
export async function deleteApiKey(id: string, tenantId: string) {
|
||||
const previousApiKey = await findLegacyApiKeyById({ id, tenantId });
|
||||
if (!previousApiKey) {
|
||||
throw new Error(`API key ${id} not found`);
|
||||
}
|
||||
const apiKey = await deleteLegacyApiKey({ id, tenantId: previousApiKey.tenantId });
|
||||
clearCacheKey(getApiKeyLookupCacheKey(apiKey.key));
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
function getApiKeyHashSecret() {
|
||||
return loadRequiredWebConfig().jwtSecret;
|
||||
}
|
||||
Reference in new issue
Block a user