feat: implement account settings and API tokens management
- Added SettingsComponent for user profile management, including display name and password change functionality. - Introduced TokensComponent for managing API tokens, including creation and revocation. - Created LayoutComponent for consistent application layout with navigation and user information. - Established main application structure in index.html and main.ts. - Integrated Tailwind CSS for styling and responsive design. - Configured TypeScript settings for strict type checking and module resolution.
This commit is contained in:
226
ui/src/app/core/services/api.service.ts
Normal file
226
ui/src/app/core/services/api.service.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// Types
|
||||
export interface IOrganization {
|
||||
id: string;
|
||||
name: string;
|
||||
displayName: string;
|
||||
description?: string;
|
||||
avatarUrl?: string;
|
||||
isPublic: boolean;
|
||||
memberCount: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface IRepository {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
name: string;
|
||||
displayName: string;
|
||||
description?: string;
|
||||
protocols: string[];
|
||||
isPublic: boolean;
|
||||
packageCount: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface IPackage {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
protocol: string;
|
||||
organizationId: string;
|
||||
repositoryId: string;
|
||||
latestVersion?: string;
|
||||
isPrivate: boolean;
|
||||
downloadCount: number;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface IToken {
|
||||
id: string;
|
||||
name: string;
|
||||
tokenPrefix: string;
|
||||
protocols: string[];
|
||||
expiresAt?: string;
|
||||
lastUsedAt?: string;
|
||||
usageCount: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface IAuditLog {
|
||||
id: string;
|
||||
actorId?: string;
|
||||
actorType: string;
|
||||
action: string;
|
||||
resourceType: string;
|
||||
resourceId?: string;
|
||||
resourceName?: string;
|
||||
success: boolean;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ApiService {
|
||||
private readonly baseUrl = '/api/v1';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
// Organizations
|
||||
getOrganizations(): Observable<{ organizations: IOrganization[] }> {
|
||||
return this.http.get<{ organizations: IOrganization[] }>(
|
||||
`${this.baseUrl}/organizations`
|
||||
);
|
||||
}
|
||||
|
||||
getOrganization(id: string): Observable<IOrganization> {
|
||||
return this.http.get<IOrganization>(`${this.baseUrl}/organizations/${id}`);
|
||||
}
|
||||
|
||||
createOrganization(data: {
|
||||
name: string;
|
||||
displayName?: string;
|
||||
description?: string;
|
||||
isPublic?: boolean;
|
||||
}): Observable<IOrganization> {
|
||||
return this.http.post<IOrganization>(`${this.baseUrl}/organizations`, data);
|
||||
}
|
||||
|
||||
updateOrganization(
|
||||
id: string,
|
||||
data: Partial<IOrganization>
|
||||
): Observable<IOrganization> {
|
||||
return this.http.put<IOrganization>(
|
||||
`${this.baseUrl}/organizations/${id}`,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
deleteOrganization(id: string): Observable<{ message: string }> {
|
||||
return this.http.delete<{ message: string }>(
|
||||
`${this.baseUrl}/organizations/${id}`
|
||||
);
|
||||
}
|
||||
|
||||
// Repositories
|
||||
getRepositories(orgId: string): Observable<{ repositories: IRepository[] }> {
|
||||
return this.http.get<{ repositories: IRepository[] }>(
|
||||
`${this.baseUrl}/organizations/${orgId}/repositories`
|
||||
);
|
||||
}
|
||||
|
||||
getRepository(id: string): Observable<IRepository> {
|
||||
return this.http.get<IRepository>(`${this.baseUrl}/repositories/${id}`);
|
||||
}
|
||||
|
||||
createRepository(
|
||||
orgId: string,
|
||||
data: {
|
||||
name: string;
|
||||
displayName?: string;
|
||||
description?: string;
|
||||
protocols?: string[];
|
||||
isPublic?: boolean;
|
||||
}
|
||||
): Observable<IRepository> {
|
||||
return this.http.post<IRepository>(
|
||||
`${this.baseUrl}/organizations/${orgId}/repositories`,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
updateRepository(
|
||||
id: string,
|
||||
data: Partial<IRepository>
|
||||
): Observable<IRepository> {
|
||||
return this.http.put<IRepository>(`${this.baseUrl}/repositories/${id}`, data);
|
||||
}
|
||||
|
||||
deleteRepository(id: string): Observable<{ message: string }> {
|
||||
return this.http.delete<{ message: string }>(
|
||||
`${this.baseUrl}/repositories/${id}`
|
||||
);
|
||||
}
|
||||
|
||||
// Packages
|
||||
searchPackages(params?: {
|
||||
q?: string;
|
||||
protocol?: string;
|
||||
organizationId?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Observable<{ packages: IPackage[]; total: number }> {
|
||||
let httpParams = new HttpParams();
|
||||
if (params?.q) httpParams = httpParams.set('q', params.q);
|
||||
if (params?.protocol) httpParams = httpParams.set('protocol', params.protocol);
|
||||
if (params?.organizationId)
|
||||
httpParams = httpParams.set('organizationId', params.organizationId);
|
||||
if (params?.limit) httpParams = httpParams.set('limit', params.limit.toString());
|
||||
if (params?.offset) httpParams = httpParams.set('offset', params.offset.toString());
|
||||
|
||||
return this.http.get<{ packages: IPackage[]; total: number }>(
|
||||
`${this.baseUrl}/packages`,
|
||||
{ params: httpParams }
|
||||
);
|
||||
}
|
||||
|
||||
getPackage(id: string): Observable<IPackage> {
|
||||
return this.http.get<IPackage>(
|
||||
`${this.baseUrl}/packages/${encodeURIComponent(id)}`
|
||||
);
|
||||
}
|
||||
|
||||
deletePackage(id: string): Observable<{ message: string }> {
|
||||
return this.http.delete<{ message: string }>(
|
||||
`${this.baseUrl}/packages/${encodeURIComponent(id)}`
|
||||
);
|
||||
}
|
||||
|
||||
// Tokens
|
||||
getTokens(): Observable<{ tokens: IToken[] }> {
|
||||
return this.http.get<{ tokens: IToken[] }>(`${this.baseUrl}/tokens`);
|
||||
}
|
||||
|
||||
createToken(data: {
|
||||
name: string;
|
||||
protocols: string[];
|
||||
scopes: { protocol: string; actions: string[] }[];
|
||||
expiresInDays?: number;
|
||||
}): Observable<IToken & { token: string }> {
|
||||
return this.http.post<IToken & { token: string }>(
|
||||
`${this.baseUrl}/tokens`,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
revokeToken(id: string): Observable<{ message: string }> {
|
||||
return this.http.delete<{ message: string }>(`${this.baseUrl}/tokens/${id}`);
|
||||
}
|
||||
|
||||
// Audit
|
||||
getAuditLogs(params?: {
|
||||
organizationId?: string;
|
||||
resourceType?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Observable<{ logs: IAuditLog[]; total: number }> {
|
||||
let httpParams = new HttpParams();
|
||||
if (params?.organizationId)
|
||||
httpParams = httpParams.set('organizationId', params.organizationId);
|
||||
if (params?.resourceType)
|
||||
httpParams = httpParams.set('resourceType', params.resourceType);
|
||||
if (params?.startDate) httpParams = httpParams.set('startDate', params.startDate);
|
||||
if (params?.endDate) httpParams = httpParams.set('endDate', params.endDate);
|
||||
if (params?.limit) httpParams = httpParams.set('limit', params.limit.toString());
|
||||
if (params?.offset) httpParams = httpParams.set('offset', params.offset.toString());
|
||||
|
||||
return this.http.get<{ logs: IAuditLog[]; total: number }>(
|
||||
`${this.baseUrl}/audit`,
|
||||
{ params: httpParams }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user