mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 08:42:13 +02:00
Compare commits
70 Commits
admin-dash
...
7.0.756
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfa85982c2 | ||
|
|
8451f9f90d | ||
|
|
c447941755 | ||
|
|
112e2e4faa | ||
|
|
fed9ab4621 | ||
|
|
18461d58d6 | ||
|
|
11095fc0bc | ||
|
|
a567cee47f | ||
|
|
158e2abc12 | ||
|
|
ca2095e867 | ||
|
|
708a9ba4b8 | ||
|
|
91a60eabbb | ||
|
|
7f0e07bd40 | ||
|
|
01b17b9dff | ||
|
|
b7e5cf78b9 | ||
|
|
d92d8c260b | ||
|
|
0576199db8 | ||
|
|
6f5a804d77 | ||
|
|
2f6420152e | ||
|
|
1d1d11bee2 | ||
|
|
594c36a512 | ||
|
|
ec5c852175 | ||
|
|
01ff01029b | ||
|
|
bf5d16b64c | ||
|
|
26ee469467 | ||
|
|
b514c8c189 | ||
|
|
2bbac9a545 | ||
|
|
03386eeba0 | ||
|
|
a09842c8b0 | ||
|
|
847b75b555 | ||
|
|
c839317283 | ||
|
|
1f4fd86845 | ||
|
|
8ed8c6a05c | ||
|
|
a716d54cc6 | ||
|
|
668d00418d | ||
|
|
5c36fa851c | ||
|
|
4352ada83e | ||
|
|
c6d76c4bb0 | ||
|
|
87a1a84d2e | ||
|
|
b02e622fd3 | ||
|
|
ac7e6b915f | ||
|
|
f3e1dccfc1 | ||
|
|
8683ac7677 | ||
|
|
eccb65f930 | ||
|
|
c1c27a387c | ||
|
|
aece287747 | ||
|
|
d6ff2c12fb | ||
|
|
50c8fe003d | ||
|
|
3e6b16fcf6 | ||
|
|
ce43514ee3 | ||
|
|
8318f09e26 | ||
|
|
7711902edd | ||
|
|
94ffa754eb | ||
|
|
48035ddec0 | ||
|
|
7694abe05e | ||
|
|
8eac47c4f9 | ||
|
|
fe90b50862 | ||
|
|
e3f2eaa3c6 | ||
|
|
fc09c689bc | ||
|
|
faf04a726c | ||
|
|
31e04a26ff | ||
|
|
90ea8ebee9 | ||
|
|
4d2e66fce3 | ||
|
|
6057fafd97 | ||
|
|
57671c444c | ||
|
|
11a3111098 | ||
|
|
e74c711dfd | ||
|
|
4f64693550 | ||
|
|
2336961178 | ||
|
|
c7938f62ae |
@@ -3,10 +3,13 @@
|
||||
#
|
||||
|
||||
# Pull base image nodejs image.
|
||||
FROM node:current-alpine
|
||||
FROM node:current-alpine AS base
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
@@ -24,7 +27,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN mkdir /usr/src
|
||||
|
||||
# Install common
|
||||
RUN mkdir /usr/src/Common
|
||||
|
||||
FROM base AS common
|
||||
WORKDIR /usr/src/Common
|
||||
COPY ./Common/package*.json /usr/src/Common/
|
||||
RUN npm install
|
||||
@@ -33,7 +37,8 @@ COPY ./Common /usr/src/Common
|
||||
|
||||
|
||||
# Install Model
|
||||
RUN mkdir /usr/src/Model
|
||||
|
||||
FROM base AS model
|
||||
WORKDIR /usr/src/Model
|
||||
COPY ./Model/package*.json /usr/src/Model/
|
||||
RUN npm install
|
||||
@@ -42,7 +47,8 @@ COPY ./Model /usr/src/Model
|
||||
|
||||
|
||||
# Install CommonServer
|
||||
RUN mkdir /usr/src/CommonServer
|
||||
|
||||
FROM base AS commonserver
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY ./CommonServer/package*.json /usr/src/CommonServer/
|
||||
RUN npm install
|
||||
@@ -52,7 +58,8 @@ COPY ./CommonServer /usr/src/CommonServer
|
||||
|
||||
|
||||
# Install CommonUI
|
||||
RUN mkdir /usr/src/CommonUI
|
||||
|
||||
FROM base AS commonui
|
||||
WORKDIR /usr/src/CommonUI
|
||||
COPY ./CommonUI/package*.json /usr/src/CommonUI/
|
||||
RUN npm install --force
|
||||
@@ -61,11 +68,25 @@ COPY ./CommonUI /usr/src/CommonUI
|
||||
|
||||
|
||||
#SET ENV Variables
|
||||
# Install app
|
||||
FROM base AS app
|
||||
|
||||
WORKDIR /usr/src/Common
|
||||
COPY --from=common /usr/src/Common .
|
||||
|
||||
WORKDIR /usr/src/Model
|
||||
COPY --from=model /usr/src/Model .
|
||||
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY --from=commonserver /usr/src/CommonServer .
|
||||
|
||||
WORKDIR /usr/src/CommonUI
|
||||
COPY --from=commonui /usr/src/CommonUI .
|
||||
|
||||
|
||||
ENV PRODUCTION=true
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
|
||||
RUN mkdir /usr/src/app
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install app dependencies
|
||||
|
||||
@@ -2,13 +2,13 @@ const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const dotenv = require('dotenv');
|
||||
const express = require('express');
|
||||
const axios = require('axios');
|
||||
|
||||
const readEnvFile = async (pathToFile) => {
|
||||
const readEnvFile = (pathToFile) => {
|
||||
|
||||
const parsed = dotenv.config({ path: pathToFile }).parsed;
|
||||
|
||||
const env = {};
|
||||
const env = {
|
||||
};
|
||||
|
||||
for (const key in parsed) {
|
||||
env[key] = JSON.stringify(parsed[key]);
|
||||
@@ -17,67 +17,62 @@ const readEnvFile = async (pathToFile) => {
|
||||
return env;
|
||||
}
|
||||
|
||||
const webpackConfig = async () => {
|
||||
return {
|
||||
entry: "./src/Index.tsx",
|
||||
mode: "development",
|
||||
output: {
|
||||
filename: "bundle.js",
|
||||
path: path.resolve(__dirname, "public", "dist"),
|
||||
publicPath: "/accounts/dist/",
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.css', '.scss'],
|
||||
alias: {
|
||||
react: path.resolve('./node_modules/react'),
|
||||
module.exports = {
|
||||
entry: "./src/Index.tsx",
|
||||
mode: "development",
|
||||
output: {
|
||||
filename: "bundle.js",
|
||||
path: path.resolve(__dirname, "public", "dist"),
|
||||
publicPath: "/accounts/dist/",
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.css', '.scss'],
|
||||
alias: {
|
||||
react: path.resolve('./node_modules/react'),
|
||||
}
|
||||
},
|
||||
externals: {
|
||||
'react-native-sqlite-storage': 'react-native-sqlite-storage'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process': {
|
||||
'env': {
|
||||
...readEnvFile('/usr/src/app/dev-env/.env')
|
||||
}
|
||||
}
|
||||
},
|
||||
externals: {
|
||||
'react-native-sqlite-storage': 'react-native-sqlite-storage'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process': {
|
||||
'env': {
|
||||
...(await readEnvFile('/usr/src/app/dev-env/.env'))
|
||||
}
|
||||
}
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(ts|tsx)$/,
|
||||
use: 'ts-loader'
|
||||
},
|
||||
{
|
||||
test: /\.s[ac]ss$/i,
|
||||
use: ['style-loader', 'css-loader', "sass-loader"]
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', 'css-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(jpe?g|png|gif|svg)$/i,
|
||||
loader: 'file-loader'
|
||||
}
|
||||
],
|
||||
},
|
||||
devServer: {
|
||||
historyApiFallback: true,
|
||||
devMiddleware: {
|
||||
writeToDisk: true,
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(ts|tsx)$/,
|
||||
use: 'ts-loader'
|
||||
},
|
||||
allowedHosts: "all",
|
||||
setupMiddlewares: (middlewares, devServer) => {
|
||||
devServer.app.use('/accounts/assets', express.static(path.resolve(__dirname, 'public', 'assets')));
|
||||
return middlewares;
|
||||
{
|
||||
test: /\.s[ac]ss$/i,
|
||||
use: ['style-loader', 'css-loader', "sass-loader"]
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', 'css-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(jpe?g|png|gif|svg)$/i,
|
||||
loader: 'file-loader'
|
||||
}
|
||||
],
|
||||
},
|
||||
devServer: {
|
||||
historyApiFallback: true,
|
||||
devMiddleware: {
|
||||
writeToDisk: true,
|
||||
},
|
||||
devtool: 'eval-source-map',
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = webpackConfig;
|
||||
allowedHosts: "all",
|
||||
setupMiddlewares: (middlewares, devServer) => {
|
||||
devServer.app.use('/accounts/assets', express.static(path.resolve(__dirname, 'public', 'assets')));
|
||||
return middlewares;
|
||||
}
|
||||
},
|
||||
devtool: 'eval-source-map',
|
||||
}
|
||||
@@ -3,10 +3,13 @@
|
||||
#
|
||||
|
||||
# Pull base image nodejs image.
|
||||
FROM node:current-alpine
|
||||
FROM node:current-alpine AS base
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
@@ -24,7 +27,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN mkdir /usr/src
|
||||
|
||||
# Install common
|
||||
RUN mkdir /usr/src/Common
|
||||
|
||||
FROM base AS common
|
||||
WORKDIR /usr/src/Common
|
||||
COPY ./Common/package*.json /usr/src/Common/
|
||||
RUN npm install
|
||||
@@ -32,7 +36,8 @@ COPY ./Common /usr/src/Common
|
||||
|
||||
|
||||
# Install Model
|
||||
RUN mkdir /usr/src/Model
|
||||
|
||||
FROM base AS model
|
||||
WORKDIR /usr/src/Model
|
||||
COPY ./Model/package*.json /usr/src/Model/
|
||||
RUN npm install
|
||||
@@ -41,7 +46,8 @@ COPY ./Model /usr/src/Model
|
||||
|
||||
|
||||
# Install CommonServer
|
||||
RUN mkdir /usr/src/CommonServer
|
||||
|
||||
FROM base AS commonserver
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY ./CommonServer/package*.json /usr/src/CommonServer/
|
||||
RUN npm install
|
||||
@@ -51,7 +57,8 @@ COPY ./CommonServer /usr/src/CommonServer
|
||||
|
||||
|
||||
# Install CommonUI
|
||||
RUN mkdir /usr/src/CommonUI
|
||||
|
||||
FROM base AS commonui
|
||||
WORKDIR /usr/src/CommonUI
|
||||
COPY ./CommonUI/package*.json /usr/src/CommonUI/
|
||||
RUN npm install --force
|
||||
@@ -59,11 +66,25 @@ COPY ./CommonUI /usr/src/CommonUI
|
||||
|
||||
|
||||
#SET ENV Variables
|
||||
# Install app
|
||||
FROM base AS app
|
||||
|
||||
WORKDIR /usr/src/Common
|
||||
COPY --from=common /usr/src/Common .
|
||||
|
||||
WORKDIR /usr/src/Model
|
||||
COPY --from=model /usr/src/Model .
|
||||
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY --from=commonserver /usr/src/CommonServer .
|
||||
|
||||
WORKDIR /usr/src/CommonUI
|
||||
COPY --from=commonui /usr/src/CommonUI .
|
||||
|
||||
|
||||
ENV PRODUCTION=true
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
|
||||
RUN mkdir /usr/src/app
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install app dependencies
|
||||
|
||||
@@ -24,6 +24,7 @@ import SettingsEmail from './Pages/Settings/SMTP/Index';
|
||||
import SettingsCallSMS from './Pages/Settings/CallSMS/Index';
|
||||
import SettingsProbes from './Pages/Settings/Probes/Index';
|
||||
import SettingsAuthentication from './Pages/Settings/Authentication/Index';
|
||||
import SettingsAPIKey from './Pages/Settings/APIKey/Index';
|
||||
|
||||
const App: () => JSX.Element = () => {
|
||||
Navigation.setNavigateHook(useNavigate());
|
||||
@@ -105,6 +106,11 @@ const App: () => JSX.Element = () => {
|
||||
}
|
||||
element={<SettingsAuthentication />}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.SETTINGS_API_KEY]?.toString() || ''}
|
||||
element={<SettingsAPIKey />}
|
||||
/>
|
||||
</Routes>
|
||||
</MasterPage>
|
||||
);
|
||||
|
||||
102
AdminDashboard/src/Pages/Settings/APIKey/Index.tsx
Normal file
102
AdminDashboard/src/Pages/Settings/APIKey/Index.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import DashboardSideMenu from '../SideMenu';
|
||||
import GlobalConfig from 'Model/Models/GlobalConfig';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
|
||||
const Settings: FunctionComponent = (): ReactElement => {
|
||||
return (
|
||||
<Page
|
||||
title={'Admin Settings'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Admin Dashboard',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.HOME] as Route
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.SETTINGS] as Route
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'API Key',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.SETTINGS_HOST] as Route
|
||||
),
|
||||
},
|
||||
]}
|
||||
sideMenu={<DashboardSideMenu />}
|
||||
>
|
||||
{/* Project Settings View */}
|
||||
<CardModelDetail
|
||||
name="API Key Settings"
|
||||
cardProps={{
|
||||
title: 'Master API Key Settings',
|
||||
description:
|
||||
'This API key has root access to all the resources in all the projects on OneUptime.',
|
||||
}}
|
||||
isEditable={true}
|
||||
editButtonText="Edit API Key Settings"
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
masterApiKey: true,
|
||||
},
|
||||
title: 'Master API Key',
|
||||
fieldType: FormFieldSchemaType.ObjectID,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
isMasterApiKeyEnabled: true,
|
||||
},
|
||||
title: 'Enabled',
|
||||
fieldType: FormFieldSchemaType.Toggle,
|
||||
required: false,
|
||||
},
|
||||
]}
|
||||
modelDetailProps={{
|
||||
modelType: GlobalConfig,
|
||||
id: 'model-detail-global-config',
|
||||
fields: [
|
||||
{
|
||||
field: {
|
||||
masterApiKey: true,
|
||||
},
|
||||
title: 'Master API Key',
|
||||
description:
|
||||
'This API key has root access to all the resources in all the projects on OneUptime.',
|
||||
fieldType: FieldType.HiddenText,
|
||||
opts: {
|
||||
isCopyable: true,
|
||||
},
|
||||
placeholder: 'API Key not generated yet.',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
isMasterApiKeyEnabled: true,
|
||||
},
|
||||
title: 'Enabled',
|
||||
description:
|
||||
'Enable or disable the master API key. If disabled, all requests using this key will fail.',
|
||||
fieldType: FieldType.Boolean,
|
||||
placeholder: 'Not Enabled',
|
||||
},
|
||||
],
|
||||
modelId: ObjectID.getZeroObjectID(),
|
||||
}}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
@@ -47,20 +47,6 @@ const Settings: FunctionComponent = (): ReactElement => {
|
||||
isEditable={true}
|
||||
editButtonText="Edit Host"
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
host: true,
|
||||
},
|
||||
title: 'Host',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: true,
|
||||
description:
|
||||
'IP address or Hostname of this server instance.',
|
||||
placeholder: 'oneuptime.yourcompany.com',
|
||||
validation: {
|
||||
minLength: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
useHttps: true,
|
||||
@@ -76,15 +62,6 @@ const Settings: FunctionComponent = (): ReactElement => {
|
||||
modelType: GlobalConfig,
|
||||
id: 'model-detail-global-config',
|
||||
fields: [
|
||||
{
|
||||
field: {
|
||||
host: true,
|
||||
},
|
||||
title: 'Host',
|
||||
placeholder: 'None',
|
||||
description:
|
||||
'IP address or Hostname of this server instance.',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
useHttps: true,
|
||||
|
||||
@@ -2,15 +2,65 @@ import Route from 'Common/Types/API/Route';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import React, { FunctionComponent, ReactElement, useEffect } from 'react';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import DashboardSideMenu from '../SideMenu';
|
||||
import GlobalConfig from 'Model/Models/GlobalConfig';
|
||||
import GlobalConfig, { EmailServerType } from 'Model/Models/GlobalConfig';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import ModelAPI from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
|
||||
import PageLoader from 'CommonUI/src/Components/Loader/PageLoader';
|
||||
import ErrorMessage from 'CommonUI/src/Components/ErrorMessage/ErrorMessage';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import DropdownUtil from 'CommonUI/src/Utils/Dropdown';
|
||||
import Pill from 'CommonUI/src/Components/Pill/Pill';
|
||||
import { Green, Red } from 'Common/Types/BrandColors';
|
||||
|
||||
const Settings: FunctionComponent = (): ReactElement => {
|
||||
const [emailServerType, setemailServerType] =
|
||||
React.useState<EmailServerType>(EmailServerType.Internal);
|
||||
|
||||
const [isLoading, setIsLoading] = React.useState<boolean>(true);
|
||||
|
||||
const [error, setError] = React.useState<string>('');
|
||||
|
||||
const fetchItem: Function = async (): Promise<void> => {
|
||||
setIsLoading(true);
|
||||
|
||||
const globalConfig: GlobalConfig | null =
|
||||
await ModelAPI.getItem<GlobalConfig>(
|
||||
GlobalConfig,
|
||||
ObjectID.getZeroObjectID(),
|
||||
{
|
||||
_id: true,
|
||||
emailServerType: true,
|
||||
}
|
||||
);
|
||||
|
||||
if (globalConfig) {
|
||||
setemailServerType(
|
||||
globalConfig.emailServerType || EmailServerType.Internal
|
||||
);
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchItem().catch((err: Error) => {
|
||||
setError(err.message);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return <PageLoader isVisible={true} />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <ErrorMessage error={error} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={'Admin Settings'}
|
||||
@@ -37,102 +87,31 @@ const Settings: FunctionComponent = (): ReactElement => {
|
||||
sideMenu={<DashboardSideMenu />}
|
||||
>
|
||||
{/* Project Settings View */}
|
||||
|
||||
<CardModelDetail
|
||||
name="Host Settings"
|
||||
name="Internal SMTP Settings"
|
||||
cardProps={{
|
||||
title: 'Email and SMTP Settings',
|
||||
title: 'Email Server Settings',
|
||||
description:
|
||||
'Email and SMTP Settings. We will use this SMTP server to send all the emails.',
|
||||
'Pick which email server you would like to use to send emails.',
|
||||
}}
|
||||
isEditable={true}
|
||||
editButtonText="Edit SMTP Config"
|
||||
formSteps={[
|
||||
{
|
||||
title: 'SMTP Server',
|
||||
id: 'server-info',
|
||||
},
|
||||
{
|
||||
title: 'Authentication',
|
||||
id: 'authentication',
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
id: 'email-info',
|
||||
},
|
||||
]}
|
||||
editButtonText="Edit Server"
|
||||
onSaveSuccess={() => {
|
||||
window.location.reload();
|
||||
}}
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
smtpHost: true,
|
||||
emailServerType: true,
|
||||
},
|
||||
title: 'Hostname',
|
||||
stepId: 'server-info',
|
||||
fieldType: FormFieldSchemaType.Hostname,
|
||||
title: 'Email Server Type',
|
||||
fieldType: FormFieldSchemaType.Dropdown,
|
||||
dropdownOptions:
|
||||
DropdownUtil.getDropdownOptionsFromEnum(
|
||||
EmailServerType
|
||||
),
|
||||
required: true,
|
||||
placeholder: 'smtp.server.com',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpPort: true,
|
||||
},
|
||||
title: 'Port',
|
||||
stepId: 'server-info',
|
||||
fieldType: FormFieldSchemaType.Port,
|
||||
required: true,
|
||||
placeholder: '587',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
isSMTPSecure: true,
|
||||
},
|
||||
title: 'Use SSL / TLS',
|
||||
stepId: 'server-info',
|
||||
fieldType: FormFieldSchemaType.Toggle,
|
||||
description: 'Make email communication secure?',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpUsername: true,
|
||||
},
|
||||
title: 'Username',
|
||||
stepId: 'authentication',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: false,
|
||||
placeholder: 'emailuser',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpPassword: true,
|
||||
},
|
||||
title: 'Password',
|
||||
stepId: 'authentication',
|
||||
fieldType: FormFieldSchemaType.EncryptedText,
|
||||
required: false,
|
||||
placeholder: 'Password',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromEmail: true,
|
||||
},
|
||||
title: 'Email From',
|
||||
stepId: 'email-info',
|
||||
fieldType: FormFieldSchemaType.Email,
|
||||
required: true,
|
||||
description:
|
||||
'This is the display email your team and customers see, when they receive emails from OneUptime.',
|
||||
placeholder: 'email@company.com',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromName: true,
|
||||
},
|
||||
title: 'From Name',
|
||||
stepId: 'email-info',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: true,
|
||||
description:
|
||||
'This is the display name your team and customers see, when they receive emails from OneUptime.',
|
||||
placeholder: 'Company, Inc.',
|
||||
},
|
||||
]}
|
||||
modelDetailProps={{
|
||||
@@ -141,53 +120,269 @@ const Settings: FunctionComponent = (): ReactElement => {
|
||||
fields: [
|
||||
{
|
||||
field: {
|
||||
smtpHost: true,
|
||||
emailServerType: true,
|
||||
},
|
||||
title: 'SMTP Host',
|
||||
placeholder: 'None',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpPort: true,
|
||||
},
|
||||
title: 'SMTP Port',
|
||||
placeholder: 'None',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpUsername: true,
|
||||
},
|
||||
title: 'SMTP Username',
|
||||
placeholder: 'None',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromEmail: true,
|
||||
},
|
||||
title: 'SMTP Email',
|
||||
placeholder: 'None',
|
||||
fieldType: FieldType.Email,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromName: true,
|
||||
},
|
||||
title: 'SMTP From Name',
|
||||
placeholder: 'None',
|
||||
},
|
||||
|
||||
{
|
||||
field: {
|
||||
isSMTPSecure: true,
|
||||
},
|
||||
title: 'Use SSL/TLS',
|
||||
placeholder: 'No',
|
||||
fieldType: FieldType.Boolean,
|
||||
title: 'Email Server Type',
|
||||
fieldType: FieldType.Text,
|
||||
},
|
||||
],
|
||||
modelId: ObjectID.getZeroObjectID(),
|
||||
}}
|
||||
/>
|
||||
|
||||
{emailServerType === EmailServerType.CustomSMTP ? (
|
||||
<CardModelDetail
|
||||
name="Host Settings"
|
||||
cardProps={{
|
||||
title: 'Custom Email and SMTP Settings',
|
||||
description:
|
||||
'If you have not enabled Internal SMTP server to send emails. Please configure your SMTP server here.',
|
||||
}}
|
||||
isEditable={true}
|
||||
editButtonText="Edit SMTP Config"
|
||||
formSteps={[
|
||||
{
|
||||
title: 'SMTP Server',
|
||||
id: 'server-info',
|
||||
},
|
||||
{
|
||||
title: 'Authentication',
|
||||
id: 'authentication',
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
id: 'email-info',
|
||||
},
|
||||
]}
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
smtpHost: true,
|
||||
},
|
||||
title: 'Hostname',
|
||||
stepId: 'server-info',
|
||||
fieldType: FormFieldSchemaType.Hostname,
|
||||
required: true,
|
||||
placeholder: 'smtp.server.com',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpPort: true,
|
||||
},
|
||||
title: 'Port',
|
||||
stepId: 'server-info',
|
||||
fieldType: FormFieldSchemaType.Port,
|
||||
required: true,
|
||||
placeholder: '587',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
isSMTPSecure: true,
|
||||
},
|
||||
title: 'Use SSL / TLS',
|
||||
stepId: 'server-info',
|
||||
fieldType: FormFieldSchemaType.Toggle,
|
||||
description: 'Make email communication secure?',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpUsername: true,
|
||||
},
|
||||
title: 'Username',
|
||||
stepId: 'authentication',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: false,
|
||||
placeholder: 'emailuser',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpPassword: true,
|
||||
},
|
||||
title: 'Password',
|
||||
stepId: 'authentication',
|
||||
fieldType: FormFieldSchemaType.EncryptedText,
|
||||
required: false,
|
||||
placeholder: 'Password',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromEmail: true,
|
||||
},
|
||||
title: 'Email From',
|
||||
stepId: 'email-info',
|
||||
fieldType: FormFieldSchemaType.Email,
|
||||
required: true,
|
||||
description:
|
||||
'This is the display email your team and customers see, when they receive emails from OneUptime.',
|
||||
placeholder: 'email@company.com',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromName: true,
|
||||
},
|
||||
title: 'From Name',
|
||||
stepId: 'email-info',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: true,
|
||||
description:
|
||||
'This is the display name your team and customers see, when they receive emails from OneUptime.',
|
||||
placeholder: 'Company, Inc.',
|
||||
},
|
||||
]}
|
||||
modelDetailProps={{
|
||||
modelType: GlobalConfig,
|
||||
id: 'model-detail-global-config',
|
||||
fields: [
|
||||
{
|
||||
field: {
|
||||
smtpHost: true,
|
||||
},
|
||||
title: 'SMTP Host',
|
||||
placeholder: 'None',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpPort: true,
|
||||
},
|
||||
title: 'SMTP Port',
|
||||
placeholder: 'None',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpUsername: true,
|
||||
},
|
||||
title: 'SMTP Username',
|
||||
placeholder: 'None',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromEmail: true,
|
||||
},
|
||||
title: 'SMTP Email',
|
||||
placeholder: 'None',
|
||||
fieldType: FieldType.Email,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
smtpFromName: true,
|
||||
},
|
||||
title: 'SMTP From Name',
|
||||
placeholder: 'None',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
isSMTPSecure: true,
|
||||
},
|
||||
title: 'Use SSL/TLS',
|
||||
placeholder: 'No',
|
||||
fieldType: FieldType.Boolean,
|
||||
},
|
||||
],
|
||||
modelId: ObjectID.getZeroObjectID(),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
{emailServerType === EmailServerType.Sendgrid ? (
|
||||
<CardModelDetail
|
||||
name="Sendgrid Settings"
|
||||
cardProps={{
|
||||
title: 'Sendgrid Settings',
|
||||
description:
|
||||
'Enter your Sendgrid API key to send emails through Sendgrid.',
|
||||
}}
|
||||
isEditable={true}
|
||||
editButtonText="Edit API Key"
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
sendgridApiKey: true,
|
||||
},
|
||||
title: 'Sendgrid API Key',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: true,
|
||||
placeholder: 'Sendgrid API Key',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
sendgridFromEmail: true,
|
||||
},
|
||||
title: 'From Email',
|
||||
fieldType: FormFieldSchemaType.Email,
|
||||
required: true,
|
||||
placeholder: 'email@yourcompany.com',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
sendgridFromName: true,
|
||||
},
|
||||
title: 'From Name',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: true,
|
||||
placeholder: 'Acme, Inc.',
|
||||
},
|
||||
]}
|
||||
modelDetailProps={{
|
||||
modelType: GlobalConfig,
|
||||
id: 'model-detail-global-config',
|
||||
selectMoreFields: {
|
||||
sendgridFromEmail: true,
|
||||
sendgridFromName: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
field: {
|
||||
sendgridApiKey: true,
|
||||
},
|
||||
title: '',
|
||||
placeholder: 'None',
|
||||
getElement: (item: JSONObject) => {
|
||||
if (
|
||||
item['sendgridApiKey'] &&
|
||||
item['sendgridFromEmail'] &&
|
||||
item['sendgridFromName']
|
||||
) {
|
||||
return (
|
||||
<Pill
|
||||
text="Enabled"
|
||||
color={Green}
|
||||
/>
|
||||
);
|
||||
} else if (!item['sendgridApiKey']) {
|
||||
return (
|
||||
<Pill
|
||||
text="Not Enabled. Please add the API key."
|
||||
color={Red}
|
||||
/>
|
||||
);
|
||||
} else if (!item['sendgridFromEmail']) {
|
||||
return (
|
||||
<Pill
|
||||
text="Not Enabled. Please add the From Email."
|
||||
color={Red}
|
||||
/>
|
||||
);
|
||||
} else if (!item['sendgridFromName']) {
|
||||
return (
|
||||
<Pill
|
||||
text="Not Enabled. Please add the From Name."
|
||||
color={Red}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <></>;
|
||||
},
|
||||
},
|
||||
],
|
||||
modelId: ObjectID.getZeroObjectID(),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -63,6 +63,17 @@ const DashboardSideMenu: () => JSX.Element = (): ReactElement => {
|
||||
icon={IconProp.Signal}
|
||||
/>
|
||||
</SideMenuSection>
|
||||
<SideMenuSection title="API and Integrations">
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'API Key',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.SETTINGS_API_KEY] as Route
|
||||
),
|
||||
}}
|
||||
icon={IconProp.Code}
|
||||
/>
|
||||
</SideMenuSection>
|
||||
</SideMenu>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ enum PageMap {
|
||||
SETTINGS_CALL_AND_SMS = 'SETTINGS_CALL_AND_SMS',
|
||||
SETTINGS_PROBES = 'SETTINGS_PROBES',
|
||||
SETTINGS_AUTHENTICATION = 'SETTINGS_AUTHENTICATION',
|
||||
SETTINGS_API_KEY = 'SETTINGS_API_KEY',
|
||||
}
|
||||
|
||||
export default PageMap;
|
||||
|
||||
@@ -18,6 +18,7 @@ const RouteMap: Dictionary<Route> = {
|
||||
[PageMap.SETTINGS_AUTHENTICATION]: new Route(
|
||||
`/admin/settings/authentication`
|
||||
),
|
||||
[PageMap.SETTINGS_API_KEY]: new Route(`/admin/settings/api-key`),
|
||||
};
|
||||
|
||||
export class RouteUtil {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
# Pull base image nodejs image.
|
||||
FROM node:current-alpine
|
||||
FROM node:current-alpine AS base
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
@@ -20,7 +23,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN mkdir /usr/src
|
||||
|
||||
# Install common
|
||||
RUN mkdir /usr/src/Common
|
||||
|
||||
FROM base AS common
|
||||
WORKDIR /usr/src/Common
|
||||
COPY ./Common/package*.json /usr/src/Common/
|
||||
RUN npm install
|
||||
@@ -28,7 +32,8 @@ COPY ./Common /usr/src/Common
|
||||
|
||||
|
||||
# Install Model
|
||||
RUN mkdir /usr/src/Model
|
||||
|
||||
FROM base AS model
|
||||
WORKDIR /usr/src/Model
|
||||
COPY ./Model/package*.json /usr/src/Model/
|
||||
RUN npm install
|
||||
@@ -37,7 +42,8 @@ COPY ./Model /usr/src/Model
|
||||
|
||||
|
||||
# Install CommonServer
|
||||
RUN mkdir /usr/src/CommonServer
|
||||
|
||||
FROM base AS commonserver
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY ./CommonServer/package*.json /usr/src/CommonServer/
|
||||
RUN npm install
|
||||
@@ -45,9 +51,21 @@ COPY ./CommonServer /usr/src/CommonServer
|
||||
|
||||
|
||||
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
# Install app
|
||||
FROM base AS app
|
||||
|
||||
RUN mkdir /usr/src/app
|
||||
WORKDIR /usr/src/Common
|
||||
COPY --from=common /usr/src/Common .
|
||||
|
||||
WORKDIR /usr/src/Model
|
||||
COPY --from=model /usr/src/Model .
|
||||
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY --from=commonserver /usr/src/CommonServer .
|
||||
|
||||
|
||||
ENV PRODUCTION=true
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
||||
@@ -229,6 +229,9 @@ export default class ServiceHandler {
|
||||
DashboardApiRoute.toString() +
|
||||
currentResource.model.crudApiPath?.toString();
|
||||
|
||||
pageData.isMasterAdminApiDocs =
|
||||
currentResource.model.isMasterAdminApiDocs;
|
||||
|
||||
return res.render('pages/index', {
|
||||
page: page,
|
||||
resources: Resources,
|
||||
|
||||
@@ -2,6 +2,7 @@ import BaseModel from 'Common/Models/BaseModel';
|
||||
import Models from 'Model/Models/Index';
|
||||
import ArrayUtil from 'Common/Types/ArrayUtil';
|
||||
import Dictionary from 'Common/Types/Dictionary';
|
||||
import { IsBillingEnabled } from 'CommonServer/EnvironmentConfig';
|
||||
|
||||
export interface ModelDocumentation {
|
||||
name: string;
|
||||
@@ -15,7 +16,13 @@ export default class ResourceUtil {
|
||||
const resources: Array<ModelDocumentation> = Models.filter(
|
||||
(model: typeof BaseModel) => {
|
||||
const modelInstance: BaseModel = new model();
|
||||
return modelInstance.enableDocumentation;
|
||||
let showDocs: boolean = modelInstance.enableDocumentation;
|
||||
|
||||
if (modelInstance.isMasterAdminApiDocs && IsBillingEnabled) {
|
||||
showDocs = false;
|
||||
}
|
||||
|
||||
return showDocs;
|
||||
}
|
||||
)
|
||||
.map((model: typeof BaseModel) => {
|
||||
|
||||
483
ApiReference/package-lock.json
generated
483
ApiReference/package-lock.json
generated
@@ -37,7 +37,6 @@
|
||||
"nodemon": "^2.0.20",
|
||||
"npm-force-resolutions": "0.0.10",
|
||||
"ora": "^6.1.0",
|
||||
"puppeteer": "^13.5.1",
|
||||
"start-server-and-test": "^1.14.0",
|
||||
"ts-jest": "^28.0.2",
|
||||
"ts-node-dev": "^1.1.8",
|
||||
@@ -59,7 +58,7 @@
|
||||
"moment-timezone": "^0.5.40",
|
||||
"nanoid": "^3.3.2",
|
||||
"nanoid-dictionary": "^4.3.0",
|
||||
"posthog-js": "^1.37.0",
|
||||
"posthog-js": "^1.77.0",
|
||||
"process": "^0.11.10",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"slugify": "^1.6.5",
|
||||
@@ -67,7 +66,7 @@
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^6.3.1",
|
||||
"@faker-js/faker": "^8.0.2",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^17.0.22",
|
||||
"jest": "^27.5.1",
|
||||
@@ -79,6 +78,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@clickhouse/client": "^0.2.1",
|
||||
"@elastic/elasticsearch": "^8.1.0",
|
||||
"@opentelemetry/api": "^1.1.0",
|
||||
"@opentelemetry/auto-instrumentations-node": "^0.31.0",
|
||||
@@ -811,6 +811,21 @@
|
||||
"node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/console/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/console/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -827,6 +842,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/console/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/console/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@jest/console/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -896,6 +929,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/core/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/core/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -912,6 +960,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/core/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/core/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@jest/core/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -1096,6 +1162,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/reporters/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/reporters/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -1112,6 +1193,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/reporters/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/reporters/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@jest/reporters/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -1333,6 +1432,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/types/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/types/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@jest/types/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -2758,7 +2875,8 @@
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/colors": {
|
||||
"version": "1.0.3",
|
||||
@@ -2841,6 +2959,11 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/compression/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/compression/node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -3549,6 +3672,11 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/extract-zip": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
||||
@@ -4395,6 +4523,11 @@
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/jake/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -5529,6 +5662,21 @@
|
||||
"node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-resolve/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-resolve/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -5545,6 +5693,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-resolve/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-resolve/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jest-resolve/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -6026,6 +6192,12 @@
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-util/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jest-util/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -6478,6 +6650,20 @@
|
||||
"integrity": "sha512-vlCUxxQAB8Nu6LQHqPpDRiMi06Du593/my/6JbMttQeEfJ7pf4OS8obSTh5xSOS80U/O7fq59Q8rQGAUxQatUQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lighthouse/node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/lighthouse/node_modules/semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
@@ -6769,7 +6955,8 @@
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/multimatch": {
|
||||
"version": "5.0.0",
|
||||
@@ -7453,31 +7640,6 @@
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.7.0.tgz",
|
||||
"integrity": "sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA==",
|
||||
"deprecated": "< 18.1.0 is no longer supported",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.981744",
|
||||
"extract-zip": "2.0.1",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
"pkg-dir": "4.2.0",
|
||||
"progress": "2.0.3",
|
||||
"proxy-from-env": "1.1.0",
|
||||
"rimraf": "3.0.2",
|
||||
"tar-fs": "2.1.1",
|
||||
"unbzip2-stream": "1.4.3",
|
||||
"ws": "8.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.18.1"
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer-core": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.7.0.tgz",
|
||||
@@ -7537,42 +7699,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer/node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer/node_modules/ws": {
|
||||
"version": "8.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
|
||||
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
@@ -8937,6 +9063,24 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
@@ -9625,6 +9769,15 @@
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -9635,6 +9788,21 @@
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -9689,6 +9857,15 @@
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -9699,6 +9876,21 @@
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -9840,6 +10032,15 @@
|
||||
"v8-to-istanbul": "^9.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -9850,6 +10051,21 @@
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -10018,6 +10234,21 @@
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -11165,7 +11396,8 @@
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.0.3",
|
||||
@@ -11190,7 +11422,7 @@
|
||||
"Common": {
|
||||
"version": "file:../Common",
|
||||
"requires": {
|
||||
"@faker-js/faker": "^6.3.1",
|
||||
"@faker-js/faker": "^8.0.2",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/nanoid-dictionary": "^4.2.0",
|
||||
@@ -11204,7 +11436,7 @@
|
||||
"moment-timezone": "^0.5.40",
|
||||
"nanoid": "^3.3.2",
|
||||
"nanoid-dictionary": "^4.3.0",
|
||||
"posthog-js": "^1.37.0",
|
||||
"posthog-js": "^1.77.0",
|
||||
"process": "^0.11.10",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"slugify": "^1.6.5",
|
||||
@@ -11216,6 +11448,7 @@
|
||||
"CommonServer": {
|
||||
"version": "file:../CommonServer",
|
||||
"requires": {
|
||||
"@clickhouse/client": "^0.2.1",
|
||||
"@elastic/elasticsearch": "^8.1.0",
|
||||
"@faker-js/faker": "^6.3.1",
|
||||
"@opentelemetry/api": "^1.1.0",
|
||||
@@ -11297,6 +11530,11 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -11861,6 +12099,11 @@
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -12481,6 +12724,11 @@
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -13309,6 +13557,15 @@
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -13319,6 +13576,21 @@
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -13703,6 +13975,12 @@
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -14024,6 +14302,17 @@
|
||||
"yargs-parser": "^21.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
@@ -14296,7 +14585,8 @@
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"multimatch": {
|
||||
"version": "5.0.0",
|
||||
@@ -14781,44 +15071,6 @@
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"puppeteer": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.7.0.tgz",
|
||||
"integrity": "sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.981744",
|
||||
"extract-zip": "2.0.1",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
"pkg-dir": "4.2.0",
|
||||
"progress": "2.0.3",
|
||||
"proxy-from-env": "1.1.0",
|
||||
"rimraf": "3.0.2",
|
||||
"tar-fs": "2.1.1",
|
||||
"unbzip2-stream": "1.4.3",
|
||||
"ws": "8.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
|
||||
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"puppeteer-core": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.7.0.tgz",
|
||||
@@ -15857,6 +16109,21 @@
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
"nodemon": "^2.0.20",
|
||||
"npm-force-resolutions": "0.0.10",
|
||||
"ora": "^6.1.0",
|
||||
"puppeteer": "^13.5.1",
|
||||
|
||||
"start-server-and-test": "^1.14.0",
|
||||
"ts-jest": "^28.0.2",
|
||||
"ts-node-dev": "^1.1.8",
|
||||
|
||||
@@ -9,8 +9,12 @@
|
||||
|
||||
|
||||
<h2>Permissions</h2>
|
||||
|
||||
<% if(!pageData.isMasterAdminApiDocs){ %>
|
||||
<p class="lead"> Your API Token needs permissions to create, update, read or delete this resource. If you do not have permissions to make a request a <code class="inline-code">4xx</code> status will be sent as response. </p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 id="consuming-webhooks" >
|
||||
Read Permissions
|
||||
@@ -138,6 +142,28 @@
|
||||
|
||||
</div>
|
||||
|
||||
<% } %>
|
||||
|
||||
<% if(pageData.isMasterAdminApiDocs){ %>
|
||||
|
||||
|
||||
<div class="border-l-4 border-yellow-400 bg-yellow-50 p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-sm font-medium text-yellow-700 mb-0">
|
||||
This API can only be accessed through a Master API Token. You can create one on the Admin Dashboard. Please add the token to the <code class="inline-code">ApiKey</code> header to make the request.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% } %>
|
||||
|
||||
|
||||
<h2 id="the-contact-model" class="scroll-mt-24">
|
||||
The <%= pageData.title -%> model
|
||||
|
||||
@@ -110,6 +110,7 @@ export default class BaseModel extends BaseEntity {
|
||||
public enableWorkflowOn!: EnableWorkflowOn;
|
||||
|
||||
public enableDocumentation!: boolean;
|
||||
public isMasterAdminApiDocs!: boolean;
|
||||
|
||||
public currentUserCanAccessColumnBy!: string | null;
|
||||
public labelsColumn!: string | null;
|
||||
|
||||
@@ -24,7 +24,7 @@ export const AccountsRoute: Route = new Route('/accounts');
|
||||
|
||||
export const WorkflowRoute: Route = new Route('/workflow');
|
||||
|
||||
export const ApiReferenceRoute: Route = new Route('/api-reference');
|
||||
export const ApiReferenceRoute: Route = new Route('/reference');
|
||||
|
||||
export const AdminDashboardRoute: Route = new Route('/admin');
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const LIMIT_MAX: number = 10000;
|
||||
|
||||
export const LIMIT_PER_PROJECT: number = 300;
|
||||
|
||||
export const DEFAULT_LIMIT: number = 10;
|
||||
export default LIMIT_MAX;
|
||||
|
||||
@@ -7,6 +7,7 @@ enum ExceptionCode {
|
||||
WebRequestException = 6,
|
||||
BadDataException = 400,
|
||||
BadRequestException = 400,
|
||||
UnabletoReachServerException = 415,
|
||||
ServerException = 500,
|
||||
NotAuthorizedException = 403,
|
||||
NotAuthenticatedException = 401,
|
||||
|
||||
8
Common/Types/Exception/UnableToReachServer.ts
Normal file
8
Common/Types/Exception/UnableToReachServer.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import Exception from './Exception';
|
||||
import ExceptionCode from './ExceptionCode';
|
||||
|
||||
export default class UnableToReachServer extends Exception {
|
||||
public constructor(message: string) {
|
||||
super(ExceptionCode.UnabletoReachServerException, message);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
export default () => {
|
||||
export interface EnableDocumentationProps {
|
||||
isMasterAdminApiDocs?: boolean | undefined;
|
||||
}
|
||||
|
||||
export default (props?: EnableDocumentationProps | undefined) => {
|
||||
return (ctr: Function) => {
|
||||
ctr.prototype.enableDocumentation = true;
|
||||
ctr.prototype.isMasterAdminApiDocs =
|
||||
props?.isMasterAdminApiDocs || false;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,7 +19,10 @@ import DatabaseCommonInteractionProps from 'Common/Types/Database/DatabaseCommon
|
||||
import Query from '../Types/Database/Query';
|
||||
import Select from '../Types/Database/Select';
|
||||
import Sort from '../Types/Database/Sort';
|
||||
import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax';
|
||||
import {
|
||||
DEFAULT_LIMIT,
|
||||
LIMIT_PER_PROJECT,
|
||||
} from 'Common/Types/Database/LimitMax';
|
||||
import PartialEntity from 'Common/Types/Database/PartialEntity';
|
||||
import { UserPermission } from 'Common/Types/Permission';
|
||||
import { IsBillingEnabled } from '../EnvironmentConfig';
|
||||
@@ -283,7 +286,7 @@ export default class BaseAPI<
|
||||
|
||||
const limit: PositiveNumber = req.query['limit']
|
||||
? new PositiveNumber(req.query['limit'] as string)
|
||||
: new PositiveNumber(10);
|
||||
: new PositiveNumber(DEFAULT_LIMIT);
|
||||
|
||||
if (limit.toNumber() > LIMIT_PER_PROJECT) {
|
||||
throw new BadRequestException(
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import Probe from 'Model/Models/Probe';
|
||||
import ProbeService, {
|
||||
Service as ProbeServiceType,
|
||||
} from '../Services/ProbeService';
|
||||
import {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
NextFunction,
|
||||
} from '../Utils/Express';
|
||||
import Response from '../Utils/Response';
|
||||
import BaseAPI from './BaseAPI';
|
||||
import GlobalConfigService from '../Services/GlobalConfigService';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import GlobalConfig from 'Model/Models/GlobalConfig';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
|
||||
export default class ProbeAPI extends BaseAPI<Probe, ProbeServiceType> {
|
||||
public constructor() {
|
||||
super(Probe, ProbeService);
|
||||
|
||||
this.router.get(
|
||||
`${new this.entityType().getCrudApiPath()?.toString()}/vars`,
|
||||
async (
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse,
|
||||
next: NextFunction
|
||||
) => {
|
||||
try {
|
||||
const globalConfig: GlobalConfig | null = await GlobalConfigService.findOneById({
|
||||
id: ObjectID.getZeroObjectID(),
|
||||
select: {
|
||||
host: true,
|
||||
useHttps: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if(!globalConfig){
|
||||
return Response.sendErrorResponse(req, res, new BadDataException("Global Config not found"));
|
||||
}
|
||||
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
HOST: globalConfig?.host?.toString() || 'localhost',
|
||||
USE_HTTPS: globalConfig?.useHttps || false,
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,46 @@
|
||||
import Probe from 'Model/Models/Probe';
|
||||
import ProbeService, {
|
||||
Service as ProbeServiceType,
|
||||
} from '../Services/ProbeService';
|
||||
import GlobalConfig from 'Model/Models/GlobalConfig';
|
||||
import GlobalConfigService, {
|
||||
Service as GlobalConfigServiceType,
|
||||
} from '../Services/GlobalConfigService';
|
||||
import {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
ExpressResponse,
|
||||
NextFunction,
|
||||
} from '../Utils/Express';
|
||||
import Response from '../Utils/Response';
|
||||
import BaseAPI from './BaseAPI';
|
||||
import GlobalConfigService from '../Services/GlobalConfigService';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
|
||||
export default class ProbeAPI extends BaseAPI<Probe, ProbeServiceType> {
|
||||
export default class GlobalConfigAPI extends BaseAPI<
|
||||
GlobalConfig,
|
||||
GlobalConfigServiceType
|
||||
> {
|
||||
public constructor() {
|
||||
super(Probe, ProbeService);
|
||||
super(GlobalConfig, GlobalConfigService);
|
||||
|
||||
this.router.get(
|
||||
`${new this.entityType()
|
||||
.getCrudApiPath()
|
||||
?.toString()}/vars`,
|
||||
`${new this.entityType().getCrudApiPath()?.toString()}/vars`,
|
||||
async (
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse,
|
||||
next: NextFunction
|
||||
) => {
|
||||
try {
|
||||
const globalConfig = await GlobalConfigService.findOneById({
|
||||
id: ObjectID.getZeroObjectID(),
|
||||
select: {
|
||||
host: true,
|
||||
useHttps: true
|
||||
},
|
||||
props: {
|
||||
isRoot: true
|
||||
}
|
||||
const globalConfig: GlobalConfig | null =
|
||||
await GlobalConfigService.findOneById({
|
||||
id: ObjectID.getZeroObjectID(),
|
||||
select: {
|
||||
useHttps: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
USE_HTTPS:
|
||||
globalConfig?.useHttps?.toString() || 'false',
|
||||
});
|
||||
|
||||
return Response.sendJsonObjectResponse(
|
||||
req,
|
||||
res,
|
||||
{
|
||||
'HOST': globalConfig?.host?.toString() || 'localhost',
|
||||
'USE_HTTPS': globalConfig?.useHttps?.toString() || "false"
|
||||
},
|
||||
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
|
||||
query: {
|
||||
userId: (req as OneUptimeRequest)
|
||||
.userAuthorization!.userId!,
|
||||
hasAcceptedInvitation: true,
|
||||
},
|
||||
select: {
|
||||
project: {
|
||||
|
||||
@@ -205,6 +205,7 @@ export default class ResellerPlanAPI extends BaseAPI<
|
||||
data: {
|
||||
activeMonitorsLimit: resellerPlan.monitorLimit!,
|
||||
seatLimit: resellerPlan.teamMemberLimit!,
|
||||
resellerPlanId: resellerPlan.id!,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
|
||||
@@ -15,7 +15,7 @@ import Response from '../Utils/Response';
|
||||
import NotAuthenticatedException from 'Common/Types/Exception/NotAuthenticatedException';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import StatusPageFooterLinkService from '../Services/StatusPageFooterLinkService';
|
||||
import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax';
|
||||
import LIMIT_MAX, { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax';
|
||||
import StatusPageFooterLink from 'Model/Models/StatusPageFooterLink';
|
||||
import StatusPageHeaderLinkService from '../Services/StatusPageHeaderLinkService';
|
||||
import StatusPageHeaderLink from 'Model/Models/StatusPageHeaderLink';
|
||||
@@ -553,7 +553,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
limit: LIMIT_MAX, // This can be optimized.
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
|
||||
@@ -31,9 +31,8 @@ export default class DatabaseConfig {
|
||||
}
|
||||
|
||||
public static async getHost(): Promise<Hostname> {
|
||||
return (
|
||||
((await DatabaseConfig.getFromGlobalConfig('host')) as Hostname) ||
|
||||
new Hostname('localhost')
|
||||
return Promise.resolve(
|
||||
new Hostname(process.env['HOST'] || 'localhost')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,49 +62,28 @@ export const ClusterKey: ObjectID = new ObjectID(
|
||||
|
||||
export const HasClusterKey: boolean = Boolean(process.env['ONEUPTIME_SECRET']);
|
||||
|
||||
export const RealtimeHostname: Hostname = Hostname.fromString(
|
||||
process.env['REALTIME_HOSTNAME'] || 'realtime'
|
||||
);
|
||||
export const RealtimeHostname: Hostname = Hostname.fromString('realtime:3300');
|
||||
|
||||
export const NotificationHostname: Hostname = Hostname.fromString(
|
||||
process.env['NOTIFICATION_HOSTNAME'] || 'notification'
|
||||
);
|
||||
export const NotificationHostname: Hostname =
|
||||
Hostname.fromString('notification:3191');
|
||||
|
||||
export const WorkerHostname: Hostname = Hostname.fromString(
|
||||
process.env['WORKER_HOSTNAME'] || 'worker'
|
||||
);
|
||||
export const WorkerHostname: Hostname = Hostname.fromString('worker:3452');
|
||||
|
||||
export const LinkShortenerHostname: Route = new Route(
|
||||
process.env['LINK_SHORTENER_HOSTNAME'] || 'link-shortener'
|
||||
);
|
||||
export const LinkShortenerHostname: Route = new Route('link-shortener:3521');
|
||||
|
||||
export const WorkflowHostname: Hostname = Hostname.fromString(
|
||||
process.env['WORKFLOW_HOSTNAME'] || 'workflow'
|
||||
);
|
||||
export const WorkflowHostname: Hostname = Hostname.fromString('workflow:3099');
|
||||
|
||||
export const DashboardApiHostname: Hostname = Hostname.fromString(
|
||||
process.env['DASHBOARD_API_HOSTNAME'] || 'dashboard-api'
|
||||
);
|
||||
export const DashboardApiHostname: Hostname =
|
||||
Hostname.fromString('dashboard-api:3002');
|
||||
|
||||
export const ProbeApiHostname: Hostname = Hostname.fromString(
|
||||
process.env['PROBE_API_HOSTNAME'] || 'probe-api'
|
||||
);
|
||||
export const ProbeApiHostname: Hostname = Hostname.fromString('probe-api:3400');
|
||||
|
||||
export const DataIngestorHostname: Hostname = Hostname.fromString(
|
||||
process.env['DATA_INGESTOR_HOSTNAME'] || 'daat-ingestor'
|
||||
);
|
||||
export const AccountsHostname: Hostname = Hostname.fromString('accounts:3003');
|
||||
|
||||
export const AccountsHostname: Hostname = Hostname.fromString(
|
||||
process.env['ACCOUNTS_HOSTNAME'] || 'accounts'
|
||||
);
|
||||
export const HomeHostname: Hostname = Hostname.fromString('home:1444');
|
||||
|
||||
export const HomeHostname: Hostname = Hostname.fromString(
|
||||
process.env['HOME_HOSTNAME'] || 'home'
|
||||
);
|
||||
|
||||
export const DashboardHostname: Hostname = Hostname.fromString(
|
||||
process.env['DASHBOARD_HOSTNAME'] || 'dashboard'
|
||||
);
|
||||
export const DashboardHostname: Hostname =
|
||||
Hostname.fromString('dashboard:3000');
|
||||
|
||||
export const Env: string = process.env['NODE_ENV'] || 'production';
|
||||
|
||||
|
||||
@@ -14,8 +14,12 @@ import UserType from 'Common/Types/UserType';
|
||||
import AccessTokenService from '../Services/AccessTokenService';
|
||||
import { UserTenantAccessPermission } from 'Common/Types/Permission';
|
||||
import Dictionary from 'Common/Types/Dictionary';
|
||||
import Response from '../Utils/Response';
|
||||
import QueryHelper from '../Types/Database/QueryHelper';
|
||||
import GlobalConfigService from '../Services/GlobalConfigService';
|
||||
import User from 'Model/Models/User';
|
||||
import UserService from '../Services/UserService';
|
||||
import GlobalConfig from 'Model/Models/GlobalConfig';
|
||||
import logger from '../Utils/Logger';
|
||||
|
||||
export default class ProjectMiddleware {
|
||||
public static getProjectId(req: ExpressRequest): ObjectID | null {
|
||||
@@ -55,67 +59,132 @@ export default class ProjectMiddleware {
|
||||
|
||||
public static async isValidProjectIdAndApiKeyMiddleware(
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse,
|
||||
_res: ExpressResponse,
|
||||
next: NextFunction
|
||||
): Promise<void> {
|
||||
const tenantId: ObjectID | null = this.getProjectId(req);
|
||||
try {
|
||||
const tenantId: ObjectID | null = this.getProjectId(req);
|
||||
|
||||
const apiKey: ObjectID | null = this.getApiKey(req);
|
||||
logger.info('tenantId', tenantId);
|
||||
|
||||
if (!tenantId) {
|
||||
throw new BadDataException('ProjectId not found in the request');
|
||||
}
|
||||
const apiKey: ObjectID | null = this.getApiKey(req);
|
||||
|
||||
if (!apiKey) {
|
||||
throw new BadDataException('ApiKey not found in the request');
|
||||
}
|
||||
|
||||
const apiKeyModel: ApiKey | null = await ApiKeyService.findOneBy({
|
||||
query: {
|
||||
projectId: tenantId,
|
||||
apiKey: apiKey,
|
||||
expiresAt: QueryHelper.greaterThan(
|
||||
OneUptimeDate.getCurrentDate()
|
||||
),
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (apiKeyModel) {
|
||||
(req as OneUptimeRequest).userType = UserType.API;
|
||||
// TODO: Add API key permissions.
|
||||
// (req as OneUptimeRequest).permissions =
|
||||
// apiKeyModel.permissions || [];
|
||||
(req as OneUptimeRequest).tenantId = tenantId;
|
||||
(req as OneUptimeRequest).userGlobalAccessPermission =
|
||||
await AccessTokenService.getDefaultApiGlobalPermission(
|
||||
tenantId
|
||||
);
|
||||
|
||||
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
||||
await AccessTokenService.getApiTenantAccessPermission(
|
||||
tenantId,
|
||||
apiKeyModel.id!
|
||||
);
|
||||
|
||||
if (userTenantAccessPermission) {
|
||||
(req as OneUptimeRequest).userTenantAccessPermission = {};
|
||||
(
|
||||
(req as OneUptimeRequest)
|
||||
.userTenantAccessPermission as Dictionary<UserTenantAccessPermission>
|
||||
)[tenantId.toString()] = userTenantAccessPermission;
|
||||
|
||||
return next();
|
||||
if (tenantId) {
|
||||
(req as OneUptimeRequest).tenantId = tenantId;
|
||||
}
|
||||
}
|
||||
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('Invalid Project ID or API Key')
|
||||
);
|
||||
if (!apiKey) {
|
||||
throw new BadDataException('ApiKey not found in the request');
|
||||
}
|
||||
|
||||
let apiKeyModel: ApiKey | null = null;
|
||||
|
||||
if (tenantId) {
|
||||
apiKeyModel = await ApiKeyService.findOneBy({
|
||||
query: {
|
||||
projectId: tenantId,
|
||||
apiKey: apiKey,
|
||||
expiresAt: QueryHelper.greaterThan(
|
||||
OneUptimeDate.getCurrentDate()
|
||||
),
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (apiKeyModel) {
|
||||
(req as OneUptimeRequest).userType = UserType.API;
|
||||
// TODO: Add API key permissions.
|
||||
// (req as OneUptimeRequest).permissions =
|
||||
// apiKeyModel.permissions || [];
|
||||
(req as OneUptimeRequest).userGlobalAccessPermission =
|
||||
await AccessTokenService.getDefaultApiGlobalPermission(
|
||||
tenantId
|
||||
);
|
||||
|
||||
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
||||
await AccessTokenService.getApiTenantAccessPermission(
|
||||
tenantId,
|
||||
apiKeyModel.id!
|
||||
);
|
||||
|
||||
if (userTenantAccessPermission) {
|
||||
(req as OneUptimeRequest).userTenantAccessPermission =
|
||||
{};
|
||||
(
|
||||
(req as OneUptimeRequest)
|
||||
.userTenantAccessPermission as Dictionary<UserTenantAccessPermission>
|
||||
)[tenantId.toString()] = userTenantAccessPermission;
|
||||
|
||||
return next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!apiKeyModel) {
|
||||
// check master key.
|
||||
const masterKeyGlobalConfig: GlobalConfig | null =
|
||||
await GlobalConfigService.findOneBy({
|
||||
query: {
|
||||
_id: ObjectID.getZeroObjectID().toString(),
|
||||
isMasterApiKeyEnabled: true,
|
||||
masterApiKey: apiKey,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (masterKeyGlobalConfig) {
|
||||
(req as OneUptimeRequest).userType = UserType.MasterAdmin;
|
||||
|
||||
// get master admin user
|
||||
|
||||
const user: User | null = await UserService.findOneBy({
|
||||
query: {
|
||||
isMasterAdmin: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new BadDataException(
|
||||
'Master Admin user not found. Please make sure you have created a master admin user.'
|
||||
);
|
||||
}
|
||||
|
||||
(req as OneUptimeRequest).userAuthorization = {
|
||||
userId: user.id!,
|
||||
isMasterAdmin: true,
|
||||
email: user.email!,
|
||||
name: user.name!,
|
||||
};
|
||||
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
if (!tenantId) {
|
||||
throw new BadDataException(
|
||||
'ProjectID not found in the request header.'
|
||||
);
|
||||
}
|
||||
|
||||
throw new BadDataException('Invalid Project ID or API Key');
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,40 @@ export class AccessTokenService extends BaseService {
|
||||
};
|
||||
}
|
||||
|
||||
public async getMasterKeyApiGlobalPermission(
|
||||
projectId: ObjectID
|
||||
): Promise<UserGlobalAccessPermission> {
|
||||
return {
|
||||
projectIds: [projectId],
|
||||
globalPermissions: [
|
||||
Permission.Public,
|
||||
Permission.User,
|
||||
Permission.CurrentUser,
|
||||
Permission.ProjectOwner,
|
||||
],
|
||||
_type: 'UserGlobalAccessPermission',
|
||||
};
|
||||
}
|
||||
|
||||
public async getMasterApiTenantAccessPermission(
|
||||
projectId: ObjectID
|
||||
): Promise<UserTenantAccessPermission> {
|
||||
const userPermissions: Array<UserPermission> = [];
|
||||
|
||||
userPermissions.push({
|
||||
permission: Permission.ProjectOwner,
|
||||
labelIds: [],
|
||||
_type: 'UserPermission',
|
||||
});
|
||||
|
||||
const permission: UserTenantAccessPermission =
|
||||
this.getDefaultUserTenantAccessPermission(projectId);
|
||||
|
||||
permission.permissions = permission.permissions.concat(userPermissions);
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
public async getApiTenantAccessPermission(
|
||||
projectId: ObjectID,
|
||||
apiKeyId: ObjectID
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import '../TestingUtils/Init';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import ProjectMiddleware from '../../Middleware/ProjectAuthorization';
|
||||
import {
|
||||
@@ -6,13 +7,14 @@ import {
|
||||
NextFunction,
|
||||
} from '../../Utils/Express';
|
||||
import ApiKeyService from '../../Services/ApiKeyService';
|
||||
import Response from '../../Utils/Response';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import OneUptimeDate from 'Common/Types/Date';
|
||||
import QueryHelper from '../../Types/Database/QueryHelper';
|
||||
import ApiKey from 'Model/Models/ApiKey';
|
||||
import AccessTokenService from '../../Services/AccessTokenService';
|
||||
import { UserTenantAccessPermission } from 'Common/Types/Permission';
|
||||
import Database from '../TestingUtils/Database';
|
||||
import GlobalConfigService from '../../Services/GlobalConfigService';
|
||||
|
||||
jest.mock('../../Services/ApiKeyService');
|
||||
jest.mock('../../Services/AccessTokenService');
|
||||
@@ -97,110 +99,123 @@ describe('ProjectMiddleware', () => {
|
||||
const req: ExpressRequest = { headers: {} } as ExpressRequest;
|
||||
|
||||
test('should return true when getApiKey returns a non-null value', () => {
|
||||
const spyGetApiKey: jest.SpyInstance = jest
|
||||
.spyOn(ProjectMiddleware, 'getApiKey')
|
||||
.mockReturnValue(mockedObjectId);
|
||||
req.headers['apikey'] = mockedObjectId.toString();
|
||||
|
||||
const result: boolean = ProjectMiddleware.hasApiKey(req);
|
||||
|
||||
expect(result).toStrictEqual(true);
|
||||
expect(spyGetApiKey).toHaveBeenCalledWith(req);
|
||||
});
|
||||
|
||||
test('should return false when getApiKey returns null', () => {
|
||||
const spyGetApiKey: jest.SpyInstance = jest
|
||||
.spyOn(ProjectMiddleware, 'getApiKey')
|
||||
.mockReturnValue(null);
|
||||
req.headers['apikey'] = undefined;
|
||||
|
||||
const result: boolean = ProjectMiddleware.hasApiKey(req);
|
||||
|
||||
expect(result).toStrictEqual(false);
|
||||
expect(spyGetApiKey).toHaveBeenCalledWith(req);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasProjectID', () => {
|
||||
const req: ExpressRequest = { headers: {} } as ExpressRequest;
|
||||
test('should return true when getProjectId returns a non-null value', () => {
|
||||
const spyGetProjectId: jest.SpyInstance = jest
|
||||
.spyOn(ProjectMiddleware, 'getProjectId')
|
||||
.mockReturnValue(mockedObjectId);
|
||||
req.headers['tenantid'] = mockedObjectId.toString();
|
||||
|
||||
const result: boolean = ProjectMiddleware.hasProjectID(req);
|
||||
|
||||
expect(result).toStrictEqual(true);
|
||||
expect(spyGetProjectId).toHaveBeenCalledWith(req);
|
||||
});
|
||||
|
||||
test('should return false when getProjectId returns null', () => {
|
||||
const spyGetProjectId: jest.SpyInstance = jest
|
||||
.spyOn(ProjectMiddleware, 'getProjectId')
|
||||
.mockReturnValue(null);
|
||||
req.headers['tenantid'] = undefined;
|
||||
|
||||
const result: boolean = ProjectMiddleware.hasProjectID(req);
|
||||
|
||||
expect(result).toStrictEqual(false);
|
||||
expect(spyGetProjectId).toHaveBeenCalledWith(req);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isValidProjectIdAndApiKeyMiddleware', () => {
|
||||
const req: ExpressRequest = {} as ExpressRequest;
|
||||
const res: ExpressResponse = {} as ExpressResponse;
|
||||
const next: NextFunction = jest.fn();
|
||||
let next: NextFunction = jest.fn();
|
||||
|
||||
const mockedApiModel: ApiKey = {
|
||||
id: mockedObjectId,
|
||||
} as ApiKey;
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(ProjectMiddleware, 'getProjectId').mockReturnValue(
|
||||
mockedObjectId
|
||||
);
|
||||
jest.spyOn(ProjectMiddleware, 'getApiKey').mockReturnValue(
|
||||
mockedObjectId
|
||||
);
|
||||
let database!: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
next = jest.fn();
|
||||
database = new Database();
|
||||
await database.createAndConnect();
|
||||
|
||||
if (req.headers === undefined) {
|
||||
req.headers = {};
|
||||
}
|
||||
|
||||
req.headers['tenantid'] = mockedObjectId.toString();
|
||||
req.headers['apikey'] = mockedObjectId.toString();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await database.disconnectAndDropDatabase();
|
||||
});
|
||||
|
||||
test('should throw BadDataException when getProjectId returns null', async () => {
|
||||
const spyGetProjectId: jest.SpyInstance = jest
|
||||
.spyOn(ProjectMiddleware, 'getProjectId')
|
||||
.mockReturnValueOnce(null);
|
||||
const spyFindOneBy: jest.SpyInstance = jest
|
||||
.spyOn(GlobalConfigService, 'findOneBy')
|
||||
.mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
ProjectMiddleware.isValidProjectIdAndApiKeyMiddleware(
|
||||
req,
|
||||
res,
|
||||
next
|
||||
req.headers['tenantid'] = undefined;
|
||||
req.headers['apikey'] = mockedObjectId.toString();
|
||||
|
||||
await ProjectMiddleware.isValidProjectIdAndApiKeyMiddleware(
|
||||
req,
|
||||
res,
|
||||
next
|
||||
);
|
||||
|
||||
expect(spyFindOneBy).toHaveBeenCalledWith({
|
||||
query: {
|
||||
_id: ObjectID.getZeroObjectID().toString(),
|
||||
isMasterApiKeyEnabled: true,
|
||||
masterApiKey: mockedObjectId,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
new BadDataException(
|
||||
'ProjectID not found in the request header.'
|
||||
)
|
||||
).rejects.toThrowError('ProjectId not found in the request');
|
||||
|
||||
expect(spyGetProjectId).toHaveBeenCalledWith(req);
|
||||
);
|
||||
});
|
||||
|
||||
test('should throw BadDataException when getApiKey returns null', async () => {
|
||||
const spyGetApiKey: jest.SpyInstance = jest
|
||||
.spyOn(ProjectMiddleware, 'getApiKey')
|
||||
.mockReturnValueOnce(null);
|
||||
req.headers['apikey'] = undefined;
|
||||
|
||||
await expect(
|
||||
ProjectMiddleware.isValidProjectIdAndApiKeyMiddleware(
|
||||
req,
|
||||
res,
|
||||
next
|
||||
)
|
||||
).rejects.toThrowError('ApiKey not found in the request');
|
||||
await ProjectMiddleware.isValidProjectIdAndApiKeyMiddleware(
|
||||
req,
|
||||
res,
|
||||
next
|
||||
);
|
||||
|
||||
expect(spyGetApiKey).toHaveBeenCalledWith(req);
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
new BadDataException('ApiKey not found in the request')
|
||||
);
|
||||
});
|
||||
|
||||
test('should call Response.sendErrorResponse when apiKeyModel is null', async () => {
|
||||
const spyFindOneBy: jest.SpyInstance = jest
|
||||
.spyOn(ApiKeyService, 'findOneBy')
|
||||
.mockResolvedValue(null);
|
||||
const spySendErrorResponse: jest.SpyInstance = jest
|
||||
.spyOn(Response, 'sendErrorResponse')
|
||||
.mockImplementation(jest.fn);
|
||||
|
||||
jest.spyOn(QueryHelper, 'greaterThan').mockImplementation(
|
||||
jest.fn()
|
||||
@@ -226,18 +241,12 @@ describe('ProjectMiddleware', () => {
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
expect(spySendErrorResponse).toHaveBeenCalledWith(
|
||||
req,
|
||||
res,
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
new BadDataException('Invalid Project ID or API Key')
|
||||
);
|
||||
});
|
||||
|
||||
test('should call Response.sendErrorResponse when apiKeyModel is not null but getApiTenantAccessPermission returned null', async () => {
|
||||
const spySendErrorResponse: jest.SpyInstance = jest
|
||||
.spyOn(Response, 'sendErrorResponse')
|
||||
.mockImplementation(jest.fn);
|
||||
|
||||
jest.spyOn(ApiKeyService, 'findOneBy').mockResolvedValue(
|
||||
mockedApiModel
|
||||
);
|
||||
@@ -252,9 +261,8 @@ describe('ProjectMiddleware', () => {
|
||||
);
|
||||
|
||||
expect(spyGetApiTenantAccessPermission).toHaveBeenCalled();
|
||||
expect(spySendErrorResponse).toHaveBeenCalledWith(
|
||||
req,
|
||||
res,
|
||||
// check first param of next
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
new BadDataException('Invalid Project ID or API Key')
|
||||
);
|
||||
});
|
||||
|
||||
@@ -54,6 +54,14 @@ export default class ModelPermission {
|
||||
query: Query<TBaseModel>,
|
||||
props: DatabaseCommonInteractionProps
|
||||
): Promise<Query<TBaseModel>> {
|
||||
if (props.isRoot) {
|
||||
query = await this.addTenantScopeToQueryAsRoot(
|
||||
modelType,
|
||||
query,
|
||||
props
|
||||
);
|
||||
}
|
||||
|
||||
if (!props.isRoot) {
|
||||
this.checkModelLevelPermissions(
|
||||
modelType,
|
||||
@@ -265,6 +273,14 @@ export default class ModelPermission {
|
||||
): Promise<CheckReadPermissionType<TBaseModel>> {
|
||||
const model: BaseModel = new modelType();
|
||||
|
||||
if (props.isRoot) {
|
||||
query = await this.addTenantScopeToQueryAsRoot(
|
||||
modelType,
|
||||
query,
|
||||
props
|
||||
);
|
||||
}
|
||||
|
||||
if (!props.isRoot) {
|
||||
//check if the user is logged in.
|
||||
this.checkIfUserIsLoggedIn(
|
||||
@@ -804,6 +820,25 @@ export default class ModelPermission {
|
||||
}
|
||||
}
|
||||
|
||||
private static async addTenantScopeToQueryAsRoot<
|
||||
TBaseModel extends BaseModel
|
||||
>(
|
||||
modelType: { new (): TBaseModel },
|
||||
query: Query<TBaseModel>,
|
||||
props: DatabaseCommonInteractionProps
|
||||
): Promise<Query<TBaseModel>> {
|
||||
const model: BaseModel = new modelType();
|
||||
|
||||
const tenantColumn: string | null = model.getTenantColumn();
|
||||
|
||||
// If this model has a tenantColumn, and request has tenantId, and is multiTenantQuery null then add tenantId to query.
|
||||
if (tenantColumn && props.tenantId && !props.isMultiTenantRequest) {
|
||||
(query as any)[tenantColumn] = props.tenantId;
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
private static async addTenantScopeToQuery<TBaseModel extends BaseModel>(
|
||||
modelType: { new (): TBaseModel },
|
||||
query: Query<TBaseModel>,
|
||||
|
||||
@@ -17,6 +17,7 @@ import JSONFunctions from 'Common/Types/JSONFunctions';
|
||||
import FileModel from 'Common/Models/FileModel';
|
||||
import Dictionary from 'Common/Types/Dictionary';
|
||||
import StatusCode from 'Common/Types/API/StatusCode';
|
||||
import { DEFAULT_LIMIT } from 'Common/Types/Database/LimitMax';
|
||||
|
||||
export default class Response {
|
||||
private static logResponse(
|
||||
@@ -276,6 +277,8 @@ export default class Response {
|
||||
listData.limit = new PositiveNumber(
|
||||
parseInt(oneUptimeRequest.query['limit'].toString())
|
||||
);
|
||||
} else {
|
||||
listData.limit = new PositiveNumber(DEFAULT_LIMIT);
|
||||
}
|
||||
|
||||
if (oneUptimeRequest.query['output-type'] === 'csv') {
|
||||
|
||||
@@ -28,7 +28,7 @@ import Response from './Response';
|
||||
import JSONFunctions from 'Common/Types/JSONFunctions';
|
||||
import API from 'Common/Utils/API';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
import { DashboardApiHostname } from '../EnvironmentConfig';
|
||||
import { AppVersion, DashboardApiHostname } from '../EnvironmentConfig';
|
||||
import { DashboardApiRoute } from 'Common/ServiceRoute';
|
||||
import HTTPResponse from 'Common/Types/API/HTTPResponse';
|
||||
import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse';
|
||||
@@ -95,8 +95,8 @@ app.use(setDefaultHeaders);
|
||||
* https://stackoverflow.com/questions/19917401/error-request-entity-too-large
|
||||
*/
|
||||
|
||||
app.use(ExpressJson({ limit: '50mb' }));
|
||||
app.use(ExpressUrlEncoded({ limit: '50mb' }));
|
||||
app.use(ExpressJson({ limit: '50mb', extended: true }));
|
||||
app.use(ExpressUrlEncoded({ limit: '50mb', extended: true }));
|
||||
|
||||
app.use(logRequest);
|
||||
|
||||
@@ -105,6 +105,8 @@ const init: Function = async (
|
||||
port?: Port,
|
||||
isFrontendApp?: boolean
|
||||
): Promise<ExpressApplication> => {
|
||||
logger.info(`App Version: ${AppVersion.toString()}`);
|
||||
|
||||
await Express.launchApplication(appName, port);
|
||||
LocalCache.setString('app', 'name', appName);
|
||||
CommonAPI(appName);
|
||||
|
||||
4
CommonServer/package-lock.json
generated
4
CommonServer/package-lock.json
generated
@@ -73,7 +73,7 @@
|
||||
"moment-timezone": "^0.5.40",
|
||||
"nanoid": "^3.3.2",
|
||||
"nanoid-dictionary": "^4.3.0",
|
||||
"posthog-js": "^1.37.0",
|
||||
"posthog-js": "^1.77.0",
|
||||
"process": "^0.11.10",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"slugify": "^1.6.5",
|
||||
@@ -81,7 +81,7 @@
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^6.3.1",
|
||||
"@faker-js/faker": "^8.0.2",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^17.0.22",
|
||||
"jest": "^27.5.1",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"compile": "tsc",
|
||||
"test": "jest --detectOpenHandles",
|
||||
"debug:test": "node --inspect node_modules/.bin/jest --runInBand ./Tests --detectOpenHandles"
|
||||
"debug:test": "cd .. && export $(grep -v '^#' config.env | xargs) && cd CommonServer && node --inspect node_modules/.bin/jest --runInBand ./Tests --detectOpenHandles"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -18,6 +18,8 @@ import Field, { FormFieldStyleType } from '../Types/Field';
|
||||
import FieldLabelElement from '../Fields/FieldLabel';
|
||||
import FormValues from '../Types/FormValues';
|
||||
import { JSONValue } from 'Common/Types/JSON';
|
||||
import IDGenerator from '../../ObjectID/IDGenerator';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
|
||||
export interface ComponentProps<T extends Object> {
|
||||
field: Field<T>;
|
||||
@@ -167,6 +169,35 @@ const FormField: <T extends Object>(
|
||||
/>
|
||||
)}
|
||||
|
||||
{props.field.fieldType === FormFieldSchemaType.ObjectID && (
|
||||
<IDGenerator
|
||||
tabIndex={index}
|
||||
disabled={props.isDisabled || props.field.disabled}
|
||||
error={
|
||||
props.touched && props.error
|
||||
? props.error
|
||||
: undefined
|
||||
}
|
||||
dataTestId={fieldType}
|
||||
onChange={(value: ObjectID) => {
|
||||
props.field.onChange &&
|
||||
props.field.onChange(value);
|
||||
props.setFieldValue(props.fieldName, value);
|
||||
}}
|
||||
onEnterPress={() => {
|
||||
props.submitForm && props.submitForm();
|
||||
}}
|
||||
initialValue={
|
||||
props.currentValues &&
|
||||
(props.currentValues as any)[props.fieldName]
|
||||
? (props.currentValues as any)[
|
||||
props.fieldName
|
||||
]
|
||||
: props.field.defaultValue || null
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{props.field.fieldType ===
|
||||
FormFieldSchemaType.RadioButton && (
|
||||
<RadioButtons
|
||||
|
||||
@@ -1197,30 +1197,47 @@ const ModelTable: <TBaseModel extends BaseModel>(
|
||||
): ReactElement => {
|
||||
const plan: PlanSelect | null = ProjectUtil.getCurrentPlan();
|
||||
|
||||
let showPlan: boolean = Boolean(
|
||||
BILLING_ENABLED &&
|
||||
plan &&
|
||||
new props.modelType().readBillingPlan &&
|
||||
!SubscriptionPlan.isFeatureAccessibleOnCurrentPlan(
|
||||
new props.modelType().readBillingPlan!,
|
||||
plan,
|
||||
getAllEnvVars()
|
||||
)
|
||||
);
|
||||
|
||||
let planName: string = new props.modelType().readBillingPlan!;
|
||||
|
||||
if (props.isCreateable && !showPlan) {
|
||||
// if createable then read create billing permissions.
|
||||
showPlan = Boolean(
|
||||
BILLING_ENABLED &&
|
||||
plan &&
|
||||
new props.modelType().createBillingPlan &&
|
||||
!SubscriptionPlan.isFeatureAccessibleOnCurrentPlan(
|
||||
new props.modelType().createBillingPlan!,
|
||||
plan,
|
||||
getAllEnvVars()
|
||||
)
|
||||
);
|
||||
|
||||
planName = new props.modelType().createBillingPlan!;
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
{title}
|
||||
{BILLING_ENABLED &&
|
||||
plan &&
|
||||
new props.modelType().readBillingPlan &&
|
||||
!SubscriptionPlan.isFeatureAccessibleOnCurrentPlan(
|
||||
new props.modelType().readBillingPlan!,
|
||||
plan,
|
||||
getAllEnvVars()
|
||||
) && (
|
||||
<span
|
||||
style={{
|
||||
marginLeft: '5px',
|
||||
}}
|
||||
>
|
||||
<Pill
|
||||
text={`${
|
||||
new props.modelType().readBillingPlan
|
||||
} Plan`}
|
||||
color={Yellow}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
{showPlan && (
|
||||
<span
|
||||
style={{
|
||||
marginLeft: '5px',
|
||||
}}
|
||||
>
|
||||
<Pill text={`${planName} Plan`} color={Yellow} />
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
89
CommonUI/src/Components/ObjectID/IDGenerator.tsx
Normal file
89
CommonUI/src/Components/ObjectID/IDGenerator.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import React, {
|
||||
FunctionComponent,
|
||||
ReactElement,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import Input from '../Input/Input';
|
||||
import Button, { ButtonStyleType } from '../Button/Button';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import IconProp from 'Common/Types/Icon/IconProp';
|
||||
|
||||
export interface ComponentProps {
|
||||
readonly?: boolean | undefined;
|
||||
initialValue?: undefined | ObjectID;
|
||||
onChange?: undefined | ((value: ObjectID) => void);
|
||||
value?: ObjectID | undefined;
|
||||
disabled?: boolean | undefined;
|
||||
dataTestId?: string | undefined;
|
||||
tabIndex?: number | undefined;
|
||||
onEnterPress?: (() => void) | undefined;
|
||||
error?: string | undefined;
|
||||
}
|
||||
|
||||
const IDGenerator: FunctionComponent<ComponentProps> = (
|
||||
props: ComponentProps
|
||||
): ReactElement => {
|
||||
const [value, setValue] = useState<ObjectID | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.initialValue) {
|
||||
setValue(props.initialValue);
|
||||
}
|
||||
|
||||
if (props.value) {
|
||||
setValue(props.value);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.initialValue) {
|
||||
setValue(props.initialValue);
|
||||
}
|
||||
}, [props.initialValue]);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(props.value ? props.value : props.initialValue || null);
|
||||
}, [props.value]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<>
|
||||
<div className="flex" data-testid={props.dataTestId}>
|
||||
{value && (
|
||||
<Input
|
||||
readOnly={props.readonly}
|
||||
tabIndex={props.tabIndex}
|
||||
onEnterPress={props.onEnterPress}
|
||||
value={value.toString()}
|
||||
/>
|
||||
)}
|
||||
<div className="mt-2">
|
||||
<Button
|
||||
icon={IconProp.Refresh}
|
||||
buttonStyle={ButtonStyleType.NORMAL}
|
||||
disabled={props.disabled || props.readonly}
|
||||
title={value ? 'Regenerate' : 'Generate'}
|
||||
onClick={() => {
|
||||
const generatedID: ObjectID =
|
||||
ObjectID.generate();
|
||||
setValue(generatedID);
|
||||
props.onChange && props.onChange(generatedID);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
{props.error && (
|
||||
<p
|
||||
data-testid="error-message"
|
||||
className="mt-1 text-sm text-red-400"
|
||||
>
|
||||
{props.error}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default IDGenerator;
|
||||
@@ -22,11 +22,13 @@ import SubscriptionPlan from 'Common/Types/Billing/SubscriptionPlan';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
|
||||
export const getAllEnvVars: Function = (): JSONObject => {
|
||||
return window?.process?.env || process?.env || {};
|
||||
const envVars: JSONObject = window?.process?.env || process?.env || {};
|
||||
return envVars;
|
||||
};
|
||||
|
||||
export const env: Function = (key: string): string => {
|
||||
return (getAllEnvVars()[key] as string) || '';
|
||||
const allEnv: JSONObject = getAllEnvVars();
|
||||
return (allEnv[key] as string) || '';
|
||||
};
|
||||
|
||||
export const HTTP_PROTOCOL: Protocol =
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { API_DOCS_HOSTNAME, HTTP_PROTOCOL, API_DOCS_ROUTE } from '../../Config';
|
||||
import { API_DOCS_HOSTNAME, HTTP_PROTOCOL } from '../../Config';
|
||||
import API from 'Common/Utils/API';
|
||||
import { ApiReferenceRoute } from 'Common/ServiceRoute';
|
||||
|
||||
class HelmAPI extends API {
|
||||
class ApiDocsRoute extends API {
|
||||
public constructor() {
|
||||
super(HTTP_PROTOCOL, API_DOCS_HOSTNAME, API_DOCS_ROUTE);
|
||||
super(HTTP_PROTOCOL, API_DOCS_HOSTNAME, ApiReferenceRoute);
|
||||
}
|
||||
}
|
||||
|
||||
export default new HelmAPI();
|
||||
export default new ApiDocsRoute();
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
#
|
||||
|
||||
# Pull base image nodejs image.
|
||||
FROM node:current-alpine
|
||||
FROM node:current-alpine AS base
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
@@ -24,7 +27,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN mkdir /usr/src
|
||||
|
||||
# Install common
|
||||
RUN mkdir /usr/src/Common
|
||||
|
||||
FROM base AS common
|
||||
WORKDIR /usr/src/Common
|
||||
COPY ./Common/package*.json /usr/src/Common/
|
||||
RUN npm install
|
||||
@@ -32,7 +36,8 @@ COPY ./Common /usr/src/Common
|
||||
|
||||
|
||||
# Install Model
|
||||
RUN mkdir /usr/src/Model
|
||||
|
||||
FROM base AS model
|
||||
WORKDIR /usr/src/Model
|
||||
COPY ./Model/package*.json /usr/src/Model/
|
||||
RUN npm install
|
||||
@@ -41,7 +46,8 @@ COPY ./Model /usr/src/Model
|
||||
|
||||
|
||||
# Install CommonServer
|
||||
RUN mkdir /usr/src/CommonServer
|
||||
|
||||
FROM base AS commonserver
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY ./CommonServer/package*.json /usr/src/CommonServer/
|
||||
RUN npm install
|
||||
@@ -51,7 +57,8 @@ COPY ./CommonServer /usr/src/CommonServer
|
||||
|
||||
|
||||
# Install CommonUI
|
||||
RUN mkdir /usr/src/CommonUI
|
||||
|
||||
FROM base AS commonui
|
||||
WORKDIR /usr/src/CommonUI
|
||||
COPY ./CommonUI/package*.json /usr/src/CommonUI/
|
||||
RUN npm install --force
|
||||
@@ -59,11 +66,24 @@ COPY ./CommonUI /usr/src/CommonUI
|
||||
|
||||
|
||||
#SET ENV Variables
|
||||
# Install app
|
||||
FROM base AS app
|
||||
|
||||
WORKDIR /usr/src/Common
|
||||
COPY --from=common /usr/src/Common .
|
||||
|
||||
WORKDIR /usr/src/Model
|
||||
COPY --from=model /usr/src/Model .
|
||||
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY --from=commonserver /usr/src/CommonServer .
|
||||
|
||||
WORKDIR /usr/src/CommonUI
|
||||
COPY --from=commonui /usr/src/CommonUI .
|
||||
|
||||
ENV PRODUCTION=true
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
|
||||
RUN mkdir /usr/src/app
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install app dependencies
|
||||
|
||||
@@ -394,7 +394,7 @@ const Settings: FunctionComponent<ComponentProps> = (
|
||||
|
||||
{reseller && (
|
||||
<Card
|
||||
title={`You have purchased this project from ${reseller.name}`}
|
||||
title={`You have purchased this plan from ${reseller.name}`}
|
||||
description={`If you would like to change the plan, please contact ${reseller.name} at ${reseller.description}`}
|
||||
buttons={
|
||||
reseller.changePlanLink
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
#
|
||||
|
||||
# Pull base image nodejs image.
|
||||
FROM node:current-alpine
|
||||
FROM node:current-alpine AS base
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
@@ -28,7 +31,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN mkdir /usr/src
|
||||
|
||||
# Install common
|
||||
RUN mkdir /usr/src/Common
|
||||
|
||||
FROM base AS common
|
||||
WORKDIR /usr/src/Common
|
||||
COPY ./Common/package*.json /usr/src/Common/
|
||||
RUN npm install
|
||||
@@ -36,7 +40,8 @@ COPY ./Common /usr/src/Common
|
||||
|
||||
|
||||
# Install Model
|
||||
RUN mkdir /usr/src/Model
|
||||
|
||||
FROM base AS model
|
||||
WORKDIR /usr/src/Model
|
||||
COPY ./Model/package*.json /usr/src/Model/
|
||||
RUN npm install
|
||||
@@ -45,7 +50,8 @@ COPY ./Model /usr/src/Model
|
||||
|
||||
|
||||
# Install CommonServer
|
||||
RUN mkdir /usr/src/CommonServer
|
||||
|
||||
FROM base AS commonserver
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY ./CommonServer/package*.json /usr/src/CommonServer/
|
||||
RUN npm install
|
||||
@@ -54,9 +60,19 @@ COPY ./CommonServer /usr/src/CommonServer
|
||||
|
||||
|
||||
#SET ENV Variables
|
||||
ENV PRODUCTION=true
|
||||
# Install app
|
||||
FROM base AS app
|
||||
|
||||
RUN mkdir /usr/src/app
|
||||
WORKDIR /usr/src/Common
|
||||
COPY --from=common /usr/src/Common .
|
||||
|
||||
WORKDIR /usr/src/Model
|
||||
COPY --from=model /usr/src/Model .
|
||||
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY --from=commonserver /usr/src/CommonServer .
|
||||
|
||||
ENV PRODUCTION=true
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
#
|
||||
|
||||
# Pull base image nodejs image.
|
||||
FROM node:current-alpine
|
||||
FROM node:current-alpine AS base
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
@@ -28,7 +32,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN mkdir /usr/src
|
||||
|
||||
# Install common
|
||||
RUN mkdir /usr/src/Common
|
||||
|
||||
FROM base AS common
|
||||
WORKDIR /usr/src/Common
|
||||
COPY ./Common/package*.json /usr/src/Common/
|
||||
RUN npm install
|
||||
@@ -36,7 +41,8 @@ COPY ./Common /usr/src/Common
|
||||
|
||||
|
||||
# Install Model
|
||||
RUN mkdir /usr/src/Model
|
||||
|
||||
FROM base AS model
|
||||
WORKDIR /usr/src/Model
|
||||
COPY ./Model/package*.json /usr/src/Model/
|
||||
RUN npm install
|
||||
@@ -45,19 +51,28 @@ COPY ./Model /usr/src/Model
|
||||
|
||||
|
||||
# Install CommonServer
|
||||
RUN mkdir /usr/src/CommonServer
|
||||
|
||||
FROM base AS commonserver
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY ./CommonServer/package*.json /usr/src/CommonServer/
|
||||
RUN npm install
|
||||
COPY ./CommonServer /usr/src/CommonServer
|
||||
|
||||
|
||||
# Install app
|
||||
FROM base AS app
|
||||
|
||||
WORKDIR /usr/src/Common
|
||||
COPY --from=common /usr/src/Common .
|
||||
|
||||
WORKDIR /usr/src/Model
|
||||
COPY --from=model /usr/src/Model .
|
||||
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY --from=commonserver /usr/src/CommonServer .
|
||||
|
||||
#SET ENV Variables
|
||||
ENV PRODUCTION=true
|
||||
|
||||
RUN mkdir /usr/src/app
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install app dependencies
|
||||
|
||||
@@ -2,6 +2,9 @@ FROM node:18.13.0-alpine
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
# Pull base image nodejs image.
|
||||
FROM node:current-alpine
|
||||
FROM node:current-alpine AS base
|
||||
USER root
|
||||
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
|
||||
|
||||
RUN npm config set fetch-retry-maxtimeout 6000000
|
||||
RUN npm config set fetch-retry-mintimeout 1000000
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG APP_VERSION
|
||||
|
||||
@@ -20,7 +23,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN mkdir /usr/src
|
||||
|
||||
# Install common
|
||||
RUN mkdir /usr/src/Common
|
||||
|
||||
FROM base AS common
|
||||
WORKDIR /usr/src/Common
|
||||
COPY ./Common/package*.json /usr/src/Common/
|
||||
RUN npm install
|
||||
@@ -28,7 +32,8 @@ COPY ./Common /usr/src/Common
|
||||
|
||||
|
||||
# Install Model
|
||||
RUN mkdir /usr/src/Model
|
||||
|
||||
FROM base AS model
|
||||
WORKDIR /usr/src/Model
|
||||
COPY ./Model/package*.json /usr/src/Model/
|
||||
RUN npm install
|
||||
@@ -37,7 +42,8 @@ COPY ./Model /usr/src/Model
|
||||
|
||||
|
||||
# Install CommonServer
|
||||
RUN mkdir /usr/src/CommonServer
|
||||
|
||||
FROM base AS commonserver
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY ./CommonServer/package*.json /usr/src/CommonServer/
|
||||
RUN npm install
|
||||
@@ -45,7 +51,21 @@ COPY ./CommonServer /usr/src/CommonServer
|
||||
|
||||
|
||||
|
||||
RUN mkdir /usr/src/app
|
||||
# Install app
|
||||
FROM base AS app
|
||||
|
||||
WORKDIR /usr/src/Common
|
||||
COPY --from=common /usr/src/Common .
|
||||
|
||||
WORKDIR /usr/src/Model
|
||||
COPY --from=model /usr/src/Model .
|
||||
|
||||
WORKDIR /usr/src/CommonServer
|
||||
COPY --from=commonserver /usr/src/CommonServer .
|
||||
|
||||
|
||||
ENV PRODUCTION=true
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
apiVersion: v1
|
||||
entries:
|
||||
OneUptime:
|
||||
- apiVersion: v2
|
||||
created: "2021-09-10T14:13:26.551683+01:00"
|
||||
dependencies:
|
||||
- name: nginx-ingress-controller
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: 6.0.1
|
||||
- name: redis
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: 14.8.8
|
||||
description: One complete DevOps and DevOps platform.
|
||||
digest: 84b0d954025bc9d98419d3f7d4ee9e4470db717297e4fc1aaa546af75b16a96a
|
||||
home: https://oneuptime.com
|
||||
icon: https://oneuptime.com/img/ou-bb.svg
|
||||
keywords:
|
||||
- DevOps
|
||||
- IT DevOps
|
||||
- DevOps
|
||||
- Monitoring
|
||||
- Status Page
|
||||
- On-Call
|
||||
- On-Call Management
|
||||
- Incident Management
|
||||
- Performance Monitoring
|
||||
- API Test
|
||||
- Website Monitoring
|
||||
- Website Test
|
||||
- SRE
|
||||
maintainers:
|
||||
- email: support@oneuptime.com
|
||||
name: OneUptime Support
|
||||
url: https://oneuptime.com/support
|
||||
name: OneUptime
|
||||
urls:
|
||||
- OneUptime-4.0.0.tgz
|
||||
version: 4.0.0
|
||||
generated: "2021-09-10T14:13:26.53643+01:00"
|
||||
1
HelmChart/public/oneuptime-deprecated/.helmignore
Normal file
1
HelmChart/public/oneuptime-deprecated/.helmignore
Normal file
@@ -0,0 +1 @@
|
||||
.git
|
||||
33
HelmChart/public/oneuptime-deprecated/Chart.yaml
Normal file
33
HelmChart/public/oneuptime-deprecated/Chart.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
apiVersion: v2
|
||||
name: OneUptime
|
||||
version: 4.0.0
|
||||
description: One complete DevOps and DevOps platform.
|
||||
keywords:
|
||||
- DevOps
|
||||
- IT DevOps
|
||||
- DevOps
|
||||
- Monitoring
|
||||
- Status Page
|
||||
- On-Call
|
||||
- On-Call Management
|
||||
- Incident Management
|
||||
- Performance Monitoring
|
||||
- API Test
|
||||
- Website Monitoring
|
||||
- Website Test
|
||||
- SRE
|
||||
home: https://oneuptime.com
|
||||
dependencies:
|
||||
# https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx
|
||||
- name: nginx-ingress-controller
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: "6.0.1"
|
||||
- name: redis
|
||||
version: "10.5.11"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
maintainers:
|
||||
- name: OneUptime Support
|
||||
email: support@oneuptime.com
|
||||
url: https://oneuptime.com/support
|
||||
icon: https://oneuptime.com/img/OneUptime.svg
|
||||
engine: gotplhelm dependency update
|
||||
85
HelmChart/public/oneuptime-deprecated/templates/NOTES.txt
Normal file
85
HelmChart/public/oneuptime-deprecated/templates/NOTES.txt
Normal file
@@ -0,0 +1,85 @@
|
||||
============================================
|
||||
IMPORTANT: After Installation Steps
|
||||
============================================
|
||||
|
||||
** Thank you for installing OneUptime **
|
||||
** Please be patient while the chart is being deployed **
|
||||
** This usually takes few minutes or more **
|
||||
|
||||
To access your OneUptime app from steps below:
|
||||
|
||||
{{- if eq (index .Values "nginx-ingress-controller" "service" "type") "LoadBalancer" }}
|
||||
============================================
|
||||
Make sure external IP's are assigned.
|
||||
============================================
|
||||
|
||||
Please run these commands to get OneUptime URL
|
||||
|
||||
$ kubectl get svc {{ $.Release.Name }}-nginx-ingress-controller --namespace={{ $.Release.Namespace }}
|
||||
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
If the load balancer did not assign an external IP yet (if the IP is still pending).
|
||||
Retry this command after few mins.
|
||||
{{- end}}
|
||||
============================================
|
||||
Sign Up
|
||||
============================================
|
||||
|
||||
{{- if eq (index .Values "nginx-ingress-controller" "service" "type") "LoadBalancer" }}
|
||||
Go to the External IP (generated from step 1) from your browser and sign up a new admin account.
|
||||
{{- else}}
|
||||
Go to the External IP of your server from your browser and sign up a new admin account.
|
||||
{{- end}}
|
||||
This is your master admin account (and not a user account).
|
||||
To create a user account. Please follow steps below.
|
||||
|
||||
============================================
|
||||
Setup Email
|
||||
============================================
|
||||
|
||||
When you're done signing up the admin account. Head over to "Settings" -> "Email"
|
||||
|
||||
Add your SMTP server details here to enable email alerts.
|
||||
|
||||
============================================
|
||||
Setup Twilio
|
||||
============================================
|
||||
|
||||
When you're done signing up the admin account. Head over to "Settings" -> "Call and SMS"
|
||||
|
||||
Add your Twilio Settings here to enable call and SMS alert.
|
||||
|
||||
============================================
|
||||
Create User
|
||||
============================================
|
||||
|
||||
On the Admin Dahboard, go to the "Users" menu and add a new user.
|
||||
Log out of the admin account, and log in with a user account to access User's OneUptime Dashboard.
|
||||
|
||||
{{- if not $.Values.isThirdPartyBilling }}
|
||||
============================================
|
||||
STEP 5: Buy License
|
||||
============================================
|
||||
|
||||
OneUptime which you just installed runs on an evaluation license.
|
||||
Please contact us at sales@oneuptime.com to buy a commercial license.
|
||||
We support companies of all sizes.
|
||||
|
||||
Once you buy the commercial license,
|
||||
you can enter that license key on your admin dashboard.
|
||||
{{- end }}
|
||||
|
||||
============================================
|
||||
Support and Demo
|
||||
============================================
|
||||
|
||||
Demo:
|
||||
If you're looking for a personlized OneUptime demo.
|
||||
Please email us at demo@oneuptime.com to schedule one.
|
||||
|
||||
Support and Help:
|
||||
If you're looking for help with anything,
|
||||
Please email us at support@oneuptime.com and we'll get back to you in less than 1 business day.
|
||||
|
||||
|
||||
Thank you for installing OneUptime!
|
||||
44
HelmChart/public/oneuptime-deprecated/templates/_helpers.tpl
Normal file
44
HelmChart/public/oneuptime-deprecated/templates/_helpers.tpl
Normal file
@@ -0,0 +1,44 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "oneuptime.mongodbConnectionString" -}}
|
||||
{{ printf "mongodb://%s:%s@%s-%s.%s-%s.%s.%s:%s/%s" $.Values.mongo.oneuptimeDbUsername $.Values.mongo.oneuptimeDbPassword $.Release.Name "mongo-standalone-0" $.Release.Name "mongo-standalone" $.Release.Namespace "svc.cluster.local" "27017" $.Values.mongo.databaseName }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.internalSmtpServer" -}}
|
||||
{{ printf "%s-haraka.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.redisHost" -}}
|
||||
{{ printf "%s-redis-master.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.backendHost" -}}
|
||||
{{ printf "%s-backend.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.oneuptimeHost" -}}
|
||||
{{ printf "%s-backend.%s" $.Values.oneuptime.host }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.serverUrl" -}}
|
||||
{{ printf "http://%s-backend.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.probeApiUrl" -}}
|
||||
{{ printf "http://%s-ProbeAPI.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.scriptRunnerUrl" -}}
|
||||
{{ printf "http://%s-script.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.dataIngestorUrl" -}}
|
||||
{{ printf "http://%s-ingestor.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.realtimeUrl" -}}
|
||||
{{ printf "http://%s-realtime.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
126
HelmChart/public/oneuptime-deprecated/templates/ingress.yaml
Normal file
126
HelmChart/public/oneuptime-deprecated/templates/ingress.yaml
Normal file
@@ -0,0 +1,126 @@
|
||||
############----INGRESS---#####################################
|
||||
{{- range $key, $value := $.Values.oneuptime.hosts }}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/part-of: oneuptime
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
meta.helm.sh/release-name: {{ printf "%s" $.Release.Name }}
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: nginx
|
||||
ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/affinity: "cookie"
|
||||
nginx.ingress.kubernetes.io/affinity-mode: "balanced"
|
||||
nginx.ingress.kubernetes.io/session-cookie-change-on-failure: "false"
|
||||
nginx.ingress.kubernetes.io/session-cookie-name: "fi-ingress-cookie"
|
||||
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
|
||||
ingress.kubernetes.io/session-cookie-hash: "sha1"
|
||||
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
|
||||
name: {{ printf "%s-%s-%s" $.Release.Name $key "ingress" }}
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
spec:
|
||||
{{- if $value.tls.enabled }}
|
||||
tls:
|
||||
- hosts:
|
||||
- {{ $value.host }}
|
||||
secretName: {{ printf "%s-%s-%s" $.Release.Name $key "tls" }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- if $value.host }}
|
||||
- host: {{ $value.host }}
|
||||
http:
|
||||
{{- else }}
|
||||
- http:
|
||||
{{- end }}
|
||||
paths:
|
||||
- path: /accounts
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "accounts" }}
|
||||
servicePort: 80
|
||||
- path: /data-ingestor
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "ingestor" }}
|
||||
servicePort: 80
|
||||
- path: /probe-api
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "probe-api" }}
|
||||
servicePort: 80
|
||||
- path: /dashboard
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "dashboard" }}
|
||||
servicePort: 80
|
||||
- path: /admin
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "admin" }}
|
||||
servicePort: 80
|
||||
- path: /api
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "backend" }}
|
||||
servicePort: 80
|
||||
- path: /realtime
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "realtime" }}
|
||||
servicePort: 80
|
||||
- path: /StatusPage
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "status" }}
|
||||
servicePort: 80
|
||||
- path: /haraka
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "haraka" }}
|
||||
servicePort: 80
|
||||
- path: /application
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "app-scan" }}
|
||||
servicePort: 80
|
||||
- path: /container
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "cont-scan" }}
|
||||
servicePort: 80
|
||||
- path: /lighthouse
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "lighthouse" }}
|
||||
servicePort: 80
|
||||
- path: /script
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "script" }}
|
||||
servicePort: 80
|
||||
{{- range $probeKey, $probeValue := $.Values.probes }}
|
||||
- path: {{ printf "/%s" $probeKey }}
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name $probeKey }}
|
||||
servicePort: 80
|
||||
{{- end }}
|
||||
{{- if $.Values.saas.isSaasService }}
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "home" }}
|
||||
servicePort: 80
|
||||
- path: /docs
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "api-reference" }}
|
||||
servicePort: 80
|
||||
- path: /license
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "licensing" }}
|
||||
servicePort: 80
|
||||
- path: /chart
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "helm-chart" }}
|
||||
servicePort: 80
|
||||
{{- else }}
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "accounts" }}
|
||||
servicePort: 80
|
||||
{{- end }}
|
||||
{{- if $.Values.saas.exposeInitScriptContainer }}
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "init-script" }}
|
||||
servicePort: 80
|
||||
{{- end }}
|
||||
---
|
||||
{{- end }}
|
||||
##########################################################################
|
||||
258
HelmChart/public/oneuptime-deprecated/values.yaml
Normal file
258
HelmChart/public/oneuptime-deprecated/values.yaml
Normal file
@@ -0,0 +1,258 @@
|
||||
##################################################################################
|
||||
## Important: If you're implenting this in the enterprise environment, this should always be `false`.
|
||||
## This is for OneUptime SaaS service. This will deploy all the SaaS env vars
|
||||
##################################################################################
|
||||
saas:
|
||||
exposeInitScriptContainer: false
|
||||
isSaasService: false
|
||||
stripe:
|
||||
publicKey: #Stripe public and private key
|
||||
privateKey:
|
||||
slackWebhook:
|
||||
airtable:
|
||||
key: #Airtbale key to store leads.
|
||||
baseId:
|
||||
amplitude:
|
||||
key: #Amplitude for tracking.
|
||||
twitter:
|
||||
bearertoken: # Twitter Bearer Token.
|
||||
licensing:
|
||||
airtable: # Airtable for validating licenses.
|
||||
key:
|
||||
baseId:
|
||||
tokenSecret: # Encrypting lisense with tokens to send them to clients.
|
||||
|
||||
###################################################################################
|
||||
|
||||
statusPage:
|
||||
hosts:
|
||||
host1:
|
||||
host:
|
||||
tls:
|
||||
enabled: false
|
||||
crt:
|
||||
key:
|
||||
cert: # certificate for a custom domain
|
||||
key: # private key for a custom domain
|
||||
|
||||
##################################################################################
|
||||
## Important: OneUptime Values. More information in the Readme.md
|
||||
##################################################################################
|
||||
oneuptime:
|
||||
admin:
|
||||
email:
|
||||
password:
|
||||
hosts:
|
||||
host1:
|
||||
host:
|
||||
tls:
|
||||
enabled: false
|
||||
crt:
|
||||
key:
|
||||
licensingUrl: https://oneuptime.com/license
|
||||
|
||||
###################################################################################
|
||||
|
||||
httpTestServer:
|
||||
hosts:
|
||||
host1:
|
||||
host:
|
||||
tls:
|
||||
enabled: false
|
||||
crt:
|
||||
key:
|
||||
|
||||
##################################################################################
|
||||
## Important: Probe Values. More information in the Readme.md
|
||||
##################################################################################
|
||||
|
||||
probes:
|
||||
probe1:
|
||||
name: Probe 1
|
||||
key: sample-key
|
||||
probe2:
|
||||
name: Probe 2
|
||||
key: sample-key
|
||||
|
||||
##################################################################################
|
||||
## Important: RateLimitter Values. More information in the Readme.md
|
||||
##################################################################################
|
||||
|
||||
rateLimitter:
|
||||
enabled: false
|
||||
requestLimit: 5000
|
||||
requestLimitTimePeriodInMS: 216000
|
||||
|
||||
|
||||
## OneUptime official image version on Docker Hub
|
||||
## ref: https://hub.docker.com/u/oneuptime
|
||||
##
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: oneuptime
|
||||
tag: latest
|
||||
pullPolicy: Always
|
||||
restartPolicy: Always
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
##################################################################################
|
||||
## IMPORTANT:
|
||||
## Values for Subcharts
|
||||
##
|
||||
|
||||
redis:
|
||||
redisPort: 6379
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/redis
|
||||
tag: latest
|
||||
pullPolicy: Always
|
||||
usePassword: false
|
||||
auth:
|
||||
enabled: false
|
||||
persistence:
|
||||
enabled: true
|
||||
mountPath: /bitnami/redis
|
||||
size: 20Gi
|
||||
|
||||
mongo:
|
||||
oneuptimeDbUsername: oneuptime
|
||||
oneuptimeDbPassword: password
|
||||
databaseName: oneuptimedb
|
||||
rootUsername: root
|
||||
rootPassword: root
|
||||
|
||||
## Service Configuration
|
||||
## For minikube, set service.type to NodePort, elsewhere use LoadBalancer
|
||||
##
|
||||
|
||||
## Service Configuration
|
||||
## For minikube, set this to NodePort, elsewhere use LoadBalancer
|
||||
##
|
||||
nginx-ingress-controller:
|
||||
defaultBackend:
|
||||
enabled: false
|
||||
service:
|
||||
type: LoadBalancer
|
||||
proxySetHeaders:
|
||||
X-Forwarded-For: $http_x_forwarded_for
|
||||
X-Real-Ip: $http_x_forwarded_for
|
||||
publishService:
|
||||
enabled: true
|
||||
config:
|
||||
log-format-upstream: '$remote_addr - $http_cf_connecting_ip - $http_x_forwarded_for - $request_id - [$proxy_add_x_forwarded_for] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status'
|
||||
proxy-protocol: "true"
|
||||
real-ip-header: "X-Forwarded-For"
|
||||
|
||||
|
||||
##################################################################################
|
||||
|
||||
haraka:
|
||||
fromEmail:
|
||||
fromName:
|
||||
user:
|
||||
password:
|
||||
domain:
|
||||
# This should be base64 of your private key
|
||||
dkimPrivateKey:
|
||||
tlsCert:
|
||||
tlsKey:
|
||||
|
||||
host:
|
||||
backendPort: 3002
|
||||
fetchResourcesPort: 3400
|
||||
dataIngestorPort: 3200
|
||||
realtimePort: 3300
|
||||
homePort: 1444
|
||||
licensingPort: 3004
|
||||
statusPageHttpPort: 3006
|
||||
statusPageHttpsPort: 3007
|
||||
dashboardPort: 3000
|
||||
accountsPort: 3003
|
||||
helmChartPort: 3423
|
||||
ApiReferencePort: 1445
|
||||
initScriptPort: 1447
|
||||
# if port 25 is avaialble and accessible
|
||||
# then we can use it as default port
|
||||
harakaPort: 2525
|
||||
httpTestServerPort: 3010
|
||||
adminDashboardPort: 3100
|
||||
backendServicePort: 80
|
||||
dataIngestorServicePort: 80
|
||||
realtimeServicePort: 80
|
||||
fetchResourcesServicePort: 80
|
||||
homeServicePort: 80
|
||||
ApiReferenceServicePort: 80
|
||||
statusPageHttpServicePort: 80
|
||||
statusPageHttpsServicePort: 443
|
||||
dashboardServicePort: 80
|
||||
accountsServicePort: 80
|
||||
adminDashboardServicePort: 80
|
||||
backendNodePort: 80
|
||||
statusPageNodePort: 80
|
||||
dashboardNodePort: 80
|
||||
accountsNodePort: 80
|
||||
adminDashboardNodePort: 80
|
||||
licensingServicePort: 80
|
||||
helmChartServicePort: 80
|
||||
httpTestServerServicePort: 80
|
||||
initScriptServicePort: 80
|
||||
harakaServicePort: 2525
|
||||
scriptRunnerPort: 3009
|
||||
scripRunnerServicePort: 80
|
||||
applicationScannerPort: 3005
|
||||
applicationScannerServicePort: 80
|
||||
containerScannerPort: 3055
|
||||
containerScannerServicePort: 80
|
||||
lighthouseRunnerPort: 3015
|
||||
lighthouseRunnerServicePort: 80
|
||||
|
||||
isThirdPartyBilling: false
|
||||
isRunningOnGCPMarketplace: false
|
||||
isTesting: false
|
||||
|
||||
# Encryption Key
|
||||
encryptionKey: ThisEncryptionKeyLengthIs32Size.
|
||||
|
||||
# If you disable sign up, then you need to specify
|
||||
# oneuptime.admin.email and oneuptime.admin.password values for the admin account.
|
||||
disableSignup: false
|
||||
|
||||
# What protocol is backend running on. Takes in values like 'http:' or 'https:'
|
||||
backendProtocol:
|
||||
|
||||
# Status page domain to add to CNAME to work with custom domains
|
||||
# Status page CNAME to display whcih customers will set on the cusom domain tab of status page.
|
||||
statusPageDomain:
|
||||
|
||||
# Push Notifications.
|
||||
# Generate public and pivate key for push notifications.
|
||||
# These are just the test keys.
|
||||
# You can generate them by:
|
||||
# First install the web-push npm package using npm install web-push -g, then run web-push generate-vapid-keys
|
||||
|
||||
pushNotification:
|
||||
publicKey: "BD1kb-OchZlXr32bmwpjhoxp_cq-aqK4dWXRDkC5m6Hd9_cvMOUw_bXRFR3pJFGzpEdjQUk5SDdYaXvb7xd-1Dg"
|
||||
privateKey: "WdFZTeXkuoxpsO_KNOtXvhDUc_Ae1rb-WjPv6AVexA4"
|
||||
url: "https://oneuptime-test.com"
|
||||
|
||||
|
||||
autoScaler:
|
||||
enabled: false
|
||||
averageCpuUtilization: 50
|
||||
minReplicas: 1
|
||||
maxReplicas: 1
|
||||
|
||||
nodeEnv: production
|
||||
|
||||
applicationScanner:
|
||||
name: US
|
||||
key: b6ETg5EdrIEtdjgit7r3
|
||||
containerScanner:
|
||||
name: US
|
||||
key: s9KOOlCVyly0XykZVjDe
|
||||
|
||||
logstashHost: 54.153.39.163
|
||||
logstashPort: 1514
|
||||
@@ -1 +1,23 @@
|
||||
.git
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
|
||||
@@ -1,33 +1,24 @@
|
||||
apiVersion: v2
|
||||
name: OneUptime
|
||||
version: 4.0.0
|
||||
description: One complete DevOps and DevOps platform.
|
||||
keywords:
|
||||
- DevOps
|
||||
- IT DevOps
|
||||
- DevOps
|
||||
- Monitoring
|
||||
- Status Page
|
||||
- On-Call
|
||||
- On-Call Management
|
||||
- Incident Management
|
||||
- Performance Monitoring
|
||||
- API Test
|
||||
- Website Monitoring
|
||||
- Website Test
|
||||
- SRE
|
||||
home: https://oneuptime.com
|
||||
dependencies:
|
||||
# https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx
|
||||
- name: nginx-ingress-controller
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: "6.0.1"
|
||||
- name: redis
|
||||
version: "10.5.11"
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
maintainers:
|
||||
- name: OneUptime Support
|
||||
email: support@oneuptime.com
|
||||
url: https://oneuptime.com/support
|
||||
icon: https://oneuptime.com/img/OneUptime.svg
|
||||
engine: gotplhelm dependency update
|
||||
name: oneuptime
|
||||
description: A Helm chart for Kubernetes
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.16.0"
|
||||
|
||||
@@ -1,85 +1,22 @@
|
||||
============================================
|
||||
IMPORTANT: After Installation Steps
|
||||
============================================
|
||||
|
||||
** Thank you for installing OneUptime **
|
||||
** Please be patient while the chart is being deployed **
|
||||
** This usually takes few minutes or more **
|
||||
|
||||
To access your OneUptime app from steps below:
|
||||
|
||||
{{- if eq (index .Values "nginx-ingress-controller" "service" "type") "LoadBalancer" }}
|
||||
============================================
|
||||
Make sure external IP's are assigned.
|
||||
============================================
|
||||
|
||||
Please run these commands to get OneUptime URL
|
||||
|
||||
$ kubectl get svc {{ $.Release.Name }}-nginx-ingress-controller --namespace={{ $.Release.Namespace }}
|
||||
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
If the load balancer did not assign an external IP yet (if the IP is still pending).
|
||||
Retry this command after few mins.
|
||||
{{- end}}
|
||||
============================================
|
||||
Sign Up
|
||||
============================================
|
||||
|
||||
{{- if eq (index .Values "nginx-ingress-controller" "service" "type") "LoadBalancer" }}
|
||||
Go to the External IP (generated from step 1) from your browser and sign up a new admin account.
|
||||
{{- else}}
|
||||
Go to the External IP of your server from your browser and sign up a new admin account.
|
||||
{{- end}}
|
||||
This is your master admin account (and not a user account).
|
||||
To create a user account. Please follow steps below.
|
||||
|
||||
============================================
|
||||
Setup Email
|
||||
============================================
|
||||
|
||||
When you're done signing up the admin account. Head over to "Settings" -> "Email"
|
||||
|
||||
Add your SMTP server details here to enable email alerts.
|
||||
|
||||
============================================
|
||||
Setup Twilio
|
||||
============================================
|
||||
|
||||
When you're done signing up the admin account. Head over to "Settings" -> "Call and SMS"
|
||||
|
||||
Add your Twilio Settings here to enable call and SMS alert.
|
||||
|
||||
============================================
|
||||
Create User
|
||||
============================================
|
||||
|
||||
On the Admin Dahboard, go to the "Users" menu and add a new user.
|
||||
Log out of the admin account, and log in with a user account to access User's OneUptime Dashboard.
|
||||
|
||||
{{- if not $.Values.isThirdPartyBilling }}
|
||||
============================================
|
||||
STEP 5: Buy License
|
||||
============================================
|
||||
|
||||
OneUptime which you just installed runs on an evaluation license.
|
||||
Please contact us at sales@oneuptime.com to buy a commercial license.
|
||||
We support companies of all sizes.
|
||||
|
||||
Once you buy the commercial license,
|
||||
you can enter that license key on your admin dashboard.
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oneuptime.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oneuptime.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oneuptime.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oneuptime.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||
{{- end }}
|
||||
|
||||
============================================
|
||||
Support and Demo
|
||||
============================================
|
||||
|
||||
Demo:
|
||||
If you're looking for a personlized OneUptime demo.
|
||||
Please email us at demo@oneuptime.com to schedule one.
|
||||
|
||||
Support and Help:
|
||||
If you're looking for help with anything,
|
||||
Please email us at support@oneuptime.com and we'll get back to you in less than 1 business day.
|
||||
|
||||
|
||||
Thank you for installing OneUptime!
|
||||
|
||||
@@ -1,44 +1,62 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "oneuptime.mongodbConnectionString" -}}
|
||||
{{ printf "mongodb://%s:%s@%s-%s.%s-%s.%s.%s:%s/%s" $.Values.mongo.oneuptimeDbUsername $.Values.mongo.oneuptimeDbPassword $.Release.Name "mongo-standalone-0" $.Release.Name "mongo-standalone" $.Release.Namespace "svc.cluster.local" "27017" $.Values.mongo.databaseName }}
|
||||
{{- end -}}
|
||||
{{- define "oneuptime.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "oneuptime.internalSmtpServer" -}}
|
||||
{{ printf "%s-haraka.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "oneuptime.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "oneuptime.redisHost" -}}
|
||||
{{ printf "%s-redis-master.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "oneuptime.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "oneuptime.backendHost" -}}
|
||||
{{ printf "%s-backend.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "oneuptime.labels" -}}
|
||||
helm.sh/chart: {{ include "oneuptime.chart" . }}
|
||||
{{ include "oneuptime.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "oneuptime.oneuptimeHost" -}}
|
||||
{{ printf "%s-backend.%s" $.Values.oneuptime.host }}
|
||||
{{- end -}}
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "oneuptime.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "oneuptime.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "oneuptime.serverUrl" -}}
|
||||
{{ printf "http://%s-backend.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.probeApiUrl" -}}
|
||||
{{ printf "http://%s-ProbeAPI.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.scriptRunnerUrl" -}}
|
||||
{{ printf "http://%s-script.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.dataIngestorUrl" -}}
|
||||
{{ printf "http://%s-ingestor.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "oneuptime.realtimeUrl" -}}
|
||||
{{ printf "http://%s-realtime.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }}
|
||||
{{- end -}}
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "oneuptime.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "oneuptime.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
61
HelmChart/public/oneuptime/templates/deployment.yaml
Normal file
61
HelmChart/public/oneuptime/templates/deployment.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "oneuptime.fullname" . }}
|
||||
labels:
|
||||
{{- include "oneuptime.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "oneuptime.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "oneuptime.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "oneuptime.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
28
HelmChart/public/oneuptime/templates/hpa.yaml
Normal file
28
HelmChart/public/oneuptime/templates/hpa.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "oneuptime.fullname" . }}
|
||||
labels:
|
||||
{{- include "oneuptime.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "oneuptime.fullname" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,126 +1,61 @@
|
||||
############----INGRESS---#####################################
|
||||
{{- range $key, $value := $.Values.oneuptime.hosts }}
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "oneuptime.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
app.kubernetes.io/part-of: oneuptime
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
meta.helm.sh/release-name: {{ printf "%s" $.Release.Name }}
|
||||
{{- include "oneuptime.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: nginx
|
||||
ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/affinity: "cookie"
|
||||
nginx.ingress.kubernetes.io/affinity-mode: "balanced"
|
||||
nginx.ingress.kubernetes.io/session-cookie-change-on-failure: "false"
|
||||
nginx.ingress.kubernetes.io/session-cookie-name: "fi-ingress-cookie"
|
||||
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
|
||||
ingress.kubernetes.io/session-cookie-hash: "sha1"
|
||||
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
|
||||
name: {{ printf "%s-%s-%s" $.Release.Name $key "ingress" }}
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if $value.tls.enabled }}
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
- {{ $value.host }}
|
||||
secretName: {{ printf "%s-%s-%s" $.Release.Name $key "tls" }}
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- if $value.host }}
|
||||
- host: {{ $value.host }}
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
{{- else }}
|
||||
- http:
|
||||
{{- end }}
|
||||
paths:
|
||||
- path: /accounts
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "accounts" }}
|
||||
servicePort: 80
|
||||
- path: /data-ingestor
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "ingestor" }}
|
||||
servicePort: 80
|
||||
- path: /probe-api
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "probe-api" }}
|
||||
servicePort: 80
|
||||
- path: /dashboard
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "dashboard" }}
|
||||
servicePort: 80
|
||||
- path: /admin
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "admin" }}
|
||||
servicePort: 80
|
||||
- path: /api
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "backend" }}
|
||||
servicePort: 80
|
||||
- path: /realtime
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "realtime" }}
|
||||
servicePort: 80
|
||||
- path: /StatusPage
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "status" }}
|
||||
servicePort: 80
|
||||
- path: /haraka
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "haraka" }}
|
||||
servicePort: 80
|
||||
- path: /application
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "app-scan" }}
|
||||
servicePort: 80
|
||||
- path: /container
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "cont-scan" }}
|
||||
servicePort: 80
|
||||
- path: /lighthouse
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "lighthouse" }}
|
||||
servicePort: 80
|
||||
- path: /script
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "script" }}
|
||||
servicePort: 80
|
||||
{{- range $probeKey, $probeValue := $.Values.probes }}
|
||||
- path: {{ printf "/%s" $probeKey }}
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name $probeKey }}
|
||||
servicePort: 80
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $.Values.saas.isSaasService }}
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "home" }}
|
||||
servicePort: 80
|
||||
- path: /docs
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "api-reference" }}
|
||||
servicePort: 80
|
||||
- path: /license
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "licensing" }}
|
||||
servicePort: 80
|
||||
- path: /chart
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "helm-chart" }}
|
||||
servicePort: 80
|
||||
{{- else }}
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "accounts" }}
|
||||
servicePort: 80
|
||||
{{- end }}
|
||||
{{- if $.Values.saas.exposeInitScriptContainer }}
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: {{ printf "%s-%s" $.Release.Name "init-script" }}
|
||||
servicePort: 80
|
||||
{{- end }}
|
||||
---
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
##########################################################################
|
||||
|
||||
15
HelmChart/public/oneuptime/templates/service.yaml
Normal file
15
HelmChart/public/oneuptime/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "oneuptime.fullname" . }}
|
||||
labels:
|
||||
{{- include "oneuptime.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "oneuptime.selectorLabels" . | nindent 4 }}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user