import { verify } from '@node-rs/argon2';
import { Request, Response } from 'express';
import { getConnectionManager } from 'typeorm';
import { StatsClient } from '../models/entities/StatsClient';
import authchecker from './authchecker';

/**
 * This middleware handles the authentication of stats client api tokens.
 * The tokens have to be provided via Bearer authorization header.
 * You have to manually use this middleware via @UseBefore(StatsAuth) instead of using @Authorized().
 * @param req Express request object.
 * @param res Express response object.
 * @param next Next function to call on success.
 */
const StatsAuth = async (req: Request, res: Response, next: () => void) => {
    let provided_token: string = req.headers["authorization"];
    if (provided_token == "" || provided_token === undefined || provided_token === null) {
        res.status(401).send("No api token provided.");
        return;
    }

    try {
        provided_token = provided_token.replace("Bearer ", "");
    } catch (error) {
        res.status(401).send("No valid jwt or api token provided.");
        return;
    }

    let prefix = "";
    try {
        prefix = provided_token.split(".")[0];
    }
    finally {
        if (prefix == "" || prefix == undefined || prefix == null) {
            res.status(401).send("Api token non-existant or invalid syntax.");
            return;
        }
    }

    const client = await getConnectionManager().get().getRepository(StatsClient).findOne({ prefix: prefix });
    if (!client) {
        let user_authorized = false;
        try {
            let action = { request: req, response: res, context: null, next: next }
            user_authorized = await authchecker(action, ["RUNNER:GET", "TEAM:GET", "ORGANIZATION:GET"]);
        }
        finally {
            if (user_authorized == false) {
                res.status(401).send("Api token non-existant or invalid syntax.");
                return;
            }
            else {
                next();
            }
        }
    }
    else {
        if (!(await verify(client.key, provided_token))) {
            res.status(401).send("Api token invalid.");
            return;
        }

        next();
    }
}
export default StatsAuth;