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 | |
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')
21 files changed, 379 insertions, 102 deletions
diff --git a/client/src/app/+signup/+register/register.component.html b/client/src/app/+signup/+register/register.component.html index bafb96a49..86763e801 100644 --- a/client/src/app/+signup/+register/register.component.html +++ b/client/src/app/+signup/+register/register.component.html | |||
@@ -5,29 +5,34 @@ | |||
5 | </div> | 5 | </div> |
6 | 6 | ||
7 | <ng-container *ngIf="!signupDisabled"> | 7 | <ng-container *ngIf="!signupDisabled"> |
8 | <h1 i18n class="title-page-v2"> | 8 | <h1 class="title-page-v2"> |
9 | <strong class="underline-orange">{{ instanceName }}</strong> | 9 | <strong class="underline-orange">{{ instanceName }}</strong> |
10 | > | 10 | > |
11 | Create an account | 11 | <my-signup-label [requiresApproval]="requiresApproval"></my-signup-label> |
12 | </h1> | 12 | </h1> |
13 | 13 | ||
14 | <div class="register-content"> | 14 | <div class="register-content"> |
15 | <my-custom-stepper linear> | 15 | <my-custom-stepper linear> |
16 | 16 | ||
17 | <cdk-step i18n-label label="About" [editable]="!signupSuccess"> | 17 | <cdk-step i18n-label label="About" [editable]="!signupSuccess"> |
18 | <my-signup-step-title mascotImageName="about" i18n> | 18 | <my-signup-step-title mascotImageName="about"> |
19 | <strong>Create an account</strong> | 19 | <strong> |
20 | <div>on {{ instanceName }}</div> | 20 | <my-signup-label [requiresApproval]="requiresApproval"></my-signup-label> |
21 | </strong> | ||
22 | |||
23 | <div i18n>on {{ instanceName }}</div> | ||
21 | </my-signup-step-title> | 24 | </my-signup-step-title> |
22 | 25 | ||
23 | <my-register-step-about [videoUploadDisabled]="videoUploadDisabled"></my-register-step-about> | 26 | <my-register-step-about [requiresApproval]="requiresApproval" [videoUploadDisabled]="videoUploadDisabled"></my-register-step-about> |
24 | 27 | ||
25 | <div class="step-buttons"> | 28 | <div class="step-buttons"> |
26 | <a i18n class="skip-step underline-orange" routerLink="/login"> | 29 | <a i18n class="skip-step underline-orange" routerLink="/login"> |
27 | <strong>I already have an account</strong>, I log in | 30 | <strong>I already have an account</strong>, I log in |
28 | </a> | 31 | </a> |
29 | 32 | ||
30 | <button i18n cdkStepperNext>Create an account</button> | 33 | <button cdkStepperNext> |
34 | <my-signup-label [requiresApproval]="requiresApproval"></my-signup-label> | ||
35 | </button> | ||
31 | </div> | 36 | </div> |
32 | </cdk-step> | 37 | </cdk-step> |
33 | 38 | ||
@@ -44,8 +49,8 @@ | |||
44 | ></my-instance-about-accordion> | 49 | ></my-instance-about-accordion> |
45 | 50 | ||
46 | <my-register-step-terms | 51 | <my-register-step-terms |
47 | [hasCodeOfConduct]="!!aboutHtml.codeOfConduct" | 52 | [hasCodeOfConduct]="!!aboutHtml.codeOfConduct" [minimumAge]="minimumAge" [instanceName]="instanceName" |
48 | [minimumAge]="minimumAge" | 53 | [requiresApproval]="requiresApproval" |
49 | (formBuilt)="onTermsFormBuilt($event)" (termsClick)="onTermsClick()" (codeOfConductClick)="onCodeOfConductClick()" | 54 | (formBuilt)="onTermsFormBuilt($event)" (termsClick)="onTermsClick()" (codeOfConductClick)="onCodeOfConductClick()" |
50 | ></my-register-step-terms> | 55 | ></my-register-step-terms> |
51 | 56 | ||
@@ -94,14 +99,15 @@ | |||
94 | <div class="skip-step-description" i18n>You will be able to create a channel later</div> | 99 | <div class="skip-step-description" i18n>You will be able to create a channel later</div> |
95 | </div> | 100 | </div> |
96 | 101 | ||
97 | <button cdkStepperNext [disabled]="!formStepChannel || !formStepChannel.valid || hasSameChannelAndAccountNames()" (click)="signup()" i18n> | 102 | <button cdkStepperNext [disabled]="!formStepChannel || !formStepChannel.valid || hasSameChannelAndAccountNames()" (click)="signup()"> |
98 | Create my account | 103 | <my-signup-label [requiresApproval]="requiresApproval"></my-signup-label> |
99 | </button> | 104 | </button> |
100 | </div> | 105 | </div> |
101 | </cdk-step> | 106 | </cdk-step> |
102 | 107 | ||
103 | <cdk-step #lastStep i18n-label label="Done!" [editable]="false"> | 108 | <cdk-step #lastStep i18n-label label="Done!" [editable]="false"> |
104 | <div *ngIf="!signupSuccess && !signupError" class="done-loader"> | 109 | <!-- Account creation can be a little bit long so display a loader --> |
110 | <div *ngIf="!requiresApproval && !signupSuccess && !signupError" class="done-loader"> | ||
105 | <my-loader [loading]="true"></my-loader> | 111 | <my-loader [loading]="true"></my-loader> |
106 | 112 | ||
107 | <div i18n>PeerTube is creating your account...</div> | 113 | <div i18n>PeerTube is creating your account...</div> |
@@ -109,7 +115,10 @@ | |||
109 | 115 | ||
110 | <div *ngIf="signupError" class="alert alert-danger">{{ signupError }}</div> | 116 | <div *ngIf="signupError" class="alert alert-danger">{{ signupError }}</div> |
111 | 117 | ||
112 | <my-signup-success *ngIf="signupSuccess" [requiresEmailVerification]="requiresEmailVerification"></my-signup-success> | 118 | <my-signup-success-before-email |
119 | *ngIf="signupSuccess" | ||
120 | [requiresEmailVerification]="requiresEmailVerification" [requiresApproval]="requiresApproval" [instanceName]="instanceName" | ||
121 | ></my-signup-success-before-email> | ||
113 | 122 | ||
114 | <div *ngIf="signupError" class="steps-button"> | 123 | <div *ngIf="signupError" class="steps-button"> |
115 | <button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button> | 124 | <button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button> |
diff --git a/client/src/app/+signup/+register/register.component.ts b/client/src/app/+signup/+register/register.component.ts index 958770ebf..9259d902c 100644 --- a/client/src/app/+signup/+register/register.component.ts +++ b/client/src/app/+signup/+register/register.component.ts | |||
@@ -5,10 +5,10 @@ import { ActivatedRoute } from '@angular/router' | |||
5 | import { AuthService } from '@app/core' | 5 | import { AuthService } from '@app/core' |
6 | import { HooksService } from '@app/core/plugins/hooks.service' | 6 | import { HooksService } from '@app/core/plugins/hooks.service' |
7 | import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance' | 7 | import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance' |
8 | import { UserSignupService } from '@app/shared/shared-users' | ||
9 | import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap' | 8 | import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap' |
10 | import { UserRegister } from '@shared/models' | 9 | import { UserRegister } from '@shared/models' |
11 | import { ServerConfig } from '@shared/models/server' | 10 | import { ServerConfig } from '@shared/models/server' |
11 | import { SignupService } from '../shared/signup.service' | ||
12 | 12 | ||
13 | @Component({ | 13 | @Component({ |
14 | selector: 'my-register', | 14 | selector: 'my-register', |
@@ -53,7 +53,7 @@ export class RegisterComponent implements OnInit { | |||
53 | constructor ( | 53 | constructor ( |
54 | private route: ActivatedRoute, | 54 | private route: ActivatedRoute, |
55 | private authService: AuthService, | 55 | private authService: AuthService, |
56 | private userSignupService: UserSignupService, | 56 | private signupService: SignupService, |
57 | private hooks: HooksService | 57 | private hooks: HooksService |
58 | ) { } | 58 | ) { } |
59 | 59 | ||
@@ -61,6 +61,10 @@ export class RegisterComponent implements OnInit { | |||
61 | return this.serverConfig.signup.requiresEmailVerification | 61 | return this.serverConfig.signup.requiresEmailVerification |
62 | } | 62 | } |
63 | 63 | ||
64 | get requiresApproval () { | ||
65 | return this.serverConfig.signup.requiresApproval | ||
66 | } | ||
67 | |||
64 | get minimumAge () { | 68 | get minimumAge () { |
65 | return this.serverConfig.signup.minimumAge | 69 | return this.serverConfig.signup.minimumAge |
66 | } | 70 | } |
@@ -132,42 +136,49 @@ export class RegisterComponent implements OnInit { | |||
132 | skipChannelCreation () { | 136 | skipChannelCreation () { |
133 | this.formStepChannel.reset() | 137 | this.formStepChannel.reset() |
134 | this.lastStep.select() | 138 | this.lastStep.select() |
139 | |||
135 | this.signup() | 140 | this.signup() |
136 | } | 141 | } |
137 | 142 | ||
138 | async signup () { | 143 | async signup () { |
139 | this.signupError = undefined | 144 | this.signupError = undefined |
140 | 145 | ||
141 | const body: UserRegister = await this.hooks.wrapObject( | 146 | const termsForm = this.formStepTerms.value |
147 | const userForm = this.formStepUser.value | ||
148 | const channelForm = this.formStepChannel?.value | ||
149 | |||
150 | const channel = this.formStepChannel?.value?.name | ||
151 | ? { name: channelForm?.name, displayName: channelForm?.displayName } | ||
152 | : undefined | ||
153 | |||
154 | const body = await this.hooks.wrapObject( | ||
142 | { | 155 | { |
143 | ...this.formStepUser.value, | 156 | username: userForm.username, |
157 | password: userForm.password, | ||
158 | email: userForm.email, | ||
159 | displayName: userForm.displayName, | ||
160 | |||
161 | registrationReason: termsForm.registrationReason, | ||
144 | 162 | ||
145 | channel: this.formStepChannel?.value?.name | 163 | channel |
146 | ? this.formStepChannel.value | ||
147 | : undefined | ||
148 | }, | 164 | }, |
149 | 'signup', | 165 | 'signup', |
150 | 'filter:api.signup.registration.create.params' | 166 | 'filter:api.signup.registration.create.params' |
151 | ) | 167 | ) |
152 | 168 | ||
153 | this.userSignupService.signup(body).subscribe({ | 169 | const obs = this.requiresApproval |
170 | ? this.signupService.requestSignup(body) | ||
171 | : this.signupService.directSignup(body) | ||
172 | |||
173 | obs.subscribe({ | ||
154 | next: () => { | 174 | next: () => { |
155 | if (this.requiresEmailVerification) { | 175 | if (this.requiresEmailVerification || this.requiresApproval) { |
156 | this.signupSuccess = true | 176 | this.signupSuccess = true |
157 | return | 177 | return |
158 | } | 178 | } |
159 | 179 | ||
160 | // Auto login | 180 | // Auto login |
161 | this.authService.login({ username: body.username, password: body.password }) | 181 | this.autoLogin(body) |
162 | .subscribe({ | ||
163 | next: () => { | ||
164 | this.signupSuccess = true | ||
165 | }, | ||
166 | |||
167 | error: err => { | ||
168 | this.signupError = err.message | ||
169 | } | ||
170 | }) | ||
171 | }, | 182 | }, |
172 | 183 | ||
173 | error: err => { | 184 | error: err => { |
@@ -175,4 +186,17 @@ export class RegisterComponent implements OnInit { | |||
175 | } | 186 | } |
176 | }) | 187 | }) |
177 | } | 188 | } |
189 | |||
190 | private autoLogin (body: UserRegister) { | ||
191 | this.authService.login({ username: body.username, password: body.password }) | ||
192 | .subscribe({ | ||
193 | next: () => { | ||
194 | this.signupSuccess = true | ||
195 | }, | ||
196 | |||
197 | error: err => { | ||
198 | this.signupError = err.message | ||
199 | } | ||
200 | }) | ||
201 | } | ||
178 | } | 202 | } |
diff --git a/client/src/app/+signup/+register/shared/index.ts b/client/src/app/+signup/+register/shared/index.ts new file mode 100644 index 000000000..affb54bf4 --- /dev/null +++ b/client/src/app/+signup/+register/shared/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './register-validators' | |||
diff --git a/client/src/app/+signup/+register/shared/register-validators.ts b/client/src/app/+signup/+register/shared/register-validators.ts new file mode 100644 index 000000000..f14803b68 --- /dev/null +++ b/client/src/app/+signup/+register/shared/register-validators.ts | |||
@@ -0,0 +1,18 @@ | |||
1 | import { Validators } from '@angular/forms' | ||
2 | import { BuildFormValidator } from '@app/shared/form-validators' | ||
3 | |||
4 | export const REGISTER_TERMS_VALIDATOR: BuildFormValidator = { | ||
5 | VALIDATORS: [ Validators.requiredTrue ], | ||
6 | MESSAGES: { | ||
7 | required: $localize`You must agree with the instance terms in order to register on it.` | ||
8 | } | ||
9 | } | ||
10 | |||
11 | export const REGISTER_REASON_VALIDATOR: BuildFormValidator = { | ||
12 | VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ], | ||
13 | MESSAGES: { | ||
14 | required: $localize`Registration reason is required.`, | ||
15 | minlength: $localize`Registration reason must be at least 2 characters long.`, | ||
16 | maxlength: $localize`Registration reason cannot be more than 3000 characters long.` | ||
17 | } | ||
18 | } | ||
diff --git a/client/src/app/+signup/+register/steps/register-step-about.component.html b/client/src/app/+signup/+register/steps/register-step-about.component.html index 769fe3127..580e8a92c 100644 --- a/client/src/app/+signup/+register/steps/register-step-about.component.html +++ b/client/src/app/+signup/+register/steps/register-step-about.component.html | |||
@@ -13,6 +13,10 @@ | |||
13 | <li i18n>Have access to your <strong>watch history</strong></li> | 13 | <li i18n>Have access to your <strong>watch history</strong></li> |
14 | <li *ngIf="!videoUploadDisabled" i18n>Create your channel to <strong>publish videos</strong></li> | 14 | <li *ngIf="!videoUploadDisabled" i18n>Create your channel to <strong>publish videos</strong></li> |
15 | </ul> | 15 | </ul> |
16 | |||
17 | <p *ngIf="requiresApproval" i18n> | ||
18 | Moderators of {{ instanceName }} will have to approve your registration request once you have finished to fill the form. | ||
19 | </p> | ||
16 | </div> | 20 | </div> |
17 | 21 | ||
18 | <div> | 22 | <div> |
diff --git a/client/src/app/+signup/+register/steps/register-step-about.component.ts b/client/src/app/+signup/+register/steps/register-step-about.component.ts index 9a0941016..b176ffa59 100644 --- a/client/src/app/+signup/+register/steps/register-step-about.component.ts +++ b/client/src/app/+signup/+register/steps/register-step-about.component.ts | |||
@@ -7,6 +7,7 @@ import { ServerService } from '@app/core' | |||
7 | styleUrls: [ './register-step-about.component.scss' ] | 7 | styleUrls: [ './register-step-about.component.scss' ] |
8 | }) | 8 | }) |
9 | export class RegisterStepAboutComponent { | 9 | export class RegisterStepAboutComponent { |
10 | @Input() requiresApproval: boolean | ||
10 | @Input() videoUploadDisabled: boolean | 11 | @Input() videoUploadDisabled: boolean |
11 | 12 | ||
12 | constructor (private serverService: ServerService) { | 13 | constructor (private serverService: ServerService) { |
diff --git a/client/src/app/+signup/+register/steps/register-step-channel.component.ts b/client/src/app/+signup/+register/steps/register-step-channel.component.ts index df92c5145..478ca0177 100644 --- a/client/src/app/+signup/+register/steps/register-step-channel.component.ts +++ b/client/src/app/+signup/+register/steps/register-step-channel.component.ts | |||
@@ -2,9 +2,9 @@ import { concat, of } from 'rxjs' | |||
2 | import { pairwise } from 'rxjs/operators' | 2 | import { pairwise } from 'rxjs/operators' |
3 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' | 3 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' |
4 | import { FormGroup } from '@angular/forms' | 4 | import { FormGroup } from '@angular/forms' |
5 | import { SignupService } from '@app/+signup/shared/signup.service' | ||
5 | import { VIDEO_CHANNEL_DISPLAY_NAME_VALIDATOR, VIDEO_CHANNEL_NAME_VALIDATOR } from '@app/shared/form-validators/video-channel-validators' | 6 | import { VIDEO_CHANNEL_DISPLAY_NAME_VALIDATOR, VIDEO_CHANNEL_NAME_VALIDATOR } from '@app/shared/form-validators/video-channel-validators' |
6 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' | 7 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' |
7 | import { UserSignupService } from '@app/shared/shared-users' | ||
8 | 8 | ||
9 | @Component({ | 9 | @Component({ |
10 | selector: 'my-register-step-channel', | 10 | selector: 'my-register-step-channel', |
@@ -20,7 +20,7 @@ export class RegisterStepChannelComponent extends FormReactive implements OnInit | |||
20 | 20 | ||
21 | constructor ( | 21 | constructor ( |
22 | protected formReactiveService: FormReactiveService, | 22 | protected formReactiveService: FormReactiveService, |
23 | private userSignupService: UserSignupService | 23 | private signupService: SignupService |
24 | ) { | 24 | ) { |
25 | super() | 25 | super() |
26 | } | 26 | } |
@@ -51,7 +51,7 @@ export class RegisterStepChannelComponent extends FormReactive implements OnInit | |||
51 | private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) { | 51 | private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) { |
52 | const name = this.form.value['name'] || '' | 52 | const name = this.form.value['name'] || '' |
53 | 53 | ||
54 | const newName = this.userSignupService.getNewUsername(oldDisplayName, newDisplayName, name) | 54 | const newName = this.signupService.getNewUsername(oldDisplayName, newDisplayName, name) |
55 | this.form.patchValue({ name: newName }) | 55 | this.form.patchValue({ name: newName }) |
56 | } | 56 | } |
57 | } | 57 | } |
diff --git a/client/src/app/+signup/+register/steps/register-step-terms.component.html b/client/src/app/+signup/+register/steps/register-step-terms.component.html index cbfb32518..1d753a3f2 100644 --- a/client/src/app/+signup/+register/steps/register-step-terms.component.html +++ b/client/src/app/+signup/+register/steps/register-step-terms.component.html | |||
@@ -1,4 +1,16 @@ | |||
1 | <form role="form" [formGroup]="form"> | 1 | <form role="form" [formGroup]="form"> |
2 | |||
3 | <div *ngIf="requiresApproval" class="form-group"> | ||
4 | <label i18n for="registrationReason">Why do you want to join {{ instanceName }}?</label> | ||
5 | |||
6 | <textarea | ||
7 | id="registrationReason" formControlName="registrationReason" class="form-control" rows="4" | ||
8 | [ngClass]="{ 'input-error': formErrors['registrationReason'] }" | ||
9 | ></textarea> | ||
10 | |||
11 | <div *ngIf="formErrors.registrationReason" class="form-error">{{ formErrors.registrationReason }}</div> | ||
12 | </div> | ||
13 | |||
2 | <div class="form-group"> | 14 | <div class="form-group"> |
3 | <my-peertube-checkbox inputName="terms" formControlName="terms"> | 15 | <my-peertube-checkbox inputName="terms" formControlName="terms"> |
4 | <ng-template ptTemplate="label"> | 16 | <ng-template ptTemplate="label"> |
@@ -6,7 +18,7 @@ | |||
6 | I am at least {{ minimumAge }} years old and agree | 18 | I am at least {{ minimumAge }} years old and agree |
7 | to the <a class="link-orange" (click)="onTermsClick($event)" href='#'>Terms</a> | 19 | to the <a class="link-orange" (click)="onTermsClick($event)" href='#'>Terms</a> |
8 | <ng-container *ngIf="hasCodeOfConduct"> and to the <a class="link-orange" (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container> | 20 | <ng-container *ngIf="hasCodeOfConduct"> and to the <a class="link-orange" (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container> |
9 | of this instance | 21 | of {{ instanceName }} |
10 | </ng-container> | 22 | </ng-container> |
11 | </ng-template> | 23 | </ng-template> |
12 | </my-peertube-checkbox> | 24 | </my-peertube-checkbox> |
diff --git a/client/src/app/+signup/+register/steps/register-step-terms.component.ts b/client/src/app/+signup/+register/steps/register-step-terms.component.ts index 2df963b30..1b1fb49ee 100644 --- a/client/src/app/+signup/+register/steps/register-step-terms.component.ts +++ b/client/src/app/+signup/+register/steps/register-step-terms.component.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' | 1 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' |
2 | import { FormGroup } from '@angular/forms' | 2 | import { FormGroup } from '@angular/forms' |
3 | import { USER_TERMS_VALIDATOR } from '@app/shared/form-validators/user-validators' | ||
4 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' | 3 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' |
4 | import { REGISTER_REASON_VALIDATOR, REGISTER_TERMS_VALIDATOR } from '../shared' | ||
5 | 5 | ||
6 | @Component({ | 6 | @Component({ |
7 | selector: 'my-register-step-terms', | 7 | selector: 'my-register-step-terms', |
@@ -10,7 +10,9 @@ import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' | |||
10 | }) | 10 | }) |
11 | export class RegisterStepTermsComponent extends FormReactive implements OnInit { | 11 | export class RegisterStepTermsComponent extends FormReactive implements OnInit { |
12 | @Input() hasCodeOfConduct = false | 12 | @Input() hasCodeOfConduct = false |
13 | @Input() requiresApproval: boolean | ||
13 | @Input() minimumAge = 16 | 14 | @Input() minimumAge = 16 |
15 | @Input() instanceName: string | ||
14 | 16 | ||
15 | @Output() formBuilt = new EventEmitter<FormGroup>() | 17 | @Output() formBuilt = new EventEmitter<FormGroup>() |
16 | @Output() termsClick = new EventEmitter<void>() | 18 | @Output() termsClick = new EventEmitter<void>() |
@@ -28,7 +30,11 @@ export class RegisterStepTermsComponent extends FormReactive implements OnInit { | |||
28 | 30 | ||
29 | ngOnInit () { | 31 | ngOnInit () { |
30 | this.buildForm({ | 32 | this.buildForm({ |
31 | terms: USER_TERMS_VALIDATOR | 33 | terms: REGISTER_TERMS_VALIDATOR, |
34 | |||
35 | registrationReason: this.requiresApproval | ||
36 | ? REGISTER_REASON_VALIDATOR | ||
37 | : null | ||
32 | }) | 38 | }) |
33 | 39 | ||
34 | setTimeout(() => this.formBuilt.emit(this.form)) | 40 | setTimeout(() => this.formBuilt.emit(this.form)) |
diff --git a/client/src/app/+signup/+register/steps/register-step-user.component.ts b/client/src/app/+signup/+register/steps/register-step-user.component.ts index 822f8f5c5..0a5d2e437 100644 --- a/client/src/app/+signup/+register/steps/register-step-user.component.ts +++ b/client/src/app/+signup/+register/steps/register-step-user.component.ts | |||
@@ -2,6 +2,7 @@ import { concat, of } from 'rxjs' | |||
2 | import { pairwise } from 'rxjs/operators' | 2 | import { pairwise } from 'rxjs/operators' |
3 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' | 3 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' |
4 | import { FormGroup } from '@angular/forms' | 4 | import { FormGroup } from '@angular/forms' |
5 | import { SignupService } from '@app/+signup/shared/signup.service' | ||
5 | import { | 6 | import { |
6 | USER_DISPLAY_NAME_REQUIRED_VALIDATOR, | 7 | USER_DISPLAY_NAME_REQUIRED_VALIDATOR, |
7 | USER_EMAIL_VALIDATOR, | 8 | USER_EMAIL_VALIDATOR, |
@@ -9,7 +10,6 @@ import { | |||
9 | USER_USERNAME_VALIDATOR | 10 | USER_USERNAME_VALIDATOR |
10 | } from '@app/shared/form-validators/user-validators' | 11 | } from '@app/shared/form-validators/user-validators' |
11 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' | 12 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' |
12 | import { UserSignupService } from '@app/shared/shared-users' | ||
13 | 13 | ||
14 | @Component({ | 14 | @Component({ |
15 | selector: 'my-register-step-user', | 15 | selector: 'my-register-step-user', |
@@ -24,7 +24,7 @@ export class RegisterStepUserComponent extends FormReactive implements OnInit { | |||
24 | 24 | ||
25 | constructor ( | 25 | constructor ( |
26 | protected formReactiveService: FormReactiveService, | 26 | protected formReactiveService: FormReactiveService, |
27 | private userSignupService: UserSignupService | 27 | private signupService: SignupService |
28 | ) { | 28 | ) { |
29 | super() | 29 | super() |
30 | } | 30 | } |
@@ -57,7 +57,7 @@ export class RegisterStepUserComponent extends FormReactive implements OnInit { | |||
57 | private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) { | 57 | private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) { |
58 | const username = this.form.value['username'] || '' | 58 | const username = this.form.value['username'] || '' |
59 | 59 | ||
60 | const newUsername = this.userSignupService.getNewUsername(oldDisplayName, newDisplayName, username) | 60 | const newUsername = this.signupService.getNewUsername(oldDisplayName, newDisplayName, username) |
61 | this.form.patchValue({ username: newUsername }) | 61 | this.form.patchValue({ username: newUsername }) |
62 | } | 62 | } |
63 | } | 63 | } |
diff --git a/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts b/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts index 06905f678..75b599e0e 100644 --- a/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts +++ b/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts | |||
@@ -1,8 +1,8 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnInit } from '@angular/core' |
2 | import { SignupService } from '@app/+signup/shared/signup.service' | ||
2 | import { Notifier, RedirectService, ServerService } from '@app/core' | 3 | import { Notifier, RedirectService, ServerService } from '@app/core' |
3 | import { USER_EMAIL_VALIDATOR } from '@app/shared/form-validators/user-validators' | 4 | import { USER_EMAIL_VALIDATOR } from '@app/shared/form-validators/user-validators' |
4 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' | 5 | import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' |
5 | import { UserSignupService } from '@app/shared/shared-users' | ||
6 | 6 | ||
7 | @Component({ | 7 | @Component({ |
8 | selector: 'my-verify-account-ask-send-email', | 8 | selector: 'my-verify-account-ask-send-email', |
@@ -15,7 +15,7 @@ export class VerifyAccountAskSendEmailComponent extends FormReactive implements | |||
15 | 15 | ||
16 | constructor ( | 16 | constructor ( |
17 | protected formReactiveService: FormReactiveService, | 17 | protected formReactiveService: FormReactiveService, |
18 | private userSignupService: UserSignupService, | 18 | private signupService: SignupService, |
19 | private serverService: ServerService, | 19 | private serverService: ServerService, |
20 | private notifier: Notifier, | 20 | private notifier: Notifier, |
21 | private redirectService: RedirectService | 21 | private redirectService: RedirectService |
@@ -34,7 +34,7 @@ export class VerifyAccountAskSendEmailComponent extends FormReactive implements | |||
34 | 34 | ||
35 | askSendVerifyEmail () { | 35 | askSendVerifyEmail () { |
36 | const email = this.form.value['verify-email-email'] | 36 | const email = this.form.value['verify-email-email'] |
37 | this.userSignupService.askSendVerifyEmail(email) | 37 | this.signupService.askSendVerifyEmail(email) |
38 | .subscribe({ | 38 | .subscribe({ |
39 | next: () => { | 39 | next: () => { |
40 | this.notifier.success($localize`An email with verification link will be sent to ${email}.`) | 40 | this.notifier.success($localize`An email with verification link will be sent to ${email}.`) |
diff --git a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html index 122f3c28c..8c8b1098e 100644 --- a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html +++ b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html | |||
@@ -1,14 +1,19 @@ | |||
1 | <div class="margin-content"> | 1 | <div *ngIf="loaded" class="margin-content"> |
2 | <h1 i18n class="title-page">Verify account email confirmation</h1> | 2 | <h1 i18n class="title-page">Verify email</h1> |
3 | 3 | ||
4 | <my-signup-success i18n *ngIf="!isPendingEmail && success" [requiresEmailVerification]="false"> | 4 | <my-signup-success-after-email |
5 | </my-signup-success> | 5 | *ngIf="displaySignupSuccess()" |
6 | [requiresApproval]="isRegistrationRequest() && requiresApproval" | ||
7 | > | ||
8 | </my-signup-success-after-email> | ||
6 | 9 | ||
7 | <div i18n class="alert alert-success" *ngIf="isPendingEmail && success">Email updated.</div> | 10 | <div i18n class="alert alert-success" *ngIf="!isRegistrationRequest() && isPendingEmail && success">Email updated.</div> |
8 | 11 | ||
9 | <div class="alert alert-danger" *ngIf="failed"> | 12 | <div class="alert alert-danger" *ngIf="failed"> |
10 | <span i18n>An error occurred.</span> | 13 | <span i18n>An error occurred.</span> |
11 | 14 | ||
12 | <a i18n class="ms-1 link-orange" routerLink="/verify-account/ask-send-email" [queryParams]="{ isPendingEmail: isPendingEmail }">Request new verification email</a> | 15 | <a i18n class="ms-1 link-orange" routerLink="/verify-account/ask-send-email"> |
16 | Request a new verification email | ||
17 | </a> | ||
13 | </div> | 18 | </div> |
14 | </div> | 19 | </div> |
diff --git a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts index 88efce4a1..faf663391 100644 --- a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts +++ b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnInit } from '@angular/core' |
2 | import { ActivatedRoute } from '@angular/router' | 2 | import { ActivatedRoute } from '@angular/router' |
3 | import { AuthService, Notifier } from '@app/core' | 3 | import { SignupService } from '@app/+signup/shared/signup.service' |
4 | import { UserSignupService } from '@app/shared/shared-users' | 4 | import { AuthService, Notifier, ServerService } from '@app/core' |
5 | 5 | ||
6 | @Component({ | 6 | @Component({ |
7 | selector: 'my-verify-account-email', | 7 | selector: 'my-verify-account-email', |
@@ -13,32 +13,82 @@ export class VerifyAccountEmailComponent implements OnInit { | |||
13 | failed = false | 13 | failed = false |
14 | isPendingEmail = false | 14 | isPendingEmail = false |
15 | 15 | ||
16 | requiresApproval: boolean | ||
17 | loaded = false | ||
18 | |||
16 | private userId: number | 19 | private userId: number |
20 | private registrationId: number | ||
17 | private verificationString: string | 21 | private verificationString: string |
18 | 22 | ||
19 | constructor ( | 23 | constructor ( |
20 | private userSignupService: UserSignupService, | 24 | private signupService: SignupService, |
25 | private server: ServerService, | ||
21 | private authService: AuthService, | 26 | private authService: AuthService, |
22 | private notifier: Notifier, | 27 | private notifier: Notifier, |
23 | private route: ActivatedRoute | 28 | private route: ActivatedRoute |
24 | ) { | 29 | ) { |
25 | } | 30 | } |
26 | 31 | ||
32 | get instanceName () { | ||
33 | return this.server.getHTMLConfig().instance.name | ||
34 | } | ||
35 | |||
27 | ngOnInit () { | 36 | ngOnInit () { |
28 | const queryParams = this.route.snapshot.queryParams | 37 | const queryParams = this.route.snapshot.queryParams |
38 | |||
39 | this.server.getConfig().subscribe(config => { | ||
40 | this.requiresApproval = config.signup.requiresApproval | ||
41 | |||
42 | this.loaded = true | ||
43 | }) | ||
44 | |||
29 | this.userId = queryParams['userId'] | 45 | this.userId = queryParams['userId'] |
46 | this.registrationId = queryParams['registrationId'] | ||
47 | |||
30 | this.verificationString = queryParams['verificationString'] | 48 | this.verificationString = queryParams['verificationString'] |
49 | |||
31 | this.isPendingEmail = queryParams['isPendingEmail'] === 'true' | 50 | this.isPendingEmail = queryParams['isPendingEmail'] === 'true' |
32 | 51 | ||
33 | if (!this.userId || !this.verificationString) { | 52 | if (!this.verificationString) { |
34 | this.notifier.error($localize`Unable to find user id or verification string.`) | 53 | this.notifier.error($localize`Unable to find verification string in URL query.`) |
35 | } else { | 54 | return |
36 | this.verifyEmail() | 55 | } |
56 | |||
57 | if (!this.userId && !this.registrationId) { | ||
58 | this.notifier.error($localize`Unable to find user id or registration id in URL query.`) | ||
59 | return | ||
37 | } | 60 | } |
61 | |||
62 | this.verifyEmail() | ||
63 | } | ||
64 | |||
65 | isRegistrationRequest () { | ||
66 | return !!this.registrationId | ||
67 | } | ||
68 | |||
69 | displaySignupSuccess () { | ||
70 | if (!this.success) return false | ||
71 | if (!this.isRegistrationRequest() && this.isPendingEmail) return false | ||
72 | |||
73 | return true | ||
38 | } | 74 | } |
39 | 75 | ||
40 | verifyEmail () { | 76 | verifyEmail () { |
41 | this.userSignupService.verifyEmail(this.userId, this.verificationString, this.isPendingEmail) | 77 | if (this.isRegistrationRequest()) { |
78 | return this.verifyRegistrationEmail() | ||
79 | } | ||
80 | |||
81 | return this.verifyUserEmail() | ||
82 | } | ||
83 | |||
84 | private verifyUserEmail () { | ||
85 | const options = { | ||
86 | userId: this.userId, | ||
87 | verificationString: this.verificationString, | ||
88 | isPendingEmail: this.isPendingEmail | ||
89 | } | ||
90 | |||
91 | this.signupService.verifyUserEmail(options) | ||
42 | .subscribe({ | 92 | .subscribe({ |
43 | next: () => { | 93 | next: () => { |
44 | if (this.authService.isLoggedIn()) { | 94 | if (this.authService.isLoggedIn()) { |
@@ -55,4 +105,24 @@ export class VerifyAccountEmailComponent implements OnInit { | |||
55 | } | 105 | } |
56 | }) | 106 | }) |
57 | } | 107 | } |
108 | |||
109 | private verifyRegistrationEmail () { | ||
110 | const options = { | ||
111 | registrationId: this.registrationId, | ||
112 | verificationString: this.verificationString | ||
113 | } | ||
114 | |||
115 | this.signupService.verifyRegistrationEmail(options) | ||
116 | .subscribe({ | ||
117 | next: () => { | ||
118 | this.success = true | ||
119 | }, | ||
120 | |||
121 | error: err => { | ||
122 | this.failed = true | ||
123 | |||
124 | this.notifier.error(err.message) | ||
125 | } | ||
126 | }) | ||
127 | } | ||
58 | } | 128 | } |
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 | } | ||