mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
Merge pull request #3369 from gradido/increase_initialien_count
feat(backend): increase initialien count
This commit is contained in:
commit
066bb9bbad
@ -50,7 +50,8 @@
|
||||
"sodium-native": "^3.3.0",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typed-rest-client": "^1.8.11",
|
||||
"uuid": "^8.3.2"
|
||||
"uuid": "^8.3.2",
|
||||
"xregexp": "^5.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "^3.2.1",
|
||||
|
||||
@ -9,9 +9,11 @@ import { checkDBVersion } from '@/typeorm/DBVersion'
|
||||
|
||||
import { HumHubClient } from './HumHubClient'
|
||||
import { GetUser } from './model/GetUser'
|
||||
import { UsersResponse } from './model/UsersResponse'
|
||||
import { ExecutedHumhubAction, syncUser } from './syncUser'
|
||||
|
||||
const USER_BULK_SIZE = 20
|
||||
const HUMHUB_BULK_SIZE = 50
|
||||
|
||||
function getUsersPage(page: number, limit: number): Promise<[User[], number]> {
|
||||
return User.findAndCount({
|
||||
@ -29,24 +31,28 @@ function getUsersPage(page: number, limit: number): Promise<[User[], number]> {
|
||||
async function loadUsersFromHumHub(client: HumHubClient): Promise<Map<string, GetUser>> {
|
||||
const start = new Date().getTime()
|
||||
const humhubUsers = new Map<string, GetUser>()
|
||||
const firstPage = await client.users(0, 50)
|
||||
if (!firstPage) {
|
||||
throw new LogError('not a single user found on humhub, please check config and setup')
|
||||
}
|
||||
firstPage.results.forEach((user) => {
|
||||
humhubUsers.set(user.account.email.trim(), user)
|
||||
})
|
||||
let page = 1
|
||||
while (humhubUsers.size < firstPage.total) {
|
||||
const usersPage = await client.users(page, 50)
|
||||
let page = 0
|
||||
let skippedUsersCount = 0
|
||||
let usersPage: UsersResponse | null = null
|
||||
do {
|
||||
usersPage = await client.users(page, HUMHUB_BULK_SIZE)
|
||||
if (!usersPage) {
|
||||
throw new LogError('error requesting next users page from humhub')
|
||||
}
|
||||
usersPage.results.forEach((user) => {
|
||||
humhubUsers.set(user.account.email.trim(), user)
|
||||
// deleted users have empty emails
|
||||
if (user.account.email) {
|
||||
humhubUsers.set(user.account.email.trim(), user)
|
||||
} else {
|
||||
skippedUsersCount++
|
||||
}
|
||||
})
|
||||
page++
|
||||
}
|
||||
process.stdout.write(
|
||||
`load users from humhub: ${humhubUsers.size}/${usersPage.total}, skipped: ${skippedUsersCount}\r`,
|
||||
)
|
||||
} while (usersPage && usersPage.results.length === HUMHUB_BULK_SIZE)
|
||||
|
||||
const elapsed = new Date().getTime() - start
|
||||
logger.info('load users from humhub', {
|
||||
total: humhubUsers.size,
|
||||
|
||||
@ -2,15 +2,13 @@
|
||||
import { User } from '@entity/User'
|
||||
|
||||
import { convertGradidoLanguageToHumhub } from '@/apis/humhub/convertLanguage'
|
||||
import { PublishNameLogic } from '@/data/PublishName.logic'
|
||||
import { PublishNameType } from '@/graphql/enum/PublishNameType'
|
||||
|
||||
export class Account {
|
||||
public constructor(user: User) {
|
||||
if (user.alias && user.alias.length > 2) {
|
||||
this.username = user.alias
|
||||
} else {
|
||||
this.username = user.gradidoID
|
||||
}
|
||||
|
||||
const publishNameLogic = new PublishNameLogic(user)
|
||||
this.username = publishNameLogic.getUsername(user.humhubPublishName as PublishNameType)
|
||||
this.email = user.emailContact.email
|
||||
this.language = convertGradidoLanguageToHumhub(user.language)
|
||||
this.status = 1
|
||||
|
||||
@ -10,7 +10,10 @@ export class Profile {
|
||||
const publishNameLogic = new PublishNameLogic(user)
|
||||
this.firstname = publishNameLogic.getFirstName(user.humhubPublishName as PublishNameType)
|
||||
this.lastname = publishNameLogic.getLastName(user.humhubPublishName as PublishNameType)
|
||||
this.gradido_address = CONFIG.COMMUNITY_NAME + '/' + user.gradidoID
|
||||
|
||||
this.gradido_address = `${CONFIG.COMMUNITY_NAME}/${
|
||||
publishNameLogic.hasAlias() ? user.alias : user.gradidoID
|
||||
}`
|
||||
}
|
||||
|
||||
firstname: string
|
||||
|
||||
23
backend/src/data/PublishName.logic.test.ts
Normal file
23
backend/src/data/PublishName.logic.test.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { User } from '@entity/User'
|
||||
|
||||
import { PublishNameType } from '@/graphql/enum/PublishNameType'
|
||||
|
||||
import { PublishNameLogic } from './PublishName.logic'
|
||||
|
||||
describe('test publish name logic', () => {
|
||||
describe('test username', () => {
|
||||
it('alias or initials with alias set', () => {
|
||||
const user = new User()
|
||||
user.alias = 'alias'
|
||||
const logic = new PublishNameLogic(user)
|
||||
expect(logic.getUsername(PublishNameType.PUBLISH_NAME_ALIAS_OR_INITALS)).toBe(user.alias)
|
||||
})
|
||||
it('alias or initials with empty alias', () => {
|
||||
const user = new User()
|
||||
user.firstName = 'John'
|
||||
user.lastName = 'Smith'
|
||||
const logic = new PublishNameLogic(user)
|
||||
expect(logic.getUsername(PublishNameType.PUBLISH_NAME_ALIAS_OR_INITALS)).toBe('JoSm')
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,61 +1,83 @@
|
||||
import { User } from '@entity/User'
|
||||
import XRegExp from 'xregexp'
|
||||
|
||||
import { PublishNameType } from '@/graphql/enum/PublishNameType'
|
||||
|
||||
export class PublishNameLogic {
|
||||
// allowed characters for humhub usernames
|
||||
private usernameRegex: RegExp = XRegExp('[\\p{L}\\d_\\-@\\.]', 'g')
|
||||
|
||||
constructor(private user: User) {}
|
||||
|
||||
private firstUpperCaseSecondLowerCase(name: string) {
|
||||
if (name && name.length >= 2) {
|
||||
return name.charAt(0).toUpperCase() + name.charAt(1).toLocaleLowerCase()
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// remove character which are invalid for humhub username
|
||||
private filterOutInvalidChar(name: string) {
|
||||
// eslint-disable-next-line import/no-named-as-default-member
|
||||
return XRegExp.match(name, this.usernameRegex, 'all').join('')
|
||||
}
|
||||
|
||||
public hasAlias(): boolean {
|
||||
if (this.user.alias && this.user.alias.length >= 3) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* get first name based on publishNameType: PublishNameType value
|
||||
* @param publishNameType
|
||||
* @returns user.firstName for PUBLISH_NAME_FIRST, PUBLISH_NAME_FIRST_INITIAL or PUBLISH_NAME_FULL
|
||||
* first initial from user.firstName for PUBLISH_NAME_INITIALS or PUBLISH_NAME_INITIAL_LAST
|
||||
*/
|
||||
public getFirstName(publishNameType: PublishNameType): string {
|
||||
if (
|
||||
[
|
||||
PublishNameType.PUBLISH_NAME_FIRST,
|
||||
PublishNameType.PUBLISH_NAME_FIRST_INITIAL,
|
||||
PublishNameType.PUBLISH_NAME_FULL,
|
||||
].includes(publishNameType)
|
||||
) {
|
||||
return this.user.firstName
|
||||
}
|
||||
if (PublishNameType.PUBLISH_NAME_INITIALS === publishNameType) {
|
||||
return this.user.firstName.substring(0, 1)
|
||||
}
|
||||
if (PublishNameType.PUBLISH_NAME_ALIAS_OR_INITALS === publishNameType) {
|
||||
if (this.user.alias) {
|
||||
return this.user.alias
|
||||
} else {
|
||||
return this.user.firstName.substring(0, 1)
|
||||
}
|
||||
}
|
||||
return ''
|
||||
return [
|
||||
PublishNameType.PUBLISH_NAME_FIRST,
|
||||
PublishNameType.PUBLISH_NAME_FIRST_INITIAL,
|
||||
PublishNameType.PUBLISH_NAME_FULL,
|
||||
].includes(publishNameType)
|
||||
? this.user.firstName
|
||||
: ''
|
||||
}
|
||||
|
||||
/**
|
||||
* get last name based on publishNameType: GmsPublishNameType value
|
||||
* @param publishNameType
|
||||
* @returns user.lastName for PUBLISH_NAME_LAST, PUBLISH_NAME_INITIAL_LAST, PUBLISH_NAME_FULL
|
||||
* first initial from user.lastName for PUBLISH_NAME_FIRST_INITIAL, PUBLISH_NAME_INITIALS
|
||||
* @returns user.lastName for PUBLISH_NAME_LAST, PUBLISH_NAME_FULL
|
||||
* first initial from user.lastName for PUBLISH_NAME_FIRST_INITIAL
|
||||
*/
|
||||
public getLastName(publishNameType: PublishNameType): string {
|
||||
if (PublishNameType.PUBLISH_NAME_FULL === publishNameType) {
|
||||
return this.user.lastName
|
||||
} else if (
|
||||
[PublishNameType.PUBLISH_NAME_FIRST_INITIAL, PublishNameType.PUBLISH_NAME_INITIALS].includes(
|
||||
publishNameType,
|
||||
)
|
||||
) {
|
||||
return this.user.lastName.substring(0, 1)
|
||||
} else if (
|
||||
PublishNameType.PUBLISH_NAME_ALIAS_OR_INITALS === publishNameType &&
|
||||
!this.user.alias
|
||||
) {
|
||||
return this.user.lastName.substring(0, 1)
|
||||
}
|
||||
return publishNameType === PublishNameType.PUBLISH_NAME_FULL
|
||||
? this.user.lastName
|
||||
: publishNameType === PublishNameType.PUBLISH_NAME_FIRST_INITIAL
|
||||
? this.user.lastName.charAt(0)
|
||||
: ''
|
||||
}
|
||||
|
||||
return ''
|
||||
/**
|
||||
* get username from user.alias for PUBLISH_NAME_ALIAS_OR_INITALS and if user has alias
|
||||
* get first name first two characters and last name first two characters for PUBLISH_NAME_ALIAS_OR_INITALS
|
||||
* if no alias or PUBLISH_NAME_INITIALS
|
||||
* @param publishNameType
|
||||
* @returns user.alias for publishNameType = PUBLISH_NAME_ALIAS_OR_INITALS and user has alias
|
||||
* else return user.firstName[0,2] + user.lastName[0,2] for publishNameType = [PUBLISH_NAME_ALIAS_OR_INITALS, PUBLISH_NAME_INITIALS]
|
||||
*/
|
||||
public getUsername(publishNameType: PublishNameType): string {
|
||||
if (
|
||||
[
|
||||
PublishNameType.PUBLISH_NAME_ALIAS_OR_INITALS,
|
||||
PublishNameType.PUBLISH_NAME_INITIALS,
|
||||
].includes(publishNameType)
|
||||
) {
|
||||
return publishNameType === PublishNameType.PUBLISH_NAME_ALIAS_OR_INITALS && this.hasAlias()
|
||||
? this.filterOutInvalidChar(this.user.alias)
|
||||
: this.firstUpperCaseSecondLowerCase(this.filterOutInvalidChar(this.user.firstName)) +
|
||||
this.firstUpperCaseSecondLowerCase(this.filterOutInvalidChar(this.user.lastName))
|
||||
}
|
||||
return this.hasAlias() ? this.user.alias : this.user.gradidoID
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ import { subscribe } from '@/apis/KlicktippController'
|
||||
import { encode } from '@/auth/JWT'
|
||||
import { RIGHTS } from '@/auth/RIGHTS'
|
||||
import { CONFIG } from '@/config'
|
||||
import { PublishNameLogic } from '@/data/PublishName.logic'
|
||||
import {
|
||||
sendAccountActivationEmail,
|
||||
sendAccountMultiRegistrationEmail,
|
||||
@ -59,6 +60,7 @@ import {
|
||||
EVENT_ADMIN_USER_DELETE,
|
||||
EVENT_ADMIN_USER_UNDELETE,
|
||||
} from '@/event/Events'
|
||||
import { PublishNameType } from '@/graphql/enum/PublishNameType'
|
||||
import { isValidPassword } from '@/password/EncryptorUtils'
|
||||
import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor'
|
||||
import { Context, getUser, getClientTimezoneOffset } from '@/server/context'
|
||||
@ -168,8 +170,9 @@ export class UserResolver {
|
||||
let humhubUserPromise: Promise<IRestResponse<GetUser>> | undefined
|
||||
const klicktippStatePromise = getKlicktippState(dbUser.emailContact.email)
|
||||
if (CONFIG.HUMHUB_ACTIVE && dbUser.humhubAllowed) {
|
||||
const publishNameLogic = new PublishNameLogic(dbUser)
|
||||
humhubUserPromise = HumHubClient.getInstance()?.userByUsernameAsync(
|
||||
dbUser.alias ?? dbUser.gradidoID,
|
||||
publishNameLogic.getUsername(dbUser.humhubPublishName as PublishNameType),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -324,6 +324,14 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
|
||||
"@babel/runtime-corejs3@^7.16.5":
|
||||
version "7.25.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.25.7.tgz#29ca319b1272e9d78faa3f7ee891d0af63c53aa2"
|
||||
integrity sha512-gMmIEhg35sXk9Te5qbGp3W9YKrvLt3HV658/d3odWrHSqT0JeG5OzsJWFHRLiOohRyjRsJc/x03DhJm3i8VJxg==
|
||||
dependencies:
|
||||
core-js-pure "^3.30.2"
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.21.0":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
|
||||
@ -2340,6 +2348,11 @@ core-js-pure@^3.10.2:
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.18.2.tgz#d8cc11d4885ea919f3de776d45e720e4c769d406"
|
||||
integrity sha512-4hMMLUlZhKJKOWbbGD1/VDUxGPEhEoN/T01k7bx271WiBKCvCfkgPzy0IeRS4PB50p6/N1q/SZL4B/TRsTE5bA==
|
||||
|
||||
core-js-pure@^3.30.2:
|
||||
version "3.38.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.38.1.tgz#e8534062a54b7221344884ba9b52474be495ada3"
|
||||
integrity sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
|
||||
@ -6165,6 +6178,11 @@ regenerator-runtime@^0.13.11:
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
|
||||
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
|
||||
|
||||
regenerator-runtime@^0.14.0:
|
||||
version "0.14.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
|
||||
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
|
||||
|
||||
regexp-tree@~0.1.1:
|
||||
version "0.1.27"
|
||||
resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd"
|
||||
@ -7395,6 +7413,13 @@ xmlchars@^2.2.0:
|
||||
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
||||
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
|
||||
|
||||
xregexp@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-5.1.1.tgz#6d3fe18819e3143aaf52f9284d34f49a59583ebb"
|
||||
integrity sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs3" "^7.16.5"
|
||||
|
||||
xss@^1.0.8:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.10.tgz#5cd63a9b147a755a14cb0455c7db8866120eb4d2"
|
||||
|
||||
@ -387,13 +387,13 @@
|
||||
},
|
||||
"publish-name": {
|
||||
"alias-or-initials": "Benutzername oder Initialen",
|
||||
"alias-or-initials-tooltip": "Benutzername, falls vorhanden, oder die Initialen von Vorname und Nachname",
|
||||
"alias-or-initials-tooltip": "Benutzername, falls vorhanden, oder die Initialen von Vorname und Nachname jeweils die ersten zwei Buchstaben",
|
||||
"first": "Vorname",
|
||||
"first-tooltip": "Nur der Vornamen",
|
||||
"first-initial": "Vorname und Initial",
|
||||
"first-initial-tooltip": "Vornamen plus Anfangsbuchstabe des Nachnamens",
|
||||
"first-initial-tooltip": "Vornamen plus die ersten beiden Anfangsbuchstabe des Nachnamens",
|
||||
"initials": "Initialen",
|
||||
"initials-tooltip": "Initialen von Vor- und Nachname unabhängig von der Existenz des Benutzernamens",
|
||||
"initials-tooltip": "Initialen von Vor- und Nachname also jeweils die ersten zwei Buchstaben unabhängig von der Existenz des Benutzernamens",
|
||||
"name-full": "Vorname und Nachname",
|
||||
"name-full-tooltip": "Vollständiger Name: Vorname plus Nachname"
|
||||
},
|
||||
|
||||
@ -387,15 +387,15 @@
|
||||
},
|
||||
"publish-name": {
|
||||
"alias-or-initials": "Username or initials (Default)",
|
||||
"alias-or-initials-tooltip": "username if exists or Initials of firstname and lastname",
|
||||
"first": "firstname",
|
||||
"first-tooltip": "the firstname only",
|
||||
"first-initial": "firstname and initial",
|
||||
"first-initial-tooltip": "firstname plus initial of lastname",
|
||||
"alias-or-initials-tooltip": "username, if available, or the initials of the first name and last name, the first two letters in each case",
|
||||
"first": "Firstname",
|
||||
"first-tooltip": "the first name only",
|
||||
"first-initial": "First name and initial",
|
||||
"first-initial-tooltip": "first name plus the first two initial letters of the last name",
|
||||
"initials": "Initials",
|
||||
"initials-tooltip": "Initials of firstname and lastname independent if username exists",
|
||||
"name-full": "firstname and lastname",
|
||||
"name-full-tooltip": "fullname: firstname plus lastname"
|
||||
"initials-tooltip": "Initials of first name and last name, i.e. the first two letters of each regardless of the existence of the user name",
|
||||
"name-full": "first name and last name",
|
||||
"name-full-tooltip": "full name: first name plus last name"
|
||||
},
|
||||
"showAmountGDD": "Your GDD amount is visible.",
|
||||
"showAmountGDT": "Your GDT amount is visible.",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user