"secure": false
},
"/socket.io": {
- "target": "http://localhost:9000",
- "secure": false
+ "target": "ws://localhost:9000",
+ "secure": false,
+ "ws": true
}
}
--- /dev/null
+export * from './my-account-change-email.component'
--- /dev/null
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+<div *ngIf="success" class="alert alert-success">{{ success }}</div>
+
+<div i18n class="current-email">
+ Your current email is <span class="email">{{ user.email }}</span>
+</div>
+
+<div i18n class="pending-email" *ngIf="user.pendingEmail">
+ <span class="email">{{ user.pendingEmail }}</span> is awaiting email verification
+</div>
+
+<form role="form" (ngSubmit)="changeEmail()" [formGroup]="form">
+
+ <div class="form-group">
+ <label i18n for="new-email">New email</label>
+ <input
+ type="email" id="new-email" i18n-placeholder placeholder="Your new email"
+ formControlName="new-email" [ngClass]="{ 'input-error': formErrors['new-email'] }"
+ >
+ <div *ngIf="formErrors['new-email']" class="form-error">
+ {{ formErrors['new-email'] }}
+ </div>
+ </div>
+
+ <div class="form-group">
+ <input
+ type="password" id="password" i18n-placeholder placeholder="Your password"
+ formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
+ >
+ <div *ngIf="formErrors['password']" class="form-error">
+ {{ formErrors['password'] }}
+ </div>
+ </div>
+
+ <input type="submit" i18n-value value="Change email" [disabled]="!form.valid">
+</form>
--- /dev/null
+@import '_variables';
+@import '_mixins';
+
+input[type=password],
+input[type=email] {
+ @include peertube-input-text(340px);
+
+ display: block;
+}
+
+input[type=submit] {
+ @include peertube-button;
+ @include orange-button;
+}
+
+.current-email,
+.pending-email {
+ font-size: 16px;
+ margin: 15px 0;
+
+ .email {
+ font-weight: $font-semibold;
+ }
+}
--- /dev/null
+import { Component, OnInit } from '@angular/core'
+import { AuthService, Notifier, ServerService } from '@app/core'
+import { FormReactive, UserService } from '../../../shared'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
+import { User } from '../../../../../../shared'
+import { switchMap, tap } from 'rxjs/operators'
+
+@Component({
+ selector: 'my-account-change-email',
+ templateUrl: './my-account-change-email.component.html',
+ styleUrls: [ './my-account-change-email.component.scss' ]
+})
+export class MyAccountChangeEmailComponent extends FormReactive implements OnInit {
+ error: string = null
+ success: string = null
+ user: User = null
+
+ constructor (
+ protected formValidatorService: FormValidatorService,
+ private userValidatorsService: UserValidatorsService,
+ private notifier: Notifier,
+ private authService: AuthService,
+ private userService: UserService,
+ private serverService: ServerService,
+ private i18n: I18n
+ ) {
+ super()
+ }
+
+ ngOnInit () {
+ this.buildForm({
+ 'new-email': this.userValidatorsService.USER_EMAIL,
+ 'password': this.userValidatorsService.USER_PASSWORD
+ })
+
+ this.user = this.authService.getUser()
+ }
+
+ changeEmail () {
+ this.error = null
+ this.success = null
+
+ const password = this.form.value[ 'password' ]
+ const email = this.form.value[ 'new-email' ]
+
+ this.userService.changeEmail(password, email)
+ .pipe(
+ tap(() => this.authService.refreshUserInformation())
+ )
+ .subscribe(
+ () => {
+ this.form.reset()
+
+ if (this.serverService.getConfig().signup.requiresEmailVerification) {
+ this.success = this.i18n('Please check your emails to verify your new email.')
+ } else {
+ this.success = this.i18n('Email updated.')
+ }
+ },
+
+ err => {
+ if (err.status === 401) {
+ this.error = this.i18n('You current password is invalid.')
+ return
+ }
+
+ this.error = err.message
+ }
+ )
+ }
+}
<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
- <label i18n for="new-password">Change password</label>
+ <label i18n for="current-password">Change password</label>
<input
type="password" id="current-password" i18n-placeholder placeholder="Current password"
formControlName="current-password" [ngClass]="{ 'input-error': formErrors['current-password'] }"
<div i18n class="account-title">Password</div>
<my-account-change-password></my-account-change-password>
+<div i18n class="account-title">Email</div>
+<my-account-change-email></my-account-change-email>
+
<div i18n class="account-title">Video settings</div>
<my-account-video-settings [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-video-settings>
MyAccountVideoPlaylistElementsComponent
} from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component'
import { DragDropModule } from '@angular/cdk/drag-drop'
+import { MyAccountChangeEmailComponent } from '@app/+my-account/my-account-settings/my-account-change-email'
@NgModule({
imports: [
MyAccountChangePasswordComponent,
MyAccountVideoSettingsComponent,
MyAccountProfileComponent,
+ MyAccountChangeEmailComponent,
+
MyAccountVideosComponent,
+
VideoChangeOwnershipComponent,
MyAccountOwnershipComponent,
MyAccountAcceptOwnershipComponent,
Verify account email confirmation
</div>
- <my-signup-success i18n *ngIf="success; else verificationError" message="Your email has been verified and you may now login.">
+ <my-signup-success i18n *ngIf="!isPendingEmail && success" message="Your email has been verified and you may now login.">
</my-signup-success>
- <ng-template #verificationError>
- <div>
- <span i18n>An error occurred. </span>
- <a i18n routerLink="/verify-account/ask-send-email">Request new verification email.</a>
- </div>
- </ng-template>
+ <div i18n class="alert alert-success" *ngIf="isPendingEmail && success">
+ Email updated.
+ </div>
+
+ <div *ngIf="failed">
+ <span i18n>An error occurred.</span>
+
+ <a i18n routerLink="/verify-account/ask-send-email" [queryParams]="{ isPendingEmail: isPendingEmail }">Request new verification email.</a>
+ </div>
</div>
import { Component, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { I18n } from '@ngx-translate/i18n-polyfill'
-import { Notifier } from '@app/core'
+import { AuthService, Notifier } from '@app/core'
import { UserService } from '@app/shared'
@Component({
export class VerifyAccountEmailComponent implements OnInit {
success = false
+ failed = false
+ isPendingEmail = false
private userId: number
private verificationString: string
constructor (
private userService: UserService,
+ private authService: AuthService,
private notifier: Notifier,
private router: Router,
private route: ActivatedRoute,
}
ngOnInit () {
- this.userId = this.route.snapshot.queryParams['userId']
- this.verificationString = this.route.snapshot.queryParams['verificationString']
+ const queryParams = this.route.snapshot.queryParams
+ this.userId = queryParams['userId']
+ this.verificationString = queryParams['verificationString']
+ this.isPendingEmail = queryParams['isPendingEmail'] === 'true'
+
+ console.log(this.isPendingEmail)
if (!this.userId || !this.verificationString) {
this.notifier.error(this.i18n('Unable to find user id or verification string.'))
}
verifyEmail () {
- this.userService.verifyEmail(this.userId, this.verificationString)
+ this.userService.verifyEmail(this.userId, this.verificationString, this.isPendingEmail)
.subscribe(
() => {
+ this.authService.refreshUserInformation()
+
this.success = true
},
err => {
+ this.failed = true
+
this.notifier.error(err.message)
}
)
id: number
username: string
email: string
+ pendingEmail: string | null
emailVerified: boolean
nsfwPolicy: NSFWPolicyType
)
}
+ changeEmail (password: string, newEmail: string) {
+ const url = UserService.BASE_USERS_URL + 'me'
+ const body: UserUpdateMe = {
+ currentPassword: password,
+ email: newEmail
+ }
+
+ return this.authHttp.put(url, body)
+ .pipe(
+ map(this.restExtractor.extractDataBool),
+ catchError(err => this.restExtractor.handleError(err))
+ )
+ }
+
updateMyProfile (profile: UserUpdateMe) {
const url = UserService.BASE_USERS_URL + 'me'
)
}
- verifyEmail (userId: number, verificationString: string) {
+ verifyEmail (userId: number, verificationString: string, isPendingEmail: boolean) {
const url = `${UserService.BASE_USERS_URL}/${userId}/verify-email`
const body = {
- verificationString
+ verificationString,
+ isPendingEmail
}
return this.authHttp.post(url, body)
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking usersUpdateMe parameters', { parameters: omit(req.body, 'password') })
- if (req.body.password) {
+ if (req.body.password || req.body.email) {
if (!req.body.currentPassword) {
return res.status(400)
.send({ error: 'currentPassword parameter is missing.' })