Compare commits

...

187 Commits

Author SHA1 Message Date
Simon Larsen
8d4b8b7881 Refactor DashboardToolbar component to adjust margins and spacing 2024-10-31 17:21:25 +00:00
Simon Larsen
4626520f62 Refactor DashboardBaseComponent to add full screen functionality and adjust styling 2024-10-31 13:26:32 +00:00
Simon Larsen
7c04569a14 Refactor IconProp enum and add new icons: Bold, Italic, and Underline 2024-10-30 18:45:58 +00:00
Simon Larsen
bd8b1ca909 Refactor Dashboard components and add full screen functionality 2024-10-30 17:40:38 +00:00
Simon Larsen
13dddab5e5 Refactor MonitorTestForm component to adjust margins and spacing 2024-10-30 11:56:28 +00:00
Simon Larsen
771b0e4645 Refactor MonitorTestForm component to adjust margins and spacing 2024-10-29 18:11:02 +00:00
Simon Larsen
d99111b2f9 Refactor MonitorTest table to remove "lastMonitoringLog" column and add "monitorStepProbeResponse" and "isInQueue" columns 2024-10-29 18:04:36 +00:00
Simon Larsen
c2bb44f823 Refactor MonitorTestForm component and add test functionality 2024-10-29 17:55:09 +00:00
Simon Larsen
7ece118acd Refactor MonitorTestService and MonitorTest model 2024-10-29 17:43:36 +00:00
Simon Larsen
9b4ef72682 Refactor MonitorTestService and MonitorTest model 2024-10-29 16:59:07 +00:00
Simon Larsen
25ba824d79 Refactor MonitorResourceUtil and CriteriaFilterUtil to add MonitorTest model 2024-10-29 13:43:10 +00:00
Simon Larsen
9b35836dc8 Refactor MonitorResourceUtil to support ExecutionTime metric in synthetic monitors 2024-10-29 13:19:26 +00:00
Simon Larsen
809f9a38bc Refactor MonitorResourceUtil and MonitorChart components 2024-10-28 14:43:54 +00:00
Simon Larsen
df08f2b188 Refactor MonitorResourceUtil and CriteriaFilterUtil to support ExecutionTime metric 2024-10-28 14:41:59 +00:00
Simon Larsen
9512b9d001 Merge branch 'master' into release 2024-10-28 13:46:58 +00:00
Simon Larsen
995026f65f Refactor StatusPageSubscriberService to remove unnecessary code 2024-10-28 13:46:52 +00:00
Simon Larsen
d619d2afff Refactor StatusPageSubscriberService to fix issue with sending notifications for unsubscribed subscribers 2024-10-28 13:44:49 +00:00
Simon Larsen
1affe3cdda Refactor StatusPageSubscriberService to include event type selection 2024-10-28 13:35:33 +00:00
Simon Larsen
0bee18fa63 Refactor SubscriberSettings component to remove unnecessary code 2024-10-28 13:09:26 +00:00
Simon Larsen
2ad7face9a Refactor StatusPageAPI to allow subscribers to choose event types 2024-10-28 12:53:26 +00:00
Simon Larsen
33604bba3c Refactor SubscriberSettings component to allow subscribers to choose event types 2024-10-28 12:46:16 +00:00
Simon Larsen
9d6c34b796 Refactor StatusPageEventType enum to include new event types 2024-10-28 12:41:24 +00:00
Simon Larsen
052c3040fb Merge branch 'master' into release 2024-10-28 11:52:42 +00:00
Simon Larsen
89804ebbd1 Refactor Dashboard components to include component ID in rendered output 2024-10-28 11:52:19 +00:00
Simon Larsen
e21572af6d Merge branch 'release' of github.com:OneUptime/oneuptime into release 2024-10-28 11:44:56 +00:00
Simon Larsen
3865f6cb06 Refactor Markdown class to convert tags > and < to &gt; and &lt; 2024-10-28 11:44:26 +00:00
Simon Larsen
296791ed25 Refactor NavBar component to temporarily comment out unused DashboardNavItem 2024-10-28 10:11:05 +00:00
Simon Larsen
017216b8a6 Refactor DashboardBaseComponent to remove unused event parameters in onDragStart and onDragEnd 2024-10-28 10:07:30 +00:00
Simon Larsen
6fb6329356 Refactor DashboardViewConfigUtil to fix lastRowThatHasComponent calculation 2024-10-28 10:05:57 +00:00
Simon Larsen
477da276b2 Refactor Dashboard components and add new dashboard view 2024-10-25 15:18:23 +01:00
Simon Larsen
dbf90bf114 Refactor Dashboard components and add conditional rendering for empty dashboard 2024-10-25 13:12:17 +01:00
Simon Larsen
d6fa9b3905 Refactor DashboardToolbar to remove unused imports and update props usage 2024-10-25 08:48:17 +01:00
Simon Larsen
95573032e7 Refactor DashboardCanvas to render DashboardBaseComponentElement for each component 2024-10-25 07:57:00 +01:00
Simon Larsen
82699e5276 Refactor DashboardChartComponent to remove unused imports and update file name 2024-10-25 07:52:46 +01:00
Simon Larsen
54b95107c3 Refactor DashboardChartComponent and related components 2024-10-25 07:52:21 +01:00
Simon Larsen
e54b337c45 Refactor DashboardSize to calculate total width of dashboard in rem 2024-10-24 19:12:46 +01:00
Simon Larsen
75ab4bd946 Refactor DashboardViewConfig enum to use explicit types for default height and width 2024-10-24 18:34:31 +01:00
Simon Larsen
b31ffab577 Refactor DashboardComponentType enum to fix casing and add missing newline at end of file 2024-10-24 17:23:34 +01:00
Simon Larsen
8f2da2bdc5 Refactor dashboard component types and add chart, text, and value components 2024-10-24 15:38:13 +01:00
Simon Larsen
6ae31ac0da Refactor canvas and row components to use explicit types for default height and width 2024-10-23 14:54:01 +01:00
Simon Larsen
da22f2ef51 Refactor DashboardMode enum to fix formatting and add missing newline at end of file 2024-10-23 14:48:51 +01:00
Simon Larsen
a882507aff Refactor MoreMenu component to use Button instead of Icon 2024-10-23 14:46:24 +01:00
Simon Larsen
04c74de8e3 Merge pull request #1738 from OneUptime/master
Release
2024-10-23 13:45:33 +01:00
Simon Larsen
f13adebc04 Refactor DashboardSize to fix casing of heightInDashboardUnits property 2024-10-23 13:36:31 +01:00
Simon Larsen
5573d1cd6c Refactor NavBar component to uncomment Dashboards item 2024-10-23 13:09:00 +01:00
Simon Larsen
24d15c98ef Refactor NavBar component to comment out unused code 2024-10-23 13:08:37 +01:00
Simon Larsen
97de3ff6c7 Refactor DashboardService to include DashboardViewConfig 2024-10-23 13:07:47 +01:00
Simon Larsen
7bcecd0a1d Update package dependencies 2024-10-23 12:56:34 +01:00
Simon Larsen
b050dfdc1c Refactor CategoryCheckbox component to remove unnecessary array cloning 2024-10-23 12:56:10 +01:00
Simon Larsen
05a2fe6665 Refactor CRUD permissions to include read access 2024-10-23 12:50:02 +01:00
Simon Larsen
986479e8d5 Refactor DashboardViewConfig to use semicolon instead of comma 2024-10-23 12:45:22 +01:00
Simon Larsen
16fad55f9f Refactor Dashboard model to include DashboardViewConfig 2024-10-23 12:18:15 +01:00
Simon Larsen
4f03f448e8 Add new dashboard components and interfaces 2024-10-23 12:15:00 +01:00
Simon Larsen
f3e72a30d3 Delete unused ServiceDelete component 2024-10-23 11:51:38 +01:00
Simon Larsen
cf319c5afb Add new chart types and dashboard component interfaces 2024-10-23 11:24:13 +01:00
Simon Larsen
3afd4ed5b5 Merge pull request #1734 from OneUptime/oneuptime-copilot-oneuptime-copilot-improve-comments-RINtg
Improved comments on /App/FeatureSet/Identity/API/StatusPageSSO.ts
2024-10-22 12:51:20 +01:00
Simon Larsen
00a783acca Merge pull request #1732 from OneUptime/snyk-fix-d8042450b0fd7524c713302d42109ccc
[Snyk] Fix for 1 vulnerabilities
2024-10-21 16:23:26 +01:00
Simon Larsen
3733c99b67 Merge pull request #1736 from fzamperin/master
refactor: change tailwind.js from cdn to serve local
2024-10-21 16:22:55 +01:00
Simon Larsen
e9daf776de fix monitor id on alert table 2024-10-21 16:22:03 +01:00
Fernando Penna
aced5f2124 Merge branch 'OneUptime:master' into master 2024-10-18 16:36:29 -03:00
Fernando Augusto Zamperin Penna
74ff0adefe refactor: adding standalone tailwindjs script on pages instead of cdn 2024-10-18 16:35:48 -03:00
Simon Larsen
4cefa756d6 add not notify on default incident state 2024-10-18 16:41:33 +01:00
Simon Larsen
365e44ebf9 add custom code monitor summary 2024-10-18 16:17:52 +01:00
Simon Larsen
b7d34e878f fix typo 2024-10-18 10:29:10 +01:00
OneUptime Copilot
15b2bf2071 Improved comments on /App/FeatureSet/Identity/API/StatusPageSSO.ts 2024-10-17 01:30:49 +00:00
Simon Larsen
5e85e73c0b add do not follow redirect to form 2024-10-16 18:20:03 +01:00
Simon Larsen
b9b5ca3325 switch base image to ecr 2024-10-16 15:54:57 +01:00
Simon Larsen
d89ee302fd turn do not redirect to false 2024-10-16 15:08:56 +01:00
Simon Larsen
a39db4ffc9 fix timeline on monitor chart 2024-10-16 14:59:01 +01:00
Simon Larsen
bbced15076 do not follow redirects when monitoring 2024-10-16 12:50:24 +01:00
Simon Larsen
1b3cde35f3 add filter views to other tables 2024-10-16 12:02:16 +01:00
Simon Larsen
f1dda4a7b3 fix filter settings 2024-10-15 19:20:46 +01:00
snyk-bot
f50120d19a fix: Common/package.json & Common/package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-COOKIE-8163060
2024-10-15 06:03:43 +00:00
Simon Larsen
9d50f77908 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-10-14 20:23:23 +01:00
Simon Larsen
f0a3ddbf2e make UI for table filters nicer 2024-10-14 20:23:20 +01:00
Simon Larsen
8a35eb47e6 Merge pull request #1618 from OneUptime/oneuptime-copilot-oneuptime-copilot-improve-comments-nJEHb
[OneUptime Copilot] Improve Comments on /App/Index.ts
2024-10-14 15:33:53 +01:00
Simon Larsen
6ccf8961bf Merge pull request #1701 from OneUptime/snyk-fix-2d8a0a8383cb68645721c65394cd6cd7
[Snyk] Security upgrade node from 22.5 to 22.9
2024-10-14 15:33:08 +01:00
Simon Larsen
fab8ca112b Merge pull request #1707 from OneUptime/snyk-fix-6186b78cb9bdefdfbc19f061c3bc0e9c
[Snyk] Security upgrade node from 22.5 to 22.8
2024-10-14 15:32:39 +01:00
Simon Larsen
bb81d4cf27 Merge branch 'master' into snyk-fix-6186b78cb9bdefdfbc19f061c3bc0e9c 2024-10-14 15:32:31 +01:00
Simon Larsen
931999c39f Merge pull request #1703 from OneUptime/snyk-fix-9272f658e87a4afce4e711dde5615427
[Snyk] Security upgrade express from 4.19.2 to 4.20.0
2024-10-14 15:32:09 +01:00
Simon Larsen
2e1e112b42 Merge pull request #1731 from OneUptime/snyk-fix-6dcbd9c940cb1f77c486fe016548c853
[Snyk] Security upgrade express from 4.19.2 to 4.21.1
2024-10-14 15:31:54 +01:00
snyk-bot
3b7a7c3c49 fix: StatusPage/package.json & StatusPage/package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-COOKIE-8163060
2024-10-14 05:38:21 +00:00
Simon Larsen
5d9252d1ff refactor: Enable domain editing and make certificate fields optional in StatusPageDelete component 2024-10-10 12:42:18 +01:00
Simon Larsen
7c85fb4ded refactor: Update status page delete message for custom certificates 2024-10-09 21:06:46 +01:00
Simon Larsen
9e45f4cea9 refactor: Add doNotFollowRedirects option to WebsiteRequest and API
This commit adds the `doNotFollowRedirects` option to the `WebsiteRequest` and `API` classes. When set to `true`, the classes will not follow redirects when making HTTP requests. This is achieved by setting the `maxRedirects` property of the `axiosOptions` object to 0. This change allows for more control over the behavior of HTTP requests and ensures that redirects are not automatically followed.
2024-10-09 20:11:15 +01:00
Simon Larsen
f5d2c61a70 refactor: Add logging for writing custom certificates to disk 2024-10-09 19:31:47 +01:00
Simon Larsen
d072a29cf8 refactor: Add WriteCustomCertsToDiskJob to Nginx/Index.ts and update UptimeUtil to round uptime percentage to specified precision
- The WriteCustomCertsToDiskJob has been added to the Nginx/Index.ts file to handle writing custom certificates to disk.
- The UptimeUtil has been updated to round the uptime percentage to the specified precision.
2024-10-09 19:24:17 +01:00
Simon Larsen
0d262429d9 refactor: Remove unused code in OverviewPageBranding and improve code formatting 2024-10-09 12:09:53 +01:00
Simon Larsen
7b1960f00c refactor: Update UptimeUtil to round uptime percentage to specified precision 2024-10-09 11:59:07 +01:00
Simon Larsen
e253be732f refactor: Update UptimeUtil to round uptime percentage to specified precision
The UptimeUtil class in the Common/Utils/Uptime directory has been updated to include a new method called roundToPrecision. This method takes a number and a precision value and rounds the number to the specified precision. This method is used in the calculateUptimePercentage method to round the uptime percentage to the precision specified in the data.group object.

This change ensures that the uptime percentage is displayed with the correct precision, providing more accurate information to users.

Refactor the UptimeUtil class to include the roundToPrecision method and update the calculateUptimePercentage method to use it.

Fixes #123
2024-10-09 11:39:21 +01:00
Simon Larsen
eaf4193cb0 refactor: Remove unused code in UptimeUtil 2024-10-09 11:23:49 +01:00
Simon Larsen
d7f881c468 fix: Add namespace to Semaphore lock in MonitorStatusTimelineService 2024-10-09 10:46:33 +01:00
Simon Larsen
8270934564 refactor: Improve locking mechanism in Semaphore class
- Modify the Semaphore class in Semaphore.ts to include a namespace parameter in the lock method.
- Update the lockTimeout default value from 1000 to 5000 milliseconds.
- Append the namespace to the key when creating a new Mutex instance.
- Add a try-catch block to handle errors when acquiring and releasing the mutex.
2024-10-09 10:23:50 +01:00
Simon Larsen
8590cfa4c0 feat: add note to alert type 2024-10-08 22:04:51 +01:00
Simon Larsen
09196f397e make alert private note work 2024-10-08 21:12:03 +01:00
Simon Larsen
bc714759bc Merge branch 'monitor-alert' 2024-10-08 20:26:12 +01:00
Simon Larsen
06d0dba258 add monitor alert 2024-10-08 20:26:00 +01:00
Simon Larsen
40cd066473 Merge pull request #1727 from OneUptime/monitor-alert
Monitor Alerts
2024-10-04 16:17:05 -07:00
Simon Larsen
7a38a0d9da fix rule in monitor criteria 2024-10-04 15:54:01 -07:00
Simon Larsen
add11806e0 add default alert severity id 2024-10-04 15:44:43 -07:00
Simon Larsen
97bf26ab03 make header alerts work 2024-10-04 15:34:50 -07:00
Simon Larsen
09955a5ba9 add header group 2024-10-04 11:40:38 -07:00
Simon Larsen
30db4e58ff refactor UI of header alerts 2024-10-04 11:01:36 -07:00
Simon Larsen
7eebd75088 add types to header alert 2024-10-04 09:12:13 -07:00
Simon Larsen
d17b687e03 add alert types to model alert 2024-10-04 09:08:00 -07:00
Simon Larsen
f08dbf6e8f fix issue with monitor group 2024-10-04 08:58:58 -07:00
Simon Larsen
4be7675b74 add active alerts to home page 2024-10-04 08:52:42 -07:00
Simon Larsen
6acb0fb486 add alerts page to monitor groups 2024-10-04 08:31:46 -07:00
Simon Larsen
54cd18896a Refactor SideMenu component in Settings page 2024-10-03 17:12:29 -07:00
Simon Larsen
b5596968a5 Refactor NoteTemplate component to AlertNoteTemplateDetail component 2024-10-03 16:51:18 -07:00
Simon Larsen
25f2d527f8 Refactor AlertNoteTemplateView component and create NoteTemplate component 2024-10-03 16:49:09 -07:00
Simon Larsen
7a052d69d0 Refactor AlertNoteTemplateViews component and create AlertNoteTemplateView component 2024-10-03 16:43:28 -07:00
Simon Larsen
b151eaace7 Refactor AlertNoteTemplateView component and create AlertNoteTemplateViews component 2024-10-03 16:43:18 -07:00
Simon Larsen
8e2336f753 Refactor AlertNoteTemplateViews component and create AlertNoteTemplateView component 2024-10-03 16:42:30 -07:00
Simon Larsen
b0a4bcc5fb Refactor AlertNoteTemplateView and AlertNoteTemplateViews components 2024-10-03 16:42:20 -07:00
Simon Larsen
c8d4bea49b Refactor AlertsTable component and update route in DashboardSideMenu 2024-10-03 16:41:45 -07:00
Simon Larsen
facc564616 Refactor MonitorCriteriaInstance to handle null incidents and alerts 2024-10-03 16:22:48 -07:00
Simon Larsen
591b3ab41c Refactor TableView component and fix indentation 2024-10-03 15:45:00 -07:00
Simon Larsen
cfc1fb47be Refactor MonitorPage and TableView components 2024-10-03 15:25:10 -07:00
Simon Larsen
4a7ac0ffab add monitor alerts 2024-10-03 10:51:41 -07:00
Simon Larsen
bb5a019afd enhance alert permissions and add alert routes 2024-10-03 10:35:10 -07:00
Simon Larsen
b624bd49ee add migration for alerts 2024-10-02 23:05:45 +01:00
Simon Larsen
249a9d991c Merge branch 'table-filters' into monitor-alert 2024-10-02 23:02:38 +01:00
Simon Larsen
49a2ee18a1 add alerts to monitor step 2024-10-02 23:00:47 +01:00
Simon Larsen
11a4f3442d add alert jobs in worker 2024-10-02 22:43:04 +01:00
Simon Larsen
f25f7f1f81 add jobs for alerts 2024-10-02 22:10:37 +01:00
Simon Larsen
d60d9c5a80 add alert mail templates 2024-10-02 22:08:41 +01:00
Simon Larsen
56e8c24449 fix lint 2024-10-02 22:03:40 +01:00
Simon Larsen
bf63badd19 add alerts to nav bar 2024-10-02 22:01:10 +01:00
Simon Larsen
cc1d60af11 add alert change state element 2024-10-02 21:58:56 +01:00
Simon Larsen
e6b47d85d6 add breadcrumbs 2024-10-02 21:48:40 +01:00
Simon Larsen
ae79417fbc add rotue paths to alerts 2024-10-02 21:40:36 +01:00
Simon Larsen
eaed1f8b64 add alert api's to index 2024-10-02 21:27:57 +01:00
Simon Larsen
333b06bc8a add alert services to index 2024-10-02 21:18:21 +01:00
Simon Larsen
cb8cf089c0 add alert services 2024-10-02 21:14:48 +01:00
Simon Larsen
22f5633a32 add default alert severity 2024-10-02 21:06:41 +01:00
Simon Larsen
2f47a3e808 add service for alerts 2024-10-02 21:03:11 +01:00
Simon Larsen
c217eea478 add alert custom fields. 2024-10-02 20:42:09 +01:00
Simon Larsen
1c6a242f3b add owner models 2024-10-02 20:35:05 +01:00
Simon Larsen
7a0cf315fc add alert internal note model 2024-10-02 20:26:05 +01:00
Simon Larsen
e5bb7dccc7 add alert models 2024-10-02 20:23:07 +01:00
Simon Larsen
c789438c62 add migration script for table views 2024-10-02 19:52:32 +01:00
Simon Larsen
bc0e8e323f integrate table view filters with base model table 2024-10-02 19:49:22 +01:00
Simon Larsen
fd15e66f83 add table view save settings. 2024-10-02 19:26:40 +01:00
Simon Larsen
c833bcb37a add table filters model 2024-10-02 15:13:37 +01:00
Simon Larsen
7c941da7df add table view table 2024-10-02 15:07:19 +01:00
Simon Larsen
a2e71afd53 Merge branch 'master' into table-filters 2024-10-01 19:17:23 +01:00
Simon Larsen
84fcb265f6 feat: Add logging to API Post component for better debugging 2024-10-01 19:17:15 +01:00
Simon Larsen
ae493aaee7 feat: Add MoreMenu component and related functionality for enhanced UI interactions 2024-10-01 18:37:26 +01:00
Simon Larsen
cc0670c291 Merge pull request #1725 from fzamperin/master
Refactor changing secret values from data to stringData
2024-10-01 16:51:44 +01:00
Simon Larsen
0733c15363 fix: Improve monitor status retrieval logic in Overview component 2024-10-01 16:50:39 +01:00
Fernando Augusto Zamperin Penna
8727914521 Refactor changing secret values from data to stringData 2024-09-30 14:37:31 -03:00
Simon Larsen
32fa57c63b feat: Implement cascading delete for status page resources in MonitorGroupService and MonitorService 2024-09-30 15:12:51 +01:00
Simon Larsen
346891e85d Merge pull request #1710 from OneUptime/snyk-fix-3c58f351c8ea93b844f014a3967bf666
[Snyk] Security upgrade node from 21.2-alpine3.18 to 21.7.3-alpine3.18
2024-09-30 14:56:25 +01:00
Simon Larsen
979e58ebf5 Merge pull request #1721 from OneUptime/snyk-fix-54b494d7ed7c85a9dfde1f7d20790746
[Snyk] Security upgrade node from 22.5 to 22.9
2024-09-30 14:56:12 +01:00
Simon Larsen
e9dfe14801 Merge pull request #1723 from OneUptime/snyk-fix-9beef75d5a122cf47203e4cfdf7811d2
[Snyk] Security upgrade node from 21.2-alpine3.18 to 21.7.3-alpine3.18
2024-09-30 14:55:58 +01:00
Simon Larsen
3f8c62747a Merge pull request #1722 from fzamperin/master
Fix externalClickhouse password secret
2024-09-30 13:54:36 +01:00
snyk-bot
9a38675676 fix: Workflow/Dockerfile.tpl to reduce vulnerabilities 2024-09-29 10:42:29 +00:00
Fernando Augusto Zamperin Penna
3d7b118e37 Fix externalClickhouse password secret 2024-09-28 20:42:36 -03:00
snyk-bot
c1beb9c0a0 fix: Probe/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-DEBIAN12-AOM-7197979
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855502
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855503
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855507
- https://snyk.io/vuln/SNYK-DEBIAN12-GIT-6846203
2024-09-28 05:43:30 +00:00
Simon Larsen
299707f748 Refactor Realtime class; replace BadDataException with no-op for missing tenantId 2024-09-27 16:51:44 +01:00
Simon Larsen
d48b725f6a Refactor UserAuthorization and Realtime; update mock implementation and add validation for tenantId 2024-09-27 14:21:47 +01:00
Simon Larsen
a0d77ac104 Refactor UserAuthorization test; improve formatting of mock setup for clarity 2024-09-26 17:11:18 +01:00
Simon Larsen
20b5e43b26 Refactor ProjectAuthorization test; remove unused AccessTokenService import for clarity 2024-09-26 17:09:36 +01:00
Simon Larsen
a10a83ad32 Refactor Project and User middleware tests; update method names for clarity and improve mock implementations 2024-09-26 16:15:07 +01:00
Simon Larsen
bf01322fbd Refactor ResourceUtil and UserMiddleware; update type definitions and improve method naming for clarity 2024-09-26 15:59:06 +01:00
Simon Larsen
73fc3e3a08 Refactor MonitorResourceUtil; enhance monitor status timeline logic and improve error handling 2024-09-26 15:51:36 +01:00
Simon Larsen
221f3774de Refactor MonitorResourceUtil; improve code formatting and streamline logging statements 2024-09-26 15:23:23 +01:00
Simon Larsen
b79dafc9df Refactor MonitorResourceUtil; improve error handling and streamline logging statements 2024-09-26 15:18:21 +01:00
Simon Larsen
ed7a693966 Refactor imports in Realtime utility and related components; streamline ModelEventType import paths 2024-09-26 15:13:16 +01:00
Simon Larsen
4982febd74 Refactor code for consistency; remove unnecessary whitespace and improve formatting in multiple files 2024-09-26 15:07:02 +01:00
Simon Larsen
98fe5deba7 Refactor AccessTokenService to utilize UserPermissionUtil for permission retrieval; introduce PermissionNamespace enum 2024-09-26 13:59:28 +01:00
Simon Larsen
54e8a4c224 Refactor UserAuthorization middleware; move access token extraction to Realtime utility 2024-09-26 13:49:38 +01:00
Simon Larsen
7465a44690 Refactor ProjectAuthorization middleware to utilize APIKeyAccessPermission; remove AccessTokenService methods 2024-09-26 13:46:34 +01:00
Simon Larsen
dab51a837d Refactor ProjectAuthorization middleware to use APIKeyAccessPermission; increase concurrency in Workflow feature set 2024-09-26 13:22:23 +01:00
Simon Larsen
003fdb4de4 Add Realtime event types and interfaces; refactor imports for consistency 2024-09-26 13:15:35 +01:00
Simon Larsen
2e5ec1df6f Refactor Realtime event handling and permissions management; introduce EnableRealtimeEventsOn interface 2024-09-26 11:59:11 +01:00
Simon Larsen
8afa3810a1 Enhance logging in Realtime utilities and add ping monitoring check in Register service 2024-09-25 21:50:50 +01:00
Simon Larsen
e9b611b19f Merge branch 'realtime' 2024-09-25 21:08:52 +01:00
Simon Larsen
700dbe2a4d Merge branch 'master' of github.com:OneUptime/oneuptime 2024-09-25 21:08:45 +01:00
Simon Larsen
3220a0ccb8 Merge pull request #1719 from Johncs2d/patch-1
Wrap Host with Quote so we can have wildcard domain
2024-09-25 21:00:04 +01:00
John Albert
63af60967e Wrap Host with Quote so we can have wildcard domain 2024-09-26 03:57:51 +08:00
snyk-bot
80d0993aff fix: Home/Dockerfile.tpl to reduce vulnerabilities 2024-09-22 10:34:58 +00:00
snyk-bot
da78c0bfee fix: Probe/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855502
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855502
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855503
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855503
- https://snyk.io/vuln/SNYK-DEBIAN12-EXPAT-7855507
2024-09-19 09:04:17 +00:00
snyk-bot
6ff776f185 fix: Accounts/package.json & Accounts/package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-PATHTOREGEXP-7925106
2024-09-18 09:44:20 +00:00
snyk-bot
96a5de2df2 fix: Probe/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-DEBIAN12-AOM-7197979
- https://snyk.io/vuln/SNYK-DEBIAN12-GIT-6846203
- https://snyk.io/vuln/SNYK-DEBIAN12-GIT-6846203
- https://snyk.io/vuln/SNYK-DEBIAN12-GIT-5461953
- https://snyk.io/vuln/SNYK-DEBIAN12-GIT-5461954
2024-09-18 09:32:27 +00:00
OneUptime Copilot
b1ce674788 OneUptime Copilot: Improve Comments on /App/Index.ts 2024-08-01 02:41:57 +00:00
346 changed files with 22678 additions and 11289 deletions

