Add API token roles to enhance access control

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9111ef36-26c8-4085-84ca-a35dc1fec1b5
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7083d608-d6d3-4a6a-9a27-6286c5109627/262170ae-5240-4866-86d5-1e4164217124.jpg
This commit is contained in:
alphaeusmote
2025-04-11 16:19:26 +00:00
+51 -3
View File
@@ -61,6 +61,13 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox"; import { Checkbox } from "@/components/ui/checkbox";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Loader2, Key, MoreVertical, Calendar, Copy, Info } from "lucide-react"; import { Loader2, Key, MoreVertical, Calendar, Copy, Info } from "lucide-react";
import { formatDistanceToNow, format } from "date-fns"; import { formatDistanceToNow, format } from "date-fns";
@@ -105,8 +112,9 @@ export default function ApiTokensPage() {
mutationFn: async (data: z.infer<typeof tokenFormSchema>) => { mutationFn: async (data: z.infer<typeof tokenFormSchema>) => {
const tokenData: Partial<InsertApiToken> = { const tokenData: Partial<InsertApiToken> = {
name: data.name, name: data.name,
organizationId: currentOrganization?.id || 0, organizationId: currentOrganization?.id || "",
permissions: data.permissions, permissions: data.permissions,
role: data.role,
isActive: true, isActive: true,
}; };
@@ -226,6 +234,7 @@ export default function ApiTokensPage() {
<TableRow> <TableRow>
<TableHead>Name</TableHead> <TableHead>Name</TableHead>
<TableHead>Token</TableHead> <TableHead>Token</TableHead>
<TableHead>Role</TableHead>
<TableHead>Permissions</TableHead> <TableHead>Permissions</TableHead>
<TableHead>Expires</TableHead> <TableHead>Expires</TableHead>
<TableHead>Status</TableHead> <TableHead>Status</TableHead>
@@ -239,9 +248,14 @@ export default function ApiTokensPage() {
<TableCell className="font-mono text-xs"> <TableCell className="font-mono text-xs">
{token.token.substring(0, 8)}... {token.token.substring(0, 8)}...
</TableCell> </TableCell>
<TableCell>
<Badge variant="outline" className="text-xs capitalize">
{token.role || "readonly"}
</Badge>
</TableCell>
<TableCell> <TableCell>
<div className="flex flex-wrap gap-1"> <div className="flex flex-wrap gap-1">
{token.permissions.map((permission) => ( {token.permissions?.map((permission) => (
<Badge key={permission} variant="outline" className="text-xs"> <Badge key={permission} variant="outline" className="text-xs">
{permission} {permission}
</Badge> </Badge>
@@ -328,6 +342,40 @@ export default function ApiTokensPage() {
)} )}
/> />
<FormField
control={form.control}
name="role"
render={({ field }) => (
<FormItem>
<FormLabel>Role</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select a role" />
</SelectTrigger>
</FormControl>
<SelectContent>
{systemRoles.map((role) => (
<SelectItem key={role} value={role}>
{role === "admin" && "Administrator"}
{role === "manager" && "Manager"}
{role === "user" && "User"}
{role === "readonly" && "Read-only"}
</SelectItem>
))}
</SelectContent>
</Select>
<FormDescription>
Determines the level of access for this token
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="permissions" name="permissions"
@@ -336,7 +384,7 @@ export default function ApiTokensPage() {
<div className="mb-4"> <div className="mb-4">
<FormLabel className="text-base">Permissions</FormLabel> <FormLabel className="text-base">Permissions</FormLabel>
<FormDescription> <FormDescription>
Select the permissions for this token Select specific permissions for this token
</FormDescription> </FormDescription>
</div> </div>
{systemRoles.map((role) => ( {systemRoles.map((role) => (