Refactored user store & moved popup logic from App to store

Cleaned up bits of all the components that use these stores.

User store now focuses around keeping track of the authorization token
and the response from /login. When a sucessfull login request is made we
save our new token and username & admin data to the with login(). Since
cookies aren't implemented yet we keep track of the auth_token to make
authroized requests back to the api later.
The username and admin data from within the body of the token is saved
and only cleared on logout().
Since we haven't implemented cookies we persist storage with
localStorage. Whenever we successfully decode and save a token body we
also save the token to localStorage. This is later used by
initFromLocalStorage() to hydrate the store on first page load.

Popup module is for opening and closing the popup, and now moved away
from a inline plugin in App entry. Now handles loading from &
updating query parameters type=movie | show.
The route listens checks if open every navigation and closes popup if it
is.
This commit is contained in:
2022-01-12 22:20:12 +01:00
parent d1cbbfffd8
commit b021882013
14 changed files with 723 additions and 685 deletions

59
src/modules/popup.js Normal file
View File

@@ -0,0 +1,59 @@
const removeIncludedQueryParams = (params, key) => {
if (params.has(key)) params.delete(key);
return params;
};
const updateQueryParams = (id = null, type = null) => {
let params = new URLSearchParams(window.location.search);
params = removeIncludedQueryParams(params, "movie");
params = removeIncludedQueryParams(params, "show");
if (id && type === "movie") {
params.append("movie", id);
}
if (id && type === "show") {
params.append("show", id);
}
let url = `${window.location.protocol}//${window.location.hostname}${
window.location.port ? `:${window.location.port}` : ""
}${window.location.pathname}${params.toString().length ? `?${params}` : ""}`;
window.history.replaceState({}, "search", url);
};
export default {
namespaced: true,
state: {
id: null,
type: null,
open: false
},
getters: {
isOpen: state => state.open,
id: state => state.id,
type: state => state.type
},
mutations: {
SET_OPEN: (state, { id, type }) => {
state.id = id;
state.type = type;
state.open = true;
},
SET_CLOSE: state => {
state.id = null;
state.type = null;
state.open = false;
}
},
actions: {
open: ({ commit }, { id, type = "movie" }) => {
commit("SET_OPEN", { id, type });
updateQueryParams(id, type);
},
close: ({ commit }) => {
commit("SET_CLOSE");
updateQueryParams(); // reset
}
}
};

103
src/modules/user.js Normal file
View File

@@ -0,0 +1,103 @@
import { refreshToken } from "@/api";
import { parseJwt } from "@/utils";
function setLocalStorageByKey(key, value) {
if (value instanceof Object || value instanceof Array) {
value = JSON.stringify(value);
}
const buff = Buffer.from(value);
const encodedValue = buff.toString("base64");
localStorage.setItem(key, encodedValue);
}
function getLocalStorageByKey(key) {
const encodedValue = localStorage.getItem(key);
if (encodedValue == null) {
return null;
}
const buff = new Buffer(encodedValue, "base64");
const value = buff.toString("utf-8");
try {
return JSON.parse(value);
} catch {
return value;
}
}
export default {
namespaced: true,
state: {
token: null,
admin: false,
settings: null,
username: null
},
getters: {
username: state => state.username,
settings: state => state.settings,
token: state => state.token,
loggedIn: state => state && state.username !== null,
admin: state => state && state.admin !== null,
plexId: state => {
if (state && state.settings && state.settings.plex_userid)
return state.settings.plex_userid;
return null;
}
},
mutations: {
SET_TOKEN: (state, token) => (state.token = token),
SET_USERNAME: (state, username) => (state.username = username),
SET_SETTINGS: (state, settings) => (state.settings = settings),
SET_ADMIN: (state, admin) => (state.admin = admin),
LOGOUT: state => {
state.token = null;
state.username = null;
state.settings = null;
state.admin = false;
localStorage.removeItem("token");
}
},
actions: {
initFromLocalStorage: async ({ dispatch }) => {
const token = getLocalStorageByKey("token");
if (token) await dispatch("setupStateFromToken", token);
const settings = getLocalStorageByKey("settings");
if (settings) await dispatch("setSettings", settings);
},
setupStateFromToken: ({ commit }, token) => {
try {
const jwtData = parseJwt(token);
const { username, admin } = jwtData;
if (!username) {
return false;
}
commit("SET_TOKEN", token);
commit("SET_USERNAME", username);
commit("SET_ADMIN", admin != undefined ? true : false);
return true;
} catch (error) {
console.log("Unable to parse JWT, failed with error:", error);
return false;
}
},
setSettings: ({ commit }, settings) => {
if (!(settings instanceof Object)) {
throw "Parameter is not a object.";
}
commit("SET_SETTINGS", settings);
setLocalStorageByKey("settings", settings);
},
logout: ({ commit }) => commit("LOGOUT"),
login: async ({ dispatch }, token) => {
const loggedIn = await dispatch("setupStateFromToken", token);
if (loggedIn) setLocalStorageByKey("token", token);
return loggedIn;
}
}
};

