mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
remove join from communityHandshakeState, await save direct, to prevent drag away errors
This commit is contained in:
parent
d11a794dd5
commit
1c347b7ff7
@ -55,7 +55,7 @@ export async function startCommunityAuthentication(
|
||||
)
|
||||
|
||||
// check if a authentication is already in progress
|
||||
const existingState = await findPendingCommunityHandshake(fedComBPublicKey, fedComB.apiVersion, false)
|
||||
const existingState = await findPendingCommunityHandshake(fedComBPublicKey, fedComB.apiVersion)
|
||||
if (existingState) {
|
||||
const stateLogic = new CommunityHandshakeStateLogic(existingState)
|
||||
// retry on timeout or failure
|
||||
@ -77,7 +77,7 @@ export async function startCommunityAuthentication(
|
||||
state.apiVersion = fedComB.apiVersion
|
||||
state.status = CommunityHandshakeStateType.START_COMMUNITY_AUTHENTICATION
|
||||
state.handshakeId = parseInt(handshakeID)
|
||||
const stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
|
||||
//create JWT with url in payload encrypted by foreignCom.publicJwtKey and signed with homeCom.privateJwtKey
|
||||
const payload = new OpenConnectionJwtPayloadType(handshakeID,
|
||||
@ -92,7 +92,6 @@ export async function startCommunityAuthentication(
|
||||
args.publicKey = homeComAPublicKey.asHex()
|
||||
args.jwt = jws
|
||||
args.handshakeID = handshakeID
|
||||
await stateSaveResolver
|
||||
methodLogger.debug('before client.openConnection() args:', args)
|
||||
const result = await client.openConnection(args)
|
||||
if (result) {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { CommunityHandshakeStateType } from '../enum'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
import { FederatedCommunity } from './FederatedCommunity'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
|
||||
@Entity('community_handshake_states')
|
||||
export class CommunityHandshakeState extends BaseEntity {
|
||||
@ -35,8 +34,4 @@ export class CommunityHandshakeState extends BaseEntity {
|
||||
|
||||
@UpdateDateColumn({ name: 'updated_at', type: 'datetime', precision: 3 })
|
||||
updatedAt: Date
|
||||
|
||||
@ManyToOne(() => FederatedCommunity, (federatedCommunity) => federatedCommunity.communityHandshakeStates)
|
||||
@JoinColumn({ name: 'public_key', referencedColumnName: 'publicKey' })
|
||||
federatedCommunity: FederatedCommunity
|
||||
}
|
||||
@ -5,12 +5,10 @@ import {
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm'
|
||||
import { Community } from './Community'
|
||||
import { CommunityHandshakeState } from './CommunityHandshakeState'
|
||||
|
||||
@Entity('federated_communities')
|
||||
export class FederatedCommunity extends BaseEntity {
|
||||
@ -62,8 +60,4 @@ export class FederatedCommunity extends BaseEntity {
|
||||
)
|
||||
@JoinColumn({ name: 'public_key', referencedColumnName: 'publicKey' })
|
||||
community?: Community
|
||||
|
||||
@OneToMany(() => CommunityHandshakeState, (communityHandshakeState) => communityHandshakeState.federatedCommunity)
|
||||
@JoinColumn({ name: 'public_key', referencedColumnName: 'publicKey' })
|
||||
communityHandshakeStates: CommunityHandshakeState[]
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { CommunityHandshakeState } from '..'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { FederatedCommunityLoggingView } from './FederatedCommunityLogging.view'
|
||||
|
||||
export class CommunityHandshakeStateLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: CommunityHandshakeState) {
|
||||
@ -16,10 +15,7 @@ export class CommunityHandshakeStateLoggingView extends AbstractLoggingView {
|
||||
status: this.self.status,
|
||||
lastError: this.self.lastError,
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
updatedAt: this.dateToString(this.self.updatedAt),
|
||||
federatedCommunity: this.self.federatedCommunity
|
||||
? new FederatedCommunityLoggingView(this.self.federatedCommunity)
|
||||
: undefined,
|
||||
updatedAt: this.dateToString(this.self.updatedAt),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,14 +3,13 @@ import {
|
||||
CommunityHandshakeState as DbCommunityHandshakeState,
|
||||
Community as DbCommunity,
|
||||
FederatedCommunity as DbFederatedCommunity,
|
||||
getHomeCommunityWithFederatedCommunityOrFail,
|
||||
getCommunityByPublicKeyOrFail,
|
||||
findPendingCommunityHandshake,
|
||||
CommunityHandshakeStateType
|
||||
} from '..'
|
||||
import { describe, expect, it, beforeEach, beforeAll, afterAll } from 'vitest'
|
||||
import { createCommunity, createVerifiedFederatedCommunity } from '../seeds/community'
|
||||
import { Ed25519PublicKey } from 'shared'
|
||||
import { randomBytes } from 'node:crypto'
|
||||
|
||||
const db = AppDatabase.getInstance()
|
||||
|
||||
@ -21,6 +20,15 @@ afterAll(async () => {
|
||||
await db.destroy()
|
||||
})
|
||||
|
||||
async function createCommunityHandshakeState(publicKey: Buffer) {
|
||||
const state = new DbCommunityHandshakeState()
|
||||
state.publicKey = publicKey
|
||||
state.apiVersion = '1_0'
|
||||
state.status = CommunityHandshakeStateType.START_COMMUNITY_AUTHENTICATION
|
||||
state.handshakeId = 1
|
||||
await state.save()
|
||||
}
|
||||
|
||||
describe('communityHandshakes', () => {
|
||||
// clean db for every test case
|
||||
beforeEach(async () => {
|
||||
@ -32,48 +40,32 @@ describe('communityHandshakes', () => {
|
||||
it('should find pending community handshake by public key', async () => {
|
||||
const com1 = await createCommunity(false)
|
||||
await createVerifiedFederatedCommunity('1_0', 100, com1)
|
||||
const state = new DbCommunityHandshakeState()
|
||||
state.publicKey = com1.publicKey
|
||||
state.apiVersion = '1_0'
|
||||
state.status = CommunityHandshakeStateType.OPEN_CONNECTION_CALLBACK
|
||||
state.handshakeId = 1
|
||||
await state.save()
|
||||
await createCommunityHandshakeState(com1.publicKey)
|
||||
const communityHandshakeState = await findPendingCommunityHandshake(new Ed25519PublicKey(com1.publicKey), '1_0')
|
||||
expect(communityHandshakeState).toBeDefined()
|
||||
expect(communityHandshakeState).toMatchObject({
|
||||
publicKey: com1.publicKey,
|
||||
apiVersion: '1_0',
|
||||
status: CommunityHandshakeStateType.OPEN_CONNECTION_CALLBACK,
|
||||
status: CommunityHandshakeStateType.START_COMMUNITY_AUTHENTICATION,
|
||||
handshakeId: 1
|
||||
})
|
||||
})
|
||||
|
||||
it('try to use returned public key for loading community', async () => {
|
||||
// test this explicit case, because in federation.authentication it lead to server crash
|
||||
const com1 = await createCommunity(false)
|
||||
await createVerifiedFederatedCommunity('1_0', 100, com1)
|
||||
const state = new DbCommunityHandshakeState()
|
||||
state.publicKey = com1.publicKey
|
||||
state.apiVersion = '1_0'
|
||||
state.status = CommunityHandshakeStateType.OPEN_CONNECTION_CALLBACK
|
||||
state.handshakeId = 1
|
||||
await state.save()
|
||||
const communityHandshakeState = await findPendingCommunityHandshake(new Ed25519PublicKey(com1.publicKey), '1_0')
|
||||
it('update state', async () => {
|
||||
const publicKey = new Ed25519PublicKey(randomBytes(32))
|
||||
await createCommunityHandshakeState(publicKey.asBuffer())
|
||||
const communityHandshakeState = await findPendingCommunityHandshake(publicKey, '1_0')
|
||||
expect(communityHandshakeState).toBeDefined()
|
||||
expect(communityHandshakeState?.federatedCommunity?.community).toBeDefined()
|
||||
const ed25519PublicKey = new Ed25519PublicKey(communityHandshakeState?.federatedCommunity?.community?.publicKey)
|
||||
const community = await DbCommunity.findOneBy({ publicKey: ed25519PublicKey.asBuffer() })
|
||||
expect(community).toBeDefined()
|
||||
expect(community).toMatchObject({
|
||||
communityUuid: com1.communityUuid,
|
||||
name: com1.name,
|
||||
description: com1.description,
|
||||
url: com1.url,
|
||||
creationDate: com1.creationDate,
|
||||
authenticatedAt: com1.authenticatedAt,
|
||||
foreign: com1.foreign,
|
||||
publicKey: com1.publicKey,
|
||||
privateKey: com1.privateKey
|
||||
communityHandshakeState!.status = CommunityHandshakeStateType.OPEN_CONNECTION_CALLBACK
|
||||
await communityHandshakeState!.save()
|
||||
const communityHandshakeState2 = await findPendingCommunityHandshake(publicKey, '1_0')
|
||||
const states = await DbCommunityHandshakeState.find()
|
||||
expect(communityHandshakeState2).toBeDefined()
|
||||
expect(communityHandshakeState2).toMatchObject({
|
||||
publicKey: publicKey.asBuffer(),
|
||||
apiVersion: '1_0',
|
||||
status: CommunityHandshakeStateType.OPEN_CONNECTION_CALLBACK,
|
||||
handshakeId: 1
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -5,12 +5,10 @@ import { Ed25519PublicKey } from 'shared'
|
||||
/**
|
||||
* Find a pending community handshake by public key.
|
||||
* @param publicKey The public key of the community.
|
||||
* @param withRelations Whether to include the federated community and community in the result, default true.
|
||||
* @param apiVersion The API version of the community.
|
||||
* @returns The CommunityHandshakeState with associated federated community and community.
|
||||
*/
|
||||
export function findPendingCommunityHandshake(
|
||||
publicKey: Ed25519PublicKey, apiVersion: string, withRelations = true
|
||||
): Promise<CommunityHandshakeState | null> {
|
||||
export function findPendingCommunityHandshake(publicKey: Ed25519PublicKey, apiVersion: string): Promise<CommunityHandshakeState | null> {
|
||||
return CommunityHandshakeState.findOne({
|
||||
where: {
|
||||
publicKey: publicKey.asBuffer(),
|
||||
@ -21,7 +19,6 @@ export function findPendingCommunityHandshake(
|
||||
CommunityHandshakeStateType.SUCCESS
|
||||
]))
|
||||
},
|
||||
relations: withRelations ? { federatedCommunity: { community: true } } : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
@ -30,7 +27,6 @@ export function findPendingCommunityHandshakeOrFailByOneTimeCode(
|
||||
): Promise<CommunityHandshakeState> {
|
||||
return CommunityHandshakeState.findOneOrFail({
|
||||
where: { oneTimeCode },
|
||||
relations: { federatedCommunity: { community: true } },
|
||||
})
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
getHomeCommunity,
|
||||
findPendingCommunityHandshakeOrFailByOneTimeCode,
|
||||
Community as DbCommunity,
|
||||
getCommunityByPublicKeyOrFail,
|
||||
} from 'database'
|
||||
import { getLogger } from 'log4js'
|
||||
import {
|
||||
@ -126,7 +127,6 @@ export class AuthenticationResolver {
|
||||
methodLogger.addContext('handshakeID', args.handshakeID)
|
||||
methodLogger.debug(`authenticate() via apiVersion=1_0 ...`, args)
|
||||
let state: DbCommunityHandshakeState | null = null
|
||||
let stateSaveResolver: Promise<DbCommunityHandshakeState> | undefined = undefined
|
||||
const argsPublicKey = new Ed25519PublicKey(args.publicKey)
|
||||
try {
|
||||
const authArgs = await interpretEncryptedTransferArgs(args) as AuthenticationJwtPayloadType
|
||||
@ -150,11 +150,10 @@ export class AuthenticationResolver {
|
||||
throw new Error('No valid pending community handshake found')
|
||||
}
|
||||
state.status = CommunityHandshakeStateType.SUCCESS
|
||||
// stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
|
||||
|
||||
methodLogger.debug(`search community per oneTimeCode:`, authArgs.oneTimeCode)
|
||||
const authCom = state.federatedCommunity.community
|
||||
const authCom = await getCommunityByPublicKeyOrFail(argsPublicKey)
|
||||
if (authCom) {
|
||||
methodLogger.debug('found authCom:', new CommunityLoggingView(authCom))
|
||||
const authComPublicKey = new Ed25519PublicKey(authCom.publicKey)
|
||||
@ -171,21 +170,11 @@ export class AuthenticationResolver {
|
||||
`invalid uuid: ${authArgs.uuid} for community with publicKey ${authComPublicKey.asHex()}`
|
||||
)
|
||||
}
|
||||
methodLogger.debug('before updating auth community again from db')
|
||||
// need to use query builder, loading from db, changing and save lead to server crash with this error:
|
||||
// TypeError [ERR_INVALID_ARG_TYPE]: The "otherBuffer" argument must be of type Buffer or Uint8Array. Received an instance of Object
|
||||
// seems to be a typeorm problem with Buffer, even if I give a freshly created Buffer for public_key
|
||||
/*await DbCommunity.createQueryBuilder()
|
||||
.update(DbCommunity)
|
||||
.set({
|
||||
communityUuid: communityUuid.data,
|
||||
authenticatedAt: new Date(),
|
||||
})
|
||||
.where({ id: authCom.id })
|
||||
.execute()
|
||||
authCom.communityUuid = communityUuid.data
|
||||
authCom.authenticatedAt = new Date()
|
||||
await authCom.save()
|
||||
methodLogger.debug('update authCom.uuid successfully')
|
||||
*/
|
||||
methodLogger.debug('skipped community update')
|
||||
|
||||
const homeComB = await getHomeCommunity()
|
||||
if (homeComB?.communityUuid) {
|
||||
const responseArgs = new AuthenticationResponseJwtPayloadType(args.handshakeID,homeComB.communityUuid)
|
||||
@ -205,16 +194,11 @@ export class AuthenticationResolver {
|
||||
methodLogger.info(`state: ${new CommunityHandshakeStateLoggingView(state)}`)
|
||||
state.status = CommunityHandshakeStateType.FAILED
|
||||
state.lastError = errorString
|
||||
stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
}
|
||||
methodLogger.error(`failed: ${errorString}`)
|
||||
// no infos to the caller
|
||||
return null
|
||||
} finally {
|
||||
if (stateSaveResolver) {
|
||||
await stateSaveResolver
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ export async function startOpenConnectionCallback(
|
||||
methodLogger.debug(`Authentication: startOpenConnectionCallback() with:`, {
|
||||
publicKey: publicKey.asHex(),
|
||||
})
|
||||
const pendingState = await findPendingCommunityHandshake(publicKey, api, false)
|
||||
const pendingState = await findPendingCommunityHandshake(publicKey, api)
|
||||
if (pendingState) {
|
||||
const stateLogic = new CommunityHandshakeStateLogic(pendingState)
|
||||
// retry on timeout or failure
|
||||
@ -61,7 +61,6 @@ export async function startOpenConnectionCallback(
|
||||
return
|
||||
}
|
||||
}
|
||||
let stateSaveResolver: Promise<DbCommunityHandshakeState> | undefined = undefined
|
||||
const state = new DbCommunityHandshakeState()
|
||||
try {
|
||||
const [homeComB, comA] = await Promise.all([
|
||||
@ -84,7 +83,7 @@ export async function startOpenConnectionCallback(
|
||||
state.status = CommunityHandshakeStateType.START_OPEN_CONNECTION_CALLBACK
|
||||
state.handshakeId = parseInt(handshakeID)
|
||||
state.oneTimeCode = oneTimeCode
|
||||
stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
methodLogger.debug(
|
||||
`Authentication: store oneTimeCode in CommunityHandshakeState:`,
|
||||
new CommunityHandshakeStateLoggingView(state),
|
||||
@ -103,13 +102,12 @@ export async function startOpenConnectionCallback(
|
||||
args.publicKey = new Ed25519PublicKey(homeComB.publicKey).asHex()
|
||||
args.jwt = jwt
|
||||
args.handshakeID = handshakeID
|
||||
await stateSaveResolver
|
||||
const result = await client.openConnectionCallback(args)
|
||||
if (result) {
|
||||
methodLogger.debug(`startOpenConnectionCallback() successful: ${jwt}`)
|
||||
} else {
|
||||
methodLogger.debug(`jwt: ${jwt}`)
|
||||
stateSaveResolver = errorState('startOpenConnectionCallback() failed', methodLogger, state)
|
||||
await errorState('startOpenConnectionCallback() failed', methodLogger, state)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@ -119,11 +117,7 @@ export async function startOpenConnectionCallback(
|
||||
} else {
|
||||
errorString = String(err)
|
||||
}
|
||||
stateSaveResolver = errorState(`error in startOpenConnectionCallback: ${errorString}`, methodLogger, state)
|
||||
} finally {
|
||||
if (stateSaveResolver) {
|
||||
await stateSaveResolver
|
||||
}
|
||||
await errorState(`error in startOpenConnectionCallback: ${errorString}`, methodLogger, state)
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +133,6 @@ export async function startAuthentication(
|
||||
fedComB: new FederatedCommunityLoggingView(fedComB),
|
||||
})
|
||||
let state: DbCommunityHandshakeState | null = null
|
||||
let stateSaveResolver: Promise<DbCommunityHandshakeState> | undefined = undefined
|
||||
const fedComBPublicKey = new Ed25519PublicKey(fedComB.publicKey)
|
||||
try {
|
||||
const homeComA = await getHomeCommunity()
|
||||
@ -150,7 +143,7 @@ export async function startAuthentication(
|
||||
if (!comB.publicJwtKey) {
|
||||
throw new Error('Public JWT key still not exist for foreign community')
|
||||
}
|
||||
state = await findPendingCommunityHandshake(fedComBPublicKey, fedComB.apiVersion, false)
|
||||
state = await findPendingCommunityHandshake(fedComBPublicKey, fedComB.apiVersion)
|
||||
if (!state) {
|
||||
throw new Error('No pending community handshake found')
|
||||
}
|
||||
@ -163,7 +156,7 @@ export async function startAuthentication(
|
||||
throw new Error('No valid pending community handshake found')
|
||||
}
|
||||
state.status = CommunityHandshakeStateType.START_AUTHENTICATION
|
||||
stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
|
||||
const client = AuthenticationClientFactory.getInstance(fedComB)
|
||||
|
||||
@ -196,12 +189,12 @@ export async function startAuthentication(
|
||||
comB.authenticatedAt = new Date()
|
||||
await DbCommunity.save(comB)
|
||||
state.status = CommunityHandshakeStateType.SUCCESS
|
||||
stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
methodLogger.debug('Community Authentication successful:', new CommunityLoggingView(comB))
|
||||
} else {
|
||||
state.status = CommunityHandshakeStateType.FAILED
|
||||
state.lastError = 'Community Authentication failed, empty response'
|
||||
stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
methodLogger.error('Community Authentication failed:', authenticationArgs)
|
||||
}
|
||||
}
|
||||
@ -215,12 +208,8 @@ export async function startAuthentication(
|
||||
if (state) {
|
||||
state.status = CommunityHandshakeStateType.FAILED
|
||||
state.lastError = errorString
|
||||
stateSaveResolver = state.save()
|
||||
await state.save()
|
||||
}
|
||||
methodLogger.error('error in startAuthentication:', errorString)
|
||||
} finally {
|
||||
if (stateSaveResolver) {
|
||||
await stateSaveResolver
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user