From b47bf437a92cffb060037a12a9b6653411ff9ca4 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Sat, 2 Dec 2023 21:16:56 +0530 Subject: [PATCH] created generateapitoken, getapitoken cloud function & generatetoken route --- apps/OpenSign/src/App.js | 9 ++ apps/OpenSign/src/routes/GenerateToken.js | 139 ++++++++++++++++++ apps/OpenSignServer/cloud/main.js | 8 +- .../cloud/parsefunction/generateApiToken.js | 44 ++++++ .../cloud/parsefunction/getapitoken.js | 24 +++ apps/OpenSignServer/package-lock.json | 31 +++- apps/OpenSignServer/package.json | 1 + 7 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 apps/OpenSign/src/routes/GenerateToken.js create mode 100644 apps/OpenSignServer/cloud/parsefunction/generateApiToken.js create mode 100644 apps/OpenSignServer/cloud/parsefunction/getapitoken.js diff --git a/apps/OpenSign/src/App.js b/apps/OpenSign/src/App.js index 500e00808..b14bfb284 100644 --- a/apps/OpenSign/src/App.js +++ b/apps/OpenSign/src/App.js @@ -15,6 +15,7 @@ import ForgetPassword from "./routes/ForgetPassword"; import ChangePassword from "./routes/ChangePassword"; import ReportMicroapp from "./components/ReportMicroapp"; import LoadMf from "./routes/LoadMf"; +import GenerateToken from "./routes/GenerateToken"; function App() { const [isloading, setIsLoading] = useState(true); @@ -138,6 +139,14 @@ function App() { } /> + + + + } + /> } /> {/* } /> */} diff --git a/apps/OpenSign/src/routes/GenerateToken.js b/apps/OpenSign/src/routes/GenerateToken.js new file mode 100644 index 000000000..a507d29aa --- /dev/null +++ b/apps/OpenSign/src/routes/GenerateToken.js @@ -0,0 +1,139 @@ +import React, { useEffect, useState } from "react"; +import Title from "../components/Title"; +import axios from "axios"; + +function GenerateToken() { + const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); + const [parseAppId] = useState(localStorage.getItem("parseAppId")); + const [apiToken, SetApiToken] = useState(""); + const [isLoader, setIsLoader] = useState(true); + const [copied, setCopied] = useState(false); + + useEffect(() => { + fetchToken(); + // eslint-disable-next-line + }, []); + + const fetchToken = async () => { + try { + const url = parseBaseUrl + "functions/getapitoken"; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessiontoken: localStorage.getItem("accesstoken") + }; + const res = await axios.post(url, {}, { headers: headers }); + if (res) { + SetApiToken(res.data.result.result); + } + setIsLoader(false); + } catch (err) { + SetApiToken(); + setIsLoader(false); + console.log("Err", err); + } + }; + const handleSubmit = async (e) => { + e.preventDefault(); + setIsLoader(true); + try { + const url = parseBaseUrl + "functions/generateapitoken"; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessiontoken: localStorage.getItem("accesstoken") + }; + await axios.post(url, {}, { headers: headers }).then((res) => { + if (res) { + SetApiToken(res.data.result.token); + // localStorage.setItem("apiToken", res.data.result.token); + alert("Token generated successfully!"); + setIsLoader(false); + } else { + alert("Something went wrong!"); + console.error("Error while generating Token"); + setIsLoader(false); + } + }); + } catch (error) { + setIsLoader(false); + alert("Something went wrong!"); + console.log("err", error); + } + }; + + const copytoclipboard = (text) => { + navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => { + setCopied(false); + }, 1500); // Reset copied state after 1.5 seconds + }; + return ( + + + {copied && ( + <div className={`alert alert-success alertBox`} role="alert"> + Copied + </div> + )} + {isLoader ? ( + <div + style={{ + height: "100vh", + display: "flex", + alignItems: "center", + justifyContent: "center" + }} + > + <div + style={{ + fontSize: "45px", + color: "#3dd3e0" + }} + className="loader-37" + ></div> + </div> + ) : ( + <div className="bg-white flex flex-col justify-center shadow rounded"> + <ul className="w-full flex flex-col p-2 text-sm"> + <li + className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all py-2`} + > + <span className="w-[40%]">Api Token:</span>{" "} + <span + id="token" + className="w-[60%] md:text-end cursor-pointer" + onClick={() => copytoclipboard(apiToken)} + > + {apiToken && apiToken} + </span> + </li> + <li + className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`} + > + <span className="w-[40%]">Application Id:</span>{" "} + <span + className="w-[60%] md:text-end cursor-pointer" + onClick={() => copytoclipboard(localStorage.getItem("AppID12"))} + > + {localStorage.getItem("AppID12")} + </span> + </li> + </ul> + <div className="flex justify-center pb-4"> + <button + type="button" + onClick={handleSubmit} + className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base" + > + {apiToken ? "Regenerate Token" : "Generate Token"} + </button> + </div> + </div> + )} + </React.Fragment> + ); +} + +export default GenerateToken; diff --git a/apps/OpenSignServer/cloud/main.js b/apps/OpenSignServer/cloud/main.js index e42ee38e5..97b5ab466 100644 --- a/apps/OpenSignServer/cloud/main.js +++ b/apps/OpenSignServer/cloud/main.js @@ -17,6 +17,8 @@ import getUserDetails from './parsefunction/getUserDetails.js'; import getDocument from './parsefunction/getDocument.js'; import getDrive from './parsefunction/getDrive.js'; import getReport from './parsefunction/getReport.js'; +import generateApiToken from './parsefunction/generateApiToken.js'; +import getapitoken from './parsefunction/getapitoken.js'; Parse.Cloud.define('AddUserToRole', addUserToGroups); Parse.Cloud.define('UserGroups', getUserGroups); @@ -35,5 +37,7 @@ Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail); Parse.Cloud.define('getUserId', getUserId); Parse.Cloud.define('getUserDetails', getUserDetails); Parse.Cloud.define('getDocument', getDocument); -Parse.Cloud.define('getDrive', getDrive) -Parse.Cloud.define('getReport', getReport) \ No newline at end of file +Parse.Cloud.define('getDrive', getDrive); +Parse.Cloud.define('getReport', getReport); +Parse.Cloud.define('generateapitoken', generateApiToken); +Parse.Cloud.define('getapitoken', getapitoken); diff --git a/apps/OpenSignServer/cloud/parsefunction/generateApiToken.js b/apps/OpenSignServer/cloud/parsefunction/generateApiToken.js new file mode 100644 index 000000000..bdf7842cc --- /dev/null +++ b/apps/OpenSignServer/cloud/parsefunction/generateApiToken.js @@ -0,0 +1,44 @@ +import { generateApiKey } from 'generate-api-key'; +import axios from 'axios'; +export default async function generateApiToken(request) { + const serverUrl = process.env.SERVER_URL; + try { + const userRes = await axios.get(serverUrl + '/users/me', { + headers: { + 'X-Parse-Application-Id': process.env.APP_ID, + 'X-Parse-Session-Token': request.headers['sessiontoken'], + }, + }); + const userId = userRes.data && userRes.data.objectId; + if (userId) { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('Id', userId); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // return exsiting Token + console.log('Regenerate API Token'); + const AppToken = Parse.Object.extend('appToken'); + const updateToken = new AppToken(); + updateToken.id = token.id; + const newToken = generateApiKey({ method: 'base62', prefix: 'opensign' }); + updateToken.set('token', newToken); + const updatedRes = await updateToken.save(null, { useMasterKey: true }); + return updatedRes; + } else { + // Create New Token + console.log('New API Token Generation'); + const appToken = Parse.Object.extend('appToken'); + const appTokenQuery = new appToken(); + const token = generateApiKey({ method: 'base62', prefix: 'opensign' }); + appTokenQuery.set('token', token); + appTokenQuery.set('Id', userId); + const newRes = await appTokenQuery.save(null, { useMasterKey: true }); + return newRes; + } + } else { + return 'User not found!'; + } + } catch (err) { + console.log('err ', err); + } +} diff --git a/apps/OpenSignServer/cloud/parsefunction/getapitoken.js b/apps/OpenSignServer/cloud/parsefunction/getapitoken.js new file mode 100644 index 000000000..5e12d6a39 --- /dev/null +++ b/apps/OpenSignServer/cloud/parsefunction/getapitoken.js @@ -0,0 +1,24 @@ +import axios from 'axios'; +export default async function getapitoken(request) { + const serverUrl = process.env.SERVER_URL; + try { + const userRes = await axios.get(serverUrl + '/users/me', { + headers: { + 'X-Parse-Application-Id': process.env.APP_ID, + 'X-Parse-Session-Token': request.headers['sessiontoken'], + }, + }); + const userId = userRes.data && userRes.data.objectId; + if (userId) { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('Id', userId); + const res = await tokenQuery.first({ useMasterKey: true }); + if (res) { + return { status: 'success', result: res.get('token') }; + } + } + } catch (err) { + console.log('Err', err); + return { status: 'error', result: err }; + } +} diff --git a/apps/OpenSignServer/package-lock.json b/apps/OpenSignServer/package-lock.json index e57104d95..fac7ba41c 100644 --- a/apps/OpenSignServer/package-lock.json +++ b/apps/OpenSignServer/package-lock.json @@ -17,6 +17,7 @@ "express": "4.18.2", "express-sse": "^0.5.3", "form-data": "^4.0.0", + "generate-api-key": "^1.0.2", "jsonschema": "^1.4.1", "mailgun.js": "^9.3.0", "mongoose": "^7.2.1", @@ -2037,6 +2038,11 @@ "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" }, + "node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -2401,6 +2407,11 @@ "node": ">=4" } }, + "node_modules/chance": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz", + "integrity": "sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==" + }, "node_modules/charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", @@ -4373,6 +4384,20 @@ "lodash.padstart": "^4.1.0" } }, + "node_modules/generate-api-key": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/generate-api-key/-/generate-api-key-1.0.2.tgz", + "integrity": "sha512-4rPSpXyboIXfugOTN3/0Qaoqpzbk0sepzPS0XyxPh3UMuu+Trk+0JMyJ6mB/7FEgp7oZ1juqsRW+8wSYeKDbfA==", + "dependencies": { + "base-x": "^4.0.0", + "chance": "^1.1.8", + "rfc4648": "^1.5.2", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/generic-pool": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", @@ -8804,6 +8829,11 @@ "node": ">=0.10.0" } }, + "node_modules/rfc4648": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.3.tgz", + "integrity": "sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -9897,7 +9927,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } diff --git a/apps/OpenSignServer/package.json b/apps/OpenSignServer/package.json index 4725d28d5..350f10979 100644 --- a/apps/OpenSignServer/package.json +++ b/apps/OpenSignServer/package.json @@ -26,6 +26,7 @@ "express": "4.18.2", "express-sse": "^0.5.3", "form-data": "^4.0.0", + "generate-api-key": "^1.0.2", "jsonschema": "^1.4.1", "mailgun.js": "^9.3.0", "mongoose": "^7.2.1",