update error handling for startCommunityAuthentication

This commit is contained in:
einhornimmond 2025-10-13 09:27:19 +02:00
parent ed422fe293
commit ae23aafd87
4 changed files with 50 additions and 19 deletions

View File

@ -63,29 +63,28 @@ export async function startCommunityAuthentication(
// check if a authentication is already in progress
const existingState = await findPendingCommunityHandshake(fedComB, false)
if (existingState) {
const logic = new CommunityHandshakeStateLogic(existingState)
if (!await logic.isTimeoutUpdate()) {
const stateLogic = new CommunityHandshakeStateLogic(existingState)
// retry on timeout or failure
if (!await stateLogic.isTimeoutUpdate()) {
// authentication with community and api version is still in progress and it is not timeout yet
methodLogger.debug('existingState', new CommunityHandshakeStateLoggingView(existingState))
return
}
}
const state = new DbCommunityHandshakeState()
state.publicKey = fedComB.publicKey
state.apiVersion = fedComB.apiVersion
state.status = CommunityHandshakeStateType.START_COMMUNITY_AUTHENTICATION
state.handshakeId = parseInt(handshakeID)
const client = AuthenticationClientFactory.getInstance(fedComB)
if (client instanceof V1_0_AuthenticationClient) {
if (!comB.publicJwtKey) {
state.lastError = 'Public JWT key still not exist for comB ' + comB.name
await state.save()
throw new Error(state.lastError)
throw new Error(`Public JWT key still not exist for comB ${comB.name}`)
}
const state = new DbCommunityHandshakeState()
state.publicKey = fedComB.publicKey
state.apiVersion = fedComB.apiVersion
state.status = CommunityHandshakeStateType.START_COMMUNITY_AUTHENTICATION
state.handshakeId = parseInt(handshakeID)
const stateSaveResolver = state.save()
//create JWT with url in payload encrypted by foreignCom.publicJwtKey and signed with homeCom.privateJwtKey
const payload = new OpenConnectionJwtPayloadType(handshakeID,
ensureUrlEndsWithSlash(homeFedComA.endPoint).concat(homeFedComA.apiVersion),
@ -104,7 +103,11 @@ export async function startCommunityAuthentication(
if (result) {
methodLogger.info(`successful initiated at community:`, fedComB.endPoint)
} else {
methodLogger.error(`can't initiate at community:`, fedComB.endPoint)
const errorMsg = `can't initiate at community: ${fedComB.endPoint}`
methodLogger.error(errorMsg)
state.status = CommunityHandshakeStateType.FAILED
state.lastError = errorMsg
await state.save()
}
}
}

View File

@ -9,14 +9,25 @@ export class CommunityHandshakeStateLogic {
* @returns true if the community handshake state is expired
*/
public async isTimeoutUpdate(): Promise<boolean> {
const timeout = this.isTimeout()
if (timeout && this.communityHandshakeStateEntity.status !== CommunityHandshakeStateType.EXPIRED) {
this.communityHandshakeStateEntity.status = CommunityHandshakeStateType.EXPIRED
await this.communityHandshakeStateEntity.save()
}
return timeout
}
public isTimeout(): boolean {
if (this.communityHandshakeStateEntity.status === CommunityHandshakeStateType.EXPIRED) {
return true
}
if (Date.now() - this.communityHandshakeStateEntity.updatedAt.getTime() > FEDERATION_AUTHENTICATION_TIMEOUT_MS) {
this.communityHandshakeStateEntity.status = CommunityHandshakeStateType.EXPIRED
await this.communityHandshakeStateEntity.save()
return true
}
return false
}
public isFailed(): boolean {
return this.communityHandshakeStateEntity.status === CommunityHandshakeStateType.FAILED
}
}

View File

@ -1,5 +1,5 @@
import { CommunityHandshakeState } from '../entity'
import { FederatedCommunity } from '../entity/FederatedCommunity'
import { Not, In } from 'typeorm'
import { CommunityHandshakeState, CommunityHandshakeStateType, FederatedCommunity} from '..'
/**
* Find a pending community handshake by public key.
@ -9,7 +9,15 @@ import { FederatedCommunity } from '../entity/FederatedCommunity'
*/
export function findPendingCommunityHandshake(federatedCommunity: FederatedCommunity, withRelations = true): Promise<CommunityHandshakeState | null> {
return CommunityHandshakeState.findOne({
where: { publicKey: federatedCommunity.publicKey, apiVersion: federatedCommunity.apiVersion },
where: {
publicKey: federatedCommunity.publicKey,
apiVersion: federatedCommunity.apiVersion,
status: Not(In([
CommunityHandshakeStateType.EXPIRED,
CommunityHandshakeStateType.FAILED,
CommunityHandshakeStateType.SUCCESS
]))
},
relations: withRelations ? { federatedCommunity: { community: true } } : undefined,
})
}

View File

@ -6,9 +6,11 @@ import {
Community as DbCommunity,
FederatedCommunity as DbFedCommunity,
FederatedCommunityLoggingView,
CommunityHandshakeStateType,
CommunityHandshakeState as DbCommunityHandshakeState,
getHomeCommunity,
} from 'database'
import { getLogger } from 'log4js'
import { getLogger, Logger } from 'log4js'
import {
AuthenticationJwtPayloadType,
AuthenticationResponseJwtPayloadType,
@ -25,6 +27,13 @@ const createLogger = (method: string ) => getLogger(`${LOG4JS_BASE_CATEGORY_NAM
@Resolver()
export class AuthenticationResolver {
private async errorState(errmsg: string, methodLogger: Logger, state: DbCommunityHandshakeState) {
methodLogger.error(errmsg)
state.lastError = errmsg
await state.save()
}
@Mutation(() => Boolean)
async openConnection(
@Arg('data')