This commit is contained in:
Tben 2023-06-24 13:09:26 +01:00
parent 6b6b924cc9
commit 4b826728ab
10 changed files with 286 additions and 358 deletions

3
.gitignore vendored
View File

@ -131,3 +131,6 @@ dist
# typescript # typescript
tsconfig.json tsconfig.json
# others
deprecated

View File

@ -1,168 +0,0 @@
/**
* @typedef {{
* fileBase64: string,
* fileBase64Full: string,
* fileName: string,
* fileSize: number,
* fileType: string,
* }} FunctionReturn
*/
/**
* Login with Google Function
* ==============================================================================
* @description This function takes in a *SINGLE* input file from a HTML file input element.
* HTML file input elements usually return an array of input objects, so be sure to select the target
* file from the array.
*
* @async
*
* @param {object} params - Single object passed
* @param {string} params.clientId - Google app client ID {@link https://datasquirel.com/docs}
* @param {HTMLElement} params.element - HTML Element to display google login button
* @param {boolean} params.triggerPrompt - Whether to trigger Google signing popup or not: {@link https://datasquirel.com/docs}
* @param {function(): void} [params.readyStateDispatch] - React setState Function: sets value to "true"
*
* @returns { Promise } - Return
*/
module.exports = async function loginWithGithub({ clientId, element, triggerPrompt, readyStateDispatch }) {
/**
* == Initialize
*
* @description Initialize
*/
const googleScript = document.createElement("script");
googleScript.src = "https://accounts.google.com/gsi/client";
googleScript.className = "social-script-tag";
document.body.appendChild(googleScript);
googleScript.onload = function (e) {
if (google) {
if (readyStateDispatch) readyStateDispatch(true);
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
if (element) {
function handleCredentialResponse(response) {
userLoginWithGoogle({
gUser: null,
tokenRes: response.credential,
setLoading,
});
}
google.accounts.id.initialize({
client_id: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
callback: handleCredentialResponse,
});
google.accounts.id.renderButton(document.getElementById("google-identity-button"), {
theme: "outline",
size: "large",
logo_alignment: "center",
});
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
if (triggerPrompt) {
google.accounts.id.prompt(
/**
* Google prompt notification callback
* ========================================================
* @param {object} notification - Notification object
* @param {function(): string} notification.getMomentType - Notification moment type
* @param {function(): string} notification.getDismissedReason - Notification get Dismissed Reason
* @param {function(): string} notification.getNotDisplayedReason - Notification get Not Displayed Reason
* @param {function(): string} notification.getSkippedReason - Notification get Skipped Reason
* @param {function(): boolean} notification.isDismissedMoment - Notification is Dismissed Moment
* @param {function(): boolean} notification.isDisplayMoment - Notification is Display Moment
* @param {function(): boolean} notification.isDisplayed - Notification is Displayed
* @param {function(): boolean} notification.isNotDisplayed - Notification is Not Displayed
* @param {function(): boolean} notification.isSkippedMoment - Notification is Skipped Moment
*/
(notification) => {
notification.isDisplayed();
}
);
}
}
};
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
const currentLocation = window.location.pathname;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/**
* Login with google callback function
* ==============================================================================
* @description This function takes in a *SINGLE* input file from a HTML file input element.
* HTML file input elements usually return an array of input objects, so be sure to select the target
* file from the array.
*
* @async
*
* @param {object} params - Single object passed
* @param {string} params.clientId - Google app client ID {@link https://datasquirel.com/docs}
* @param {HTMLElement} params.element - HTML Element to display google login button
* @param {boolean} params.triggerPrompt - Whether to trigger Google signing popup or not: {@link https://datasquirel.com/docs}
* @param {function(): void} [params.readyStateDispatch] - React setState Function: sets value to "true"
*
* @returns { Promise } - Return
*/
function userLoginWithGoogle({ gUser, tokenRes, setLoading }) {
setLoading(true);
if (!tokenRes) {
console.log("No Token Response received!");
return closeLoader();
}
fetchApi(`/api/social-login/google-auth${window.location.search}`, {
method: "post",
body: {
token: tokenRes,
},
})
.then(async (res) => {
if (res.success && res.user) {
localStorage.setItem("csrf", res.user.csrf_k);
localStorage.setItem("user", JSON.stringify(res.user));
window.location.reload();
} else {
console.log(res);
setLoading(false);
if (res.alert) {
window.alert(res.msg);
}
}
})
.catch(async (err) => {
alert("Login Failed");
console.log("Google login fetch error => ", err);
setLoading(false);
});
}

View File

@ -1,179 +0,0 @@
/**
* Type Definitions
* ===============================================================================
*/
/**
* @typedef {object} GoogleIdentityPromptNotification
* @property {function(): string} getMomentType - Notification moment type
* @property {function(): string} getDismissedReason - Notification get Dismissed Reason
* @property {function(): string} getNotDisplayedReason - Notification get Not Displayed Reason
* @property {function(): string} getSkippedReason - Notification get Skipped Reason
* @property {function(): boolean} isDismissedMoment - Notification is Dismissed Moment
* @property {function(): boolean} isDisplayMoment - Notification is Display Moment
* @property {function(): boolean} isDisplayed - Notification is Displayed
* @property {function(): boolean} isNotDisplayed - Notification is Not Displayed
* @property {function(): boolean} isSkippedMoment - Notification is Skipped Moment
*/
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/**
* Login with Google Function
* ===============================================================================
* @description This function uses google identity api to login a user with datasquirel
*
* @async
*
* @param {object} params - Single object passed
* @param {string} params.username - Username or email
* @param {string} params.database - Target database
* @param {string} params.clientId - Google app client ID: {@link https://datasquirel.com/docs}
* @param {HTMLElement} params.element - HTML Element to display google login button
* @param {boolean} params.triggerPrompt - Whether to trigger Google signing popup or not: {@link https://datasquirel.com/docs}
* @param {function(): void} [params.readyStateDispatch] - React setState Function: sets whether the google login button is ready or not
*
* @returns {Promise<boolean>} - Return
*/
module.exports = async function loginWithGoogle({ username, database, clientId, element, triggerPrompt, readyStateDispatch }) {
/**
* == Initialize
*
* @description Initialize
*/
const googleScript = document.createElement("script");
googleScript.src = "https://accounts.google.com/gsi/client";
googleScript.className = "social-script-tag";
document.body.appendChild(googleScript);
googleScript.onload = function (e) {
if (google) {
if (readyStateDispatch) readyStateDispatch(true);
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
if (element) {
/**
* Handle google credentials response
* ========================================================
* @param {object} response - Google response with credentials
* @param {string} response.credential - Google access token
*/
function handleCredentialResponse(response) {
userLoginWithGoogle({
gUser: null,
accessToken: response.credential,
}).then((result) => {
console.log(result);
});
}
google.accounts.id.initialize({
client_id: clientId,
callback: handleCredentialResponse,
});
google.accounts.id.renderButton(element, {
theme: "outline",
size: "large",
logo_alignment: "center",
});
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
if (triggerPrompt) {
google.accounts.id.prompt(
/**
* Google prompt notification callback
* ========================================================
* @param {GoogleIdentityPromptNotification} notification - Notification object
*/
(notification) => {
notification.isDisplayed();
}
);
}
}
};
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/**
* Login with google callback function
* ==============================================================================
* @description This function uses the google token gotten from "loginWithGoogle" function
* and makes the required request to datasquirel
*
* @async
*
* @param {object} params - Single object passed
* @param {string} params.accessToken - Google access token
*
* @returns { Promise<boolean> } - Return
*/
async function userLoginWithGoogle({ accessToken }) {
if (!accessToken) {
console.log("No Token Response received!");
return closeLoader();
}
return await new Promise((resolve, reject) => {
fetch(`https://datasquirel.com/api/user/google-login`, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
token: accessToken,
clientId: clientId,
username: username,
database: database,
}),
})
.then(async (res) => {
if (res.success && res.user) {
localStorage.setItem("csrf", res.user.csrf_k);
localStorage.setItem("user", JSON.stringify(res.user));
resolve(true);
} else {
console.log(res);
if (res.alert) {
window.alert(res.msg);
}
resolve(false);
}
})
.catch(async (err) => {
alert("Login Failed");
console.log("Google login fetch error => ", err);
resolve(false);
});
});
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
};

137
client/auth/logout.js Normal file
View File

@ -0,0 +1,137 @@
/**
* Type Definitions
* ===============================================================================
*/
const parseClientCookies = require("../utils/parseClientCookies");
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/**
* Login with Google Function
* ===============================================================================
* @description This function uses google identity api to login a user with datasquirel
*
* @async
*
* @param {object} params - Single object passed
* @param {string|null} params.googleClientId - Google client Id if applicable
*
* @requires localStorageUser - a "user" JSON string stored in local storage with all
* the necessary user data gotten from the server
*
* @returns {Promise<boolean>} - Return
*/
module.exports = async function logout({ googleClientId }) {
/**
* == Initialize
*
* @description Initialize
*/
const localUser = localStorage.getItem("user");
let targetUser;
try {
targetUser = JSON.parse(localUser);
} catch (error) {
console.log(error);
}
if (!targetUser) {
window.alert("NO client user object found in localStorage");
return false;
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
const cookies = parseClientCookies();
const socialId = cookies.datasquirel_social_id;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
localStorage.setItem("user", "{}");
localStorage.removeItem("csrf");
document.cookie = `datasquirel_social_id=null;samesite=strict;path=/`;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
const response = await new Promise((resolve, reject) => {
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
if (googleClientId) {
const googleScript = document.createElement("script");
googleScript.src = "https://accounts.google.com/gsi/client";
googleScript.className = "social-script-tag";
document.body.appendChild(googleScript);
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
googleScript.onload = function (e) {
if (google) {
if (readyStateDispatch) readyStateDispatch(true);
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
google.accounts.id.initialize({
client_id: clientId,
});
google.accounts.id.revoke(socialId, (done) => {
console.log(done.error);
resolve(true);
});
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
}
};
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
});
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
return response;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
};

View File

@ -0,0 +1,65 @@
/**
* ==============================================================================
* Imports
* ==============================================================================
*/
/**
* Parse request cookies
* ==============================================================================
*
* @description This function takes in a request object and returns the cookies as a JS object
*
* @async
*
* @param {object} params - main params object
* @param {object} params.request - HTTPS request object
*
* @returns {{}|null}
*/
module.exports = function () {
/**
* Check inputs
*
* @description Check inputs
*/
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/** @type {string|null} */
const cookieString = document.cookie;
if (!cookieString || typeof cookieString !== "string") {
return null;
}
/** @type {string[]} */
const cookieSplitArray = cookieString.split(";");
let cookieObject = {};
cookieSplitArray.forEach((keyValueString) => {
const [key, value] = keyValueString.split("=");
if (key && typeof key == "string") {
cookieObject[key.replace(/^ +| +$/, "")] = value && typeof value == "string" ? value.replace(/^ +| +$/, "") : null;
}
});
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
return cookieObject;
};
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////

View File

@ -1,6 +1,6 @@
{ {
"name": "datasquirel", "name": "datasquirel",
"version": "1.1.42", "version": "1.1.43",
"description": "Cloud-based SQL data management tool", "description": "Cloud-based SQL data management tool",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@ -1,10 +1,13 @@
const parseCookies = require("../utils/functions/parseCookies");
/** /**
* ============================================================================== * Logout user
* Main Function
* ============================================================================== * ==============================================================================
* @param {object} params - Single Param object containing params * @param {object} params - Single Param object containing params
* @param {object} params.request - Http request object * @param {object} params.request - Http request object
* @param {object} params.response - Http response object * @param {object} params.response - Http response object
*
* @returns {{success: boolean, payload: string}}
*/ */
module.exports = function ({ request, response }) { module.exports = function ({ request, response }) {
/** /**
@ -13,7 +16,7 @@ module.exports = function ({ request, response }) {
* @description Check Encryption Keys * @description Check Encryption Keys
*/ */
try { try {
const cookiesKeys = Object.keys(request.cookies); const cookiesKeys = Object.keys(parseCookies({ request }));
const authKeyName = cookiesKeys.filter((cookieKey) => cookieKey.match(/datasquirel_.*_auth_key/))[0]; const authKeyName = cookiesKeys.filter((cookieKey) => cookieKey.match(/datasquirel_.*_auth_key/))[0];
const csrfName = cookiesKeys.filter((cookieKey) => cookieKey.match(/datasquirel_.*_csrf/))[0]; const csrfName = cookiesKeys.filter((cookieKey) => cookieKey.match(/datasquirel_.*_csrf/))[0];

View File

@ -170,12 +170,12 @@ module.exports = async function ({ key, token, database, clientId, response, enc
encryptionSalt, encryptionSalt,
}); });
const { user } = httpResponse; const { user, dsqlUserId } = httpResponse;
const authKeyName = `datasquirel_${user.id}_${database}_auth_key`; const authKeyName = `datasquirel_${dsqlUserId}_${database}_auth_key`;
const csrfName = `datasquirel_${user.id}_${database}_csrf`; const csrfName = `datasquirel_${dsqlUserId}_${database}_csrf`;
response.setHeader("Set-Cookie", [`${authKeyName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`, `${csrfName}=${httpResponse.user.csrf_k};samesite=strict;path=/;sHttpOnly=true`, `dsqluid=${user.id};samesite=strict;path=/;HttpOnly=true`]); response.setHeader("Set-Cookie", [`${authKeyName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`, `${csrfName}=${user.csrf_k};samesite=strict;path=/;HttpOnly=true`, `dsqluid=${dsqlUserId};samesite=strict;path=/;HttpOnly=true`, `datasquirel_social_id=${user.social_id};samesite=strict;path=/`]);
} }
//////////////////////////////////////// ////////////////////////////////////////

View File

@ -4,6 +4,7 @@
* ============================================================================== * ==============================================================================
*/ */
const decrypt = require("../functions/decrypt"); const decrypt = require("../functions/decrypt");
const parseCookies = require("../utils/functions/parseCookies");
/** ****************************************************************************** */ /** ****************************************************************************** */
/** ****************************************************************************** */ /** ****************************************************************************** */
@ -56,12 +57,13 @@ module.exports = function ({ request, encryptionKey, encryptionSalt, level, data
* *
* @description Grab the payload * @description Grab the payload
*/ */
const dsqluid = request.cookies.dsqluid; const cookies = parseCookies({ request });
const dsqluid = cookies.dsqluid;
const authKeyName = `datasquirel_${dsqluid}_${database}_auth_key`; const authKeyName = `datasquirel_${dsqluid}_${database}_auth_key`;
const csrfName = `datasquirel_${dsqluid}_${database}_csrf`; const csrfName = `datasquirel_${dsqluid}_${database}_csrf`;
const key = request.cookies[authKeyName]; const key = cookies[authKeyName];
const csrf = request.cookies[csrfName]; const csrf = cookies[csrfName];
/** /**
* Grab the payload * Grab the payload

View File

@ -0,0 +1,65 @@
/**
* ==============================================================================
* Imports
* ==============================================================================
*/
/**
* Parse request cookies
* ==============================================================================
*
* @description This function takes in a request object and returns the cookies as a JS object
*
* @async
*
* @param {object} params - main params object
* @param {object} params.request - HTTPS request object
*
* @returns {{}|null}
*/
module.exports = function ({ request }) {
/**
* Check inputs
*
* @description Check inputs
*/
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/** @type {string|null} */
const cookieString = request.headers.cookie;
if (!cookieString || typeof cookieString !== "string") {
return null;
}
/** @type {string[]} */
const cookieSplitArray = cookieString.split(";");
let cookieObject = {};
cookieSplitArray.forEach((keyValueString) => {
const [key, value] = keyValueString.split("=");
if (key && typeof key == "string") {
cookieObject[key.replace(/^ +| +$/, "")] = value && typeof value == "string" ? value.replace(/^ +| +$/, "") : null;
}
});
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
return cookieObject;
};
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////