rename components, add cypress tests, update hash
This commit is contained in:
parent
236afbeb4f
commit
13685b082e
|
|
@ -0,0 +1,95 @@
|
|||
describe('Change Password Page', () => {
|
||||
|
||||
const validNewPassword = 'Abcd1234!';
|
||||
const validOldPassword = 'test';
|
||||
const validationTooShort = 'Das neue Passwort muss mindestens 8 Zeichen lang sein';
|
||||
const validationErrorMsg = 'Das Passwort muss Grossbuchstaben, Zahlen und Sonderzeichen beinhalten';
|
||||
const validationOldWrongMsg = 'Die Eingabe ist falsch';
|
||||
|
||||
after(function () {
|
||||
cy.exec("python ../server/manage.py reset_testuser_password rahel.cueni");
|
||||
});
|
||||
|
||||
it('shows an empty form', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.get('[data-cy=password-change-success]').should('not.exist');
|
||||
cy.get('[data-cy=old-password]').should('have.value', '');
|
||||
cy.get('[data-cy=new-password]').should('have.value', '');
|
||||
});
|
||||
|
||||
it('shows errors if old password is not entered', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword('', validNewPassword);
|
||||
cy.get('[data-cy=old-password-local-errors]').should('contain', 'Dein aktuelles Passwort fehlt')
|
||||
});
|
||||
|
||||
it('shows errors if old password is not entered', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword(validOldPassword, '');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', 'Dein neues Passwort fehlt')
|
||||
});
|
||||
|
||||
it('shows errors if new password is too short', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword(validOldPassword, 'Abc1!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationTooShort)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no uppercase letter', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword(validOldPassword, 'aabdddedddbc1!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no lowercase letter', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword(validOldPassword, 'ABCDDD334551!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no digit', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword(validOldPassword, 'AbcdEEDE!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no special character', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword(validOldPassword, 'AbcdEEDE09877');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if old password does not match', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword('test12345', validNewPassword);
|
||||
cy.get('[data-cy=old-password-remote-errors]').should('contain', validationOldWrongMsg)
|
||||
});
|
||||
|
||||
it('shows success if change was successful', () => {
|
||||
cy.login('rahel.cueni', 'test');
|
||||
cy.visit('/password-change');
|
||||
|
||||
cy.changePassword('test', validNewPassword);
|
||||
cy.get('[data-cy=password-change-success]').should('contain', 'Dein Password wurde erfolgreich geändert.');
|
||||
cy.get('[data-cy=old-password]').should('have.value', '');
|
||||
cy.get('[data-cy=new-password]').should('have.value', '');
|
||||
});
|
||||
});
|
||||
|
|
@ -68,3 +68,14 @@ Cypress.Commands.add('waitFor', operationName => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('changePassword', (oldPassword, newPassword) => {
|
||||
if (oldPassword) {
|
||||
cy.get('[data-cy=old-password]').type(oldPassword);
|
||||
}
|
||||
|
||||
if (newPassword) {
|
||||
cy.get('[data-cy=new-password]').type(newPassword);
|
||||
}
|
||||
cy.get('[data-cy=change-password-button]').click();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="pw-reset">
|
||||
<form class="pw-reset__form reset-form" novalidate @submit.prevent="validateBeforeSubmit">
|
||||
<div class="reset-form__field sbform-input">
|
||||
<div class="pw-change">
|
||||
<form class="pw-change__form change-form" novalidate @submit.prevent="validateBeforeSubmit">
|
||||
<div class="change-form__field sbform-input">
|
||||
<label for="old-pw" class="sbform-input__label">Aktuells Passwort</label>
|
||||
<input id="old-pw"
|
||||
name="oldPassword"
|
||||
|
|
@ -9,11 +9,13 @@
|
|||
v-model="oldPassword"
|
||||
v-validate="'required'"
|
||||
:class="{ 'sbform-input__input--error': errors.has('oldPassword') }"
|
||||
class="reset-form__old skillbox-input sbform-input__input">
|
||||
<small v-if="errors.has('oldPassword') && submitted" class="sbform-input__error">{{ errors.first('oldPassword') }}</small>
|
||||
<small v-for="error in oldPasswordErrors" :key="error" class=" sbform-input__error">{{ error }}</small>
|
||||
class="change-form__old skillbox-input sbform-input__input"
|
||||
autocomplete="off"
|
||||
data-cy="old-password">
|
||||
<small v-if="errors.has('oldPassword') && submitted" class="sbform-input__error" data-cy="old-password-local-errors">{{ errors.first('oldPassword') }}</small>
|
||||
<small v-for="error in oldPasswordErrors" :key="error" class=" sbform-input__error" data-cy="old-password-remote-errors">{{ error }}</small>
|
||||
</div>
|
||||
<div class="reset-form__field sbform-input">
|
||||
<div class="change-form__field sbform-input">
|
||||
<label for="new-pw" class="sbform-input__label">Neues Passwort</label>
|
||||
<input id="new-pw"
|
||||
name="newPassword"
|
||||
|
|
@ -21,11 +23,13 @@
|
|||
v-model="newPassword"
|
||||
v-validate="'required|min:8|strongPassword'"
|
||||
:class="{ 'sbform-input__input--error': errors.has('newPassword') }"
|
||||
class="reset-form__new skillbox-input sbform-input__input">
|
||||
<small v-if="errors.has('newPassword') && submitted" class=" sbform-input__error">{{ errors.first('newPassword') }}</small>
|
||||
<small v-for="error in newPasswordErrors" :key="error" class=" sbform-input__error">{{ error }}</small>
|
||||
class="change-form__new skillbox-input sbform-input__input"
|
||||
autocomplete="off"
|
||||
data-cy="new-password">
|
||||
<small v-if="errors.has('newPassword') && submitted" class=" sbform-input__error" data-cy="new-password-local-errors">{{ errors.first('newPassword') }}</small>
|
||||
<small v-for="error in newPasswordErrors" :key="error" class=" sbform-input__error" data-cy="new-password-remote-errors">{{ error }}</small>
|
||||
</div>
|
||||
<button class="button button--primary reset-form__submit">Zurücksetzen</button>
|
||||
<button class="button button--primary change-form__submit" data-cy="change-password-button">Zurücksetzen</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -49,8 +53,19 @@
|
|||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
resetForm () {
|
||||
this.oldPassword = '';
|
||||
this.newPassword = '';
|
||||
this.submitted = false;
|
||||
this.$validator.reset();
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$root.$on('reset-password-form', () => {
|
||||
this.resetForm();
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -58,7 +73,7 @@
|
|||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_buttons.scss";
|
||||
|
||||
.reset-form {
|
||||
.change-form {
|
||||
width: 50%;
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
|
|
@ -82,7 +82,7 @@ Validator.extend('min', min);
|
|||
const dict = {
|
||||
custom: {
|
||||
oldPassword: {
|
||||
required: 'Dein jetztiges Passwort fehlt'
|
||||
required: 'Dein aktuelles Passwort fehlt'
|
||||
},
|
||||
newPassword: {
|
||||
required: 'Dein neues Passwort fehlt',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<div class="password-reset">
|
||||
<h1 class="password-reset__header">Passwort Zurücksetzen</h1>
|
||||
<password-reset
|
||||
<h1 class="password-reset__header">Passwort ändern</h1>
|
||||
<div v-if="showSuccess" class="success-message">
|
||||
<p class="success-message__msg" data-cy="password-change-success">Dein Password wurde erfolgreich geändert.</p>
|
||||
</div>
|
||||
<password-change
|
||||
@passwordSubmited="resetPassword"
|
||||
:oldPasswordErrors="oldPasswordErrors"
|
||||
:newPasswordErrors="newPasswordErrors" />
|
||||
|
|
@ -11,17 +14,18 @@
|
|||
<script>
|
||||
|
||||
import UPDATE_PASSWORD_MUTATION from '@/graphql/gql/mutations/updatePassword.gql';
|
||||
import PasswordReset from '@/components/PasswordReset'
|
||||
import PasswordChange from '@/components/PasswordChange'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PasswordReset
|
||||
PasswordChange
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
oldPasswordErrors: [],
|
||||
newPasswordErrors: []
|
||||
newPasswordErrors: [],
|
||||
showSuccess: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -37,6 +41,8 @@
|
|||
if (data.updatePassword.success) {
|
||||
this.oldPasswordErrors = [];
|
||||
this.newPasswordErrors = [];
|
||||
this.showSuccess = true;
|
||||
this.$root.$emit('reset-password-form')
|
||||
} else {
|
||||
// currently we just have one error per field
|
||||
const error = data.updatePassword.errors[0]
|
||||
|
|
@ -82,4 +88,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
.success-message {
|
||||
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__msg {
|
||||
color: $color-accent-4-dark;
|
||||
font-family: $sans-serif-font-family;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -19,7 +19,7 @@ import submission from '@/pages/studentSubmission'
|
|||
import portfolio from '@/pages/portfolio'
|
||||
import project from '@/pages/project'
|
||||
import profilePage from '@/pages/profile'
|
||||
import passwordReset from '@/pages/passwordReset'
|
||||
import passwordChange from '@/pages/passwordChange'
|
||||
|
||||
const routes = [
|
||||
{path: '/', component: start, meta: {layout: 'blank'}},
|
||||
|
|
@ -65,7 +65,7 @@ const routes = [
|
|||
]
|
||||
},
|
||||
{path: '/me', name: 'profile', component: profilePage},
|
||||
{path: '/password-reset', name: 'pw-reset', component: passwordReset},
|
||||
{path: '/password-change', name: 'pw-change', component: passwordChange},
|
||||
{path: '*', component: p404}
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ITerativ GmbH
|
||||
# http://www.iterativ.ch/
|
||||
#
|
||||
# Copyright (c) 2019 ITerativ GmbH. All rights reserved.
|
||||
#
|
||||
# Created on 2019-04-08
|
||||
# @author: chrigu <christian.cueni@iterativ.ch>
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management import BaseCommand
|
||||
|
||||
from books.models import Module
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# Positional arguments
|
||||
parser.add_argument('username', nargs='+', type=str)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.stdout.write("Reset Testuser Password")
|
||||
|
||||
email = "{}@skillbox.example".format(options['username'][0])
|
||||
|
||||
try:
|
||||
user = get_user_model().objects.get(email=email)
|
||||
user.set_password('test')
|
||||
user.save()
|
||||
self.stdout.write("Password reset successful")
|
||||
except get_user_model().DoesNotExist:
|
||||
self.stdout.write("No user found!")
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import graphene
|
||||
from django.contrib.auth import update_session_auth_hash
|
||||
from graphene import relay
|
||||
from users.inputs import PasswordUpdateInput
|
||||
from users.serializers import PasswordSerialzer
|
||||
|
|
@ -30,6 +31,7 @@ class UpdatePassword(relay.ClientIDMutation):
|
|||
if serializer.is_valid():
|
||||
user.set_password(password_data['new_password'])
|
||||
user.save()
|
||||
update_session_auth_hash(info.context, user)
|
||||
return cls(success=True)
|
||||
|
||||
errors = []
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@ def create_users(data=None):
|
|||
name='second_class'
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
else:
|
||||
for school_class in data:
|
||||
first, last = school_class.get('teacher')
|
||||
|
|
|
|||
Loading…
Reference in New Issue