Compare commits

...
Author SHA1 Message Date
Andrew 8833018027 fix: password validation issue 2025-09-26 17:57:57 +00:00
prafull-opensignlabsandGitHub d1c405912b Merge pull request #1945 from OpenSignLabs/updates-17798985943
refactor: remove unnecessary code
2025-09-17 18:51:19 +05:30
prafull-opensignlabs 745aca1754 Merge pull request #1298 from nxglabs/sync-to-public_repo-17798472199
Merge pull request #1297 from nxglabs/staging
2025-09-17 13:19:46 +00:00
prafull-opensignlabsandGitHub 672eeea851 Merge pull request #1943 from OpenSignLabs/updates-17788011031
build(deps): build dependencies and dark mode ui
2025-09-17 11:21:02 +05:30
6 changed files with 87 additions and 109 deletions
+1 -1
View File
@@ -253,7 +253,7 @@ const AddAdmin = () => {
/[A-Z]/.test(newPassword) &&
/\d/.test(newPassword)
);
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>]/.test(newPassword));
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>?]/.test(newPassword));
};
const subscribeNewsletter = async () => {
try {
+26 -1
View File
@@ -4,6 +4,18 @@ import { Navigate } from "react-router";
import { useTranslation } from "react-i18next";
function ChangePassword() {
const [lengthValid, setLengthValid] = useState(false);
const [caseDigitValid, setCaseDigitValid] = useState(false);
const [specialCharValid, setSpecialCharValid] = useState(false);
const handlePasswordChange = (e) => {
const value = e.target.value;
setnewpassword(value);
setLengthValid(value.length >= 8);
setCaseDigitValid(
/[a-z]/.test(value) && /[A-Z]/.test(value) && /\d/.test(value)
);
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>?]/.test(value));
};
const { t } = useTranslation();
const [currentpassword, setCurrentPassword] = useState("");
const [newpassword, setnewpassword] = useState("");
@@ -84,13 +96,26 @@ function ChangePassword() {
type="password"
name="newpassword"
value={newpassword}
onChange={(e) => setnewpassword(e.target.value)}
onChange={handlePasswordChange}
className="op-input op-input-bordered op-input-sm text-xs w-full"
placeholder={t("new-password")}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
{newpassword.length > 0 && (
<div className="mt-1 text-[11px]">
<p className={lengthValid ? "text-green-600" : "text-red-600"}>
{lengthValid ? "✓" : "✗"} Password length 8
</p>
<p className={caseDigitValid ? "text-green-600" : "text-red-600"}>
{caseDigitValid ? "✓" : "✗"} Uppercase, lowercase, and number
</p>
<p className={specialCharValid ? "text-green-600" : "text-red-600"}>
{specialCharValid ? "✓" : "✗"} Special character
</p>
</div>
)}
</div>
<div>
<label htmlFor="newpassword" className="text-xs block ml-1">
@@ -13,6 +13,18 @@ import { useTranslation } from "react-i18next";
import Loader from "../primitives/Loader";
function ForgotPassword() {
const [lengthValid, setLengthValid] = useState(false);
const [caseDigitValid, setCaseDigitValid] = useState(false);
const [specialCharValid, setSpecialCharValid] = useState(false);
const handlePasswordChange = (event) => {
let value = event.target.value;
setState({ ...state, password: value });
setLengthValid(value.length >= 8);
setCaseDigitValid(
/[a-z]/.test(value) && /[A-Z]/.test(value) && /\d/.test(value)
);
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>?]/.test(value));
};
const { t } = useTranslation();
const dispatch = useDispatch();
const navigate = useNavigate();
@@ -124,6 +136,28 @@ function ForgotPassword() {
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold">
<input
type="password"
name="password"
className="op-input op-input-bordered op-input-sm w-full mt-2"
value={state.password}
onChange={handlePasswordChange}
placeholder="New password"
required
/>
{state.password.length > 0 && (
<div className="mt-1 text-[11px]">
<p className={lengthValid ? "text-green-600" : "text-red-600"}>
{lengthValid ? "✓" : "✗"} Password length 8
</p>
<p className={caseDigitValid ? "text-green-600" : "text-red-600"}>
{caseDigitValid ? "✓" : "✗"} Uppercase, lowercase, and number
</p>
<p className={specialCharValid ? "text-green-600" : "text-red-600"}>
{specialCharValid ? "✓" : "✗"} Special character
</p>
</div>
)}
<button type="submit" className="op-btn op-btn-primary">
{t("submit")}
</button>
+26 -1
View File
@@ -23,6 +23,18 @@ import { useTranslation } from "react-i18next";
import SelectLanguage from "../components/pdf/SelectLanguage";
function Login() {
const [lengthValid, setLengthValid] = useState(false);
const [caseDigitValid, setCaseDigitValid] = useState(false);
const [specialCharValid, setSpecialCharValid] = useState(false);
const handlePasswordChange = (event) => {
let value = event.target.value;
setState({ ...state, password: value });
setLengthValid(value.length >= 8);
setCaseDigitValid(
/[a-z]/.test(value) && /[A-Z]/.test(value) && /\d/.test(value)
);
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>?]/.test(value));
};
const appName =
"OpenSign™";
const { t, i18n } = useTranslation();
@@ -474,7 +486,7 @@ function Login() {
name="password"
value={state.password}
autoComplete="current-password"
onChange={handleChange}
onChange={handlePasswordChange}
onInvalid={(e) =>
e.target.setCustomValidity(
t("input-required")
@@ -495,6 +507,19 @@ function Login() {
</span>
</div>
<div className="relative mt-1">
{state.password.length > 0 && (
<div className="mt-1 text-[11px]">
<p className={lengthValid ? "text-green-600" : "text-red-600"}>
{lengthValid ? "✓" : "✗"} Password length 8
</p>
<p className={caseDigitValid ? "text-green-600" : "text-red-600"}>
{caseDigitValid ? "✓" : "✗"} Uppercase, lowercase, and number
</p>
<p className={specialCharValid ? "text-green-600" : "text-red-600"}>
{specialCharValid ? "✓" : "✗"} Special character
</p>
</div>
)}
<NavLink
to="/forgetpassword"
className="text-[13px] op-link op-link-primary underline-offset-1 focus:outline-none ml-1"
@@ -1,6 +1,5 @@
import axios from 'axios';
import { cloudServerUrl, generateId, serverAppId } from '../../../Utils.js';
import sendmailtoSupport from '../sendMailToSupport.js';
import { deleteContactsInBatch, deleteDataFiles, deleteInBatches } from './deleteFileUrl.js';
import { MAX_ATTEMPTS } from './deleteUtils.js';
const serverUrl = cloudServerUrl;
@@ -55,7 +54,6 @@ export async function deleteUser(userId, adminId) {
userDetails = { ...userDetails, UserId: userId };
if (!userResult) {
const errorMessage = 'User not found.';
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
const contractsUserId = userResult.id;
@@ -74,7 +72,6 @@ export async function deleteUser(userId, adminId) {
};
if (adminId && isAdmin) {
const errorMessage = 'An error occurred while deleting your account.';
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -86,7 +83,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed during contracts_Template cleanup:', err);
const errorMessage = 'Failed during contracts_Template cleanup:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -96,7 +92,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed during contactbook cleanup:', err);
const errorMessage = 'Failed during contactbook cleanup:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -117,7 +112,6 @@ export async function deleteUser(userId, adminId) {
console.error('Failed during contactbook current user cleanup:', err);
const errorMessage =
'Failed during contactbook current user cleanup: ' + (err?.message || err);
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -131,7 +125,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed to delete appToken entries:', err);
const errorMessage = 'Failed to delete appToken entries:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -141,7 +134,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed during partners_DataFiles cleanup:', err);
const errorMessage = 'Failed during partners_DataFiles cleanup:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -157,7 +149,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed to delete contracts_Organizations entry:', err);
const errorMessage = 'Failed to delete contracts_Organizations entry:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
// STEP 7: Delete each entry in contracts_Teams by objectId from teamIds
@@ -171,7 +162,6 @@ export async function deleteUser(userId, adminId) {
} catch (teamErr) {
console.error(`Failed to delete team with ID ${team.id}:`, teamErr);
const errorMessage = `Failed to delete team with ID ${team.id}` + teamErr?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
}
@@ -179,7 +169,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed during contracts_Teams deletion loop:', err);
const errorMessage = 'Failed during contracts_Teams deletion loop:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -195,7 +184,6 @@ export async function deleteUser(userId, adminId) {
const msg = `Failed during partners_Tenant ${'cleanup:'} `;
console.error(msg, err);
const errorMessage = msg + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -215,7 +203,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed during partners_TenantCredits cleanup:', err);
const errorMessage = 'Failed during partners_TenantCredits cleanup:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
}
@@ -229,7 +216,6 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed during contracts_Signature cleanup:', err);
const errorMessage = 'Failed during contracts_Signature cleanup:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
@@ -239,14 +225,12 @@ export async function deleteUser(userId, adminId) {
} catch (err) {
console.error('Failed to delete contracts_Users entry:', err);
const errorMessage = 'Failed to delete contracts_Users entry:' + err?.message;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
return { code: 200, message: 'User and all associated data deleted successfully.' };
} catch (error) {
console.error('User deletion process failed:', error);
const errorMessage = `User deletion failed: ${error.message || error}`;
sendmailtoSupport(userDetails, errorMessage);
return { code: 400, message: errorMessage };
}
}
@@ -272,8 +256,6 @@ export const deleteUserPost = async (req, res) => {
const user = await userQuery.first({ useMasterKey: true });
if (!user) {
const errorMessage = 'User not found.';
// sendmailtoSupport(userDetails, errorMessage);
// return res.status(404).send(errorMessage);
return res.send(errorMessage);
}
const extUserQuery = new Parse.Query('contracts_Users');
@@ -321,8 +303,6 @@ export const deleteUserPost = async (req, res) => {
await extUser.save(null, { useMasterKey: true });
} catch (err) {
console.log('err while validating password: ', err?.response?.data || err);
// sendmailtoSupport(userDetails, errorMessage);
// return res.status(401).send(errorMessage);
}
const response = await deleteUser(userId);
@@ -332,7 +312,6 @@ export const deleteUserPost = async (req, res) => {
} catch (error) {
console.error('Account deletion error:', error);
const errorMessage = error?.message || 'An error occurred while deleting your account.';
sendmailtoSupport(userDetails, errorMessage);
return res.status(500).send(errorMessage);
}
};
@@ -371,7 +350,6 @@ export const deleteUserByAdmin = async (req, res) => {
const user = await userQuery.first({ useMasterKey: true });
if (!user) {
const errorMessage = 'User not found.';
sendmailtoSupport(userDetails, errorMessage);
return res.status(400).json({ message: errorMessage });
}
const response = await deleteUser(userId, adminId);
@@ -385,7 +363,6 @@ export const deleteUserByAdmin = async (req, res) => {
error?.message ||
'An error occurred while deleting your account.';
console.error(`Account deletion error:`, errorMessage);
sendmailtoSupport(userDetails, errorMessage);
return res.status(code).json({ message: errorMessage });
}
};
@@ -1,83 +0,0 @@
import { appName, smtpenable } from '../../Utils.js';
export default async function sendmailtoSupport(userDetails, errorMessage) {
const mailsender = smtpenable ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER;
// Render a simple HTML form. In production, consider using a templating engine.
try {
await Parse.Cloud.sendEmail({
sender: appName + ' <' + mailsender + '>',
recipient: 'support@opensignlabs.com',
subject: `Error while deleting account ${appName}`,
text: `Error while deleting account ${appName}`,
html: `<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f8f9fa;
margin: 0;
padding: 40px;
color: #333;
}
.container {
max-width: 600px;
margin: auto;
background: #ffffff;
border: 1px solid #dee2e6;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0,0,0,0.05);
padding: 30px;
}
h1 {
color: #dc3545;
font-size: 24px;
margin-bottom: 20px;
text-align: center;
}
h2 {
font-size: 20px;
color: #495057;
margin-top: 30px;
border-bottom: 1px solid #dee2e6;
padding-bottom: 10px;
}
.details p {
margin: 10px 0;
line-height: 1.6;
}
.label {
font-weight: bold;
color: #212529;
}
.value {
color: #495057;
}
</style>
</head>
<body>
<div class="container">
<h1>Error: ${errorMessage}</h1>
<h2>User Details</h2>
<div class="details">
<p><span class="label">UserRole:</span> <span class="value">${userDetails?.UserRole}</span></p>
<p><span class="label">Name:</span> <span class="value">${userDetails?.Name}</span></p>
<p><span class="label">Email:</span> <span class="value">${userDetails?.Email}</span></p>
<p><span class="label">UserId:</span> <span class="value">${userDetails?.UserId}</span></p>
<p><span class="label">ExtUserId:</span> <span class="value">${userDetails?.objectId}</span></p>
<p><span class="label">TenantId:</span> <span class="value">${userDetails?.TenantId}</span></p>
</div>
</div>
</body>
</html>`,
});
} catch (err) {
console.log('err while sending mail to support', err);
}
}