diff --git a/.gitignore b/.gitignore index 69319e0402..a8d9897db5 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,7 @@ Nginx/default.conf Certs/StatusPageCerts/*.crt Certs/StatusPageCerts/*.key +Certs/ServerCerts/*.crt +Certs/ServerCerts/*.key + Backups/*.backup diff --git a/Certs/ServerCerts/Readme.md b/Certs/ServerCerts/Readme.md new file mode 100644 index 0000000000..488b2d4b0c --- /dev/null +++ b/Certs/ServerCerts/Readme.md @@ -0,0 +1 @@ +This project is for Automatic Acme Certificate verification or renewal for the OneUptime server. \ No newline at end of file diff --git a/CommonServer/API/StatusPageAPI.ts b/CommonServer/API/StatusPageAPI.ts index 9d56c1d1c1..cbd0944430 100644 --- a/CommonServer/API/StatusPageAPI.ts +++ b/CommonServer/API/StatusPageAPI.ts @@ -405,6 +405,7 @@ export default class StatusPageAPI extends BaseAPI< return monitor.monitorId!; }); + const startDate: Date = OneUptimeDate.getSomeDaysAgo(90); const endDate: Date = OneUptimeDate.getCurrentDate(); @@ -445,6 +446,8 @@ export default class StatusPageAPI extends BaseAPI< }); } + + // check if status page has active incident. let activeIncidents: Array = []; if (monitorsOnStatusPage.length > 0) { @@ -518,7 +521,7 @@ export default class StatusPageAPI extends BaseAPI< let incidentStateTimelines: Array = []; - + console.log("HERE"); if (incidentsOnStausPage.length > 0) { incidentStateTimelines = await IncidentStateTimelineService.findBy({ @@ -550,7 +553,7 @@ export default class StatusPageAPI extends BaseAPI< const activeAnnouncements: Array = await StatusPageAnnouncementService.findBy({ query: { - statusPages: QueryHelper.in([objectId]), + statusPages: objectId as any, showAnnouncementAt: QueryHelper.lessThan(today), endAnnouncementAt: QueryHelper.greaterThan(today), @@ -577,7 +580,7 @@ export default class StatusPageAPI extends BaseAPI< currentScheduledMaintenanceState: { isOngoingState: true, } as any, - statusPages: QueryHelper.in([objectId]), + statusPages: objectId as any, projectId: statusPage.projectId!, }, select: { diff --git a/CommonUI/src/Components/Footer/Footer.tsx b/CommonUI/src/Components/Footer/Footer.tsx index 6c6e5db8e0..58aaa9d6b0 100644 --- a/CommonUI/src/Components/Footer/Footer.tsx +++ b/CommonUI/src/Components/Footer/Footer.tsx @@ -61,11 +61,12 @@ const Footer: FunctionComponent = ( {!props.copyright && (
- {props.links && - props.links.filter((link: FooterLink) => { - return !link.showOnRightIfNoCopyright; - }).length > 0 && ( -
+
+ {props.links && + props.links.filter((link: FooterLink) => { + return !link.showOnRightIfNoCopyright; + }).length > 0 && ( +

{props.links && props.links @@ -100,8 +101,9 @@ const Footer: FunctionComponent = ( } )}

-
- )} + + )} +
{props.links && props.links.filter((link: FooterLink) => { return link.showOnRightIfNoCopyright; diff --git a/CommonUI/src/Components/ModelTable/ModelTable.tsx b/CommonUI/src/Components/ModelTable/ModelTable.tsx index c56aad7c0e..c2bd3260aa 100644 --- a/CommonUI/src/Components/ModelTable/ModelTable.tsx +++ b/CommonUI/src/Components/ModelTable/ModelTable.tsx @@ -518,7 +518,7 @@ const ModelTable: Function = ( onClick: () => { fetchItems(); }, - disabled: isLoading, + disabled: isTableFilterFetchLoading, icon: IconProp.Refresh, }); } @@ -534,7 +534,7 @@ const ModelTable: Function = ( } setShowTableFilter(newValue); }, - disabled: isLoading, + disabled: isTableFilterFetchLoading, icon: IconProp.Filter, }); } diff --git a/Dashboard/src/Pages/StatusPages/View/SideMenu.tsx b/Dashboard/src/Pages/StatusPages/View/SideMenu.tsx index e51f15743a..a072685f28 100644 --- a/Dashboard/src/Pages/StatusPages/View/SideMenu.tsx +++ b/Dashboard/src/Pages/StatusPages/View/SideMenu.tsx @@ -135,7 +135,7 @@ const DashboardSideMenu: FunctionComponent = ( icon={IconProp.Image} /> - = ( ), }} icon={IconProp.Circle} - /> + /> */} = ( links={[ ...props.links, { - title: 'Powered by OneUptime', + title: 'Powered by OneUptime.', to: URL.fromString('https://oneuptime.com'), openInNewTab: true, showOnRightIfNoCopyright: true, diff --git a/StatusPage/src/Components/Header/Header.tsx b/StatusPage/src/Components/Header/Header.tsx index b4919e218a..d0d83b56a9 100644 --- a/StatusPage/src/Components/Header/Header.tsx +++ b/StatusPage/src/Components/Header/Header.tsx @@ -14,6 +14,11 @@ export interface ComponentProps { const StatusPageHeader: FunctionComponent = ( props: ComponentProps ): ReactElement => { + + if (!props.banner && !props.logo && props.links.length === 0) { + return <> + } + return (
= ( : (RouteMap[PageMap.SUBSCRIBE] as Route) )} > - = ( ? (RouteMap[PageMap.PREVIEW_RSS] as Route) : (RouteMap[PageMap.RSS] as Route) )} - > + > */} } maxWidth="880px" diff --git a/StatusPage/src/Pages/Overview/Overview.tsx b/StatusPage/src/Pages/Overview/Overview.tsx index 60017d5dd8..6c5f865ec2 100644 --- a/StatusPage/src/Pages/Overview/Overview.tsx +++ b/StatusPage/src/Pages/Overview/Overview.tsx @@ -575,12 +575,12 @@ const Overview: FunctionComponent = ( eventViewRoute={RouteUtil.populateRouteParams( props.isPreviewPage ? (RouteMap[ - PageMap - .PREVIEW_INCIDENT_DETAIL - ] as Route) + PageMap + .PREVIEW_INCIDENT_DETAIL + ] as Route) : (RouteMap[ - PageMap.INCIDENT_DETAIL - ] as Route), + PageMap.INCIDENT_DETAIL + ] as Route), incidentGroup.incident.id! )} /> @@ -621,12 +621,12 @@ const Overview: FunctionComponent = ( eventViewRoute={RouteUtil.populateRouteParams( props.isPreviewPage ? (RouteMap[ - PageMap - .PREVIEW_SCHEDULED_EVENT_DETAIL - ] as Route) + PageMap + .PREVIEW_SCHEDULED_EVENT_DETAIL + ] as Route) : (RouteMap[ - PageMap.SCHEDULED_EVENT_DETAIL - ] as Route), + PageMap.SCHEDULED_EVENT_DETAIL + ] as Route), scheduledEventGroup.scheduledMaintenance .id! )} @@ -636,13 +636,12 @@ const Overview: FunctionComponent = ( )}
- {currentStatus && ( + {currentStatus && statusPageResources.length > 0 && ( = ( )}
-
+ {statusPageResources.length > 0 &&
{statusPageResources.filter( (resources: StatusPageResource) => { @@ -690,7 +689,7 @@ const Overview: FunctionComponent = ( } isLastElement={ resourceGroups.length - - 1 === + 1 === i } title={resourceGroup.name!} @@ -704,7 +703,10 @@ const Overview: FunctionComponent = ( )}
-
+
} + + {statusPageResources.length === 0 &&

No resources added to this Status Page, please add some resources from OneUptime dashboard.

} + ) : ( <> diff --git a/get-certs.sh b/get-certs.sh new file mode 100644 index 0000000000..7e91143bb7 --- /dev/null +++ b/get-certs.sh @@ -0,0 +1,14 @@ +# This script generates or renews certs for this server. +export $(grep -v '^#' config.env | xargs) +npm run prerun +docker compose stop nginx +sudo snap install core +sudo snap refresh core +sudo apt-get remove certbot +sudo snap install --classic certbot +sudo ln -s /snap/bin/certbot /usr/bin/certbot +sudo certbot certonly --standalone +sudo certbot renew --dry-run +sudo cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem $(pwd)/Certs/ServerCerts/Cert.crt +sudo cp /etc/letsencrypt/live/$DOMAIN/privkey.pem $(pwd)/Certs/ServerCerts/Key.key +docker compose start nginx \ No newline at end of file diff --git a/preinstall.sh b/preinstall.sh index 9421ee68b9..d625954dfe 100644 --- a/preinstall.sh +++ b/preinstall.sh @@ -139,12 +139,12 @@ cd oneuptime # Generate Self Signed SSL certificate. -CERT=./Certs/Cert.crt +CERT=./Certs/ServerCerts/Cert.crt if test -f "$CERT"; then echo "SSL Certificate exists. Skipping generating a new one." else echo "SSL Certificate not found. Generating a new certificate." - openssl req -new -x509 -nodes -subj "/C=GB/ST=London/L=London/O=Global Security/OU=IT Department/CN=example.com" -out ./Certs/Cert.crt -keyout ./Certs/Key.key + openssl req -new -x509 -nodes -subj "/C=GB/ST=London/L=London/O=Global Security/OU=IT Department/CN=example.com" -out ./Certs/ServerCerts/Cert.crt -keyout ./Certs/ServerCerts/Key.key fi # Create .env file if it does not exist. diff --git a/renew-certs.sh b/renew-certs.sh new file mode 100644 index 0000000000..7103bb7f0a --- /dev/null +++ b/renew-certs.sh @@ -0,0 +1,8 @@ +# Run this cron every day to see if the cert needs renewal. +export $(grep -v '^#' config.env | xargs) +npm run prerun +docker compose nginx stop +sudo certbot renew +sudo cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem $(pwd)/Certs/ServerCerts/Cert.crt +sudo cp /etc/letsencrypt/live/$DOMAIN/privkey.pem $(pwd)/Certs/ServerCerts/Key.key +docker compose start nginx \ No newline at end of file