Add access permission management API

Backend:
- Add AccessPermission schemas (Create, Update, Response)
- Add ProjectWithAccessResponse schema
- Add permission endpoints:
  - GET /project/{name}/permissions - list permissions (admin only)
  - POST /project/{name}/permissions - grant access (admin only)
  - PUT /project/{name}/permissions/{username} - update access
  - DELETE /project/{name}/permissions/{username} - revoke access
  - GET /project/{name}/my-access - get current user's access level

Frontend:
- Add AccessLevel, AccessPermission types
- Add API functions for access management:
  - getMyProjectAccess()
  - listProjectPermissions()
  - grantProjectAccess()
  - updateProjectAccess()
  - revokeProjectAccess()
This commit is contained in:
Mondo Diaz
2026-01-08 18:26:22 -06:00
parent 6aa199b80b
commit 0bef44a292
4 changed files with 300 additions and 0 deletions

View File

@@ -25,6 +25,10 @@ import {
AdminUser,
UserCreate,
UserUpdate,
AccessPermission,
AccessPermissionCreate,
AccessPermissionUpdate,
AccessLevel,
} from './types';
const API_BASE = '/api/v1';
@@ -299,3 +303,62 @@ export async function resetUserPassword(username: string, newPassword: string):
throw new Error(error.detail || `HTTP ${response.status}`);
}
}
// Access Permission API
export interface MyAccessResponse {
project: string;
access_level: AccessLevel | null;
is_owner: boolean;
}
export async function getMyProjectAccess(projectName: string): Promise<MyAccessResponse> {
const response = await fetch(`${API_BASE}/project/${projectName}/my-access`, {
credentials: 'include',
});
return handleResponse<MyAccessResponse>(response);
}
export async function listProjectPermissions(projectName: string): Promise<AccessPermission[]> {
const response = await fetch(`${API_BASE}/project/${projectName}/permissions`, {
credentials: 'include',
});
return handleResponse<AccessPermission[]>(response);
}
export async function grantProjectAccess(
projectName: string,
data: AccessPermissionCreate
): Promise<AccessPermission> {
const response = await fetch(`${API_BASE}/project/${projectName}/permissions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
credentials: 'include',
});
return handleResponse<AccessPermission>(response);
}
export async function updateProjectAccess(
projectName: string,
username: string,
data: AccessPermissionUpdate
): Promise<AccessPermission> {
const response = await fetch(`${API_BASE}/project/${projectName}/permissions/${username}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
credentials: 'include',
});
return handleResponse<AccessPermission>(response);
}
export async function revokeProjectAccess(projectName: string, username: string): Promise<void> {
const response = await fetch(`${API_BASE}/project/${projectName}/permissions/${username}`, {
method: 'DELETE',
credentials: 'include',
});
if (!response.ok) {
const error = await response.json().catch(() => ({ detail: 'Unknown error' }));
throw new Error(error.detail || `HTTP ${response.status}`);
}
}

View File

@@ -289,3 +289,38 @@ export interface UserUpdate {
is_admin?: boolean;
is_active?: boolean;
}
// Access Control types
export type AccessLevel = 'read' | 'write' | 'admin';
export interface AccessPermission {
id: string;
project_id: string;
user_id: string;
level: AccessLevel;
created_at: string;
expires_at: string | null;
}
export interface AccessPermissionCreate {
username: string;
level: AccessLevel;
expires_at?: string;
}
export interface AccessPermissionUpdate {
level?: AccessLevel;
expires_at?: string | null;
}
// Extended Project with user's access level
export interface ProjectWithAccess extends Project {
user_access_level?: AccessLevel;
}
// Current user with permissions context
export interface CurrentUser extends User {
permissions?: {
[projectId: string]: AccessLevel;
};
}