fix: dashboard not showing when root accessn not provided

This commit is contained in:
=
2024-09-26 15:13:07 +05:30
parent 4f5c49a529
commit 3d8fbc0a58
2 changed files with 157 additions and 156 deletions
+153 -140
View File
@@ -1,3 +1,4 @@
import { ForbiddenError } from "@casl/ability";
import { z } from "zod"; import { z } from "zod";
import { SecretFoldersSchema, SecretImportsSchema, SecretTagsSchema } from "@app/db/schemas"; import { SecretFoldersSchema, SecretImportsSchema, SecretTagsSchema } from "@app/db/schemas";
@@ -173,60 +174,49 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
} }
} }
if (includeDynamicSecrets) { try {
// this is the unique count, ie duplicate secrets across envs only count as 1 if (includeDynamicSecrets) {
totalDynamicSecretCount = await server.services.dynamicSecret.getCountMultiEnv({ // this is the unique count, ie duplicate secrets across envs only count as 1
actor: req.permission.type, totalDynamicSecretCount = await server.services.dynamicSecret.getCountMultiEnv({
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
projectId,
search,
environmentSlugs: environments,
path: secretPath
});
if (remainingLimit > 0 && totalDynamicSecretCount > adjustedOffset) {
dynamicSecrets = await server.services.dynamicSecret.listDynamicSecretsByFolderIds({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId, projectId,
search, search,
orderBy,
orderDirection,
environmentSlugs: environments, environmentSlugs: environments,
path: secretPath, path: secretPath
limit: remainingLimit,
offset: adjustedOffset
}); });
// get the count of unique dynamic secret names to properly adjust remaining limit if (remainingLimit > 0 && totalDynamicSecretCount > adjustedOffset) {
const uniqueDynamicSecretsCount = new Set(dynamicSecrets.map((dynamicSecret) => dynamicSecret.name)).size; dynamicSecrets = await server.services.dynamicSecret.listDynamicSecretsByFolderIds({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
projectId,
search,
orderBy,
orderDirection,
environmentSlugs: environments,
path: secretPath,
limit: remainingLimit,
offset: adjustedOffset
});
remainingLimit -= uniqueDynamicSecretsCount; // get the count of unique dynamic secret names to properly adjust remaining limit
adjustedOffset = 0; const uniqueDynamicSecretsCount = new Set(dynamicSecrets.map((dynamicSecret) => dynamicSecret.name)).size;
} else {
adjustedOffset = Math.max(0, adjustedOffset - totalDynamicSecretCount); remainingLimit -= uniqueDynamicSecretsCount;
adjustedOffset = 0;
} else {
adjustedOffset = Math.max(0, adjustedOffset - totalDynamicSecretCount);
}
} }
}
if (includeSecrets) { if (includeSecrets) {
// this is the unique count, ie duplicate secrets across envs only count as 1 // this is the unique count, ie duplicate secrets across envs only count as 1
totalSecretCount = await server.services.secret.getSecretsCountMultiEnv({ totalSecretCount = await server.services.secret.getSecretsCountMultiEnv({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
environments,
actorAuthMethod: req.permission.authMethod,
projectId,
path: secretPath,
search
});
if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
secrets = await server.services.secret.getSecretsRawMultiEnv({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
@@ -234,47 +224,64 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
projectId, projectId,
path: secretPath, path: secretPath,
orderBy, search
orderDirection,
search,
limit: remainingLimit,
offset: adjustedOffset
}); });
for await (const environment of environments) { if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
const secretCountFromEnv = secrets.filter((secret) => secret.environment === environment).length; secrets = await server.services.secret.getSecretsRawMultiEnv({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
environments,
actorAuthMethod: req.permission.authMethod,
projectId,
path: secretPath,
orderBy,
orderDirection,
search,
limit: remainingLimit,
offset: adjustedOffset
});
if (secretCountFromEnv) { for await (const environment of environments) {
await server.services.auditLog.createAuditLog({ const secretCountFromEnv = secrets.filter((secret) => secret.environment === environment).length;
projectId,
...req.auditLogInfo,
event: {
type: EventType.GET_SECRETS,
metadata: {
environment,
secretPath,
numberOfSecrets: secretCountFromEnv
}
}
});
if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) { if (secretCountFromEnv) {
await server.services.telemetry.sendPostHogEvents({ await server.services.auditLog.createAuditLog({
event: PostHogEventTypes.SecretPulled, projectId,
distinctId: getTelemetryDistinctId(req), ...req.auditLogInfo,
properties: { event: {
numberOfSecrets: secretCountFromEnv, type: EventType.GET_SECRETS,
workspaceId: projectId, metadata: {
environment, environment,
secretPath, secretPath,
channel: getUserAgentType(req.headers["user-agent"]), numberOfSecrets: secretCountFromEnv
...req.auditLogInfo }
} }
}); });
if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) {
await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: secretCountFromEnv,
workspaceId: projectId,
environment,
secretPath,
channel: getUserAgentType(req.headers["user-agent"]),
...req.auditLogInfo
}
});
}
} }
} }
} }
} }
} catch (error) {
if (!(error instanceof ForbiddenError)) {
throw error;
}
} }
return { return {
@@ -498,56 +505,44 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
} }
} }
if (includeDynamicSecrets) { try {
totalDynamicSecretCount = await server.services.dynamicSecret.getDynamicSecretCount({ if (includeDynamicSecrets) {
actor: req.permission.type, totalDynamicSecretCount = await server.services.dynamicSecret.getDynamicSecretCount({
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
projectId,
search,
environmentSlug: environment,
path: secretPath
});
if (remainingLimit > 0 && totalDynamicSecretCount > adjustedOffset) {
dynamicSecrets = await server.services.dynamicSecret.listDynamicSecretsByEnv({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId, projectId,
search, search,
orderBy,
orderDirection,
environmentSlug: environment, environmentSlug: environment,
path: secretPath, path: secretPath
limit: remainingLimit,
offset: adjustedOffset
}); });
remainingLimit -= dynamicSecrets.length; if (remainingLimit > 0 && totalDynamicSecretCount > adjustedOffset) {
adjustedOffset = 0; dynamicSecrets = await server.services.dynamicSecret.listDynamicSecretsByEnv({
} else { actor: req.permission.type,
adjustedOffset = Math.max(0, adjustedOffset - totalDynamicSecretCount); actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
projectId,
search,
orderBy,
orderDirection,
environmentSlug: environment,
path: secretPath,
limit: remainingLimit,
offset: adjustedOffset
});
remainingLimit -= dynamicSecrets.length;
adjustedOffset = 0;
} else {
adjustedOffset = Math.max(0, adjustedOffset - totalDynamicSecretCount);
}
} }
}
if (includeSecrets) { if (includeSecrets) {
totalSecretCount = await server.services.secret.getSecretsCount({ totalSecretCount = await server.services.secret.getSecretsCount({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
environment,
actorAuthMethod: req.permission.authMethod,
projectId,
path: secretPath,
search,
tagSlugs: tags
});
if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
const secretsRaw = await server.services.secret.getSecretsRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
@@ -555,44 +550,62 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
projectId, projectId,
path: secretPath, path: secretPath,
orderBy,
orderDirection,
search, search,
limit: remainingLimit,
offset: adjustedOffset,
tagSlugs: tags tagSlugs: tags
}); });
secrets = secretsRaw.secrets; if (remainingLimit > 0 && totalSecretCount > adjustedOffset) {
const secretsRaw = await server.services.secret.getSecretsRaw({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
environment,
actorAuthMethod: req.permission.authMethod,
projectId,
path: secretPath,
orderBy,
orderDirection,
search,
limit: remainingLimit,
offset: adjustedOffset,
tagSlugs: tags
});
await server.services.auditLog.createAuditLog({ secrets = secretsRaw.secrets;
projectId,
...req.auditLogInfo,
event: {
type: EventType.GET_SECRETS,
metadata: {
environment,
secretPath,
numberOfSecrets: secrets.length
}
}
});
if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) { await server.services.auditLog.createAuditLog({
await server.services.telemetry.sendPostHogEvents({ projectId,
event: PostHogEventTypes.SecretPulled, ...req.auditLogInfo,
distinctId: getTelemetryDistinctId(req), event: {
properties: { type: EventType.GET_SECRETS,
numberOfSecrets: secrets.length, metadata: {
workspaceId: projectId, environment,
environment, secretPath,
secretPath, numberOfSecrets: secrets.length
channel: getUserAgentType(req.headers["user-agent"]), }
...req.auditLogInfo
} }
}); });
if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) {
await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: secrets.length,
workspaceId: projectId,
environment,
secretPath,
channel: getUserAgentType(req.headers["user-agent"]),
...req.auditLogInfo
}
});
}
} }
} }
} catch (error) {
if (!(error instanceof ForbiddenError)) {
throw error;
}
} }
return { return {
@@ -191,20 +191,10 @@ export const SecretOverviewPage = () => {
const userAvailableEnvs = currentWorkspace?.environments || []; const userAvailableEnvs = currentWorkspace?.environments || [];
const readableEnvs = userAvailableEnvs?.filter(({ slug }) => const [visibleEnvs, setVisibleEnvs] = useState(userAvailableEnvs);
permission.can(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
environment: slug,
secretPath
})
)
);
const [visibleEnvs, setVisibleEnvs] = useState(readableEnvs);
useEffect(() => { useEffect(() => {
setVisibleEnvs(readableEnvs); setVisibleEnvs(userAvailableEnvs);
}, [userAvailableEnvs, secretPath]); }, [userAvailableEnvs, secretPath]);
const { isImportedSecretPresentInEnv, getImportedSecretByKey } = useGetImportedSecretsAllEnvs({ const { isImportedSecretPresentInEnv, getImportedSecretByKey } = useGetImportedSecretsAllEnvs({
@@ -529,9 +519,7 @@ export const SecretOverviewPage = () => {
const isTableEmpty = totalCount === 0; const isTableEmpty = totalCount === 0;
const isTableFiltered = const isTableFiltered = Boolean(Object.values(filter).filter((enabled) => !enabled).length);
Boolean(Object.values(filter).filter((enabled) => !enabled).length) ||
visibleEnvs.length !== readableEnvs?.length;
if (!isProjectV3) if (!isProjectV3)
return ( return (
@@ -611,7 +599,7 @@ export const SecretOverviewPage = () => {
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<DropdownMenuLabel>Choose visible environments</DropdownMenuLabel> <DropdownMenuLabel>Choose visible environments</DropdownMenuLabel>
{readableEnvs.map((availableEnv) => { {userAvailableEnvs.map((availableEnv) => {
const { id: envId, name } = availableEnv; const { id: envId, name } = availableEnv;
const isEnvSelected = visibleEnvs.map((env) => env.id).includes(envId); const isEnvSelected = visibleEnvs.map((env) => env.id).includes(envId);