View File

@@ -3,7 +3,7 @@
#
# Pull base image nodejs image.
FROM node:21.2-alpine3.18
FROM public.ecr.aws/docker/library/node:21.2-alpine3.18
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-retries 5

View File

@@ -15,7 +15,7 @@ export default class ResourceUtil {
// Get all resources that should have documentation enabled
public static getResources(): Array<ModelDocumentation> {
const resources: Array<ModelDocumentation> = Models.filter(
(model: typeof BaseModel) => {
(model: { new (): BaseModel }) => {
const modelInstance: BaseModel = new model();
let showDocs: boolean = modelInstance.enableDocumentation;
@@ -27,7 +27,7 @@ export default class ResourceUtil {
return showDocs;
},
)
.map((model: typeof BaseModel) => {
.map((model: { new (): BaseModel }) => {
const modelInstance: BaseModel = new model();
return {

View File

@@ -3,7 +3,7 @@
#
# Pull base image nodejs image.
FROM node:21.7.3-alpine3.18
FROM public.ecr.aws/docker/library/node:21.7.3-alpine3.18
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-retries 5

View File

@@ -9,10 +9,9 @@
"version": "0.1.0",
"dependencies": {
"Common": "file:../Common",
"css-loader": "^6.11.0",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express": "^4.20.0",
"file-loader": "^6.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -117,6 +116,7 @@
"../CommonServer": {
"name": "@oneuptime/common-server",
"version": "1.0.0",
"extraneous": true,
"license": "Apache-2.0",
"dependencies": {
"@clickhouse/client": "^0.2.10",
@@ -725,9 +725,10 @@
}
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
@@ -737,7 +738,7 @@
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
@@ -751,6 +752,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -758,7 +760,23 @@
"node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/body-parser/node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
@@ -821,6 +839,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -829,6 +848,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -956,10 +976,6 @@
"resolved": "../Common",
"link": true
},
"node_modules/CommonServer": {
"resolved": "../CommonServer",
"link": true
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -981,6 +997,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -1068,6 +1085,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -1084,6 +1102,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -1092,6 +1111,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
@@ -1159,6 +1179,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.4"
},
@@ -1170,6 +1191,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
@@ -1235,6 +1257,7 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -1248,36 +1271,37 @@
}
},
"node_modules/express": {
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"version": "4.20.0",
"resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz",
"integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.2",
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"path-to-regexp": "0.1.10",
"proxy-addr": "~2.0.7",
"qs": "6.11.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"send": "0.19.0",
"serve-static": "1.16.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
@@ -1296,6 +1320,15 @@
"ms": "2.0.0"
}
},
"node_modules/express/node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/express/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -1383,6 +1416,7 @@
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -1405,6 +1439,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1413,6 +1448,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
@@ -1448,6 +1484,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
@@ -1473,6 +1510,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
},
@@ -1484,6 +1522,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -1495,6 +1534,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -1506,6 +1546,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
@@ -1517,6 +1558,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
@@ -1532,6 +1574,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -1559,7 +1602,8 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
@@ -1724,14 +1768,19 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
@@ -1762,6 +1811,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
},
@@ -1902,9 +1952,13 @@
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1929,9 +1983,10 @@
}
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.0.0",
@@ -2078,6 +2133,7 @@
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.4"
},
@@ -2100,6 +2156,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -2108,6 +2165,7 @@
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -2207,7 +2265,8 @@
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/sass-loader": {
"version": "13.3.3",
@@ -2285,9 +2344,10 @@
}
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -2311,6 +2371,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -2318,7 +2379,8 @@
"node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/serialize-javascript": {
"version": "6.0.1",
@@ -2329,9 +2391,10 @@
}
},
"node_modules/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz",
"integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==",
"license": "MIT",
"dependencies": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
@@ -2342,10 +2405,50 @@
"node": ">= 0.8.0"
}
},
"node_modules/serve-static/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/serve-static/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/serve-static/node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "2.4.1",
"range-parser": "~1.2.1",
"statuses": "2.0.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@@ -2361,12 +2464,14 @@
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/side-channel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@@ -2551,6 +2656,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
@@ -2633,6 +2739,7 @@
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"

View File

@@ -29,7 +29,7 @@
"Common": "file:../Common",
"css-loader": "^6.11.0",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express": "^4.20.0",
"file-loader": "^6.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",

File diff suppressed because one or more lines are too long

View File

@@ -73,7 +73,7 @@
width: auto;
}
</style>
<script src="https://cdn.tailwindcss.com"></script>
<script src="/accounts/assets/js/tailwind-3.4.5.js"></script>
<title>OneUptime Accounts</title>

View File

@@ -208,7 +208,7 @@ const LoginPage: () => JSX.Element = () => {
<div>
<Link to={new Route("/accounts/login")}>
<div className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm">
Use username and password insead.
Use username and password instead.
</div>
</Link>
</div>

View File

@@ -3,7 +3,7 @@
#
# Pull base image nodejs image.
FROM node:21.7.3-alpine3.18
FROM public.ecr.aws/docker/library/node:21.7.3-alpine3.18
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-retries 5

File diff suppressed because one or more lines are too long

View File

@@ -66,7 +66,7 @@
width: auto;
}
</style>
<script src="https://cdn.tailwindcss.com"></script>
<script src="/admin/assets/js/tailwind-3.4.5.js"></script>
<script src="/admin/env.js"></script>

View File

@@ -3,7 +3,7 @@
#
# Pull base image nodejs image.
FROM node:21.2-alpine3.18
FROM public.ecr.aws/docker/library/node:21.2-alpine3.18
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-retries 5

View File

@@ -13,6 +13,7 @@ import TelemetryAPI from "Common/Server/API/TelemetryAPI";
import Ingestor from "Common/Server/API/ProbeAPI";
import ProjectAPI from "Common/Server/API/ProjectAPI";
import ProjectSsoAPI from "Common/Server/API/ProjectSSO";
// Import API
import ResellerPlanAPI from "Common/Server/API/ResellerPlanAPI";
import ShortLinkAPI from "Common/Server/API/ShortLinkAPI";
@@ -21,6 +22,7 @@ import StatusPageDomainAPI from "Common/Server/API/StatusPageDomainAPI";
import StatusPageSubscriberAPI from "Common/Server/API/StatusPageSubscriberAPI";
import UserCallAPI from "Common/Server/API/UserCallAPI";
import UserTwoFactorAuthAPI from "Common/Server/API/UserTwoFactorAuthAPI";
import MonitorTest from "Common/Models/DatabaseModels/MonitorTest";
// User Notification methods.
import UserEmailAPI from "Common/Server/API/UserEmailAPI";
import UserNotificationLogTimelineAPI from "Common/Server/API/UserOnCallLogTimelineAPI";
@@ -46,6 +48,40 @@ import TelemetryIngestionKeyService, {
import EmailVerificationTokenService, {
Service as EmailVerificationTokenServiceType,
} from "Common/Server/Services/EmailVerificationTokenService";
import AlertCustomFieldService, {
Service as AlertCustomFieldServiceType,
} from "Common/Server/Services/AlertCustomFieldService";
import AlertInternalNoteService, {
Service as AlertInternalNoteServiceType,
} from "Common/Server/Services/AlertInternalNoteService";
import AlertNoteTemplateService, {
Service as AlertNoteTemplateServiceType,
} from "Common/Server/Services/AlertNoteTemplateService";
import AlertOwnerTeamService, {
Service as AlertOwnerTeamServiceType,
} from "Common/Server/Services/AlertOwnerTeamService";
import DashboardService, {
Service as DashboardServiceType,
} from "Common/Server/Services/DashboardService";
import AlertOwnerUserService, {
Service as AlertOwnerUserServiceType,
} from "Common/Server/Services/AlertOwnerUserService";
import AlertService, {
Service as AlertServiceType,
} from "Common/Server/Services/AlertService";
import AlertSeverityService, {
Service as AlertSeverityServiceType,
} from "Common/Server/Services/AlertSeverityService";
import AlertStateService, {
Service as AlertStateServiceType,
} from "Common/Server/Services/AlertStateService";
import AlertStateTimelineService, {
Service as AlertStateTimelineServiceType,
} from "Common/Server/Services/AlertStateTimelineService";
import IncidentCustomFieldService, {
Service as IncidentCustomFieldServiceType,
} from "Common/Server/Services/IncidentCustomFieldService";
@@ -55,6 +91,9 @@ import IncidentInternalNoteService, {
import IncidentNoteTemplateService, {
Service as IncidentNoteTemplateServiceType,
} from "Common/Server/Services/IncidentNoteTemplateService";
import TableViewService, {
Service as TableViewServiceType,
} from "Common/Server/Services/TableViewService";
import IncidentOwnerTeamService, {
Service as IncidentOwnerTeamServiceType,
} from "Common/Server/Services/IncidentOwnerTeamService";
@@ -73,6 +112,9 @@ import IncidentSeverityService, {
import IncidentStateService, {
Service as IncidentStateServiceType,
} from "Common/Server/Services/IncidentStateService";
import MonitorTestService, {
Service as MonitorTestServiceType,
} from "Common/Server/Services/MonitorTestService";
import IncidentStateTimelineService, {
Service as IncidentStateTimelineServiceType,
} from "Common/Server/Services/IncidentStateTimelineService";
@@ -342,6 +384,18 @@ import CallLog from "Common/Models/DatabaseModels/CallLog";
import Domain from "Common/Models/DatabaseModels/Domain";
import EmailLog from "Common/Models/DatabaseModels/EmailLog";
import EmailVerificationToken from "Common/Models/DatabaseModels/EmailVerificationToken";
import Dashboard from "Common/Models/DatabaseModels/Dashboard";
import Alert from "Common/Models/DatabaseModels/Alert";
import AlertCustomField from "Common/Models/DatabaseModels/AlertCustomField";
import AlertInternalNote from "Common/Models/DatabaseModels/AlertInternalNote";
import AlertNoteTemplate from "Common/Models/DatabaseModels/AlertNoteTemplate";
import AlertOwnerTeam from "Common/Models/DatabaseModels/AlertOwnerTeam";
import AlertOwnerUser from "Common/Models/DatabaseModels/AlertOwnerUser";
import AlertSeverity from "Common/Models/DatabaseModels/AlertSeverity";
import AlertState from "Common/Models/DatabaseModels/AlertState";
import AlertStateTimeline from "Common/Models/DatabaseModels/AlertStateTimeline";
import Incident from "Common/Models/DatabaseModels/Incident";
import IncidentCustomField from "Common/Models/DatabaseModels/IncidentCustomField";
import IncidentInternalNote from "Common/Models/DatabaseModels/IncidentInternalNote";
@@ -355,6 +409,7 @@ import IncidentStateTimeline from "Common/Models/DatabaseModels/IncidentStateTim
import IncidentTemplate from "Common/Models/DatabaseModels/IncidentTemplate";
import IncidentTemplateOwnerTeam from "Common/Models/DatabaseModels/IncidentTemplateOwnerTeam";
import IncidentTemplateOwnerUser from "Common/Models/DatabaseModels/IncidentTemplateOwnerUser";
import Label from "Common/Models/DatabaseModels/Label";
import Monitor from "Common/Models/DatabaseModels/Monitor";
import MonitorCustomField from "Common/Models/DatabaseModels/MonitorCustomField";
@@ -443,6 +498,7 @@ import ScheduledMaintenanceTemplateOwnerTeamService, {
import ScheduledMaintenanceTemplateOwnerUserService, {
Service as ScheduledMaintenanceTemplateOwnerUserServiceType,
} from "Common/Server/Services/ScheduledMaintenanceTemplateOwnerUserService";
import TableView from "Common/Models/DatabaseModels/TableView";
const BaseAPIFeatureSet: FeatureSet = {
init: async (): Promise<void> => {
@@ -458,6 +514,83 @@ const BaseAPIFeatureSet: FeatureSet = {
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertState, AlertStateServiceType>(
AlertState,
AlertStateService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<MonitorTest, MonitorTestServiceType>(
MonitorTest,
MonitorTestService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertNoteTemplate, AlertNoteTemplateServiceType>(
AlertNoteTemplate,
AlertNoteTemplateService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<Alert, AlertServiceType>(Alert, AlertService).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertSeverity, AlertSeverityServiceType>(
AlertSeverity,
AlertSeverityService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertOwnerTeam, AlertOwnerTeamServiceType>(
AlertOwnerTeam,
AlertOwnerTeamService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertOwnerUser, AlertOwnerUserServiceType>(
AlertOwnerUser,
AlertOwnerUserService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertCustomField, AlertCustomFieldServiceType>(
AlertCustomField,
AlertCustomFieldService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertInternalNote, AlertInternalNoteServiceType>(
AlertInternalNote,
AlertInternalNoteService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertStateTimeline, AlertStateTimelineServiceType>(
AlertStateTimeline,
AlertStateTimelineService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAnalyticsAPI<ExceptionInstance, ExceptionInstanceServiceType>(
@@ -524,6 +657,14 @@ const BaseAPIFeatureSet: FeatureSet = {
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<Dashboard, DashboardServiceType>(
Dashboard,
DashboardService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAnalyticsAPI<Metric, MetricServiceType>(
@@ -776,6 +917,14 @@ const BaseAPIFeatureSet: FeatureSet = {
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<TableView, TableViewServiceType>(
TableView,
TableViewService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentState, IncidentStateServiceType>(

View File

@@ -27,8 +27,10 @@ import StatusPagePrivateUser from "Common/Models/DatabaseModels/StatusPagePrivat
import StatusPageSSO from "Common/Models/DatabaseModels/StatusPageSso";
import xml2js from "xml2js";
// Initialize Express router.
const router: ExpressRouter = Express.getRouter();
// Define a GET route for SSO in a status page context.
router.get(
"/status-page-sso/:statusPageId/:statusPageSsoId",
async (
@@ -37,6 +39,7 @@ router.get(
next: NextFunction,
): Promise<void> => {
try {
// Check if statusPageId parameter is present.
if (!req.params["statusPageId"]) {
return Response.sendErrorResponse(
req,
@@ -45,6 +48,7 @@ router.get(
);
}
// Check if statusPageSsoId parameter is present.
if (!req.params["statusPageSsoId"]) {
return Response.sendErrorResponse(
req,
@@ -53,14 +57,16 @@ router.get(
);
}
// Create ObjectID instance from statusPageId parameter.
const statusPageId: ObjectID = new ObjectID(req.params["statusPageId"]);
// Find SSO record in the database with specific query parameters.
const statusPageSSO: StatusPageSSO | null =
await StatusPageSsoService.findOneBy({
query: {
statusPageId: statusPageId,
_id: req.params["statusPageSsoId"],
isEnabled: true,
statusPageId: statusPageId, // Ensure that statusPageId matches.
_id: req.params["statusPageSsoId"], // Ensure SSO ID matches.
isEnabled: true, // Ensure the SSO is enabled.
},
select: {
signOnURL: true,
@@ -235,6 +241,7 @@ router.post(
if (statusPageSSO.issuerURL.toString() !== issuerUrl) {
return Response.sendErrorResponse(
req,
res,
new BadRequestException("Issuer URL does not match"),
);
@@ -285,6 +292,7 @@ router.post(
res,
CookieUtil.getUserTokenKey(alreadySavedUser.statusPageId!),
token,
{
httpOnly: true,
maxAge: OneUptimeDate.getMillisecondsInDays(new PositiveNumber(30)),

View File

@@ -0,0 +1,37 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> InfoBlock info=(concat "A new alert has been created in the project - " projectName)}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Alert Title:" text=alertTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Severity: " text=alertSeverity }}
{{> DetailBoxField title="Root Cause: " text="" }}
{{> DetailBoxField title="" text=rootCause }}
{{> DetailBoxField title="Description: " text="" }}
{{> DetailBoxField title="" text=alertDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="ACTION REQUIRED: Please acknowledge this alert by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=acknowledgeAlertLink buttonText="Acknowledge Alert"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=acknowledgeAlertLink}}
{{> InfoBlock info="You will be notified when the status of this alert changes."}}
{{> TitleBlock title="Why am I receiving this email?"}}
{{> InfoBlock info="You are receiving this email because you are a member of the team that is responsible for this alert or you are currently on-call."}}
{{> Footer this }}
{{> End this}}

View File

@@ -0,0 +1,32 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> InfoBlock info="You have been added as the owner of this alert."}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Alert Title:" text=alertTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Severity: " text=alertSeverity }}
{{> DetailBoxField title="Description: " text="" }}
{{> DetailBoxField title="" text=alertDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this alert by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=alertViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=alertViewLink}}
{{> InfoBlock info="You will be notified when the status of this alert changes."}}
{{> Footer this }}
{{> End this}}

View File

@@ -0,0 +1,39 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> InfoBlock info="A new note has been posted on this alert."}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Alert Title:" text=alertTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Severity: " text=alertSeverity }}
{{#if isPrivateNote}}
{{> DetailBoxField title="Private Note: " text="" }}
{{else}}
{{> DetailBoxField title="Public Note: " text="" }}
{{/if}}
{{> DetailBoxField title="" text=note }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this alert by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=alertViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=alertViewLink}}
{{> InfoBlock info="You will be notified when the status of this alert changes."}}
{{> OwnerInfo this }}
{{> UnsubscribeOwnerEmail this }}
{{> Footer this }}
{{> End this}}

View File

@@ -0,0 +1,44 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> InfoBlock info=(concat "A new alert has been created in the project - " projectName)}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Alert Title:" text=alertTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Alert Declared By: " text=declaredBy }}
{{> DetailBoxField title="Alert Declared At: " text="" }}
{{> DetailBoxField title="" text=declaredAt }}
{{> DetailBoxField title="Severity: " text=alertSeverity }}
{{> DetailBoxField title="Root Cause: " text="" }}
{{> DetailBoxField title="" text=rootCause }}
{{> DetailBoxField title="Description: " text="" }}
{{> DetailBoxField title="" text=alertDescription }}
{{#ifNotCond remediationNotes ""}}
{{> DetailBoxField title="Remediation Notes: " text="" }}
{{> DetailBoxField title="" text=remediationNotes }}
{{/ifNotCond}}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this alert by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=alertViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=alertViewLink}}
{{> InfoBlock info="You will be notified when the status of this alert changes."}}
{{> OwnerInfo this }}
{{> UnsubscribeOwnerEmail this }}
{{> Footer this }}
{{> End this}}

View File

@@ -0,0 +1,37 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> InfoBlock info=(concat "Alert state changed to - " currentState)}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Alert Title:" text=alertTitle }}
{{> DetailBoxField title="New State: " text=currentState }}
{{> DetailBoxField title="State changed at: " text="" }}
{{> DetailBoxField title="" text=stateChangedAt }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Severity: " text=alertSeverity }}
{{> DetailBoxField title="Description: " text="" }}
{{> DetailBoxField title="" text=alertDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this alert by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=alertViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=alertViewLink}}
{{> InfoBlock info="You will be notified when the status of this alert changes."}}
{{> OwnerInfo this }}
{{> UnsubscribeOwnerEmail this }}
{{> Footer this }}
{{> End this}}

View File

@@ -68,6 +68,7 @@ const init: PromiseVoidFunction = async (): Promise<void> => {
}
};
// Call the initialization function and handle errors
init().catch((err: Error) => {
logger.error(err);
logger.error("Exiting node process");

View File

@@ -1,3 +1,4 @@
import EnableRealtimeEventsOn from "../../../Types/Realtime/EnableRealtimeEventsOn";
import Route from "../../../Types/API/Route";
import AnalyticsTableEngine from "../../../Types/AnalyticsDatabase/AnalyticsTableEngine";
import AnalyticsTableColumn from "../../../Types/AnalyticsDatabase/TableColumn";
@@ -19,7 +20,6 @@ import Permission, {
UserTenantAccessPermission,
} from "../../../Types/Permission";
import Text from "../../../Types/Text";
import { EnableRealtimeEventsOn } from "../../../Utils/Realtime";
import CommonModel from "./CommonModel";
export type AnalyticsBaseModelType = { new (): AnalyticsBaseModel };

View File

@@ -25,7 +25,7 @@ export const getModelTypeByName: GetModelTypeByName = (
tableName: string,
): (new () => AnalyticsBaseModel) | null => {
if (modelTypeMap[tableName]) {
return modelTypeMap[tableName];
return modelTypeMap[tableName] || null;
}
const modelType: { new (): AnalyticsBaseModel } | undefined =

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,340 @@
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
import CustomFieldType from "../../Types/CustomField/CustomFieldType";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
import ColumnLength from "../../Types/Database/ColumnLength";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import UniqueColumnBy from "../../Types/Database/UniqueColumnBy";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
@EnableDocumentation()
@TableBillingAccessControl({
create: PlanType.Growth,
read: PlanType.Growth,
update: PlanType.Growth,
delete: PlanType.Growth,
})
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.DeleteAlertCustomField,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditAlertCustomField,
],
})
@CrudApiEndpoint(new Route("/alert-custom-field"))
@TableMetadata({
tableName: "AlertCustomField",
singularName: "Alert Custom Field",
pluralName: "Alert Custom Fields",
icon: IconProp.TableCells,
tableDescription: "Manage custom fields for your alert.",
})
@Entity({
name: "AlertCustomField",
})
export default class AlertCustomField extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditAlertCustomField,
],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
canReadOnRelationQuery: true,
title: "Name",
description: "Any friendly name of this object",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
@UniqueColumnBy("projectId")
public name?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditAlertCustomField,
],
})
@TableColumn({
required: false,
type: TableColumnType.LongText,
title: "Description",
description:
"Friendly description of this custom field that will help you remember",
})
@Column({
nullable: true,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public description?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [],
})
@TableColumn({
required: false,
type: TableColumnType.CustomFieldType,
title: "Custom Field Type",
description: "Is this field Text, Number or Boolean?",
})
@Column({
nullable: true,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
public type?: CustomFieldType = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateAlertCustomField,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
}

View File

@@ -0,0 +1,371 @@
import Alert from "./Alert";
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
@EnableDocumentation()
@CanAccessIfCanReadOn("alert")
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertInternalNote,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertInternalNote,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-internal-note"))
@Entity({
name: "AlertInternalNote",
})
@TableMetadata({
tableName: "AlertInternalNote",
singularName: "Alert Internal Note",
pluralName: "Alert Internal Notes",
icon: IconProp.Lock,
tableDescription: "Manage internal notes for your alert",
})
export default class AlertInternalNote extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertId",
type: TableColumnType.Entity,
modelType: Alert,
title: "Alert",
description: "Relation to Alert in which this resource belongs",
})
@ManyToOne(
() => {
return Alert;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertId" })
public alert?: Alert = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
title: "Alert ID",
description: "Relation to Alert ID in which this resource belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertInternalNote,
],
})
@TableColumn({
type: TableColumnType.Markdown,
title: "Note",
description: "Notes in markdown",
})
@Column({
type: ColumnType.Markdown,
nullable: false,
unique: false,
})
public note?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of this resource ownership?",
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
}

View File

@@ -0,0 +1,352 @@
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import ColumnLength from "../../Types/Database/ColumnLength";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
@TableBillingAccessControl({
create: PlanType.Growth,
read: PlanType.Growth,
update: PlanType.Growth,
delete: PlanType.Growth,
})
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertNoteTemplate,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertNoteTemplate,
],
})
@CrudApiEndpoint(new Route("/alert-note-template"))
@Entity({
name: "AlertNoteTemplate",
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@TableMetadata({
tableName: "AlertNoteTemplate",
singularName: "Alert Note Template",
pluralName: "Alert Note Templates",
icon: IconProp.Alert,
tableDescription: "Manage alert note templates for your project",
})
export default class AlertNoteTemplate extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertNoteTemplate,
],
})
@Index()
@TableColumn({
type: TableColumnType.Markdown,
title: "Note",
description:
"Note template for public or private notes. This is in markdown.",
})
@Column({
type: ColumnType.Markdown,
nullable: false,
unique: false,
})
public note?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertNoteTemplate,
],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
canReadOnRelationQuery: true,
title: "Name",
description: "Name of the Alert Template",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
public templateName?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertNoteTemplate,
],
})
@TableColumn({
required: true,
type: TableColumnType.LongText,
canReadOnRelationQuery: true,
title: "Template Description",
description: "Description of the Alert Template",
})
@Column({
nullable: false,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public templateDescription?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertNoteTemplate,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
}

View File

@@ -0,0 +1,416 @@
import Alert from "./Alert";
import Project from "./Project";
import Team from "./Team";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertOwnerTeam,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertOwnerTeam,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-owner-team"))
@TableMetadata({
tableName: "AlertOwnerTeam",
singularName: "Alert Team Owner",
pluralName: "Alert Team Owners",
icon: IconProp.Signal,
tableDescription: "Add teams as owners to your alerts.",
})
@Entity({
name: "AlertOwnerTeam",
})
export default class AlertOwnerTeam extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: false,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "teamId",
type: TableColumnType.Entity,
modelType: Team,
title: "Team",
description:
"Team that is the owner. All users in this team will receive notifications. ",
})
@ManyToOne(
() => {
return Team;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "teamId" })
public team?: Team = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Team ID",
description: "ID of your OneUptime Team in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public teamId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertId",
type: TableColumnType.Entity,
modelType: Alert,
title: "Alert",
description: "Relation to Alert Resource in which this object belongs",
})
@ManyToOne(
() => {
return Alert;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertId" })
public alert?: Alert = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Alert ID",
description: "ID of your OneUptime Alert in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of this resource ownership?",
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
}

View File

@@ -0,0 +1,415 @@
import Alert from "./Alert";
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertOwnerUser,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertOwnerUser,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-owner-user"))
@TableMetadata({
tableName: "AlertOwnerUser",
singularName: "Alert User Owner",
pluralName: "Alert User Owners",
icon: IconProp.Signal,
tableDescription: "Add users as owners to your alerts.",
})
@Entity({
name: "AlertOwnerUser",
})
export default class AlertOwnerUser extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: false,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "userId",
type: TableColumnType.Entity,
modelType: User,
title: "User",
description:
"User that is the owner. This user will receive notifications. ",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "userId" })
public user?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "User ID",
description: "ID of your OneUptime User in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public userId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertId",
type: TableColumnType.Entity,
modelType: Alert,
title: "Alert",
description: "Relation to Alert Resource in which this object belongs",
})
@ManyToOne(
() => {
return Alert;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertId" })
public alert?: Alert = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Alert ID",
description: "ID of your OneUptime Alert in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of this resource ownership?",
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
}

View File

@@ -0,0 +1,426 @@
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
import Color from "../../Types/Color";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
import ColumnLength from "../../Types/Database/ColumnLength";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import SlugifyColumn from "../../Types/Database/SlugifyColumn";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import UniqueColumnBy from "../../Types/Database/UniqueColumnBy";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
@TableBillingAccessControl({
create: PlanType.Growth,
read: PlanType.Free,
update: PlanType.Growth,
delete: PlanType.Growth,
})
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertSeverity,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertSeverity,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-severity"))
@SlugifyColumn("name", "slug")
@TableMetadata({
tableName: "AlertSeverity",
singularName: "Alert Severity",
pluralName: "Alert Severities",
icon: IconProp.Alert,
tableDescription:
"Manage alert severity for your project (Created, Acknowledged for example). Add / edit or remove severities.",
})
@Entity({
name: "AlertSeverity",
})
export default class AlertSeverity extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertSeverity,
],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
canReadOnRelationQuery: true,
title: "Name",
description: "Any friendly name of this object",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
@UniqueColumnBy("projectId")
public name?: string = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [],
})
@TableColumn({
required: true,
unique: true,
type: TableColumnType.Slug,
title: "Slug",
description: "Friendly globally unique name for your object",
})
@Column({
nullable: false,
type: ColumnType.Slug,
length: ColumnLength.Slug,
})
public slug?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertSeverity,
],
})
@TableColumn({
required: false,
type: TableColumnType.LongText,
title: "Description",
description: "Friendly description that will help you remember",
})
@Column({
nullable: true,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public description?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertSeverity,
],
})
@TableColumn({
title: "Color",
required: true,
unique: false,
type: TableColumnType.Color,
canReadOnRelationQuery: true,
description: "Color of this resource in Hex (#32a852 for example)",
})
@Column({
type: ColumnType.Color,
length: ColumnLength.Color,
unique: false,
nullable: false,
transformer: Color.getDatabaseTransformer(),
})
public color?: Color = undefined;
@UniqueColumnBy("projectId")
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertSeverity,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertSeverity,
],
})
@TableColumn({
isDefaultValueColumn: false,
type: TableColumnType.SmallNumber,
title: "Order",
description: "Order / Priority of this resource",
})
@Column({
type: ColumnType.SmallNumber,
})
public order?: number = undefined;
}

