mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-01-06 13:56:14 +08:00
10f70b781f
Signed-off-by: MiniDigger <admin@minidigger.me>
140 lines
5.7 KiB
TypeScript
140 lines
5.7 KiB
TypeScript
import { Context } from '@nuxt/types';
|
|
import { Inject } from '@nuxt/types/app';
|
|
import { AxiosPromise } from 'axios';
|
|
import { ApiSession } from 'hangar-api';
|
|
import { NuxtAxiosInstance } from '@nuxtjs/axios';
|
|
import { NuxtCookies } from 'cookie-universal-nuxt';
|
|
import { Store } from 'vuex';
|
|
import { ApiSessionType } from '~/types/enums';
|
|
|
|
const createApi = ($axios: NuxtAxiosInstance, $cookies: NuxtCookies, store: Store<any>) => {
|
|
class API {
|
|
getSession(): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
let session: ApiSession;
|
|
const date = new Date();
|
|
date.setTime(date.getTime() + 60000);
|
|
|
|
if (store.state.auth.authenticated) {
|
|
session = $cookies.get('api_session');
|
|
if (typeof session === 'undefined' || (!isNaN(new Date(session.expires).getTime()) && new Date(session.expires) < date)) {
|
|
return $axios
|
|
.post<object, ApiSession>('/api/v1/authenticate', {}, { headers: { 'Content-Type': 'application/json' } })
|
|
.then((data) => {
|
|
if (data.type !== 'user') {
|
|
reject(new Error('Expected user session from user authentication'));
|
|
} else {
|
|
$cookies.set('api_session', JSON.stringify(data), {
|
|
path: '/',
|
|
maxAge: 60 * 60 * 24 * 7,
|
|
});
|
|
store.commit('auth/SET_AUTHED', true);
|
|
resolve(data.session);
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
reject(error);
|
|
});
|
|
} else {
|
|
resolve(session.session);
|
|
}
|
|
} else {
|
|
session = $cookies.get('public_api_session');
|
|
if (typeof session === 'undefined' || (!isNaN(new Date(session.expires).getTime()) && new Date(session.expires) < date)) {
|
|
$axios
|
|
.post<ApiSession>('/api/v1/authenticate', {}, { headers: { 'Content-Type': 'application/json' } })
|
|
.then(({ data }) => {
|
|
if (data.type !== ApiSessionType.PUBLIC) {
|
|
reject(new Error('Expected public session from public authentication'));
|
|
} else {
|
|
$cookies.set('public_api_session', JSON.stringify(data), {
|
|
path: '/',
|
|
maxAge: 60 * 60 * 24 * 7 * 4,
|
|
});
|
|
resolve(data.session);
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
reject(error);
|
|
});
|
|
} else {
|
|
resolve(session.session);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
invalidateSession(): void {
|
|
if (store.state.auth.authenticated) {
|
|
$cookies.remove('api_session', {
|
|
path: '/',
|
|
});
|
|
} else {
|
|
store.commit('auth/SET_AUTHED', false);
|
|
$cookies.remove('public_api_session', {
|
|
path: '/',
|
|
});
|
|
}
|
|
}
|
|
|
|
request<T>(url: string, method: 'get' | 'post' = 'get', data: object = {}): Promise<T> {
|
|
return new Promise<T>((resolve, reject) => {
|
|
return this.getSession().then((session) => {
|
|
return ($axios({
|
|
method,
|
|
url: '/api/v1/' + url,
|
|
headers: { Authorization: 'HangarApi session="' + session + '"' },
|
|
data,
|
|
}) as AxiosPromise<T>)
|
|
.then(({ data }) => resolve(data))
|
|
.catch((error) => {
|
|
if (error.response && (error.response.error === 'Api session expired' || error.response.error === 'Invalid session')) {
|
|
// This should never happen but just in case we catch it and invalidate the session to definitely get a new one
|
|
this.invalidateSession();
|
|
this.request<T>(url, method, data)
|
|
.then((data) => {
|
|
resolve(data);
|
|
})
|
|
.catch((error) => {
|
|
reject(error);
|
|
});
|
|
} else {
|
|
reject(error.response.statusText);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
return new API();
|
|
};
|
|
|
|
type apiType = ReturnType<typeof createApi>;
|
|
|
|
declare module 'vue/types/vue' {
|
|
interface Vue {
|
|
$api: apiType;
|
|
}
|
|
}
|
|
|
|
declare module '@nuxt/types' {
|
|
interface NuxtAppOptions {
|
|
$api: apiType;
|
|
}
|
|
|
|
interface Context {
|
|
$api: apiType;
|
|
}
|
|
}
|
|
|
|
declare module 'vuex/types/index' {
|
|
interface Store<S> {
|
|
$api: apiType;
|
|
}
|
|
}
|
|
|
|
export default ({ $axios, app: { $cookies }, store }: Context, inject: Inject) => {
|
|
inject('api', createApi($axios, $cookies, store));
|
|
};
|