Browse Source

Block new user signup from backend during third party login

pull/1512/head
gobdevel 3 years ago
parent
commit
0a08a41094
  1. 4
      apps/api/src/app/auth/auth.module.ts
  2. 29
      apps/api/src/app/auth/auth.service.ts
  3. 13
      apps/api/src/app/user/user.service.ts
  4. 3
      apps/client/src/app/components/header/header.component.html
  5. 6
      apps/client/src/app/pages/landing/landing-page.component.ts
  6. 4
      apps/client/src/app/pages/landing/landing-page.html

4
apps/api/src/app/auth/auth.module.ts

@ -3,6 +3,7 @@ import { WebAuthService } from '@ghostfolio/api/app/auth/web-auth.service';
import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module'; import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module';
import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module';
import { PropertyModule } from '@ghostfolio/api/services/property/property.module';
import { PrismaModule } from '@ghostfolio/api/services/prisma.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma.module';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt'; import { JwtModule } from '@nestjs/jwt';
@ -22,7 +23,8 @@ import { JwtStrategy } from './jwt.strategy';
}), }),
PrismaModule, PrismaModule,
SubscriptionModule, SubscriptionModule,
UserModule UserModule,
PropertyModule
], ],
providers: [ providers: [
AuthDeviceService, AuthDeviceService,

29
apps/api/src/app/auth/auth.service.ts

@ -1,15 +1,18 @@
import { UserService } from '@ghostfolio/api/app/user/user.service'; import { UserService } from '@ghostfolio/api/app/user/user.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
import { Injectable, InternalServerErrorException } from '@nestjs/common'; import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt'; import { JwtService } from '@nestjs/jwt';
import { Provider } from '@prisma/client'; import { Provider } from '@prisma/client';
import { ValidateOAuthLoginParams } from './interfaces/interfaces'; import { ValidateOAuthLoginParams } from './interfaces/interfaces';
import { PROPERTY_DISABLE_USER_SIGNUP } from '@ghostfolio/common/config';
@Injectable() @Injectable()
export class AuthService { export class AuthService {
public constructor( public constructor(
private readonly configurationService: ConfigurationService, private readonly configurationService: ConfigurationService,
private readonly propertyService: PropertyService,
private readonly jwtService: JwtService, private readonly jwtService: JwtService,
private readonly userService: UserService private readonly userService: UserService
) {} ) {}
@ -50,6 +53,19 @@ export class AuthService {
}); });
if (!user) { if (!user) {
// Guard new user registration based on config property
if (this.configurationService.get('ENABLE_FEATURE_USER_SIGNUP_CONTROL')) {
const isUserSignupDisabled = (await this.propertyService.getByKey(
PROPERTY_DISABLE_USER_SIGNUP
)) as boolean;
if(isUserSignupDisabled){
throw new InternalServerErrorException(
'validateInternetIdentityLogin',
'Not Allowed'
);
}
}
// Create new user if not found // Create new user if not found
user = await this.userService.createUser({ user = await this.userService.createUser({
provider, provider,
@ -78,6 +94,19 @@ export class AuthService {
}); });
if (!user) { if (!user) {
// Guard new user registration based on config property
if (this.configurationService.get('ENABLE_FEATURE_USER_SIGNUP_CONTROL')) {
const isUserSignupDisabled = (await this.propertyService.getByKey(
PROPERTY_DISABLE_USER_SIGNUP
)) as boolean;
if(isUserSignupDisabled){
throw new InternalServerErrorException(
'validateInternetIdentityLogin',
'Not Allowed'
);
}
}
// Create new user if not found // Create new user if not found
user = await this.userService.createUser({ user = await this.userService.createUser({
provider, provider,

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

@ -165,6 +165,12 @@ export class UserService {
currentPermissions.push(permissions.reportDataGlitch); currentPermissions.push(permissions.reportDataGlitch);
} }
if (this.configurationService.get('ENABLE_FEATURE_USER_SIGNUP_CONTROL')) {
if (hasRole(user, Role.ADMIN)) {
currentPermissions.push(permissions.toggleUserSignupMode);
}
}
if (this.configurationService.get('ENABLE_FEATURE_READ_ONLY_MODE')) { if (this.configurationService.get('ENABLE_FEATURE_READ_ONLY_MODE')) {
if (hasRole(user, Role.ADMIN)) { if (hasRole(user, Role.ADMIN)) {
currentPermissions.push(permissions.toggleReadOnlyMode); currentPermissions.push(permissions.toggleReadOnlyMode);
@ -185,12 +191,6 @@ export class UserService {
} }
} }
if (this.configurationService.get('ENABLE_FEATURE_USER_SIGNUP_CONTROL')) {
if (hasRole(user, Role.ADMIN)) {
currentPermissions.push(permissions.toggleUserSignupMode);
}
}
user.Account = sortBy(user.Account, (account) => { user.Account = sortBy(user.Account, (account) => {
return account.name; return account.name;
}); });
@ -224,6 +224,7 @@ export class UserService {
} }
public async createUser(data: Prisma.UserCreateInput): Promise<User> { public async createUser(data: Prisma.UserCreateInput): Promise<User> {
if (!data?.provider) { if (!data?.provider) {
data.provider = 'ANONYMOUS'; data.provider = 'ANONYMOUS';
} }

3
apps/client/src/app/components/header/header.component.html

@ -289,7 +289,8 @@
<ng-container i18n>Sign in</ng-container> <ng-container i18n>Sign in</ng-container>
</button> </button>
<a <a
*ngIf="currentRoute !== 'register' && !info?.isReadOnlyMode" *ngIf="currentRoute !== 'register' && !info?.isReadOnlyMode &&
info.globalPermissions.includes('createUserAccount')"
class="d-none d-sm-block" class="d-none d-sm-block"
color="primary" color="primary"
mat-flat-button mat-flat-button

6
apps/client/src/app/pages/landing/landing-page.component.ts

@ -17,6 +17,7 @@ export class LandingPageComponent implements OnDestroy, OnInit {
public demoAuthToken: string; public demoAuthToken: string;
public deviceType: string; public deviceType: string;
public hasPermissionForStatistics: boolean; public hasPermissionForStatistics: boolean;
public hasPermissionForUserSignup: boolean;
public statistics: Statistics; public statistics: Statistics;
public testimonials = [ public testimonials = [
{ {
@ -54,6 +55,11 @@ export class LandingPageComponent implements OnDestroy, OnInit {
permissions.enableStatistics permissions.enableStatistics
); );
this.hasPermissionForUserSignup = hasPermission(
globalPermissions,
permissions.createUserAccount
);
this.statistics = statistics; this.statistics = statistics;
} }

4
apps/client/src/app/pages/landing/landing-page.html

@ -28,7 +28,7 @@
</div> </div>
<div class="container"> <div class="container">
<div class="button-container mb-5 row"> <div class="button-container mb-5 row" *ngIf="hasPermissionForUserSignup">
<div class="align-items-center col d-flex justify-content-center"> <div class="align-items-center col d-flex justify-content-center">
<div class="text-center"> <div class="text-center">
<a <a
@ -306,7 +306,7 @@
</div> </div>
</div> </div>
<div class="row my-5"> <div class="row my-5" *ngIf="hasPermissionForUserSignup">
<div class="col"> <div class="col">
<h2 class="h4 mb-1 text-center">Are <strong>you</strong> ready?</h2> <h2 class="h4 mb-1 text-center">Are <strong>you</strong> ready?</h2>
<p class="lead mb-3 text-center"> <p class="lead mb-3 text-center">

Loading…
Cancel
Save