mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-17 21:25:54 +02:00
Feat: create SSO user account on platform
This commit is contained in:
@@ -10,7 +10,11 @@ const Menu = ({ item, isOpen, closeSidebar }) => {
|
||||
? `/${item.pageType}/${item.objectId}`
|
||||
: `/${item.objectId}`
|
||||
}
|
||||
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 cursor-pointer focus:text-[#0056b3] focus:bg-[#eef1f5]"
|
||||
className={({ isActive }) =>
|
||||
`${
|
||||
isActive ? "text-[#0056b3] bg-[#eef1f5]" : ""
|
||||
} mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 cursor-pointer`
|
||||
}
|
||||
onClick={closeSidebar}
|
||||
tabIndex={isOpen ? 0 : -1}
|
||||
role="menuitem"
|
||||
|
||||
@@ -12,8 +12,12 @@ export const isMobile = window.innerWidth < 767;
|
||||
export const textInputWidget = "text input";
|
||||
export const textWidget = "text";
|
||||
export const radioButtonWidget = "radio button";
|
||||
export const openInNewTab = (url) => {
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
export const openInNewTab = (url, target) => {
|
||||
if (target) {
|
||||
window.open(url, target, "noopener,noreferrer");
|
||||
} else {
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
}
|
||||
};
|
||||
|
||||
export async function fetchSubscription(
|
||||
|
||||
@@ -1041,10 +1041,15 @@ function Login() {
|
||||
localStorage.setItem("baseUrl", baseUrl);
|
||||
localStorage.setItem("parseAppId", appid);
|
||||
};
|
||||
|
||||
// `handleSignInWithSSO` is trigger when user click sign in with sso and open sso authorize endpoint
|
||||
const handleSignInWithSSO = () => {
|
||||
if (state?.email) {
|
||||
const encodedEmail = encodeURIComponent(state.email);
|
||||
const clientUrl = window.location.origin;
|
||||
openInNewTab(
|
||||
`https://osl-jacksonv2.vercel.app/api/oauth/authorize?response_type=code&provider=saml&tenant=Okta-dev-nxglabs-in&product=OpenSign&redirect_uri=http://localhost:3000/sso&state=${state.email}`
|
||||
`https://osl-jacksonv2.vercel.app/api/oauth/authorize?response_type=code&provider=saml&tenant=Okta-dev-nxglabs-in&product=OpenSign&redirect_uri=${clientUrl}/sso&state=${encodedEmail}`,
|
||||
"_self"
|
||||
);
|
||||
} else {
|
||||
alert("Please provide email.");
|
||||
|
||||
@@ -1,64 +1,143 @@
|
||||
// import axios from "axios";
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import Parse from "parse";
|
||||
import axios from "axios";
|
||||
import { appInfo } from "../constant/appinfo";
|
||||
import { isEnableSubscription } from "../constant/const";
|
||||
import {
|
||||
isEnableSubscription,
|
||||
modalCancelBtnColor,
|
||||
modalSubmitBtnColor
|
||||
} from "../constant/const";
|
||||
import { fetchSubscription } from "../constant/Utils";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||
import ModalUi from "../primitives/ModalUi";
|
||||
|
||||
const SSOVerify = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const [isModal, setIsModal] = useState(false);
|
||||
const [ssoErrMsg, setSsoErrMsg] = useState("Verifying SSO...");
|
||||
const [isLoader, setIsLoader] = useState(false);
|
||||
const [userDetails, setUserDetails] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
Destination: "",
|
||||
Company: ""
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
getAccesstoken();
|
||||
linkUserWithSSO();
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
const getAccesstoken = async () => {
|
||||
|
||||
// `linkUserWithSSO` is used to sign in or sign up a user using an SSO code and check if the user is present in the extended class
|
||||
const linkUserWithSSO = async () => {
|
||||
const param = new URLSearchParams(location.search);
|
||||
const code = param?.get("code");
|
||||
const state = param?.get("state");
|
||||
// console.log("code ", code);
|
||||
try {
|
||||
// The `ssosign` cloud function is used to sign in or sign up a user
|
||||
const ssosign = await Parse.Cloud.run("ssosign", {
|
||||
code: code,
|
||||
email: state
|
||||
});
|
||||
localStorage.setItem("accesstoken", ssosign.sessiontoken);
|
||||
// `checkExtUser` checks if the user is present in the extended class `contracts_Users` and if not, initiates the new user flow
|
||||
await checkExtUser(ssosign);
|
||||
// console.log("ssores ", ssosign);
|
||||
} catch (err) {
|
||||
console.log("err", err);
|
||||
setSsoErrMsg(err.message);
|
||||
console.log("err", err.message);
|
||||
}
|
||||
};
|
||||
const checkExtUser = async (ssosign) => {
|
||||
// const extUser = new Parse.Query("contracts_Users");
|
||||
// extUser.equalTo("Email", details.Gmail);
|
||||
// const extRes = await extUser.first();
|
||||
const params = { email: ssosign?.email };
|
||||
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||
// console.log("extRes ", extRes);
|
||||
if (extRes) {
|
||||
if (ssosign && ssosign.sessiontoken) {
|
||||
const LocalUserDetails = {
|
||||
name: extRes.Name,
|
||||
email: extRes.email,
|
||||
phone: extRes?.get("Phone") || "",
|
||||
company: extRes.get("Company")
|
||||
};
|
||||
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
|
||||
thirdpartyLoginfn(ssosign.sessiontoken);
|
||||
try {
|
||||
// `isextenduser` checks if the current user is present in the extended class
|
||||
const extRes = await Parse.Cloud.run("isextenduser", params);
|
||||
if (extRes?.isUserExist) {
|
||||
// `getUserDetails` retrieves the current user's details from the extended class
|
||||
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||
if (ssosign && ssosign.sessiontoken) {
|
||||
const LocalUserDetails = {
|
||||
name: extRes.Name,
|
||||
email: extRes.email,
|
||||
phone: extRes?.get("Phone") || "",
|
||||
company: extRes.get("Company")
|
||||
};
|
||||
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
|
||||
thirdpartyLoginfn(ssosign.sessiontoken);
|
||||
}
|
||||
} else {
|
||||
setIsModal(true);
|
||||
setUserDetails((prev) => ({
|
||||
...prev,
|
||||
name: ssosign.name,
|
||||
email: ssosign.email,
|
||||
phone: ssosign?.phone || ""
|
||||
}));
|
||||
}
|
||||
return { msg: "exist" };
|
||||
} else {
|
||||
// setIsModal(true);
|
||||
// setThirdpartyLoader(false);
|
||||
console.log("not exist");
|
||||
return { msg: "notexist" };
|
||||
} catch (err) {
|
||||
console.log("Err in isextenduser or getuserdetails cloud function", err);
|
||||
alert(err.message);
|
||||
}
|
||||
};
|
||||
// `handleSubmitbtn` is used to create a user in the extended class
|
||||
const handleSubmitbtn = async (e) => {
|
||||
e.preventDefault();
|
||||
setIsLoader(true);
|
||||
let phone;
|
||||
if (userDetails?.phone) {
|
||||
phone = validateInput(userDetails?.phone);
|
||||
} else {
|
||||
phone = true;
|
||||
}
|
||||
if (userDetails.Destination && userDetails.Company && phone) {
|
||||
const payload = { sessionToken: localStorage.getItem("accesstoken") };
|
||||
if (payload && payload.sessionToken) {
|
||||
const params = {
|
||||
userDetails: {
|
||||
name: userDetails.name,
|
||||
email: userDetails.email,
|
||||
phone: userDetails?.phone || "",
|
||||
role: "contracts_User",
|
||||
company: userDetails.Company,
|
||||
jobTitle: userDetails.Destination
|
||||
}
|
||||
};
|
||||
try {
|
||||
const userSignUp = await Parse.Cloud.run("usersignup", params);
|
||||
if (userSignUp && userSignUp.sessionToken) {
|
||||
const LocalUserDetails = params.userDetails;
|
||||
localStorage.setItem(
|
||||
"userDetails",
|
||||
JSON.stringify(LocalUserDetails)
|
||||
);
|
||||
await thirdpartyLoginfn(userSignUp.sessionToken);
|
||||
setIsLoader(false);
|
||||
} else {
|
||||
alert(userSignUp.message);
|
||||
setIsLoader(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("error in usersignup", err);
|
||||
localStorage.removeItem("accesstoken");
|
||||
alert("something went wrong, please try again later.");
|
||||
setIsLoader(false);
|
||||
}
|
||||
} else {
|
||||
localStorage.removeItem("accesstoken");
|
||||
alert("Internal server error !");
|
||||
setIsLoader(false);
|
||||
}
|
||||
} else {
|
||||
alert("Please fill required details correctly.");
|
||||
setIsLoader(false);
|
||||
}
|
||||
};
|
||||
// `thirdpartyLoginfn` is used to save necessary parameters locally for the logged-in user
|
||||
const thirdpartyLoginfn = async (sessionToken) => {
|
||||
const baseUrl = localStorage.getItem("baseUrl");
|
||||
const parseAppId = localStorage.getItem("parseAppId");
|
||||
@@ -67,7 +146,6 @@ const SSOVerify = () => {
|
||||
if (validUser) {
|
||||
localStorage.setItem("accesstoken", sessionToken);
|
||||
const _user = JSON.parse(JSON.stringify(validUser));
|
||||
// console.log("_user ", _user);
|
||||
localStorage.setItem("UserInformation", JSON.stringify(_user));
|
||||
if (_user.ProfilePic) {
|
||||
localStorage.setItem("profileImg", _user.ProfilePic);
|
||||
@@ -77,132 +155,252 @@ const SSOVerify = () => {
|
||||
// Check extended class user role and tenentId
|
||||
try {
|
||||
let userRoles = [];
|
||||
if (appInfo.settings) {
|
||||
const userSettings = appInfo.settings;
|
||||
|
||||
//Get Current user roles
|
||||
let url = `${baseUrl}functions/UserGroups`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": parseAppId,
|
||||
sessionToken: _user.sessionToken
|
||||
};
|
||||
const body = { appname: appInfo.appname };
|
||||
const UserGroupsRes = await axios.post(url, JSON.stringify(body), {
|
||||
headers: headers
|
||||
});
|
||||
userRoles = (UserGroupsRes.data && UserGroupsRes.data.result) || [];
|
||||
if (userRoles) {
|
||||
let _currentRole = "";
|
||||
// const excludeRoles = ["contracts_Guest", `contracts_appeditor`];
|
||||
// const filteredRole = userRoles.filter(
|
||||
// (x) => !excludeRoles.includes(x)
|
||||
// );
|
||||
// if (filteredRole?.length > 1) {
|
||||
// _currentRole = userRoles.filter((x) => x === "contracts_User");
|
||||
// } else {
|
||||
// _currentRole = rolesfiltered[0];
|
||||
// }
|
||||
_currentRole = userRoles?.find((x) => x === "contracts_User");
|
||||
if (_currentRole) {
|
||||
const roleSetting = userSettings?.find(
|
||||
(setting) => setting.role === _currentRole
|
||||
);
|
||||
const redirectUrl =
|
||||
location?.state?.from ||
|
||||
`/${roleSetting.pageType}/${roleSetting.pageId}`;
|
||||
const _role = _currentRole.replace(`${appInfo.appname}_`, "");
|
||||
localStorage.setItem("_user_role", _role);
|
||||
// Get TenentID from Extendend Class
|
||||
localStorage.setItem(
|
||||
"extended_class",
|
||||
roleSetting.extended_class
|
||||
);
|
||||
try {
|
||||
const extUser = await Parse.Cloud.run("getUserDetails", {
|
||||
email: _user.email
|
||||
});
|
||||
if (extUser) {
|
||||
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||
localStorage.setItem("userEmail", _extUser.Email);
|
||||
localStorage.setItem("username", _extUser.Name);
|
||||
localStorage.setItem("scriptId", true);
|
||||
// console.log("_extUser", _extUser);
|
||||
let tenentInfo = [];
|
||||
const results = [extUser];
|
||||
if (results) {
|
||||
let extendedInfo_stringify = JSON.stringify(results);
|
||||
localStorage.setItem(
|
||||
"Extand_Class",
|
||||
extendedInfo_stringify
|
||||
);
|
||||
if (_extUser.TenantId) {
|
||||
const obj = {
|
||||
tenentId: _extUser.TenantId.objectId,
|
||||
tenentName: _extUser.TenantId.TenantName || ""
|
||||
};
|
||||
localStorage.setItem("TenantId", obj.tenentId);
|
||||
tenentInfo.push(obj);
|
||||
dispatch(showTenant(obj.tenentName || ""));
|
||||
localStorage.setItem(
|
||||
"TenantName",
|
||||
obj.tenentName || ""
|
||||
);
|
||||
}
|
||||
localStorage.setItem("PageLanding", roleSetting.pageId);
|
||||
localStorage.setItem("defaultmenuid", roleSetting.menuId);
|
||||
localStorage.setItem("pageType", roleSetting.pageType);
|
||||
if (isEnableSubscription) {
|
||||
const res = await fetchSubscription();
|
||||
const plan = res.plan;
|
||||
const billingDate = res.billingDate;
|
||||
if (plan === "freeplan") {
|
||||
const userSettings = appInfo.settings;
|
||||
//Get Current user roles
|
||||
const url = `${baseUrl}functions/UserGroups`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": parseAppId,
|
||||
sessionToken: _user.sessionToken
|
||||
};
|
||||
const body = { appname: appInfo.appname };
|
||||
const UserGroupsRes = await axios.post(url, JSON.stringify(body), {
|
||||
headers: headers
|
||||
});
|
||||
userRoles = (UserGroupsRes.data && UserGroupsRes.data.result) || [];
|
||||
if (userRoles) {
|
||||
let _currentRole = "";
|
||||
const excludeRoles = ["contracts_Guest", `contracts_appeditor`];
|
||||
const filteredRole = userRoles.filter(
|
||||
(x) => !excludeRoles.includes(x)
|
||||
);
|
||||
if (filteredRole?.length > 1) {
|
||||
console.log("user has two roles");
|
||||
// _currentRole = filteredRole.filter((x) => x === "contracts_User");
|
||||
} else {
|
||||
_currentRole = filteredRole?.[0] || "";
|
||||
}
|
||||
if (_currentRole) {
|
||||
const roleSetting = userSettings?.find(
|
||||
(setting) => setting.role === _currentRole
|
||||
);
|
||||
const redirectUrl =
|
||||
location?.state?.from ||
|
||||
`/${roleSetting.pageType}/${roleSetting.pageId}`;
|
||||
const _role = _currentRole.replace(`${appInfo.appname}_`, "");
|
||||
localStorage.setItem("_user_role", _role);
|
||||
// Get TenentID from Extendend Class
|
||||
localStorage.setItem(
|
||||
"extended_class",
|
||||
roleSetting.extended_class
|
||||
);
|
||||
try {
|
||||
const extUser = await Parse.Cloud.run("getUserDetails", {
|
||||
email: _user.email
|
||||
});
|
||||
if (extUser) {
|
||||
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||
localStorage.setItem("userEmail", _extUser.Email);
|
||||
localStorage.setItem("username", _extUser.Name);
|
||||
localStorage.setItem("scriptId", true);
|
||||
let tenentInfo = [];
|
||||
const results = [extUser];
|
||||
if (results) {
|
||||
let extendedInfo_stringify = JSON.stringify(results);
|
||||
localStorage.setItem(
|
||||
"Extand_Class",
|
||||
extendedInfo_stringify
|
||||
);
|
||||
if (_extUser.TenantId) {
|
||||
const obj = {
|
||||
tenentId: _extUser.TenantId.objectId,
|
||||
tenentName: _extUser.TenantId.TenantName || ""
|
||||
};
|
||||
localStorage.setItem("TenantId", obj.tenentId);
|
||||
tenentInfo.push(obj);
|
||||
dispatch(showTenant(obj.tenentName || ""));
|
||||
localStorage.setItem("TenantName", obj.tenentName || "");
|
||||
}
|
||||
localStorage.setItem("PageLanding", roleSetting.pageId);
|
||||
localStorage.setItem("defaultmenuid", roleSetting.menuId);
|
||||
localStorage.setItem("pageType", roleSetting.pageType);
|
||||
if (isEnableSubscription) {
|
||||
const res = await fetchSubscription();
|
||||
const plan = res.plan;
|
||||
const billingDate = res.billingDate;
|
||||
if (plan === "freeplan") {
|
||||
navigate(redirectUrl);
|
||||
} else if (billingDate) {
|
||||
if (new Date(billingDate) > new Date()) {
|
||||
localStorage.removeItem("userDetails");
|
||||
navigate(redirectUrl);
|
||||
} else if (billingDate) {
|
||||
if (new Date(billingDate) > new Date()) {
|
||||
localStorage.removeItem("userDetails");
|
||||
navigate(redirectUrl);
|
||||
} else {
|
||||
navigate(`/subscription`, {
|
||||
replace: true
|
||||
});
|
||||
}
|
||||
} else {
|
||||
navigate(`/subscription`, {
|
||||
replace: true
|
||||
});
|
||||
}
|
||||
} else {
|
||||
navigate(redirectUrl);
|
||||
navigate(`/subscription`, {
|
||||
replace: true
|
||||
});
|
||||
}
|
||||
} else {
|
||||
navigate(redirectUrl);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// const payload = {
|
||||
// sessionToken: sessionToken
|
||||
// };
|
||||
// setThirdpartyLoader(false);
|
||||
// handleSubmitbtn(payload);
|
||||
|
||||
alert("ext user not exist.");
|
||||
console.log("err in get extUser", err);
|
||||
}
|
||||
} else {
|
||||
alert("contracts_User role not exist");
|
||||
} catch (err) {
|
||||
alert("user not exist.");
|
||||
console.log("err in get extUser", err);
|
||||
}
|
||||
} else {
|
||||
alert("contracts_User role not exist");
|
||||
alert("Role does not exists.");
|
||||
}
|
||||
} else {
|
||||
alert("Role does not exists.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in usergroups", err);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Err in me call", err);
|
||||
console.log("Err in become method", err);
|
||||
}
|
||||
};
|
||||
return <div>Verifying SSO....</div>;
|
||||
// `handleCloseModal` is triggered when the user wants to close the new user flow modal
|
||||
const handleCloseModal = () => {
|
||||
setIsModal(false);
|
||||
if (Parse?.User?.current()) {
|
||||
Parse.User.logOut();
|
||||
}
|
||||
};
|
||||
|
||||
// `validateInput` is used to verify the phone pattern
|
||||
function validateInput(input) {
|
||||
if (input) {
|
||||
const pattern = /^(?!.*\+.*\+)[\d+-]*$/;
|
||||
return pattern.test(input);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="w-full h-screen flex justify-center items-center text-sm md:text-xl ">
|
||||
{ssoErrMsg}
|
||||
</div>
|
||||
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
|
||||
<div className="relative">
|
||||
{isLoader && (
|
||||
<div className="absolute w-full h-full bg-black bg-opacity-25 flex justify-center items-center">
|
||||
<div
|
||||
style={{
|
||||
fontSize: "45px",
|
||||
color: "#3dd3e0"
|
||||
}}
|
||||
className="loader-37"
|
||||
></div>
|
||||
</div>
|
||||
)}
|
||||
<form className="px-4 py-3" onSubmit={handleSubmitbtn}>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="Company"
|
||||
style={{ display: "flex" }}
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
Phone <span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||
</label>
|
||||
<input
|
||||
type="tel"
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
id="Phone"
|
||||
value={userDetails.phone}
|
||||
onChange={(e) =>
|
||||
setUserDetails({
|
||||
...userDetails,
|
||||
phone: e.target.value
|
||||
})
|
||||
}
|
||||
disabled={isLoader}
|
||||
required
|
||||
/>
|
||||
<p className="text-[10px] text-[red] ml-2">
|
||||
{!validateInput(userDetails.phone) && "Invalid phone value"}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="Company"
|
||||
style={{ display: "flex" }}
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
Company <span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
id="Company"
|
||||
value={userDetails.Company}
|
||||
onChange={(e) =>
|
||||
setUserDetails({
|
||||
...userDetails,
|
||||
Company: e.target.value
|
||||
})
|
||||
}
|
||||
disabled={isLoader}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="JobTitle"
|
||||
style={{ display: "flex" }}
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
Job Title
|
||||
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
id="JobTitle"
|
||||
value={userDetails.Destination}
|
||||
onChange={(e) =>
|
||||
setUserDetails({
|
||||
...userDetails,
|
||||
Destination: e.target.value
|
||||
})
|
||||
}
|
||||
disabled={isLoader}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<button
|
||||
type="submit"
|
||||
className="px-3 py-1.5 text-white rounded shadow-md text-center focus:outline-none "
|
||||
style={{
|
||||
marginRight: 10,
|
||||
backgroundColor: modalSubmitBtnColor
|
||||
}}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none"
|
||||
onClick={handleCloseModal}
|
||||
style={{ width: 75, backgroundColor: modalCancelBtnColor }}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</ModalUi>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SSOVerify;
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import axios from 'axios';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
const ssoApiUrl = process.env.SSO_API_URL || 'https://osl-jacksonv2.vercel.app/api';
|
||||
export const SSOAuth = {
|
||||
// Returns a promise that fulfills if this user mail is valid.
|
||||
validateAuthData: async authData => {
|
||||
try {
|
||||
const response = await axios.get('https://osl-jacksonv2.vercel.app/api/oauth/userinfo', {
|
||||
const response = await axios.get(ssoApiUrl + '/oauth/userinfo', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${authData.access_token}`,
|
||||
},
|
||||
});
|
||||
// console.log('response.data.id ', response.data.email);
|
||||
// console.log('authData.id', authData.id);
|
||||
if (response.data && response.data.id && response.data.email === authData.id) {
|
||||
return;
|
||||
}
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'SSO auth is invalid for this user.');
|
||||
} catch (error) {
|
||||
console.log('error in sso adapter', error?.response);
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'SSO auth is invalid for this user.');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -43,6 +43,7 @@ import CreatePublicTemplate from './parsefunction/CreatePublicTemplate.js';
|
||||
import GetPublicUserName from './parsefunction/GetPublicUserName.js';
|
||||
import GetPublicTemplate from './parsefunction/GetPublicTemplate.js';
|
||||
import ssoSignin from './parsefunction/ssoSignin.js';
|
||||
import isextenduser from './parsefunction/isextenduser.js';
|
||||
|
||||
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
|
||||
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
||||
@@ -96,3 +97,4 @@ Parse.Cloud.define('createpublictemplate', CreatePublicTemplate);
|
||||
Parse.Cloud.define('getpublicusername', GetPublicUserName);
|
||||
Parse.Cloud.define('getpublictemplate', GetPublicTemplate);
|
||||
Parse.Cloud.define('ssosign', ssoSignin);
|
||||
Parse.Cloud.define('isextenduser', isextenduser);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Checks if a user exists in the extended class 'contracts_Users' based on the provided email.
|
||||
* @param email - The request contains parameters, such as the user's email.
|
||||
* @returns {Object} - Returns an object indicating whether the user exists.
|
||||
*/
|
||||
export default async function isextenduser(request) {
|
||||
try {
|
||||
// Query the 'contracts_Users' class in the database based on the provided email
|
||||
const userQuery = new Parse.Query('contracts_Users');
|
||||
userQuery.equalTo('Email', request.params.email);
|
||||
|
||||
// Execute the query
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
|
||||
// Check if a user was found
|
||||
if (res) {
|
||||
// If user exists, return object with 'isUserExist' set to true
|
||||
return { isUserExist: true };
|
||||
} else {
|
||||
// If user does not exist, return object with 'isUserExist' set to false
|
||||
return { isUserExist: false };
|
||||
}
|
||||
} catch (err) {
|
||||
// Handle errors
|
||||
console.log('Error in userexist', err);
|
||||
const code = err?.code || 400;
|
||||
const message = err?.message || 'Something went wrong.';
|
||||
throw new Parse.Error(code, message);
|
||||
}
|
||||
}
|
||||
@@ -3,39 +3,37 @@ import axios from 'axios';
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const APPID = process.env.APP_ID;
|
||||
const masterKEY = process.env.MASTER_KEY;
|
||||
|
||||
const clientUrl = process.env.PUBLIC_URL;
|
||||
const ssoApiUrl = process.env.SSO_API_URL || 'https://osl-jacksonv2.vercel.app/api';
|
||||
/**
|
||||
* ssoSign is function which is used to sign up/sign in with SSO
|
||||
* @param code It is code return by jackson using authorize endpoint
|
||||
* @param email It is user's email with user sign in/sign up
|
||||
* @returns if success {email, message, sessiontoken} else on reject {message}
|
||||
* @returns if success {email, name, phone message, sessiontoken} else on reject error {code, message}
|
||||
*/
|
||||
|
||||
export default async function ssoSignin(request) {
|
||||
const code = request.params.code;
|
||||
const userEmail = request.params.email;
|
||||
|
||||
// console.log('code ', code);
|
||||
try {
|
||||
const headers = { 'content-type': 'application/x-www-form-urlencoded' };
|
||||
const axiosRes = await axios.post(
|
||||
'https://osl-jacksonv2.vercel.app/api/oauth/token',
|
||||
ssoApiUrl + '/oauth/token',
|
||||
{
|
||||
grant_type: 'authorization_code',
|
||||
client_id: 'dummy',
|
||||
tenant: 'Okta-dev-nxglabs-in',
|
||||
product: 'OpenSign',
|
||||
client_secret: 'dummy',
|
||||
redirect_uri: 'http://localhost:3000/sso',
|
||||
redirect_uri: clientUrl + '/sso',
|
||||
code: code,
|
||||
},
|
||||
{ headers: headers }
|
||||
);
|
||||
const ssoAccessToken = axiosRes.data && axiosRes.data.access_token;
|
||||
// console.log('ssoAccessToken ', ssoAccessToken);
|
||||
const authData = { sso: { id: userEmail, access_token: ssoAccessToken } };
|
||||
const userQuery = new Parse.Query(Parse.User);
|
||||
userQuery.equalTo('email', userEmail);
|
||||
userQuery.equalTo('username', userEmail);
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
try {
|
||||
@@ -51,17 +49,31 @@ export default async function ssoSignin(request) {
|
||||
);
|
||||
|
||||
if (SignIn.data) {
|
||||
const response = await axios.get(ssoApiUrl + '/oauth/userinfo', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${ssoAccessToken}`,
|
||||
},
|
||||
});
|
||||
const sessiontoken = SignIn.data.sessionToken;
|
||||
// console.log('sso sessiontoken', sessiontoken);
|
||||
return {
|
||||
const payload = {
|
||||
email: userEmail,
|
||||
name: response.data?.firstName + ' ' + response.data?.lastName,
|
||||
phone: response?.data?.phone || '',
|
||||
message: 'User Sign In',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err in user sso sign in', err);
|
||||
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Internal server error.');
|
||||
const errCode = err?.response?.data?.code || err?.response?.status || err?.code || 400;
|
||||
const message =
|
||||
err?.response?.data?.error ||
|
||||
err?.response?.data ||
|
||||
err?.message ||
|
||||
'Internal server error.';
|
||||
console.log('err in user sso sign in', errCode, message);
|
||||
throw new Parse.Error(errCode, message);
|
||||
}
|
||||
} else {
|
||||
// console.log("in sign up condition");
|
||||
@@ -79,7 +91,7 @@ export default async function ssoSignin(request) {
|
||||
username: response.data.email,
|
||||
email: response.data.email,
|
||||
phone: response.data?.phone,
|
||||
name: response.data?.firstName + response.data?.lastName,
|
||||
name: response.data?.firstName + ' ' + response.data?.lastName,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
@@ -88,21 +100,26 @@ export default async function ssoSignin(request) {
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// console.log("SignUp", SignUp);
|
||||
|
||||
if (SignUp.data) {
|
||||
const sessiontoken = SignUp.data.sessionToken;
|
||||
const payload = {
|
||||
email: userEmail,
|
||||
name: SignUp?.data?.name,
|
||||
phone: SignUp?.data?.phone || '',
|
||||
message: 'User Sign Up',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err in user sso sign up', err);
|
||||
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Internal server error.');
|
||||
const errCode = err?.response?.data?.code || err?.response?.status || err?.code || 400;
|
||||
const message =
|
||||
err?.response?.data?.error ||
|
||||
err?.response?.data ||
|
||||
err?.message ||
|
||||
'Internal server error.';
|
||||
console.log('err in user sso sign up', errCode, message);
|
||||
throw new Parse.Error(errCode, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,9 @@ export default async function usersignup(request) {
|
||||
newObj.set('JobTitle', userDetails.jobTitle);
|
||||
}
|
||||
const extRes = await newObj.save(null, { useMasterKey: true });
|
||||
await saveSubscription(extRes.id, user.id, tenantRes.id, subscription);
|
||||
if (subscription) {
|
||||
await saveSubscription(extRes.id, user.id, tenantRes.id, subscription);
|
||||
}
|
||||
return { message: 'User sign up', sessionToken: user.sessionToken };
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user