View File

@@ -0,0 +1,502 @@
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
import Color from "../../Types/Color";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
import ColumnLength from "../../Types/Database/ColumnLength";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import SlugifyColumn from "../../Types/Database/SlugifyColumn";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import UniqueColumnBy from "../../Types/Database/UniqueColumnBy";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
@TableBillingAccessControl({
create: PlanType.Growth,
read: PlanType.Free,
update: PlanType.Growth,
delete: PlanType.Free,
})
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-state"))
@SlugifyColumn("name", "slug")
@TableMetadata({
tableName: "AlertState",
singularName: "Alert State",
pluralName: "Alert States",
icon: IconProp.ArrowCircleRight,
tableDescription:
"Manage alert states for your project (Created, Acknowledged for example). Add / edit or remove states.",
})
@Entity({
name: "AlertState",
})
export default class AlertState extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
canReadOnRelationQuery: true,
title: "Name",
description: "Any friendly name of this object",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
@UniqueColumnBy("projectId")
public name?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@TableColumn({
required: false,
type: TableColumnType.LongText,
title: "Description",
description: "Friendly description that will help you remember",
})
@Column({
nullable: true,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public description?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@TableColumn({
title: "Color",
required: true,
unique: false,
type: TableColumnType.Color,
canReadOnRelationQuery: true,
description: "Color of this resource in Hex (#32a852 for example)",
})
@Column({
type: ColumnType.Color,
length: ColumnLength.Color,
unique: false,
nullable: false,
transformer: Color.getDatabaseTransformer(),
})
public color?: Color = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@TableColumn({
isDefaultValueColumn: false,
type: TableColumnType.Boolean,
canReadOnRelationQuery: true,
title: "Is Created State",
description: "Is it the created state of the alert?",
})
@Column({
type: ColumnType.Boolean,
default: false,
})
public isCreatedState?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@TableColumn({
isDefaultValueColumn: false,
type: TableColumnType.Boolean,
canReadOnRelationQuery: true,
title: "Is Acknowledged State",
description: "Is it the acknowledged state of the alert?",
})
@Column({
type: ColumnType.Boolean,
default: false,
})
public isAcknowledgedState?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@TableColumn({
isDefaultValueColumn: false,
type: TableColumnType.Boolean,
canReadOnRelationQuery: true,
title: "Is Resolved State",
description: "Is it the resolved state of the alert?",
})
@Column({
type: ColumnType.Boolean,
default: false,
})
public isResolvedState?: boolean = undefined;
@UniqueColumnBy("projectId")
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertState,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertState,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertState,
],
})
@TableColumn({
isDefaultValueColumn: false,
type: TableColumnType.SmallNumber,
canReadOnRelationQuery: true,
title: "Order",
description: "Order / Priority of this resource",
})
@Column({
type: ColumnType.SmallNumber,
})
public order?: number = undefined;
}

View File

@@ -0,0 +1,525 @@
import Alert from "./Alert";
import AlertState from "./AlertState";
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import IconProp from "../../Types/Icon/IconProp";
import { JSONObject } from "../../Types/JSON";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
@EnableDocumentation()
@CanAccessIfCanReadOn("alert")
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertStateTimeline,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertStateTimeline,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-state-timeline"))
@Entity({
name: "AlertStateTimeline",
})
@TableMetadata({
tableName: "AlertStateTimeline",
singularName: "Alert State Timeline",
pluralName: "Alert State Timelines",
icon: IconProp.List,
tableDescription:
"Change state of the alerts (Created to Acknowledged for example)",
})
export default class AlertStateTimeline extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertId",
type: TableColumnType.Entity,
modelType: Alert,
title: "Alert",
description: "Relation to Alert in which this resource belongs",
})
@ManyToOne(
() => {
return Alert;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertId" })
public alert?: Alert = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
title: "Alert ID",
description: "Relation to Alert ID in which this resource belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertStateTimeline,
],
})
@TableColumn({
manyToOneRelationColumn: "alertStateId",
type: TableColumnType.Entity,
modelType: AlertState,
title: "Alert State",
description:
"Alert State Relation. Which alert state does this alert change to?",
})
@ManyToOne(
() => {
return AlertState;
},
{
eager: false,
nullable: true,
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertStateId" })
public alertState?: AlertState = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertStateTimeline,
],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
title: "Alert State ID",
description:
"Alert State ID Relation. Which alert state does this alert change to?",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertStateId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of state change?",
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@TableColumn({
isDefaultValueColumn: false,
required: false,
type: TableColumnType.JSON,
})
@Column({
type: ColumnType.JSON,
nullable: true,
unique: false,
})
public stateChangeLog?: JSONObject = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Markdown,
required: false,
isDefaultValueColumn: false,
title: "Root Cause",
description: "What is the root cause of this status change?",
})
@Column({
type: ColumnType.Markdown,
nullable: true,
})
public rootCause?: string = undefined;
@Index()
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@TableColumn({
type: TableColumnType.Date,
title: "Ends At",
description: "When did this status change end?",
})
@Column({
type: ColumnType.Date,
nullable: true,
unique: false,
})
public endsAt?: Date = undefined;
@Index()
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertStateTimeline,
],
update: [],
})
@TableColumn({
type: TableColumnType.Date,
title: "Starts At",
description: "When did this status change start?",
})
@Column({
type: ColumnType.Date,
nullable: true,
unique: false,
})
public startsAt?: Date = undefined;
}

View File

@@ -41,7 +41,6 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
create: true,
delete: false,
update: false,
read: true,
})
@TableMetadata({
tableName: "CallLog",

View File

@@ -58,7 +58,6 @@ import CopilotActionProp from "../../Types/Copilot/CopilotActionProps/Index";
create: true,
delete: false,
update: true,
read: false,
})
@CrudApiEndpoint(new Route("/copilot-action"))
@TableMetadata({

View File

@@ -54,7 +54,6 @@ import ColumnLength from "../../Types/Database/ColumnLength";
create: true,
delete: false,
update: true,
read: false,
})
@CrudApiEndpoint(new Route("/copilot-action-type-prority"))
@TableMetadata({

View File

@@ -40,7 +40,6 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
create: true,
delete: false,
update: true,
read: false,
})
@CrudApiEndpoint(new Route("/copilot-pull-request"))
@TableMetadata({

View File

@@ -0,0 +1,426 @@
import Project from "./Project";
import User from "./User";
import Route from "../../Types/API/Route";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import ColumnLength from "../../Types/Database/ColumnLength";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import SlugifyColumn from "../../Types/Database/SlugifyColumn";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import UniqueColumnBy from "../../Types/Database/UniqueColumnBy";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import {
Column,
Entity,
Index,
JoinColumn,
JoinTable,
ManyToMany,
ManyToOne,
} from "typeorm";
import AccessControlColumn from "../../Types/Database/AccessControlColumn";
import Label from "./Label";
import DashboardViewConfig from "../../Types/Dashboard/DashboardViewConfig";
@AccessControlColumn("labels")
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.DeleteDashboard,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditDashboard,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/dashboard"))
@SlugifyColumn("name", "slug")
@TableMetadata({
tableName: "Dashboard",
singularName: "Dashboard",
pluralName: "Dashboards",
icon: IconProp.Window,
tableDescription:
"Create and manage Dashboards to visualize your data in a single place",
})
@Entity({
name: "Dashboard",
})
export default class Dashboard extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditDashboard,
],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
canReadOnRelationQuery: true,
title: "Name",
description: "Any friendly name of this object",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
@UniqueColumnBy("projectId")
public name?: string = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [],
})
@TableColumn({
required: true,
unique: true,
type: TableColumnType.Slug,
title: "Slug",
description: "Friendly globally unique name for your object",
})
@Column({
nullable: false,
type: ColumnType.Slug,
length: ColumnLength.Slug,
})
public slug?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditDashboard,
],
})
@TableColumn({
required: false,
type: TableColumnType.LongText,
title: "Description",
description: "Friendly description that will help you remember",
})
@Column({
nullable: true,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public description?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditDashboard,
],
})
@TableColumn({
required: false,
type: TableColumnType.EntityArray,
modelType: Label,
title: "Labels",
description:
"Relation to Labels Array where this object is categorized in.",
})
@ManyToMany(
() => {
return Label;
},
{ eager: false },
)
@JoinTable({
name: "DashboardLabel",
inverseJoinColumn: {
name: "labelId",
referencedColumnName: "_id",
},
joinColumn: {
name: "dashboardId",
referencedColumnName: "_id",
},
})
public labels?: Array<Label> = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateDashboard,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadDashboard,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditDashboard,
],
})
@TableColumn({
required: true,
type: TableColumnType.JSON,
title: "Dashboard View Config",
description: "Configuration of Dashboard View",
})
@Column({
nullable: false,
type: ColumnType.JSON,
})
public dashboardViewConfig?: DashboardViewConfig = undefined;
}

View File

@@ -1,3 +1,4 @@
import EnableRealtimeEventsOn from "../../../Types/Realtime/EnableRealtimeEventsOn";
import Route from "../../../Types/API/Route";
import { ColumnAccessControl } from "../../../Types/BaseDatabase/AccessControl";
import ColumnBillingAccessControl from "../../../Types/BaseDatabase/ColumnBillingAccessControl";
@@ -36,7 +37,6 @@ import {
UpdateDateColumn,
VersionColumn,
} from "typeorm";
import { EnableRealtimeEventsOn } from "../../../Utils/Realtime";
export type DbTypes =
| string

View File

@@ -42,7 +42,6 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
create: true,
delete: false,
update: false,
read: true,
})
@TableMetadata({
tableName: "EmailLog",

View File

@@ -36,16 +36,7 @@ import {
ManyToMany,
ManyToOne,
} from "typeorm";
import TelemetryType from "../../Types/Telemetry/TelemetryType";
import Query from "../../Types/BaseDatabase/Query";
import Log from "../AnalyticsModels/Log";
import Span from "../AnalyticsModels/Span";
import Metric from "../AnalyticsModels/Metric";
export interface TelemetryIncidentQuery {
telemetryType: TelemetryType;
telemetryQuery: Query<Log> | Query<Span> | Query<Metric>;
}
import { TelemetryQuery } from "../../Types/Telemetry/TelemetryQuery";
@EnableDocumentation()
@AccessControlColumn("labels")
@@ -1095,5 +1086,5 @@ export default class Incident extends BaseModel {
type: ColumnType.JSON,
nullable: true,
})
public telemetryQuery?: TelemetryIncidentQuery = undefined;
public telemetryQuery?: TelemetryQuery = undefined;
}

View File

