Browse Source

Code review changes

pull/4458/head
csehatt741 1 month ago
parent
commit
641c3baaef
  1. 32
      apps/api/src/app/user/user.controller.ts
  2. 8
      apps/api/src/app/user/user.service.ts
  3. 9
      apps/client/src/app/components/admin-users/admin-users.component.ts
  4. 2
      apps/client/src/app/components/admin-users/admin-users.html
  5. 16
      apps/client/src/app/services/data.service.ts
  6. 3
      libs/common/src/lib/interfaces/access-token.interface.ts
  7. 4
      libs/common/src/lib/interfaces/index.ts
  8. 3
      libs/common/src/lib/interfaces/responses/access-token-response.interface.ts

32
apps/api/src/app/user/user.controller.ts

@ -2,7 +2,11 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorat
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service';
import { AccessToken, User, UserSettings } from '@ghostfolio/common/interfaces'; import {
AccessTokenResponse,
User,
UserSettings
} from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import type { RequestWithUser } from '@ghostfolio/common/types'; import type { RequestWithUser } from '@ghostfolio/common/types';
@ -85,6 +89,19 @@ export class UserController {
}); });
} }
@Post(':id/access-token')
@HasPermission(permissions.accessAdminControl)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async generateAccessToken(
@Param('id') id: string
): Promise<AccessTokenResponse> {
const { accessToken } = await this.userService.generateAccessToken({
userId: id
});
return { accessToken };
}
@Get() @Get()
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async getUser( public async getUser(
@ -123,19 +140,6 @@ export class UserController {
}; };
} }
@Post(':id/security-token')
@HasPermission(permissions.accessAdminControl)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async generateSecurityToken(
@Param('id') id: string
): Promise<AccessToken> {
const accessToken = await this.userService.generateAccessToken({
userId: id
});
return { accessToken };
}
@Put('setting') @Put('setting')
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async updateUserSetting(@Body() data: UpdateUserSettingDto) { public async updateUserSetting(@Body() data: UpdateUserSettingDto) {

8
apps/api/src/app/user/user.service.ts

@ -464,7 +464,9 @@ export class UserService {
} }
if (data.provider === 'ANONYMOUS') { if (data.provider === 'ANONYMOUS') {
const accessToken = await this.generateAccessToken({ userId: user.id }); const { accessToken } = await this.generateAccessToken({
userId: user.id
});
return { ...user, accessToken }; return { ...user, accessToken };
} }
@ -576,7 +578,7 @@ export class UserService {
userId userId
}: { }: {
userId: string; userId: string;
}): Promise<string> { }): Promise<{ accessToken: string }> {
const accessToken = this.createAccessToken(userId, getRandomString(10)); const accessToken = this.createAccessToken(userId, getRandomString(10));
const hashedAccessToken = this.createAccessToken( const hashedAccessToken = this.createAccessToken(
@ -589,6 +591,6 @@ export class UserService {
where: { id: userId } where: { id: userId }
}); });
return accessToken; return { accessToken };
} }
} }

9
apps/client/src/app/components/admin-users/admin-users.component.ts

@ -141,16 +141,15 @@ export class AdminUsersComponent implements OnDestroy, OnInit {
}); });
} }
public onGenerateSecurityToken(aId: string) { public onGenerateAccessToken(aId: string) {
this.notificationService.confirm({ this.notificationService.confirm({
confirmFn: () => { confirmFn: () => {
this.dataService this.dataService
.generateSecurityToken(aId) .generateAccessToken(aId)
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ accessToken }) => { .subscribe(({ accessToken }) => {
this.notificationService.prompt({ this.notificationService.alert({
confirmFn: () => undefined, message: accessToken,
defaultValue: accessToken,
title: $localize`Security token` title: $localize`Security token`
}); });
}); });

2
apps/client/src/app/components/admin-users/admin-users.html

@ -243,7 +243,7 @@
} }
<button <button
mat-menu-item mat-menu-item
(click)="onGenerateSecurityToken(element.id)" (click)="onGenerateAccessToken(element.id)"
> >
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">
<ion-icon class="mr-2" name="key-outline" /> <ion-icon class="mr-2" name="key-outline" />

16
apps/client/src/app/services/data.service.ts

@ -22,7 +22,7 @@ import { PropertyDto } from '@ghostfolio/api/services/property/property.dto';
import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { import {
Access, Access,
AccessToken, AccessTokenResponse,
AccountBalancesResponse, AccountBalancesResponse,
Accounts, Accounts,
AiPromptResponse, AiPromptResponse,
@ -325,13 +325,6 @@ export class DataService {
return this.http.delete<any>(`/api/v1/user/${aId}`); return this.http.delete<any>(`/api/v1/user/${aId}`);
} }
public generateSecurityToken(aId: string) {
return this.http.post<AccessToken>(
`/api/v1/user/${aId}/security-token`,
{}
);
}
public fetchAccesses() { public fetchAccesses() {
return this.http.get<Access[]>('/api/v1/access'); return this.http.get<Access[]>('/api/v1/access');
} }
@ -699,6 +692,13 @@ export class DataService {
return this.http.get<Tag[]>('/api/v1/tags'); return this.http.get<Tag[]>('/api/v1/tags');
} }
public generateAccessToken(aId: string) {
return this.http.post<AccessTokenResponse>(
`/api/v1/user/${aId}/access-token`,
{}
);
}
public loginAnonymous(accessToken: string) { public loginAnonymous(accessToken: string) {
return this.http.post<OAuthResponse>('/api/v1/auth/anonymous', { return this.http.post<OAuthResponse>('/api/v1/auth/anonymous', {
accessToken accessToken

3
libs/common/src/lib/interfaces/access-token.interface.ts

@ -1,3 +0,0 @@
export interface AccessToken {
accessToken: string;
}

4
libs/common/src/lib/interfaces/index.ts

@ -1,4 +1,3 @@
import type { AccessToken } from './access-token.interface';
import type { Access } from './access.interface'; import type { Access } from './access.interface';
import type { AccountBalance } from './account-balance.interface'; import type { AccountBalance } from './account-balance.interface';
import type { Accounts } from './accounts.interface'; import type { Accounts } from './accounts.interface';
@ -39,6 +38,7 @@ import type { PortfolioReportRule } from './portfolio-report-rule.interface';
import type { PortfolioSummary } from './portfolio-summary.interface'; import type { PortfolioSummary } from './portfolio-summary.interface';
import type { Position } from './position.interface'; import type { Position } from './position.interface';
import type { Product } from './product'; import type { Product } from './product';
import type { AccessTokenResponse } from './responses/access-token-response.interface';
import type { AccountBalancesResponse } from './responses/account-balances-response.interface'; import type { AccountBalancesResponse } from './responses/account-balances-response.interface';
import type { AiPromptResponse } from './responses/ai-prompt-response.interface'; import type { AiPromptResponse } from './responses/ai-prompt-response.interface';
import type { ApiKeyResponse } from './responses/api-key-response.interface'; import type { ApiKeyResponse } from './responses/api-key-response.interface';
@ -70,7 +70,7 @@ import type { XRayRulesSettings } from './x-ray-rules-settings.interface';
export { export {
Access, Access,
AccessToken, AccessTokenResponse,
AccountBalance, AccountBalance,
AccountBalancesResponse, AccountBalancesResponse,
Accounts, Accounts,

3
libs/common/src/lib/interfaces/responses/access-token-response.interface.ts

@ -0,0 +1,3 @@
export interface AccessTokenResponse {
accessToken: string;
}
Loading…
Cancel
Save