import * as crypto from "node:crypto";
import define from "../../define.js";
import { ApiError } from "../../error.js";
import { AuthSessions, AccessTokens, Apps } from "../../../../models/index.js";
import { genId } from "../../../../misc/gen-id.js";
import { secureRndstr } from "../../../../misc/secure-rndstr.js";
export const meta = {
    tags: [
        "auth"
    ],
    requireCredential: true,
    secure: true,
    errors: {
        noSuchSession: {
            message: "No such session.",
            code: "NO_SUCH_SESSION",
            id: "9c72d8de-391a-43c1-9d06-08d29efde8df"
        }
    }
};
export const paramDef = {
    type: "object",
    properties: {
        token: {
            type: "string"
        }
    },
    required: [
        "token"
    ]
};
export default define(meta, paramDef, async (ps, user)=>{
    // Fetch token
    const session = await AuthSessions.findOneBy({
        token: ps.token
    });
    if (session == null) {
        throw new ApiError(meta.errors.noSuchSession);
    }
    // Generate access token
    const accessToken = secureRndstr(32);
    // Fetch exist access token
    const exist = await AccessTokens.exist({
        where: {
            appId: session.appId,
            userId: user.id
        }
    });
    if (!exist) {
        // Lookup app
        const app = await Apps.findOneByOrFail({
            id: session.appId
        });
        // Generate Hash
        const sha256 = crypto.createHash("sha256");
        sha256.update(accessToken + app.secret);
        const hash = sha256.digest("hex");
        const now = new Date();
        // Insert access token doc
        await AccessTokens.insert({
            id: genId(),
            createdAt: now,
            lastUsedAt: now,
            appId: session.appId,
            userId: user.id,
            token: accessToken,
            hash: hash
        });
    }
    // Update session
    await AuthSessions.update(session.id, {
        userId: user.id
    });
});