View File

@@ -1,112 +0,0 @@
import { getSettings } from '@/api'
function setLocalStorageByKey(key, value) {
if (value instanceof Object || value instanceof Array) {
value = JSON.stringify(value)
}
const buff = Buffer.from(value)
const encodedValue = buff.toString('base64')
localStorage.setItem(key, encodedValue)
}
function getLocalStorageByKey(key) {
const encodedValue = localStorage.getItem(key)
if (encodedValue == null) {
return undefined
}
const buff = new Buffer(encodedValue, 'base64')
const value = buff.toString('utf-8')
try {
return JSON.parse(value)
} catch {
return value
}
}
const ifMissingSettingsAndTokenExistsFetchSettings =
() => getLocalStorageByKey('token') ? getSettings() : null
export default {
namespaced: true,
state: {
admin: false,
settings: undefined,
username: undefined,
plex_userid: undefined
},
getters: {
admin: (state) => {
return state.admin
},
settings: (state, foo, bar) => {
console.log('is this called?')
const settings = state.settings || getLocalStorageByKey('settings')
if (settings instanceof Object) {
return settings
}
ifMissingSettingsAndTokenExistsFetchSettings()
return undefined
},
username: (state) => {
const settings = state.settings || getLocalStorageByKey('settings')
if (settings instanceof Object && settings.hasOwnProperty('user_name')) {
return settings.user_name
}
ifMissingSettingsAndTokenExistsFetchSettings()
return undefined
},
plex_userid: (state) => {
const settings = state.settings || getLocalStorageByKey('settings')
console.log('plex_userid from store', settings)
if (settings instanceof Object && settings.hasOwnProperty('plex_userid')) {
return settings.plex_userid
}
ifMissingSettingsAndTokenExistsFetchSettings()
return undefined
},
isPlexAuthenticated: (state) => {
const settings = state.settings || getLocalStorageByKey('settings')
if (settings == null)
return false
const hasPlexId = settings['plex_userid']
return hasPlexId != null ? true : false
}
},
mutations: {
SET_ADMIN: (state, isAdmin) => {
state.admin = isAdmin
},
SET_USERNAME: (state, username) => {
state.username = username
console.log('username')
setLocalStorageByKey('username', username)
},
SET_SETTINGS: (state, settings) => {
state.settings = settings
console.log('settings')
setLocalStorageByKey('settings', settings)
}
},
actions: {
setAdmin: ({commit}, isAdmin) => {
if (!(isAdmin instanceof Object)) {
throw "Parameter is not a boolean value."
}
commit('SET_ADMIN', isAdmin)
},
setSettings: ({commit}, settings) => {
console.log('settings input', settings)
if (!(settings instanceof Object)) {
throw "Parameter is not a object."
}
commit('SET_SETTINGS', settings)
}
}
}