diff options
author | Chocobozzz <me@florianbigard.com> | 2023-01-19 09:29:47 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2023-01-19 13:53:40 +0100 |
commit | 9589907c89d29a6c0acd52c8cb789af9f93ce9af (patch) | |
tree | f1d238e6144231bbfbed5614e05a21eca8aa6fc2 /client/src/app/+signup/shared | |
parent | b379759f55a35837b803a3b988674972db2903d1 (diff) | |
download | PeerTube-9589907c89d29a6c0acd52c8cb789af9f93ce9af.tar.gz PeerTube-9589907c89d29a6c0acd52c8cb789af9f93ce9af.tar.zst PeerTube-9589907c89d29a6c0acd52c8cb789af9f93ce9af.zip |
Implement signup approval in client
Diffstat (limited to 'client/src/app/+signup/shared')
8 files changed, 171 insertions, 44 deletions
diff --git a/client/src/app/+signup/shared/shared-signup.module.ts b/client/src/app/+signup/shared/shared-signup.module.ts index 0aa08f3e2..0600f0af8 100644 --- a/client/src/app/+signup/shared/shared-signup.module.ts +++ b/client/src/app/+signup/shared/shared-signup.module.ts | |||
@@ -5,7 +5,9 @@ import { SharedMainModule } from '@app/shared/shared-main' | |||
5 | import { SharedUsersModule } from '@app/shared/shared-users' | 5 | import { SharedUsersModule } from '@app/shared/shared-users' |
6 | import { SignupMascotComponent } from './signup-mascot.component' | 6 | import { SignupMascotComponent } from './signup-mascot.component' |
7 | import { SignupStepTitleComponent } from './signup-step-title.component' | 7 | import { SignupStepTitleComponent } from './signup-step-title.component' |
8 | import { SignupSuccessComponent } from './signup-success.component' | 8 | import { SignupSuccessBeforeEmailComponent } from './signup-success-before-email.component' |
9 | import { SignupSuccessAfterEmailComponent } from './signup-success-after-email.component' | ||
10 | import { SignupService } from './signup.service' | ||
9 | 11 | ||
10 | @NgModule({ | 12 | @NgModule({ |
11 | imports: [ | 13 | imports: [ |
@@ -16,7 +18,8 @@ import { SignupSuccessComponent } from './signup-success.component' | |||
16 | ], | 18 | ], |
17 | 19 | ||
18 | declarations: [ | 20 | declarations: [ |
19 | SignupSuccessComponent, | 21 | SignupSuccessBeforeEmailComponent, |
22 | SignupSuccessAfterEmailComponent, | ||
20 | SignupStepTitleComponent, | 23 | SignupStepTitleComponent, |
21 | SignupMascotComponent | 24 | SignupMascotComponent |
22 | ], | 25 | ], |
@@ -26,12 +29,14 @@ import { SignupSuccessComponent } from './signup-success.component' | |||
26 | SharedFormModule, | 29 | SharedFormModule, |
27 | SharedGlobalIconModule, | 30 | SharedGlobalIconModule, |
28 | 31 | ||
29 | SignupSuccessComponent, | 32 | SignupSuccessBeforeEmailComponent, |
33 | SignupSuccessAfterEmailComponent, | ||
30 | SignupStepTitleComponent, | 34 | SignupStepTitleComponent, |
31 | SignupMascotComponent | 35 | SignupMascotComponent |
32 | ], | 36 | ], |
33 | 37 | ||
34 | providers: [ | 38 | providers: [ |
39 | SignupService | ||
35 | ] | 40 | ] |
36 | }) | 41 | }) |
37 | export class SharedSignupModule { } | 42 | export class SharedSignupModule { } |
diff --git a/client/src/app/+signup/shared/signup-success-after-email.component.html b/client/src/app/+signup/shared/signup-success-after-email.component.html new file mode 100644 index 000000000..1c3536ada --- /dev/null +++ b/client/src/app/+signup/shared/signup-success-after-email.component.html | |||
@@ -0,0 +1,21 @@ | |||
1 | <my-signup-step-title mascotImageName="success"> | ||
2 | <strong i18n>Email verified!</strong> | ||
3 | </my-signup-step-title> | ||
4 | |||
5 | <div class="alert pt-alert-primary"> | ||
6 | <ng-container *ngIf="requiresApproval"> | ||
7 | <p i18n>Your email has been verified and your account request has been sent!</p> | ||
8 | |||
9 | <p i18n> | ||
10 | A moderator will check your registration request soon and you'll receive an email when it will be accepted or rejected. | ||
11 | </p> | ||
12 | </ng-container> | ||
13 | |||
14 | <ng-container *ngIf="!requiresApproval"> | ||
15 | <p i18n>Your email has been verified and your account has been created!</p> | ||
16 | |||
17 | <p i18n> | ||
18 | If you need help to use PeerTube, you can have a look at the <a class="link-orange" href="https://docs.joinpeertube.org/use-setup-account" target="_blank" rel="noopener noreferrer">documentation</a>. | ||
19 | </p> | ||
20 | </ng-container> | ||
21 | </div> | ||
diff --git a/client/src/app/+signup/shared/signup-success-after-email.component.ts b/client/src/app/+signup/shared/signup-success-after-email.component.ts new file mode 100644 index 000000000..3d72fdae9 --- /dev/null +++ b/client/src/app/+signup/shared/signup-success-after-email.component.ts | |||
@@ -0,0 +1,10 @@ | |||
1 | import { Component, Input } from '@angular/core' | ||
2 | |||
3 | @Component({ | ||
4 | selector: 'my-signup-success-after-email', | ||
5 | templateUrl: './signup-success-after-email.component.html', | ||
6 | styleUrls: [ './signup-success.component.scss' ] | ||
7 | }) | ||
8 | export class SignupSuccessAfterEmailComponent { | ||
9 | @Input() requiresApproval: boolean | ||
10 | } | ||
diff --git a/client/src/app/+signup/shared/signup-success-before-email.component.html b/client/src/app/+signup/shared/signup-success-before-email.component.html new file mode 100644 index 000000000..b9668ee82 --- /dev/null +++ b/client/src/app/+signup/shared/signup-success-before-email.component.html | |||
@@ -0,0 +1,35 @@ | |||
1 | <my-signup-step-title mascotImageName="success"> | ||
2 | <ng-container *ngIf="requiresApproval"> | ||
3 | <strong i18n>Account request sent</strong> | ||
4 | </ng-container> | ||
5 | |||
6 | <ng-container *ngIf="!requiresApproval" i18n> | ||
7 | <strong>Welcome</strong> | ||
8 | <div>on {{ instanceName }}</div> | ||
9 | </ng-container> | ||
10 | </my-signup-step-title> | ||
11 | |||
12 | <div class="alert pt-alert-primary"> | ||
13 | <p *ngIf="requiresApproval" i18n>Your account request has been sent!</p> | ||
14 | <p *ngIf="!requiresApproval" i18n>Your account has been created!</p> | ||
15 | |||
16 | <ng-container *ngIf="requiresEmailVerification"> | ||
17 | <p i18n *ngIf="requiresApproval"> | ||
18 | <strong>Check your emails</strong> to validate your account and complete your registration request. | ||
19 | </p> | ||
20 | |||
21 | <p i18n *ngIf="!requiresApproval"> | ||
22 | <strong>Check your emails</strong> to validate your account and complete your registration. | ||
23 | </p> | ||
24 | </ng-container> | ||
25 | |||
26 | <ng-container *ngIf="!requiresEmailVerification"> | ||
27 | <p i18n *ngIf="requiresApproval"> | ||
28 | A moderator will check your registration request soon and you'll receive an email when it will be accepted or rejected. | ||
29 | </p> | ||
30 | |||
31 | <p *ngIf="!requiresApproval" i18n> | ||
32 | If you need help to use PeerTube, you can have a look at the <a class="link-orange" href="https://docs.joinpeertube.org/use-setup-account" target="_blank" rel="noopener noreferrer">documentation</a>. | ||
33 | </p> | ||
34 | </ng-container> | ||
35 | </div> | ||
diff --git a/client/src/app/+signup/shared/signup-success-before-email.component.ts b/client/src/app/+signup/shared/signup-success-before-email.component.ts new file mode 100644 index 000000000..d72462340 --- /dev/null +++ b/client/src/app/+signup/shared/signup-success-before-email.component.ts | |||
@@ -0,0 +1,12 @@ | |||
1 | import { Component, Input } from '@angular/core' | ||
2 | |||
3 | @Component({ | ||
4 | selector: 'my-signup-success-before-email', | ||
5 | templateUrl: './signup-success-before-email.component.html', | ||
6 | styleUrls: [ './signup-success.component.scss' ] | ||
7 | }) | ||
8 | export class SignupSuccessBeforeEmailComponent { | ||
9 | @Input() requiresApproval: boolean | ||
10 | @Input() requiresEmailVerification: boolean | ||
11 | @Input() instanceName: string | ||
12 | } | ||
diff --git a/client/src/app/+signup/shared/signup-success.component.html b/client/src/app/+signup/shared/signup-success.component.html deleted file mode 100644 index c14889c72..000000000 --- a/client/src/app/+signup/shared/signup-success.component.html +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | <my-signup-step-title mascotImageName="success" i18n> | ||
2 | <strong>Welcome</strong> | ||
3 | <div>on {{ instanceName }}</div> | ||
4 | </my-signup-step-title> | ||
5 | |||
6 | <div class="alert pt-alert-primary"> | ||
7 | <p i18n>Your account has been created!</p> | ||
8 | |||
9 | <p i18n *ngIf="requiresEmailVerification"> | ||
10 | <strong>Check your emails</strong> to validate your account and complete your inscription. | ||
11 | </p> | ||
12 | |||
13 | <ng-container *ngIf="!requiresEmailVerification"> | ||
14 | <p i18n> | ||
15 | If you need help to use PeerTube, you can have a look at the <a class="link-orange" href="https://docs.joinpeertube.org/use-setup-account" target="_blank" rel="noopener noreferrer">documentation</a>. | ||
16 | </p> | ||
17 | |||
18 | <p i18n> | ||
19 | To help moderators and other users to know <strong>who you are</strong>, don't forget to <a class="link-orange" routerLink="/my-account/settings">set up your account profile</a> by adding an <strong>avatar</strong> and a <strong>description</strong>. | ||
20 | </p> | ||
21 | </ng-container> | ||
22 | </div> | ||
diff --git a/client/src/app/+signup/shared/signup-success.component.ts b/client/src/app/+signup/shared/signup-success.component.ts deleted file mode 100644 index a03f3819d..000000000 --- a/client/src/app/+signup/shared/signup-success.component.ts +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | import { Component, Input } from '@angular/core' | ||
2 | import { ServerService } from '@app/core' | ||
3 | |||
4 | @Component({ | ||
5 | selector: 'my-signup-success', | ||
6 | templateUrl: './signup-success.component.html', | ||
7 | styleUrls: [ './signup-success.component.scss' ] | ||
8 | }) | ||
9 | export class SignupSuccessComponent { | ||
10 | @Input() requiresEmailVerification: boolean | ||
11 | |||
12 | constructor (private serverService: ServerService) { | ||
13 | |||
14 | } | ||
15 | |||
16 | get instanceName () { | ||
17 | return this.serverService.getHTMLConfig().instance.name | ||
18 | } | ||
19 | } | ||
diff --git a/client/src/app/+signup/shared/signup.service.ts b/client/src/app/+signup/shared/signup.service.ts new file mode 100644 index 000000000..f647298be --- /dev/null +++ b/client/src/app/+signup/shared/signup.service.ts | |||
@@ -0,0 +1,85 @@ | |||
1 | import { catchError, tap } from 'rxjs/operators' | ||
2 | import { HttpClient } from '@angular/common/http' | ||
3 | import { Injectable } from '@angular/core' | ||
4 | import { RestExtractor, UserService } from '@app/core' | ||
5 | import { UserRegister, UserRegistrationRequest } from '@shared/models' | ||
6 | |||
7 | @Injectable() | ||
8 | export class SignupService { | ||
9 | |||
10 | constructor ( | ||
11 | private authHttp: HttpClient, | ||
12 | private restExtractor: RestExtractor, | ||
13 | private userService: UserService | ||
14 | ) { } | ||
15 | |||
16 | directSignup (userCreate: UserRegister) { | ||
17 | return this.authHttp.post(UserService.BASE_USERS_URL + 'register', userCreate) | ||
18 | .pipe( | ||
19 | tap(() => this.userService.setSignupInThisSession(true)), | ||
20 | catchError(err => this.restExtractor.handleError(err)) | ||
21 | ) | ||
22 | } | ||
23 | |||
24 | requestSignup (userCreate: UserRegistrationRequest) { | ||
25 | return this.authHttp.post(UserService.BASE_USERS_URL + 'registrations/request', userCreate) | ||
26 | .pipe(catchError(err => this.restExtractor.handleError(err))) | ||
27 | } | ||
28 | |||
29 | // --------------------------------------------------------------------------- | ||
30 | |||
31 | verifyUserEmail (options: { | ||
32 | userId: number | ||
33 | verificationString: string | ||
34 | isPendingEmail: boolean | ||
35 | }) { | ||
36 | const { userId, verificationString, isPendingEmail } = options | ||
37 | |||
38 | const url = `${UserService.BASE_USERS_URL}${userId}/verify-email` | ||
39 | const body = { | ||
40 | verificationString, | ||
41 | isPendingEmail | ||
42 | } | ||
43 | |||
44 | return this.authHttp.post(url, body) | ||
45 | .pipe(catchError(res => this.restExtractor.handleError(res))) | ||
46 | } | ||
47 | |||
48 | verifyRegistrationEmail (options: { | ||
49 | registrationId: number | ||
50 | verificationString: string | ||
51 | }) { | ||
52 | const { registrationId, verificationString } = options | ||
53 | |||
54 | const url = `${UserService.BASE_USERS_URL}registrations/${registrationId}/verify-email` | ||
55 | const body = { verificationString } | ||
56 | |||
57 | return this.authHttp.post(url, body) | ||
58 | .pipe(catchError(res => this.restExtractor.handleError(res))) | ||
59 | } | ||
60 | |||
61 | askSendVerifyEmail (email: string) { | ||
62 | const url = UserService.BASE_USERS_URL + 'ask-send-verify-email' | ||
63 | |||
64 | return this.authHttp.post(url, { email }) | ||
65 | .pipe(catchError(err => this.restExtractor.handleError(err))) | ||
66 | } | ||
67 | |||
68 | // --------------------------------------------------------------------------- | ||
69 | |||
70 | getNewUsername (oldDisplayName: string, newDisplayName: string, currentUsername: string) { | ||
71 | // Don't update display name, the user seems to have changed it | ||
72 | if (this.displayNameToUsername(oldDisplayName) !== currentUsername) return currentUsername | ||
73 | |||
74 | return this.displayNameToUsername(newDisplayName) | ||
75 | } | ||
76 | |||
77 | private displayNameToUsername (displayName: string) { | ||
78 | if (!displayName) return '' | ||
79 | |||
80 | return displayName | ||
81 | .toLowerCase() | ||
82 | .replace(/\s/g, '_') | ||
83 | .replace(/[^a-z0-9_.]/g, '') | ||
84 | } | ||
85 | } | ||