diff --git a/backend/src/database/connection.ts b/backend/src/database/connection.ts deleted file mode 100644 index 584b657d2..000000000 --- a/backend/src/database/connection.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createConnection, Connection } from 'mysql2/promise' -import CONFIG from '../config' - -const connection = async (): Promise => { - const con = await createConnection({ - host: CONFIG.DB_HOST, - port: CONFIG.DB_PORT, - user: CONFIG.DB_USER, - password: CONFIG.DB_PASSWORD, - database: CONFIG.DB_DATABASE, - }) - - await con.connect() - - return con -} - -export default connection diff --git a/backend/src/graphql/resolvers/index.ts b/backend/src/graphql/resolvers/index.ts new file mode 100644 index 000000000..f42829645 --- /dev/null +++ b/backend/src/graphql/resolvers/index.ts @@ -0,0 +1,19 @@ +import { UserResolver } from './UserResolver' +import { BalanceResolver } from './BalanceResolver' +import { GdtResolver } from './GdtResolver' +import { TransactionResolver } from './TransactionResolver' +import { KlicktippResolver } from './KlicktippResolver' +import { NonEmptyArray } from 'type-graphql' + +export { UserResolver, BalanceResolver, GdtResolver, TransactionResolver, KlicktippResolver } + +// eslint-disable-next-line @typescript-eslint/ban-types +const resolvers = (): NonEmptyArray => [ + UserResolver, + BalanceResolver, + GdtResolver, + TransactionResolver, + KlicktippResolver, +] + +export default resolvers diff --git a/backend/src/graphql/schema.ts b/backend/src/graphql/schema.ts new file mode 100644 index 000000000..f18a3bea6 --- /dev/null +++ b/backend/src/graphql/schema.ts @@ -0,0 +1,14 @@ +import { GraphQLSchema } from 'graphql' +import { buildSchema } from 'type-graphql' + +import resolvers from './resolvers' +import { isAuthorized } from '../auth/auth' + +const schema = async (): Promise => { + return buildSchema({ + resolvers: resolvers(), + authChecker: isAuthorized, + }) +} + +export default schema diff --git a/backend/src/index.ts b/backend/src/index.ts index bd58f8c86..1c3814096 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -2,98 +2,58 @@ import 'reflect-metadata' import express from 'express' -import cors from 'cors' -import { buildSchema } from 'type-graphql' import { ApolloServer } from 'apollo-server-express' -import { RowDataPacket } from 'mysql2/promise' -import connection from './database/connection' -import typeOrmConnection from './typeorm/connection' +// config import CONFIG from './config' -// TODO move to extern -import { UserResolver } from './graphql/resolvers/UserResolver' -import { BalanceResolver } from './graphql/resolvers/BalanceResolver' -import { GdtResolver } from './graphql/resolvers/GdtResolver' -import { TransactionResolver } from './graphql/resolvers/TransactionResolver' -import { KlicktippResolver } from './graphql/resolvers/KlicktippResolver' +// database +import connection from './typeorm/connection' +import getDBVersion from './typeorm/getDBVersion' -import { isAuthorized } from './auth/auth' +// server +import cors from './server/cors' +import context from './server/context' +import plugins from './server/plugins' + +// graphql +import schema from './graphql/schema' // TODO implement // import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity"; const DB_VERSION = '0001-init_db' -const context = (args: any) => { - const authorization = args.req.headers.authorization - let token = null - if (authorization) { - token = authorization.replace(/^Bearer /, '') - } - const context = { - token, - setHeaders: [], - } - return context -} - async function main() { - // check for correct database version + // open mysql connection const con = await connection() - const [rows] = await con.query(`SELECT * FROM migrations ORDER BY version DESC LIMIT 1;`) - if ( - (rows).length === 0 || - !(rows)[0].fileName || - (rows)[0].fileName.indexOf(DB_VERSION) === -1 - ) { - throw new Error(`Wrong database version - the backend requires '${DB_VERSION}'`) + if (!con || !con.isConnected) { + throw new Error(`Couldn't open connection to database`) } - const toCon = await typeOrmConnection() - if (!toCon.isConnected) { - throw new Error(`Couldn't open typeorm db connection`) - } - - const schema = await buildSchema({ - resolvers: [UserResolver, BalanceResolver, TransactionResolver, GdtResolver, KlicktippResolver], - authChecker: isAuthorized, - }) - - // Graphiql interface - let playground = false - if (CONFIG.GRAPHIQL) { - playground = true + // check for correct database version + const dbVersion = await getDBVersion() + if (!dbVersion || dbVersion.indexOf(DB_VERSION) === -1) { + throw new Error( + `Wrong database version - the backend requires '${DB_VERSION}' but found '${ + dbVersion || 'None' + }'`, + ) } // Express Server const server = express() - const corsOptions = { - origin: '*', - exposedHeaders: ['token'], - } - - server.use(cors(corsOptions)) - - const plugins = [ - { - requestDidStart() { - return { - willSendResponse(requestContext: any) { - const { setHeaders = [] } = requestContext.context - setHeaders.forEach(({ key, value }: { [key: string]: string }) => { - requestContext.response.http.headers.append(key, value) - }) - return requestContext - }, - } - }, - }, - ] + // cors + server.use(cors) // Apollo Server - const apollo = new ApolloServer({ schema, playground, context, plugins }) + const apollo = new ApolloServer({ + schema: await schema(), + playground: CONFIG.GRAPHIQL, + context, + plugins, + }) apollo.applyMiddleware({ app: server }) // Start Server diff --git a/backend/src/server/context.ts b/backend/src/server/context.ts new file mode 100644 index 000000000..2ad4b520d --- /dev/null +++ b/backend/src/server/context.ts @@ -0,0 +1,14 @@ +const context = (args: any) => { + const authorization = args.req.headers.authorization + let token = null + if (authorization) { + token = authorization.replace(/^Bearer /, '') + } + const context = { + token, + setHeaders: [], + } + return context +} + +export default context diff --git a/backend/src/server/cors.ts b/backend/src/server/cors.ts new file mode 100644 index 000000000..e76ed1591 --- /dev/null +++ b/backend/src/server/cors.ts @@ -0,0 +1,8 @@ +import cors from 'cors' + +const corsOptions = { + origin: '*', + exposedHeaders: ['token'], +} + +export default cors(corsOptions) diff --git a/backend/src/server/plugins.ts b/backend/src/server/plugins.ts new file mode 100644 index 000000000..6b27d19ea --- /dev/null +++ b/backend/src/server/plugins.ts @@ -0,0 +1,17 @@ +const plugins = [ + { + requestDidStart() { + return { + willSendResponse(requestContext: any) { + const { setHeaders = [] } = requestContext.context + setHeaders.forEach(({ key, value }: { [key: string]: string }) => { + requestContext.response.http.headers.append(key, value) + }) + return requestContext + }, + } + }, + }, +] + +export default plugins diff --git a/backend/src/typeorm/connection.ts b/backend/src/typeorm/connection.ts index b108c5ef5..0fcd6aac3 100644 --- a/backend/src/typeorm/connection.ts +++ b/backend/src/typeorm/connection.ts @@ -2,18 +2,21 @@ import { createConnection, Connection } from 'typeorm' import CONFIG from '../config' import path from 'path' -const connection = async (): Promise => { - const con = await createConnection({ - name: 'default', - type: 'mysql', - host: CONFIG.DB_HOST, - port: CONFIG.DB_PORT, - username: CONFIG.DB_USER, - password: CONFIG.DB_PASSWORD, - database: CONFIG.DB_DATABASE, - entities: [path.join(__dirname, 'entity', '*.ts')], - synchronize: false, - }) +const connection = async (): Promise => { + let con = null + try { + con = await createConnection({ + name: 'default', + type: 'mysql', + host: CONFIG.DB_HOST, + port: CONFIG.DB_PORT, + username: CONFIG.DB_USER, + password: CONFIG.DB_PASSWORD, + database: CONFIG.DB_DATABASE, + entities: [path.join(__dirname, 'entity', '*.{ts,js}')], + synchronize: false, + }) + } catch (error) {} return con } diff --git a/backend/src/typeorm/entity/Migration.ts b/backend/src/typeorm/entity/Migration.ts new file mode 100644 index 000000000..f1163cfbc --- /dev/null +++ b/backend/src/typeorm/entity/Migration.ts @@ -0,0 +1,13 @@ +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' + +@Entity('migrations') +export class Migration extends BaseEntity { + @PrimaryGeneratedColumn() // This is actually not a primary column + version: number + + @Column({ length: 256, nullable: true, default: null }) + fileName: string + + @Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) + date: Date +} diff --git a/backend/src/typeorm/getDBVersion.ts b/backend/src/typeorm/getDBVersion.ts new file mode 100644 index 000000000..497a6da5e --- /dev/null +++ b/backend/src/typeorm/getDBVersion.ts @@ -0,0 +1,15 @@ +import { getConnection } from 'typeorm' +import { Migration } from './entity/Migration' + +const getDBVersion = async (): Promise => { + const connection = getConnection() + const migrations = connection.getRepository(Migration) + try { + const dbVersion = await migrations.findOne({ order: { version: 'DESC' } }) + return dbVersion ? dbVersion.fileName : null + } catch (error) { + return null + } +} + +export default getDBVersion diff --git a/docu/graphics/AnachBüberweisen.drawio b/docu/graphics/AnachBüberweisen.drawio new file mode 100644 index 000000000..e27e275f5 --- /dev/null +++ b/docu/graphics/AnachBüberweisen.drawio @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docu/graphics/AnachBüberweisen.png b/docu/graphics/AnachBüberweisen.png new file mode 100644 index 000000000..5fec2a577 Binary files /dev/null and b/docu/graphics/AnachBüberweisen.png differ diff --git a/frontend/.env.dist b/frontend/.env.dist index 1252faf5b..a7d67f970 100644 --- a/frontend/.env.dist +++ b/frontend/.env.dist @@ -1,5 +1,3 @@ -LOGIN_API_URL=http://localhost/login_api/ -COMMUNITY_API_URL=http://localhost/api/ ALLOW_REGISTER=true GRAPHQL_URI=http://localhost:4000/graphql //BUILD_COMMIT=0000000 \ No newline at end of file diff --git a/frontend/src/components/DecayInformation.vue b/frontend/src/components/DecayInformation.vue index 470f45dc7..04a850040 100644 --- a/frontend/src/components/DecayInformation.vue +++ b/frontend/src/components/DecayInformation.vue @@ -1,120 +1,114 @@ diff --git a/frontend/src/components/Inputs/InputPasswordConfirmation.vue b/frontend/src/components/Inputs/InputPasswordConfirmation.vue index 19d4ab02e..ecb3aa55a 100644 --- a/frontend/src/components/Inputs/InputPasswordConfirmation.vue +++ b/frontend/src/components/Inputs/InputPasswordConfirmation.vue @@ -9,6 +9,8 @@ containsUppercaseCharacter: true, containsNumericCharacter: true, atLeastEightCharactera: true, + atLeastOneSpecialCharater: true, + noWhitespaceCharacters: true, }" :label="register ? $t('form.password') : $t('form.password_new')" :showAllErrors="true" diff --git a/frontend/src/components/LanguageSwitchSelect.vue b/frontend/src/components/LanguageSwitchSelect.vue index 518bcf6cf..3467bdafd 100644 --- a/frontend/src/components/LanguageSwitchSelect.vue +++ b/frontend/src/components/LanguageSwitchSelect.vue @@ -14,7 +14,6 @@ export default { return { selected: null, options: [ - { value: null, text: this.$t('select_language') }, { value: 'de', text: this.$t('languages.de') }, { value: 'en', text: this.$t('languages.en') }, ], diff --git a/frontend/src/components/Transaction.vue b/frontend/src/components/Transaction.vue index 4358a3596..4071e809d 100644 --- a/frontend/src/components/Transaction.vue +++ b/frontend/src/components/Transaction.vue @@ -19,40 +19,40 @@ - + {{ getLinesByType(gdtEntryType).description }} - + {{ getLinesByType(gdtEntryType).descriptiontext }} - + {{ $t('gdt.credit') }} - + {{ getLinesByType(gdtEntryType).credittext }} - + {{ $t('form.memo') }} - + {{ comment }} - + {{ $t('form.date') }} - + {{ $d($moment(date), 'long') }} {{ $i18n.locale === 'de' ? 'Uhr' : '' }} diff --git a/frontend/src/components/TransactionCollapse.vue b/frontend/src/components/TransactionCollapse.vue index 444012820..aacc3b4f6 100644 --- a/frontend/src/components/TransactionCollapse.vue +++ b/frontend/src/components/TransactionCollapse.vue @@ -4,21 +4,21 @@ style="border: 0px; background-color: #f1f1f1" > -
+ {{ getLinesByType(gdtEntryType).headline }} -
+
-
+
{{ getLinesByType(gdtEntryType).first }}
{{ getLinesByType(gdtEntryType).second }}
-
-
+ +
{{ getLinesByType(gdtEntryType).firstMath }}
{{ getLinesByType(gdtEntryType).secondMath }}
-
+
@@ -33,6 +33,8 @@ export default { }, methods: { getLinesByType(givenType) { + if (givenType === 2 || givenType === 3 || givenType === 5 || givenType === 6) givenType = 1 + const linesByType = { 1: { headline: this.$t('gdt.calculation'), diff --git a/frontend/src/config/index.js b/frontend/src/config/index.js index 54c2c7aeb..96f7795ce 100644 --- a/frontend/src/config/index.js +++ b/frontend/src/config/index.js @@ -18,8 +18,6 @@ const environment = { } const server = { - LOGIN_API_URL: process.env.LOGIN_API_URL || 'http://localhost/login_api/', - COMMUNITY_API_URL: process.env.COMMUNITY_API_URL || 'http://localhost/api/', GRAPHQL_URI: process.env.GRAPHQL_URI || 'http://localhost:4000/graphql', } diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 2842a6a39..7155c1879 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -45,21 +45,14 @@ "amount": "Betrag", "at": "am", "cancel": "Abbrechen", - "change": "ändern", - "change-name": "Name ändern", - "change-password": "Passwort ändern", - "changeLanguage": "Sprache ändern", - "change_username_info": "Einmal gespeichert, kann der Username ncht mehr geändert werden!", "close": "schließen", "date": "Datum", "description": "Beschreibung", "edit": "bearbeiten", "email": "E-Mail", - "email_repeat": "eMail wiederholen", "firstname": "Vorname", "from": "von", "lastname": "Nachname", - "max_gdd_info": "Maximale anzahl GDD zum versenden erreicht!", "memo": "Nachricht", "message": "Nachricht", "password": "Passwort", @@ -81,7 +74,6 @@ "time": "Zeit", "to": "bis", "to1": "an", - "username": "Username", "validation": { "gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein", "is-not": "Du kannst dir selbst keine Gradidos überweisen", @@ -106,29 +98,40 @@ }, "imprint": "Impressum", "language": "Sprache", - "languages": { - "de": "Deutsch", - "en": "English", - "success": "Deine Sprache wurde erfolgreich geändert." - }, "login": "Anmeldung", "logout": "Abmelden", "members_area": "Mitgliederbereich", "message": "hallo gradido !!", "privacy_policy": "Datenschutzerklärung", - "reset": "Passwort zurücksetzen", - "reset-password": { - "not-authenticated": "Leider konnten wir dich nicht authentifizieren. Bitte wende dich an den Support.", - "text": "Jetzt kannst du ein neues Passwort speichern, mit dem du dich zukünftig in der Gradido-App anmelden kannst.", - "title": "Passwort zurücksetzen" - }, - "select_language": "Bitte wähle eine Sprache für die App und Newsletter", "send": "Senden", - "setting": { - "changeNewsletter": "Newsletter Status ändern", - "newsletter": "Newsletter", - "newsletterFalse": "Du bist aus Newslettersystem ausgetragen.", - "newsletterTrue": "Du bist im Newslettersystem eingetraten." + "settings": { + "language": { + "changeLanguage": "Sprache ändern", + "de": "Deutsch", + "en": "English", + "select_language": "Bitte wähle eine Sprache.", + "success": "Deine Sprache wurde erfolgreich geändert." + }, + "name": { + "change-name": "Name ändern", + "change-success": "Dein Name wurde erfolgreich geändert." + }, + "newsletter": { + "newsletter": "Newsletter", + "newsletterFalse": "Du bist aus Newslettersystem ausgetragen.", + "newsletterTrue": "Du bist im Newslettersystem eingetraten." + }, + "password": { + "change-password": "Passwort ändern", + "forgot_pwd": "Passwort vergessen?", + "reset": "Passwort zurücksetzen", + "reset-password": { + "not-authenticated": "Leider konnten wir dich nicht authentifizieren. Bitte wende dich an den Support.", + "text": "Jetzt kannst du ein neues Passwort speichern, mit dem du dich zukünftig in der Gradido-App anmelden kannst." + }, + "send_now": "Jetzt senden", + "subtitle": "Wenn du dein Passwort vergessen hast, kannst du es hier zurücksetzen." + } }, "signup": "Registrieren", "site": { @@ -143,34 +146,21 @@ }, "login": { "community": "Tausend Dank, weil du bei uns bist!", - "forgot_pwd": "Passwort vergessen?", "new_wallet": "Neues Konto erstellen", - "remember": "Passwort merken", "signin": "Anmelden" }, "navbar": { - "activity": "Aktivität", "my-profil": "Mein Profil", - "settings": "Einstellungen", "support": "Support" }, - "overview": { - "account_overview": "Kontoübersicht", - "add_work": "neuer Gemeinschaftsbeitrag", - "send_gradido": "Gradido versenden", - "since_last_month": "seid letzten Monat" - }, - "password": { - "send_now": "Jetzt senden", - "subtitle": "Wenn du dein Passwort vergessen hast, kannst du es hier zurücksetzen.", - "title": "Passwort zurücksetzen" - }, "signup": { "agree": "Ich stimme der Datenschutzerklärung zu.", "dont_match": "Die Passwörter stimmen nicht überein.", "lowercase": "Ein Kleinbuchstabe erforderlich.", "minimum": "Mindestens 8 Zeichen.", + "no-whitespace": "Keine Leerzeichen und Tabulatoren", "one_number": "Eine Zahl erforderlich.", + "special-char": "Ein Sonderzeichen erforderlich (z.B. _ oder ä)", "subtitle": "Werde Teil der Gemeinschaft!", "title": "Erstelle dein Gradido-Konto", "uppercase": "Ein Großbuchstabe erforderlich." @@ -192,6 +182,5 @@ "show_all": "Alle {count} Transaktionen ansehen" }, "transactions": "Transaktionen", - "welcome": "Willkommen!", "whitepaper": "Whitepaper" } diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 90faa6b33..d15f10b7d 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -45,21 +45,14 @@ "amount": "Amount", "at": "at", "cancel": "Cancel", - "change": "change", - "change-name": "Change name", - "change-password": "Change password", - "changeLanguage": "Change language", - "change_username_info": "Once saved, the username cannot be changed again!", "close": "Close", "date": "Date", "description": "Description", "edit": "Edit", "email": "Email", - "email_repeat": "Repeat Email", "firstname": "Firstname", "from": "from", "lastname": "Lastname", - "max_gdd_info": "Maximum number of GDDs to be sent has been reached!", "memo": "Message", "message": "Message", "password": "Password", @@ -81,7 +74,6 @@ "time": "Time", "to": "to", "to1": "to", - "username": "Username", "validation": { "gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits", "is-not": "You cannot send Gradidos to yourself", @@ -106,29 +98,40 @@ }, "imprint": "Legal notice", "language": "Language", - "languages": { - "de": "Deutsch", - "en": "English", - "success": "Your language has been successfully updated." - }, "login": "Login", "logout": "Logout", "members_area": "Member's area", "message": "hello gradido !!", "privacy_policy": "Privacy policy", - "reset": "Reset password", - "reset-password": { - "not-authenticated": "Unfortunately we could not authenticate you. Please contact the support.", - "text": "Now you can save a new password to login to the Gradido-App in the future.", - "title": "Reset Password" - }, - "select_language": "Please choose a language for the app and newsletter", "send": "Send", - "setting": { - "changeNewsletter": "Newsletter status change", - "newsletter": "Newsletter", - "newsletterFalse": "You are unsubscribed from newsletter system.", - "newsletterTrue": "You are subscribed to newsletter system." + "settings": { + "language": { + "changeLanguage": "Change language", + "de": "Deutsch", + "en": "English", + "select_language": "Please choose a language.", + "success": "Your language has been successfully updated." + }, + "name": { + "change-name": "Change name", + "change-success": "Your name has been successfully changed." + }, + "newsletter": { + "newsletter": "Newsletter", + "newsletterFalse": "You are unsubscribed from newsletter system.", + "newsletterTrue": "You are subscribed to newsletter system." + }, + "password": { + "change-password": "Change password", + "forgot_pwd": "Forgot password?", + "reset": "Reset password", + "reset-password": { + "not-authenticated": "Unfortunately we could not authenticate you. Please contact the support.", + "text": "Now you can save a new password to login to the Gradido-App in the future." + }, + "send_now": "Send now", + "subtitle": "If you have forgotten your password, you can reset it here." + } }, "signup": "Sign up", "site": { @@ -143,34 +146,21 @@ }, "login": { "community": "A thousand thanks for being with us!", - "forgot_pwd": "Forgot password?", "new_wallet": "Create new account", - "remember": "Remember password", "signin": "Sign in" }, "navbar": { - "activity": "Activity", "my-profil": "My profile", - "settings": "Settings", "support": "Support" }, - "overview": { - "account_overview": "Account overview", - "add_work": "New Community Contribution", - "send_gradido": "Send Gradido", - "since_last_month": "since last month" - }, - "password": { - "send_now": "Send now", - "subtitle": "If you have forgotten your password, you can reset it here.", - "title": "Reset password" - }, "signup": { "agree": "I agree to the privacy policy.", "dont_match": "Passwords don't match.", "lowercase": "One lowercase letter required.", "minimum": "8 characters minimum.", + "no-whitespace": "No white spaces and tabs", "one_number": "One number required.", + "special-char": "One special character required (e.g. _ or ä)", "subtitle": "Become a part of the community!", "title": "Create your Gradido account", "uppercase": "One uppercase letter required." @@ -192,6 +182,5 @@ "show_all": "View all {count} transactions." }, "transactions": "Transactions", - "welcome": "Welcome!", "whitepaper": "Whitepaper" } diff --git a/frontend/src/validation-rules.js b/frontend/src/validation-rules.js index da4e07b78..9ea954a92 100644 --- a/frontend/src/validation-rules.js +++ b/frontend/src/validation-rules.js @@ -112,6 +112,20 @@ export const loadAllRules = (i18nCallback) => { message: (_, values) => i18nCallback.t('site.signup.minimum', values), }) + extend('atLeastOneSpecialCharater', { + validate(value) { + return !!value.match(/[^a-zA-Z0-9]/) + }, + message: (_, values) => i18nCallback.t('site.signup.special-char', values), + }) + + extend('noWhitespaceCharacters', { + validate(value) { + return !!value.match(/[^ \t\n\r]/) + }, + message: (_, values) => i18nCallback.t('site.signup.no-whitespace', values), + }) + extend('samePassword', { validate(value, [pwd]) { return value === pwd diff --git a/frontend/src/views/Pages/AccountOverview/GddTransactionList.spec.js b/frontend/src/views/Pages/AccountOverview/GddTransactionList.spec.js index 5af115546..5418ff3ba 100644 --- a/frontend/src/views/Pages/AccountOverview/GddTransactionList.spec.js +++ b/frontend/src/views/Pages/AccountOverview/GddTransactionList.spec.js @@ -54,7 +54,7 @@ describe('GddTransactionList', () => { await wrapper.setProps({ transactions: [ { - balance: '19.93', + balance: 19.93, date: '2021-05-25T17:38:13+00:00', memo: 'Alles Gute zum Geburtstag', name: 'Bob der Baumeister', @@ -63,7 +63,7 @@ describe('GddTransactionList', () => { decay: { balance: '0.5' }, }, { - balance: '1000', + balance: 1000, date: '2021-04-29T15:34:49+00:00', memo: 'Gut das du da bist!', name: 'Gradido Akademie', @@ -71,7 +71,7 @@ describe('GddTransactionList', () => { type: 'creation', }, { - balance: '314.98', + balance: 314.98, date: '2021-04-29T17:26:40+00:00', memo: 'Für das Fahrrad!', name: 'Jan Ulrich', diff --git a/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue b/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue index bdf4199f3..7348f96de 100644 --- a/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue +++ b/frontend/src/views/Pages/AccountOverview/GddTransactionList.vue @@ -18,13 +18,13 @@ - +
-
+
@@ -70,7 +70,7 @@
- +
diff --git a/frontend/src/views/Pages/ForgotPassword.spec.js b/frontend/src/views/Pages/ForgotPassword.spec.js index d4615c221..91247d8a6 100644 --- a/frontend/src/views/Pages/ForgotPassword.spec.js +++ b/frontend/src/views/Pages/ForgotPassword.spec.js @@ -39,11 +39,11 @@ describe('ForgotPassword', () => { }) it('has a title', () => { - expect(wrapper.find('h1').text()).toEqual('site.password.title') + expect(wrapper.find('h1').text()).toEqual('settings.password.reset') }) it('has a subtitle', () => { - expect(wrapper.find('p.text-lead').text()).toEqual('site.password.subtitle') + expect(wrapper.find('p.text-lead').text()).toEqual('settings.password.subtitle') }) describe('back button', () => { diff --git a/frontend/src/views/Pages/ForgotPassword.vue b/frontend/src/views/Pages/ForgotPassword.vue index ad56ae95e..444e94495 100644 --- a/frontend/src/views/Pages/ForgotPassword.vue +++ b/frontend/src/views/Pages/ForgotPassword.vue @@ -5,8 +5,8 @@
-

{{ $t('site.password.title') }}

-

{{ $t('site.password.subtitle') }}

+

{{ $t('settings.password.reset') }}

+

{{ $t('settings.password.subtitle') }}

@@ -22,7 +22,7 @@
- {{ $t('site.password.send_now') }} + {{ $t('settings.password.send_now') }}
diff --git a/frontend/src/views/Pages/Login.spec.js b/frontend/src/views/Pages/Login.spec.js index 20eead7a3..7218384f7 100644 --- a/frontend/src/views/Pages/Login.spec.js +++ b/frontend/src/views/Pages/Login.spec.js @@ -71,7 +71,7 @@ describe('Login', () => { describe('links', () => { it('has a link "Forgot Password?"', () => { expect(wrapper.findAllComponents(RouterLinkStub).at(0).text()).toEqual( - 'site.login.forgot_pwd', + 'settings.password.forgot_pwd', ) }) diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index e5b365d75..f5c6f025d 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -40,7 +40,7 @@ - {{ $t('site.login.forgot_pwd') }} + {{ $t('settings.password.forgot_pwd') }} diff --git a/frontend/src/views/Pages/Register.spec.js b/frontend/src/views/Pages/Register.spec.js index 1a266606b..f3f66fca9 100644 --- a/frontend/src/views/Pages/Register.spec.js +++ b/frontend/src/views/Pages/Register.spec.js @@ -25,7 +25,7 @@ describe('Register', () => { $store: { state: { email: 'peter@lustig.de', - language: null, + language: 'en', }, }, } @@ -55,11 +55,11 @@ describe('Register', () => { describe('links', () => { it('has a link "Back"', () => { - expect(wrapper.findAllComponents(RouterLinkStub).at(0).text()).toEqual('back') + expect(wrapper.find('.test-button-back').text()).toEqual('back') }) it('links to /login when clicking "Back"', () => { - expect(wrapper.findAllComponents(RouterLinkStub).at(0).props().to).toBe('/login') + expect(wrapper.find('.test-button-back').props().to).toBe('/login') }) }) @@ -89,17 +89,17 @@ describe('Register', () => { it('has Language selected field', () => { expect(wrapper.find('.selectedLanguage').exists()).toBeTruthy() }) - it('selected Language value de', async () => { + it('selects Language value en', async () => { wrapper.find('.selectedLanguage').findAll('option').at(1).setSelected() - expect(wrapper.find('.selectedLanguage').element.value).toBe('de') + expect(wrapper.find('.selectedLanguage').element.value).toBe('en') }) it('has 1 checkbox input fields', () => { expect(wrapper.find('#registerCheckbox').exists()).toBeTruthy() }) - it('has no submit button when not completely filled', () => { - expect(wrapper.find('button[type="submit"]').exists()).toBe(false) + it('has disabled submit button when not completely filled', () => { + expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled') }) it('displays a message that Email is required', async () => { @@ -127,70 +127,20 @@ describe('Register', () => { }) }) - describe('resetForm', () => { - beforeEach(() => { - wrapper.find('#registerFirstname').setValue('Max') - wrapper.find('#registerLastname').setValue('Mustermann') - wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net') - wrapper.find('input[name="form.password"]').setValue('Aa123456') - wrapper.find('input[name="form.passwordRepeat"]').setValue('Aa123456') - wrapper.find('.language-switch-select').findAll('option').at(1).setSelected() - wrapper.find('input[name="site.signup.agree"]').setChecked(true) - }) - - it('reset selected value language', async () => { - await wrapper.find('button.ml-2').trigger('click') - await flushPromises() - expect(wrapper.find('.language-switch-select').element.value).toBe(undefined) - }) - - it('resets the firstName field after clicking the reset button', async () => { - await wrapper.find('button.ml-2').trigger('click') - await flushPromises() - expect(wrapper.find('#registerFirstname').element.value).toBe('') - }) - - it('resets the lastName field after clicking the reset button', async () => { - await wrapper.find('button.ml-2').trigger('click') - await flushPromises() - expect(wrapper.find('#registerLastname').element.value).toBe('') - }) - - it('resets the email field after clicking the reset button', async () => { - await wrapper.find('button.ml-2').trigger('click') - await flushPromises() - expect(wrapper.find('#Email-input-field').element.value).toBe('') - }) - - it.skip('resets the password field after clicking the reset button', async () => { - await wrapper.find('button.ml-2').trigger('click') - await flushPromises() - expect(wrapper.find('input[name="form.password"]').element.value).toBe('') - }) - - it.skip('resets the passwordRepeat field after clicking the reset button', async () => { - await wrapper.find('button.ml-2').trigger('click') - await flushPromises() - expect(wrapper.find('input[name="form.passwordRepeat"]').element.value).toBe('') - }) - - it('resets the firstName field after clicking the reset button', async () => { - await wrapper.find('button.ml-2').trigger('click') - await flushPromises() - expect(wrapper.find('input[name="site.signup.agree"]').props.checked).not.toBeTruthy() - }) - }) - describe('API calls', () => { beforeEach(() => { wrapper.find('#registerFirstname').setValue('Max') wrapper.find('#registerLastname').setValue('Mustermann') wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net') - wrapper.find('input[name="form.password"]').setValue('Aa123456') - wrapper.find('input[name="form.passwordRepeat"]').setValue('Aa123456') + wrapper.find('input[name="form.password"]').setValue('Aa123456_') + wrapper.find('input[name="form.passwordRepeat"]').setValue('Aa123456_') wrapper.find('.language-switch-select').findAll('option').at(1).setSelected() }) + it('has enabled submit button when completely filled', () => { + expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled') + }) + describe('server sends back error', () => { beforeEach(async () => { registerUserMutationMock.mockRejectedValue({ message: 'Ouch!' }) @@ -234,8 +184,8 @@ describe('Register', () => { email: 'max.mustermann@gradido.net', firstName: 'Max', lastName: 'Mustermann', - password: 'Aa123456', - language: 'de', + password: 'Aa123456_', + language: 'en', }, }), ) diff --git a/frontend/src/views/Pages/Register.vue b/frontend/src/views/Pages/Register.vue index 1a1b91bbe..f08ea286e 100755 --- a/frontend/src/views/Pages/Register.vue +++ b/frontend/src/views/Pages/Register.vue @@ -116,13 +116,19 @@ -
+
- {{ $t('form.reset') }} - {{ $t('signup') }} + + {{ $t('back') }} + + + + {{ $t('signup') }} +
@@ -131,9 +137,6 @@ -
- {{ $t('back') }} -
@@ -172,22 +175,6 @@ export default { getValidationState({ dirty, validated, valid = null }) { return dirty || validated ? valid : null }, - resetForm() { - this.form = { - firstname: '', - lastname: '', - email: '', - password: { - password: '', - passwordRepeat: '', - }, - agree: false, - } - this.language = '' - this.$nextTick(() => { - this.$refs.observer.reset() - }) - }, async onSubmit() { this.$apollo .mutate({ @@ -238,7 +225,7 @@ export default { return this.form.email !== '' }, languageFilled() { - return this.language !== null && this.language !== '' + return !!this.language }, }, } diff --git a/frontend/src/views/Pages/ResetPassword.spec.js b/frontend/src/views/Pages/ResetPassword.spec.js index 87198ba62..81ea7ed0f 100644 --- a/frontend/src/views/Pages/ResetPassword.spec.js +++ b/frontend/src/views/Pages/ResetPassword.spec.js @@ -71,8 +71,10 @@ describe('ResetPassword', () => { }) it('has a message suggesting to contact the support', () => { - expect(wrapper.find('div.header').text()).toContain('reset-password.title') - expect(wrapper.find('div.header').text()).toContain('reset-password.not-authenticated') + expect(wrapper.find('div.header').text()).toContain('settings.password.reset') + expect(wrapper.find('div.header').text()).toContain( + 'settings.password.reset-password.not-authenticated', + ) }) }) @@ -99,8 +101,10 @@ describe('ResetPassword', () => { describe('Register header', () => { it('has a welcome message', async () => { - expect(wrapper.find('div.header').text()).toContain('reset-password.title') - expect(wrapper.find('div.header').text()).toContain('reset-password.text') + expect(wrapper.find('div.header').text()).toContain('settings.password.reset') + expect(wrapper.find('div.header').text()).toContain( + 'settings.password.reset-password.text', + ) }) }) @@ -140,8 +144,8 @@ describe('ResetPassword', () => { beforeEach(async () => { await wrapper.setData({ authenticated: true, sessionId: 1 }) await wrapper.vm.$nextTick() - await wrapper.findAll('input').at(0).setValue('Aa123456') - await wrapper.findAll('input').at(1).setValue('Aa123456') + await wrapper.findAll('input').at(0).setValue('Aa123456_') + await wrapper.findAll('input').at(1).setValue('Aa123456_') await flushPromises() await wrapper.find('form').trigger('submit') }) @@ -169,7 +173,7 @@ describe('ResetPassword', () => { variables: { sessionId: 1, email: 'user@example.org', - password: 'Aa123456', + password: 'Aa123456_', }, }), ) diff --git a/frontend/src/views/Pages/ResetPassword.vue b/frontend/src/views/Pages/ResetPassword.vue index a9ca9e6c0..81b3d7df7 100644 --- a/frontend/src/views/Pages/ResetPassword.vue +++ b/frontend/src/views/Pages/ResetPassword.vue @@ -5,13 +5,13 @@
-

{{ $t('reset-password.title') }}

+

{{ $t('settings.password.reset') }}

- {{ $t('reset-password.text') }} + {{ $t('settings.password.reset-password.text') }} - {{ $t('reset-password.not-authenticated') }} + {{ $t('settings.password.reset-password.not-authenticated') }}
@@ -29,7 +29,7 @@
- {{ $t('reset') }} + {{ $t('settings.password.reset') }}
diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.spec.js b/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.spec.js index 87bb3edb9..927f1d29d 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.spec.js +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.spec.js @@ -139,7 +139,7 @@ describe('UserCard_FormUserData', () => { }) it('toasts a success message', () => { - expect(toastSuccessMock).toBeCalledWith('site.profil.user-data.change-success') + expect(toastSuccessMock).toBeCalledWith('settings.name.change-success') }) it('has an edit button again', () => { diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.vue b/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.vue index abdf9bb19..b3cee1ef5 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.vue +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserData.vue @@ -4,7 +4,7 @@ - {{ $t('form.change-name') }} + {{ $t('settings.name.change-name') }} @@ -122,7 +122,7 @@ export default { this.$store.commit('lastName', this.form.lastName) this.$store.commit('description', this.form.description) this.showUserData = true - this.$toasted.success(this.$t('site.profil.user-data.change-success')) + this.$toasted.success(this.$t('settings.name.change-success')) }) .catch((error) => { this.$toasted.error(error.message) diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js index dcce66b7f..264595240 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.spec.js @@ -47,7 +47,7 @@ describe('UserCard_FormUserPasswort', () => { }) it('has a change password button with text "form.change-password"', () => { - expect(wrapper.find('a').text()).toEqual('form.change-password') + expect(wrapper.find('a').text()).toEqual('settings.password.change-password') }) it('has a change password button with a pencil icon', () => { @@ -105,12 +105,14 @@ describe('UserCard_FormUserPasswort', () => { describe('validation', () => { it('displays all password requirements', () => { const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(5) + expect(feedbackArray).toHaveLength(7) expect(feedbackArray.at(0).text()).toBe('validations.messages.required') expect(feedbackArray.at(1).text()).toBe('site.signup.lowercase') expect(feedbackArray.at(2).text()).toBe('site.signup.uppercase') expect(feedbackArray.at(3).text()).toBe('site.signup.one_number') expect(feedbackArray.at(4).text()).toBe('site.signup.minimum') + expect(feedbackArray.at(5).text()).toBe('site.signup.special-char') + expect(feedbackArray.at(6).text()).toBe('site.signup.no-whitespace') }) it('removes first message when a character is given', async () => { @@ -125,7 +127,7 @@ describe('UserCard_FormUserPasswort', () => { await wrapper.findAll('input').at(1).setValue('a') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(3) + expect(feedbackArray).toHaveLength(4) expect(feedbackArray.at(0).text()).toBe('site.signup.uppercase') }) @@ -133,7 +135,7 @@ describe('UserCard_FormUserPasswort', () => { await wrapper.findAll('input').at(1).setValue('Aa') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(2) + expect(feedbackArray).toHaveLength(3) expect(feedbackArray.at(0).text()).toBe('site.signup.one_number') }) @@ -141,14 +143,22 @@ describe('UserCard_FormUserPasswort', () => { await wrapper.findAll('input').at(1).setValue('Aa1') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') - expect(feedbackArray).toHaveLength(1) + expect(feedbackArray).toHaveLength(2) expect(feedbackArray.at(0).text()).toBe('site.signup.minimum') }) - it('removes all messages when all rules are fulfilled', async () => { + it('removes the first five messages when a eight lowercase, uppercase and numeric characters are given', async () => { await wrapper.findAll('input').at(1).setValue('Aa123456') await flushPromises() const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') + expect(feedbackArray).toHaveLength(1) + expect(feedbackArray.at(0).text()).toBe('site.signup.special-char') + }) + + it('removes all messages when a eight lowercase, uppercase and numeric characters are given', async () => { + await wrapper.findAll('input').at(1).setValue('Aa123456_') + await flushPromises() + const feedbackArray = wrapper.findAll('div.invalid-feedback').at(1).findAll('span') expect(feedbackArray).toHaveLength(0) }) }) @@ -164,8 +174,8 @@ describe('UserCard_FormUserPasswort', () => { }, }) await form.findAll('input').at(0).setValue('1234') - await form.findAll('input').at(1).setValue('Aa123456') - await form.findAll('input').at(2).setValue('Aa123456') + await form.findAll('input').at(1).setValue('Aa123456_') + await form.findAll('input').at(2).setValue('Aa123456_') await form.trigger('submit') await flushPromises() }) @@ -176,7 +186,7 @@ describe('UserCard_FormUserPasswort', () => { variables: { email: 'user@example.org', password: '1234', - passwordNew: 'Aa123456', + passwordNew: 'Aa123456_', }, }), ) @@ -197,8 +207,8 @@ describe('UserCard_FormUserPasswort', () => { message: 'error', }) await form.findAll('input').at(0).setValue('1234') - await form.findAll('input').at(1).setValue('Aa123456') - await form.findAll('input').at(2).setValue('Aa123456') + await form.findAll('input').at(1).setValue('Aa123456_') + await form.findAll('input').at(2).setValue('Aa123456_') await form.trigger('submit') await flushPromises() }) diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.vue b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.vue index f1c531468..1f6c34c26 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.vue +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUserPasswort.vue @@ -4,7 +4,7 @@ - {{ $t('form.change-password') }} + {{ $t('settings.password.change-password') }} diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.spec.js b/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.spec.js index 1791d326c..a55c223d7 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.spec.js +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.spec.js @@ -125,7 +125,7 @@ describe('UserCard_FormUsername', () => { }) it('toasts an success message', () => { - expect(toastSuccessMock).toBeCalledWith('site.profil.user-data.change-success') + expect(toastSuccessMock).toBeCalledWith('settings.name.change-success') }) it('has no edit button anymore', () => { diff --git a/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.vue b/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.vue index 7c100f41f..f9d46bbba 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.vue +++ b/frontend/src/views/Pages/UserProfile/UserCard_FormUsername.vue @@ -98,7 +98,7 @@ export default { this.$store.commit('username', this.form.username) this.username = this.form.username this.showUsername = true - this.$toasted.success(this.$t('site.profil.user-data.change-success')) + this.$toasted.success(this.$t('settings.name.change-success')) }) .catch((error) => { this.$toasted.error(error.message) diff --git a/frontend/src/views/Pages/UserProfile/UserCard_Language.vue b/frontend/src/views/Pages/UserProfile/UserCard_Language.vue index 2632f8186..8d05620c9 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_Language.vue +++ b/frontend/src/views/Pages/UserProfile/UserCard_Language.vue @@ -4,7 +4,7 @@ - {{ $t('form.changeLanguage') }} + {{ $t('settings.language.changeLanguage') }} @@ -97,7 +97,7 @@ export default { this.$i18n.locale = this.language localeChanged(this.language) this.cancelEdit() - this.$toasted.success(this.$t('languages.success')) + this.$toasted.success(this.$t('settings.language.success')) }) .catch((error) => { this.language = this.$store.state.language diff --git a/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.spec.js b/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.spec.js index febb47fd6..3a70840e1 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.spec.js +++ b/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.spec.js @@ -74,7 +74,7 @@ describe('UserCard_Newsletter', () => { }) it('toasts a success message', () => { - expect(toastSuccessMock).toBeCalledWith('setting.newsletterFalse') + expect(toastSuccessMock).toBeCalledWith('settings.newsletter.newsletterFalse') }) }) diff --git a/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.vue b/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.vue index c571ef99a..31fd745b2 100644 --- a/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.vue +++ b/frontend/src/views/Pages/UserProfile/UserCard_Newsletter.vue @@ -4,7 +4,7 @@ - {{ $t('setting.newsletter') }} + {{ $t('settings.newsletter.newsletter') }} @@ -15,7 +15,11 @@ switch @change="onSubmit" > - {{ newsletterState ? $t('setting.newsletterTrue') : $t('setting.newsletterFalse') }} + {{ + newsletterState + ? $t('settings.newsletter.newsletterTrue') + : $t('settings.newsletter.newsletterFalse') + }} @@ -46,8 +50,8 @@ export default { this.$store.commit('newsletterState', this.newsletterState) this.$toasted.success( this.newsletterState - ? this.$t('setting.newsletterTrue') - : this.$t('setting.newsletterFalse'), + ? this.$t('settings.newsletter.newsletterTrue') + : this.$t('settings.newsletter.newsletterFalse'), ) }) .catch((error) => { diff --git a/frontend/test/testSetup.js b/frontend/test/testSetup.js index 7005ff5be..daf862548 100644 --- a/frontend/test/testSetup.js +++ b/frontend/test/testSetup.js @@ -1,6 +1,7 @@ import { createLocalVue } from '@vue/test-utils' import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' import Vuex from 'vuex' +import Vue from 'vue' import { ValidationProvider, ValidationObserver, extend } from 'vee-validate' import * as rules from 'vee-validate/dist/rules' @@ -47,3 +48,8 @@ global.localVue.component('validation-provider', ValidationProvider) global.localVue.component('validation-observer', ValidationObserver) global.localVue.directive('click-outside', clickOutside) global.localVue.directive('focus', focus) + +// throw errors for vue warnings to force the programmers to take care about warnings +Vue.config.warnHandler = (w) => { + throw new Error(w) +} diff --git a/login_server/src/LOCALE/de_DE.mo b/login_server/src/LOCALE/de_DE.mo index bfee8efd3..d3d2c86e9 100644 Binary files a/login_server/src/LOCALE/de_DE.mo and b/login_server/src/LOCALE/de_DE.mo differ diff --git a/login_server/src/LOCALE/de_DE.po b/login_server/src/LOCALE/de_DE.po index b4bca3098..b9eea0d59 100644 --- a/login_server/src/LOCALE/de_DE.po +++ b/login_server/src/LOCALE/de_DE.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-21 13:37+0200\n" -"PO-Revision-Date: 2021-06-21 13:38+0200\n" +"POT-Creation-Date: 2021-09-23 17:56+0200\n" +"PO-Revision-Date: 2021-09-27 13:31+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de_DE\n" @@ -455,11 +455,10 @@ msgstr "Gradido: Passwort zurücksetzen" #: src/cpp/SingletonManager/SessionManager.cpp:604 msgid "" "Please enter a valid password with at least 8 characters, upper and lower " -"case letters, at least one number and one special character (@$!%*?&+-_)!" +"case letters, at least one number and one special character!" msgstr "" "Bitte gebe ein gültiges Password ein mit mindestens 8 Zeichen, Groß- und " -"Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen (@$!%*?&+-_) " -"ein!" +"Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen!" #: src/cpp/SingletonManager/SessionManager.cpp:610 msgid "Your password is to short!" @@ -478,8 +477,8 @@ msgid "Your password does not contain any number!" msgstr "Dein Passwort enthält keine Zahlen!" #: src/cpp/SingletonManager/SessionManager.cpp:630 -msgid "Your password does not contain special characters (@$!%*?&+-)!" -msgstr "Dein Passwort enthält keine Sonderzeichen (@$!%*?&+-)!" +msgid "Your password does not contain special characters!" +msgstr "Dein Passwort enthält keine Sonderzeichen!" #~ msgid "Account" #~ msgstr "Konto" diff --git a/login_server/src/cpp/SingletonManager/SessionManager.cpp b/login_server/src/cpp/SingletonManager/SessionManager.cpp index d854c2a97..c4039b10d 100644 --- a/login_server/src/cpp/SingletonManager/SessionManager.cpp +++ b/login_server/src/cpp/SingletonManager/SessionManager.cpp @@ -46,22 +46,22 @@ bool SessionManager::init() case VALIDATE_NAME: mValidations[i] = new Poco::RegularExpression("^[^<>&;]{2,}$"); break; case VALIDATE_USERNAME: mValidations[i] = new Poco::RegularExpression("^[a-zA-Z][a-zA-Z0-9_-]*$"); break; case VALIDATE_EMAIL: mValidations[i] = new Poco::RegularExpression("^[a-zA-Z0-9.!#$%&?*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"); break; - case VALIDATE_PASSWORD: mValidations[i] = new Poco::RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@$!%*?&+-_])[A-Za-z0-9@$!%*?&+-_]{8,}$"); break; + case VALIDATE_PASSWORD: mValidations[i] = new Poco::RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9 \\t\\n\\r]).{8,}$"); break; case VALIDATE_PASSPHRASE: mValidations[i] = new Poco::RegularExpression("^(?:[a-z]* ){23}[a-z]*\s*$"); break; case VALIDATE_GROUP_ALIAS: mValidations[i] = new Poco::RegularExpression("^[a-z0-9-]{3,120}"); break; case VALIDATE_HEDERA_ID: mValidations[i] = new Poco::RegularExpression("^[0-9]*\.[0-9]*\.[0-9]\.$"); break; - case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression(".*[0-9].*"); break; + case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression("[0-9]"); break; case VALIDATE_ONLY_INTEGER: mValidations[i] = new Poco::RegularExpression("^[0-9]*$"); break; case VALIDATE_ONLY_DECIMAL: mValidations[i] = new Poco::RegularExpression("^[0-9]*(\.|,)[0-9]*$"); break; case VALIDATE_ONLY_HEX: mValidations[i] = new Poco::RegularExpression("^(0x)?[a-fA-F0-9]*$"); break; //case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}$"); break; case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\/?"); break; - case VALIDATE_HAS_SPECIAL_CHARACTER: mValidations[i] = new Poco::RegularExpression(".*[@$!%*?&+-].*"); break; + case VALIDATE_HAS_SPECIAL_CHARACTER: mValidations[i] = new Poco::RegularExpression("[^a-zA-Z0-9 \\t\\n\\r]"); break; case VALIDATE_HAS_UPPERCASE_LETTER: - mValidations[i] = new Poco::RegularExpression(".*[A-Z].*"); + mValidations[i] = new Poco::RegularExpression("[A-Z]"); ServerConfig::g_ServerKeySeed->put(i, DRRandom::r64()); break; - case VALIDATE_HAS_LOWERCASE_LETTER: mValidations[i] = new Poco::RegularExpression(".*[a-z].*"); break; + case VALIDATE_HAS_LOWERCASE_LETTER: mValidations[i] = new Poco::RegularExpression("[a-z]"); break; default: printf("[SessionManager::%s] unknown validation type\n", __FUNCTION__); } } @@ -601,7 +601,7 @@ bool SessionManager::checkPwdValidation(const std::string& pwd, NotificationList if (!isValid(pwd, VALIDATE_PASSWORD)) { errorReciver->addError(new Error( lang->gettext("Password"), - lang->gettext("Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character (@$!%*?&+-_)!"))); + lang->gettext("Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!"))); // @$!%*?&+- if (pwd.size() < 8) { @@ -627,7 +627,7 @@ bool SessionManager::checkPwdValidation(const std::string& pwd, NotificationList else if (!isValid(pwd, VALIDATE_HAS_SPECIAL_CHARACTER)) { errorReciver->addError(new Error( lang->gettext("Password"), - lang->gettext("Your password does not contain special characters (@$!%*?&+-)!"))); + lang->gettext("Your password does not contain special characters!"))); } return false; diff --git a/login_server/src/cpsp/UserUpdatePassword.cpsp b/login_server/src/cpsp/UserUpdatePassword.cpsp index 04d1e487e..260a29475 100644 --- a/login_server/src/cpsp/UserUpdatePassword.cpsp +++ b/login_server/src/cpsp/UserUpdatePassword.cpsp @@ -85,7 +85,7 @@ enum PageState {

Bitte denke dir ein sicheres Passwort aus, das mindestens 8 Zeichen lang ist, einen Klein- und einen Großbuchstaben enthält, - eine Zahl und eines der folgenden Sonderzeichen: @$!%*?&+- + eine Zahl und ein Sonderzeichen.