diff --git a/client/src/app/core/repositories/users/user-repository.service.ts b/client/src/app/core/repositories/users/user-repository.service.ts index f061848d7..0bf12a78e 100644 --- a/client/src/app/core/repositories/users/user-repository.service.ts +++ b/client/src/app/core/repositories/users/user-repository.service.ts @@ -132,11 +132,15 @@ export class UserRepositoryService extends BaseRepository { * * @param user The user to update * @param password The password to set + * @param updateDefaultPassword Control, if the default password should be updated. */ - public async resetPassword(user: ViewUser, password: string): Promise { + public async resetPassword( + user: ViewUser, + password: string, + updateDefaultPassword: boolean = false + ): Promise { const path = `/rest/users/user/${user.id}/reset_password/`; - await this.httpService.post(path, { password: password }); - await this.update({ default_password: password }, user); + await this.httpService.post(path, { password: password, update_default_password: updateDefaultPassword }); } /** diff --git a/client/src/app/site/users/components/password/password.component.html b/client/src/app/site/users/components/password/password.component.html index f02286d5a..11c8074ba 100644 --- a/client/src/app/site/users/components/password/password.component.html +++ b/client/src/app/site/users/components/password/password.component.html @@ -11,24 +11,37 @@

Change password for {{ user.full_name }}

- warning You override the personally set password! + warning +  You override the personally set password!

- sync_problem + matTooltip="{{ hidePassword ? ('Show password' | translate) : ('Hide password' | translate) }}" + (click)="hidePassword = !hidePassword"> + {{ hidePassword ? 'visibility' : 'visibility_off' }} + + settings + + +

@@ -36,62 +49,45 @@ Initial password: {{ user.default_password }}
Username: {{ user.username }} -
- + +

- sync_problem + (click)="hidePassword = !hidePassword"> + {{ hidePassword ? 'visibility' : 'visibility_off' }}
-
+ + diff --git a/client/src/app/site/users/components/password/password.component.ts b/client/src/app/site/users/components/password/password.component.ts index 6cd0469d7..3a31b9750 100644 --- a/client/src/app/site/users/components/password/password.component.ts +++ b/client/src/app/site/users/components/password/password.component.ts @@ -1,10 +1,11 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; -import { TranslateService } from '@ngx-translate/core'; import { MatSnackBar } from '@angular/material'; import { Title } from '@angular/platform-browser'; +import { TranslateService } from '@ngx-translate/core'; + import { ViewUser } from '../../models/view-user'; import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service'; import { OperatorService } from 'app/core/core-services/operator.service'; @@ -29,11 +30,6 @@ export class PasswordComponent extends BaseViewComponent implements OnInit { */ public ownPage: boolean; - /** - * user id from url parameter - */ - public userId: number; - /** * if current user has the "can_manage" permission */ @@ -50,14 +46,11 @@ export class PasswordComponent extends BaseViewComponent implements OnInit { public userPasswordForm: FormGroup; /** - * if the new password in userform is hidden + * if all password inputs is hidden */ - public hide_user_password = true; + public hidePassword = true; - /** - * If the new Password in the adminform is hidden - */ - public hide_admin_newPassword = true; + private urlUserId: number | null; /** * Constructor @@ -82,39 +75,48 @@ export class PasswordComponent extends BaseViewComponent implements OnInit { private formBuilder: FormBuilder ) { super(title, translate, matSnackBar); - this.route.params.subscribe(params => { - if (params.id) { - this.userId = params.id; - } - }); - if (this.userId === undefined) { - this.operator.getUserObservable().subscribe(user => { - if (user) { - this.userId = user.id; - this.router.navigate([`./users/password/${this.userId}`]); - } - }); - } } /** * Initializes the forms and some of the frontend options */ public ngOnInit(): void { - this.setViewUser(this.userId); - this.setOpOwnsPage(this.userId); + this.route.params.subscribe(params => { + if (params.id) { + this.urlUserId = +params.id; + this.repo.getViewModelObservable(this.urlUserId).subscribe(() => { + this.updateUser(); + }); + } + this.updateUser(); + }); + + this.operator.getUserObservable().subscribe(() => { + this.updateUser(); + }); this.adminPasswordForm = this.formBuilder.group({ - admin_newPassword: ['', Validators.required] + newPassword: ['', Validators.required] }); this.userPasswordForm = this.formBuilder.group({ - user_newPassword1: ['', Validators.required], - user_newPassword2: ['', Validators.required], - user_oldPassword: ['', Validators.required] + newPassword1: ['', Validators.required], + newPassword2: ['', Validators.required], + oldPassword: ['', Validators.required] }); } + private updateUser(): void { + const operator = this.operator.user; + this.ownPage = this.urlUserId ? operator.id === this.urlUserId : true; + if (this.ownPage) { + this.user = this.operator.viewUser; + } else { + this.user = this.repo.getViewModel(this.urlUserId); + } + this.canManage = this.operator.hasPerms('users.can_manage'); + } + /** * Triggered by the "x" Button of the Form */ @@ -126,34 +128,6 @@ export class PasswordComponent extends BaseViewComponent implements OnInit { } } - /** - * sets the current user that should be worked on - * - * @param userId user id from the route - */ - private setViewUser(userId: number): void { - this.repo.getViewModelObservable(userId).subscribe(newViewUser => { - if (newViewUser) { - this.user = newViewUser; - } - }); - } - - /** - * sets the parameters if the pw-page is our own and if the current - * user has the can_manage permission - * - * @param userId user id from the route - */ - private setOpOwnsPage(userId: number): void { - this.operator.getUserObservable().subscribe(user => { - if (user) { - this.ownPage = +userId === +user.id; - this.canManage = this.operator.hasPerms('users.can_manage'); - } - }); - } - /** * Handles the whole save routine for every possible event */ @@ -161,46 +135,32 @@ export class PasswordComponent extends BaseViewComponent implements OnInit { // can Manage, but not own Page (a.k.a. Admin) try { if (this.canManage && !this.ownPage) { - const pw = this.adminPasswordForm.get('admin_newPassword').value; - this.adminNewPassword(pw); + if (!this.adminPasswordForm.valid) { + return; + } + const password = this.adminPasswordForm.value.newPassword; + await this.repo.resetPassword(this.user, password); this.router.navigate([`./users/${this.user.id}`]); - } - // can not Manage, but own Page (a.k.a. User) - if (this.ownPage) { - const oldPw = this.userPasswordForm.get('user_oldPassword').value; - const newPw1 = this.userPasswordForm.get('user_newPassword1').value; - const newPw2 = this.userPasswordForm.get('user_newPassword2').value; - await this.userNewPassword(newPw1, newPw2, oldPw); - this.router.navigate(['./']); + } else if (this.ownPage) { + if (!this.userPasswordForm.valid) { + return; + } + const oldPassword = this.userPasswordForm.value.oldPassword; + const newPassword1 = this.userPasswordForm.value.newPassword1; + const newPassword2 = this.userPasswordForm.value.newPassword2; + + if (newPassword1 !== newPassword2) { + this.raiseError(this.translate.instant('New passwords do not match')); + } else { + await this.repo.setNewPassword(oldPassword, newPassword1); + this.router.navigate(['./']); + } } } catch (e) { this.raiseError(e); } } - /** - * Sends new Password entered in the new password field to server - * - * @param password the password that should be set - */ - private adminNewPassword(password: string): void { - this.repo.resetPassword(this.user, password).catch(this.raiseError); - } - - /** - * sets the new password for a user and sends it to the server - * - * @param newPassword1 the new password - * @param newPassword2 confirmation of the new password - * @param oldPassword the old password - */ - private userNewPassword(newPassword1: string, newPassword2: string, oldPassword: string): void { - if (newPassword1 !== newPassword2) { - this.raiseError(this.translate.instant('Passwords do not match')); - } - this.repo.setNewPassword(oldPassword, newPassword1).catch(this.raiseError); - } - /** * clicking Shift and Enter will save automatically * @@ -216,49 +176,15 @@ export class PasswordComponent extends BaseViewComponent implements OnInit { * Takes generated password and puts it into admin PW field * and displays it */ - public admin_generatePassword(): void { + public generatePassword(): void { + const randomPassword = this.repo.getRandomPassword(); this.adminPasswordForm.patchValue({ - admin_newPassword: this.repo.getRandomPassword() + newPassword: randomPassword }); - this.admin_hidePassword(false); - } - - /** - * Takes generated password and puts it into user PW fields - * and displays them - */ - public user_generatePassword(): void { - const newPW = this.repo.getRandomPassword(); this.userPasswordForm.patchValue({ - user_newPassword1: newPW, - user_newPassword2: newPW + newPassword1: randomPassword, + newPassword2: randomPassword }); - this.user_hidePassword(false); - } - - /** - * Helper function to hide or display the pw in cleartext for admin form - * - * @param hide optional - states if it should be shown or not - */ - public admin_hidePassword(hide?: boolean): void { - if (hide !== null) { - this.hide_admin_newPassword = hide; - } else { - this.hide_admin_newPassword = !this.hide_admin_newPassword; - } - } - - /** - * Helper function to hide or display new pw in clearext for user form - * - * @param hide optional - states if it should be shown or not - */ - public user_hidePassword(hide?: boolean): void { - if (hide !== null) { - this.hide_user_password = hide; - } else { - this.hide_user_password = !this.hide_user_password; - } + this.hidePassword = false; } } diff --git a/client/src/app/site/users/components/user-list/user-list.component.ts b/client/src/app/site/users/components/user-list/user-list.component.ts index 560b61b69..afab6453a 100644 --- a/client/src/app/site/users/components/user-list/user-list.component.ts +++ b/client/src/app/site/users/components/user-list/user-list.component.ts @@ -273,7 +273,7 @@ export class UserListComponent extends ListViewBaseComponent implement public async resetPasswordsSelected(): Promise { for (const user of this.selectedRows) { const password = this.repo.getRandomPassword(); - this.repo.resetPassword(user, password); + this.repo.resetPassword(user, password, true); } } diff --git a/client/src/styles.scss b/client/src/styles.scss index 4825158b0..799968c87 100644 --- a/client/src/styles.scss +++ b/client/src/styles.scss @@ -398,6 +398,11 @@ button.mat-menu-item.selected { .spacer-bottom-20 { margin-bottom: 20px !important; } +.spacer-left-10 { + margin-left: 10px; +} + + .button24 { background-color: white; width: 24px !important; diff --git a/openslides/users/views.py b/openslides/users/views.py index a5140f43f..64f393f9a 100644 --- a/openslides/users/views.py +++ b/openslides/users/views.py @@ -141,18 +141,29 @@ class UserViewSet(ModelViewSet): def reset_password(self, request, pk=None): """ View to reset the password using the requested password. + If update_defualt_password=True is given, the new password will also be set + as the default_password. """ user = self.get_object() - if isinstance(request.data.get("password"), str): - try: - validate_password(request.data.get("password"), user=request.user) - except DjangoValidationError as errors: - raise ValidationError({"detail": " ".join(errors)}) - user.set_password(request.data.get("password")) - user.save() - return Response({"detail": "Password successfully reset."}) + password = request.data.get("password") + if not isinstance(password, str): + raise ValidationError({"detail": "Password has to be a string."}) - raise ValidationError({"detail": "Password has to be a string."}) + update_default_password = request.data.get("update_default_password", False) + if not isinstance(update_default_password, bool): + raise ValidationError( + {"detail": "update_default_password has to be a boolean."} + ) + + try: + validate_password(password, user=request.user) + except DjangoValidationError as errors: + raise ValidationError({"detail": " ".join(errors)}) + user.set_password(password) + if update_default_password: + user.default_password = password + user.save() + return Response({"detail": "Password successfully reset."}) @list_route(methods=["post"]) @transaction.atomic