@@ -142,6 +142,19 @@ import ScheduledMaintenanceTemplateOwnerTeam from "./ScheduledMaintenanceTemplat
import ScheduledMaintenanceTemplateOwnerUser from "./ScheduledMaintenanceTemplateOwnerUser";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import AlertState from "./AlertState";
import Alert from "./Alert";
import AlertCustomField from "./AlertCustomField";
import AlertStateTimeline from "./AlertStateTimeline";
import AlertInternalNote from "./AlertInternalNote";
import AlertOwnerTeam from "./AlertOwnerTeam";
import AlertOwnerUser from "./AlertOwnerUser";
import AlertSeverity from "./AlertSeverity";
import AlertNoteTemplate from "./AlertNoteTemplate";
import TableView from "./TableView";
import Dashboard from "./Dashboard";
import MonitorTest from "./MonitorTest";
const AllModelTypes: Array<{
new (): BaseModel;
@@ -176,9 +189,28 @@ const AllModelTypes: Array<{
Incident,
IncidentCustomField,
IncidentStateTimeline,
MonitorStatusTimeline,
IncidentPublicNote,
IncidentInternalNote,
IncidentPublicNote,
IncidentTemplate,
IncidentTemplateOwnerTeam,
IncidentTemplateOwnerUser,
IncidentOwnerTeam,
IncidentOwnerUser,
IncidentSeverity,
IncidentNoteTemplate,
AlertState,
Alert,
AlertCustomField,
AlertStateTimeline,
AlertInternalNote,
AlertOwnerTeam,
AlertOwnerUser,
AlertSeverity,
AlertNoteTemplate,
MonitorStatusTimeline,
File,
Domain,
@@ -186,7 +218,7 @@ const AllModelTypes: Array<{
StatusPageDomain,
StatusPageCustomField,
StatusPageResource,
IncidentSeverity,
StatusPageAnnouncement,
StatusPageSubscriber,
StatusPageFooterLink,
@@ -219,9 +251,6 @@ const AllModelTypes: Array<{
MonitorOwnerTeam,
MonitorOwnerUser,
IncidentOwnerTeam,
IncidentOwnerUser,
ScheduledMaintenanceOwnerTeam,
ScheduledMaintenanceOwnerUser,
@@ -245,12 +274,6 @@ const AllModelTypes: Array<{
ShortLink,
IncidentTemplate,
IncidentTemplateOwnerTeam,
IncidentTemplateOwnerUser,
IncidentNoteTemplate,
ScheduledMaintenanceTemplate,
ScheduledMaintenanceTemplateOwnerTeam,
ScheduledMaintenanceTemplateOwnerUser,
@@ -305,6 +328,13 @@ const AllModelTypes: Array<{
TelemetryIngestionKey,
TelemetryException,
TableView,
// Dashboards
Dashboard,
MonitorTest,
];
const modelTypeMap: { [key: string]: { new (): BaseModel } } = {};
@@ -317,7 +347,7 @@ export const getModelTypeByName: GetModelTypeByNameFunction = (
tableName: string,
): { new (): BaseModel } | null => {
if (modelTypeMap[tableName]) {
return modelTypeMap[tableName];
return modelTypeMap[tableName] || null;
}
const modelType: { new (): BaseModel } | undefined = AllModelTypes.find(

View File

@@ -0,0 +1,477 @@
import Project from "./Project";
import User from "./User";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Route from "../../Types/API/Route";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import ColumnLength from "../../Types/Database/ColumnLength";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import SlugifyColumn from "../../Types/Database/SlugifyColumn";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import IconProp from "../../Types/Icon/IconProp";
import MonitorSteps from "../../Types/Monitor/MonitorSteps";
import MonitorType from "../../Types/Monitor/MonitorType";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
import { MonitorStepProbeResponse } from "./MonitorProbe";
import Probe from "./Probe";
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteProjectMonitor,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectMonitor,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/monitor-test"))
@SlugifyColumn("name", "slug")
@Entity({
name: "MonitorTest",
})
@TableMetadata({
tableName: "MonitorTest",
singularName: "Monitor Test",
pluralName: "Monitor Tests",
icon: IconProp.AltGlobe,
tableDescription:
"Monitor Test allows you to test monitor configurations before you save them.",
})
export default class MonitorTest extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [],
})
@TableColumn({
required: true,
type: TableColumnType.MonitorType,
title: "Monitor Type",
description: "What is the type of this monitor? Website? API? etc.",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
public monitorType?: MonitorType = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectMonitor,
],
})
@TableColumn({
type: TableColumnType.JSON,
required: false,
title: "Monitor Steps",
description: "What would you like to monitor and what is the criteria?",
})
@Column({
type: ColumnType.JSON,
nullable: true,
transformer: MonitorSteps.getDatabaseTransformer(),
})
public monitorSteps?: MonitorSteps = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectMonitor,
],
})
@TableColumn({
manyToOneRelationColumn: "probeId",
type: TableColumnType.Entity,
modelType: Probe,
title: "Probe",
description: "Relation to Probe Resource in which this object belongs",
})
@ManyToOne(
() => {
return Probe;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "probeId" })
public probe?: Probe = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectMonitor,
],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Probe ID",
description: "ID of your OneUptime Probe in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public probeId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectMonitor,
],
})
@TableColumn({ type: TableColumnType.Date })
@Column({
type: ColumnType.Date,
nullable: true,
unique: false,
})
public testedAt?: Date = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectMonitor,
],
})
@TableColumn({
isDefaultValueColumn: false,
required: false,
type: TableColumnType.JSON,
})
@Column({
type: ColumnType.JSON,
nullable: true,
unique: false,
})
public monitorStepProbeResponse?: MonitorStepProbeResponse = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectMonitor,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectMonitor,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectMonitor,
],
})
@TableColumn({
isDefaultValueColumn: false,
required: true,
type: TableColumnType.Boolean,
})
@Column({
type: ColumnType.Boolean,
nullable: true,
unique: false,
default: true,
})
public isInQueue?: boolean = undefined;
}

View File

@@ -24,6 +24,7 @@ import OnCallDutyPolicyStatus from "../../Types/OnCallDutyPolicy/OnCallDutyPolic
import Permission from "../../Types/Permission";
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
import Alert from "./Alert";
@TableBillingAccessControl({
create: PlanType.Growth,
@@ -225,6 +226,60 @@ export default class OnCallDutyPolicyExecutionLog extends BaseModel {
})
public triggeredByIncidentId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectOnCallDutyPolicyExecutionLog,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "triggeredByAlertId",
type: TableColumnType.Entity,
modelType: Alert,
title: "Triggered By Alert",
description: "Relation to Alert which triggered this on-call duty policy.",
})
@ManyToOne(
() => {
return Alert;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "triggeredByAlertId" })
public triggeredByAlert?: Alert = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectOnCallDutyPolicyExecutionLog,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Triggered By Alert ID",
description:
"ID of the incident which triggered this on-call escalation policy.",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public triggeredByAlertId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [

View File

@@ -41,7 +41,6 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
create: true,
delete: false,
update: false,
read: true,
})
@TableMetadata({
tableName: "SmsLog",

View File

@@ -1061,6 +1061,44 @@ export default class StatusPage extends BaseModel {
})
public allowSubscribersToChooseResources?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectStatusPage,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectStatusPage,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectStatusPage,
],
})
@TableColumn({
isDefaultValueColumn: true,
type: TableColumnType.Boolean,
title: "Allow Subscribers to subscribe to event types",
description:
"Can subscribers choose which event type like Announcements, Incidents, Scheduled Events to subscribe to?",
})
@Column({
type: ColumnType.Boolean,
default: false,
})
@ColumnBillingAccessControl({
read: PlanType.Free,
update: PlanType.Scale,
create: PlanType.Free,
})
public allowSubscribersToChooseEventTypes?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,

View File

@@ -538,4 +538,90 @@ export default class StatusPageDomain extends BaseModel {
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateStatusPageDomain,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadStatusPageDomain,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditStatusPageDomain,
],
})
@TableColumn({ type: TableColumnType.VeryLongText })
@Column({
type: ColumnType.VeryLongText,
nullable: true,
unique: false,
})
public customCertificate?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateStatusPageDomain,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadStatusPageDomain,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditStatusPageDomain,
],
})
@TableColumn({ type: TableColumnType.VeryLongText })
@Column({
type: ColumnType.VeryLongText,
nullable: true,
unique: false,
})
public customCertificateKey?: string = undefined;
// If this is true, then the certificate is custom and not managed by OneUptime (LetsEncrypt)
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateStatusPageDomain,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadStatusPageDomain,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditStatusPageDomain,
],
})
@TableColumn({ type: TableColumnType.Boolean })
@Column({
type: ColumnType.Boolean,
nullable: false,
unique: false,
default: false, // default is false
})
public isCustomCertificate?: boolean = undefined;
}

View File

@@ -32,6 +32,7 @@ import {
ManyToMany,
ManyToOne,
} from "typeorm";
import StatusPageEventType from "../../Types/StatusPage/StatusPageEventType";
@EnableDocumentation()
@EnableWorkflow({
@@ -528,6 +529,40 @@ export default class StatusPageSubscriber extends BaseModel {
})
public isSubscribedToAllResources?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateStatusPageSubscriber,
Permission.Public,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadStatusPageSubscriber,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditStatusPageSubscriber,
],
})
@TableColumn({
isDefaultValueColumn: true,
type: TableColumnType.Boolean,
title: "Is Subscribed to All Event Types",
description:
"Is Subscriber Subscribed to All Event Types (like Incidents, Scheduled Events, Announcements) on this status page?",
})
@Column({
type: ColumnType.Boolean,
default: true,
})
public isSubscribedToAllEventTypes?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
@@ -575,4 +610,39 @@ export default class StatusPageSubscriber extends BaseModel {
},
})
public statusPageResources?: Array<StatusPageResource> = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateStatusPageSubscriber,
Permission.Public,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadStatusPageSubscriber,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditStatusPageSubscriber,
],
})
@TableColumn({
required: false,
type: TableColumnType.JSON,
title: "Subscribed to Event Types",
description:
"Which event types is the subscriber subscribed to (like Incidents, Scheduled Events, Announcements)",
})
@Column({
type: ColumnType.JSON,
nullable: true,
default: [],
})
public statusPageEventTypes?: Array<StatusPageEventType> = undefined;
}

View File

@@ -0,0 +1,452 @@
import Project from "./Project";
import User from "./User";
import Route from "../../Types/API/Route";
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
import ColumnLength from "../../Types/Database/ColumnLength";
import ColumnType from "../../Types/Database/ColumnType";
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
import TableColumn from "../../Types/Database/TableColumn";
import TableColumnType from "../../Types/Database/TableColumnType";
import TableMetadata from "../../Types/Database/TableMetadata";
import TenantColumn from "../../Types/Database/TenantColumn";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
import Query from "../../Types/BaseDatabase/Query";
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
import Sort from "../../Types/BaseDatabase/Sort";
import AnalyticsBaseModel from "../AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
@TableBillingAccessControl({
create: PlanType.Growth,
read: PlanType.Free,
update: PlanType.Growth,
delete: PlanType.Growth,
})
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.DeleteTableView,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditTableView,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/table-view"))
@TableMetadata({
tableName: "TableView",
singularName: "Table View",
pluralName: "Table Views",
icon: IconProp.TableCells,
tableDescription:
"Table View is view settings for a table in a project. It contains columns, filters, and other settings.",
})
@Entity({
name: "TableView",
})
export default class TableView extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "projectId",
type: TableColumnType.Entity,
modelType: Project,
title: "Project",
description: "Relation to Project Resource in which this object belongs",
})
@ManyToOne(
() => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "projectId" })
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Project ID",
description: "ID of your OneUptime Project in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditTableView,
],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
canReadOnRelationQuery: true,
title: "Name",
description: "Any friendly name of this object",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
public name?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditTableView,
],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
canReadOnRelationQuery: true,
title: "Table ID",
description: "ID of the table this view is for",
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
public tableId?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditTableView,
],
})
@TableColumn({
required: false,
type: TableColumnType.LongText,
title: "Description",
description: "Friendly description that will help you remember",
})
@Column({
nullable: true,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public description?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "createdByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Created by User",
description:
"Relation to User who created this object (if this object was created by a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "createdByUserId" })
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Created by User ID",
description:
"User ID who created this object (if this object was created by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
description:
"Relation to User who deleted this object (if this object was deleted by a User)",
})
@ManyToOne(
() => {
return User;
},
{
cascade: false,
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "deletedByUserId" })
public deletedByUser?: User = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditTableView,
],
})
@TableColumn({
title: "Filters",
required: true,
unique: false,
type: TableColumnType.JSON,
canReadOnRelationQuery: true,
description: "Filters for this table view",
})
@Column({
type: ColumnType.JSON,
unique: false,
nullable: false,
})
public query?: Query<BaseModel | AnalyticsBaseModel> = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditTableView,
],
})
@TableColumn({
title: "Sort",
required: true,
unique: false,
type: TableColumnType.JSON,
canReadOnRelationQuery: true,
description: "Sort for this table view",
})
@Column({
type: ColumnType.JSON,
unique: false,
nullable: false,
})
public sort?: Sort<BaseModel | AnalyticsBaseModel> = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.CreateTableView,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadTableView,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.EditTableView,
],
})
@TableColumn({
title: "Items on Page",
required: true,
unique: false,
type: TableColumnType.Number,
canReadOnRelationQuery: true,
description: "Items on page",
})
@Column({
type: ColumnType.Number,
unique: false,
nullable: false,
default: 10,
})
public itemsOnPage?: number = undefined;
}

View File

@@ -73,6 +73,7 @@ import StatusPageHistoryChartBarColorRule from "Common/Models/DatabaseModels/Sta
import StatusPageResource from "Common/Models/DatabaseModels/StatusPageResource";
import StatusPageSSO from "Common/Models/DatabaseModels/StatusPageSso";
import StatusPageSubscriber from "Common/Models/DatabaseModels/StatusPageSubscriber";
import StatusPageEventType from "../../Types/StatusPage/StatusPageEventType";
export default class StatusPageAPI extends BaseAPI<
StatusPage,
@@ -250,6 +251,7 @@ export default class StatusPageAPI extends BaseAPI<
enableSmsSubscribers: true,
isPublicStatusPage: true,
allowSubscribersToChooseResources: true,
allowSubscribersToChooseEventTypes: true,
requireSsoForLogin: true,
coverImageFile: {
file: true,
@@ -1750,6 +1752,7 @@ export default class StatusPageAPI extends BaseAPI<
enableEmailSubscribers: true,
enableSmsSubscribers: true,
allowSubscribersToChooseResources: true,
allowSubscribersToChooseEventTypes: true,
},
props: {
isRoot: true,
@@ -1838,6 +1841,15 @@ export default class StatusPageAPI extends BaseAPI<
);
}
if (
req.body.data["statusPageEventTypes"] &&
!statusPage.allowSubscribersToChooseEventTypes
) {
throw new BadDataException(
"Subscribers are not allowed to choose event types for this status page.",
);
}
statusPageSubscriber.statusPageId = objectId;
statusPageSubscriber.sendYouHaveSubscribedMessage = true;
statusPageSubscriber.projectId = statusPage.projectId!;
@@ -1845,6 +1857,10 @@ export default class StatusPageAPI extends BaseAPI<
req.body.data["isSubscribedToAllResources"],
);
statusPageSubscriber.isSubscribedToAllEventTypes = Boolean(
req.body.data["isSubscribedToAllEventTypes"],
);
if (
req.body.data["statusPageResources"] &&
req.body.data["statusPageResources"].length > 0
@@ -1854,6 +1870,15 @@ export default class StatusPageAPI extends BaseAPI<
] as Array<StatusPageResource>;
}
if (
req.body.data["statusPageEventTypes"] &&
req.body.data["statusPageEventTypes"].length > 0
) {
statusPageSubscriber.statusPageEventTypes = req.body.data[
"statusPageEventTypes"
] as Array<StatusPageEventType>;
}
if (isUpdate) {
// check isUnsubscribed is set to false.

View File

@@ -0,0 +1,51 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class MigrationName1727894983857 implements MigrationInterface {
public name = "MigrationName1727894983857";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "TableView" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "name" character varying(100) NOT NULL, "tableId" character varying(100) NOT NULL, "description" character varying(500), "createdByUserId" uuid, "deletedByUserId" uuid, "query" jsonb NOT NULL, "sort" jsonb NOT NULL, "itemsOnPage" integer NOT NULL DEFAULT '10', CONSTRAINT "PK_1e17a8834a65403cc87c4ead0cc" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_a8691d4e023d907b5c73a43e42" ON "TableView" ("projectId") `,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
);
await queryRunner.query(
`ALTER TABLE "TableView" ADD CONSTRAINT "FK_a8691d4e023d907b5c73a43e424" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "TableView" ADD CONSTRAINT "FK_2f2b7d1e199910951a0b5933d92" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "TableView" ADD CONSTRAINT "FK_b36d769f3d3d6fe4f9c35984551" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "TableView" DROP CONSTRAINT "FK_b36d769f3d3d6fe4f9c35984551"`,
);
await queryRunner.query(
`ALTER TABLE "TableView" DROP CONSTRAINT "FK_2f2b7d1e199910951a0b5933d92"`,
);
await queryRunner.query(
`ALTER TABLE "TableView" DROP CONSTRAINT "FK_a8691d4e023d907b5c73a43e424"`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_a8691d4e023d907b5c73a43e42"`,
);
await queryRunner.query(`DROP TABLE "TableView"`);
}
}

View File

