Feature/extract users from admin control panel endpoint to dedicated endpoint (#3740)
* Introduce GET api/v1/admin/user endpoint * Update changelog
This commit is contained in:
parent
728f84e7eb
commit
9cd4321bd0
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Extracted the users from the admin control panel endpoint to a dedicated endpoint
|
||||||
|
|
||||||
## 2.106.0 - 2024-09-07
|
## 2.106.0 - 2024-09-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
AdminData,
|
AdminData,
|
||||||
AdminMarketData,
|
AdminMarketData,
|
||||||
AdminMarketDataDetails,
|
AdminMarketDataDetails,
|
||||||
|
AdminUsers,
|
||||||
EnhancedSymbolProfile
|
EnhancedSymbolProfile
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { permissions } from '@ghostfolio/common/permissions';
|
import { permissions } from '@ghostfolio/common/permissions';
|
||||||
@ -347,4 +348,11 @@ export class AdminController {
|
|||||||
) {
|
) {
|
||||||
return this.adminService.putSetting(key, data.value);
|
return this.adminService.putSetting(key, data.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('user')
|
||||||
|
@HasPermission(permissions.accessAdminControl)
|
||||||
|
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
|
||||||
|
public async getUsers(): Promise<AdminUsers> {
|
||||||
|
return this.adminService.getUsers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import {
|
|||||||
AdminMarketData,
|
AdminMarketData,
|
||||||
AdminMarketDataDetails,
|
AdminMarketDataDetails,
|
||||||
AdminMarketDataItem,
|
AdminMarketDataItem,
|
||||||
|
AdminUsers,
|
||||||
AssetProfileIdentifier,
|
AssetProfileIdentifier,
|
||||||
EnhancedSymbolProfile,
|
EnhancedSymbolProfile,
|
||||||
Filter
|
Filter
|
||||||
@ -135,7 +136,6 @@ export class AdminService {
|
|||||||
settings: await this.propertyService.get(),
|
settings: await this.propertyService.get(),
|
||||||
transactionCount: await this.prismaService.order.count(),
|
transactionCount: await this.prismaService.order.count(),
|
||||||
userCount: await this.prismaService.user.count(),
|
userCount: await this.prismaService.user.count(),
|
||||||
users: await this.getUsersWithAnalytics(),
|
|
||||||
version: environment.version
|
version: environment.version
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -377,6 +377,10 @@ export class AdminService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getUsers(): Promise<AdminUsers> {
|
||||||
|
return { users: await this.getUsersWithAnalytics() };
|
||||||
|
}
|
||||||
|
|
||||||
public async patchAssetProfileData({
|
public async patchAssetProfileData({
|
||||||
assetClass,
|
assetClass,
|
||||||
assetSubClass,
|
assetSubClass,
|
||||||
@ -546,11 +550,11 @@ export class AdminService {
|
|||||||
return { marketData, count: marketData.length };
|
return { marketData, count: marketData.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getUsersWithAnalytics(): Promise<AdminData['users']> {
|
private async getUsersWithAnalytics(): Promise<AdminUsers['users']> {
|
||||||
let orderBy: any = {
|
let orderBy: any = {
|
||||||
createdAt: 'desc'
|
createdAt: 'desc'
|
||||||
};
|
};
|
||||||
let where;
|
let where: Prisma.UserWhereInput;
|
||||||
|
|
||||||
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
|
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
|
||||||
orderBy = {
|
orderBy = {
|
||||||
|
@ -5,7 +5,7 @@ import { DataService } from '@ghostfolio/client/services/data.service';
|
|||||||
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
|
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
|
||||||
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
||||||
import { getDateFormatString, getEmojiFlag } from '@ghostfolio/common/helper';
|
import { getDateFormatString, getEmojiFlag } from '@ghostfolio/common/helper';
|
||||||
import { AdminData, InfoItem, User } from '@ghostfolio/common/interfaces';
|
import { AdminUsers, InfoItem, User } from '@ghostfolio/common/interfaces';
|
||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
|
|
||||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
@ -24,7 +24,7 @@ import { takeUntil } from 'rxjs/operators';
|
|||||||
templateUrl: './admin-users.html'
|
templateUrl: './admin-users.html'
|
||||||
})
|
})
|
||||||
export class AdminUsersComponent implements OnDestroy, OnInit {
|
export class AdminUsersComponent implements OnDestroy, OnInit {
|
||||||
public dataSource: MatTableDataSource<AdminData['users'][0]> =
|
public dataSource: MatTableDataSource<AdminUsers['users'][0]> =
|
||||||
new MatTableDataSource();
|
new MatTableDataSource();
|
||||||
public defaultDateFormat: string;
|
public defaultDateFormat: string;
|
||||||
public displayedColumns: string[] = [];
|
public displayedColumns: string[] = [];
|
||||||
@ -94,7 +94,7 @@ export class AdminUsersComponent implements OnDestroy, OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.fetchAdminData();
|
this.fetchUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public formatDistanceToNow(aDateString: string) {
|
public formatDistanceToNow(aDateString: string) {
|
||||||
@ -119,7 +119,7 @@ export class AdminUsersComponent implements OnDestroy, OnInit {
|
|||||||
.deleteUser(aId)
|
.deleteUser(aId)
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.fetchAdminData();
|
this.fetchUsers();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
confirmType: ConfirmationDialogType.Warn,
|
confirmType: ConfirmationDialogType.Warn,
|
||||||
@ -142,11 +142,11 @@ export class AdminUsersComponent implements OnDestroy, OnInit {
|
|||||||
this.unsubscribeSubject.complete();
|
this.unsubscribeSubject.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
private fetchAdminData() {
|
private fetchUsers() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
this.adminService
|
this.adminService
|
||||||
.fetchAdminData()
|
.fetchUsers()
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe(({ users }) => {
|
.subscribe(({ users }) => {
|
||||||
this.dataSource = new MatTableDataSource(users);
|
this.dataSource = new MatTableDataSource(users);
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
AdminJobs,
|
AdminJobs,
|
||||||
AdminMarketData,
|
AdminMarketData,
|
||||||
AdminMarketDataDetails,
|
AdminMarketDataDetails,
|
||||||
|
AdminUsers,
|
||||||
EnhancedSymbolProfile,
|
EnhancedSymbolProfile,
|
||||||
Filter
|
Filter
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
@ -155,6 +156,10 @@ export class AdminService {
|
|||||||
return this.http.get<Tag[]>('/api/v1/tag');
|
return this.http.get<Tag[]>('/api/v1/tag');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fetchUsers() {
|
||||||
|
return this.http.get<AdminUsers>('/api/v1/admin/user');
|
||||||
|
}
|
||||||
|
|
||||||
public gather7Days() {
|
public gather7Days() {
|
||||||
return this.http.post<void>('/api/v1/admin/gather', {});
|
return this.http.post<void>('/api/v1/admin/gather', {});
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces';
|
import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces';
|
||||||
|
|
||||||
import { Role } from '@prisma/client';
|
|
||||||
|
|
||||||
export interface AdminData {
|
export interface AdminData {
|
||||||
exchangeRates: ({
|
exchangeRates: ({
|
||||||
label1: string;
|
label1: string;
|
||||||
@ -11,15 +9,5 @@ export interface AdminData {
|
|||||||
settings: { [key: string]: boolean | object | string | string[] };
|
settings: { [key: string]: boolean | object | string | string[] };
|
||||||
transactionCount: number;
|
transactionCount: number;
|
||||||
userCount: number;
|
userCount: number;
|
||||||
users: {
|
|
||||||
accountCount: number;
|
|
||||||
country: string;
|
|
||||||
createdAt: Date;
|
|
||||||
engagement: number;
|
|
||||||
id: string;
|
|
||||||
lastActivity: Date;
|
|
||||||
role: Role;
|
|
||||||
transactionCount: number;
|
|
||||||
}[];
|
|
||||||
version: string;
|
version: string;
|
||||||
}
|
}
|
||||||
|
14
libs/common/src/lib/interfaces/admin-users.interface.ts
Normal file
14
libs/common/src/lib/interfaces/admin-users.interface.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Role } from '@prisma/client';
|
||||||
|
|
||||||
|
export interface AdminUsers {
|
||||||
|
users: {
|
||||||
|
accountCount: number;
|
||||||
|
country: string;
|
||||||
|
createdAt: Date;
|
||||||
|
engagement: number;
|
||||||
|
id: string;
|
||||||
|
lastActivity: Date;
|
||||||
|
role: Role;
|
||||||
|
transactionCount: number;
|
||||||
|
}[];
|
||||||
|
}
|
@ -7,6 +7,7 @@ import type {
|
|||||||
AdminMarketData,
|
AdminMarketData,
|
||||||
AdminMarketDataItem
|
AdminMarketDataItem
|
||||||
} from './admin-market-data.interface';
|
} from './admin-market-data.interface';
|
||||||
|
import type { AdminUsers } from './admin-users.interface';
|
||||||
import type { AssetProfileIdentifier } from './asset-profile-identifier.interface';
|
import type { AssetProfileIdentifier } from './asset-profile-identifier.interface';
|
||||||
import type { BenchmarkMarketDataDetails } from './benchmark-market-data-details.interface';
|
import type { BenchmarkMarketDataDetails } from './benchmark-market-data-details.interface';
|
||||||
import type { BenchmarkProperty } from './benchmark-property.interface';
|
import type { BenchmarkProperty } from './benchmark-property.interface';
|
||||||
@ -61,6 +62,7 @@ export {
|
|||||||
AdminMarketData,
|
AdminMarketData,
|
||||||
AdminMarketDataDetails,
|
AdminMarketDataDetails,
|
||||||
AdminMarketDataItem,
|
AdminMarketDataItem,
|
||||||
|
AdminUsers,
|
||||||
AssetProfileIdentifier,
|
AssetProfileIdentifier,
|
||||||
Benchmark,
|
Benchmark,
|
||||||
BenchmarkMarketDataDetails,
|
BenchmarkMarketDataDetails,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user