Ground-Zerro / Phobos Public
Code Issues Pull requests Actions Releases View on GitHub ↗
3.1 KB typescript
import type { H3Event } from 'h3';
import type { UserType } from '#db/repositories/user/types';
import { hasActiveTlsCert } from '~~/server/utils/TlsInfo';

export type WGSession = Partial<{
  userId: ID;
}>;

const DEFAULT_SESSION_MAX_AGE = 24 * 60 * 60;

function resolveSessionParams(allowInsecureHttpLogin: boolean) {
  const allowPlainHttp = WG_ENV.INSECURE || allowInsecureHttpLogin || !hasActiveTlsCert();
  return {
    name: allowPlainHttp ? 'phobos-h' : 'phobos-s',
    secure: !allowPlainHttp,
  };
}

export async function useWGSession(event: H3Event, rememberMe = false) {
  const sessionConfig = await Database.general.getSessionConfig();
  const { name, secure } = resolveSessionParams(sessionConfig.allowInsecureHttpLogin);
  return useSession<WGSession>(event, {
    password: sessionConfig.sessionPassword,
    name,
    cookie: {
      maxAge: rememberMe ? sessionConfig.sessionTimeout : DEFAULT_SESSION_MAX_AGE,
      secure,
      sameSite: 'lax',
    },
  });
}

export async function getWGSession(event: H3Event) {
  const sessionConfig = await Database.general.getSessionConfig();
  const { name, secure } = resolveSessionParams(sessionConfig.allowInsecureHttpLogin);
  return getSession<WGSession>(event, {
    password: sessionConfig.sessionPassword,
    name,
    cookie: {
      secure,
      sameSite: 'lax',
    },
  });
}

/**
 * @throws
 */
export async function getCurrentUser(event: H3Event) {
  const session = await getWGSession(event);

  const authorization = getHeader(event, 'Authorization');

  let user: UserType | undefined = undefined;
  if (session.data.userId) {
    user = await Database.users.get(session.data.userId);
  } else if (authorization) {
    const [method, value] = authorization.split(' ');
    if (method !== 'Basic' || !value) {
      throw createError({
        statusCode: 400,
        statusMessage: 'Invalid Basic Authorization',
      });
    }

    const basicValue = Buffer.from(value, 'base64').toString('utf-8');

    const index = basicValue.indexOf(':');
    const username = basicValue.substring(0, index);
    const password = basicValue.substring(index + 1);

    if (!username || !password) {
      throw createError({
        statusCode: 400,
        statusMessage: 'Invalid Basic Authorization',
      });
    }

    const foundUser = await Database.users.getByUsername(username);

    if (!foundUser) {
      throw createError({
        statusCode: 401,
        statusMessage: 'Session failed',
      });
    }

    const userHashPassword = foundUser.password;
    const passwordValid = await isPasswordValid(password, userHashPassword);

    if (!passwordValid) {
      throw createError({
        statusCode: 401,
        statusMessage: 'Session failed',
      });
    }
    user = foundUser;
  } else {
    throw createError({
      statusCode: 401,
      statusMessage: 'Session failed. No Authorization',
    });
  }

  if (!user) {
    throw createError({
      statusCode: 401,
      statusMessage: 'Session failed. User not found',
    });
  }

  if (!user.enabled) {
    throw createError({
      statusCode: 403,
      statusMessage: 'User is disabled',
    });
  }

  return user;
}