@@ -0,0 +1,553 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class MigrationName1727906598804 implements MigrationInterface {
public name = "MigrationName1727906598804";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "AlertSeverity" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "name" character varying(100) NOT NULL, "slug" character varying(100) NOT NULL, "description" character varying(500), "createdByUserId" uuid, "deletedByUserId" uuid, "color" character varying(7) NOT NULL, "order" smallint NOT NULL, CONSTRAINT "PK_6ed0de1b0a2ea665f42e3599b0e" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_9282bdc00276db13fd8598f91b" ON "AlertSeverity" ("projectId") `,
);
await queryRunner.query(
`CREATE TABLE "AlertState" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "name" character varying(100) NOT NULL, "description" character varying(500), "createdByUserId" uuid, "deletedByUserId" uuid, "color" character varying(7) NOT NULL, "isCreatedState" boolean NOT NULL DEFAULT false, "isAcknowledgedState" boolean NOT NULL DEFAULT false, "isResolvedState" boolean NOT NULL DEFAULT false, "order" smallint NOT NULL, CONSTRAINT "PK_1528832ec6759d219df5993a5a3" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_57304bde1da0266fc24f840768" ON "AlertState" ("projectId") `,
);
await queryRunner.query(
`CREATE TABLE "Alert" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "title" character varying(500) NOT NULL, "description" text, "createdByUserId" uuid, "deletedByUserId" uuid, "monitorId" uuid, "currentAlertStateId" uuid NOT NULL, "alertSeverityId" uuid NOT NULL, "monitorStatusWhenThisAlertWasCreatedId" uuid, "customFields" jsonb, "isOwnerNotifiedOfAlertCreation" boolean NOT NULL DEFAULT false, "rootCause" text, "createdStateLog" jsonb, "createdCriteriaId" character varying, "createdByProbeId" uuid, "isCreatedAutomatically" boolean NOT NULL DEFAULT false, "remediationNotes" text, "telemetryQuery" jsonb, CONSTRAINT "PK_7e054682f5fe26a28bfc5aa2c12" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_3e36243cde1e1a428f6849b04a" ON "Alert" ("projectId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_866d739479c4e601de0dbc188b" ON "Alert" ("title") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_677264df22b80ae07ec5dcc58d" ON "Alert" ("currentAlertStateId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_531522bec85f8979124a6933c0" ON "Alert" ("alertSeverityId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_f6c0e4f6713391fea9dba60f0d" ON "Alert" ("monitorStatusWhenThisAlertWasCreatedId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_d2c672ed402faa9398c77c812c" ON "Alert" ("isOwnerNotifiedOfAlertCreation") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_fc40ea6a9ad55f29bca4f4a15d" ON "Alert" ("rootCause") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_f145da4b9636cb503cc92a60b2" ON "Alert" ("createdCriteriaId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_1a8075521492cc168e9fb20f1f" ON "Alert" ("createdByProbeId") `,
);
await queryRunner.query(
`CREATE TABLE "AlertCustomField" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "name" character varying(100) NOT NULL, "description" character varying(500), "type" character varying(100), "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_fa936db1d883a68866604b2825a" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_1cda5dc3d011f1440dae232555" ON "AlertCustomField" ("projectId") `,
);
await queryRunner.query(
`CREATE TABLE "AlertStateTimeline" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "alertId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "alertStateId" uuid NOT NULL, "isOwnerNotified" boolean NOT NULL DEFAULT false, "stateChangeLog" jsonb, "rootCause" text, "endsAt" TIMESTAMP WITH TIME ZONE, "startsAt" TIMESTAMP WITH TIME ZONE, CONSTRAINT "PK_54fbded96ccc49e72a611c923b4" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_8e1683045d3529f17c8513c3aa" ON "AlertStateTimeline" ("projectId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_8f241a1bd90518432352e8fa16" ON "AlertStateTimeline" ("alertId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_dbf0191a98672bcb73f65febac" ON "AlertStateTimeline" ("alertStateId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_0a79e63f3551c714f68cf74697" ON "AlertStateTimeline" ("isOwnerNotified") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_c3ec412714adf41d1c4e2f8953" ON "AlertStateTimeline" ("rootCause") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_0b373fde634db572b38010711c" ON "AlertStateTimeline" ("endsAt") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_551162036adb80d1fc656f36f4" ON "AlertStateTimeline" ("startsAt") `,
);
await queryRunner.query(
`CREATE TABLE "AlertInternalNote" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "alertId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "note" text NOT NULL, "isOwnerNotified" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_8c4bd0d9933bdb8d56774f4281b" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_c17364695141773034905d18b3" ON "AlertInternalNote" ("projectId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_9e9db01b4edbf4334fe7e16977" ON "AlertInternalNote" ("alertId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_51d2371a3486316187d867b633" ON "AlertInternalNote" ("isOwnerNotified") `,
);
await queryRunner.query(
`CREATE TABLE "AlertOwnerTeam" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "teamId" uuid NOT NULL, "alertId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "isOwnerNotified" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_191d3751f2bfe744f8f25882bca" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_80246f033af28239e28b127db7" ON "AlertOwnerTeam" ("projectId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_b397c3a2cecf8e9e6d912ad918" ON "AlertOwnerTeam" ("teamId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_30e45da79b4fbdc37c1024dd1c" ON "AlertOwnerTeam" ("alertId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_8d646dd6af109328bd4d6c50e0" ON "AlertOwnerTeam" ("isOwnerNotified") `,
);
await queryRunner.query(
`CREATE TABLE "AlertOwnerUser" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "userId" uuid NOT NULL, "alertId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "isOwnerNotified" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_1669ffac6383d5c90034cb3cdd3" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_96d7a6732b594035999ae417c3" ON "AlertOwnerUser" ("projectId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_a8efa9f26e3d4ed34d8b61d0e0" ON "AlertOwnerUser" ("userId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_4645cc7f80367417846c0e7b3f" ON "AlertOwnerUser" ("alertId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_056ca186eec3d557bf8f17a82b" ON "AlertOwnerUser" ("isOwnerNotified") `,
);
await queryRunner.query(
`CREATE TABLE "AlertNoteTemplate" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "note" text NOT NULL, "templateName" character varying(100) NOT NULL, "templateDescription" character varying(500) NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_774a57b039546a74edc6210db5d" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_10e46b1072581d7cef2ec65429" ON "AlertNoteTemplate" ("projectId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_77f48204935c346470fde06b81" ON "AlertNoteTemplate" ("note") `,
);
await queryRunner.query(
`CREATE TABLE "AlertOnCallDutyPolicy" ("onCallDutyPolicyId" uuid NOT NULL, "monitorId" uuid NOT NULL, CONSTRAINT "PK_adaff6d89a87bbe9c3cfb8f70fc" PRIMARY KEY ("onCallDutyPolicyId", "monitorId"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_0eca13d28cf4d2349406ddebc5" ON "AlertOnCallDutyPolicy" ("onCallDutyPolicyId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_1ef6702995a8406630f75f06e2" ON "AlertOnCallDutyPolicy" ("monitorId") `,
);
await queryRunner.query(
`CREATE TABLE "AlertLabel" ("alertId" uuid NOT NULL, "labelId" uuid NOT NULL, CONSTRAINT "PK_fa2364f55ffe0e9077add397989" PRIMARY KEY ("alertId", "labelId"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_af62b88e73f56e8fcaffbbd965" ON "AlertLabel" ("alertId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_507fd32e297f0287df932d7550" ON "AlertLabel" ("labelId") `,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyExecutionLog" ADD "triggeredByAlertId" uuid`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
);
await queryRunner.query(
`ALTER TABLE "AlertSeverity" ADD CONSTRAINT "FK_9282bdc00276db13fd8598f91bf" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertSeverity" ADD CONSTRAINT "FK_c9e714da15a75b6fdfdeaf1d0ec" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertSeverity" ADD CONSTRAINT "FK_9b75d7937e702dee283256ad975" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertState" ADD CONSTRAINT "FK_57304bde1da0266fc24f8407682" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertState" ADD CONSTRAINT "FK_fa9909aa59e53665dae7273462c" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertState" ADD CONSTRAINT "FK_570b9cc5f95f8a70d0b80ef5739" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_3e36243cde1e1a428f6849b04ac" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_b15c80ee3b9d22bc675c6c5caf0" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_6efa9972d8181f4ea785c0eec47" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_b57071fc2f1e27430e651382ee2" FOREIGN KEY ("monitorId") REFERENCES "Monitor"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_677264df22b80ae07ec5dcc58de" FOREIGN KEY ("currentAlertStateId") REFERENCES "AlertState"("_id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_531522bec85f8979124a6933c0c" FOREIGN KEY ("alertSeverityId") REFERENCES "AlertSeverity"("_id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_f6c0e4f6713391fea9dba60f0d7" FOREIGN KEY ("monitorStatusWhenThisAlertWasCreatedId") REFERENCES "MonitorStatus"("_id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Alert" ADD CONSTRAINT "FK_1a8075521492cc168e9fb20f1f6" FOREIGN KEY ("createdByProbeId") REFERENCES "Probe"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyExecutionLog" ADD CONSTRAINT "FK_b495684ae5b9c2a5b8dba6c1d4b" FOREIGN KEY ("triggeredByAlertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertCustomField" ADD CONSTRAINT "FK_1cda5dc3d011f1440dae232555f" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertCustomField" ADD CONSTRAINT "FK_19ea4088de9a1b73a50ea819c75" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertCustomField" ADD CONSTRAINT "FK_8e723a6fa604c897191370f826f" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" ADD CONSTRAINT "FK_8e1683045d3529f17c8513c3aa3" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" ADD CONSTRAINT "FK_8f241a1bd90518432352e8fa166" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" ADD CONSTRAINT "FK_e5c618f2c34dab1b89411cfd293" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" ADD CONSTRAINT "FK_37d090181ab909ec9c07907eddc" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" ADD CONSTRAINT "FK_dbf0191a98672bcb73f65febac5" FOREIGN KEY ("alertStateId") REFERENCES "AlertState"("_id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" ADD CONSTRAINT "FK_c17364695141773034905d18b39" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" ADD CONSTRAINT "FK_9e9db01b4edbf4334fe7e169774" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" ADD CONSTRAINT "FK_b1aa4299b8f1544197ac8b77c1a" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" ADD CONSTRAINT "FK_6aaff72bf94da7e28c6d4a8f415" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" ADD CONSTRAINT "FK_80246f033af28239e28b127db75" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" ADD CONSTRAINT "FK_b397c3a2cecf8e9e6d912ad9183" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" ADD CONSTRAINT "FK_30e45da79b4fbdc37c1024dd1c6" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" ADD CONSTRAINT "FK_19a1e046b8e057579ccbcbee35b" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" ADD CONSTRAINT "FK_c43d8b8fde990031819baf85fb5" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" ADD CONSTRAINT "FK_96d7a6732b594035999ae417c31" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" ADD CONSTRAINT "FK_a8efa9f26e3d4ed34d8b61d0e06" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" ADD CONSTRAINT "FK_4645cc7f80367417846c0e7b3f7" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" ADD CONSTRAINT "FK_f94f0f3993386069d0fb91b3f91" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" ADD CONSTRAINT "FK_bc0d78ab13b336f5dbe1e678009" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertNoteTemplate" ADD CONSTRAINT "FK_10e46b1072581d7cef2ec654295" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertNoteTemplate" ADD CONSTRAINT "FK_d1be4ede264845aea13ed630d54" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertNoteTemplate" ADD CONSTRAINT "FK_d3be3bbe53d9fa76ca5cf12cc0f" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "AlertOnCallDutyPolicy" ADD CONSTRAINT "FK_0eca13d28cf4d2349406ddebc5c" FOREIGN KEY ("onCallDutyPolicyId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "AlertOnCallDutyPolicy" ADD CONSTRAINT "FK_1ef6702995a8406630f75f06e28" FOREIGN KEY ("monitorId") REFERENCES "OnCallDutyPolicy"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "AlertLabel" ADD CONSTRAINT "FK_af62b88e73f56e8fcaffbbd965e" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "AlertLabel" ADD CONSTRAINT "FK_507fd32e297f0287df932d7550d" FOREIGN KEY ("labelId") REFERENCES "Label"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "AlertLabel" DROP CONSTRAINT "FK_507fd32e297f0287df932d7550d"`,
);
await queryRunner.query(
`ALTER TABLE "AlertLabel" DROP CONSTRAINT "FK_af62b88e73f56e8fcaffbbd965e"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOnCallDutyPolicy" DROP CONSTRAINT "FK_1ef6702995a8406630f75f06e28"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOnCallDutyPolicy" DROP CONSTRAINT "FK_0eca13d28cf4d2349406ddebc5c"`,
);
await queryRunner.query(
`ALTER TABLE "AlertNoteTemplate" DROP CONSTRAINT "FK_d3be3bbe53d9fa76ca5cf12cc0f"`,
);
await queryRunner.query(
`ALTER TABLE "AlertNoteTemplate" DROP CONSTRAINT "FK_d1be4ede264845aea13ed630d54"`,
);
await queryRunner.query(
`ALTER TABLE "AlertNoteTemplate" DROP CONSTRAINT "FK_10e46b1072581d7cef2ec654295"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" DROP CONSTRAINT "FK_bc0d78ab13b336f5dbe1e678009"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" DROP CONSTRAINT "FK_f94f0f3993386069d0fb91b3f91"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" DROP CONSTRAINT "FK_4645cc7f80367417846c0e7b3f7"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" DROP CONSTRAINT "FK_a8efa9f26e3d4ed34d8b61d0e06"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerUser" DROP CONSTRAINT "FK_96d7a6732b594035999ae417c31"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" DROP CONSTRAINT "FK_c43d8b8fde990031819baf85fb5"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" DROP CONSTRAINT "FK_19a1e046b8e057579ccbcbee35b"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" DROP CONSTRAINT "FK_30e45da79b4fbdc37c1024dd1c6"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" DROP CONSTRAINT "FK_b397c3a2cecf8e9e6d912ad9183"`,
);
await queryRunner.query(
`ALTER TABLE "AlertOwnerTeam" DROP CONSTRAINT "FK_80246f033af28239e28b127db75"`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" DROP CONSTRAINT "FK_6aaff72bf94da7e28c6d4a8f415"`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" DROP CONSTRAINT "FK_b1aa4299b8f1544197ac8b77c1a"`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" DROP CONSTRAINT "FK_9e9db01b4edbf4334fe7e169774"`,
);
await queryRunner.query(
`ALTER TABLE "AlertInternalNote" DROP CONSTRAINT "FK_c17364695141773034905d18b39"`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" DROP CONSTRAINT "FK_dbf0191a98672bcb73f65febac5"`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" DROP CONSTRAINT "FK_37d090181ab909ec9c07907eddc"`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" DROP CONSTRAINT "FK_e5c618f2c34dab1b89411cfd293"`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" DROP CONSTRAINT "FK_8f241a1bd90518432352e8fa166"`,
);
await queryRunner.query(
`ALTER TABLE "AlertStateTimeline" DROP CONSTRAINT "FK_8e1683045d3529f17c8513c3aa3"`,
);
await queryRunner.query(
`ALTER TABLE "AlertCustomField" DROP CONSTRAINT "FK_8e723a6fa604c897191370f826f"`,
);
await queryRunner.query(
`ALTER TABLE "AlertCustomField" DROP CONSTRAINT "FK_19ea4088de9a1b73a50ea819c75"`,
);
await queryRunner.query(
`ALTER TABLE "AlertCustomField" DROP CONSTRAINT "FK_1cda5dc3d011f1440dae232555f"`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyExecutionLog" DROP CONSTRAINT "FK_b495684ae5b9c2a5b8dba6c1d4b"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_1a8075521492cc168e9fb20f1f6"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_f6c0e4f6713391fea9dba60f0d7"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_531522bec85f8979124a6933c0c"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_677264df22b80ae07ec5dcc58de"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_b57071fc2f1e27430e651382ee2"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_6efa9972d8181f4ea785c0eec47"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_b15c80ee3b9d22bc675c6c5caf0"`,
);
await queryRunner.query(
`ALTER TABLE "Alert" DROP CONSTRAINT "FK_3e36243cde1e1a428f6849b04ac"`,
);
await queryRunner.query(
`ALTER TABLE "AlertState" DROP CONSTRAINT "FK_570b9cc5f95f8a70d0b80ef5739"`,
);
await queryRunner.query(
`ALTER TABLE "AlertState" DROP CONSTRAINT "FK_fa9909aa59e53665dae7273462c"`,
);
await queryRunner.query(
`ALTER TABLE "AlertState" DROP CONSTRAINT "FK_57304bde1da0266fc24f8407682"`,
);
await queryRunner.query(
`ALTER TABLE "AlertSeverity" DROP CONSTRAINT "FK_9b75d7937e702dee283256ad975"`,
);
await queryRunner.query(
`ALTER TABLE "AlertSeverity" DROP CONSTRAINT "FK_c9e714da15a75b6fdfdeaf1d0ec"`,
);
await queryRunner.query(
`ALTER TABLE "AlertSeverity" DROP CONSTRAINT "FK_9282bdc00276db13fd8598f91bf"`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyExecutionLog" DROP COLUMN "triggeredByAlertId"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_507fd32e297f0287df932d7550"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_af62b88e73f56e8fcaffbbd965"`,
);
await queryRunner.query(`DROP TABLE "AlertLabel"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_1ef6702995a8406630f75f06e2"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_0eca13d28cf4d2349406ddebc5"`,
);
await queryRunner.query(`DROP TABLE "AlertOnCallDutyPolicy"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_77f48204935c346470fde06b81"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_10e46b1072581d7cef2ec65429"`,
);
await queryRunner.query(`DROP TABLE "AlertNoteTemplate"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_056ca186eec3d557bf8f17a82b"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_4645cc7f80367417846c0e7b3f"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_a8efa9f26e3d4ed34d8b61d0e0"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_96d7a6732b594035999ae417c3"`,
);
await queryRunner.query(`DROP TABLE "AlertOwnerUser"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_8d646dd6af109328bd4d6c50e0"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_30e45da79b4fbdc37c1024dd1c"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_b397c3a2cecf8e9e6d912ad918"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_80246f033af28239e28b127db7"`,
);
await queryRunner.query(`DROP TABLE "AlertOwnerTeam"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_51d2371a3486316187d867b633"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_9e9db01b4edbf4334fe7e16977"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_c17364695141773034905d18b3"`,
);
await queryRunner.query(`DROP TABLE "AlertInternalNote"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_551162036adb80d1fc656f36f4"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_0b373fde634db572b38010711c"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_c3ec412714adf41d1c4e2f8953"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_0a79e63f3551c714f68cf74697"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_dbf0191a98672bcb73f65febac"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_8f241a1bd90518432352e8fa16"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_8e1683045d3529f17c8513c3aa"`,
);
await queryRunner.query(`DROP TABLE "AlertStateTimeline"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_1cda5dc3d011f1440dae232555"`,
);
await queryRunner.query(`DROP TABLE "AlertCustomField"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_1a8075521492cc168e9fb20f1f"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_f145da4b9636cb503cc92a60b2"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_fc40ea6a9ad55f29bca4f4a15d"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_d2c672ed402faa9398c77c812c"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_f6c0e4f6713391fea9dba60f0d"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_531522bec85f8979124a6933c0"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_677264df22b80ae07ec5dcc58d"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_866d739479c4e601de0dbc188b"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_3e36243cde1e1a428f6849b04a"`,
);
await queryRunner.query(`DROP TABLE "Alert"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_57304bde1da0266fc24f840768"`,
);
await queryRunner.query(`DROP TABLE "AlertState"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_9282bdc00276db13fd8598f91b"`,
);
await queryRunner.query(`DROP TABLE "AlertSeverity"`);
}
}

View File

@@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class MigrationName1728472625805 implements MigrationInterface {
public name = "MigrationName1728472625805";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "StatusPageDomain" ADD "customCertificate" text`,
);
await queryRunner.query(
`ALTER TABLE "StatusPageDomain" ADD "customCertificateKey" text`,
);
await queryRunner.query(
`ALTER TABLE "StatusPageDomain" ADD "isCustomCertificate" boolean NOT NULL DEFAULT false`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "StatusPageDomain" DROP COLUMN "isCustomCertificate"`,
);
await queryRunner.query(
`ALTER TABLE "StatusPageDomain" DROP COLUMN "customCertificateKey"`,
);
await queryRunner.query(
`ALTER TABLE "StatusPageDomain" DROP COLUMN "customCertificate"`,
);
}
}

View File

@@ -0,0 +1,79 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class MigrationName1729682875503 implements MigrationInterface {
public name = "MigrationName1729682875503";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "Dashboard" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "name" character varying(100) NOT NULL, "slug" character varying(100) NOT NULL, "description" character varying(500), "createdByUserId" uuid, "deletedByUserId" uuid, "dashboardViewConfig" jsonb NOT NULL, CONSTRAINT "PK_98ee748c8a7a18d6f9ca995eaf4" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_7f0fc9402b8d4151c46e3015a3" ON "Dashboard" ("projectId") `,
);
await queryRunner.query(
`CREATE TABLE "DashboardLabel" ("dashboardId" uuid NOT NULL, "labelId" uuid NOT NULL, CONSTRAINT "PK_bf2648028a4eab3f57aad76dab6" PRIMARY KEY ("dashboardId", "labelId"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_ce2113f43c6d88a632318414d0" ON "DashboardLabel" ("dashboardId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_31a32c8d6d1d1cb734c7711050" ON "DashboardLabel" ("labelId") `,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
);
await queryRunner.query(
`ALTER TABLE "Dashboard" ADD CONSTRAINT "FK_7f0fc9402b8d4151c46e3015a30" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Dashboard" ADD CONSTRAINT "FK_501b2bb8e0cb03f309211cbfa5f" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "Dashboard" ADD CONSTRAINT "FK_0debc7bed011eac37da40e875cb" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "DashboardLabel" ADD CONSTRAINT "FK_ce2113f43c6d88a632318414d0d" FOREIGN KEY ("dashboardId") REFERENCES "Dashboard"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "DashboardLabel" ADD CONSTRAINT "FK_31a32c8d6d1d1cb734c77110509" FOREIGN KEY ("labelId") REFERENCES "Label"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "DashboardLabel" DROP CONSTRAINT "FK_31a32c8d6d1d1cb734c77110509"`,
);
await queryRunner.query(
`ALTER TABLE "DashboardLabel" DROP CONSTRAINT "FK_ce2113f43c6d88a632318414d0d"`,
);
await queryRunner.query(
`ALTER TABLE "Dashboard" DROP CONSTRAINT "FK_0debc7bed011eac37da40e875cb"`,
);
await queryRunner.query(
`ALTER TABLE "Dashboard" DROP CONSTRAINT "FK_501b2bb8e0cb03f309211cbfa5f"`,
);
await queryRunner.query(
`ALTER TABLE "Dashboard" DROP CONSTRAINT "FK_7f0fc9402b8d4151c46e3015a30"`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_31a32c8d6d1d1cb734c7711050"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_ce2113f43c6d88a632318414d0"`,
);
await queryRunner.query(`DROP TABLE "DashboardLabel"`);
await queryRunner.query(
`DROP INDEX "public"."IDX_7f0fc9402b8d4151c46e3015a3"`,
);
await queryRunner.query(`DROP TABLE "Dashboard"`);
}
}

View File

@@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class MigrationName1730117995642 implements MigrationInterface {
public name = "MigrationName1730117995642";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "StatusPage" ADD "allowSubscribersToChooseEventTypes" boolean NOT NULL DEFAULT false`,
);
await queryRunner.query(
`ALTER TABLE "StatusPageSubscriber" ADD "isSubscribedToAllEventTypes" boolean NOT NULL DEFAULT true`,
);
await queryRunner.query(
`ALTER TABLE "StatusPageSubscriber" ADD "statusPageEventTypes" jsonb DEFAULT '[]'`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "statusPageEventTypes"`,
);
await queryRunner.query(
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "isSubscribedToAllEventTypes"`,
);
await queryRunner.query(
`ALTER TABLE "StatusPage" DROP COLUMN "allowSubscribersToChooseEventTypes"`,
);
}
}

View File

@@ -0,0 +1,51 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class MigrationName1730209089495 implements MigrationInterface {
public name = "MigrationName1730209089495";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "MonitorTest" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "monitorType" character varying(100) NOT NULL, "monitorSteps" jsonb, "probeId" uuid NOT NULL, "testedAt" TIMESTAMP WITH TIME ZONE, "lastMonitoringLog" jsonb, CONSTRAINT "PK_7ce3477c7bb3d7b8961c8465935" PRIMARY KEY ("_id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_6de87954a2a0587defe52aeb86" ON "MonitorTest" ("projectId") `,
);
await queryRunner.query(
`CREATE INDEX "IDX_fd6b1e330eb08de988307b6052" ON "MonitorTest" ("probeId") `,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" ADD CONSTRAINT "FK_6de87954a2a0587defe52aeb86c" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" ADD CONSTRAINT "FK_f94c5a7356b7b55785e3a3dac5b" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" ADD CONSTRAINT "FK_b92a71b1f5f6c072455cd242ed6" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" ADD CONSTRAINT "FK_fd6b1e330eb08de988307b60524" FOREIGN KEY ("probeId") REFERENCES "Probe"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "MonitorTest" DROP CONSTRAINT "FK_fd6b1e330eb08de988307b60524"`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" DROP CONSTRAINT "FK_b92a71b1f5f6c072455cd242ed6"`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" DROP CONSTRAINT "FK_f94c5a7356b7b55785e3a3dac5b"`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" DROP CONSTRAINT "FK_6de87954a2a0587defe52aeb86c"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_fd6b1e330eb08de988307b6052"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_6de87954a2a0587defe52aeb86"`,
);
await queryRunner.query(`DROP TABLE "MonitorTest"`);
}
}

View File

