feat: minor bug fixes and text changes

This commit is contained in:
Akhil Mohan
2024-03-12 21:49:33 +05:30
parent f1f18e81cd
commit 4152b3a524
11 changed files with 51 additions and 40 deletions
+21 -3
View File
@@ -1,6 +1,7 @@
import slugify from "@sindresorhus/slugify";
import { z } from "zod"; import { z } from "zod";
import { OrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas"; import { OrgMembershipRole, OrgMembershipsSchema, OrgRolesSchema } 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";
@@ -13,7 +14,14 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
organizationId: z.string().trim() organizationId: z.string().trim()
}), }),
body: z.object({ body: z.object({
slug: z.string().trim(), slug: z
.string()
.min(1)
.trim()
.refine((val) => Object.keys(OrgMembershipRole).includes(val), "Invalid keyword slugs")
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
}),
name: z.string().trim(), name: z.string().trim(),
description: z.string().trim().optional(), description: z.string().trim().optional(),
permissions: z.any().array() permissions: z.any().array()
@@ -45,7 +53,17 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
roleId: z.string().trim() roleId: z.string().trim()
}), }),
body: z.object({ body: z.object({
slug: z.string().trim().optional(), slug: z
.string()
.trim()
.optional()
.refine(
(val) => typeof val === "undefined" || Object.keys(OrgMembershipRole).includes(val),
"Invalid keyword slugs"
)
.refine((val) => typeof val === "undefined" || slugify(val) === val, {
message: "Slug must be a valid slug"
}),
name: z.string().trim().optional(), name: z.string().trim().optional(),
description: z.string().trim().optional(), description: z.string().trim().optional(),
permissions: z.any().array() permissions: z.any().array()
@@ -1,3 +1,4 @@
import ms from "ms";
import { z } from "zod"; import { z } from "zod";
import { import {
@@ -147,7 +148,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
role: z.string(), role: z.string(),
isTemporary: z.literal(true), isTemporary: z.literal(true),
temporaryMode: z.nativeEnum(ProjectUserMembershipTemporaryMode), temporaryMode: z.nativeEnum(ProjectUserMembershipTemporaryMode),
temporaryRange: z.string(), temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be positive"),
temporaryAccessStartTime: z.string().datetime() temporaryAccessStartTime: z.string().datetime()
}) })
]) ])
@@ -1,3 +1,4 @@
import ms from "ms";
import { z } from "zod"; import { z } from "zod";
import { import {
@@ -69,13 +70,12 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
role: z.string(), role: z.string(),
isTemporary: z.literal(true), isTemporary: z.literal(true),
temporaryMode: z.nativeEnum(ProjectUserMembershipTemporaryMode), temporaryMode: z.nativeEnum(ProjectUserMembershipTemporaryMode),
temporaryRange: z.string(), temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be positive"),
temporaryAccessStartTime: z.string().datetime() temporaryAccessStartTime: z.string().datetime()
}) })
]) ])
) )
.min(1) .min(1)
.refine((data) => data.some(({ isTemporary }) => !isTemporary), "Atleast one permanent role required")
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -158,9 +158,6 @@ export const identityProjectServiceFactory = ({
// check cron or relative here later for now its just relative // check cron or relative here later for now its just relative
const relativeTimeInMs = ms(inputRole.temporaryRange); const relativeTimeInMs = ms(inputRole.temporaryRange);
if (relativeTimeInMs <= 0) {
throw new BadRequestError({ message: "Temporary relative time range must be positive" });
}
return { return {
projectMembershipId: projectIdentity.id, projectMembershipId: projectIdentity.id,
role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role, role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role,
+2 -2
View File
@@ -58,7 +58,7 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
{ id: roleId, orgId }, { id: roleId, orgId },
{ ...data, permissions: data.permissions ? JSON.stringify(data.permissions) : undefined } { ...data, permissions: data.permissions ? JSON.stringify(data.permissions) : undefined }
); );
if (!updateRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); if (!updatedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
return updatedRole; return updatedRole;
}; };
@@ -66,7 +66,7 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role);
const [deletedRole] = await orgRoleDAL.delete({ id: roleId, orgId }); const [deletedRole] = await orgRoleDAL.delete({ id: roleId, orgId });
if (!deleteRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
return deletedRole; return deletedRole;
}; };
@@ -320,9 +320,6 @@ export const projectMembershipServiceFactory = ({
// check cron or relative here later for now its just relative // check cron or relative here later for now its just relative
const relativeTimeInMs = ms(inputRole.temporaryRange); const relativeTimeInMs = ms(inputRole.temporaryRange);
if (relativeTimeInMs <= 0) {
throw new BadRequestError({ message: "Temporary relative time range must be positive" });
}
return { return {
projectMembershipId: membershipId, projectMembershipId: membershipId,
role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role, role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role,
@@ -76,7 +76,7 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role);
const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId }); const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId });
if (!deleteRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
return deletedRole; return deletedRole;
}; };
@@ -5,12 +5,7 @@ import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
import { withProjectPermission } from "@app/hoc"; import { withProjectPermission } from "@app/hoc";
import { import { IdentityTab, MemberListTab, ProjectRoleListTab, ServiceTokenTab } from "./components";
IdentityTab,
MemberListTab,
ProjectRoleListTab,
ServiceTokenTab
} from "./components";
enum TabSections { enum TabSections {
Member = "members", Member = "members",
@@ -23,19 +18,14 @@ export const MembersPage = withProjectPermission(
() => { () => {
return ( return (
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white"> <div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
<div className="mb-6 w-full py-6 px-6 max-w-7xl mx-auto"> <div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
<p className="mr-4 mb-4 text-3xl font-semibold text-white"> <p className="mr-4 mb-4 text-3xl font-semibold text-white">Project Access Control</p>
Project Access Control
</p>
<Tabs defaultValue={TabSections.Member}> <Tabs defaultValue={TabSections.Member}>
<TabList> <TabList>
<Tab value={TabSections.Member}>People</Tab> <Tab value={TabSections.Member}>People</Tab>
<Tab value={TabSections.Identities}> <Tab value={TabSections.Identities}>
<div className="flex items-center"> <div className="flex items-center">
<p>Machine Identities</p> <p>Machine Identities</p>
<div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
New
</div>
</div> </div>
</Tab> </Tab>
<Tab value={TabSections.ServiceTokens}>Service Tokens</Tab> <Tab value={TabSections.ServiceTokens}>Service Tokens</Tab>
@@ -155,7 +155,7 @@ const IdentityTemporaryRoleForm = ({
})() })()
} }
> >
Give access Grant access
</Button> </Button>
) : ( ) : (
<Button <Button
@@ -155,7 +155,7 @@ const TemporaryRoleForm = ({
})() })()
} }
> >
Give access Grant access
</Button> </Button>
) : ( ) : (
<Button <Button
@@ -78,18 +78,26 @@ export const ProjectNameChangeSection = () => {
</CopyButton> </CopyButton>
</div> </div>
</div> </div>
<div className="max-w-md"> <div className="max-w-md">
<Controller <ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Workspace}>
defaultValue="" {(isAllowed) => (
render={({ field, fieldState: { error } }) => ( <Controller
<FormControl isError={Boolean(error)} errorText={error?.message}> defaultValue=""
<Input placeholder="Project name" {...field} className="bg-mineshaft-800" /> render={({ field, fieldState: { error } }) => (
</FormControl> <FormControl isError={Boolean(error)} errorText={error?.message}>
<Input
placeholder="Project name"
{...field}
className="bg-mineshaft-800"
isDisabled={!isAllowed}
/>
</FormControl>
)}
control={control}
name="name"
/>
)} )}
control={control} </ProjectPermissionCan>
name="name"
/>
</div> </div>
<ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Workspace}> <ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Workspace}>
{(isAllowed) => ( {(isAllowed) => (