all over the place with comments and console statements but now properly chains all the calls for login (except translation may have an issue)

This commit is contained in:
2020-06-10 21:05:45 +00:00
parent c0fcecb3f8
commit 0a43e53ab7
25 changed files with 1966 additions and 976 deletions

View File

@@ -4,24 +4,61 @@ import { processLogin, processLogout } from "./authutil";
export default {
async authenticate(login, password) {
return fetch(
window.$gz.api.APIUrl("auth"),
window.$gz.api.fetchPostNoAuthOptions({
login: login,
password: password
})
)
.then(window.$gz.api.status)
.then(window.$gz.api.extractBody)
.then(processLogin)
.then(() => {
return Promise.resolve(true);
}) //succeeded, nothing to return
.catch(function handleAuthError(error) {
processLogout();
return Promise.reject(error);
});
return new Promise(async function doAuth(resolve, reject) {
try {
console.log("AUTH: TOP");
let fetchData = await fetch(
window.$gz.api.APIUrl("auth"),
window.$gz.api.fetchPostNoAuthOptions({
login: login,
password: password
})
);
console.log("AUTH: status");
fetchData = await window.$gz.api.status(fetchData);
console.log("AUTH: extractBody");
fetchData = await window.$gz.api.extractBody(fetchData);
console.log("AUTH: calling processLogin");
await processLogin(fetchData);
console.log(
"### AUTH:after processlogin completed - resolving done (THIS SHOULD BE LAST)"
);
resolve();
} catch (e) {
reject(e);
}
// .catch(function handleAuthError(error) {
// processLogout();
// return reject(error);
// });
// .then(processLogin)
// .then(() => {
// return resolve(true);
// }) //succeeded, nothing to return
});
},
// async authenticate(login, password) {
// return fetch(
// window.$gz.api.APIUrl("auth"),
// window.$gz.api.fetchPostNoAuthOptions({
// login: login,
// password: password
// })
// )
// .then(window.$gz.api.status)
// .then(window.$gz.api.extractBody)
// .then(processLogin)
// .then(() => {
// console.log("auth:authenticate returning resolved done");
// return Promise.resolve(true);
// }) //succeeded, nothing to return
// .catch(function handleAuthError(error) {
// processLogout();
// return Promise.reject(error);
// });
// },
logout() {
processLogout();
}

View File

@@ -3,67 +3,101 @@ import decode from "jwt-decode";
import initialize from "./initialize";
export function processLogin(response) {
return new Promise(function(resolve, reject) {
//check there is a response of some kind
if (!response) {
window.$gz.store.commit("logItem", "auth::processLogin -> no response");
return reject();
}
return new Promise(async function(resolve, reject) {
try {
console.log("authutil:process login TOP");
//is there an error?
if (response.error) {
return reject(response.error);
}
//check there is a response of some kind
if (!response) {
window.$gz.store.commit("logItem", "auth::processLogin -> no response");
return reject();
}
//is token present?
if (!response.data || !response.data.token) {
window.$gz.store.commit(
"logItem",
"auth::processLogin -> response contains no data"
);
return reject();
}
const token = decode(response.data.token);
//is there an error?
if (response.error) {
return reject(response.error);
}
if (!token || !token.iss) {
window.$gz.store.commit(
"logItem",
"auth::processLogin -> response token empty"
);
return reject();
}
//is token present?
if (!response.data || !response.data.token) {
window.$gz.store.commit(
"logItem",
"auth::processLogin -> response contains no data"
);
return reject();
}
const token = decode(response.data.token);
if (token.iss != "ayanova.com") {
window.$gz.store.commit(
"logItem",
"auth::processLogin -> token invalid (iss): " + token.iss
);
return reject();
}
if (!token || !token.iss) {
window.$gz.store.commit(
"logItem",
"auth::processLogin -> response token empty"
);
return reject();
}
//ensure the store is clean first in case we didn't come here from a clean logout
window.$gz.store.commit("logout");
sessionStorage.clear(); //clear all temporary session storage data
if (token.iss != "ayanova.com") {
window.$gz.store.commit(
"logItem",
"auth::processLogin -> token invalid (iss): " + token.iss
);
return reject();
}
//Put app relevant items into vuex store so app can use them
window.$gz.store.commit("login", {
apiToken: response.data.token,
authenticated: true,
userId: Number(token.id),
userName: response.data.name,
roles: response.data.roles,
userType: response.data.usertype,
dlt: response.data.dlt
});
//ensure the store is clean first in case we didn't come here from a clean logout
window.$gz.store.commit("logout");
sessionStorage.clear(); //clear all temporary session storage data
//Initialize the application
initialize().then(() => {
//Put app relevant items into vuex store so app can use them
window.$gz.store.commit("login", {
apiToken: response.data.token,
authenticated: true,
userId: Number(token.id),
userName: response.data.name,
roles: response.data.roles,
userType: response.data.usertype,
dlt: response.data.dlt
});
//log the login
window.$gz.store.commit(
"logItem",
"auth::processLogin -> User " + token.id + " logged in"
);
resolve(true);
});
//Get global settings
console.log("authutil:calling get blobal settings");
let gsets = await window.$gz.api.get("global-biz-setting/client");
console.log("authutil:got global settings");
if (gsets.error) {
//In a form this would trigger a bunch of validation or error display code but for here and now:
//convert error to human readable string for display and popup a notification to user
let msg = window.$gz.api.apiErrorToHumanString(gsets.error);
window.$gz.store.commit(
"logItem",
"Initialize::() fetch global-biz-setting/client -> error" + msg
);
window.$gz.eventBus.$emit("notify-error", msg);
} else {
//Check if overrides and use them here
//or else use browser defaults
window.$gz.store.commit("setGlobalSettings", gsets.data);
}
console.log("** authutil calling test delay --->>>>");
await window.$gz.api.doDelayAsync();
console.log("** authutil back from delay continuing..");
//INITIALIZE
console.log("authutil:calling initialize");
await initialize();
} catch (err) {
console.log("authutil:error in async chain global/init");
reject(err);
}
console.log("authutil:no error resolving async chain global/init");
resolve();
//-------------------------------------------------
});
}

View File

@@ -43,7 +43,7 @@ export default {
if (!window.$gz._.has(window.$gz.store.state.enums, k)) {
let that = this;
await that.fetch(k).then(dat => {
await that.fetchEnumKey(k).then(dat => {
//massage the data as necessary
let e = { enumKey: k, items: {} };
for (let i = 0; i < dat.length; i++) {
@@ -56,7 +56,7 @@ export default {
}
}
},
fetch(enumKey) {
fetchEnumKey(enumKey) {
return window.$gz.api.get("enum-list/list/" + enumKey).then(res => {
if (res.error) {
throw res.error;

View File

@@ -150,6 +150,63 @@ export default {
return Promise.resolve(response);
}
},
statusEx(response) {
//Handle expected api errors
if (response.status == 401) {
//must reject if not Authenticated
throw new Error("[ErrorUserNotAuthenticated]");
}
if (response.status == 403) {
//must reject if not Authorized
throw new Error("[ErrorUserNotAuthorized]");
}
//404 not found is an expected status not worth logging allow to bubble up
//for client code to deal with
if (response.status == 404) {
return;
}
if (response.status == 405) {
//Probably a development error
throw new Error("Method Not Allowed (route issue?) " + response.url);
}
if (response.status >= 200 && response.status < 300) {
return;
} else {
//log unhandled api error
window.$gz.store.commit(
"logItem",
"API error: status=" +
response.status +
", statusText=" +
response.statusText +
", url=" +
response.url
);
}
},
async extractBodyEx(response) {
if (response.status == 204) {
//no content, nothing to process
return response;
}
let contentType = response.headers.get("content-type");
if (!contentType) {
return response;
}
//console.log("gzapi::extractBody method, content type is:", contentType);
if (contentType.includes("json")) {
return await response.json();
}
if (contentType.includes("text/plain")) {
return await response.text();
}
return response;
},
extractBody(response) {
if (response.status == 204) {
//no content, nothing to process
@@ -372,9 +429,58 @@ export default {
});
});
},
//////////////////////////////////////
// Test delay for troubleshooting
//
doDelayAsync: () => {
return new Promise((resolve) => {
setTimeout(() => resolve("I did something"), 10000);
});
},
///////////////////////////////////
// POST / PUT DATA TO API SERVER
//
async upsertEx(route, data) {
try {
console.log("gzapi:upsertEx TOP");
let that = this;
// return new Promise(function upsertDataToServer(resolve, reject) {
//determine if this is a new or existing record
let fetchOptions = undefined;
if (data.concurrency) {
//has concurrency token, so this is a PUT as it's updating an existing record
fetchOptions = that.fetchPutOptions(data);
} else {
//Does not have a concurrency token so this is a POST as it's posting a new record without a concurrency token
fetchOptions = that.fetchPostOptions(data);
//ensure the route doesn't end in /0 which will happen if it's a new record since the edit forms just send the url here with the ID regardless
if (window.$gz._.endsWith(route, "/0")) {
route = route.slice(0, -2);
}
}
// console.log("** gzapi:upsertEx calling test delay");
// await this.doDelayAsync();
// console.log("** gzapi:upsertEx back from delay continuing..");
console.log("gzapi:upsertEx calling fetch");
let r = await fetch(that.APIUrl(route), fetchOptions);
console.log("gzapi:upsertEx calling statusEx");
that.statusEx(r);
console.log("gzapi:upsertEx calling extractBodyEx");
r = await that.extractBodyEx(r);
console.log("gzapi:upsertEx done, returning response");
return r;
// eslint-disable-next-line
// .then((response) => {
// //Note: response.error indicates there is an error, however this is not an unusual condition
// //it could be validation errors or other general error so we need to treat it here like it's normal
// //and let the caller deal with it appropriately
// resolve(response);
// })
} catch (error) {
handleError("UPSERT", error, route, reject);
}
// });
},
upsert(route, data) {
let that = this;
return new Promise(function upsertDataToServer(resolve, reject) {

File diff suppressed because it is too large Load Diff

View File

@@ -11,8 +11,8 @@ export default {
}
return window.$gz.store.state.translationText[key];
},
fetch(keys) {
return new Promise(function fetchTranslationKeysFromServer(resolve) {
async cacheTranslations(keys) {
return new Promise(async function fetchTranslationKeysFromServer(resolve) {
//
//step 1: build an array of keys that we don't have already
//Note: this will ensure only unique keys go into the store so it's safe to call this with dupes as can happen
@@ -27,29 +27,74 @@ export default {
}
if (needIt.length == 0) {
resolve();
return;
return resolve();
}
//step 2: get it
fetch(
console.log("translation:cacheTranslations calling fetch via API");
let testres = await window.$gz.api.upsertEx("translation/subset", needIt);
console.log(testres);
console.log("translation:cacheTranslations calling fetch directly");
let response = await fetch(
window.$gz.api.APIUrl("translation/subset"),
window.$gz.api.fetchPostOptions(needIt)
)
.then(window.$gz.api.status)
.then(window.$gz.api.extractBody)
// eslint-disable-next-line
.then((response) => {
window.$gz._.forEach(
response.data,
function commitFetchedLTItemToStore(item) {
window.$gz.store.commit("addTranslationText", item);
}
);
resolve();
});
);
console.log("translation:fetch calling STATUS");
let data = await window.$gz.api.status(response);
console.log("translation:fetch calling extractBody");
let data2 = await window.$gz.api.extractBody(data);
console.log("translation:fetch calling processing into store");
window.$gz._.forEach(data2, function commitFetchedLTItemToStore(item) {
window.$gz.store.commit("addTranslationText", item);
});
console.log("translation:fetch done calling resolve");
return resolve();
});
},
// fetch(keys) {
// return new Promise(async function fetchTranslationKeysFromServer(resolve) {
// //
// //step 1: build an array of keys that we don't have already
// //Note: this will ensure only unique keys go into the store so it's safe to call this with dupes as can happen
// //for example datatables have dynamic column names so they need to fetch on demand
// let needIt = [];
// for (let i = 0; i < keys.length; i++) {
// if (
// !window.$gz._.has(window.$gz.store.state.translationText, keys[i])
// ) {
// needIt.push(keys[i]);
// }
// }
// if (needIt.length == 0) {
// resolve();
// return;
// }
// //step 2: get it
// await fetch(
// window.$gz.api.APIUrl("translation/subset"),
// window.$gz.api.fetchPostOptions(needIt)
// )
// .then(window.$gz.api.status)
// .then(window.$gz.api.extractBody)
// // eslint-disable-next-line
// .then((response) => {
// window.$gz._.forEach(
// response.data,
// function commitFetchedLTItemToStore(item) {
// window.$gz.store.commit("addTranslationText", item);
// }
// );
// console.log("translation:fetch calling resolve");
// resolve();
// });
// });
// },
//Keys that will always be required for any AyaNova work for any user
coreKeys: [
//main nav options