You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

122 lines
3.3 KiB

import { ActionTree } from "vuex";
import { Actions } from "./generics";
import { IState } from "./state";
import { Mutation, MutationsTypes } from "./mutations";
import router from "../routes";
import { GettersTypes } from "./getters";
// Payload types
type IAuthenticatePayload = { email: string, password: string, remember: boolean };
type IAuthenticateResult = { email?: string[], password?: string[] } | null;
type IAuthFetchPayload = { path: string, options?: RequestInit };
/**
* The available actions te perform
*/
export enum Action {
// Authentication
AuthAuthenticate = "AUTH_AUTHENTICATE",
AuthForget = "AUHT_FORGET",
AuthLoad = "AUTH_LOAD",
// RESTful
AuthFetch = "AUTH_FETCH"
}
/**
* The action function signatures
*/
export type ActionsTypes = {
// Authentication
[Action.AuthAuthenticate]: (payload: IAuthenticatePayload) => Promise<IAuthenticateResult>,
[Action.AuthForget] : () => void,
[Action.AuthLoad] : () => boolean
// RESTful
[Action.AuthFetch]: (payload: IAuthFetchPayload) => Promise<Response>
}
/**
* The action function implementations
*/
export const actions: Actions<IState, GettersTypes, MutationsTypes, ActionsTypes> & ActionTree<IState, IState> = {
// Authentication ------------------------------------------------------------------------------
/**
* Authenticate the credentials of a user and log them in
*/
[Action.AuthAuthenticate]({commit, dispatch}, {email, password, remember = false}) {
return new Promise((resolve, reject) => {
fetch(`/auth/login?use_cookies=${navigator.cookieEnabled}`, {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({email, password})
})
.then(async response => {
let body = await response.json();
if (response.status !== 200) {
if (response.status === 401) {
body.errors = { "email": [ "Email or password is incorrect" ] };
}
resolve(body.errors || {});
return;
}
commit(Mutation.LoadUser, body.token);
commit(Mutation.StoreUser, remember);
resolve(null);
})
.catch(e => {
console.error("Error occurred during submission:", e);
reject(e);
});
});
},
/**
* Forget the login token and log the user out
*/
[Action.AuthForget]({commit}) {
commit(Mutation.ForgetUser, undefined);
},
/**
* Load the user from local storage
*/
[Action.AuthLoad]({getters, commit, dispatch}) {
let token = getters.storedToken;
if (!token) {
return false;
}
try {
commit(Mutation.LoadUser, token);
} catch(e) {
dispatch(Action.AuthForget, undefined);
return false;
}
return true;
},
// RESTful -------------------------------------------------------------------------------------
/**
* Fetch request providing authentication and logout upon unauthorized requests
*/
async [Action.AuthFetch]({commit, state}, {path, options = {}}) {
if (state.user == null) {
router.push({ name: "Login" });
throw Error("Unauthorized");
}
options.credentials = "include";
options.headers = Object.assign(options.headers ?? {}, {
"Authorization": `Bearer ${state.user.token}`
});
let response = await fetch(path, options);
if (response.status === 401) {
commit(Mutation.ForgetUser, undefined);
router.push({ name: "Login" });
throw Error("Unauthorized");
}
return response;
}
};