better names, check humhubAllowed flag

This commit is contained in:
einhornimmond 2024-04-16 16:21:28 +02:00
parent b20081c50c
commit b0d2a1566e
5 changed files with 74 additions and 85 deletions

View File

@ -132,6 +132,18 @@ export class HumHubClient {
}
return response.result
}
public async deleteUser(humhubUserId: number): Promise<void> {
const options = await this.createRequestOptions()
const response = await this.restClient.del(`/api/v1/user/${humhubUserId}`, options)
if (response.statusCode === 400) {
throw new LogError('invalid user supplied', { userId: humhubUserId, response })
} else if (response.statusCode === 404) {
throw new LogError('User not found', { userId: humhubUserId, response })
} else if (response.statusCode !== 200) {
throw new LogError('error deleting user', { userId: humhubUserId, response })
}
}
}
// new RestClient('gradido', 'api/v1/')

View File

@ -7,7 +7,7 @@ import { backendLogger as logger } from '@/server/logger'
import { Connection } from '@/typeorm/connection'
import { checkDBVersion } from '@/typeorm/DBVersion'
import { checkForChanges } from './checkForChanges'
import { isHumhubUserIdenticalToDbUser } from './compareHumhubUserDbUser'
import { HumHubClient } from './HumHubClient'
import { GetUser } from './model/GetUser'
import { PostUser } from './model/PostUser'
@ -18,6 +18,7 @@ enum ExecutedHumhubAction {
UPDATE,
CREATE,
SKIP,
DELETE,
}
function getUsersPage(page: number, limit: number): Promise<[User[], number]> {
@ -29,23 +30,44 @@ function getUsersPage(page: number, limit: number): Promise<[User[], number]> {
})
}
async function createOrUpdateOrSkipUser(
/**
* Trigger action according to conditions
* | User exist on humhub | export to humhub allowed | changes in user data | ACTION
* | true | false | ignored | DELETE
* | true | true | true | UPDATE
* | true | true | false | SKIP
* | false | false | ignored | SKIP
* | false | true | ignored | CREATE
* @param user
* @param humHubClient
* @param humhubUsers
* @returns
*/
async function syncUser(
user: User,
humHubClient: HumHubClient,
humhubUsers: Map<string, GetUser>,
): Promise<ExecutedHumhubAction> {
const postUser = new PostUser(user)
const humhubUser = humhubUsers.get(user.emailContact.email.trim())
if (humhubUser) {
if (checkForChanges(humhubUser, user)) {
return ExecutedHumhubAction.SKIP
if (!user.humhubAllowed) {
await humHubClient.deleteUser(humhubUser.id)
return ExecutedHumhubAction.DELETE
}
if (!isHumhubUserIdenticalToDbUser(humhubUser, user)) {
// if humhub allowed
await humHubClient.updateUser(postUser, humhubUser.id)
return ExecutedHumhubAction.UPDATE
}
await humHubClient.updateUser(postUser, humhubUser.id)
return ExecutedHumhubAction.UPDATE
} else {
await humHubClient.createUser(postUser)
return ExecutedHumhubAction.CREATE
if (user.humhubAllowed) {
await humHubClient.createUser(postUser)
return ExecutedHumhubAction.CREATE
}
}
return ExecutedHumhubAction.SKIP
}
/**
@ -107,9 +129,7 @@ async function main() {
const humhubUsers = await loadUsersFromHumHub(humHubClient)
let dbUserCount = 0
let updatedUserCount = 0
let createdUserCount = 0
let skippedUserCount = 0
const executedHumhubActionsCount = [0, 0, 0, 0]
do {
const [users, totalUsers] = await getUsersPage(page, USER_BULK_SIZE)
@ -117,14 +137,10 @@ async function main() {
userCount = users.length
page++
const promises: Promise<ExecutedHumhubAction>[] = []
users.forEach((user: User) =>
promises.push(createOrUpdateOrSkipUser(user, humHubClient, humhubUsers)),
)
users.forEach((user: User) => promises.push(syncUser(user, humHubClient, humhubUsers)))
const executedActions = await Promise.all(promises)
executedActions.forEach((executedAction: ExecutedHumhubAction) => {
if (executedAction === ExecutedHumhubAction.CREATE) createdUserCount++
else if (executedAction === ExecutedHumhubAction.UPDATE) updatedUserCount++
else if (executedAction === ExecutedHumhubAction.SKIP) skippedUserCount++
executedHumhubActionsCount[executedAction as number]++
})
// using process.stdout.write here so that carriage-return is working analog to c
// printf("\rchecked user: %d/%d", dbUserCount, totalUsers);
@ -136,9 +152,10 @@ async function main() {
logger.info('export user to humhub, statistics:', {
timeSeconds: elapsed / 1000.0,
gradidoUserCount: dbUserCount,
updatedUserCount,
createdUserCount,
skippedUserCount,
createdCount: executedHumhubActionsCount[ExecutedHumhubAction.CREATE],
updatedCount: executedHumhubActionsCount[ExecutedHumhubAction.UPDATE],
skippedCount: executedHumhubActionsCount[ExecutedHumhubAction.SKIP],
deletedCount: executedHumhubActionsCount[ExecutedHumhubAction.DELETE],
})
}

View File

@ -24,8 +24,9 @@ function accountIsTheSame(account: Account, user: User): boolean {
* compare if gradido user (db entity) differ from humhub user
* @param humhubUser
* @param gradidoUse
* @return true if no differences
*/
export function checkForChanges(humhubUser: GetUser, gradidoUser: User): boolean {
export function isHumhubUserIdenticalToDbUser(humhubUser: GetUser, gradidoUser: User): boolean {
return (
profileIsTheSame(humhubUser.profile, gradidoUser) &&
accountIsTheSame(humhubUser.account, gradidoUser)

View File

@ -1,30 +1,31 @@
import { User } from '@entity/User'
import { GmsPublishNameType } from '@/graphql/enum/GmsPublishNameType';
import { PublishNameType } from '@/graphql/enum/PublishNameType'
export class PublishNameLogic {
constructor(private user: User) {}
/**
* get first name based on publishNameType: GmsPublishNameType value
* get first name based on publishNameType: PublishNameType value
* @param publishNameType
* @returns user.firstName for GMS_PUBLISH_NAME_FIRST, GMS_PUBLISH_NAME_FIRST_INITIAL or GMS_PUBLISH_NAME_FULL
* first initial from user.firstName for GMS_PUBLISH_NAME_INITIALS or GMS_PUBLISH_NAME_ALIAS_OR_INITALS and empty alias
*/
public getFirstName(publishNameType: GmsPublishNameType): string | undefined {
public getFirstName(publishNameType: PublishNameType): string | undefined {
if (
[
GmsPublishNameType.GMS_PUBLISH_NAME_FIRST,
GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL,
GmsPublishNameType.GMS_PUBLISH_NAME_FULL,
PublishNameType.PUBLISH_NAME_FIRST,
PublishNameType.PUBLISH_NAME_FIRST_INITIAL,
PublishNameType.PUBLISH_NAME_FULL,
].includes(publishNameType)
) {
return this.user.firstName
}
if (
(!this.user.alias &&
publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS) ||
publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_INITIALS
[
PublishNameType.PUBLISH_NAME_INITIALS,
PublishNameType.PUBLISH_NAME_INITIAL_LAST,
].includes(publishNameType)
) {
return this.user.firstName.substring(0, 1)
}
@ -36,32 +37,23 @@ export class PublishNameLogic {
* @returns user.lastName for GMS_PUBLISH_NAME_FULL
* first initial from user.lastName for GMS_PUBLISH_NAME_FIRST_INITIAL, GMS_PUBLISH_NAME_INITIALS or GMS_PUBLISH_NAME_ALIAS_OR_INITALS and empty alias
*/
public getLastName(publishNameType: GmsPublishNameType): string | undefined {
if (publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_FULL) {
public getLastName(publishNameType: PublishNameType): string | undefined {
if (
[
PublishNameType.PUBLISH_NAME_LAST,
PublishNameType.PUBLISH_NAME_INITIAL_LAST,
PublishNameType.PUBLISH_NAME_FULL,
].includes(publishNameType)
) {
return this.user.lastName
}
if (
(!this.user.alias &&
publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS) ||
publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_FIRST_INITIAL ||
publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_INITIALS
[
PublishNameType.PUBLISH_NAME_FIRST_INITIAL,
PublishNameType.PUBLISH_NAME_INITIALS,
].includes(publishNameType)
) {
return this.user.lastName.substring(0, 1)
}
}
public getUsername(publishNameType: GmsPublishNameType): string {
if (
this.user.alias &&
publishNameType === GmsPublishNameType.GMS_PUBLISH_NAME_ALIAS_OR_INITALS
) {
return this.user.alias
}
const firstName = this.getFirstName(publishNameType)
const lastName = this.getLastName(publishNameType)
if (firstName && lastName) {
return `${firstName} ${lastName}`
}
return this.user.gradidoID
}
}

View File

@ -1188,13 +1188,6 @@
"@types/mime" "^1"
"@types/node" "*"
"@types/simple-get@^4.0.3":
version "4.0.3"
resolved "https://registry.yarnpkg.com/@types/simple-get/-/simple-get-4.0.3.tgz#91f8f03fd4e5d3720a1a6114c6a1bb5761326092"
integrity sha512-X3HNxcz8ZjpTB+eLf3dH0m/KVt6mln3XKKAeBLca3rMtjFeB67hy3SDAkfWj0ulb++nqSp8nmCfMLAq9FpBW9g==
dependencies:
"@types/node" "*"
"@types/sodium-native@^2.3.5":
version "2.3.5"
resolved "https://registry.yarnpkg.com/@types/sodium-native/-/sodium-native-2.3.5.tgz#5d2681e7b6b67bcbdc63cfb133e303ec9e942e43"
@ -2520,13 +2513,6 @@ decompress-response@^3.3.0:
dependencies:
mimic-response "^1.0.0"
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
dependencies:
mimic-response "^3.1.0"
dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@ -3710,7 +3696,7 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
"gradido-database@file:../database":
version "2.2.0"
version "2.2.1"
dependencies:
"@types/uuid" "^8.3.4"
cross-env "^7.0.3"
@ -5282,11 +5268,6 @@ mimic-response@^1.0.0, mimic-response@^1.0.1:
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
mimic-response@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
@ -6475,20 +6456,6 @@ signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f"
integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==
simple-concat@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
simple-get@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543"
integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==
dependencies:
decompress-response "^6.0.0"
once "^1.3.1"
simple-concat "^1.0.0"
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"