File

src/database/migrations/1760000000000-AddSessionSingleUseTracking.ts

Description

Add consumed and consumedAt columns to session table.

This migration adds two columns to track single-use validation for offers:

  • consumed: boolean flag indicating whether the offer has been consumed
  • consumedAt: timestamp of when the offer was consumed

This implements the single-use validation feature to prevent replay attacks and ensure each credential offer or presentation request can only be used once.

Implements

MigrationInterface

Index

Properties
Methods
  • Public Async down
  • Public Async up

Properties

name
Type : string
Default value : "AddSessionSingleUseTracking1760000000000"

Methods

Public Async down
down(queryRunner: QueryRunner)
Parameters :
Name Type Optional
queryRunner QueryRunner No
Returns : Promise<void>
Public Async up
up(queryRunner: QueryRunner)
Parameters :
Name Type Optional
queryRunner QueryRunner No
Returns : Promise<void>
import { MigrationInterface, QueryRunner, TableColumn } from "typeorm";

/**
 * Add consumed and consumedAt columns to session table.
 *
 * This migration adds two columns to track single-use validation for offers:
 * - consumed: boolean flag indicating whether the offer has been consumed
 * - consumedAt: timestamp of when the offer was consumed
 *
 * This implements the single-use validation feature to prevent replay attacks
 * and ensure each credential offer or presentation request can only be used once.
 */
export class AddSessionSingleUseTracking1760000000000
    implements MigrationInterface
{
    name = "AddSessionSingleUseTracking1760000000000";

    public async up(queryRunner: QueryRunner): Promise<void> {
        const table = await queryRunner.getTable("session");
        if (!table) {
            console.log(
                "[Migration] session table not found — skipping (schema may not exist yet).",
            );
            return;
        }

        const hasConsumedColumn = table.columns.some(
            (col) => col.name === "consumed",
        );
        if (hasConsumedColumn) {
            console.log(
                "[Migration] consumed column already exists — skipping.",
            );
            return;
        }

        // Add consumed column
        await queryRunner.addColumn(
            "session",
            new TableColumn({
                name: "consumed",
                type: "boolean",
                default: false,
                isNullable: false,
            }),
        );

        // Add consumedAt column
        await queryRunner.addColumn(
            "session",
            new TableColumn({
                name: "consumedAt",
                type:
                    queryRunner.connection.driver.options.type === "sqlite"
                        ? "datetime"
                        : "timestamp",
                isNullable: true,
            }),
        );
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        const table = await queryRunner.getTable("session");
        if (!table) {
            console.log(
                "[Migration] session table not found — skipping (schema may not exist yet).",
            );
            return;
        }

        const hasConsumedColumn = table.columns.some(
            (col) => col.name === "consumed",
        );
        if (hasConsumedColumn) {
            await queryRunner.dropColumn("session", "consumed");
        }

        const hasConsumedAtColumn = table.columns.some(
            (col) => col.name === "consumedAt",
        );
        if (hasConsumedAtColumn) {
            await queryRunner.dropColumn("session", "consumedAt");
        }
    }
}

results matching ""

    No results matching ""