// Copyright (C) 2023 Vaughn Nugent
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
import { AxiosInstance } from "axios";
import { get } from "@vueuse/core";
import { computed } from "vue";
import { delay } from "lodash";
import { usePkiAuth, useSession, useUser } from "@vnuge/vnlib.browser";
import type { ClientStatus } from "./types";
import type { AppSettings } from "./settings";
import type { JsonObject } from "type-fest";
import { type FeatureApi, type BgRuntime, type IFeatureExport, exportForegroundApi, popupAndOptionsOnly, popupOnly } from "./framework";
import { waitForChangeFn } from "./util";
export interface ProectedHandler {
(message: T): Promise
}
export interface MessageHandler {
(message: T): Promise
}
export interface ApiMessageHandler {
(message: T, apiHandle: { axios: AxiosInstance }): Promise
}
export interface UserApi extends FeatureApi {
login: (token: string) => Promise
logout: () => Promise
getProfile: () => Promise
getStatus: () => Promise
waitForChange: () => Promise
}
export const useAuthApi = (): IFeatureExport => {
return {
background: ({ state }:BgRuntime): UserApi =>{
const { loggedIn, clearLoginState } = useSession();
const { currentConfig } = state
const { logout, getProfile, heartbeat, userName } = useUser();
const currentPkiPath = computed(() => `${currentConfig.value.accountBasePath}/pki`)
//Use pki login controls
const { login } = usePkiAuth(currentPkiPath as any)
//We can send post messages to the server heartbeat endpoint to get status
const runHeartbeat = async () => {
//Only run if the api thinks its logged in, and config is enabled
if (!loggedIn.value || currentConfig.value.heartbeat !== true) {
return
}
try {
//Post against the heartbeat endpoint
await heartbeat()
}
catch (error: any) {
if (error.response?.status === 401 || error.response?.status === 403) {
//If we get a 401, the user is no longer logged in
clearLoginState()
}
}
}
//Configure interval to run every 5 minutes to update the status
setInterval(runHeartbeat, 60 * 1000);
delay(runHeartbeat, 1000) //Delay 1 second to allow the extension to load
return {
waitForChange: waitForChangeFn([currentConfig, loggedIn, userName]),
login: popupOnly(async (token: string): Promise => {
//Perform login
await login(token)
//load profile
getProfile()
return true;
}),
logout: popupOnly(async (): Promise => {
//Perform logout
await logout()
//Cleanup after logout
clearLoginState()
}),
getProfile: popupAndOptionsOnly(getProfile),
async getStatus (){
return {
//Logged in if the cookie is set and the api flag is set
loggedIn: get(loggedIn),
//username
userName: get(userName),
} as ClientStatus
},
}
},
foreground: exportForegroundApi([
'login',
'logout',
'getProfile',
'getStatus',
'waitForChange'
]),
}
}