mirror of
https://github.com/OneUptime/oneuptime
synced 2024-11-21 14:49:07 +00:00
fix mail service
This commit is contained in:
parent
addfc9d69c
commit
a0fc136870
@ -36,72 +36,88 @@ const RegisterPage: FunctionComponent = () => {
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<h5 className="mb-0">
|
||||
Reset Password.
|
||||
Reset Password.
|
||||
</h5>
|
||||
{!isSuccess && <p className="text-muted mt-2 mb-0">
|
||||
Please enter your new password and we will have it updated.{' '}
|
||||
</p>}
|
||||
{!isSuccess && (
|
||||
<p className="text-muted mt-2 mb-0">
|
||||
Please enter your new
|
||||
password and we will have it
|
||||
updated.{' '}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{isSuccess && <p className="text-muted mt-2 mb-0">
|
||||
Your password has been updated. Please log in.
|
||||
</p>}
|
||||
|
||||
{isSuccess && (
|
||||
<p className="text-muted mt-2 mb-0">
|
||||
Your password has been
|
||||
updated. Please log in.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!isSuccess && <ModelForm<User>
|
||||
modelType={User}
|
||||
id="register-form"
|
||||
onBeforeCreate={(item: User) => {
|
||||
item.resetPasswordToken = Navigation.getLastParam()?.toString().replace("/", "").toString() ||''
|
||||
return item;
|
||||
}}
|
||||
showAsColumns={1}
|
||||
maxPrimaryButtonWidth={true}
|
||||
initialValues={{
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
}}
|
||||
fields={[
|
||||
|
||||
{
|
||||
field: {
|
||||
password: true,
|
||||
{!isSuccess && (
|
||||
<ModelForm<User>
|
||||
modelType={User}
|
||||
id="register-form"
|
||||
onBeforeCreate={(
|
||||
item: User
|
||||
) => {
|
||||
item.resetPasswordToken =
|
||||
Navigation.getLastParam()
|
||||
?.toString()
|
||||
.replace('/', '')
|
||||
.toString() || '';
|
||||
return item;
|
||||
}}
|
||||
showAsColumns={1}
|
||||
maxPrimaryButtonWidth={true}
|
||||
initialValues={{
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
}}
|
||||
fields={[
|
||||
{
|
||||
field: {
|
||||
password: true,
|
||||
},
|
||||
fieldType:
|
||||
FormFieldSchemaType.Password,
|
||||
validation: {
|
||||
minLength: 6,
|
||||
},
|
||||
placeholder:
|
||||
'New Password',
|
||||
title: 'New Password',
|
||||
required: true,
|
||||
},
|
||||
fieldType:
|
||||
FormFieldSchemaType.Password,
|
||||
validation: {
|
||||
minLength: 6,
|
||||
{
|
||||
field: {
|
||||
password: true,
|
||||
},
|
||||
validation: {
|
||||
minLength: 6,
|
||||
toMatchField:
|
||||
'password',
|
||||
},
|
||||
fieldType:
|
||||
FormFieldSchemaType.Password,
|
||||
placeholder:
|
||||
'Confirm Password',
|
||||
title: 'Confirm Password',
|
||||
overideFieldKey:
|
||||
'confirmPassword',
|
||||
required: true,
|
||||
},
|
||||
placeholder: 'New Password',
|
||||
title: 'New Password',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
password: true,
|
||||
},
|
||||
validation: {
|
||||
minLength: 6,
|
||||
toMatchField:
|
||||
'password',
|
||||
},
|
||||
fieldType:
|
||||
FormFieldSchemaType.Password,
|
||||
placeholder:
|
||||
'Confirm Password',
|
||||
title: 'Confirm Password',
|
||||
overideFieldKey:
|
||||
'confirmPassword',
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
apiUrl={apiUrl}
|
||||
formType={FormType.Create}
|
||||
submitButtonText={'Reset Password'}
|
||||
onSuccess={() => {
|
||||
setIsSuccess(true);
|
||||
}}
|
||||
/>}
|
||||
]}
|
||||
apiUrl={apiUrl}
|
||||
formType={FormType.Create}
|
||||
submitButtonText={
|
||||
'Reset Password'
|
||||
}
|
||||
onSuccess={() => {
|
||||
setIsSuccess(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="mt-5 text-center">
|
||||
<p className="text-muted mb-0">
|
||||
|
@ -4,7 +4,7 @@ import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimePNG/7.png';
|
||||
import Link from 'CommonUI/src/Components/Link/Link';
|
||||
import PageLoader from 'CommonUI/src/Components/Loader/PageLoader';
|
||||
import ModelAPI from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
|
||||
import EmailVerificationToken from "Model/Models/EmailVerificationToken"
|
||||
import EmailVerificationToken from 'Model/Models/EmailVerificationToken';
|
||||
import { VERIFY_EMAIL_API_URL } from '../Utils/ApiPaths';
|
||||
import { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
@ -17,16 +17,18 @@ const VerifyEmail: FunctionComponent = () => {
|
||||
const [error, setError] = useState<string>('');
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
|
||||
|
||||
const init = async (): Promise<void> => {
|
||||
const init: Function = async (): Promise<void> => {
|
||||
// Ping an API here.
|
||||
setError('');
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
// strip data.
|
||||
const emailverificationToken = new EmailVerificationToken();
|
||||
emailverificationToken.token = new ObjectID(Navigation.getLastParam()?.toString().replace('/', '') || '');
|
||||
const emailverificationToken: EmailVerificationToken =
|
||||
new EmailVerificationToken();
|
||||
emailverificationToken.token = new ObjectID(
|
||||
Navigation.getLastParam()?.toString().replace('/', '') || ''
|
||||
);
|
||||
|
||||
await ModelAPI.createOrUpdate<EmailVerificationToken>(
|
||||
emailverificationToken,
|
||||
@ -36,24 +38,24 @@ const VerifyEmail: FunctionComponent = () => {
|
||||
{},
|
||||
{}
|
||||
);
|
||||
|
||||
|
||||
} catch (err) {
|
||||
setError(
|
||||
(err as HTTPErrorResponse).message ||
|
||||
'Server Error. Please try again'
|
||||
'Server Error. Please try again'
|
||||
);
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
init();
|
||||
}, [])
|
||||
init().catch((err: Error) => {
|
||||
setError(err.toString());
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return <PageLoader isVisible={true} />
|
||||
return <PageLoader isVisible={true} />;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -76,25 +78,29 @@ const VerifyEmail: FunctionComponent = () => {
|
||||
src={`/accounts/public/${OneUptimeLogo}`}
|
||||
/>
|
||||
</div>
|
||||
{!error && <div className="text-center">
|
||||
<h5 className="mb-0">
|
||||
Your email is verified.
|
||||
</h5>
|
||||
<p className="text-muted mt-2 mb-0">
|
||||
Thank you for veryfing your
|
||||
email. You can now log in to
|
||||
OneUptime.{' '}
|
||||
</p>
|
||||
</div>}
|
||||
{!error && (
|
||||
<div className="text-center">
|
||||
<h5 className="mb-0">
|
||||
Your email is verified.
|
||||
</h5>
|
||||
<p className="text-muted mt-2 mb-0">
|
||||
Thank you for veryfing your
|
||||
email. You can now log in to
|
||||
OneUptime.{' '}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && <div className="text-center">
|
||||
<h5 className="mb-0">
|
||||
Sorry, something went wrong!
|
||||
</h5>
|
||||
<p className="text-muted mt-2 mb-0">
|
||||
{error}
|
||||
</p>
|
||||
</div>}
|
||||
{error && (
|
||||
<div className="text-center">
|
||||
<h5 className="mb-0">
|
||||
Sorry, something went wrong!
|
||||
</h5>
|
||||
<p className="text-muted mt-2 mb-0">
|
||||
{error}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-5 text-center">
|
||||
<p className="text-muted mb-0">
|
||||
|
@ -19,4 +19,4 @@ export const VERIFY_EMAIL_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
|
||||
|
||||
export const RESET_PASSWORD_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
|
||||
new Route('/reset-password')
|
||||
);
|
||||
);
|
||||
|
@ -116,8 +116,6 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
protected checkRequiredFields(data: TBaseModel): void {
|
||||
// Check required fields.
|
||||
|
||||
console.log(data);
|
||||
|
||||
const relatationalColumns: Dictionary<string> = {};
|
||||
|
||||
const tableColumns: Array<string> = data.getTableColumns().columns;
|
||||
@ -143,12 +141,16 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
!(data as any)[requiredField] &&
|
||||
!data.isDefaultValueColumn(requiredField)
|
||||
) {
|
||||
|
||||
const metadata: TableColumnMetadata =
|
||||
data.getTableColumnMetadata(requiredField);
|
||||
data.getTableColumnMetadata(requiredField);
|
||||
|
||||
if (metadata && metadata.manyToOneRelationColumn && metadata.type === TableColumnType.Entity && data.getColumnValue(metadata.manyToOneRelationColumn)) {
|
||||
continue;
|
||||
if (
|
||||
metadata &&
|
||||
metadata.manyToOneRelationColumn &&
|
||||
metadata.type === TableColumnType.Entity &&
|
||||
data.getColumnValue(metadata.manyToOneRelationColumn)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -16,7 +16,7 @@ export default class MailService {
|
||||
const body: JSONObject = {
|
||||
...mail,
|
||||
clusterKey: ClusterKey.toString(),
|
||||
toEmail: mail.toEmail.toString()
|
||||
toEmail: mail.toEmail.toString(),
|
||||
};
|
||||
|
||||
if (mailServer) {
|
||||
|
@ -56,7 +56,6 @@ router.post(
|
||||
user.isEmailVerified = false;
|
||||
}
|
||||
|
||||
|
||||
const alreadySavedUser: User | null = await UserService.findOneBy({
|
||||
query: { email: user.email! },
|
||||
select: {
|
||||
@ -99,20 +98,19 @@ router.post(
|
||||
});
|
||||
}
|
||||
|
||||
console.log(savedUser);
|
||||
const generatedToken: ObjectID = ObjectID.generate();
|
||||
|
||||
const generatedToken = ObjectID.generate();
|
||||
|
||||
const emailVerificationToken = new EmailVerificationToken();
|
||||
const emailVerificationToken: EmailVerificationToken =
|
||||
new EmailVerificationToken();
|
||||
emailVerificationToken.userId = savedUser?.id!;
|
||||
emailVerificationToken.email = savedUser?.email!;
|
||||
emailVerificationToken.token = generatedToken;
|
||||
emailVerificationToken.expires = OneUptimeDate.getOneDayAfter()
|
||||
emailVerificationToken.expires = OneUptimeDate.getOneDayAfter();
|
||||
|
||||
await EmailVerificationTokenService.create({
|
||||
data: emailVerificationToken,
|
||||
props: {
|
||||
isRoot: true
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
@ -127,7 +125,8 @@ router.post(
|
||||
Domain,
|
||||
new Route(AccountsRoute.toString()).addRoute(
|
||||
'/verify-email/' + generatedToken.toString()
|
||||
)).toString(),
|
||||
)
|
||||
).toString(),
|
||||
homeUrl: new URL(HttpProtocol, HomeHostname).toString(),
|
||||
},
|
||||
}).catch((err: Error) => {
|
||||
@ -234,45 +233,56 @@ router.post(
|
||||
try {
|
||||
const data: JSONObject = req.body['data'];
|
||||
|
||||
const token: EmailVerificationToken = EmailVerificationToken.fromJSON(data as JSONObject, EmailVerificationToken) as EmailVerificationToken;
|
||||
const token: EmailVerificationToken =
|
||||
EmailVerificationToken.fromJSON(
|
||||
data as JSONObject,
|
||||
EmailVerificationToken
|
||||
) as EmailVerificationToken;
|
||||
|
||||
const alreadySavedToken: EmailVerificationToken | null = await EmailVerificationTokenService.findOneBy({
|
||||
query: { token: token.token! },
|
||||
select: {
|
||||
_id: true,
|
||||
userId: true,
|
||||
email: true,
|
||||
expires: true
|
||||
const alreadySavedToken: EmailVerificationToken | null =
|
||||
await EmailVerificationTokenService.findOneBy({
|
||||
query: { token: token.token! },
|
||||
select: {
|
||||
_id: true,
|
||||
userId: true,
|
||||
email: true,
|
||||
expires: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!alreadySavedToken) {
|
||||
throw new BadDataException(
|
||||
'Invalid link. Please try to log in and we will resend you another link which you should be able to verify email with.'
|
||||
);
|
||||
}
|
||||
|
||||
if (OneUptimeDate.hasExpired(alreadySavedToken.expires!)) {
|
||||
throw new BadDataException(
|
||||
'Link expired. Please try to log in and we will resend you another link which you should be able to verify email with.'
|
||||
);
|
||||
}
|
||||
|
||||
const user: User | null = await UserService.findOneBy({
|
||||
query: {
|
||||
email: token.email!,
|
||||
_id: token._id!,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!alreadySavedToken) {
|
||||
throw new BadDataException("Invalid link. Please try to log in and we will resend you another link which you should be able to verify email with.")
|
||||
}
|
||||
|
||||
if (OneUptimeDate.hasExpired(alreadySavedToken.expires!)) {
|
||||
throw new BadDataException("Link expired. Please try to log in and we will resend you another link which you should be able to verify email with.")
|
||||
}
|
||||
|
||||
let user = await UserService.findOneBy({
|
||||
query: {
|
||||
email: token.email!,
|
||||
_id: token._id!
|
||||
},
|
||||
props: {
|
||||
isRoot: true
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
email: true
|
||||
}
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new BadDataException("Invalid link. Please try to log in and we will resend you another link which you should be able to verify email with.")
|
||||
throw new BadDataException(
|
||||
'Invalid link. Please try to log in and we will resend you another link which you should be able to verify email with.'
|
||||
);
|
||||
}
|
||||
|
||||
await UserService.updateOneBy({
|
||||
@ -280,15 +290,13 @@ router.post(
|
||||
_id: user._id!,
|
||||
},
|
||||
data: {
|
||||
isEmailVerified: true
|
||||
isEmailVerified: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true
|
||||
}
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(user.email);
|
||||
|
||||
MailService.sendMail({
|
||||
toEmail: user.email!,
|
||||
subject: 'Email Verified.',
|
||||
@ -318,17 +326,21 @@ router.post(
|
||||
const data: JSONObject = req.body['data'];
|
||||
|
||||
const user: User = User.fromJSON(data as JSONObject, User) as User;
|
||||
|
||||
await user.password?.hashValue(EncryptionSecret);
|
||||
|
||||
const alreadySavedUser: User | null = await UserService.findOneBy({
|
||||
query: { resetPasswordToken: user.resetPasswordToken as string || '' },
|
||||
query: {
|
||||
resetPasswordToken:
|
||||
(user.resetPasswordToken as string) || '',
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
password: true,
|
||||
name: true,
|
||||
email: true,
|
||||
isMasterAdmin: true,
|
||||
resetPasswordExpires: true
|
||||
resetPasswordExpires: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@ -336,20 +348,26 @@ router.post(
|
||||
});
|
||||
|
||||
if (!alreadySavedUser) {
|
||||
throw new BadDataException("Invalid link. Please go to forgot password page again and request a new link.")
|
||||
throw new BadDataException(
|
||||
'Invalid link. Please go to forgot password page again and request a new link.'
|
||||
);
|
||||
}
|
||||
|
||||
if (alreadySavedUser && OneUptimeDate.hasExpired(alreadySavedUser.resetPasswordExpires!)) {
|
||||
throw new BadDataException("Expired link. Please go to forgot password page again and request a new link.")
|
||||
if (
|
||||
alreadySavedUser &&
|
||||
OneUptimeDate.hasExpired(alreadySavedUser.resetPasswordExpires!)
|
||||
) {
|
||||
throw new BadDataException(
|
||||
'Expired link. Please go to forgot password page again and request a new link.'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
await UserService.updateOneById({
|
||||
id: alreadySavedUser.id!,
|
||||
data: {
|
||||
password: user.password!,
|
||||
resetPasswordToken: null!,
|
||||
resetPasswordExpires: null!
|
||||
resetPasswordExpires: null!,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@ -368,7 +386,6 @@ router.post(
|
||||
});
|
||||
|
||||
return Response.sendEmptyResponse(req, res);
|
||||
|
||||
} catch (err) {
|
||||
return next(err);
|
||||
}
|
||||
@ -405,24 +422,23 @@ router.post(
|
||||
});
|
||||
|
||||
if (alreadySavedUser) {
|
||||
|
||||
if (!alreadySavedUser.isEmailVerified) {
|
||||
const generatedToken = ObjectID.generate();
|
||||
const generatedToken: ObjectID = ObjectID.generate();
|
||||
|
||||
const emailVerificationToken = new EmailVerificationToken();
|
||||
const emailVerificationToken:EmailVerificationToken = new EmailVerificationToken();
|
||||
emailVerificationToken.userId = alreadySavedUser?.id!;
|
||||
emailVerificationToken.email = alreadySavedUser?.email!;
|
||||
emailVerificationToken.token = generatedToken;
|
||||
emailVerificationToken.expires = OneUptimeDate.getOneDayAfter()
|
||||
emailVerificationToken.expires =
|
||||
OneUptimeDate.getOneDayAfter();
|
||||
|
||||
await EmailVerificationTokenService.create({
|
||||
data: emailVerificationToken,
|
||||
props: {
|
||||
isRoot: true
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
MailService.sendMail({
|
||||
toEmail: alreadySavedUser.email!,
|
||||
subject: 'Please verify email.',
|
||||
@ -434,14 +450,20 @@ router.post(
|
||||
Domain,
|
||||
new Route(AccountsRoute.toString()).addRoute(
|
||||
'/verify-email/' + generatedToken.toString()
|
||||
)).toString(),
|
||||
homeUrl: new URL(HttpProtocol, HomeHostname).toString(),
|
||||
)
|
||||
).toString(),
|
||||
homeUrl: new URL(
|
||||
HttpProtocol,
|
||||
HomeHostname
|
||||
).toString(),
|
||||
},
|
||||
}).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
});
|
||||
|
||||
throw new BadDataException("Email is not verified. We have sent you an email with the verification link. Please do not forget to check spam.")
|
||||
throw new BadDataException(
|
||||
'Email is not verified. We have sent you an email with the verification link. Please do not forget to check spam.'
|
||||
);
|
||||
}
|
||||
|
||||
const token: string = JSONWebToken.sign(
|
||||
|
@ -164,7 +164,6 @@ export default class MailService {
|
||||
to: mail.toEmail.toString(),
|
||||
subject: mail.subject,
|
||||
html: mail.body,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user