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:
2025-11-27 22:15:38 +00:00
parent a6c6ea1393
commit ab88ac896f
71 changed files with 9446 additions and 0 deletions

View 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 }
);
}
}