All files / src/sessionkey login.ts

12.82% Statements 5/39
18.75% Branches 6/32
7.69% Functions 1/13
10.52% Lines 4/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 9920x   1x                       1x                                                                                                                                                                     1x  
import {AbstractLoginPlugin, LoginContext, LoginHookTypes} from '../login'
import {SessionKeyConfig} from './types'
import {SessionKeyManager} from './manager'
 
/**
 * Configuration options for the [[SessionKeyLoginPlugin]].
 */
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface SessionKeyLoginPluginOptions extends SessionKeyConfig {}
 
/**
 * Login plugin that automatically handles session key setup and validation during login flow.
 * Prompts for consent, handles conflicts, and validates whitelist mismatches.
 */
export class SessionKeyLoginPlugin extends AbstractLoginPlugin {
    private config?: SessionKeyLoginPluginOptions
    private manager?: SessionKeyManager
 
    constructor(options?: SessionKeyLoginPluginOptions) {
        super()
        this.config = options
        Iif (options) {
            this.manager = new SessionKeyManager(options)
        }
    }
 
    register(context: LoginContext): void {
        context.addHook(LoginHookTypes.afterLogin, async () => {
            Iif (!context.session) {
                return
            }
 
            const manager = this.manager || context.sessionKeyManager
            Iif (!manager) {
                return
            }
 
            const session = context.session
            const result = await manager.checkExistingSessionKey(session)
 
            if (result.exists && result.mismatch) {
                if (context.ui?.onSessionKeyMismatch) {
                    const choice = await context.ui.onSessionKeyMismatch({
                        appName: String(session.appName || 'this app'),
                        added: result.mismatch.added.map((e) => ({
                            contract: String(e.contract),
                            actions: e.actions?.map((a) => String(a)),
                        })),
                        removed: result.mismatch.removed.map((e) => ({
                            contract: String(e.contract),
                            actions: e.actions?.map((a) => String(a)),
                        })),
                    })
 
                    Iif (choice !== 'update') {
                        return
                    }
                } else {
                    return
                }
            } else {
                Iif (!manager.config.skipConsent && context.ui?.onSessionKeyConsent) {
                    const consent = await context.ui.onSessionKeyConsent({
                        appName: String(session.appName || 'this app'),
                        whitelist: manager.whitelist.map((e) => ({
                            contract: String(e.contract),
                            actions: e.actions?.map((a) => String(a)),
                        })),
                    })
 
                    Iif (!consent) {
                        return
                    }
                }
            }
 
            const onConflict = context.ui?.onSessionKeyConflict
                ? async (existingKeys: any[]) => {
                      const choice = await context.ui!.onSessionKeyConflict!({
                          appName: String(session.appName || 'this app'),
                          existingKeyCount: existingKeys.length,
                      })
                      return choice
                  }
                : undefined
 
            await manager.setup(session, onConflict)
        })
    }
 
    getConfig(): SessionKeyLoginPluginOptions | undefined {
        return this.config
    }
 
    getManager(): SessionKeyManager | undefined {
        return this.manager
    }
}