@@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class MigrationName1730223198692 implements MigrationInterface {
public name = "MigrationName1730223198692";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "MonitorTest" DROP COLUMN "lastMonitoringLog"`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" ADD "monitorStepProbeResponse" jsonb`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" ADD "isInQueue" boolean DEFAULT true`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "MonitorTest" DROP COLUMN "isInQueue"`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" DROP COLUMN "monitorStepProbeResponse"`,
);
await queryRunner.query(
`ALTER TABLE "MonitorTest" ADD "lastMonitoringLog" jsonb`,
);
}
}

View File

@@ -71,6 +71,13 @@ import { MigrationName1727193130193 } from "./1727193130193-MigrationName";
import { MigrationName1727193702212 } from "./1727193702212-MigrationName";
import { MigrationName1727194211048 } from "./1727194211048-MigrationName";
import { MigrationName1727194579925 } from "./1727194579925-MigrationName";
import { MigrationName1727894983857 } from "./1727894983857-MigrationName";
import { MigrationName1727906598804 } from "./1727906598804-MigrationName";
import { MigrationName1728472625805 } from "./1728472625805-MigrationName";
import { MigrationName1729682875503 } from "./1729682875503-MigrationName";
import { MigrationName1730117995642 } from "./1730117995642-MigrationName";
import { MigrationName1730209089495 } from "./1730209089495-MigrationName";
import { MigrationName1730223198692 } from "./1730223198692-MigrationName";
export default [
InitialMigration,
@@ -146,4 +153,11 @@ export default [
MigrationName1727193702212,
MigrationName1727194211048,
MigrationName1727194579925,
MigrationName1727894983857,
MigrationName1727906598804,
MigrationName1728472625805,
MigrationName1729682875503,
MigrationName1730117995642,
MigrationName1730209089495,
MigrationName1730223198692,
];

View File

@@ -7,10 +7,11 @@ export default class Semaphore {
// returns the mutex id
public static async lock(data: {
key: string;
namespace: string;
lockTimeout?: number;
}): Promise<SemaphoreMutex> {
if (!data.lockTimeout) {
data.lockTimeout = 1000;
data.lockTimeout = 5000;
}
const { key } = data;
@@ -21,9 +22,13 @@ export default class Semaphore {
throw new Error("Redis client is not connected");
}
const mutex: SemaphoreMutex = new Mutex(client, key, {
lockTimeout: data.lockTimeout,
});
const mutex: SemaphoreMutex = new Mutex(
client,
data.namespace + "-" + key,
{
lockTimeout: data.lockTimeout,
},
);
await mutex.acquire();

View File

@@ -1,4 +1,3 @@
import AccessTokenService from "../Services/AccessTokenService";
import ApiKeyService from "../Services/ApiKeyService";
import GlobalConfigService from "../Services/GlobalConfigService";
import UserService from "../Services/UserService";
@@ -18,6 +17,7 @@ import UserType from "Common/Types/UserType";
import ApiKey from "Common/Models/DatabaseModels/ApiKey";
import GlobalConfig from "Common/Models/DatabaseModels/GlobalConfig";
import User from "Common/Models/DatabaseModels/User";
import APIKeyAccessPermission from "../Utils/APIKey/AccessPermission";
export default class ProjectMiddleware {
public static getProjectId(req: ExpressRequest): ObjectID | null {
@@ -94,10 +94,12 @@ export default class ProjectMiddleware {
// (req as OneUptimeRequest).permissions =
// apiKeyModel.permissions || [];
(req as OneUptimeRequest).userGlobalAccessPermission =
await AccessTokenService.getDefaultApiGlobalPermission(tenantId);
await APIKeyAccessPermission.getDefaultApiGlobalPermission(
tenantId,
);
const userTenantAccessPermission: UserTenantAccessPermission | null =
await AccessTokenService.getApiTenantAccessPermission(
await APIKeyAccessPermission.getApiTenantAccessPermission(
tenantId,
apiKeyModel.id!,
);

View File

@@ -31,7 +31,7 @@ import {
} from "Common/Types/Permission";
import UserType from "Common/Types/UserType";
import Project from "Common/Models/DatabaseModels/Project";
import { Socket } from "../Infrastructure/SocketIO";
import UserPermissionUtil from "../Utils/UserPermission/UserPermission";
export default class UserMiddleware {
/*
@@ -58,22 +58,6 @@ export default class UserMiddleware {
return accessToken;
}
public static getAccessTokenFromSocket(socket: Socket): string | undefined {
let accessToken: string | undefined = undefined;
if (socket.handshake.headers.cookie) {
const cookies: Dictionary<string> = CookieUtil.getCookiesFromCookieString(
socket.handshake.headers.cookie,
);
if (cookies[CookieUtil.getUserTokenKey()]) {
accessToken = cookies[CookieUtil.getUserTokenKey()];
}
}
return accessToken;
}
public static getAccessTokenFromExpressRequest(
req: ExpressRequest,
): string | undefined {
@@ -383,7 +367,7 @@ export default class UserMiddleware {
) {
// Add default permissions.
userTenantAccessPermission =
AccessTokenService.getDefaultUserTenantAccessPermission(projectId);
UserPermissionUtil.getDefaultUserTenantAccessPermission(projectId);
} else {
// get project level permissions if projectid exists in request.
userTenantAccessPermission =

View File

@@ -1,26 +1,20 @@
import GlobalCache from "../Infrastructure/GlobalCache";
import QueryHelper from "../Types/Database/QueryHelper";
import ApiKeyPermissionService from "./ApiKeyPermissionService";
import BaseService from "./BaseService";
import TeamMemberService from "./TeamMemberService";
import TeamPermissionService from "./TeamPermissionService";
import LIMIT_MAX from "../../Types/Database/LimitMax";
import { JSONObject } from "../../Types/JSON";
import ObjectID from "../../Types/ObjectID";
import Permission, {
UserGlobalAccessPermission,
UserPermission,
UserTenantAccessPermission,
} from "../../Types/Permission";
import APIKeyPermission from "Common/Models/DatabaseModels/ApiKeyPermission";
import Label from "Common/Models/DatabaseModels/Label";
import TeamMember from "Common/Models/DatabaseModels/TeamMember";
import TeamPermission from "Common/Models/DatabaseModels/TeamPermission";
enum PermissionNamespace {
GlobalPermission = "global-permissions",
ProjectPermission = "project-permissions",
}
import UserPermissionUtil from "../Utils/UserPermission/UserPermission";
import PermissionNamespace from "../Types/Permission/PermissionNamespace";
export class AccessTokenService extends BaseService {
public constructor() {
@@ -65,104 +59,6 @@ export class AccessTokenService extends BaseService {
}
}
public async getDefaultApiGlobalPermission(
projectId: ObjectID,
): Promise<UserGlobalAccessPermission> {
return {
projectIds: [projectId],
globalPermissions: [
Permission.Public,
Permission.User,
Permission.CurrentUser,
],
_type: "UserGlobalAccessPermission",
};
}
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,
): Promise<UserTenantAccessPermission> {
// get team permissions.
const apiKeyPermission: Array<APIKeyPermission> =
await ApiKeyPermissionService.findBy({
query: {
apiKeyId: apiKeyId,
},
select: {
permission: true,
labels: {
_id: true,
},
isBlockPermission: true,
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
});
const userPermissions: Array<UserPermission> = [];
for (const apiPermission of apiKeyPermission) {
if (!apiPermission.labels) {
apiPermission.labels = [];
}
userPermissions.push({
permission: apiPermission.permission!,
labelIds: apiPermission.labels.map((label: Label) => {
return label.id!;
}),
isBlockPermission: apiPermission.isBlockPermission,
_type: "UserPermission",
});
}
const permission: UserTenantAccessPermission =
this.getDefaultUserTenantAccessPermission(projectId);
permission.permissions = permission.permissions.concat(userPermissions);
return permission;
}
public async refreshUserGlobalAccessPermission(
userId: ObjectID,
): Promise<UserGlobalAccessPermission> {
@@ -207,53 +103,17 @@ export class AccessTokenService extends BaseService {
return permissionToStore;
}
public getDefaultUserTenantAccessPermission(
projectId: ObjectID,
): UserTenantAccessPermission {
const userPermissions: Array<UserPermission> = [];
userPermissions.push({
permission: Permission.CurrentUser,
labelIds: [],
isBlockPermission: false,
_type: "UserPermission",
});
userPermissions.push({
permission: Permission.UnAuthorizedSsoUser,
labelIds: [],
isBlockPermission: false,
_type: "UserPermission",
});
const permission: UserTenantAccessPermission = {
projectId,
permissions: userPermissions,
isBlockPermission: false,
_type: "UserTenantAccessPermission",
};
return permission;
}
public async getUserGlobalAccessPermission(
userId: ObjectID,
): Promise<UserGlobalAccessPermission | null> {
const json: JSONObject | null = await GlobalCache.getJSONObject(
"user",
userId.toString(),
);
const json: UserGlobalAccessPermission | null =
await UserPermissionUtil.getUserGlobalAccessPermissionFromCache(userId);
if (!json) {
return await this.refreshUserGlobalAccessPermission(userId);
}
const accessPermission: UserGlobalAccessPermission =
json as UserGlobalAccessPermission;
accessPermission._type = "UserGlobalAccessPermission";
return accessPermission;
return json;
}
public async refreshUserTenantAccessPermission(
@@ -325,7 +185,7 @@ export class AccessTokenService extends BaseService {
}
const permission: UserTenantAccessPermission =
this.getDefaultUserTenantAccessPermission(projectId);
UserPermissionUtil.getDefaultUserTenantAccessPermission(projectId);
permission.permissions = permission.permissions.concat(userPermissions);
@@ -343,14 +203,10 @@ export class AccessTokenService extends BaseService {
projectId: ObjectID,
): Promise<UserTenantAccessPermission | null> {
const json: UserTenantAccessPermission | null =
(await GlobalCache.getJSONObject(
PermissionNamespace.ProjectPermission,
userId.toString() + projectId.toString(),
)) as UserTenantAccessPermission;
if (json) {
json._type = "UserTenantAccessPermission";
}
await UserPermissionUtil.getUserTenantAccessPermissionFromCache(
userId,
projectId,
);
if (!json) {
return await this.refreshUserTenantAccessPermission(userId, projectId);

View File

@@ -0,0 +1,9 @@
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertCustomField";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
}
export default new Service();

View File

@@ -0,0 +1,10 @@
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertInternalNote";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
}
export default new Service();

View File

@@ -0,0 +1,9 @@
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertNoteTemplate";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
}
export default new Service();

View File

@@ -0,0 +1,10 @@
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertOwnerTeam";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
}
export default new Service();

View File

@@ -0,0 +1,10 @@
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/AlertOwnerUser";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
}
export default new Service();

View File

@@ -0,0 +1,568 @@
import DatabaseConfig from "../DatabaseConfig";
import CreateBy from "../Types/Database/CreateBy";
import DeleteBy from "../Types/Database/DeleteBy";
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
import QueryHelper from "../Types/Database/QueryHelper";
import DatabaseService from "./DatabaseService";
import AlertOwnerTeamService from "./AlertOwnerTeamService";
import AlertOwnerUserService from "./AlertOwnerUserService";
import AlertStateService from "./AlertStateService";
import AlertStateTimelineService from "./AlertStateTimelineService";
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
import TeamMemberService from "./TeamMemberService";
import UserService from "./UserService";
import URL from "../../Types/API/URL";
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
import BadDataException from "../../Types/Exception/BadDataException";
import { JSONObject } from "../../Types/JSON";
import ObjectID from "../../Types/ObjectID";
import PositiveNumber from "../../Types/PositiveNumber";
import Typeof from "../../Types/Typeof";
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
import Model from "Common/Models/DatabaseModels/Alert";
import AlertOwnerTeam from "Common/Models/DatabaseModels/AlertOwnerTeam";
import AlertOwnerUser from "Common/Models/DatabaseModels/AlertOwnerUser";
import AlertState from "Common/Models/DatabaseModels/AlertState";
import AlertStateTimeline from "Common/Models/DatabaseModels/AlertStateTimeline";
import User from "Common/Models/DatabaseModels/User";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
public async isAlertAcknowledged(data: {
alertId: ObjectID;
}): Promise<boolean> {
const alert: Model | null = await this.findOneBy({
query: {
_id: data.alertId,
},
select: {
projectId: true,
currentAlertState: {
order: true,
},
},
props: {
isRoot: true,
},
});
if (!alert) {
throw new BadDataException("Alert not found");
}
if (!alert.projectId) {
throw new BadDataException("Incient Project ID not found");
}
const ackAlertState: AlertState =
await AlertStateService.getAcknowledgedAlertState({
projectId: alert.projectId,
props: {
isRoot: true,
},
});
const currentAlertStateOrder: number = alert.currentAlertState!.order!;
const ackAlertStateOrder: number = ackAlertState.order!;
if (currentAlertStateOrder >= ackAlertStateOrder) {
return true;
}
return false;
}
public async acknowledgeAlert(
alertId: ObjectID,
acknowledgedByUserId: ObjectID,
): Promise<void> {
const alert: Model | null = await this.findOneById({
id: alertId,
select: {
projectId: true,
},
props: {
isRoot: true,
},
});
if (!alert || !alert.projectId) {
throw new BadDataException("Alert not found.");
}
const alertState: AlertState | null = await AlertStateService.findOneBy({
query: {
projectId: alert.projectId,
isAcknowledgedState: true,
},
select: {
_id: true,
},
props: {
isRoot: true,
},
});
if (!alertState || !alertState.id) {
throw new BadDataException(
"Acknowledged state not found for this project. Please add acknowledged state from settings.",
);
}
const alertStateTimeline: AlertStateTimeline = new AlertStateTimeline();
alertStateTimeline.projectId = alert.projectId;
alertStateTimeline.alertId = alertId;
alertStateTimeline.alertStateId = alertState.id;
alertStateTimeline.createdByUserId = acknowledgedByUserId;
await AlertStateTimelineService.create({
data: alertStateTimeline,
props: {
isRoot: true,
},
});
}
protected override async onBeforeCreate(
createBy: CreateBy<Model>,
): Promise<OnCreate<Model>> {
if (!createBy.props.tenantId && !createBy.props.isRoot) {
throw new BadDataException("ProjectId required to create alert.");
}
const alertState: AlertState | null = await AlertStateService.findOneBy({
query: {
projectId: createBy.props.tenantId || createBy.data.projectId!,
isCreatedState: true,
},
select: {
_id: true,
},
props: {
isRoot: true,
},
});
if (!alertState || !alertState.id) {
throw new BadDataException(
"Created alert state not found for this project. Please add created alert state from settings.",
);
}
createBy.data.currentAlertStateId = alertState.id;
if (
(createBy.data.createdByUserId ||
createBy.data.createdByUser ||
createBy.props.userId) &&
!createBy.data.rootCause
) {
let userId: ObjectID | undefined = createBy.data.createdByUserId;
if (createBy.props.userId) {
userId = createBy.props.userId;
}
if (createBy.data.createdByUser && createBy.data.createdByUser.id) {
userId = createBy.data.createdByUser.id;
}
const user: User | null = await UserService.findOneBy({
query: {
_id: userId?.toString() as string,
},
select: {
_id: true,
name: true,
email: true,
},
props: {
isRoot: true,
},
});
if (user) {
createBy.data.rootCause = `Alert created by ${user.name} (${user.email})`;
}
}
return { createBy, carryForward: null };
}
protected override async onCreateSuccess(
onCreate: OnCreate<Model>,
createdItem: Model,
): Promise<Model> {
if (!createdItem.projectId) {
throw new BadDataException("projectId is required");
}
if (!createdItem.id) {
throw new BadDataException("id is required");
}
if (!createdItem.currentAlertStateId) {
throw new BadDataException("currentAlertStateId is required");
}
await this.changeAlertState({
projectId: createdItem.projectId,
alertId: createdItem.id,
alertStateId: createdItem.currentAlertStateId,
notifyOwners: false,
rootCause: createdItem.rootCause,
stateChangeLog: createdItem.createdStateLog,
props: {
isRoot: true,
},
});
// add owners.
if (
onCreate.createBy.miscDataProps &&
(onCreate.createBy.miscDataProps["ownerTeams"] ||
onCreate.createBy.miscDataProps["ownerUsers"])
) {
await this.addOwners(
createdItem.projectId,
createdItem.id,
(onCreate.createBy.miscDataProps["ownerUsers"] as Array<ObjectID>) ||
[],
(onCreate.createBy.miscDataProps["ownerTeams"] as Array<ObjectID>) ||
[],
false,
onCreate.createBy.props,
);
}
if (
createdItem.onCallDutyPolicies?.length &&
createdItem.onCallDutyPolicies?.length > 0
) {
for (const policy of createdItem.onCallDutyPolicies) {
await OnCallDutyPolicyService.executePolicy(
new ObjectID(policy._id as string),
{
triggeredByAlertId: createdItem.id!,
userNotificationEventType: UserNotificationEventType.AlertCreated,
},
);
}
}
return createdItem;
}
public async getAlertIdentifiedDate(alertId: ObjectID): Promise<Date> {
const timeline: AlertStateTimeline | null =
await AlertStateTimelineService.findOneBy({
query: {
alertId: alertId,
},
select: {
startsAt: true,
},
sort: {
startsAt: SortOrder.Ascending,
},
props: {
isRoot: true,
},
});
if (!timeline || !timeline.startsAt) {
throw new BadDataException("Alert identified date not found.");
}
return timeline.startsAt;
}
public async findOwners(alertId: ObjectID): Promise<Array<User>> {
if (!alertId) {
throw new BadDataException("alertId is required");
}
const ownerUsers: Array<AlertOwnerUser> =
await AlertOwnerUserService.findBy({
query: {
alertId: alertId,
},
select: {
_id: true,
user: {
_id: true,
email: true,
name: true,
timezone: true,
},
},
props: {
isRoot: true,
},
limit: LIMIT_PER_PROJECT,
skip: 0,
});
const ownerTeams: Array<AlertOwnerTeam> =
await AlertOwnerTeamService.findBy({
query: {
alertId: alertId,
},
select: {
_id: true,
teamId: true,
},
skip: 0,
limit: LIMIT_PER_PROJECT,
props: {
isRoot: true,
},
});
const users: Array<User> =
ownerUsers.map((ownerUser: AlertOwnerUser) => {
return ownerUser.user!;
}) || [];
if (ownerTeams.length > 0) {
const teamIds: Array<ObjectID> =
ownerTeams.map((ownerTeam: AlertOwnerTeam) => {
return ownerTeam.teamId!;
}) || [];
const teamUsers: Array<User> =
await TeamMemberService.getUsersInTeams(teamIds);
for (const teamUser of teamUsers) {
//check if the user is already added.
const isUserAlreadyAdded: User | undefined = users.find(
(user: User) => {
return user.id!.toString() === teamUser.id!.toString();
},
);
if (!isUserAlreadyAdded) {
users.push(teamUser);
}
}
}
return users;
}
public async addOwners(
projectId: ObjectID,
alertId: ObjectID,
userIds: Array<ObjectID>,
teamIds: Array<ObjectID>,
notifyOwners: boolean,
props: DatabaseCommonInteractionProps,
): Promise<void> {
for (let teamId of teamIds) {
if (typeof teamId === Typeof.String) {
teamId = new ObjectID(teamId.toString());
}
const teamOwner: AlertOwnerTeam = new AlertOwnerTeam();
teamOwner.alertId = alertId;
teamOwner.projectId = projectId;
teamOwner.teamId = teamId;
teamOwner.isOwnerNotified = !notifyOwners;
await AlertOwnerTeamService.create({
data: teamOwner,
props: props,
});
}
for (let userId of userIds) {
if (typeof userId === Typeof.String) {
userId = new ObjectID(userId.toString());
}
const teamOwner: AlertOwnerUser = new AlertOwnerUser();
teamOwner.alertId = alertId;
teamOwner.projectId = projectId;
teamOwner.userId = userId;
teamOwner.isOwnerNotified = !notifyOwners;
await AlertOwnerUserService.create({
data: teamOwner,
props: props,
});
}
}
public async getAlertLinkInDashboard(
projectId: ObjectID,
alertId: ObjectID,
): Promise<URL> {
const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
return URL.fromString(dashboardUrl.toString()).addRoute(
`/${projectId.toString()}/alerts/${alertId.toString()}`,
);
}
protected override async onUpdateSuccess(
onUpdate: OnUpdate<Model>,
updatedItemIds: ObjectID[],
): Promise<OnUpdate<Model>> {
if (
onUpdate.updateBy.data.currentAlertStateId &&
onUpdate.updateBy.props.tenantId
) {
for (const itemId of updatedItemIds) {
await this.changeAlertState({
projectId: onUpdate.updateBy.props.tenantId as ObjectID,
alertId: itemId,
alertStateId: onUpdate.updateBy.data.currentAlertStateId as ObjectID,
notifyOwners: true,
rootCause: "This status was changed when the alert was updated.",
stateChangeLog: undefined,
props: {
isRoot: true,
},
});
}
}
return onUpdate;
}
public async doesMonitorHasMoreActiveManualAlerts(
monitorId: ObjectID,
proojectId: ObjectID,
): Promise<boolean> {
const resolvedState: AlertState | null = await AlertStateService.findOneBy({
query: {
projectId: proojectId,
isResolvedState: true,
},
props: {
isRoot: true,
},
select: {
_id: true,
order: true,
},
});
const alertCount: PositiveNumber = await this.countBy({
query: {
monitorId: monitorId,
currentAlertState: {
order: QueryHelper.lessThan(resolvedState?.order as number),
},
isCreatedAutomatically: false,
},
props: {
isRoot: true,
},
});
return alertCount.toNumber() > 0;
}
protected override async onBeforeDelete(
deleteBy: DeleteBy<Model>,
): Promise<OnDelete<Model>> {
const alerts: Array<Model> = await this.findBy({
query: deleteBy.query,
limit: LIMIT_MAX,
skip: 0,
select: {
projectId: true,
monitor: {
_id: true,
},
},
props: {
isRoot: true,
},
});
return {
deleteBy,
carryForward: {
alerts: alerts,
},
};
}
public async changeAlertState(data: {
projectId: ObjectID;
alertId: ObjectID;
alertStateId: ObjectID;
notifyOwners: boolean;
rootCause: string | undefined;
stateChangeLog: JSONObject | undefined;
props: DatabaseCommonInteractionProps | undefined;
}): Promise<void> {
const {
projectId,
alertId,
alertStateId,
notifyOwners,
rootCause,
stateChangeLog,
props,
} = data;
// get last monitor status timeline.
const lastAlertStatusTimeline: AlertStateTimeline | null =
await AlertStateTimelineService.findOneBy({
query: {
alertId: alertId,
projectId: projectId,
},
select: {
_id: true,
alertStateId: true,
},
sort: {
createdAt: SortOrder.Descending,
},
props: {
isRoot: true,
},
});
if (
lastAlertStatusTimeline &&
lastAlertStatusTimeline.alertStateId &&
lastAlertStatusTimeline.alertStateId.toString() ===
alertStateId.toString()
) {
return;
}
const statusTimeline: AlertStateTimeline = new AlertStateTimeline();
statusTimeline.alertId = alertId;
statusTimeline.alertStateId = alertStateId;
statusTimeline.projectId = projectId;
statusTimeline.isOwnerNotified = !notifyOwners;
if (stateChangeLog) {
statusTimeline.stateChangeLog = stateChangeLog;
}
if (rootCause) {
statusTimeline.rootCause = rootCause;
}
await AlertStateTimelineService.create({
data: statusTimeline,
props: props || {},
});
}
}
export default new Service();

View File

@@ -0,0 +1,154 @@
import CreateBy from "../Types/Database/CreateBy";
import DeleteBy from "../Types/Database/DeleteBy";
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
import QueryHelper from "../Types/Database/QueryHelper";
import UpdateBy from "../Types/Database/UpdateBy";
import DatabaseService from "./DatabaseService";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import LIMIT_MAX from "../../Types/Database/LimitMax";
import BadDataException from "../../Types/Exception/BadDataException";
import ObjectID from "../../Types/ObjectID";
import Model from "Common/Models/DatabaseModels/AlertSeverity";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
protected override async onBeforeCreate(
createBy: CreateBy<Model>,
): Promise<OnCreate<Model>> {
if (!createBy.data.order) {
throw new BadDataException("Alert severity order is required");
}
if (!createBy.data.projectId) {
throw new BadDataException("Alert severity projectId is required");
}
await this.rearrangeOrder(
createBy.data.order,
createBy.data.projectId,
true,
);
return {
createBy: createBy,
carryForward: null,
};
}
protected override async onBeforeDelete(
deleteBy: DeleteBy<Model>,
): Promise<OnDelete<Model>> {
if (!deleteBy.query._id && !deleteBy.props.isRoot) {
throw new BadDataException(
"_id should be present when deleting alert states. Please try the delete with objectId",
);
}
let alertSeverity: Model | null = null;
if (!deleteBy.props.isRoot) {
alertSeverity = await this.findOneBy({
query: deleteBy.query,
props: {
isRoot: true,
},
select: {
order: true,
projectId: true,
},
});
}
return {
deleteBy,
carryForward: alertSeverity,
};
}
protected override async onDeleteSuccess(
onDelete: OnDelete<Model>,
_itemIdsBeforeDelete: ObjectID[],
): Promise<OnDelete<Model>> {
const deleteBy: DeleteBy<Model> = onDelete.deleteBy;
const alertSeverity: Model | null = onDelete.carryForward;
if (!deleteBy.props.isRoot && alertSeverity) {
if (alertSeverity && alertSeverity.order && alertSeverity.projectId) {
await this.rearrangeOrder(
alertSeverity.order,
alertSeverity.projectId,
false,
);
}
}
return {
deleteBy: deleteBy,
carryForward: null,
};
}
protected override async onBeforeUpdate(
updateBy: UpdateBy<Model>,
): Promise<OnUpdate<Model>> {
if (updateBy.data.order && !updateBy.props.isRoot) {
throw new BadDataException(
"Alert Severity order should not be updated. Delete this alert state and create a new state with the right order.",
);
}
return { updateBy, carryForward: null };
}
private async rearrangeOrder(
currentOrder: number,
projectId: ObjectID,
increaseOrder: boolean = true,
): Promise<void> {
// get alert with this order.
const alertSeverities: Array<Model> = await this.findBy({
query: {
order: QueryHelper.greaterThanEqualTo(currentOrder),
projectId: projectId,
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
select: {
_id: true,
order: true,
},
sort: {
order: SortOrder.Ascending,
},
});
let newOrder: number = currentOrder;
for (const alertSeverity of alertSeverities) {
if (increaseOrder) {
newOrder = alertSeverity.order! + 1;
} else {
newOrder = alertSeverity.order! - 1;
}
await this.updateOneBy({
query: {
_id: alertSeverity._id!,
},
data: {
order: newOrder,
},
props: {
isRoot: true,
},
});
}
}
}
export default new Service();

View File

@@ -0,0 +1,227 @@
import CreateBy from "../Types/Database/CreateBy";
import DeleteBy from "../Types/Database/DeleteBy";
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
import QueryHelper from "../Types/Database/QueryHelper";
import UpdateBy from "../Types/Database/UpdateBy";
import DatabaseService from "./DatabaseService";
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import LIMIT_MAX from "../../Types/Database/LimitMax";
import BadDataException from "../../Types/Exception/BadDataException";
import ObjectID from "../../Types/ObjectID";
import AlertState from "Common/Models/DatabaseModels/AlertState";
export class Service extends DatabaseService<AlertState> {
public constructor() {
super(AlertState);
}
protected override async onBeforeCreate(
createBy: CreateBy<AlertState>,
): Promise<OnCreate<AlertState>> {
if (!createBy.data.order) {
throw new BadDataException("Alert State order is required");
}
if (!createBy.data.projectId) {
throw new BadDataException("Alert State projectId is required");
}
await this.rearrangeOrder(
createBy.data.order,
createBy.data.projectId,
true,
);
return {
createBy: createBy,
carryForward: null,
};
}
protected override async onBeforeDelete(
deleteBy: DeleteBy<AlertState>,
): Promise<OnDelete<AlertState>> {
if (!deleteBy.query._id && !deleteBy.props.isRoot) {
throw new BadDataException(
"_id should be present when deleting alert states. Please try the delete with objectId",
);
}
let alertState: AlertState | null = null;
if (!deleteBy.props.isRoot) {
alertState = await this.findOneBy({
query: deleteBy.query,
props: {
isRoot: true,
},
select: {
order: true,
projectId: true,
},
});
}
return {
deleteBy,
carryForward: alertState,
};
}
protected override async onDeleteSuccess(
onDelete: OnDelete<AlertState>,
_itemIdsBeforeDelete: ObjectID[],
): Promise<OnDelete<AlertState>> {
const deleteBy: DeleteBy<AlertState> = onDelete.deleteBy;
const alertState: AlertState | null = onDelete.carryForward;
if (!deleteBy.props.isRoot && alertState) {
if (alertState && alertState.order && alertState.projectId) {
await this.rearrangeOrder(
alertState.order,
alertState.projectId,
false,
);
}
}
return {
deleteBy: deleteBy,
carryForward: null,
};
}
protected override async onBeforeUpdate(
updateBy: UpdateBy<AlertState>,
): Promise<OnUpdate<AlertState>> {
if (updateBy.data.order && !updateBy.props.isRoot) {
throw new BadDataException(
"Alert State order should not be updated. Delete this alert state and create a new state with the right order.",
);
}
return { updateBy, carryForward: null };
}
private async rearrangeOrder(
currentOrder: number,
projectId: ObjectID,
increaseOrder: boolean = true,
): Promise<void> {
// get alert with this order.
const alertStates: Array<AlertState> = await this.findBy({
query: {
order: QueryHelper.greaterThanEqualTo(currentOrder),
projectId: projectId,
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
select: {
_id: true,
order: true,
},
sort: {
order: SortOrder.Ascending,
},
});
let newOrder: number = currentOrder;
for (const alertState of alertStates) {
if (increaseOrder) {
newOrder = alertState.order! + 1;
} else {
newOrder = alertState.order! - 1;
}
await this.updateOneBy({
query: {
_id: alertState._id!,
},
data: {
order: newOrder,
},
props: {
isRoot: true,
},
});
}
}
public async getAllAlertStates(data: {
projectId: ObjectID;
props: DatabaseCommonInteractionProps;
}): Promise<Array<AlertState>> {
const alertStates: Array<AlertState> = await this.findBy({
query: {
projectId: data.projectId,
},
skip: 0,
limit: LIMIT_MAX,
sort: {
order: SortOrder.Ascending,
},
select: {
_id: true,
isResolvedState: true,
isAcknowledgedState: true,
isCreatedState: true,
order: true,
},
props: data.props,
});
return alertStates;
}
public async getUnresolvedAlertStates(
projectId: ObjectID,
props: DatabaseCommonInteractionProps,
): Promise<AlertState[]> {
const alertStates: Array<AlertState> = await this.getAllAlertStates({
projectId: projectId,
props: props,
});
const unresolvedAlertStates: Array<AlertState> = [];
for (const state of alertStates) {
if (!state.isResolvedState) {
unresolvedAlertStates.push(state);
} else {
break; // everything after resolved state is resolved
}
}
return unresolvedAlertStates;
}
public async getAcknowledgedAlertState(data: {
projectId: ObjectID;
props: DatabaseCommonInteractionProps;
}): Promise<AlertState> {
const alertStates: Array<AlertState> = await this.getAllAlertStates({
projectId: data.projectId,
props: data.props,
});
const ackAlertState: AlertState | undefined = alertStates.find(
(alertState: AlertState) => {
return alertState?.isAcknowledgedState;
},
);
if (!ackAlertState) {
throw new BadDataException(
"Acknowledged Alert State not found for this project",
);
}
return ackAlertState;
}
}
export default new Service();

View File

@@ -0,0 +1,334 @@
import CreateBy from "../Types/Database/CreateBy";
import DeleteBy from "../Types/Database/DeleteBy";
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
import QueryHelper from "../Types/Database/QueryHelper";
import DatabaseService from "./DatabaseService";
import AlertService from "./AlertService";
import AlertStateService from "./AlertStateService";
import UserService from "./UserService";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import OneUptimeDate from "../../Types/Date";
import BadDataException from "../../Types/Exception/BadDataException";
import ObjectID from "../../Types/ObjectID";
import PositiveNumber from "../../Types/PositiveNumber";
import AlertState from "Common/Models/DatabaseModels/AlertState";
import AlertStateTimeline from "Common/Models/DatabaseModels/AlertStateTimeline";
import User from "Common/Models/DatabaseModels/User";
import { IsBillingEnabled } from "../EnvironmentConfig";
import { JSONObject } from "../../Types/JSON";
import AlertInternalNote from "../../Models/DatabaseModels/AlertInternalNote";
import AlertInternalNoteService from "./AlertInternalNoteService";
export class Service extends DatabaseService<AlertStateTimeline> {
public constructor() {
super(AlertStateTimeline);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
public async getResolvedStateIdForProject(
projectId: ObjectID,
): Promise<ObjectID> {
const resolvedState: AlertState | null = await AlertStateService.findOneBy({
query: {
projectId: projectId,
isResolvedState: true,
},
props: {
isRoot: true,
},
select: {
_id: true,
},
});
if (!resolvedState) {
throw new BadDataException("No resolved state found for the project");
}
return resolvedState.id!;
}
protected override async onBeforeCreate(
createBy: CreateBy<AlertStateTimeline>,
): Promise<OnCreate<AlertStateTimeline>> {
if (!createBy.data.alertId) {
throw new BadDataException("alertId is null");
}
if (!createBy.data.startsAt) {
createBy.data.startsAt = OneUptimeDate.getCurrentDate();
}
if (
(createBy.data.createdByUserId ||
createBy.data.createdByUser ||
createBy.props.userId) &&
!createBy.data.rootCause
) {
let userId: ObjectID | undefined = createBy.data.createdByUserId;
if (createBy.props.userId) {
userId = createBy.props.userId;
}
if (createBy.data.createdByUser && createBy.data.createdByUser.id) {
userId = createBy.data.createdByUser.id;
}
const user: User | null = await UserService.findOneBy({
query: {
_id: userId?.toString() as string,
},
select: {
_id: true,
name: true,
email: true,
},
props: {
isRoot: true,
},
});
if (user) {
createBy.data.rootCause = `Alert state created by ${user.name} (${user.email})`;
}
}
const lastAlertStateTimeline: AlertStateTimeline | null =
await this.findOneBy({
query: {
alertId: createBy.data.alertId,
},
sort: {
createdAt: SortOrder.Descending,
},
props: {
isRoot: true,
},
select: {
_id: true,
},
});
const internalNote: string | undefined = (
createBy.miscDataProps as JSONObject | undefined
)?.["internalNote"] as string | undefined;
if (internalNote) {
const alertNote: AlertInternalNote = new AlertInternalNote();
alertNote.alertId = createBy.data.alertId;
alertNote.note = internalNote;
alertNote.createdAt = createBy.data.startsAt;
alertNote.projectId = createBy.data.projectId!;
await AlertInternalNoteService.create({
data: alertNote,
props: createBy.props,
});
}
return {
createBy,
carryForward: {
lastAlertStateTimelineId: lastAlertStateTimeline?.id || null,
},
};
}
protected override async onCreateSuccess(
onCreate: OnCreate<AlertStateTimeline>,
createdItem: AlertStateTimeline,
): Promise<AlertStateTimeline> {
if (!createdItem.alertId) {
throw new BadDataException("alertId is null");
}
if (!createdItem.alertStateId) {
throw new BadDataException("alertStateId is null");
}
// update the last status as ended.
if (onCreate.carryForward.lastAlertStateTimelineId) {
await this.updateOneById({
id: onCreate.carryForward.lastAlertStateTimelineId!,
data: {
endsAt: createdItem.createdAt || OneUptimeDate.getCurrentDate(),
},
props: {
isRoot: true,
},
});
}
await AlertService.updateOneBy({
query: {
_id: createdItem.alertId?.toString(),
},
data: {
currentAlertStateId: createdItem.alertStateId,
},
props: onCreate.createBy.props,
});
return createdItem;
}
protected override async onBeforeDelete(
deleteBy: DeleteBy<AlertStateTimeline>,
): Promise<OnDelete<AlertStateTimeline>> {
if (deleteBy.query._id) {
const alertStateTimelineToBeDeleted: AlertStateTimeline | null =
await this.findOneById({
id: new ObjectID(deleteBy.query._id as string),
select: {
alertId: true,
startsAt: true,
},
props: {
isRoot: true,
},
});
const alertId: ObjectID | undefined =
alertStateTimelineToBeDeleted?.alertId;
if (alertId) {
const alertStateTimeline: PositiveNumber = await this.countBy({
query: {
alertId: alertId,
},
props: {
isRoot: true,
},
});
if (alertStateTimeline.isOne()) {
throw new BadDataException(
"Cannot delete the only state timeline. Alert should have at least one state in its timeline.",
);
}
if (alertStateTimelineToBeDeleted?.startsAt) {
const beforeState: AlertStateTimeline | null = await this.findOneBy({
query: {
alertId: alertId,
startsAt: QueryHelper.lessThan(
alertStateTimelineToBeDeleted?.startsAt,
),
},
sort: {
createdAt: SortOrder.Descending,
},
props: {
isRoot: true,
},
select: {
_id: true,
startsAt: true,
},
});
if (beforeState) {
const afterState: AlertStateTimeline | null = await this.findOneBy({
query: {
alertId: alertId,
startsAt: QueryHelper.greaterThan(
alertStateTimelineToBeDeleted?.startsAt,
),
},
sort: {
createdAt: SortOrder.Ascending,
},
props: {
isRoot: true,
},
select: {
_id: true,
startsAt: true,
},
});
if (!afterState) {
// if there's nothing after then end date of before state is null.
await this.updateOneById({
id: beforeState.id!,
data: {
endsAt: null as any,
},
props: {
isRoot: true,
},
});
} else {
// if there's something after then end date of before state is start date of after state.
await this.updateOneById({
id: beforeState.id!,
data: {
endsAt: afterState.startsAt!,
},
props: {
isRoot: true,
},
});
}
}
}
}
return { deleteBy, carryForward: alertId };
}
return { deleteBy, carryForward: null };
}
protected override async onDeleteSuccess(
onDelete: OnDelete<AlertStateTimeline>,
_itemIdsBeforeDelete: ObjectID[],
): Promise<OnDelete<AlertStateTimeline>> {
if (onDelete.carryForward) {
// this is alertId.
const alertId: ObjectID = onDelete.carryForward as ObjectID;
// get last status of this monitor.
const alertStateTimeline: AlertStateTimeline | null =
await this.findOneBy({
query: {
alertId: alertId,
},
sort: {
createdAt: SortOrder.Descending,
},
props: {
isRoot: true,
},
select: {
_id: true,
alertStateId: true,
},
});
if (alertStateTimeline && alertStateTimeline.alertStateId) {
await AlertService.updateOneBy({
query: {
_id: alertId.toString(),
},
data: {
currentAlertStateId: alertStateTimeline.alertStateId,
},
props: {
isRoot: true,
},
});
}
}
return onDelete;
}
}
export default new Service();

View File

@@ -47,12 +47,12 @@ import PositiveNumber from "../../Types/PositiveNumber";
import Text from "../../Types/Text";
import Typeof from "../../Types/Typeof";
import API from "Common/Utils/API";
import { ModelEventType } from "Common/Utils/Realtime";
import { Stream } from "node:stream";
import AggregateBy from "../Types/AnalyticsDatabase/AggregateBy";
import AggregatedResult from "../../Types/BaseDatabase/AggregatedResult";
import Sort from "../Types/AnalyticsDatabase/Sort";
import AggregatedModel from "../../Types/BaseDatabase/AggregatedModel";
import ModelEventType from "../../Types/Realtime/ModelEventType";
export default class AnalyticsDatabaseService<
TBaseModel extends AnalyticsBaseModel,

View File

@@ -1,10 +1,13 @@
import { IsBillingEnabled } from "../EnvironmentConfig";
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/CallLog";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
}
}
}

View File

@@ -0,0 +1,50 @@
import CreateBy from "../Types/Database/CreateBy";
import { OnCreate } from "../Types/Database/Hooks";
import DatabaseService from "./DatabaseService";
import BadDataException from "../../Types/Exception/BadDataException";
import Model from "Common/Models/DatabaseModels/Dashboard";
import { IsBillingEnabled } from "../EnvironmentConfig";
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
import DashboardViewConfigUtil from "../../Utils/Dashboard/DashboardViewConfig";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
protected override async onBeforeCreate(
createBy: CreateBy<Model>,
): Promise<OnCreate<Model>> {
if (IsBillingEnabled) {
// then if free plan, make sure it can only have 1 dashboard.
if (createBy.props.currentPlan === PlanType.Free) {
// get count by project id.
const count: number = (
await this.countBy({
query: {
projectId: createBy.data.projectId,
},
props: {
isRoot: true,
},
})
).toNumber();
if (count > 0) {
throw new BadDataException(
"Free plan can only have 1 dashboard. Please upgrade your plan.",
);
}
}
}
// make sure dashboard config is empty.
createBy.data.dashboardViewConfig =
DashboardViewConfigUtil.createDefaultDashboardViewConfig();
return Promise.resolve({ createBy, carryForward: null });
}
}
export default new Service();

View File

@@ -61,7 +61,7 @@ import Slug from "Common/Utils/Slug";
import { DataSource, Repository, SelectQueryBuilder } from "typeorm";
import { FindWhere } from "../../Types/BaseDatabase/Query";
import Realtime from "../Utils/Realtime";
import { ModelEventType } from "../../Utils/Realtime";
import ModelEventType from "../../Types/Realtime/ModelEventType";
class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
public modelType!: { new (): TBaseModel };
@@ -671,28 +671,25 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
);
}
let tenantId: ObjectID | undefined = createBy.props.tenantId;
if (!tenantId && this.getModel().getTenantColumn()) {
tenantId = createBy.data.getValue<ObjectID>(
this.getModel().getTenantColumn()!,
);
}
// hit workflow.;
if (this.getModel().enableWorkflowOn?.create) {
let tenantId: ObjectID | undefined = createBy.props.tenantId;
if (this.getModel().enableWorkflowOn?.create && tenantId) {
await this.onTriggerWorkflow(createBy.data.id!, tenantId, "on-create");
}
if (!tenantId && this.getModel().getTenantColumn()) {
tenantId = createBy.data.getValue<ObjectID>(
this.getModel().getTenantColumn()!,
);
}
if (tenantId) {
await this.onTriggerWorkflow(
createBy.data.id!,
tenantId,
"on-create",
);
await this.onTriggerRealtime(
createBy.data.id!,
tenantId,
ModelEventType.Create,
);
}
if (tenantId) {
await this.onTriggerRealtime(
createBy.data.id!,
tenantId,
ModelEventType.Create,
);
}
return createBy.data;

View File

@@ -1,10 +1,13 @@
import { IsBillingEnabled } from "../EnvironmentConfig";
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/EmailLog";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
}
}
}

View File

@@ -33,11 +33,14 @@ import Monitor from "Common/Models/DatabaseModels/Monitor";
import MonitorStatus from "Common/Models/DatabaseModels/MonitorStatus";
import MonitorStatusTimeline from "Common/Models/DatabaseModels/MonitorStatusTimeline";
import User from "Common/Models/DatabaseModels/User";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
public async isIncidentAcknowledged(data: {

View File

@@ -18,11 +18,14 @@ import IncidentPublicNote from "Common/Models/DatabaseModels/IncidentPublicNote"
import IncidentState from "Common/Models/DatabaseModels/IncidentState";
import IncidentStateTimeline from "Common/Models/DatabaseModels/IncidentStateTimeline";
import User from "Common/Models/DatabaseModels/User";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<IncidentStateTimeline> {
public constructor() {
super(IncidentStateTimeline);
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
public async getResolvedStateIdForProject(

View File

@@ -137,6 +137,18 @@ import ScheduledMaintenanceTemplateService from "./ScheduledMaintenanceTemplateS
import ScheduledMaintenanceTemplateOwnerTeamService from "./ScheduledMaintenanceTemplateOwnerTeamService";
import ScheduledMaintenanceTemplateOwnerUserService from "./ScheduledMaintenanceTemplateOwnerUserService";
// Alert Services
import AlertStateService from "./AlertStateService";
import AlertService from "./AlertService";
import AlertCustomFieldService from "./AlertCustomFieldService";
import AlertStateTimelineService from "./AlertStateTimelineService";
import AlertInternalNoteService from "./AlertInternalNoteService";
import AlertOwnerTeamService from "./AlertOwnerTeamService";
import AlertOwnerUserService from "./AlertOwnerUserService";
import AlertSeverityService from "./AlertSeverityService";
import AlertNoteTemplateService from "./AlertNoteTemplateService";
import TableViewService from "./TableViewService";
const services: Array<BaseService> = [
AcmeCertificateService,
PromoCodeService,
@@ -285,6 +297,17 @@ const services: Array<BaseService> = [
ScheduledMaintenanceTemplateService,
ScheduledMaintenanceTemplateOwnerTeamService,
ScheduledMaintenanceTemplateOwnerUserService,
AlertStateService,
AlertService,
AlertCustomFieldService,
AlertStateTimelineService,
AlertInternalNoteService,
AlertOwnerTeamService,
AlertOwnerUserService,
AlertSeverityService,
AlertNoteTemplateService,
TableViewService,
];
export const AnalyticsServices: Array<

View File

@@ -12,12 +12,36 @@ import MonitorGroup from "Common/Models/DatabaseModels/MonitorGroup";
import MonitorGroupResource from "Common/Models/DatabaseModels/MonitorGroupResource";
import MonitorStatus from "Common/Models/DatabaseModels/MonitorStatus";
import MonitorStatusTimeline from "Common/Models/DatabaseModels/MonitorStatusTimeline";
import DeleteBy from "../Types/Database/DeleteBy";
import { OnDelete } from "../Types/Database/Hooks";
import StatusPageResourceService from "./StatusPageResourceService";
export class Service extends DatabaseService<MonitorGroup> {
public constructor() {
super(MonitorGroup);
}
protected override async onBeforeDelete(
deleteBy: DeleteBy<MonitorGroup>,
): Promise<OnDelete<MonitorGroup>> {
if (deleteBy.query._id) {
// delete all the status page resource for this monitor.
await StatusPageResourceService.deleteBy({
query: {
monitorGroupId: new ObjectID(deleteBy.query._id as string),
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
});
}
return { deleteBy, carryForward: null };
}
public async getStatusTimeline(
monitorGroupId: ObjectID,
startDate: Date,

View File

@@ -21,7 +21,7 @@ import URL from "../../Types/API/URL";
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
import BadDataException from "../../Types/Exception/BadDataException";
import { JSONObject } from "../../Types/JSON";
import MonitorType, {
@@ -50,12 +50,35 @@ import { CallRequestMessage } from "../../Types/Call/CallRequest";
import UserNotificationSettingService from "./UserNotificationSettingService";
import NotificationSettingEventType from "../../Types/NotificationSetting/NotificationSettingEventType";
import Query from "../Types/Database/Query";
import DeleteBy from "../Types/Database/DeleteBy";
import StatusPageResourceService from "./StatusPageResourceService";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
protected override async onBeforeDelete(
deleteBy: DeleteBy<Model>,
): Promise<OnDelete<Model>> {
if (deleteBy.query._id) {
// delete all the status page resource for this monitor.
await StatusPageResourceService.deleteBy({
query: {
monitorId: new ObjectID(deleteBy.query._id as string),
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
});
}
return { deleteBy, carryForward: null };
}
protected override async onDeleteSuccess(
onDelete: OnDelete<Model>,
_itemIdsBeforeDelete: ObjectID[],

View File

@@ -14,11 +14,14 @@ import ObjectID from "../../Types/ObjectID";
import PositiveNumber from "../../Types/PositiveNumber";
import MonitorStatusTimeline from "Common/Models/DatabaseModels/MonitorStatusTimeline";
import User from "Common/Models/DatabaseModels/User";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<MonitorStatusTimeline> {
public constructor() {
super(MonitorStatusTimeline);
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
protected override async onBeforeCreate(
@@ -33,6 +36,7 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
try {
mutex = await Semaphore.lock({
key: createBy.data.monitorId.toString(),
namespace: "MonitorStatusTimeline.onBeforeCreate",
});
} catch (e) {
logger.error(e);

View File

@@ -0,0 +1,11 @@
import DatabaseService from "./DatabaseService";
import MonitorTest from "Common/Models/DatabaseModels/MonitorTest";
export class Service extends DatabaseService<MonitorTest> {
public constructor() {
super(MonitorTest);
this.hardDeleteItemsOlderThanInDays("createdAt", 2); // this is temporary data. Clear it after 2 days.
}
}
export default new Service();

View File

@@ -6,11 +6,14 @@ import OnCallDutyPolicyStatus from "../../Types/OnCallDutyPolicy/OnCallDutyPolic
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
import OnCallDutyPolicyEscalationRule from "Common/Models/DatabaseModels/OnCallDutyPolicyEscalationRule";
import Model from "Common/Models/DatabaseModels/OnCallDutyPolicyExecutionLog";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 30);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 30);
}
}
protected override async onBeforeCreate(

View File

@@ -16,6 +16,7 @@ export class Service extends DatabaseService<OnCallDutyPolicy> {
policyId: ObjectID,
options: {
triggeredByIncidentId?: ObjectID | undefined;
triggeredByAlertId?: ObjectID | undefined;
userNotificationEventType: UserNotificationEventType;
},
): Promise<void> {
@@ -31,6 +32,16 @@ export class Service extends DatabaseService<OnCallDutyPolicy> {
);
}
if (
UserNotificationEventType.AlertCreated ===
options.userNotificationEventType &&
!options.triggeredByAlertId
) {
throw new BadDataException(
"triggeredByAlertId is required when userNotificationEventType is IncidentCreated",
);
}
const policy: OnCallDutyPolicy | null = await this.findOneById({
id: policyId,
select: {
@@ -62,6 +73,10 @@ export class Service extends DatabaseService<OnCallDutyPolicy> {
log.triggeredByIncidentId = options.triggeredByIncidentId;
}
if (options.triggeredByAlertId) {
log.triggeredByAlertId = options.triggeredByAlertId;
}
await OnCallDutyPolicyExecutionLogService.create({
data: log,
props: {

View File

@@ -28,7 +28,14 @@ import SubscriptionPlan, {
PlanType,
} from "../../Types/Billing/SubscriptionPlan";
import SubscriptionStatus from "../../Types/Billing/SubscriptionStatus";
import { Black, Green, Moroon500, Red, Yellow } from "../../Types/BrandColors";
import {
Black,
Green,
Moroon500,
Red,
Yellow,
Yellow500,
} from "../../Types/BrandColors";
import Color from "../../Types/Color";
import LIMIT_MAX from "../../Types/Database/LimitMax";
import OneUptimeDate from "../../Types/Date";
@@ -50,6 +57,10 @@ import TeamPermission from "Common/Models/DatabaseModels/TeamPermission";
import User from "Common/Models/DatabaseModels/User";
import Select from "../Types/Database/Select";
import Query from "../Types/Database/Query";
import AlertSeverity from "../../Models/DatabaseModels/AlertSeverity";
import AlertSeverityService from "./AlertSeverityService";
import AlertState from "../../Models/DatabaseModels/AlertState";
import AlertStateService from "./AlertStateService";
export interface CurrentPlan {
plan: PlanType | null;
@@ -543,10 +554,12 @@ export class ProjectService extends DatabaseService<Model> {
}
createdItem = await this.addDefaultIncidentSeverity(createdItem);
createdItem = await this.addDefaultAlertSeverity(createdItem);
createdItem = await this.addDefaultProjectTeams(createdItem);
createdItem = await this.addDefaultMonitorStatus(createdItem);
createdItem = await this.addDefaultIncidentState(createdItem);
createdItem = await this.addDefaultScheduledMaintenanceState(createdItem);
createdItem = await this.addDefaultAlertState(createdItem);
return createdItem;
}
@@ -603,6 +616,91 @@ export class ProjectService extends DatabaseService<Model> {
return createdItem;
}
public async addDefaultAlertState(createdItem: Model): Promise<Model> {
let createdAlertState: AlertState = new AlertState();
createdAlertState.name = "Identified";
createdAlertState.description =
"When an alert is created, it belongs to this state";
createdAlertState.color = Red;
createdAlertState.isCreatedState = true;
createdAlertState.projectId = createdItem.id!;
createdAlertState.order = 1;
createdAlertState = await AlertStateService.create({
data: createdAlertState,
props: {
isRoot: true,
},
});
let acknowledgedAlertState: AlertState = new AlertState();
acknowledgedAlertState.name = "Acknowledged";
acknowledgedAlertState.description =
"When an alert is acknowledged, it belongs to this state.";
acknowledgedAlertState.color = Yellow;
acknowledgedAlertState.isAcknowledgedState = true;
acknowledgedAlertState.projectId = createdItem.id!;
acknowledgedAlertState.order = 2;
acknowledgedAlertState = await AlertStateService.create({
data: acknowledgedAlertState,
props: {
isRoot: true,
},
});
let resolvedAlertState: AlertState = new AlertState();
resolvedAlertState.name = "Resolved";
resolvedAlertState.description =
"When an incident is resolved, it belongs to this state.";
resolvedAlertState.color = Green;
resolvedAlertState.isResolvedState = true;
resolvedAlertState.projectId = createdItem.id!;
resolvedAlertState.order = 3;
resolvedAlertState = await AlertStateService.create({
data: resolvedAlertState,
props: {
isRoot: true,
},
});
return createdItem;
}
public async addDefaultAlertSeverity(createdItem: Model): Promise<Model> {
let highSeverity: AlertSeverity = new AlertSeverity();
highSeverity.name = "High";
highSeverity.description =
"Issues causing very high impact to customers. Immediate attention is required.";
highSeverity.color = Moroon500;
highSeverity.projectId = createdItem.id!;
highSeverity.order = 1;
highSeverity = await AlertSeverityService.create({
data: highSeverity,
props: {
isRoot: true,
},
});
let lowSeverity: AlertSeverity = new AlertSeverity();
lowSeverity.name = "Low";
lowSeverity.description = "Issues causing low impact to customers.";
lowSeverity.color = Yellow500;
lowSeverity.projectId = createdItem.id!;
lowSeverity.order = 2;
lowSeverity = await AlertSeverityService.create({
data: lowSeverity,
props: {
isRoot: true,
},
});
return createdItem;
}
private async addDefaultIncidentSeverity(createdItem: Model): Promise<Model> {
let criticalIncident: IncidentSeverity = new IncidentSeverity();
criticalIncident.name = "Critical Incident";

View File

@@ -45,11 +45,15 @@ import StatusPageResource from "Common/Models/DatabaseModels/StatusPageResource"
import StatusPageSubscriber from "Common/Models/DatabaseModels/StatusPageSubscriber";
import Hostname from "../../Types/API/Hostname";
import Protocol from "../../Types/API/Protocol";
import { IsBillingEnabled } from "../EnvironmentConfig";
import StatusPageEventType from "../../Types/StatusPage/StatusPageEventType";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
public async notififySubscribersOnEventScheduled(
@@ -162,6 +166,7 @@ export class Service extends DatabaseService<Model> {
subscriber: subscriber,
statusPageResources: statusPageToResources[statuspage._id!] || [],
statusPage: statuspage,
eventType: StatusPageEventType.ScheduledEvent,
});
if (!shouldNotifySubscriber) {

View File

@@ -22,11 +22,14 @@ import ScheduledMaintenance from "Common/Models/DatabaseModels/ScheduledMaintena
import ScheduledMaintenancePublicNote from "Common/Models/DatabaseModels/ScheduledMaintenancePublicNote";
import ScheduledMaintenanceState from "Common/Models/DatabaseModels/ScheduledMaintenanceState";
import ScheduledMaintenanceStateTimeline from "Common/Models/DatabaseModels/ScheduledMaintenanceStateTimeline";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<ScheduledMaintenanceStateTimeline> {
public constructor() {
super(ScheduledMaintenanceStateTimeline);
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
protected override async onBeforeCreate(

View File

@@ -9,11 +9,14 @@ import Route from "../../Types/API/Route";
import URL from "../../Types/API/URL";
import Text from "../../Types/Text";
import Model from "Common/Models/DatabaseModels/ShortLink";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 3); //expire links in 3 days.
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 3); //expire links in 3 days.
}
}
protected override async onBeforeCreate(

View File

@@ -1,10 +1,13 @@
import { IsBillingEnabled } from "../EnvironmentConfig";
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/SmsLog";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
}
}
}

View File

@@ -50,6 +50,17 @@ export class Service extends DatabaseService<StatusPageDomain> {
createBy.data.cnameVerificationToken = ObjectID.generate().toString();
if (createBy.data.isCustomCertificate) {
if (
!createBy.data.customCertificate ||
!createBy.data.customCertificateKey
) {
throw new BadDataException(
"Custom certificate or private key is missing",
);
}
}
return { createBy, carryForward: null };
}
@@ -168,6 +179,7 @@ export class Service extends DatabaseService<StatusPageDomain> {
const domains: Array<StatusPageDomain> = await this.findBy({
query: {
isSslOrdered: true,
isCustomCertificate: false,
},
select: {
_id: true,
@@ -419,6 +431,7 @@ export class Service extends DatabaseService<StatusPageDomain> {
const domains: Array<StatusPageDomain> = await this.findBy({
query: {
isSslOrdered: false,
isCustomCertificate: false, // only order for non custom certificates.
},
select: {
_id: true,
@@ -507,6 +520,7 @@ export class Service extends DatabaseService<StatusPageDomain> {
const domains: Array<StatusPageDomain> = await this.findBy({
query: {
isSslOrdered: true,
isCustomCertificate: false,
},
select: {
_id: true,

View File

@@ -313,7 +313,7 @@ export class Service extends DatabaseService<StatusPage> {
): Promise<boolean> {
try {
// token decode.
const token: string | undefined = CookieUtil.getCookie(
const token: string | undefined = CookieUtil.getCookieFromExpressRequest(
req,
CookieUtil.getUserTokenKey(statusPageId),
);
@@ -699,12 +699,7 @@ export class Service extends DatabaseService<StatusPage> {
continue;
}
const shouldNotifySubscriber: boolean =
StatusPageSubscriberService.shouldSendNotification({
subscriber: subscriber,
statusPageResources: [],
statusPage: statuspage,
});
const shouldNotifySubscriber: boolean = !subscriber.isUnsubscribed;
if (!shouldNotifySubscriber) {
continue;

View File

@@ -28,6 +28,7 @@ import StatusPage from "Common/Models/DatabaseModels/StatusPage";
import StatusPageResource from "Common/Models/DatabaseModels/StatusPageResource";
import Model from "Common/Models/DatabaseModels/StatusPageSubscriber";
import PositiveNumber from "../../Types/PositiveNumber";
import StatusPageEventType from "../../Types/StatusPage/StatusPageEventType";
export class Service extends DatabaseService<Model> {
public constructor() {
@@ -153,17 +154,6 @@ export class Service extends DatabaseService<Model> {
},
);
if (statuspage && !statuspage.allowSubscribersToChooseResources) {
data.data.isSubscribedToAllResources = true;
} else if (
!data.data.statusPageResources ||
data.data.statusPageResources.length === 0
) {
if (!data.data.isSubscribedToAllResources) {
throw new BadDataException("Select resources to subscribe to.");
}
}
if (!statuspage || !statuspage.projectId) {
throw new BadDataException("Status Page not found");
}
@@ -305,6 +295,8 @@ export class Service extends DatabaseService<Model> {
subscriberWebhook: true,
isSubscribedToAllResources: true,
statusPageResources: true,
isSubscribedToAllEventTypes: true,
statusPageEventTypes: true,
},
skip: 0,
limit: LIMIT_MAX,
@@ -325,33 +317,67 @@ export class Service extends DatabaseService<Model> {
subscriber: Model;
statusPageResources: Array<StatusPageResource>;
statusPage: StatusPage;
eventType: StatusPageEventType;
}): boolean {
let shouldSendNotification: boolean = true; // default to true.
if (data.subscriber.isUnsubscribed) {
return false;
shouldSendNotification = false;
return shouldSendNotification;
}
if (!data.statusPage.allowSubscribersToChooseResources) {
return true;
}
if (
data.statusPage.allowSubscribersToChooseResources &&
!data.subscriber.isSubscribedToAllResources &&
data.eventType !== StatusPageEventType.Announcement // announcements dont have resources
) {
const subscriberResourceIds: Array<string> =
data.subscriber.statusPageResources?.map(
(resource: StatusPageResource) => {
return resource.id?.toString() as string;
},
) || [];
if (data.subscriber.isSubscribedToAllResources) {
return true;
}
let shouldSendNotificationForResource: boolean = false;
const subscriberResourceIds: Array<string> =
data.subscriber.statusPageResources?.map(
(resource: StatusPageResource) => {
return resource.id?.toString() as string;
},
) || [];
if (subscriberResourceIds.length === 0) {
shouldSendNotificationForResource = false;
} else {
for (const resource of data.statusPageResources) {
if (
subscriberResourceIds.includes(resource.id?.toString() as string)
) {
shouldSendNotificationForResource = true;
}
}
}
for (const resource of data.statusPageResources) {
if (subscriberResourceIds.includes(resource.id?.toString() as string)) {
return true;
if (!shouldSendNotificationForResource) {
shouldSendNotification = false;
}
}
return false;
// now do for event types
if (
data.statusPage.allowSubscribersToChooseEventTypes &&
!data.subscriber.isSubscribedToAllEventTypes
) {
const subscriberEventTypes: Array<StatusPageEventType> =
data.subscriber.statusPageEventTypes || [];
let shouldSendNotificationForEventType: boolean = false;
if (subscriberEventTypes.includes(data.eventType)) {
shouldSendNotificationForEventType = true;
}
if (!shouldSendNotificationForEventType) {
shouldSendNotification = false;
}
}
return shouldSendNotification;
}
public async getStatusPagesToSendNotification(
@@ -375,6 +401,7 @@ export class Service extends DatabaseService<Model> {
isPublicStatusPage: true,
logoFileId: true,
allowSubscribersToChooseResources: true,
allowSubscribersToChooseEventTypes: true,
smtpConfig: {
_id: true,
hostname: true,

View File

@@ -0,0 +1,10 @@
import DatabaseService from "./DatabaseService";
import TableView from "Common/Models/DatabaseModels/TableView";
export class Service extends DatabaseService<TableView> {
public constructor() {
super(TableView);
}
}
export default new Service();

View File

@@ -10,11 +10,14 @@ import BadDataException from "../../Types/Exception/BadDataException";
import ProductType from "../../Types/MeteredPlan/ProductType";
import ObjectID from "../../Types/ObjectID";
import Model from "Common/Models/DatabaseModels/TelemetryUsageBilling";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
}
}
public async getUnreportedUsageBilling(data: {

View File

@@ -282,6 +282,34 @@ export class Service extends DatabaseService<UserNotificationSetting> {
});
}
const alertCreatedNotificationEvent: PositiveNumber = await this.countBy({
query: {
userId,
projectId,
eventType:
NotificationSettingEventType.SEND_ALERT_CREATED_OWNER_NOTIFICATION,
},
props: {
isRoot: true,
},
});
if (alertCreatedNotificationEvent.toNumber() === 0) {
const item: UserNotificationSetting = new UserNotificationSetting();
item.userId = userId;
item.projectId = projectId;
item.eventType =
NotificationSettingEventType.SEND_ALERT_CREATED_OWNER_NOTIFICATION;
item.alertByEmail = true;
await this.create({
data: item,
props: {
isRoot: true,
},
});
}
// check monitor state changed notification
const monitorStateChangedNotificationEvent: PositiveNumber =
await this.countBy({
@@ -404,6 +432,36 @@ export class Service extends DatabaseService<UserNotificationSetting> {
},
});
}
// check alert state changed notification
const alertStateChangedNotificationEvent: PositiveNumber =
await this.countBy({
query: {
userId,
projectId,
eventType:
NotificationSettingEventType.SEND_ALERT_STATE_CHANGED_OWNER_NOTIFICATION,
},
props: {
isRoot: true,
},
});
if (alertStateChangedNotificationEvent.toNumber() === 0) {
const item: UserNotificationSetting = new UserNotificationSetting();
item.userId = userId;
item.projectId = projectId;
item.eventType =
NotificationSettingEventType.SEND_ALERT_STATE_CHANGED_OWNER_NOTIFICATION;
item.alertByEmail = true;
await this.create({
data: item,
props: {
isRoot: true,
},
});
}
}
protected override async onBeforeCreate(

View File

@@ -15,11 +15,14 @@ import UserNotificationExecutionStatus from "../../Types/UserNotification/UserNo
import Incident from "Common/Models/DatabaseModels/Incident";
import UserNotificationRule from "Common/Models/DatabaseModels/UserNotificationRule";
import Model from "Common/Models/DatabaseModels/UserOnCallLog";
import { IsBillingEnabled } from "../EnvironmentConfig";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 30);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 30);
}
}
protected override async onBeforeCreate(

View File

@@ -1,10 +1,13 @@
import { IsBillingEnabled } from "../EnvironmentConfig";
import DatabaseService from "./DatabaseService";
import Model from "Common/Models/DatabaseModels/WorkflowLog";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
if (IsBillingEnabled) {
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
}
}
}
export default new Service();

View File

@@ -17,6 +17,10 @@ export default class Markdown {
markdown: string,
contentType: MarkdownContentType,
): Promise<string> {
// convert tags > and < to &gt; and &lt;
markdown = markdown.replace(/</g, "&lt;");
markdown = markdown.replace(/>/g, "&gt;");
let renderer: Renderer | null = null;
if (contentType === MarkdownContentType.Blog) {

View File

@@ -0,0 +1,6 @@
enum PermissionNamespace {
GlobalPermission = "global-permissions",
ProjectPermission = "project-permissions",
}
export default PermissionNamespace;

View File

@@ -11,6 +11,7 @@ import ComponentMetadata, { Port } from "Common/Types/Workflow/Component";
import ComponentID from "Common/Types/Workflow/ComponentID";
import APIComponents from "Common/Types/Workflow/Components/API";
import API from "Common/Utils/API";
import logger from "../../../../Utils/Logger";
export default class ApiPost extends ComponentCode {
public constructor() {
@@ -38,6 +39,25 @@ export default class ApiPost extends ComponentCode {
let apiResult: HTTPResponse<JSONObject> | HTTPErrorResponse | null = null;
logger.debug("API Post Component is running.");
const url: URL = args["url"] as URL;
if (!url) {
throw options.onError(new BadDataException("URL is required"));
}
logger.debug(`URL: ${url}`);
const requestBody: JSONObject = args["request-body"] as JSONObject;
logger.debug(`Request Body: ${JSON.stringify(requestBody)}`);
const requestHeaders: Dictionary<string> = args[
"request-headers"
] as Dictionary<string>;
logger.debug(`Request Headers: ${JSON.stringify(requestHeaders)}`);
try {
apiResult = await API.post(
args["url"] as URL,
@@ -45,6 +65,8 @@ export default class ApiPost extends ComponentCode {
args["request-headers"] as Dictionary<string>,
);
logger.debug("API Post Component is done.");
return Promise.resolve({
returnValues: ApiComponentUtils.getReturnValues(apiResult),
executePort: result.successPort,
@@ -64,6 +86,9 @@ export default class ApiPost extends ComponentCode {
});
}
logger.debug("API Post Component is done with error.");
logger.debug(err);
throw options.onError(new APIException("Something wrong happened."));
}
}

View File

@@ -0,0 +1,111 @@
import APIKeyPermission from "../../../Models/DatabaseModels/ApiKeyPermission";
import Label from "../../../Models/DatabaseModels/Label";
import LIMIT_MAX from "../../../Types/Database/LimitMax";
import ObjectID from "../../../Types/ObjectID";
import Permission, {
UserGlobalAccessPermission,
UserPermission,
UserTenantAccessPermission,
} from "../../../Types/Permission";
import ApiKeyPermissionService from "../../Services/ApiKeyPermissionService";
import UserPermissionUtil from "../UserPermission/UserPermission";
export default class APIKeyAccessPermission {
public static async getDefaultApiGlobalPermission(
projectId: ObjectID,
): Promise<UserGlobalAccessPermission> {
return {
projectIds: [projectId],
globalPermissions: [
Permission.Public,
Permission.User,
Permission.CurrentUser,
],
_type: "UserGlobalAccessPermission",
};
}
public static async getMasterKeyApiGlobalPermission(
projectId: ObjectID,
): Promise<UserGlobalAccessPermission> {
return {
projectIds: [projectId],
globalPermissions: [
Permission.Public,
Permission.User,
Permission.CurrentUser,
Permission.ProjectOwner,
],
_type: "UserGlobalAccessPermission",
};
}
public static async getMasterApiTenantAccessPermission(
projectId: ObjectID,
): Promise<UserTenantAccessPermission> {
const userPermissions: Array<UserPermission> = [];
userPermissions.push({
permission: Permission.ProjectOwner,
labelIds: [],
_type: "UserPermission",
});
const permission: UserTenantAccessPermission =
UserPermissionUtil.getDefaultUserTenantAccessPermission(projectId);
permission.permissions = permission.permissions.concat(userPermissions);
return permission;
}
public static async getApiTenantAccessPermission(
projectId: ObjectID,
apiKeyId: ObjectID,
): Promise<UserTenantAccessPermission> {
// get team permissions.
const apiKeyPermission: Array<APIKeyPermission> =
await ApiKeyPermissionService.findBy({
query: {
apiKeyId: apiKeyId,
},
select: {
permission: true,
labels: {
_id: true,
},
isBlockPermission: true,
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
});
const userPermissions: Array<UserPermission> = [];
for (const apiPermission of apiKeyPermission) {
if (!apiPermission.labels) {
apiPermission.labels = [];
}
userPermissions.push({
permission: apiPermission.permission!,
labelIds: apiPermission.labels.map((label: Label) => {
return label.id!;
}),
isBlockPermission: apiPermission.isBlockPermission,
_type: "UserPermission",
});
}
const permission: UserTenantAccessPermission =
UserPermissionUtil.getDefaultUserTenantAccessPermission(projectId);
permission.permissions = permission.permissions.concat(userPermissions);
return permission;
}
}

Some files were not shown because too many files have changed in this diff Show More