mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
fix lint
This commit is contained in:
@@ -0,0 +1 @@
|
||||
PORT=3003
|
||||
@@ -16,7 +16,10 @@ app.use(ExpressStatic(path.join(__dirname, 'public')));
|
||||
|
||||
app.use(`/${APP_NAME}`, ExpressStatic(path.join(__dirname, 'public')));
|
||||
|
||||
app.use([`/${APP_NAME}/assets`,`/${APP_NAME}/${APP_NAME}/assets`], ExpressStatic(path.join(__dirname, 'dist')));
|
||||
app.use(
|
||||
[`/${APP_NAME}/assets`, `/${APP_NAME}/${APP_NAME}/assets`],
|
||||
ExpressStatic(path.join(__dirname, 'dist'))
|
||||
);
|
||||
|
||||
app.get('/*', (_req: ExpressRequest, res: ExpressResponse) => {
|
||||
res.sendFile(path.join(__dirname, 'public', 'index.html'));
|
||||
@@ -26,7 +29,6 @@ const init: Function = async (): Promise<void> => {
|
||||
try {
|
||||
// init the app
|
||||
await App(APP_NAME);
|
||||
|
||||
} catch (err) {
|
||||
logger.error('App Init Failed:');
|
||||
logger.error(err);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import BasicModelForm from 'CommonUI/src/Components/Forms/BasicModelForm';
|
||||
import React, { FunctionComponent, useState } from 'react';
|
||||
import ModelForm, { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
|
||||
import User from 'Model/Models/User';
|
||||
import FormValues from 'CommonUI/src/Components/Forms/Types/FormValues';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimePNG/7.png';
|
||||
import Link from 'CommonUI/src/Components/Link/Link';
|
||||
import { FORGOT_PASSWORD_API_URL } from '../Utils/ApiPaths';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
|
||||
const ForgotPassword: FunctionComponent = () => {
|
||||
const user: User = new User();
|
||||
|
||||
const apiUrl: URL = FORGOT_PASSWORD_API_URL;
|
||||
|
||||
const [isSuccess, setIsSuccess] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<div className="auth-page">
|
||||
@@ -20,9 +24,11 @@ const ForgotPassword: FunctionComponent = () => {
|
||||
<div className="auth-full-page-content d-flex p-sm-5 p-4">
|
||||
<div className="w-100">
|
||||
<div className="d-flex flex-column h-100">
|
||||
|
||||
<div className="auth-content my-auto">
|
||||
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
|
||||
<div
|
||||
className="mt-4 text-center"
|
||||
style={{ marginBottom: '40px' }}
|
||||
>
|
||||
<img
|
||||
style={{ height: '40px' }}
|
||||
src={`/accounts/public/${OneUptimeLogo}`}
|
||||
@@ -30,18 +36,25 @@ const ForgotPassword: FunctionComponent = () => {
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<h5 className="mb-0">
|
||||
Reset Password
|
||||
Forgot Password
|
||||
</h5>
|
||||
<p className="text-muted mt-2 mb-0">
|
||||
{!isSuccess && <p className="text-muted mt-2 mb-0">
|
||||
Please enter your email and the
|
||||
password reset link will be sent
|
||||
to you.{' '}
|
||||
</p>
|
||||
</p>}
|
||||
|
||||
|
||||
{isSuccess && <p className="text-muted mt-2 mb-0">
|
||||
We have emailed you the password reset link. Please do not forget to check spam.{' '}
|
||||
</p>}
|
||||
|
||||
</div>
|
||||
|
||||
<BasicModelForm<User>
|
||||
model={user}
|
||||
{!isSuccess && <ModelForm<User>
|
||||
modelType={User}
|
||||
id="login-form"
|
||||
apiUrl={apiUrl}
|
||||
fields={[
|
||||
{
|
||||
field: {
|
||||
@@ -53,12 +66,13 @@ const ForgotPassword: FunctionComponent = () => {
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
onSubmit={(
|
||||
_values: FormValues<User>
|
||||
) => { }}
|
||||
onSuccess={() => {
|
||||
setIsSuccess(true);
|
||||
}}
|
||||
submitButtonText={
|
||||
'Send Password Reset Link'
|
||||
}
|
||||
formType={FormType.Create}
|
||||
maxPrimaryButtonWidth={true}
|
||||
footer={
|
||||
<div className="actions pointer text-center mt-4 underline-on-hover fw-semibold">
|
||||
@@ -75,7 +89,7 @@ const ForgotPassword: FunctionComponent = () => {
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
/>}
|
||||
|
||||
<div className="mt-5 text-center">
|
||||
<p className="text-muted mb-0">
|
||||
|
||||
@@ -23,9 +23,11 @@ const LoginPage: FunctionComponent = () => {
|
||||
<div className="auth-full-page-content d-flex p-sm-5 p-4">
|
||||
<div className="w-100">
|
||||
<div className="d-flex flex-column h-100">
|
||||
|
||||
<div className="auth-content my-auto">
|
||||
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
|
||||
<div
|
||||
className="mt-4 text-center"
|
||||
style={{ marginBottom: '40px' }}
|
||||
>
|
||||
<img
|
||||
style={{ height: '40px' }}
|
||||
src={`/accounts/public/${OneUptimeLogo}`}
|
||||
|
||||
@@ -24,9 +24,11 @@ const RegisterPage: FunctionComponent = () => {
|
||||
<div className="auth-full-page-content d-flex p-sm-5 p-4">
|
||||
<div className="w-100">
|
||||
<div className="d-flex flex-column h-100">
|
||||
|
||||
<div className="auth-content my-auto">
|
||||
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
|
||||
<div
|
||||
className="mt-4 text-center"
|
||||
style={{ marginBottom: '40px' }}
|
||||
>
|
||||
<img
|
||||
style={{ height: '40px' }}
|
||||
src={`/accounts/public/${OneUptimeLogo}`}
|
||||
|
||||
@@ -20,9 +20,11 @@ const SsoLoginPage: FunctionComponent = () => {
|
||||
<div className="auth-full-page-content d-flex p-sm-5 p-4">
|
||||
<div className="w-100">
|
||||
<div className="d-flex flex-column h-100">
|
||||
|
||||
<div className="auth-content my-auto">
|
||||
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
|
||||
<div
|
||||
className="mt-4 text-center"
|
||||
style={{ marginBottom: '40px' }}
|
||||
>
|
||||
<img
|
||||
style={{ height: '40px' }}
|
||||
src={`/accounts/public/${OneUptimeLogo}`}
|
||||
|
||||
@@ -14,9 +14,11 @@ const VerifyEmail: FunctionComponent = () => {
|
||||
<div className="auth-full-page-content d-flex p-sm-5 p-4">
|
||||
<div className="w-100">
|
||||
<div className="d-flex flex-column h-100">
|
||||
|
||||
<div className="auth-content my-auto">
|
||||
<div className="mt-4 text-center" style={{ marginBottom: "40px" }}>
|
||||
<div
|
||||
className="mt-4 text-center"
|
||||
style={{ marginBottom: '40px' }}
|
||||
>
|
||||
<img
|
||||
style={{ height: '40px' }}
|
||||
src={`/accounts/public/${OneUptimeLogo}`}
|
||||
|
||||
@@ -8,3 +8,8 @@ export const SIGNUP_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
|
||||
export const LOGIN_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
|
||||
new Route('/login')
|
||||
);
|
||||
|
||||
export const FORGOT_PASSWORD_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
|
||||
new Route('/forgot-password')
|
||||
);
|
||||
|
||||
|
||||
@@ -26,9 +26,8 @@ export default class Hostname extends DatabaseProperty {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static isValid(value: string): boolean {
|
||||
const re: RegExp = /^[a-zA-Z-\d!#$&'*+,/:;=?@[\].]*$/;
|
||||
const re: RegExp = /^[a-zA-Z-\d!#$&'*+,/:;=?@[\].]*$/;
|
||||
const isValid: boolean = re.test(value);
|
||||
if (!isValid) {
|
||||
return false;
|
||||
|
||||
@@ -35,7 +35,7 @@ export default class Email extends DatabaseProperty {
|
||||
if (Email.isValid(value)) {
|
||||
this._email = value;
|
||||
} else {
|
||||
throw new BadDataException('Email is not in valid format.');
|
||||
throw new BadDataException(`Email ${value} is not in valid format.`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
enum EmailTemplateType {
|
||||
ForgotPassword = "ForgotPassword.hbs",
|
||||
WelomeEmail="WelcomeEmail.hbs"
|
||||
ForgotPassword = 'ForgotPassword.hbs',
|
||||
WelomeEmail = 'WelcomeEmail.hbs',
|
||||
}
|
||||
|
||||
export default EmailTemplateType;
|
||||
|
||||
@@ -11,7 +11,6 @@ export default class Port extends DatabaseProperty {
|
||||
return this._port;
|
||||
}
|
||||
public set port(value: PositiveNumber) {
|
||||
|
||||
if (Port.isValid(value)) {
|
||||
this._port = value;
|
||||
} else {
|
||||
@@ -24,7 +23,7 @@ export default class Port extends DatabaseProperty {
|
||||
try {
|
||||
port = Number.parseInt(port.toString(), 10);
|
||||
} catch (error) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +32,9 @@ export default class Port extends DatabaseProperty {
|
||||
}
|
||||
|
||||
if (port >= 0 && port <= 65535) {
|
||||
return true
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public constructor(port: number | string) {
|
||||
|
||||
@@ -24,4 +24,18 @@ HOME_HOSTNAME={{ .Env.HOME_HOSTNAME }}
|
||||
BILLING_PRIVATE_KEY={{ .Env.BILLING_PRIVATE_KEY }}
|
||||
|
||||
DOMAIN={{ .Env.DOMAIN }}
|
||||
HTTP_PROTOCOL={{ .Env.HTTP_PROTOCOL }}
|
||||
HTTP_PROTOCOL={{ .Env.HTTP_PROTOCOL }}
|
||||
|
||||
REALTIME_ROUTE={{ .Env.REALTIME_ROUTE }}
|
||||
MAIL_ROUTE={{ .Env.MAIL_ROUTE }}
|
||||
DASHBOARD_ROUTE={{ .Env.DASHBOARD_ROUTE }}
|
||||
DASHBOARD_API_ROUTE={{ .Env.DASHBOARD_API_ROUTE }}
|
||||
PROBE_API_ROUTE={{ .Env.PROBE_API_ROUTE }}
|
||||
DATA_INGESTOR_ROUTE={{ .Env.DATA_INGESTOR_ROUTE }}
|
||||
ACCOUNTS_ROUTE={{ .Env.ACCOUNTS_ROUTE }}
|
||||
HOME_ROUTE={{ .Env.HOME_ROUTE }}
|
||||
HELMCHARTS_ROUTE={{ .Env.HELMCHARTS_ROUTE }}
|
||||
APIDOCS_ROUTE={{ .Env.APIDOCS_ROUTE }}
|
||||
IDENTITY_ROUTE={{ .Env.IDENTITY_ROUTE }}
|
||||
FILE_ROUTE={{ .Env.FILE_ROUTE }}
|
||||
STATUS_PAGE_ROUTE={{ .Env.STATUS_PAGE_ROUTE }}
|
||||
@@ -85,23 +85,36 @@ export const RedisHostname: string = process.env['REDIS_HOST'] || '';
|
||||
export const RedisPassword: string = process.env['REDIS_PASSWORD'] || '';
|
||||
export const RedisPort: Port = new Port(process.env['REDIS_PORT'] || '');
|
||||
|
||||
export const DashboardApiRoute: Route = new Route(
|
||||
process.env['DASHBOARD_API_ROUTE'] || ''
|
||||
);
|
||||
|
||||
export const DashboardApiRoute: Route = new Route(process.env['DASHBOARD_API_ROUTE'] || '');
|
||||
|
||||
export const IdentityRoute: Route = new Route(process.env['IDENTITY_ROUTE'] || '');
|
||||
export const IdentityRoute: Route = new Route(
|
||||
process.env['IDENTITY_ROUTE'] || ''
|
||||
);
|
||||
|
||||
export const FileRoute: Route = new Route(process.env['FILE_ROUTE'] || '');
|
||||
|
||||
export const StausPageRoute: Route = new Route(process.env['STATUS_PAGE_ROUTE'] || '');
|
||||
export const StausPageRoute: Route = new Route(
|
||||
process.env['STATUS_PAGE_ROUTE'] || ''
|
||||
);
|
||||
|
||||
export const DashboardRoute: Route = new Route(process.env['DASHBOARD_ROUTE'] || '');
|
||||
export const DashboardRoute: Route = new Route(
|
||||
process.env['DASHBOARD_ROUTE'] || ''
|
||||
);
|
||||
|
||||
export const IntegrationRoute: Route = new Route(process.env['INTEGRATION_ROUTE'] || '');
|
||||
export const IntegrationRoute: Route = new Route(
|
||||
process.env['INTEGRATION_ROUTE'] || ''
|
||||
);
|
||||
|
||||
export const HelmRoute: Route = new Route(process.env['HELMCHART_ROUTE'] || '');
|
||||
export const AccountsRoute: Route = new Route(process.env['ACCOUNTS_ROUTE'] || '');
|
||||
export const AccountsRoute: Route = new Route(
|
||||
process.env['ACCOUNTS_ROUTE'] || ''
|
||||
);
|
||||
|
||||
export const ApiDocsRoute: Route = new Route(process.env['APIDOCS_ROUTE'] || '');
|
||||
export const ApiDocsRoute: Route = new Route(
|
||||
process.env['APIDOCS_ROUTE'] || ''
|
||||
);
|
||||
|
||||
export const AdminDashboardRoute: Route = new Route(
|
||||
process.env['ADMINDASHBOARD_ROUTE'] || ''
|
||||
|
||||
@@ -34,7 +34,7 @@ export default class ClusterKeyAuthorization {
|
||||
);
|
||||
}
|
||||
|
||||
const isAuthorized: boolean = clusterKey === ONEUPTIME_SECRET;
|
||||
const isAuthorized: boolean = clusterKey.toString() === ONEUPTIME_SECRET.toString();
|
||||
|
||||
if (!isAuthorized) {
|
||||
return Response.sendErrorResponse(
|
||||
|
||||
@@ -15,6 +15,7 @@ export default class MailService {
|
||||
): Promise<HTTPResponse<EmptyResponseData>> {
|
||||
const body: JSONObject = {
|
||||
...mail,
|
||||
clusterKey: ClusterKey.toString()
|
||||
};
|
||||
|
||||
if (mailServer) {
|
||||
@@ -28,15 +29,8 @@ export default class MailService {
|
||||
}
|
||||
|
||||
return await API.post<EmptyResponseData>(
|
||||
new URL(
|
||||
HttpProtocol,
|
||||
MailHostname,
|
||||
new Route('/email/send')
|
||||
),
|
||||
body,
|
||||
{
|
||||
clusterkey: ClusterKey.toString(),
|
||||
}
|
||||
new URL(HttpProtocol, MailHostname, new Route('/email/send')),
|
||||
body
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,10 @@ app.use(ExpressStatic(path.join(__dirname, 'public')));
|
||||
|
||||
app.use(`/${APP_NAME}`, ExpressStatic(path.join(__dirname, 'public')));
|
||||
|
||||
app.use([`/${APP_NAME}/assets`,`/${APP_NAME}/${APP_NAME}/assets`], ExpressStatic(path.join(__dirname, 'dist')));
|
||||
app.use(
|
||||
[`/${APP_NAME}/assets`, `/${APP_NAME}/${APP_NAME}/assets`],
|
||||
ExpressStatic(path.join(__dirname, 'dist'))
|
||||
);
|
||||
|
||||
app.get('/*', (_req: ExpressRequest, res: ExpressResponse) => {
|
||||
res.sendFile(path.join(__dirname, 'public', 'index.html'));
|
||||
@@ -26,7 +29,6 @@ const init: Function = async (): Promise<void> => {
|
||||
try {
|
||||
// init the app
|
||||
await App(APP_NAME);
|
||||
|
||||
} catch (err) {
|
||||
logger.error('App Init Failed:');
|
||||
logger.error(err);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"test": "react-app-rewired test",
|
||||
"eject": "webpack eject",
|
||||
"compile": "tsc",
|
||||
"start": "webpack serve --port=3009",
|
||||
"start": "node --require ts-node/register Index.ts",
|
||||
"audit": "npm audit --audit-level=low",
|
||||
"preinstall": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
|
||||
"dep-check": "depcheck ./ --skip-missing=true'"
|
||||
|
||||
@@ -31,6 +31,7 @@ import OneUptimeDate from 'Common/Types/Date';
|
||||
import PositiveNumber from 'Common/Types/PositiveNumber';
|
||||
import BaseModel from 'Common/Models/BaseModel';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import logger from 'CommonServer/Utils/Logger';
|
||||
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
@@ -86,7 +87,7 @@ router.post(
|
||||
emailVerificationToken &&
|
||||
user &&
|
||||
alreadySavedUser?.id?.toString() ===
|
||||
emailVerificationToken?.userId?.toString()
|
||||
emailVerificationToken?.userId?.toString()
|
||||
) {
|
||||
user.isEmailVerified = true;
|
||||
}
|
||||
@@ -123,18 +124,21 @@ router.post(
|
||||
|
||||
if (alreadySavedUser) {
|
||||
// Send Welcome Mail
|
||||
await MailService.sendMail({
|
||||
MailService.sendMail({
|
||||
toEmail: user.email!,
|
||||
subject: "Welcome to OneUptime.",
|
||||
subject: 'Welcome to OneUptime.',
|
||||
templateType: EmailTemplateType.WelomeEmail,
|
||||
vars: {
|
||||
name: user.name!.toString(),
|
||||
dashboardUrl: new URL(
|
||||
HttpProtocol,
|
||||
Domain, DashboardRoute
|
||||
Domain,
|
||||
DashboardRoute
|
||||
).toString(),
|
||||
homeUrl: new URL(HttpProtocol, HomeHostname).toString(),
|
||||
}
|
||||
},
|
||||
}).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
});
|
||||
} else {
|
||||
// Send EmailVerification Link because this is a new user.
|
||||
@@ -144,11 +148,18 @@ router.post(
|
||||
templateType: EmailTemplateType.WelomeEmail,
|
||||
vars: {
|
||||
name: user.name!.toString(),
|
||||
emailVerificationUrl: new URL(HttpProtocol, Domain, new Route(AccountsRoute.toString()).addRoute("/reset-password/")).toString(),
|
||||
emailVerificationUrl: new URL(
|
||||
HttpProtocol,
|
||||
Domain,
|
||||
new Route(AccountsRoute.toString()).addRoute(
|
||||
'/reset-password/'
|
||||
)
|
||||
).toString(),
|
||||
homeUrl: new URL(HttpProtocol, HomeHostname).toString(),
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
}).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
if (savedUser) {
|
||||
@@ -171,7 +182,7 @@ router.post(
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/request-reset-password',
|
||||
'/forgot-password',
|
||||
async (
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse,
|
||||
@@ -197,29 +208,36 @@ router.post(
|
||||
});
|
||||
|
||||
if (alreadySavedUser) {
|
||||
|
||||
const token = ObjectID.generate().toString();
|
||||
const token: string = ObjectID.generate().toString();
|
||||
await UserService.updateOneBy({
|
||||
query: {
|
||||
_id: user._id!
|
||||
_id: user._id!,
|
||||
},
|
||||
data: {
|
||||
resetPasswordToken: token,
|
||||
resetPasswordExpires: OneUptimeDate.getOneDayAfter()
|
||||
resetPasswordExpires: OneUptimeDate.getOneDayAfter(),
|
||||
},
|
||||
props: {
|
||||
isRoot: true
|
||||
}
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
MailService.sendMail({
|
||||
toEmail: user.email!,
|
||||
subject: "Password Reset Request for OneUptime",
|
||||
subject: 'Password Reset Request for OneUptime',
|
||||
templateType: EmailTemplateType.ForgotPassword,
|
||||
vars: {
|
||||
homeURL: new URL(HttpProtocol, Domain).toString(),
|
||||
tokenVerifyUrl: new URL(HttpProtocol, Domain, new Route(AccountsRoute.toString()).addRoute("/reset-password/" + token)).toString(),
|
||||
}
|
||||
tokenVerifyUrl: new URL(
|
||||
HttpProtocol,
|
||||
Domain,
|
||||
new Route(AccountsRoute.toString()).addRoute(
|
||||
'/reset-password/' + token
|
||||
)
|
||||
).toString(),
|
||||
},
|
||||
}).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
});
|
||||
|
||||
return Response.sendEmptyResponse(req, res);
|
||||
@@ -228,7 +246,6 @@ router.post(
|
||||
throw new BadDataException(
|
||||
`No user is registered with ${user.email?.toString()}`
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ router.post(
|
||||
toEmail: new Email(body['to-email'] as string),
|
||||
subject: body['subject'] as string,
|
||||
vars: body['vars'] as Dictionary<string>,
|
||||
body: body['body'] as string || '',
|
||||
body: (body['body'] as string) || '',
|
||||
};
|
||||
|
||||
let mailServer: EmailServer | undefined = undefined;
|
||||
@@ -34,16 +34,19 @@ router.post(
|
||||
mailServer = MailService.getEmailServer(req.body);
|
||||
}
|
||||
|
||||
await MailService.send(
|
||||
mail, mailServer
|
||||
);
|
||||
await MailService.send(mail, mailServer);
|
||||
|
||||
return Response.sendEmptyResponse(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
const hasMailServerSettingsInBody = (body: JSONObject): boolean => {
|
||||
return body && Object.keys(body).filter((key) => key.startsWith("SMTP_")).length > 0;
|
||||
}
|
||||
const hasMailServerSettingsInBody: Function = (body: JSONObject): boolean => {
|
||||
return (
|
||||
body &&
|
||||
Object.keys(body).filter((key: string) => {
|
||||
return key.startsWith('SMTP_');
|
||||
}).length > 0
|
||||
);
|
||||
};
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -17,75 +17,81 @@ import { JSONObject } from 'Common/Types/JSON';
|
||||
import logger from 'CommonServer/Utils/Logger';
|
||||
|
||||
export default class MailService {
|
||||
|
||||
public static isSMTPConfigValid(obj: JSONObject): boolean {
|
||||
if (!obj['SMTP_USERNAME']) {
|
||||
logger.error('SMTP_USERNAME env var not found');
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obj['SMTP_EMAIL']) {
|
||||
logger.error('SMTP_EMAIL env var not found');
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Email.isValid(obj['SMTP_EMAIL'].toString())) {
|
||||
logger.error('SMTP_EMAIL env var ' + obj['SMTP_EMAIL'] + ' is not a valid email');
|
||||
return false;
|
||||
logger.error(
|
||||
'SMTP_EMAIL env var ' +
|
||||
obj['SMTP_EMAIL'] +
|
||||
' is not a valid email'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obj['SMTP_FROM_NAME']) {
|
||||
logger.error('SMTP_FROM_NAME env var not found');
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obj['SMTP_IS_SECURE']) {
|
||||
logger.error('SMTP_IS_SECURE env var not found');
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obj['SMTP_PORT']) {
|
||||
logger.error('SMTP_PORT env var not found');
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Port.isValid(obj['SMTP_PORT'].toString())) {
|
||||
logger.error('SMTP_PORT ' + obj['SMTP_HOST'] + ' env var not valid');
|
||||
return false;
|
||||
logger.error(
|
||||
'SMTP_PORT ' + obj['SMTP_HOST'] + ' env var not valid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obj['SMTP_HOST']) {
|
||||
logger.error('SMTP_HOST env var not found');
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Hostname.isValid(obj['SMTP_HOST'].toString())) {
|
||||
logger.error('SMTP_HOST env var ' + obj['SMTP_HOST'] + ' not valid');
|
||||
return false;
|
||||
logger.error(
|
||||
'SMTP_HOST env var ' + obj['SMTP_HOST'] + ' not valid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obj['SMTP_PASSWORD']) {
|
||||
logger.error('SMTP_PASSWORD env var not found');
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static getEmailServer(obj : JSONObject): EmailServer {
|
||||
public static getEmailServer(obj: JSONObject): EmailServer {
|
||||
if (!this.isSMTPConfigValid(obj)) {
|
||||
throw new BadDataException("SMTP Config is not valid");
|
||||
throw new BadDataException('SMTP Config is not valid');
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
username: obj['SMTP_USERNAME']?.toString()!,
|
||||
password: obj['SMTP_PASSWORD']?.toString()!,
|
||||
host: new Hostname(obj['SMTP_HOST']?.toString()!),
|
||||
port: new Port(obj['SMTP_PORT']?.toString()!),
|
||||
fromEmail: new Email(obj['SMTP_EMAIL']?.toString()!),
|
||||
fromName: obj['SMTP_FROM_NAME']?.toString()!,
|
||||
secure: obj['SMTP_IS_SECURE'] === "true",
|
||||
password: obj['SMTP_PASSWORD']?.toString()!,
|
||||
host: new Hostname(obj['SMTP_HOST']?.toString()!),
|
||||
port: new Port(obj['SMTP_PORT']?.toString()!),
|
||||
fromEmail: new Email(obj['SMTP_EMAIL']?.toString()!),
|
||||
fromName: obj['SMTP_FROM_NAME']?.toString()!,
|
||||
secure: obj['SMTP_IS_SECURE'] === 'true',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -93,7 +99,6 @@ export default class MailService {
|
||||
return this.getEmailServer(process.env);
|
||||
}
|
||||
|
||||
|
||||
private static async compileEmailBody(
|
||||
emailTemplateType: EmailTemplateType,
|
||||
vars: Dictionary<string>
|
||||
@@ -193,7 +198,9 @@ export default class MailService {
|
||||
mail.vars['year'] = OneUptimeDate.getCurrentYear().toString();
|
||||
}
|
||||
|
||||
mail.body = mail.templateType ? await this.compileEmailBody(mail.templateType, mail.vars) : this.compileText(mail.body || '', mail.vars);
|
||||
mail.body = mail.templateType
|
||||
? await this.compileEmailBody(mail.templateType, mail.vars)
|
||||
: this.compileText(mail.body || '', mail.vars);
|
||||
mail.subject = this.compileText(mail.subject, mail.vars);
|
||||
|
||||
await this.transportMail(mail, EmailServer);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This script merges config.env.tpl to config.env
|
||||
|
||||
import fs from 'fs'
|
||||
import fs from 'fs';
|
||||
|
||||
const init: Function = (): void => {
|
||||
const tempate: string = fs.readFileSync('./config.tpl.env', 'utf8');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// This script merges config.env.tpl to config.env
|
||||
|
||||
|
||||
import fs from 'fs'
|
||||
import fs from 'fs';
|
||||
|
||||
const init: Function = (): void => {
|
||||
let env: string = '';
|
||||
|
||||
@@ -16,7 +16,10 @@ app.use(ExpressStatic(path.join(__dirname, 'public')));
|
||||
|
||||
app.use(`/${APP_NAME}`, ExpressStatic(path.join(__dirname, 'public')));
|
||||
|
||||
app.use([`/${APP_NAME}/assets`,`/${APP_NAME}/${APP_NAME}/assets`], ExpressStatic(path.join(__dirname, 'dist')));
|
||||
app.use(
|
||||
[`/${APP_NAME}/assets`, `/${APP_NAME}/${APP_NAME}/assets`],
|
||||
ExpressStatic(path.join(__dirname, 'dist'))
|
||||
);
|
||||
|
||||
app.get('/*', (_req: ExpressRequest, res: ExpressResponse) => {
|
||||
res.sendFile(path.join(__dirname, 'public', 'index.html'));
|
||||
@@ -26,7 +29,6 @@ const init: Function = async (): Promise<void> => {
|
||||
try {
|
||||
// init the app
|
||||
await App(APP_NAME);
|
||||
|
||||
} catch (err) {
|
||||
logger.error('App Init Failed:');
|
||||
logger.error(err);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"test": "react-app-rewired test",
|
||||
"eject": "webpack eject",
|
||||
"compile": "tsc",
|
||||
"start": "webpack serve --port=3105",
|
||||
"start": "node --require ts-node/register Index.ts",
|
||||
"audit": "npm audit --audit-level=low",
|
||||
"preinstall": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
|
||||
"dep-check": "depcheck ./ --skip-missing=true'"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { FunctionComponent, useState } from 'react';
|
||||
import React, { FunctionComponent, useState, useEffect } from 'react';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import {
|
||||
Routes,
|
||||
@@ -26,7 +26,6 @@ import 'CommonUI/src/Styles/theme.scss';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import { JSONFunctions, JSONObject } from 'Common/Types/JSON';
|
||||
import RouteParams from './Utils/RouteParams';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const App: FunctionComponent = () => {
|
||||
Navigation.setNavigateHook(useNavigate());
|
||||
@@ -35,10 +34,9 @@ const App: FunctionComponent = () => {
|
||||
|
||||
const [isPreview, setIsPreview] = useState<boolean>(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setIsPreview(isPreviewPage());
|
||||
}, [])
|
||||
}, []);
|
||||
|
||||
// js.
|
||||
const [javascript, setJavaScript] = useState<string | null>(null);
|
||||
@@ -49,7 +47,7 @@ const App: FunctionComponent = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const isPreviewPage: Function = (): boolean => {
|
||||
const isPreviewPage: Function = (): boolean => {
|
||||
const id: string | null = Navigation.getParamByName(
|
||||
RouteParams.StatusPageId,
|
||||
RouteMap[PageMap.PREVIEW_OVERVIEW]!
|
||||
@@ -59,7 +57,7 @@ const App: FunctionComponent = () => {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -80,7 +78,6 @@ const App: FunctionComponent = () => {
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.OVERVIEW]?.toString()}
|
||||
|
||||
element={
|
||||
<Overview
|
||||
pageRoute={RouteMap[PageMap.OVERVIEW] as Route}
|
||||
|
||||
@@ -129,7 +129,11 @@ const Overview: FunctionComponent<PageComponentProps> = (
|
||||
footerEventStatus: 'Announced at',
|
||||
footerDateTime: announcement.showAnnouncementAt,
|
||||
eventViewRoute: RouteUtil.populateRouteParams(
|
||||
props.isPreviewPage ? RouteMap[PageMap.PREVIEW_ANNOUNCEMENT_DETAIL] as Route : RouteMap[PageMap.ANNOUNCEMENT_DETAIL] as Route,
|
||||
props.isPreviewPage
|
||||
? (RouteMap[
|
||||
PageMap.PREVIEW_ANNOUNCEMENT_DETAIL
|
||||
] as Route)
|
||||
: (RouteMap[PageMap.ANNOUNCEMENT_DETAIL] as Route),
|
||||
announcement.id!
|
||||
),
|
||||
});
|
||||
|
||||
@@ -104,7 +104,7 @@ const Overview: FunctionComponent<PageComponentProps> = (
|
||||
try {
|
||||
setError(
|
||||
(err as HTTPErrorResponse).message ||
|
||||
'Server Error. Please try again'
|
||||
'Server Error. Please try again'
|
||||
);
|
||||
} catch (e) {
|
||||
setError('Server Error. Please try again');
|
||||
@@ -177,11 +177,12 @@ const Overview: FunctionComponent<PageComponentProps> = (
|
||||
eventDescription: incident.description,
|
||||
eventTimeline: timeline,
|
||||
eventType: 'Incident',
|
||||
eventViewRoute: RouteUtil.populateRouteParams(props.isPreviewPage ?
|
||||
RouteMap[PageMap.PREVIEW_INCIDENT_DETAIL] as Route :
|
||||
RouteMap[PageMap.INCIDENT_DETAIL] as Route,
|
||||
incident.id!
|
||||
),
|
||||
eventViewRoute: RouteUtil.populateRouteParams(
|
||||
props.isPreviewPage
|
||||
? (RouteMap[PageMap.PREVIEW_INCIDENT_DETAIL] as Route)
|
||||
: (RouteMap[PageMap.INCIDENT_DETAIL] as Route),
|
||||
incident.id!
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -573,11 +573,14 @@ const Overview: FunctionComponent<PageComponentProps> = (
|
||||
)}
|
||||
eventType={'Incident'}
|
||||
eventViewRoute={RouteUtil.populateRouteParams(
|
||||
props.isPreviewPage ? RouteMap[
|
||||
PageMap.PREVIEW_INCIDENT_DETAIL
|
||||
] as Route : RouteMap[
|
||||
PageMap.INCIDENT_DETAIL
|
||||
] as Route,
|
||||
props.isPreviewPage
|
||||
? (RouteMap[
|
||||
PageMap
|
||||
.PREVIEW_INCIDENT_DETAIL
|
||||
] as Route)
|
||||
: (RouteMap[
|
||||
PageMap.INCIDENT_DETAIL
|
||||
] as Route),
|
||||
incidentGroup.incident.id!
|
||||
)}
|
||||
/>
|
||||
@@ -616,11 +619,14 @@ const Overview: FunctionComponent<PageComponentProps> = (
|
||||
}
|
||||
eventType={'Scheduled Maintenance'}
|
||||
eventViewRoute={RouteUtil.populateRouteParams(
|
||||
props.isPreviewPage ? RouteMap[
|
||||
PageMap.PREVIEW_SCHEDULED_EVENT_DETAIL
|
||||
] as Route : RouteMap[
|
||||
PageMap.SCHEDULED_EVENT_DETAIL
|
||||
] as Route,
|
||||
props.isPreviewPage
|
||||
? (RouteMap[
|
||||
PageMap
|
||||
.PREVIEW_SCHEDULED_EVENT_DETAIL
|
||||
] as Route)
|
||||
: (RouteMap[
|
||||
PageMap.SCHEDULED_EVENT_DETAIL
|
||||
] as Route),
|
||||
scheduledEventGroup.scheduledMaintenance
|
||||
.id!
|
||||
)}
|
||||
|
||||
@@ -5,5 +5,5 @@ export default interface ComponentProps {
|
||||
pageRoute: Route;
|
||||
statusPageId?: ObjectID | null | undefined;
|
||||
onLoadComplete: () => void;
|
||||
isPreviewPage?: boolean; // if this status page is not hosted on a domain, then this is true, otherwise false.
|
||||
isPreviewPage?: boolean; // if this status page is not hosted on a domain, then this is true, otherwise false.
|
||||
}
|
||||
|
||||
@@ -191,7 +191,11 @@ const Overview: FunctionComponent<PageComponentProps> = (
|
||||
eventTimeline: timeline,
|
||||
eventType: 'Scheduled Maintenance',
|
||||
eventViewRoute: RouteUtil.populateRouteParams(
|
||||
props.isPreviewPage ? RouteMap[PageMap.PREVIEW_SCHEDULED_EVENT_DETAIL] as Route : RouteMap[PageMap.SCHEDULED_EVENT_DETAIL] as Route,
|
||||
props.isPreviewPage
|
||||
? (RouteMap[
|
||||
PageMap.PREVIEW_SCHEDULED_EVENT_DETAIL
|
||||
] as Route)
|
||||
: (RouteMap[PageMap.SCHEDULED_EVENT_DETAIL] as Route),
|
||||
scheduledMaintenance.id!
|
||||
),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user