Compare commits

...

608 Commits

Author SHA1 Message Date
Nawaz Dhandala
268d13786f refactor: Define types for connectWithSlack and workspace display name functions in SlackIntegration and WorkspaceNotificationRuleTable 2026-02-12 19:04:36 +00:00
Nawaz Dhandala
79ab00bc29 refactor: Improve code formatting and readability across multiple files 2026-02-12 18:59:21 +00:00
Nawaz Dhandala
95a0ddc49f feat: Add migration for updating indexes and default values in OnCallDutyPolicyScheduleLayer 2026-02-12 18:58:49 +00:00
Nawaz Dhandala
9759d839d9 feat: Add workspaceProjectAuthTokenId for multi-workspace support
- Updated MicrosoftTeamsUtil and SlackUtil to include workspaceProjectAuthTokenId in various methods for better handling of multi-workspace scenarios.
- Modified WorkspaceUtil to utilize workspaceProjectAuthTokenId when fetching project auth tokens.
- Enhanced WorkspaceBase interface to support workspaceProjectAuthTokenId.
- Updated NotificationRuleWorkspaceChannel and WorkspaceMessagePayload to include workspaceProjectAuthTokenId.
- Adjusted SlackChannelCacheModal and SlackIntegration components to handle workspaceProjectAuthTokenId.
- Implemented changes in WorkspaceNotificationRulesTable to support workspaceProjectAuthTokenId selection.
- Added database migration to introduce workspaceProjectAuthTokenId and workspaceProjectId columns in relevant tables.
2026-02-12 18:57:15 +00:00
Nawaz Dhandala
8d3712c36a feat: Enhance probe handling in secrets.yaml with improved logic for existing secrets 2026-02-12 17:05:33 +00:00
Nawaz Dhandala
f8e26246dd refactor: Improve related types handling and add peer dependencies in package-lock.json 2026-02-12 10:33:04 +00:00
Nawaz Dhandala
8560ecab41 chore: Bump version to 9.5.9 2026-02-12 09:14:53 +00:00
Nawaz Dhandala
5b2a6924d9 feat: Enhance DataTypeDetail and data-type.ejs with enriched related types and summary box 2026-02-11 22:51:39 +00:00
Nawaz Dhandala
e047143974 refactor: Improve type annotations and code readability in Dropdown component and migration file 2026-02-11 22:43:09 +00:00
Nawaz Dhandala
d23dc791e2 feat: Enhance data type documentation with category grouping and related types links 2026-02-11 22:38:41 +00:00
Nawaz Dhandala
a4b3b340c8 Add new data types for monitoring criteria and configurations
- Introduced CriteriaFilter, CriteriaIncident, and CriteriaAlert for defining filter conditions and incident configurations.
- Added enums for CheckOn, FilterType, and FilterCondition to specify evaluation aspects and comparison operators.
- Included configurations for various monitor step types: Log, Trace, Metric, and SNMP monitors.
2026-02-11 22:25:59 +00:00
Nawaz Dhandala
2173e4e611 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-11 22:10:58 +00:00
Nawaz Dhandala
dc19f87404 refactor: Clean up code formatting and improve readability across multiple files 2026-02-11 22:08:17 +00:00
Nawaz Dhandala
a3045c5f26 feat: Implement PermissionPicker component for enhanced permission selection 2026-02-11 22:04:25 +00:00
Nawaz Dhandala
5d6907be97 feat: Enhance dropdown options handling by introducing DropdownOptionGroup support 2026-02-11 21:42:57 +00:00
Nawaz Dhandala
e2ace9fc11 feat: Enhance permissions documentation with quick navigation and category links 2026-02-11 21:18:43 +00:00
Nawaz Dhandala
5a11bf228a feat: Enhance permissions handling by grouping permissions into categories 2026-02-11 21:14:55 +00:00
Nawaz Dhandala
cdd8d5523f Implement feature X to enhance user experience and optimize performance 2026-02-11 21:06:04 +00:00
Nawaz Dhandala
f5029fada7 feat: Refactor TypeToDocPath mapping to use dynamic generation from DataTypes 2026-02-11 20:54:47 +00:00
Nawaz Dhandala
8131c9d42f feat: Swap Data Types and Resources sections in navigation 2026-02-11 20:47:15 +00:00
Nawaz Dhandala
946c7d4c48 feat: Add detailed data type documentation and navigation
- Implemented a new DataTypeDetail service to handle detailed views for data types.
- Created a DataTypeUtil to manage data type definitions and retrieval.
- Added a new EJS template for displaying data type details, including properties, values, and JSON examples.
- Updated navigation to include a section for data types in both desktop and mobile views.
- Introduced a new DataTypes module to encapsulate data type information and improve maintainability.
2026-02-11 20:46:02 +00:00
Simon Larsen
9cbc7d9646 Merge pull request #2293 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-02-11 20:20:52 +00:00
Nawaz Dhandala
72d95871f7 feat: enhance model documentation links in API reference view 2026-02-11 19:24:51 +00:00
Nawaz Dhandala
3545a221bc feat: Add Alert Creation Page and Update Related Components
- Implemented a new page for creating alerts with a form that includes fields for title, description, severity, state, monitor, on-call policy, labels, root cause, and remediation notes.
- Updated the AlertsTable component to conditionally render a "Create Alert" button based on the disableCreate prop.
- Modified the AlertsLayout to optionally hide the side menu when navigating to the create alert page.
- Enhanced routing to include a new route for the alert creation page and adjusted the side menu visibility accordingly.
- Updated PageMap and RouteMap to include the new alert creation route.
- Added migration to update database schema related to incident and alert policies.
2026-02-11 19:17:25 +00:00
Nawaz Dhandala
9a5bcb9f31 feat: add migration for updating constraints and indexes in Incident and Alert OnCallDutyPolicy tables 2026-02-11 18:25:10 +00:00
Nawaz Dhandala
91a4d3601c fix: rename columns and update constraints in AlertOnCallDutyPolicy and IncidentOnCallDutyPolicy migrations 2026-02-11 18:23:43 +00:00
Nawaz Dhandala
ea99dd4873 refactor: update model relationships and descriptions for On-Call Duty Policies in Alert, Incident, and IncidentTemplate models; add migration for database schema changes 2026-02-11 18:16:38 +00:00
Nawaz Dhandala
34863dbcb6 fix: rename "Deleted by User ID" to "Acknowledged by User ID" in OnCallDutyPolicyExecutionLog and UserOnCallLog models 2026-02-11 18:09:28 +00:00
Nawaz Dhandala
effeb3a0b6 fix: update title and description for Monitor ID in Alert model 2026-02-11 18:06:59 +00:00
Nawaz Dhandala
86bdcb416a fix: await token refresh before retrying original request in response interceptor 2026-02-11 17:38:36 +00:00
Nawaz Dhandala
665f194f6d feat: add peer dependency flag to multiple packages in package-lock.json 2026-02-11 15:01:14 +00:00
Nawaz Dhandala
1378445dc5 feat: update dependencies for React and React Native 2026-02-11 14:59:54 +00:00
Nawaz Dhandala
236be5b60e feat: conditionally include prefix properties in alert and incident services 2026-02-11 14:53:57 +00:00
Nawaz Dhandala
256f4334eb Merge branch 'release' 2026-02-11 14:32:22 +00:00
Nawaz Dhandala
28d5ad4292 chore: bump version to 9.5.8 2026-02-11 14:32:03 +00:00
Nawaz Dhandala
5c169ccd5b feat: simplify props handling in Slack alert and incident episode actions 2026-02-11 14:27:26 +00:00
Nawaz Dhandala
e05f15d3f6 feat: refactor episode state update methods for Slack and Microsoft Teams actions 2026-02-11 14:24:50 +00:00
Nawaz Dhandala
de0cbe1f42 feat: update on-call policy notifications in Slack and Teams actions for clarity 2026-02-11 13:36:58 +00:00
Nawaz Dhandala
fc48a0efdb feat: add notification for missing on-call policies in Slack actions 2026-02-11 13:31:02 +00:00
Nawaz Dhandala
e623c973ee feat: enhance incident episode note handling with public/private options 2026-02-11 13:26:00 +00:00
Nawaz Dhandala
8d56287892 feat: update workspace channel retrieval to support incident and alert episodes 2026-02-11 13:09:21 +00:00
Nawaz Dhandala
0950d4288f feat: add episode and incident number prefixes to relevant services and messages 2026-02-11 12:58:23 +00:00
Nawaz Dhandala
56ea1c4690 fix: streamline formatting in various services for consistency 2026-02-11 12:52:15 +00:00
Nawaz Dhandala
08d2b6f5a2 feat: add emoji to button titles in Slack incident episode messages 2026-02-11 12:49:21 +00:00
Nawaz Dhandala
2cabdde5bd feat: add workspace notification handling for alert and incident episode services 2026-02-11 12:45:16 +00:00
Nawaz Dhandala
3e48a706bd feat: enhance workspace notification handling in various services 2026-02-11 12:39:48 +00:00
Nawaz Dhandala
7c672e14a1 feat: add workspace notification handling in Alert and Incident episode services 2026-02-11 12:16:42 +00:00
Nawaz Dhandala
80a3bbac3d Merge branch 'master' into release 2026-02-11 11:46:59 +00:00
simlarsen
25f9b826cf chore: npm audit fix 2026-02-11 02:38:02 +00:00
Nawaz Dhandala
c478e6af30 feat: add openSourceDeployment schema with webhookUrl property 2026-02-10 23:26:06 +00:00
Nawaz Dhandala
555a722732 feat: update expo-device to version 8.0.10 and react-native-screens to version 4.16.0 2026-02-10 23:24:47 +00:00
Nawaz Dhandala
6b5f981424 feat: refactor push token handling and move related functions to pushTokenUtils 2026-02-10 23:23:17 +00:00
Nawaz Dhandala
e0e614cf21 feat: enable new architecture in app.json 2026-02-10 23:17:53 +00:00
Nawaz Dhandala
44cc072d98 feat: add expo-system-ui dependency to package.json and package-lock.json 2026-02-10 23:15:38 +00:00
Nawaz Dhandala
c2c97dae0a feat: add mobile app Android and iOS deployment jobs to release workflow 2026-02-10 23:09:02 +00:00
Nawaz Dhandala
3978374ccb feat: add release signing setup documentation for Android and iOS 2026-02-10 23:08:24 +00:00
Nawaz Dhandala
6950daf10a feat: add workflows for mobile app Android and iOS deployment 2026-02-10 23:06:32 +00:00
Nawaz Dhandala
7a07e669c9 feat: add mobile app compilation and testing workflows 2026-02-10 22:55:57 +00:00
Nawaz Dhandala
67ece0fcca refactor: enhance type safety and improve code readability across multiple files 2026-02-10 22:45:12 +00:00
Nawaz Dhandala
5413e24bd4 refactor: enhance type safety and improve code readability across multiple files
- Updated hooks to return specific types using UseQueryResult for better type safety.
- Refactored various components to explicitly define return types for functions and callbacks.
- Improved type annotations for variables and function parameters in screens and hooks.
- Enhanced readability by restructuring code and ensuring consistent formatting.
- Added missing type imports and ensured proper usage of types from the API.
- Cleaned up unnecessary type assertions and improved overall code clarity.
2026-02-10 22:38:45 +00:00
Nawaz Dhandala
59b3fc0334 Refactor screens and components for improved readability and consistency
- Simplified state management and data fetching in IncidentEpisodeDetailScreen.
- Enhanced code clarity by using arrow functions consistently and removing unnecessary destructuring.
- Improved type annotations across various screens for better TypeScript support.
- Streamlined the rendering of components in IncidentEpisodesScreen and IncidentsScreen.
- Updated NotificationPreferencesScreen to use consistent function signatures and improved readability.
- Refactored ProjectSelectionScreen and SettingsScreen for better structure and clarity.
- Enhanced LoginScreen and ServerUrlScreen with clearer type definitions and improved error handling.
- Updated storage utilities to ensure consistent type usage and improved code clarity.
- Refactored theme context and spacing utilities for better type safety and readability.
- Improved color and date utility functions for better maintainability.
2026-02-10 22:29:37 +00:00
Nawaz Dhandala
2bc72dbdb6 feat: update project view route to use current navigation context 2026-02-10 22:21:19 +00:00
Nawaz Dhandala
15ccf00503 chore: update expo-server-sdk to version 3.15.0; reorganize push notifications documentation
- Updated expo-server-sdk in package.json from 3.10.0 to 3.15.0.
- Deleted outdated firebase-push-notifications.md and created new push-notifications.md for clarity.
- Updated navigation links in Nav.ts and README.md to point to the new push-notifications documentation.
2026-02-10 22:07:39 +00:00
Nawaz Dhandala
b3d73a5523 feat: add notification preferences screen and settings stack navigator
feat: implement notification preferences management with local storage
feat: enhance accessibility for alert and incident actions
feat: integrate haptic feedback for user interactions in various screens
refactor: update navigation structure to include settings and notification preferences
2026-02-10 22:04:37 +00:00
Nawaz Dhandala
43e6291608 feat: enhance incident detail screens with haptic feedback and loading skeletons
- Added haptic feedback on state change actions in IncidentDetailScreen and IncidentEpisodeDetailScreen.
- Replaced ActivityIndicator with SkeletonCard for better loading experience in IncidentDetailScreen and IncidentEpisodeDetailScreen.
- Updated empty state messages in IncidentEpisodesScreen and IncidentsScreen for clarity.
- Refactored SettingsScreen to improve layout and added biometric authentication options.
- Introduced OfflineBanner component to notify users of network issues.
- Created SwipeableCard component for better interaction with list items.
- Implemented useBiometric and useNetworkStatus hooks for managing biometric settings and network status.
- Added BiometricLockScreen for unlocking the app using biometric authentication.
- Introduced preferences storage for theme mode and biometric settings.
2026-02-10 21:54:18 +00:00
Nawaz Dhandala
09d82f64de refactor: remove Firebase Cloud Messaging configuration and related code for push notifications 2026-02-10 21:38:42 +00:00
Nawaz Dhandala
51ed9fc2bb feat: implement push notification registration and unregistration functionality 2026-02-10 21:27:35 +00:00
Nawaz Dhandala
b23ccdcc57 feat: add Incident and Alert Episodes screens and navigators
- Created IncidentEpisodesStackNavigator for managing navigation between incident episodes list and detail screens.
- Implemented AlertEpisodesScreen to display a list of alert episodes with pagination and refresh functionality.
- Developed AlertEpisodeDetailScreen to show detailed information about a specific alert episode, including state changes and internal notes.
- Added IncidentEpisodesScreen to display a list of incident episodes with similar functionality to the alert episodes screen.
- Created IncidentEpisodeDetailScreen for detailed view of incident episodes, including state management and note-taking features.
- Integrated hooks for fetching data related to alert and incident episodes.
- Added UI components for displaying episode details, actions, and notes.
2026-02-10 20:34:53 +00:00
Nawaz Dhandala
147e687bac fix: refactor alert and incident state handling to use state IDs for acknowledgment and resolution 2026-02-10 20:15:46 +00:00
Nawaz Dhandala
b84cebcb10 feat: add hooks and screens for alerts and incidents management
- Implemented `useAlertDetail`, `useAlertStates`, and `useAlertStateTimeline` hooks for fetching alert details, states, and timelines.
- Created `useAlerts` and `useUnresolvedAlertCount` hooks for managing alerts list and unresolved alert counts.
- Developed `useIncidentDetail`, `useIncidentStates`, and `useIncidentStateTimeline` hooks for incident management.
- Added `useIncidents` and `useUnresolvedIncidentCount` hooks for fetching incidents and unresolved incident counts.
- Introduced `ProjectProvider` and `useProject` hook for managing project selection and state.
- Created `AlertsStackNavigator` and `IncidentsStackNavigator` for navigation between alerts and incidents screens.
- Developed `AlertDetailScreen` and `IncidentDetailScreen` for displaying detailed information about alerts and incidents.
- Added `ProjectSelectionScreen` for selecting projects with loading and error handling.
- Implemented utility functions for color conversion and date formatting.
2026-02-10 20:10:37 +00:00
Nawaz Dhandala
7374e3bf9a fix: update UI/UX design philosophy to emphasize native app experience 2026-02-10 18:00:54 +00:00
Nawaz Dhandala
413ba90b02 fix: correct property access for miscData in login function 2026-02-10 17:59:55 +00:00
Nawaz Dhandala
2fd61385bd fix: update login function to structure email and password as objects 2026-02-10 17:58:04 +00:00
Nawaz Dhandala
822bc9f8d5 fix: update newArchEnabled to false and modify start scripts in package.json 2026-02-10 17:54:43 +00:00
Nawaz Dhandala
e53a490606 Merge branch 'master' into release 2026-02-10 16:39:21 +00:00
Nawaz Dhandala
cc53460e7a feat: add README.md for OneUptime Mobile App setup and configuration 2026-02-10 16:01:51 +00:00
Nawaz Dhandala
7d6e0488ba feat: add Firebase Cloud Messaging configuration for native push notifications 2026-02-10 15:58:12 +00:00
Nawaz Dhandala
385a0fb9e5 fix: change deviceType property type to PushDeviceType in UserPush model 2026-02-10 15:34:21 +00:00
Nawaz Dhandala
584b79f48c Merge branch 'master' into mob-phase-1 2026-02-10 15:26:41 +00:00
Nawaz Dhandala
92901b1647 feat: add openSourceDeployment schema and update values.yaml documentation 2026-02-10 15:23:15 +00:00
Nawaz Dhandala
bcbc4f6d99 chore: bump version to 9.5.7 2026-02-10 15:00:30 +00:00
Nawaz Dhandala
04dd1260ac style: improve code formatting for better readability in Register and BasicForm components 2026-02-10 15:00:08 +00:00
Nawaz Dhandala
882f9f6ae4 feat: add support for full row spanning in form fields and conditionally display notification checkbox based on billing status 2026-02-10 14:58:51 +00:00
Nawaz Dhandala
549dc3546b refactor: clean up code formatting and improve readability in Authentication and OpenSourceDeploymentAPI 2026-02-10 14:14:33 +00:00
Nawaz Dhandala
25edcf7d9b feat: add migration for OpenSourceDeployment table and update OnCallDutyPolicyScheduleLayer defaults 2026-02-10 14:13:07 +00:00
Nawaz Dhandala
46378fc3db Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-10 14:11:31 +00:00
Nawaz Dhandala
f9f5bff4ce feat: add Open Source Deployment webhook support and related configuration 2026-02-10 14:11:03 +00:00
Nawaz Dhandala
12b78249c5 feat: rename version field to oneuptimeVersion in OpenSourceDeployment model and API 2026-02-10 13:57:55 +00:00
Nawaz Dhandala
f8cbc3a551 feat: implement Open Source Deployment registration and related database schema 2026-02-10 13:50:56 +00:00
Simon Larsen
670b984cee Merge pull request #2288 from OneUptime/episode-resolve
Episode resolve
2026-02-10 13:29:17 +00:00
Nawaz Dhandala
e677e54ea9 feat: update migration and services to handle allIncidentsResolvedAt and allAlertsResolvedAt fields 2026-02-10 13:28:18 +00:00
Nawaz Dhandala
928a2589c2 feat: remove workspaceProjectAuthTokenId from WorkspaceNotificationRule in migration 2026-02-10 13:20:40 +00:00
Nawaz Dhandala
45f7a86888 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-10 13:12:42 +00:00
Nawaz Dhandala
0fa7848ab9 feat: add migration for allIncidentsResolvedAt and allAlertsResolvedAt fields with index creation 2026-02-10 13:12:10 +00:00
Nawaz Dhandala
ae6e49da8f feat: add allAlertsResolvedAt and allIncidentsResolvedAt fields for resolve delay calculations 2026-02-10 13:08:42 +00:00
Simon Larsen
e80e22b1fa Merge pull request #2285 from OneUptime/inc-episode
feat(AutoResolve): implement resolve delay logic based on incident gr…
2026-02-10 12:42:17 +00:00
Simon Larsen
2adefd1cee Merge pull request #2287 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-02-10 11:17:17 +00:00
simlarsen
36cbb3159a chore: npm audit fix 2026-02-10 02:40:36 +00:00
Nawaz Dhandala
54909116b9 mobile phase 1 2026-02-09 23:45:17 +00:00
Nawaz Dhandala
4582f6100a feat(MobileApp): enhance UI/UX design philosophy with modern aesthetics and user experience considerations 2026-02-09 22:49:00 +00:00
Nawaz Dhandala
49a01eca8c feat(MobileApp): add UI/UX design philosophy and core design principles to the design document 2026-02-09 22:47:15 +00:00
Nawaz Dhandala
349df0e181 feat(MobileApp): enhance multi-project support with project badges and filters in UI 2026-02-09 22:43:03 +00:00
Nawaz Dhandala
c52116bec1 feat(MobileApp): add design document for OneUptime On-Call mobile app 2026-02-09 22:32:55 +00:00
Nawaz Dhandala
098a18005f feat(ResolveInactiveEpisodes): implement inactivity timeout logic based on incident grouping rules 2026-02-09 22:20:42 +00:00
Nawaz Dhandala
6dbcd69ecd feat(AutoResolve): implement resolve delay logic based on incident grouping rules 2026-02-09 21:49:49 +00:00
Nawaz Dhandala
09a6827709 refactor(Service): streamline incident count template replacement 2026-02-09 21:16:52 +00:00
Nawaz Dhandala
dbb1fa6c18 feat(IncidentEpisodeService): enhance incident count update with dynamic title and description templates 2026-02-09 21:15:56 +00:00
Nawaz Dhandala
cd450bc3b6 feat(migrations): set default value of groupByMonitor to false for Alert and Incident grouping rules 2026-02-09 20:15:15 +00:00
Nawaz Dhandala
047195116d feat(migrations): optimize backfill queries to use MAX instead of COUNT for performance and accuracy 2026-02-09 19:27:12 +00:00
Nawaz Dhandala
564f21388b chore(VERSION): bump version to 9.5.6 2026-02-09 18:21:05 +00:00
Nawaz Dhandala
c69d7c949e feat(templates): reorder service and autoscaler definitions in Helm chart templates 2026-02-09 18:04:54 +00:00
Nawaz Dhandala
dd47b9c3a9 feat(e2e-tests): add CRUD and idempotency tests for oneuptime_file resource 2026-02-09 14:46:40 +00:00
Nawaz Dhandala
ce731cb489 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-09 14:41:34 +00:00
Nawaz Dhandala
f725fdd2d9 feat(ResourceGenerator): implement no-op methods for read, update, and delete operations 2026-02-09 14:41:32 +00:00
Simon Larsen
1aec570c83 Merge pull request #2280 from OneUptime/feat/readme-ai-copilot
docs: add AI Copilot section to README
2026-02-09 14:32:57 +00:00
Jamie Mallers
97b7e15ece docs: add AI Copilot section to README
Highlight the AI agent capabilities - auto-detection, root cause analysis,
and automated code fix PRs. This is our key differentiator and was missing
from the README.
2026-02-09 14:31:03 +00:00
Nawaz Dhandala
7cdac5fe66 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-09 14:28:11 +00:00
Nawaz Dhandala
4add175070 refactor(Monitor): improve code readability by consolidating API ping parameters
refactor(Migration): update comments for clarity and maintainability
fix(MarkdownEditor): adjust code block formatting for consistency in documentation
2026-02-09 14:28:09 +00:00
Nawaz Dhandala
711cfd2f6b feat(MonitorUtil): add tests for URL placeholder resolution and update method visibility 2026-02-09 14:21:05 +00:00
Nawaz Dhandala
6869ee670a fix(VMUtil): skip replacement if variable is not found in storageMap 2026-02-09 14:17:20 +00:00
Nawaz Dhandala
c4d978cc3b feat: add API and Website monitor documentation with dynamic URL placeholders 2026-02-09 14:11:02 +00:00
Simon Larsen
1dffc2fbbe Merge pull request #2279 from OneUptime/feat/ga4-signup-tracking
feat(analytics): add GA4 sign_up and page view tracking
2026-02-09 13:56:18 +00:00
Jamie Mallers
6b0756cd3a feat(analytics): add GA4 sign_up and page view tracking
- Fire sign_up event on successful registration (Accounts/Register.tsx)
- Fire page_view_pricing event on pricing page load
- Fire page_view_demo event on demo page load
- All events use dataLayer.push for GTM/GA4 compatibility
2026-02-09 13:54:44 +00:00
Simon Larsen
fbfa7747e0 Merge pull request #2278 from OneUptime/fluentbit
Fluentbit
2026-02-09 13:14:59 +00:00
Nawaz Dhandala
a7c38dcbf2 refactor(FluentLogsIngestService): improve code readability by formatting function arguments and object properties 2026-02-09 13:14:39 +00:00
Nawaz Dhandala
6b8dd9e8b5 feat(FluentLogsIngestService): enhance log ingestion with structured fields and attributes extraction
test(FluentLogsIngestService): add comprehensive tests for log normalization and attribute extraction
2026-02-09 13:05:52 +00:00
Nawaz Dhandala
c5e7429b3d chore(VERSION): bump version to 9.5.5 2026-02-09 11:54:17 +00:00
Nawaz Dhandala
13ccee4e69 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-09 11:53:31 +00:00
Nawaz Dhandala
f9c9ac5ef0 fix(Migration): optimize backfill queries for project counters using JOINs 2026-02-09 11:53:29 +00:00
Nawaz Dhandala
10654a0a04 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-09 11:07:56 +00:00
Nawaz Dhandala
0d900dca78 fix(StatusPageDomain): change subdomain requirement from required to optional 2026-02-09 11:07:24 +00:00
Nawaz Dhandala
bf5846e7f4 fix(ProductCompare): improve question formatting for clarity in FAQ section 2026-02-08 22:25:06 +00:00
Nawaz Dhandala
9fa48c7a25 chore(VERSION): bump version to 9.5.4 2026-02-08 22:02:16 +00:00
Simon Larsen
9efb070334 Merge pull request #2276 from OneUptime/fix/seo-better-uptime-enhanced
SEO: Add FAQ schema to compare pages + enhance Better Uptime content
2026-02-08 18:46:52 +00:00
Nawaz Dhandala
85e7dd1150 fix(sitemap): update comment format for clarity on blog tag sitemaps removal 2026-02-08 18:16:51 +00:00
Nawaz Dhandala
072f162b6e fix(Project): update create permissions to allow User role 2026-02-08 18:12:26 +00:00
Nawaz Dhandala
9e01b0b75a fix(playwright): install browsers to a fixed path for runtime accessibility 2026-02-08 17:56:59 +00:00
Nawaz Dhandala
3d7b98d1ee fix(deps): update net-snmp to version 3.26.1 2026-02-08 15:37:41 +00:00
Jamie Mallers
62f6900dd2 Merge origin/master - resolve conflict in product-compare.ejs
Keep both:
- Updated meta description from master
- FAQ schema for rich snippets from this branch
2026-02-08 15:20:49 +00:00
Jamie Mallers
51cf4a88bf SEO: Add FAQ schema + enhance Better Uptime comparison content
Changes:
1. Add JSON-LD FAQ schema to all compare pages for rich snippets
2. Expand Better Uptime FAQs from 4 to 8 questions
3. Add more detailed answers covering:
   - Better Uptime → Better Stack rebrand context
   - Self-hosting advantages
   - Detailed pricing comparison
   - Feature differences

Target: /compare/better-uptime at position 13.5 for 'better uptime' query
Expected: Rich snippet eligibility + better content relevance
2026-02-08 09:21:54 +00:00
Simon Larsen
0dfd38d263 Merge pull request #2275 from OneUptime/fix/seo-compare-page-titles
fix(seo): improve compare page title tags for better CTR
2026-02-07 20:44:53 +00:00
Simon Larsen
66424eee24 Merge pull request #2274 from OneUptime/fix/seo-meta-descriptions
fix(seo): unique meta descriptions for product pages
2026-02-07 20:44:14 +00:00
Simon Larsen
93adee4b16 Merge pull request #2273 from OneUptime/fix/seo-noindex-tag-pages
fix(seo): noindex tag pages and remove from sitemap
2026-02-07 20:42:57 +00:00
Jamie Mallers
d7efe2445c fix(seo): improve compare page title tags for better CTR
Changed title pattern from:
'OneUptime vs [Product]: Open-Source Alternative | 2026 Comparison'

To:
'[Product] Alternative - OneUptime | Open Source | 2026 Comparison'

Rationale:
- Puts competitor name first (matches search intent)
- 'Alternative' keyword prominent (what users search for)
- Shorter, more scannable

Also improved meta description to be more action-oriented with clear value props.

Targets: /compare/better-uptime (position 13.5, 803 impressions)
2026-02-07 17:01:18 +00:00
Jamie Mallers
1bf4c52518 fix(seo): unique meta descriptions for product pages
Multiple product pages had identical generic meta descriptions:
'OneUptime monitors websites, APIs, and servers...'

This hurt CTR because Google showed the same text for different pages.

Updated with unique, keyword-rich descriptions:
- /product/status-page: Focus on free, unlimited subscribers, Statuspage alternative
- /product/monitoring: Focus on global locations, alerts, Datadog alternative
- /product/incident-management: Focus on features, integrations
- /product/on-call: Focus on rotations, escalations, PagerDuty alternative
- /about: Focus on open source, GitHub stars, mission

Expected impact: Improved CTR from search results
2026-02-07 16:53:21 +00:00
Jamie Mallers
8348bf6897 fix(seo): noindex tag pages and remove from sitemap
Google Search Console shows 0/10,519 pages indexed. Root cause: 5,000+
thin tag pages are diluting site quality signals and consuming crawl budget.

Changes:
- Add noindex,follow meta tag to blog tag pages (ListByTag.ejs)
- Remove tag sitemaps from sitemap index (Sitemap.ts)

This tells Google to:
1. Stop trying to index tag pages (they're thin content)
2. Still follow links on those pages to discover real content
3. Focus crawl budget on valuable pages (blog posts, product pages)

Expected impact:
- Improved crawl budget efficiency
- Better quality signals for the domain
- Gradual improvement in indexing of valuable pages
2026-02-07 15:49:51 +00:00
Simon Larsen
7f2192206f Merge pull request #2272 from OneUptime/prefix-alert-number
Prefix alert number
2026-02-06 20:50:57 +00:00
Nawaz Dhandala
ddf7636965 Set default number prefixes for incident, alert, and maintenance numbers in ProjectService 2026-02-06 20:48:02 +00:00
Nawaz Dhandala
52514fbb7e Rename parameter onCreate to _onCreate in onCreateSuccess method for clarity 2026-02-06 20:40:21 +00:00
Nawaz Dhandala
2c3521561d Add type annotations to fix ESLint typedef errors for numberResult variables
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 20:31:31 +00:00
Nawaz Dhandala
8d6ef5a277 Refactor alert and incident number display formatting
- Updated multiple components and worker jobs to improve the formatting of alert and incident numbers.
- Ensured consistent use of conditional rendering for alert and incident numbers with prefixes.
- Enhanced readability by using multiline return statements for JSX elements.
2026-02-06 20:27:35 +00:00
Nawaz Dhandala
726ae7ef98 Fix prefix display in UI tables and detail views by adding WithPrefix to selectMoreFields
ModelTable/CardModelDetail only fetch the first key from column field objects.
The WithPrefix fields must be in selectMoreFields to be included in the API query.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 20:19:52 +00:00
Nawaz Dhandala
fde974d968 Add alertNumberWithPrefix support to AlertEpisodeMemberService and UserNotificationRuleService
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 20:08:08 +00:00
Nawaz Dhandala
eae5e026fa Add prefix support to monitor evaluation log incident/alert number display
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 20:00:44 +00:00
Nawaz Dhandala
5b01743e74 Add alertNumberWithPrefix support to AlertOwners Worker notification files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 19:53:01 +00:00
Nawaz Dhandala
2cfc6a5e68 feat: Add migration for new prefix fields in Project, Incident, Alert, and ScheduledMaintenance tables 2026-02-06 19:46:40 +00:00
Nawaz Dhandala
0976df1bee feat: Add custom prefixes for alert, incident, and scheduled maintenance numbers
- Implemented functionality to allow users to set custom prefixes for alert numbers and alert episode numbers in the AlertMoreSettings component.
- Added similar functionality for incident numbers and incident episode numbers in the IncidentMoreSettings component.
- Introduced custom prefixes for scheduled maintenance numbers in the ScheduledMaintenanceMoreSettings component.
- Updated various notification jobs to utilize the new prefix settings for alert, incident, and scheduled maintenance numbers.
- Ensured backward compatibility by maintaining the default '#' prefix when no custom prefix is provided.
2026-02-06 19:43:11 +00:00
Nawaz Dhandala
caa59aea7e Refactor Analytics event tracking for consistent string quoting 2026-02-06 14:46:44 +00:00
Nawaz Dhandala
ab5e0ec3c4 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-02-06 14:43:21 +00:00
Nawaz Dhandala
f4eda526c5 Remove semaphore mutex implementation from AlertEpisodeService and IncidentEpisodeService for simplified episode creation 2026-02-06 14:43:19 +00:00
Nawaz Dhandala
19f347a826 Remove semaphore mutex implementation from AlertService, IncidentService, and ScheduledMaintenanceService for simplified alert and incident creation 2026-02-06 14:39:49 +00:00
Nawaz Dhandala
7eb84c2fb0 Refactor increment methods in ProjectService to use atomicIncrementColumnValueByOne for better code reuse 2026-02-06 14:32:30 +00:00
Nawaz Dhandala
a27f3953ab Add counters for incidents, alerts, and scheduled maintenance to Project model and implement corresponding increment methods 2026-02-06 14:30:16 +00:00
Simon Larsen
4ec162208b Merge pull request #2269 from OneUptime/fix/add-ga4-conversion-tracking
Add GA4 conversion tracking for demo bookings and CTA clicks
2026-02-06 00:00:01 +00:00
Jamie Mallers
13482b13d7 Add GA4 tracking to Analytics module for signup and all events
- All events captured via Analytics.capture() now also push to GA4 dataLayer
- This enables tracking signups (accounts/register) and other events in GA4
- Works alongside existing PostHog tracking
2026-02-05 23:52:33 +00:00
Jamie Mallers
69c0253862 Add GA4 conversion tracking for demo bookings and CTA clicks
- Add GA4 gtag event tracking alongside PostHog for demo bookings
- Add dataLayer push for GTM compatibility
- Add CTA click tracking for 'Get started' and 'Request demo' buttons
- Enable conversion funnel analysis in Google Analytics

This fixes the issue where GA4 Key Events showed 0 conversions
despite demos being booked (only tracked in PostHog previously).
2026-02-05 23:42:10 +00:00
Nawaz Dhandala
92d8b7b425 Add computed property to various database models 2026-02-05 15:23:06 +00:00
Nawaz Dhandala
0ef053dc3d Add computed property to schedule next event column in ScheduledMaintenanceTemplate 2026-02-05 13:52:34 +00:00
Nawaz Dhandala
fa0bd99bc8 Bump version to 9.5.3 2026-02-05 12:58:30 +00:00
Simon Larsen
68b6ca9fd3 Merge pull request #2267 from OneUptime/episode-status-page
Episode status page
2026-02-05 12:58:03 +00:00
Simon Larsen
cd9b711ee4 Merge pull request #2268 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-02-05 12:56:59 +00:00
Nawaz Dhandala
b05d1652e1 Implement logic to mark episode public notes and state timelines as Skipped for subscriber notifications 2026-02-05 12:52:55 +00:00
Nawaz Dhandala
d971573db0 Refactor code for improved readability and consistency
- Adjusted formatting in PublicNote.tsx for better alignment of imports and function parameters.
- Reformatted episode monitor extraction in Detail.tsx for clarity.
- Enhanced readability of episodes data parsing in List.tsx.
2026-02-05 12:48:13 +00:00
Nawaz Dhandala
5a11518c31 Add episode settings section to Alert Grouping Rules page 2026-02-05 12:47:09 +00:00
Nawaz Dhandala
ce4f41367b Add episode settings section to Incident Grouping Rules page 2026-02-05 12:44:37 +00:00
Nawaz Dhandala
f553726186 Refactor code structure for improved readability and maintainability 2026-02-05 12:32:56 +00:00
Nawaz Dhandala
1bd746b285 Update icon SVG path for improved rendering and clarity 2026-02-05 12:14:41 +00:00
Nawaz Dhandala
82558fda59 Add episode management features to Status Page
- Implement fetching and displaying active incident episodes on the Status Page.
- Introduce episode public notes and state timelines for enhanced episode details.
- Create EpisodeGroup type to structure episode-related data.
- Update Overview component to integrate episodes alongside incidents.
2026-02-05 12:11:41 +00:00
Nawaz Dhandala
3f1fe2bf1c Preserve monitor data in episodes from raw JSON and update serialization logic 2026-02-05 12:00:57 +00:00
Nawaz Dhandala
d00fa80e47 Add monitor mapping and resource filtering for episode events in Detail component 2026-02-05 11:40:37 +00:00
Nawaz Dhandala
dc4805c3b2 Add settings page for incident episodes with routing and UI integration 2026-02-05 11:27:50 +00:00
Nawaz Dhandala
642fb95209 Replace Toggle components with Checkbox in MonitorCriteriaAlertForm and MonitorCriteriaIncidentForm 2026-02-05 11:19:06 +00:00
Nawaz Dhandala
01baf60b2e Add endpoint and logic for retrieving incident episode public note attachments 2026-02-05 10:52:03 +00:00
simlarsen
225679f5d3 chore: npm audit fix 2026-02-05 02:25:19 +00:00
Nawaz Dhandala
51f16e2213 Add public notes feature for incident episodes with routing and UI integration 2026-02-04 21:55:32 +00:00
Nawaz Dhandala
0af23bbacb Add migration for new StatusPage fields and update index 2026-02-04 20:36:14 +00:00
Nawaz Dhandala
7b446a853c Add migration for StatusPage enhancements and OnCallDutyPolicyScheduleLayer defaults 2026-02-04 20:35:43 +00:00
Nawaz Dhandala
df480577ab Clarify comments regarding incident visibility and episode display logic in StatusPageAPI 2026-02-04 20:33:42 +00:00
Nawaz Dhandala
c031cc2af3 Refactor incident query logic to clarify episode visibility criteria on status page 2026-02-04 20:31:26 +00:00
Nawaz Dhandala
ae17820d0d Add subscriber episode notification templates for incident updates 2026-02-04 20:28:37 +00:00
Nawaz Dhandala
f2f3900506 Refactor notification templates and job scripts to replace "Episode" with "Incident" for consistency across the application. 2026-02-04 20:26:49 +00:00
Nawaz Dhandala
4c8b92144c Refactor code for improved readability and consistency: adjust formatting, enhance type annotations, and streamline notification logging in various files. 2026-02-04 20:20:08 +00:00
Nawaz Dhandala
4c45e16f56 Refactor episode handling: remove EpisodeDetail component and update routing; enhance incident and episode event item retrieval 2026-02-04 20:13:25 +00:00
Nawaz Dhandala
53e39724e7 Add episode management features to status page: enable episode display, history, and labels 2026-02-04 20:09:01 +00:00
Nawaz Dhandala
849882d868 Add notification jobs for incident episode public notes and state timelines
- Implemented SendNotificationToSubscribers job for IncidentEpisodePublicNote to notify subscribers about new public notes added to episodes.
- Implemented SendNotificationToSubscribers job for IncidentEpisodeStateTimeline to notify subscribers about state changes of episodes.
- Both jobs include logic for fetching relevant episodes, monitors, and subscribers, and sending notifications via email, SMS, Slack, and Microsoft Teams.
- Added error handling and logging for better traceability of notification processes.
2026-02-04 19:11:44 +00:00
Nawaz Dhandala
e3f8af83e5 Add showIncidentOnStatusPage feature to CriteriaIncident and update forms 2026-02-04 18:30:06 +00:00
Simon Larsen
18a5559116 Merge pull request #2265 from OneUptime/compare-pages-seo-improvement
Improve compare page SEO: add 'open-source alternative' positioning
2026-02-03 15:20:18 +00:00
Jamie Mallers
3c3ecfc698 Enhance compare pages: stronger positioning and CTAs
- Badge: 'Open Source Alternative' with GitHub link (reinforces positioning)
- H1: 'The Open-Source [Competitor] Alternative' (SEO + clear value prop)
- CTA: 'Start free — no credit card' (removes friction)
- Added trust signal: 'Self-host for free or use our cloud. No vendor lock-in.'

These changes make the compare pages more conversion-focused.
2026-02-03 15:16:51 +00:00
Jamie Mallers
c22f7fec46 Improve compare page SEO: add 'open-source alternative' positioning
- Title: 'OneUptime vs [Competitor]: Open-Source Alternative | 2026 Comparison'
- Meta: Highlights open-source, alternative positioning, and all-in-one value prop
- Targets high-intent search terms: '[competitor] alternative', 'open source [competitor]'

Affects all /compare/* pages (Datadog, PagerDuty, New Relic, Statuspage, etc.)
2026-02-03 15:12:45 +00:00
Simon Larsen
75d473f6d7 Merge pull request #2264 from OneUptime/homepage-messaging-update
Update homepage messaging: lead with open-source positioning
2026-02-03 15:04:40 +00:00
Jamie Mallers
5d8f8e248e Update homepage messaging: lead with open-source positioning
- Title: 'OneUptime | The Open-Source Observability Platform'
- Meta: Focus on unified platform, self-hostable
- H1: 'The Open-Source Observability Platform'
- Sub: Emphasize complete reliability stack (monitoring, incidents, status pages, APM)

Part of GTM refresh to improve SEO and conversion.
2026-02-03 14:54:29 +00:00
Simon Larsen
a7c3ea274f Merge pull request #2263 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-02-03 08:13:39 +00:00
simlarsen
da324f49d9 chore: npm audit fix 2026-02-03 02:29:12 +00:00
Nawaz Dhandala
6fd9223ee9 refactor: Improve code formatting for better readability in UserSettings components 2026-02-02 19:36:32 +00:00
Nawaz Dhandala
c062d651e8 chore: Bump version number to 9.5.2 2026-02-02 19:35:12 +00:00
Nawaz Dhandala
1c264ac5a1 feat: Enhance User Settings with Incident On-Call Rules and related components 2026-02-02 19:31:58 +00:00
Nawaz Dhandala
8923a4bff6 feat: Format MicrosoftTeamsIntegration component for improved readability 2026-02-02 18:29:57 +00:00
Nawaz Dhandala
ab4e0cf85f chore: Bump version number to 9.5.1 2026-02-02 18:29:48 +00:00
Nawaz Dhandala
8f63e93eba feat: Replace ComingSoon component with MicrosoftTeamsIntegration for immediate functionality 2026-02-02 18:26:52 +00:00
Nawaz Dhandala
c06697f299 chore: Clean up whitespace in migration file for better readability 2026-02-02 18:21:51 +00:00
Nawaz Dhandala
2590a8d671 feat: Refactor DashboardSideMenu to use sections for better organization and readability 2026-02-02 18:20:55 +00:00
Nawaz Dhandala
e4eadc297b feat: Update Dashboard SideMenu to rename "Overview" to "Monitors" and conditionally add "Monitor Groups" section 2026-02-02 18:05:45 +00:00
Nawaz Dhandala
d0bf351dc1 feat: Add monitorId column and constraints to log tables in migration 2026-02-02 17:56:22 +00:00
Nawaz Dhandala
3234cc7d09 feat: Add migration for monitorId integration and schema updates across log tables 2026-02-02 17:46:50 +00:00
Nawaz Dhandala
0158271e6a feat: Add monitorId support across notification services and logs, and implement Notification Logs page 2026-02-02 17:44:25 +00:00
Nawaz Dhandala
9d50bf2535 chore: Bump version to 9.5.0 2026-02-01 16:19:28 +00:00
Nawaz Dhandala
c8ca2eacc5 fix: Improve descriptions for note reminder intervals and templates in IncidentSlaRule 2026-02-01 16:18:42 +00:00
Nawaz Dhandala
66699901a7 refactor: Simplify function signatures and improve code readability in Sla.tsx 2026-02-01 16:13:20 +00:00
Nawaz Dhandala
68a33eee2f feat: Enhance SLA management by integrating incident state timeline for accurate response and resolution tracking 2026-02-01 16:04:50 +00:00
Nawaz Dhandala
016793d77d feat: Implement SLA rule management with add and remove functionality in IncidentViewSla 2026-02-01 16:00:52 +00:00
Nawaz Dhandala
7b040b659d fix: Update SlaCard to consider incident resolution status for completion state 2026-02-01 15:56:54 +00:00
Nawaz Dhandala
c6db71f383 fix: Convert modelId and projectId to strings for stable dependency references in IncidentViewSla 2026-02-01 15:50:07 +00:00
Nawaz Dhandala
16923c750b feat: Add canReadOnRelationQuery property to IncidentSlaRule model and enhance SLA timers with real-time updates 2026-02-01 15:49:07 +00:00
Nawaz Dhandala
f57173f43c fix: Update sorting field in SLA tracking to use 'slaStartedAt' instead of 'createdAt' 2026-02-01 15:42:45 +00:00
Nawaz Dhandala
9716d138ea refactor: Update fetchStates function type annotation and simplify error handling in EpisodeAlerts and EpisodeIncidents components 2026-02-01 15:34:18 +00:00
Nawaz Dhandala
8e1b6859f5 feat: Add support for incident episode notification rule type and update default title generation to use 'Untitled Episode' 2026-02-01 15:28:38 +00:00
Nawaz Dhandala
9751dd0d5f refactor: Update episode title generation to remove prefix and use 'Untitled Episode' as default 2026-02-01 15:21:47 +00:00
Nawaz Dhandala
e84bd95f49 feat: Add canReadOnRelationQuery property to Alert and Incident models 2026-02-01 14:10:13 +00:00
Nawaz Dhandala
02b76539ab feat: Fetch and display alert and incident states in episode views 2026-02-01 14:07:46 +00:00
Nawaz Dhandala
c40c33773b feat: Add action buttons and current state display for alerts and incidents in episode views 2026-02-01 13:55:49 +00:00
Nawaz Dhandala
b0cebf9338 refactor: Improve code structure and readability in role assignment components 2026-02-01 13:47:39 +00:00
Nawaz Dhandala
674e35dc70 refactor: Improve code readability by formatting and simplifying filter/map functions in various components 2026-02-01 13:44:07 +00:00
Nawaz Dhandala
d5f42141a0 feat: Enhance Episode Member Role Assignments with user selection and role management 2026-02-01 13:41:54 +00:00
Nawaz Dhandala
8fb6da7d41 feat: Add Episode Member Role Assignments form field for incident grouping rules 2026-02-01 13:39:41 +00:00
Nawaz Dhandala
d14e77ee7f feat: Implement role assignment functionality for incident episodes with UI components 2026-02-01 13:29:31 +00:00
Nawaz Dhandala
71e8a70717 feat: Add IncidentEpisodeRoleMember service and model to BaseAPI feature set 2026-02-01 13:20:21 +00:00
Nawaz Dhandala
370bdc6e21 feat: Refactor MonitorCriteria components to use dedicated UI elements for teams, users, and labels 2026-02-01 13:09:07 +00:00
Nawaz Dhandala
d2a5d037c1 feat: Add support for labels, teams, users, and incident roles in monitor criteria components 2026-02-01 13:02:53 +00:00
Nawaz Dhandala
1ffa87d322 feat: Update title of My On-Call Policies card to reflect active assignments 2026-02-01 12:48:45 +00:00
Nawaz Dhandala
28ffde7983 feat: Enhance My On-Call Policies page with project details and improved UI components 2026-02-01 12:48:17 +00:00
Nawaz Dhandala
4655e207a5 feat: Add My On-Call Policies page and integrate routing 2026-02-01 12:44:00 +00:00
Nawaz Dhandala
62a5b216a0 feat: Update collapsible section titles for clarity in Monitor Criteria forms 2026-02-01 12:33:15 +00:00
Nawaz Dhandala
79fb9d18ca feat: Conditionally render Test Monitor Card based on monitor type 2026-02-01 12:28:23 +00:00
Nawaz Dhandala
ba5e8fdaeb feat: Simplify Monitor Criteria section by removing conditional rendering 2026-02-01 12:26:50 +00:00
Nawaz Dhandala
aa31bbab45 feat: Refactor Ownership & Labels section in MonitorCriteriaIncidentForm with improved dropdown handling 2026-02-01 12:22:27 +00:00
Nawaz Dhandala
3c84365d61 feat: Add reassign functionality for member roles with modal confirmation 2026-02-01 12:13:57 +00:00
Nawaz Dhandala
ae59bd8300 feat: Enhance incident member assignment logic to include primary role assignments for creators 2026-02-01 12:08:34 +00:00
Nawaz Dhandala
b868206e82 feat: Improve user assignment flow with enhanced dropdown handling and feedback 2026-02-01 12:05:23 +00:00
Nawaz Dhandala
ddbf971f1f feat: Reorder Owners item in SideMenu for improved accessibility 2026-02-01 12:01:35 +00:00
Nawaz Dhandala
483578ba4d refactor: Remove unused owner teams and users fields from incident creation 2026-02-01 12:00:41 +00:00
Nawaz Dhandala
614cb4413e feat: Enhance user assignment button with disabled state and tooltip for clarity 2026-02-01 11:57:47 +00:00
Nawaz Dhandala
ad43fc2df2 fix: Adjust icon size in MemberRoleAssignment component for better visibility 2026-02-01 11:54:44 +00:00
Nawaz Dhandala
aa2a6deb9e feat: Refactor role assignments to use useRef for better performance and update role assignment handling in IncidentCreate 2026-02-01 11:51:28 +00:00
Nawaz Dhandala
dcb13bb401 feat: Add showEvenIfPermissionDoesNotExist option to incident roles assignment 2026-02-01 11:40:00 +00:00
Nawaz Dhandala
5260364e91 fix lint 2026-01-30 20:38:36 +00:00
Nawaz Dhandala
1938e620bb feat: Update role assignment label to clarify multiple user assignment for incident roles 2026-01-30 20:32:27 +00:00
Nawaz Dhandala
c3fd71dcd4 feat: Enhance incident role assignment functionality with new IncidentRoleFormField component and support for multiple user assignments 2026-01-30 20:24:34 +00:00
Nawaz Dhandala
aba191c533 feat: Implement validation for primary roles to restrict multiple user assignments and update IncidentRoles component to include toggle for multiple user assignment 2026-01-30 20:09:31 +00:00
Nawaz Dhandala
847c019aea feat: Add canAssignMultipleUsers field to IncidentRole and update related components for multi-user assignment 2026-01-30 19:55:13 +00:00
Nawaz Dhandala
edf05944c1 feat: Add roleIcon to MemberRole and IncidentMemberRoleAssignment for enhanced role representation 2026-01-30 19:48:13 +00:00
Nawaz Dhandala
5293876943 feat: Update MemberRoleAssignment to allow single member assignment per role and improve user dropdown options 2026-01-30 19:42:51 +00:00
Nawaz Dhandala
ca7a702c13 feat: Add createdAt field to user selection in IncidentMemberRoleAssignment 2026-01-30 19:37:42 +00:00
Nawaz Dhandala
4020b4b647 feat: Update SideMenu section titles for clarity and consistency 2026-01-30 19:34:44 +00:00
Nawaz Dhandala
650849f4ad feat: Rename Members page to Roles and implement role assignment component 2026-01-30 19:09:06 +00:00
Nawaz Dhandala
9098261ac0 feat: Enhance user role assignment logic by validating role assignments and filtering available users by role 2026-01-30 19:07:28 +00:00
Nawaz Dhandala
70c6abbb86 feat: Add alert and incident episode counts with real-time updates in DashboardHeader 2026-01-30 14:15:52 +00:00
Nawaz Dhandala
23bc5531f0 feat: Add Incident SLA and Incident SLA Rule services and models to BaseAPI 2026-01-30 14:07:55 +00:00
Nawaz Dhandala
20404458e2 refactor: Remove dynamic imports of IncidentService and IncidentSlaService for improved performance 2026-01-30 14:00:44 +00:00
Nawaz Dhandala
31d3ce949d Refactor and clean up code across multiple files
- Added missing commas in migration index.
- Improved type annotations for dynamic imports in IncidentService and IncidentSlaRuleService.
- Simplified logger debug messages in IncidentSlaService and IncidentSlaRuleService.
- Cleaned up JSX formatting in IconPicker, NotificationBellDropdown, RoleLabel, and Header components.
- Enhanced readability by restructuring long lines and removing unnecessary line breaks in various components.
- Updated error handling in fetch functions within DashboardHeader to use concise catch blocks.
- Refactored UserSettings and Incident routes for better readability.
- Improved code consistency and formatting in CheckSlaBreaches job.
2026-01-30 13:50:50 +00:00
Nawaz Dhandala
61ed224ad0 feat: Add Incident SLA and related tables with migration 2026-01-30 13:39:46 +00:00
Nawaz Dhandala
71ea76ee62 feat: Implement Incident SLA Management System
- Added IncidentSlaStatus enum to define SLA status values.
- Created IncidentSlaRulesPage component for managing SLA rules, including documentation and configuration options.
- Developed IncidentViewSla component to display SLA status and deadlines for incidents.
- Implemented CheckSlaBreaches job to monitor SLA breaches and send notifications.
- Created SendNoteReminders job to automate internal and public note reminders based on SLA rules.
2026-01-30 13:03:48 +00:00
Nawaz Dhandala
7a4a0553ca fix: Update fetchData dependencies to use string representations of incidentId and projectId 2026-01-30 12:26:22 +00:00
Nawaz Dhandala
cb57fa4a07 feat: Add new icon types (Compass, Disc, Grid) to Icon component 2026-01-30 12:20:47 +00:00
Nawaz Dhandala
22bc222689 feat: Refactor IconPicker and RoleLabel components for improved icon handling and styling 2026-01-30 12:12:21 +00:00
Nawaz Dhandala
9d96170c42 feat: Add migration for roleIcon column in IncidentRole and update OnCallDutyPolicyScheduleLayer defaults 2026-01-30 12:03:01 +00:00
Nawaz Dhandala
d0f4d21177 feat: Change roleIcon type from string to IconProp in IncidentRole model 2026-01-30 11:59:18 +00:00
Nawaz Dhandala
e9a2167484 feat: Rename icon to roleIcon in IncidentRole model and update references in IncidentRoles and CustomFields components 2026-01-30 11:59:03 +00:00
Nawaz Dhandala
a8af991a80 feat: Add IconPicker component and integrate icon selection in IncidentRoles 2026-01-30 11:52:21 +00:00
Nawaz Dhandala
8bb3a5b7ac feat: Replace Pill with RoleLabel component in IncidentRoles for enhanced role display 2026-01-30 11:45:22 +00:00
Nawaz Dhandala
d0b1efb660 feat: Add isEditable prop to CustomFieldsDetail and set it in UserView 2026-01-30 11:34:24 +00:00
Nawaz Dhandala
4f3259c3b1 feat: Enhance user profile creation with HTTP response handling and validation 2026-01-30 11:31:42 +00:00
Nawaz Dhandala
30b53a90a4 feat: Reorder profile section in SideMenu for improved organization 2026-01-30 11:31:00 +00:00
Nawaz Dhandala
cf8377ceec feat: Add custom fields management for team members and user profiles
- Introduced new models: ProjectUserProfile and TeamMemberCustomField to manage custom fields for users in projects.
- Implemented services for ProjectUserProfile and TeamMemberCustomField for database interactions.
- Created UI components for managing team member custom fields and user-specific custom fields in settings.
- Updated routing to include new pages for custom fields management.
- Added necessary database migrations for new tables and relationships.
- Enhanced side menu in user settings to navigate to custom fields.
2026-01-30 11:28:00 +00:00
Nawaz Dhandala
ffc7dbc35f feat: Update user notification event type for incident episode creation 2026-01-30 11:01:23 +00:00
Nawaz Dhandala
97fd817db4 feat: Enhance change plan API with payment method validation and error handling 2026-01-30 10:50:19 +00:00
Nawaz Dhandala
aa7caaa193 feat: Add validation for payment provider customer and methods before changing plan 2026-01-30 10:48:08 +00:00
Nawaz Dhandala
a05853ea09 feat: Move NotificationBell component to the right section for improved visibility 2026-01-30 10:45:26 +00:00
Nawaz Dhandala
2ba96c093d feat: Update NotificationBell to improve badge count logic and display based on alert types 2026-01-30 10:43:56 +00:00
Nawaz Dhandala
ed3df77ca4 feat: Refactor NotificationBell and related components for improved alert handling and UI consistency 2026-01-30 10:39:35 +00:00
Nawaz Dhandala
9ec363d222 feat: Implement notification system with NotificationBell and related components 2026-01-30 10:29:33 +00:00
Nawaz Dhandala
a090ec2747 feat: Enhance migration and service files for incident roles and alert grouping
- Updated migration file to include new tables and constraints for incident roles and grouping rules.
- Refactored alert grouping engine service for improved readability.
- Adjusted incident episode role member service for better error logging and code clarity.
- Modified data migration to streamline imports and enhance maintainability.
2026-01-29 22:09:38 +00:00
Nawaz Dhandala
9fde4fece9 feat: Add migration for IncidentEpisodeRoleMember and related grouping rules 2026-01-29 22:03:40 +00:00
Nawaz Dhandala
596798801a feat: Add episode configuration fields and role assignments to incident and alert grouping rules 2026-01-29 21:59:13 +00:00
Nawaz Dhandala
dcc87c46b2 feat: Implement Incident Episode Role Member functionality and UI components 2026-01-29 21:51:49 +00:00
Nawaz Dhandala
33fdabaea3 feat: Add migration to assign default incident roles to existing projects 2026-01-29 21:41:30 +00:00
Nawaz Dhandala
35deea863b feat: Refactor incident member role assignment and improve code readability across components 2026-01-29 21:39:29 +00:00
Nawaz Dhandala
2b2bbbdd55 feat: Add incident member role assignment functionality to MonitorIncident and related components 2026-01-29 21:38:41 +00:00
Nawaz Dhandala
d8cd92c504 feat: Update title and description in ListByTag.ejs for improved SEO 2026-01-29 21:38:17 +00:00
Nawaz Dhandala
f6ef2fa97d feat: Add IncidentMemberRoleAssignment component for managing team member roles in incidents 2026-01-29 21:25:03 +00:00
Nawaz Dhandala
8a86f6a94f feat: Implement auto-assignment of Incident Commander during state changes 2026-01-29 21:14:33 +00:00
Nawaz Dhandala
4b30274915 feat: Add incident member notification system with email and WhatsApp templates 2026-01-29 21:09:44 +00:00
Nawaz Dhandala
01f7d7cc78 feat: Refactor routing and add ActiveIncidents and ActiveAlerts components 2026-01-29 20:59:58 +00:00
Nawaz Dhandala
616e64110a feat: Add MigrationName1769719826928 to implement isPrimaryRole and isDeleteable fields in IncidentRole 2026-01-29 20:51:00 +00:00
Nawaz Dhandala
903a72a4e1 feat: Add isPrimaryRole and isDeleteable fields to IncidentRole model and update related service logic 2026-01-29 20:50:17 +00:00
Nawaz Dhandala
699c1d4341 feat: Update MigrationName1769719135546 to include down method and fix formatting 2026-01-29 20:42:13 +00:00
Nawaz Dhandala
078a4e8180 Merge branch 'incident-roles' 2026-01-29 20:39:52 +00:00
Nawaz Dhandala
29232e7052 feat: Add new migration MigrationName1769719135546 to schema migrations 2026-01-29 20:39:29 +00:00
Nawaz Dhandala
a221f7247c feat: Remove startsAt and endsAt fields from IncidentMember model and update related migration 2026-01-29 20:39:12 +00:00
Simon Larsen
c4b5aca463 Merge pull request #2259 from OneUptime/incident-roles
feat: Add Incident Member and Role Management
2026-01-29 20:32:09 +00:00
Nawaz Dhandala
9de4be6661 chore: Remove unnecessary blank lines in SettingsRoutes component 2026-01-29 20:31:57 +00:00
Simon Larsen
a532dcdd5f Merge pull request #2260 from digitalsparky/patch-1
Fix installation command to ensure it can follow the redirect
2026-01-29 20:20:35 +00:00
Simon Larsen
bde09d2326 Merge pull request #2261 from digitalsparky/patch-2
Modify clone instructions for release branch
2026-01-29 20:19:40 +00:00
Matt Spurrier
b36ac68026 Modify clone instructions for release branch
Updated the instructions to clone the repository with only the release branch.

This will save significant bandwidth and disk space by cloning only the release branch as it exists now, rather than the entire repository with its full history.
2026-01-30 04:02:16 +08:00
Matt Spurrier
200a94692e Fix installation command to ensure it can follow the redirect
The install.The URL is a redirect, for curl to follow it, you must use the -L option, otherwise you get an error.

EG:

root@inf1:~# curl https://oneuptime.com/install.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   107  100   107    0     0    242      0 --:--:-- --:--:-- --:--:--   243
bash: line 1: Found.: command not found
2026-01-30 03:42:58 +08:00
Nawaz Dhandala
3afc3a3302 feat: Add IncidentRole and IncidentMember APIs to BaseAPIFeatureSet 2026-01-29 19:16:23 +00:00
Nawaz Dhandala
fa52c30462 feat: Add Incident Roles page and update routing in incidents and settings 2026-01-29 19:09:19 +00:00
Nawaz Dhandala
c229936d5c Refactor permission arrays in database models to improve formatting consistency
- Updated permission arrays in various database model files to ensure consistent formatting by aligning closing brackets.
- Adjusted the `onBeforeCreate` function in the IncidentMembers component for improved readability.
- Cleaned up descriptions in the Permission helper class for better clarity.
- Added a new migration for IncidentRole and IncidentMember tables with appropriate constraints and indexes.
2026-01-29 18:58:05 +00:00
Nawaz Dhandala
70b2fb8c16 feat: Add IncidentRole and IncidentMember migration with constraints and indexes 2026-01-29 18:54:51 +00:00
Nawaz Dhandala
264613c676 feat: Rename On-Call Users to Members and update related routes and components 2026-01-29 16:52:50 +00:00
Nawaz Dhandala
61209f967f refactor: Remove order field from IncidentRole model and related services 2026-01-29 16:50:59 +00:00
Nawaz Dhandala
f82de89f3f feat: Add Incident Member and Role Management
- Introduced IncidentMember model to manage users assigned to incidents with specific roles.
- Created IncidentRole model to define roles that can be assigned during incident response.
- Implemented IncidentMemberService for CRUD operations on incident members.
- Implemented IncidentRoleService for CRUD operations on incident roles with order management.
- Added OnCallUsers page to display and manage users assigned to incidents.
- Added IncidentRoles settings page to define and manage incident roles.
- Updated RouteMap to include new routes for on-call users and incident roles.
2026-01-29 16:33:52 +00:00
Nawaz Dhandala
b94a095bef feat: add ReadAllProjectResources permission to various models
- Updated TelemetryIngestionKey, TelemetryUsageBilling, User, WhatsAppLog, Workflow, WorkflowLog, WorkflowVariable, WorkspaceNotificationLog, WorkspaceNotificationRule, WorkspaceProjectAuthToken models to include the new ReadAllProjectResources permission in access control settings.
- Introduced ReadAllProjectResources permission in Permission.ts with a description outlining its purpose and scope.
2026-01-29 15:03:22 +00:00
Simon Larsen
c08de3da35 Merge pull request #2258 from OneUptime/monitor-ui
feat: Add support for labels and ownership in Monitor Alert and Incid…
2026-01-29 14:09:25 +00:00
Nawaz Dhandala
748e18fd1b fix: Correct type annotation for updateField function in MonitorCriteriaAlertForm and MonitorCriteriaIncidentForm 2026-01-29 14:09:08 +00:00
Nawaz Dhandala
c0d7c34018 refactor: Improve code readability by formatting multiline expressions and consistent function signatures in Monitor components 2026-01-29 14:04:42 +00:00
Nawaz Dhandala
e249ee6e59 feat: Add support for labels and ownership in Monitor Alert and Incident forms
- Updated MonitorAlert and MonitorIncident classes to handle labels and owner teams/users.
- Enhanced CriteriaAlert and CriteriaIncident types to include labelIds, ownerTeamIds, and ownerUserIds.
- Modified MonitorCriteriaAlertForm and MonitorCriteriaIncidentForm components to support new fields for labels and ownership.
- Integrated dropdown options for labels, teams, and users in MonitorSteps and related components.
- Implemented fetching of labels, teams, and users in MonitorSteps for dynamic dropdowns.
2026-01-29 14:02:55 +00:00
Simon Larsen
9eca0153ce Merge pull request #2257 from OneUptime/monitor-ui
feat: Refactor MonitorStep component to use CollapsibleSection for ad…
2026-01-29 13:34:13 +00:00
Nawaz Dhandala
c4deb0d0b4 feat: Refactor MonitorStep component to use CollapsibleSection for advanced options and improve UI structure
- Introduced CollapsibleSection component for better organization of advanced options in MonitorStep.
- Replaced existing div structures with Card components for improved visual hierarchy.
- Enhanced user experience by adding collapsible sections for API and Website monitor advanced settings.
- Cleaned up code by removing unnecessary comments and consolidating error handling logic.
2026-01-29 13:28:33 +00:00
Simon Larsen
7ecd86eca7 Merge pull request #2256 from elmy-team/fix-missing-redis-existing-secret
Fix missing Redis & ClickHouse existing secrets
2026-01-29 12:09:37 +00:00
Matías Plaza
f3312a2417 fix(helm-chart): add missing existing secret condition for clickhouse 2026-01-29 10:52:33 +01:00
Nawaz Dhandala
e0558a4a0a chore: Bump version to 9.4.13 2026-01-29 09:07:31 +00:00
Nawaz Dhandala
e2a238e3e3 refactor: Simplify imports and improve type annotations in IncidentEpisode services 2026-01-29 09:06:32 +00:00
Nawaz Dhandala
543c62df5a feat: Implement AI-generated postmortem functionality for IncidentEpisode 2026-01-29 09:05:42 +00:00
Matías Plaza
382c838d40 fix(helm-chart): add missing existing secret condition for redis 2026-01-29 10:04:31 +01:00
Nawaz Dhandala
1a88832efc feat: Enhance EpisodePostmortem component with template functionality 2026-01-29 09:01:07 +00:00
Nawaz Dhandala
d1f97a3193 feat: Add canReadOnRelationQuery property to Incident model 2026-01-29 08:58:18 +00:00
Nawaz Dhandala
70a269b662 fix: Update icons in DashboardSideMenu for better clarity 2026-01-29 08:56:23 +00:00
Nawaz Dhandala
a4ae42fd08 feat: Add create episode button to IncidentEpisodesTable component 2026-01-29 08:54:05 +00:00
Simon Larsen
6c0161543a Merge pull request #2255 from OneUptime/snmp-monitor
Snmp monitor
2026-01-29 08:45:54 +00:00
Nawaz Dhandala
4519292cc8 feat: Add migration to rename 'eveluateOverTime' to 'evaluateOverTime' in Monitor table 2026-01-29 08:42:34 +00:00
Nawaz Dhandala
83993fc2a4 fix: Correct spelling of 'evaluateOverTime' in multiple criteria files 2026-01-29 08:38:35 +00:00
Simon Larsen
5340b04b26 Merge pull request #2253 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-01-29 08:28:58 +00:00
Nawaz Dhandala
2a6003e78f refactor: Add type annotations for functions in SnmpOidEditor and SnmpMonitor 2026-01-29 08:28:23 +00:00
Nawaz Dhandala
bfed03a10e refactor: Improve code formatting and readability in SNMP monitor components 2026-01-29 08:24:51 +00:00
Nawaz Dhandala
d99b20327f feat: Update SNMP monitor implementation and add net-snmp dependency 2026-01-29 08:22:04 +00:00
Nawaz Dhandala
3a317a8b55 feat: Enhance E2E test execution with retry mechanism 2026-01-29 08:09:32 +00:00
Nawaz Dhandala
0c64ba30b0 fix: Correct URL construction in generateBlogSitemapXml function 2026-01-29 08:08:40 +00:00
simlarsen
4400a7e5dd chore: npm audit fix 2026-01-29 02:15:00 +00:00
Nawaz Dhandala
45aab853c4 feat: Add SNMP monitor documentation with configuration and usage details 2026-01-28 23:26:10 +00:00
Nawaz Dhandala
b37c13d347 feat: Enhance monitor destination handling for SNMP monitors 2026-01-28 23:21:32 +00:00
Nawaz Dhandala
d13407494b feat: Implement SNMP monitor support with criteria and view components 2026-01-28 23:06:13 +00:00
Nawaz Dhandala
724ab97874 feat: Add SNMP Monitor functionality with v3 authentication support
- Introduced MonitorStepSnmpMonitor interface for SNMP configuration.
- Implemented SNMP version handling with enums for V1, V2c, and V3.
- Created utility classes for handling SNMP OIDs and v3 authentication parameters.
- Developed SNMP Monitor response structure to capture OID responses and status.
- Added UI components for SNMP Monitor configuration including OID editor and v3 auth form.
- Implemented SNMP query logic with retry mechanism and response time tracking.
- Added type definitions for net-snmp library to support SNMP operations.
2026-01-28 22:56:28 +00:00
Nawaz Dhandala
15e2fdcf48 feat: add IncidentGroupingRule service and router integration 2026-01-28 21:10:37 +00:00
Simon Larsen
3a546f9b5a Merge pull request #2254 from OneUptime/incident-episodes
feat: Add Incident Episode Management Pages and Components
2026-01-28 20:32:17 +00:00
Nawaz Dhandala
291a0f12f1 feat: Enhance Incident Grouping Rules Migration and UI Components
- Updated the migration script for IncidentGroupingRule to improve structure and readability.
- Added new foreign key constraints and indexes to enhance database integrity.
- Refactored DeleteAccount component to improve layout and readability.
- Improved placeholder text formatting in IncidentGroupingRules page for better clarity.
- Added ProjectService import in BillingService to resolve circular dependency.
- Refactored condition checks in IncidentGroupingEngineService for better readability.
2026-01-28 20:27:23 +00:00
Nawaz Dhandala
3d62b67bca feat: add IncidentGroupingRule migration with related tables and constraints 2026-01-28 19:55:03 +00:00
Nawaz Dhandala
4c31c2b651 feat: add incidentEpisodeId to multiple service classes 2026-01-28 19:42:44 +00:00
Nawaz Dhandala
acdcb2d5da feat: add IncidentGroupingRuleService and IncidentGroupingRules page
- Implemented IncidentGroupingRuleService to manage incident grouping rules with automatic deletion of old records if billing is enabled.
- Created IncidentGroupingRules page for managing incident grouping rules, including detailed documentation on grouping logic, match criteria, and configuration options.
- Added UI components for creating, editing, and displaying incident grouping rules with various filtering and grouping options.
2026-01-28 19:31:13 +00:00
Nawaz Dhandala
43084263ab feat: Add tabs for Incident and Incident Episodes in Microsoft Teams and Slack pages 2026-01-28 19:10:10 +00:00
Nawaz Dhandala
1bbc953462 Refactor and clean up code across multiple services and components
- Added missing commas in migration index.
- Removed unused imports in IncidentEpisodeService and UserNotificationRuleService.
- Simplified conditional statements and improved code readability in various services.
- Adjusted formatting for better consistency in code style.
- Enhanced error handling and logging in MicrosoftTeamsIncidentEpisodeActions.
- Updated documentation text in IncidentEpisodeDocs for clarity.
- Improved API call structure in IncidentEpisodesTable and IncidentEpisodeFeed.
- Refactored SlackIncidentEpisodeActions for better readability.
- Cleaned up unnecessary code and improved formatting in various components.
2026-01-28 18:49:22 +00:00
Nawaz Dhandala
7cef3956e8 feat: Add IncidentEpisode migration with related tables and constraints 2026-01-28 18:48:36 +00:00
Nawaz Dhandala
4904a535d1 feat: Add Active Incident Episodes page and integrate with SideMenu 2026-01-28 18:47:26 +00:00
Nawaz Dhandala
5db511036e feat: Add notification handling for Incident Episodes and enhance Push Notification utility 2026-01-28 18:40:39 +00:00
Nawaz Dhandala
8b9023d93d feat: Add incident episode auto-resolution and notification jobs
- Implemented AutoResolve job to automatically resolve inactive incident episodes.
- Created ResolveInactiveEpisodes job to resolve episodes inactive for over 24 hours.
- Added SendCreatedResourceNotification job to notify owners of newly created incident episodes.
- Developed SendNotePostedNotification job to inform owners when a note is posted on an incident episode.
- Introduced SendOwnerAddedNotification job to notify users when they are added as owners of an incident episode.
- Implemented SendStateChangeNotification job to alert owners of state changes in incident episodes.
2026-01-28 18:30:45 +00:00
Nawaz Dhandala
0546d1fb12 feat: Enhance User Notification and OnCall Duty Policy services to support Incident Episode handling 2026-01-28 18:13:09 +00:00
Nawaz Dhandala
d523ae822d feat: Implement Incident Episode services, routes, and notification templates 2026-01-28 18:07:36 +00:00
Nawaz Dhandala
9fd781c083 feat: Add Slack and Workspace message handling for Incident Episodes
- Implemented SlackIncidentEpisodeMessages class to create message blocks for incident episodes in Slack.
- Added IncidentEpisodeWorkspaceMessages class to handle workspace notifications and message blocks for incident episodes.
- Created IncidentEpisodeDocs component to provide a comprehensive guide on incident grouping, including lifecycle, setup steps, and best practices.
2026-01-28 18:00:10 +00:00
Nawaz Dhandala
8d743dbb59 feat: Add Incident Episode creation functionality and related routes 2026-01-28 17:19:15 +00:00
Nawaz Dhandala
5b3e97c10d feat: Add Incident Episode Management Pages and Components
- Implemented Episode Internal Note component for managing private notes related to incident episodes.
- Created Layout component for the Incident Episode view, integrating side menu and breadcrumb navigation.
- Developed Owners component to manage teams and users associated with incident episodes.
- Added Postmortem component for documenting postmortem analyses of incidents.
- Introduced Remediation component for capturing remediation notes for incidents.
- Created Root Cause component to document the root causes of incidents.
- Developed SideMenu for navigating through various sections of the Incident Episode view.
- Implemented State Timeline component to track the status changes of incident episodes.
- Added Episodes and Unresolved Episodes pages for listing all incident episodes and unresolved ones respectively.
2026-01-28 17:10:08 +00:00
Nawaz Dhandala
252a81c9ae chore: bump version to 9.4.12 2026-01-28 15:50:27 +00:00
Nawaz Dhandala
e6b414a94b feat: enhance project fetching in NewAlerts and NewIncidents components with ListResult type 2026-01-28 15:50:15 +00:00
Nawaz Dhandala
f521091f8e feat: update project filter to use projectId and change filter type to EntityArray in NewAlerts and NewIncidents components 2026-01-28 15:46:08 +00:00
Nawaz Dhandala
19e112a8a8 feat: add project filter functionality to NewAlerts and NewIncidents components 2026-01-28 15:33:35 +00:00
Nawaz Dhandala
84dd084dae feat: add saveFilterProps to NewAlerts and NewIncidents components for improved table filtering 2026-01-28 13:08:56 +00:00
Nawaz Dhandala
439c1f8716 style: format code for improved readability in EpisodeCreate component 2026-01-28 12:59:00 +00:00
Nawaz Dhandala
647b713375 feat: add episode creation functionality with form and routing 2026-01-28 12:58:16 +00:00
Nawaz Dhandala
a2e6b7a4fc feat: add Stripe type definitions and improve type safety in Billing and Project services 2026-01-28 12:09:41 +00:00
Nawaz Dhandala
b06bc71a2c refactor: improve logging and code formatting in billing and project services 2026-01-28 12:08:01 +00:00
Nawaz Dhandala
367a80c413 fix: remove unused status field from invoice template and billing service 2026-01-28 12:05:03 +00:00
Nawaz Dhandala
f49e4bd5d0 feat: implement invoice email notification system with template and email handling 2026-01-28 12:01:28 +00:00
Nawaz Dhandala
a74a7e0a9a feat: enhance billing functionality with detailed logging for invoice email processes and Stripe synchronization 2026-01-28 11:52:34 +00:00
Nawaz Dhandala
f4946449f3 feat: add migration to introduce sendInvoicesByEmail column and update defaults for OnCallDutyPolicyScheduleLayer 2026-01-28 11:32:44 +00:00
Nawaz Dhandala
9640732e29 feat: implement Stripe webhook for automatic invoice email sending and add configuration for webhook secret 2026-01-28 11:26:22 +00:00
Nawaz Dhandala
6ef5e409da fix: replace Navigation with window.location for redirect after account deletion 2026-01-28 09:53:57 +00:00
Nawaz Dhandala
bcdfa034f6 feat: add user account deletion functionality with confirmation modal 2026-01-28 09:50:25 +00:00
Nawaz Dhandala
959267a174 feat: update NewAlerts and NewIncidents to use alertNumber and incidentNumber with appropriate types 2026-01-28 09:40:42 +00:00
Nawaz Dhandala
767db415d2 fix: conditionally include incidentNumber in notification payloads 2026-01-27 21:11:50 +00:00
Nawaz Dhandala
7ca81aa9f8 chore: bump version to 9.4.11 2026-01-27 20:42:20 +00:00
Nawaz Dhandala
26bd4c7a90 fix: improve readability of conditional check in Delete method 2026-01-27 20:42:00 +00:00
Nawaz Dhandala
9d29a1d00b Refactor Terraform tests to remove project_id references
- Removed project_id variable and its usage from multiple Terraform test files (23-probe-crud, 24-status-page-crud, 25-status-page-with-domain, 26-monitor-steps-basic, 27-monitor-types, 28-incident-crud, 29-alert-crud, 30-scheduled-maintenance-crud, 31-on-call-duty-policy-crud, 32-monitor-group-crud, 33-team-crud, 35-monitor-with-steps, 36-monitor-types-basic, 37-label-order-idempotency).
- Updated ResourceGenerator to treat project_id as computed-only, inferred from API key authentication.
- Adjusted related logic in resource update and delete operations to exclude project_id from requests.
2026-01-27 20:00:41 +00:00
Nawaz Dhandala
935608d23d fix: format condition for attribute import check in DataSourceGenerator 2026-01-27 18:30:58 +00:00
Nawaz Dhandala
4a3000d3c3 feat: add initial Netscape HTTP cookie file for E2E tests 2026-01-27 18:30:17 +00:00
Nawaz Dhandala
b5df7042f7 fix: correct variable name in label validation checks for idempotency test 2026-01-27 18:30:01 +00:00
Nawaz Dhandala
a345390b9b feat: add URL normalization helpers to avoid drift in resource handling 2026-01-27 18:16:28 +00:00
Nawaz Dhandala
d0a8c049ba feat: add support for 'set' type in data source and resource generation, enhancing collection handling 2026-01-27 18:04:51 +00:00
Nawaz Dhandala
56037adcf0 fix: update alert field to use alertId for episode alerts 2026-01-27 16:18:28 +00:00
Nawaz Dhandala
73e2fcf3c6 feat: implement Episode Alerts table with CRUD functionality and enhanced alert display 2026-01-27 16:13:55 +00:00
Nawaz Dhandala
710bdea813 refactor: remove unused alert feed entry creation logic and related parameters 2026-01-27 15:44:11 +00:00
Nawaz Dhandala
f07ba35310 feat: add RemovedFromEpisode event type and update alert feed creation logic 2026-01-27 15:39:43 +00:00
Nawaz Dhandala
9ef2163bc0 feat: add New Alerts page and integrate with routing 2026-01-27 14:32:38 +00:00
Nawaz Dhandala
1f53a56b8f chore: bump version to 9.4.10 2026-01-27 13:55:36 +00:00
Nawaz Dhandala
6998b63f59 feat: enhance alert data retrieval in notification service for improved accuracy 2026-01-27 13:55:21 +00:00
Nawaz Dhandala
dccddf3ebc refactor: define ResourceInfo type for improved type safety in resource info retrieval 2026-01-27 13:36:43 +00:00
Nawaz Dhandala
2a7d076407 chore: bump version to 9.4.9 2026-01-27 13:33:00 +00:00
Nawaz Dhandala
0e82b17f6b refactor: format code for better readability in notification handling 2026-01-27 13:30:37 +00:00
Nawaz Dhandala
0aa7838fc5 feat: include alert numbers in push notification titles and bodies for note and state change updates 2026-01-27 13:29:52 +00:00
Nawaz Dhandala
b1d243896f feat: update alert episode notification templates to include episode numbers 2026-01-27 13:26:42 +00:00
Nawaz Dhandala
ab70c2c041 Enhance notification templates and services to include alert and incident numbers
- Updated email templates for alerts and incidents to include alertNumber and incidentNumber in the subject and body.
- Modified PushNotificationUtil to incorporate alert and incident numbers in notification titles and messages.
- Adjusted UserNotificationRuleService to pass alertNumber and incidentNumber for notifications.
- Enhanced SendCreatedResourceNotification, SendNotePostedNotification, SendOwnerAddedNotification, and SendStateChangeNotification jobs to include alert and incident numbers in subjects and messages.
- Updated ScheduledMaintenance notification jobs to reflect scheduledMaintenanceNumber in relevant notifications.
2026-01-27 13:19:12 +00:00
Nawaz Dhandala
22b6c5ace0 feat: update email subject and template to include alert episode number 2026-01-27 13:04:04 +00:00
Nawaz Dhandala
ad32579214 feat: enhance alert episode email template with styled alerts list 2026-01-27 13:01:51 +00:00
Nawaz Dhandala
e525cc3708 feat: enhance UserNotificationRuleService to include alert episode members and build alerts list for notifications 2026-01-27 12:56:02 +00:00
Nawaz Dhandala
db7eaacd14 feat: enhance UserNotificationLogTimelineAPI to support Alert Episodes and improve notification handling 2026-01-27 12:52:03 +00:00
Nawaz Dhandala
a549daf9ab refactor: improve code readability by updating comments and formatting in migration and services 2026-01-27 12:45:28 +00:00
Nawaz Dhandala
d9e65ce633 feat: add migration to rename notification rule types in UserNotificationRule 2026-01-27 12:43:00 +00:00
Nawaz Dhandala
be2d33591d refactor: update notification rule types for incidents and alerts 2026-01-27 12:36:00 +00:00
Nawaz Dhandala
88897004a2 refactor: rename fetchSitemap to fetchSitemapXml and update tests for sitemap structure 2026-01-27 12:20:41 +00:00
Simon Larsen
dceccf00fa Merge pull request #2251 from elmy-team/support-existing-secret-clickhouse-redis
Support existing secrets for Redis & ClickHouse
2026-01-27 10:39:44 +00:00
Matías Plaza
f079a2b9e6 feat: support existing secrets for redis & clickhouse 2026-01-27 10:53:29 +01:00
Nawaz Dhandala
4044d705d6 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-01-27 08:44:35 +00:00
Nawaz Dhandala
a2cbe4e241 fix: update containerRef type to remove null from HTMLDivElement reference 2026-01-27 08:43:00 +00:00
Simon Larsen
b509b57bb8 Merge pull request #2250 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-01-27 08:38:44 +00:00
simlarsen
4a7f27a372 chore: npm audit fix 2026-01-27 02:04:49 +00:00
Nawaz Dhandala
214ac678d3 feat: add triggeredByAlertEpisodeId to on-call related tables and update UserOnCallLogService comments 2026-01-26 23:35:05 +00:00
Nawaz Dhandala
9dabce1b7a feat: add support for alert episode handling in user on-call logs and notifications 2026-01-26 23:34:30 +00:00
Nawaz Dhandala
9bc260847d feat: add migration for triggeredByAlertEpisodeId in on-call related tables 2026-01-26 23:24:27 +00:00
Nawaz Dhandala
229775935e style: improve code formatting and readability in various services 2026-01-26 23:22:27 +00:00
Nawaz Dhandala
668c35ba2e feat: add AcknowledgeAlertEpisode template and update related services for alert episode notifications 2026-01-26 23:21:50 +00:00
Nawaz Dhandala
a808913049 feat: add support for alert episode handling in user on-call logs and notifications 2026-01-26 23:06:20 +00:00
Nawaz Dhandala
54da185280 feat: enhance on-call duty policy execution to support alert episode handling 2026-01-26 22:45:49 +00:00
Nawaz Dhandala
b1bc7bfde4 fix: update canonical link generation in blog post view 2026-01-26 22:43:27 +00:00
Nawaz Dhandala
09d5ce0e1a feat: add support for triggeredByAlertEpisodeId in on-call duty policy execution and related services 2026-01-26 22:36:15 +00:00
Nawaz Dhandala
3935446071 feat: enhance on-call policy execution by adding policy names to feed entry 2026-01-26 22:28:52 +00:00
Nawaz Dhandala
2463dcb2db fix: update alert episode handling in ExecutionLogsTable; add support for triggeredByAlertEpisodeId 2026-01-26 22:26:17 +00:00
Nawaz Dhandala
0eb239a469 feat: implement on-call duty policy execution in episode creation process 2026-01-26 22:21:31 +00:00
Nawaz Dhandala
b865caae7a fix: update comment formatting in AlertEpisodeService for clarity 2026-01-26 22:16:32 +00:00
Nawaz Dhandala
a3e25723af fix: update sorting and resolve logic in AlertEpisodeService; improve clarity in auto-resolve comments 2026-01-26 22:15:14 +00:00
Nawaz Dhandala
bae0338c36 fix: encode tag slugs in AllTagsFilter and Tags partials for proper URL formatting 2026-01-26 22:07:39 +00:00
Nawaz Dhandala
f656f23836 fix: encode tag slugs in generateTagsSitemapXml for proper URL formatting 2026-01-26 22:06:24 +00:00
Nawaz Dhandala
a8a79162e4 fix: ensure consistent response handling in sitemap generation routes 2026-01-26 22:02:57 +00:00
Nawaz Dhandala
04556835b0 feat: add bulk delete action to Team and Users tables 2026-01-26 21:36:51 +00:00
Nawaz Dhandala
84c5e50199 chore: bump version to 9.4.8 2026-01-26 21:13:31 +00:00
Nawaz Dhandala
06fd44ecaf refactor: improve code formatting and consistency across multiple components 2026-01-26 21:12:47 +00:00
Nawaz Dhandala
c535b68056 feat(tests): update icon visibility checks in Input and TextArea tests 2026-01-26 21:03:03 +00:00
Nawaz Dhandala
34c8e4fdec feat(alert): update feed message icons for episode creation and addition 2026-01-26 20:50:39 +00:00
Nawaz Dhandala
bf04796637 feat(subscriber-notification-template): add connected status pages table for linking templates 2026-01-26 20:46:05 +00:00
Nawaz Dhandala
16e6c0c601 feat(alert): add event type for alert added to episode and create corresponding feed entries 2026-01-26 20:39:56 +00:00
Nawaz Dhandala
75a733e9b8 feat(scheduled-maintenance): implement bulk state change functionality for scheduled maintenance events 2026-01-26 20:33:38 +00:00
Nawaz Dhandala
30217a64ec feat(alert): enhance mutex handling in groupAlertWithRule to prevent race conditions 2026-01-26 20:23:28 +00:00
Nawaz Dhandala
488295e303 feat(alert): trigger sidebar badge count refresh on bulk actions 2026-01-26 20:12:55 +00:00
Nawaz Dhandala
973131b70a feat(alert): implement mutex for episode creation to prevent race conditions 2026-01-26 20:07:33 +00:00
Nawaz Dhandala
52cb00a1c4 feat(alert-episode): fetch current state order and name for alert episodes in bulk state change 2026-01-26 20:03:27 +00:00
Nawaz Dhandala
ab0027a042 feat(alert-episode): implement bulk state change functionality for alert episodes 2026-01-26 19:58:46 +00:00
Nawaz Dhandala
26a6d12809 refactor(alert): simplify episode retrieval by removing resolved state checks 2026-01-26 19:52:20 +00:00
Nawaz Dhandala
0bdf74cab2 feat(modal): exclude close button from focus trap in modal 2026-01-26 19:43:07 +00:00
Nawaz Dhandala
dd996539bc feat(alert): implement mutex for episode number generation to prevent race conditions 2026-01-26 19:40:57 +00:00
Nawaz Dhandala
ad2ee2b0d6 feat(alert): make cascadeStateToMemberAlerts public and integrate it into onCreateSuccess 2026-01-26 19:38:59 +00:00
Nawaz Dhandala
ed6630c2d6 feat(alert): update current alert state and handle resolvedAt transitions 2026-01-26 19:34:23 +00:00
Simon Larsen
3af9121d6a Merge pull request #2238 from OneUptime/alert-episode
Alert episode
2026-01-26 19:24:18 +00:00
Nawaz Dhandala
e9d5a560ff Refactor migration files and improve code formatting
- Updated migration files to enhance readability by adjusting indentation and line breaks.
- Added missing commas in the index file for migration imports.
- Improved accessibility attributes in various UI components by ensuring proper aria-labels and roles.
- Refactored key event handlers in UI components for better clarity and consistency.
- Enhanced error message handling in form components to ensure proper display and accessibility.
- Updated legacy function comments for clarity and maintainability.
2026-01-26 19:23:58 +00:00
Nawaz Dhandala
d87b6da7c5 fix(dependencies): update random provider version and adjust lock file handling 2026-01-26 19:19:23 +00:00
Nawaz Dhandala
34d6c8edbe feat(remediation): add remediation notes feature and alert episode feed component 2026-01-26 17:26:27 +00:00
Nawaz Dhandala
e9f63fb1e2 feat(alert): add lastAlertAddedAt and resolvedAt fields to alert selection 2026-01-26 17:18:20 +00:00
Nawaz Dhandala
7a515f7ad8 feat(alert): add priority field to alert selection criteria 2026-01-26 17:13:04 +00:00
Nawaz Dhandala
4564baae70 fix(accessibility): remove skip to main content link for improved keyboard navigation 2026-01-26 17:07:26 +00:00
Nawaz Dhandala
4316fdbf81 fix(vpat): update conformance status for Non-text Contrast to reflect full support 2026-01-26 16:58:08 +00:00
Nawaz Dhandala
be98736f4e fix(modal): correct type definition for modalRef to avoid null type 2026-01-26 16:55:45 +00:00
Nawaz Dhandala
ce7e10e3d9 feat(accessibility): enhance ARIA attributes and keyboard navigation across multiple components for improved accessibility 2026-01-26 16:53:41 +00:00
Nawaz Dhandala
21683de677 feat(accessibility): enhance ARIA roles and attributes across multiple components for improved screen reader support 2026-01-26 16:37:03 +00:00
Nawaz Dhandala
4dddec9966 feat(accessibility): enhance ARIA roles and attributes across components for improved screen reader support 2026-01-26 16:23:47 +00:00
Nawaz Dhandala
b79a287791 feat(accessibility): enhance ARIA attributes and alt text for improved screen reader support 2026-01-26 15:58:59 +00:00
Nawaz Dhandala
6bd4b7257d feat(legal): add VPAT page and update legal navigation 2026-01-26 14:41:48 +00:00
Nawaz Dhandala
438f8f4b6f refactor(AlertEpisodeService): import AlertService to avoid circular dependency 2026-01-26 13:46:25 +00:00
Nawaz Dhandala
75c1fedfba feat(package-lock): add peer dependency flag to multiple packages 2026-01-26 13:41:40 +00:00
Nawaz Dhandala
731a8e8b8f refactor(MarkdownViewer): simplify containerRef declaration in MermaidDiagram component 2026-01-26 13:40:29 +00:00
Simon Larsen
74768efea1 Merge pull request #2249 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-01-26 13:32:56 +00:00
Nawaz Dhandala
716d05b105 feat(logging): enhance alert processing with detailed debug logs 2026-01-26 13:18:11 +00:00
Nawaz Dhandala
8ea7b26299 feat(migration): add migration for episodeTitleTemplate and titleTemplate adjustments 2026-01-26 12:01:03 +00:00
Nawaz Dhandala
1538852bc4 feat: update title template fields to use LongText type for better flexibility 2026-01-26 11:58:41 +00:00
Nawaz Dhandala
a85607b996 feat(migration): add migration for AlertEpisode and OnCallDutyPolicyScheduleLayer schema updates 2026-01-26 11:58:05 +00:00
Nawaz Dhandala
a53db3b673 feat: rename menu items for clarity in DashboardSideMenu 2026-01-26 11:56:29 +00:00
Nawaz Dhandala
f6ec592cb6 feat: add Active Episodes page and integrate into dashboard routing 2026-01-26 11:54:48 +00:00
Nawaz Dhandala
d2e82fe50e feat(sitemap): implement paginated tags sitemap generation with caching 2026-01-25 18:51:23 +00:00
Nawaz Dhandala
30cb030470 feat(sitemap): enhance sitemap generation with multiple endpoints and caching mechanisms 2026-01-25 18:45:20 +00:00
Nawaz Dhandala
3b84f5cece feat: add comprehensive Dashboard Grafana Parity Plan document outlining improvements and implementation phases 2026-01-24 12:22:39 +00:00
Nawaz Dhandala
7f84f5c34d feat(migrations): add episodeDescriptionTemplate to AlertGroupingRule and update OnCallDutyPolicyScheduleLayer defaults
refactor(AlertEpisodeService): change variable declaration from let to const for users

refactor(AlertGroupingEngineService): improve code readability with comments and formatting

fix(WhatsAppTemplateUtil): format long lines for better readability

refactor(MicrosoftTeamsAlertEpisodeActions): format code for consistency and readability

refactor(MicrosoftTeams): improve readability by formatting conditional statements

refactor(SlackAlertEpisodeActions): format code for better readability

refactor(AlertEpisodeMemberService.test): improve imports and formatting for clarity

refactor(AlertEpisodeService.test): enhance readability with consistent formatting

refactor(AlertGroupingEngineService.test): improve code readability and formatting

refactor(MarkdownViewer): format imports and improve readability

refactor(BaseModelTable): format helpContent type definition for clarity

refactor(OrderedStatesList): format JSX for better readability

fix(AlertEpisodeDocs): format descriptions for consistency

fix(AlertGroupingRules): format helpContent description for clarity

fix(UserSettingsRoutes): format route path for better readability

fix(ResolveInactiveEpisodes): format conditional statements for clarity

fix(SendCreatedResourceNotification): format code for better readability

fix(SendNotePostedNotification): format code for consistency

fix(SendStateChangeNotification): format code for better readability
2026-01-24 11:50:16 +00:00
Nawaz Dhandala
47b42d92c1 Add unit tests for AlertEpisodeService, AlertGroupingEngineService, and AlertGroupingRuleService
- Implement comprehensive tests for AlertEpisodeService covering model instantiation, property accessors, and template rendering.
- Create tests for AlertGroupingEngineService focusing on alert grouping logic, matching criteria, and grouping key generation.
- Develop tests for AlertGroupingRuleService to validate rule properties, match criteria, group settings, and priority ordering.
2026-01-24 11:38:56 +00:00
simlarsen
1928244a8e chore: npm audit fix 2026-01-24 01:54:38 +00:00
Nawaz Dhandala
c3af14c3fe feat: Add title and description template support in AlertEpisode and update related services for dynamic variable handling 2026-01-23 21:26:07 +00:00
Nawaz Dhandala
324666bafe feat: Refactor template variable display in AlertGroupingRules for improved clarity and structure 2026-01-23 21:22:18 +00:00
Nawaz Dhandala
8d4862f39f feat: Add migration for episodeDescriptionTemplate in AlertGroupingRule and update OnCallDutyPolicyScheduleLayer defaults 2026-01-23 21:15:36 +00:00
Nawaz Dhandala
8c42627d46 feat: Add episode description template support and update placeholders in AlertGroupingRules 2026-01-23 21:14:44 +00:00
Nawaz Dhandala
590caa0563 feat: Remove unused ShowAs prop and related ordered states list props from AlertGroupingRulesPage 2026-01-23 21:06:58 +00:00
Nawaz Dhandala
15ac2bf749 feat: Update help content button style in BaseModelTable for improved UI 2026-01-23 20:55:32 +00:00
Nawaz Dhandala
d98103ca94 feat: Add help content support to BaseModelTable and integrate into AlertGroupingRules 2026-01-23 20:49:33 +00:00
Nawaz Dhandala
f8a6354fb4 feat: Update documentation headings in AlertGroupingRules for improved clarity 2026-01-23 20:38:01 +00:00
Nawaz Dhandala
c7cb3b3b20 feat: Enhance MarkdownViewer to handle Mermaid diagrams without additional wrappers 2026-01-23 20:22:53 +00:00
Nawaz Dhandala
978998b3f8 feat: Enhance Mermaid diagram styling in MarkdownViewer component 2026-01-23 20:21:10 +00:00
Nawaz Dhandala
738e464c1e feat: Add 'Group By Service' option to Alert Grouping Rules and implement related database migration 2026-01-23 20:15:58 +00:00
Nawaz Dhandala
8882d62eac chore: update mermaid dependency from 11.4.0 to 11.12.2 in package.json 2026-01-23 19:24:22 +00:00
Nawaz Dhandala
90cd819b0a feat: Add Mermaid diagram support to MarkdownViewer and integrate documentation in AlertGroupingRules 2026-01-23 19:23:47 +00:00
Nawaz Dhandala
a6873c687a feat: Update grouping logic to require explicit enabling of group by options 2026-01-23 19:16:40 +00:00
Nawaz Dhandala
4b54bd6b91 feat: Conditionally display no items message based on create button presence 2026-01-23 18:51:03 +00:00
Nawaz Dhandala
eaf2cbcb71 feat: Remove no items message from Alert Grouping Rules page 2026-01-23 18:46:49 +00:00
Nawaz Dhandala
d9a1876ad4 feat: Add cascade state change functionality for member alerts in AlertEpisodeService 2026-01-23 18:44:18 +00:00
Nawaz Dhandala
c09f75faf0 feat: Add Episode On-Call Rules functionality and related routes 2026-01-23 18:32:19 +00:00
Nawaz Dhandala
674e32b95b feat: add computed properties for SSL ordered and provisioned in StatusPageDomain 2026-01-23 18:20:48 +00:00
Nawaz Dhandala
84cab49386 feat: Add migration for remediation notes and workspace channel updates in AlertEpisode 2026-01-23 17:49:31 +00:00
Nawaz Dhandala
479b83f6bf feat: Implement Alert Episode functionality with Slack and Microsoft Teams integration 2026-01-23 17:33:15 +00:00
Nawaz Dhandala
81ed9e0fc1 fix: correct typo in TerraformPrompt.md regarding provider code generation 2026-01-23 17:28:39 +00:00
Nawaz Dhandala
1f162461ad feat: Add alert episode owner notifications and related email templates
- Implemented findOwners method in AlertEpisodeService to retrieve user and team owners for alert episodes.
- Added new email templates for alert episode owner notifications: AlertEpisodeOwnerAdded, AlertEpisodeOwnerStateChanged, AlertEpisodeOwnerNotePosted, and AlertEpisodeOwnerResourceCreated.
- Created jobs for sending notifications when an owner is added, a note is posted, and when the state of an alert episode changes.
- Updated routes to include new jobs for alert episode owner notifications.
2026-01-23 14:17:32 +00:00
Nawaz Dhandala
ad4f901e2f feat: add alert episode support across services and notification settings 2026-01-23 14:05:00 +00:00
Nawaz Dhandala
a885e2e8a8 feat: add migration for alert episode related fields and constraints 2026-01-23 13:56:25 +00:00
Nawaz Dhandala
8f11156011 feat: Add Alert Episode functionality and Slack integration
- Implemented addNote and hasNoteFromSlackMessage methods in AlertEpisodeInternalNoteService.
- Added isEpisodeAcknowledged method in AlertEpisodeService to check acknowledgment status.
- Enhanced OnCallDutyPolicyService to include triggeredByAlertEpisodeId in logs.
- Updated WorkspaceNotificationRuleService to support Alert Episode conditions.
- Introduced new Slack action types for Alert Episodes.
- Extended NotificationRuleEventType and NotificationRuleConditionCheckOn enums for Alert Episodes.
- Modified WorkspaceConnectionMicrosoftTeams and WorkspaceConnectionSlack components to handle Alert Episodes.
- Created SlackAlertEpisodeActions class for managing Alert Episode actions in Slack.
- Implemented emoji reaction handling for private notes in Alert Episodes.
2026-01-23 13:53:54 +00:00
Nawaz Dhandala
1ef1101134 Merge branch 'master' into release 2026-01-23 13:05:05 +00:00
Nawaz Dhandala
5664ad48dd fix: move git user configuration after repository initialization in publish script 2026-01-23 13:04:50 +00:00
Nawaz Dhandala
e2608f56db feat: add migration for AlertGroupingRuleMonitor and related tables 2026-01-23 12:47:09 +00:00
Nawaz Dhandala
78df267145 feat: add monitor name and description pattern fields to alert grouping rules 2026-01-23 12:45:45 +00:00
Nawaz Dhandala
20e7e68e71 feat: enhance alert grouping rules with match criteria and grouping options 2026-01-23 12:35:30 +00:00
Nawaz Dhandala
877d69f22e feat: add migration for enableTimeWindow column in AlertGroupingRule 2026-01-23 12:16:48 +00:00
Nawaz Dhandala
0791029f4a feat: add enable time window option for alert grouping rules 2026-01-23 12:16:10 +00:00
Nawaz Dhandala
69c91a2c41 Merge branch 'master' into alert-episode 2026-01-23 12:04:34 +00:00
Nawaz Dhandala
499d28c34c Merge branch 'master' into release 2026-01-23 12:01:58 +00:00
Nawaz Dhandala
ec57a9ddbc chore: bump version to 9.4.7 2026-01-23 12:01:46 +00:00
Nawaz Dhandala
e59db99b22 feat: update migration for monitor log retention and format RouteMap entries 2026-01-23 11:58:30 +00:00
Nawaz Dhandala
aaa3c4f602 fix: remove unnecessary constraints and columns from Alert table in migration 2026-01-23 11:57:21 +00:00
Nawaz Dhandala
29842c06e3 feat: add migration for monitor log retention and update alert table structure 2026-01-23 11:56:46 +00:00
Nawaz Dhandala
402ccf01d0 feat: add Data Retention settings page and integrate with global configuration 2026-01-23 11:55:37 +00:00
Nawaz Dhandala
b7114304ee fix: streamline git repository handling in Terraform provider publishing script 2026-01-23 11:51:40 +00:00
Nawaz Dhandala
dca72856a2 fix: configure git user before committing generated Terraform provider files 2026-01-23 11:48:30 +00:00
Nawaz Dhandala
1d7c758096 fix: update import path for ReactElement in CategoryCheckboxTypes 2026-01-23 11:31:50 +00:00
Simon Larsen
1e748365a5 Merge pull request #2245 from OneUptime/snyk-fix-a7af8e60213a832c66f6a2fdddd05e1e
[Snyk] Fix for 1 vulnerabilities
2026-01-23 11:28:56 +00:00
Nawaz Dhandala
a8022762a2 Merge branch 'release' into alert-episode 2026-01-23 11:02:19 +00:00
Nawaz Dhandala
9c1ed659e9 fix(URL): streamline route handling in toString method 2026-01-23 09:24:03 +00:00
Nawaz Dhandala
42accb4204 feat(Migration): add migration for new alert grouping rule features and on-call duty policy updates 2026-01-22 23:46:59 +00:00
Nawaz Dhandala
529e5954d4 feat(AlertEpisodes): add resolve delay, reopen window, and inactivity timeout features 2026-01-22 23:45:48 +00:00
Nawaz Dhandala
75ea34ef9e feat(AlertEpisodeDocs): enhance descriptions and update icons for clarity 2026-01-22 23:32:10 +00:00
Nawaz Dhandala
c4e1b8d97d fix: increase timeout for Terraform E2E tests from 60 to 120 minutes 2026-01-22 23:31:21 +00:00
Nawaz Dhandala
b5626ef352 feat(AlertEpisodeDocs): add on-call policy flow steps and notification scenarios 2026-01-22 23:14:56 +00:00
Nawaz Dhandala
692d15159c feat(Terraform E2E): enhance disk cleanup process and optimize Docker storage management 2026-01-22 23:13:51 +00:00
Nawaz Dhandala
91c163af9e feat(AlertEpisodes): add documentation page for alert episodes and update side menu 2026-01-22 23:05:49 +00:00
Nawaz Dhandala
fe71be64dd refactor: replace dynamic imports with direct imports for service dependencies 2026-01-22 22:58:49 +00:00
Nawaz Dhandala
9e6587cb62 feat(OrderedStatesList): enhance no items message with add new item option 2026-01-22 22:48:05 +00:00
snyk-bot
42b2f58d6a 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-DIFF-14917201
2026-01-22 22:34:30 +00:00
Simon Larsen
98afb63880 Merge pull request #2243 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-01-22 22:33:12 +00:00
Nawaz Dhandala
6d352c8579 Merge branch 'master' into alert-episode 2026-01-22 22:28:57 +00:00
Nawaz Dhandala
21b761ddbf chore(VERSION): bump version to 9.4.6 2026-01-22 22:23:34 +00:00
Nawaz Dhandala
e51009e94d Merge branch 'master' into release 2026-01-22 22:23:21 +00:00
Nawaz Dhandala
619136c9da feat(MailService): enhance email sending response types for SendGrid and SMTP 2026-01-22 21:58:45 +00:00
Nawaz Dhandala
d622334bd3 feat(StatusPageAuthentication): integrate SMTP configuration into status page login and creation processes 2026-01-22 21:51:34 +00:00
Nawaz Dhandala
5508bf6302 feat(StatusPagePrivateUserService): integrate SMTP configuration into status page creation process 2026-01-22 21:44:11 +00:00
Nawaz Dhandala
4ba9151400 feat(dockerignore): add large directories to ignore for Docker builds 2026-01-22 21:42:52 +00:00
Nawaz Dhandala
97fe212d15 feat(ExceptionProductImprovements): add comprehensive plan for enhancing exception tracking features 2026-01-22 21:21:09 +00:00
Nawaz Dhandala
af3738924e feat(MailService): add debug logging for SMTP and SendGrid email responses 2026-01-22 20:57:18 +00:00
Nawaz Dhandala
92f77c7ce2 feat(SCIM): update user name in SCIM request if missing or different 2026-01-22 20:44:11 +00:00
Nawaz Dhandala
ecb54381d8 style(Login.tsx, MasterPassword.tsx, StatusPage.ts): improve code formatting for better readability 2026-01-22 20:29:08 +00:00
Nawaz Dhandala
0a9435ef1a feat(auth): implement safe redirect URL handling to prevent navigation to auth pages 2026-01-22 20:23:18 +00:00
Nawaz Dhandala
2bc52c7b5d Merge branch 'master' into release 2026-01-22 18:11:50 +00:00
Nawaz Dhandala
392b6dda9a chore: bump version to 9.4.5 2026-01-22 18:11:39 +00:00
Nawaz Dhandala
0a6035ed65 style(ProductCompare.ts, GenerateProvider.ts): improve code formatting for better readability 2026-01-22 18:11:21 +00:00
Nawaz Dhandala
70f9444aab feat(svg): add new SVG icons for better integration and visual consistency 2026-01-22 18:07:19 +00:00
Nawaz Dhandala
088333c91c style(pricing.ejs, product-compare.ejs): improve text wrapping and update image styling for better layout 2026-01-22 15:47:30 +00:00
Nawaz Dhandala
7fc7276207 feat(pricing.ejs): enhance Bitcoin payment interaction with clickable text and improved styling 2026-01-22 15:43:20 +00:00
Nawaz Dhandala
631bf12c23 style(pricing.ejs): adjust genesis text styling and update content for clarity 2026-01-22 15:19:28 +00:00
Nawaz Dhandala
5ce158ebf3 Refactor code structure for improved readability and maintainability 2026-01-22 15:18:17 +00:00
Nawaz Dhandala
4684f25f22 easter egg 2026-01-22 15:17:19 +00:00
Nawaz Dhandala
3d36d86bd6 chore(VERSION): bump version to 9.4.4 2026-01-22 13:36:19 +00:00
Nawaz Dhandala
93c017dbab chore(GenerateProvider): add VERSION file generation to ensure proper detection of changes 2026-01-22 13:25:03 +00:00
Nawaz Dhandala
c74204ed1f chore(sitemap): remove outdated sitemap.xml file 2026-01-22 13:12:09 +00:00
Nawaz Dhandala
80125f500c chore(views): update card components to ensure full height for better layout consistency 2026-01-22 12:58:43 +00:00
Nawaz Dhandala
2771efcd87 chore(GoModuleGenerator): update comments for clarity in generateGoMod method
chore(GenerateProvider): format log message for consistency in main function
2026-01-22 12:43:45 +00:00
Nawaz Dhandala
0e27802f1a chore(verify.sh): update monitor verification logic to check for manual with description and remove empty steps check 2026-01-22 12:39:14 +00:00
Nawaz Dhandala
a96c270a94 chore(URL.ts): update toString method to conditionally add route and improve URL construction logic
chore(MonitorStep.ts): remove redundant default monitor assignments in getDefaultMonitorStep method
chore(Port.ts): change toJSON method to return port value as a number instead of string
2026-01-22 12:38:50 +00:00
Nawaz Dhandala
66d76676f5 chore(ResourceGenerator): add sorting for list items to ensure consistent ordering and fix idempotency issues 2026-01-22 12:35:50 +00:00
simlarsen
cc0eb6a4b9 chore: npm audit fix 2026-01-22 02:02:10 +00:00
Nawaz Dhandala
2d687a3275 chore(E2E Tests): refactor verification scripts to use shared library functions and improve validation 2026-01-21 22:23:20 +00:00
Nawaz Dhandala
47bca3fb9b chore(ResourceGenerator): refactor valid ObjectType handling to use dynamic generation from enum 2026-01-21 21:29:29 +00:00
Nawaz Dhandala
79d3548492 chore(ResourceGenerator): add validation for OneUptime ObjectType in resource handling 2026-01-21 21:26:07 +00:00
Nawaz Dhandala
3156302dbc chore(JSON.ts): remove unnecessary blank line in ObjectType enum 2026-01-21 21:15:35 +00:00
Nawaz Dhandala
84307250b7 chore(GoModuleGenerator): update go.mod generation to specify minimum versions and clarify dependency fetching process 2026-01-21 21:13:07 +00:00
Nawaz Dhandala
c3986bd66a chore(GoModuleGenerator): update go.mod to use Go 1.23 and pin dependencies for compatibility with Terraform 1.5+ 2026-01-21 21:08:42 +00:00
Nawaz Dhandala
a4a56bf2c7 chore(GoModuleGenerator): update go.mod to pin additional indirect dependencies for compatibility with Terraform 1.5+ 2026-01-21 21:04:36 +00:00
Nawaz Dhandala
6644523c54 chore(robots.txt): update AI agent access rules and refine API disallow directive 2026-01-21 18:20:50 +00:00
Nawaz Dhandala
44aa046fec chore: update Go version to 'stable' in workflow files 2026-01-21 17:27:08 +00:00
Nawaz Dhandala
da5b9b4955 chore(VERSION): bump version to 9.4.3 2026-01-21 15:59:54 +00:00
Nawaz Dhandala
81dd803b62 Merge branch 'release' 2026-01-21 15:59:39 +00:00
Nawaz Dhandala
efffa82cbf refactor(StatusPageService): simplify conditional check for downtimeMonitorStatuses 2026-01-21 15:56:49 +00:00
Nawaz Dhandala
64b0c9f137 feat(Terraform): update monitor names to use random suffixes for uniqueness 2026-01-21 15:48:15 +00:00
Nawaz Dhandala
a3661e1626 Merge branch 'master' of https://github.com/OneUptime/oneuptime 2026-01-21 15:46:18 +00:00
Nawaz Dhandala
4115deadc4 feat(Monitor): add monitorId prop to MonitorStep and MonitorSteps components for secret population during testing 2026-01-21 14:58:09 +00:00
Nawaz Dhandala
6fbd112964 fix(ResourceGenerator): enhance handling of complex typed objects in Delete method 2026-01-21 14:55:25 +00:00
Nawaz Dhandala
a171c52c8d feat(tests): refactor E2E tests to use random suffixes for resource names
- Updated multiple test files to replace timestamp-based naming with random suffixes for better uniqueness and idempotency.
- Added random provider to each test file to generate unique identifiers.
- Removed unnecessary lifecycle blocks that ignored changes to resource names.
- Ensured consistent naming conventions across all test cases for clarity and maintainability.
2026-01-21 14:45:46 +00:00
Nawaz Dhandala
4f7d3ed2be feat(E2E Tests): add comprehensive tests for various monitor types with steps and basic configurations 2026-01-21 13:38:49 +00:00
Nawaz Dhandala
9db97b3919 Add E2E tests for OneUptime resources
- Implemented monitor types tests including variable definitions and verification scripts.
- Created incident CRUD tests with various configurations and verification logic.
- Added alert CRUD tests to validate alert creation and configurations.
- Developed scheduled maintenance CRUD tests to ensure proper handling of maintenance events.
- Established on-call duty policy CRUD tests to validate policy creation and configurations.
- Introduced monitor group CRUD tests to verify group creation and uniqueness.
- Created team CRUD tests to validate team creation and configurations.
2026-01-21 13:25:55 +00:00
Nawaz Dhandala
8bc545c90f Add end-to-end tests for OneUptime resources
- Implemented idempotency tests for status pages, monitors, and probes.
- Created Terraform configurations and verification scripts for:
  - StatusPageDomain idempotency (Issue #2236)
  - Monitor CRUD operations with various configurations
  - Probe CRUD operations, ensuring probe_version is a string (Issue #2228)
  - StatusPage CRUD operations, handling server defaults (Issue #2232)
  - StatusPage with domain integration, validating computed fields and server-injected defaults
- Added necessary variable files for configuration.
2026-01-21 13:09:36 +00:00
Nawaz Dhandala
19d1629e37 fix(StatusPageDomain): update access control for create permissions and adjust required fields 2026-01-21 13:01:51 +00:00
Nawaz Dhandala
e7fd472c14 fix(ResourceGenerator): enhance handling of complex object responses in Delete method 2026-01-21 12:33:27 +00:00
Nawaz Dhandala
dd4a1416fc fix(StatusPageService): simplify downtime monitor statuses check 2026-01-21 12:17:25 +00:00
Nawaz Dhandala
09b65b9a5b fix(StatusPageDomain): change CNAME Verification Token requirement to optional 2026-01-21 12:09:11 +00:00
Simon Larsen
8fb1a1daf9 Merge pull request #2239 from OneUptime/chore/npm-audit-fix
chore: npm audit fix
2026-01-21 09:27:59 +00:00
simlarsen
d3d0dedfee chore: npm audit fix 2026-01-21 02:01:12 +00:00
Nawaz Dhandala
46635f4251 refactor: improve type safety with type aliases for dynamically imported services 2026-01-20 21:09:37 +00:00
Nawaz Dhandala
1068a5d96e refactor: add type annotations for improved type safety and clarity in service imports 2026-01-20 21:00:36 +00:00
Nawaz Dhandala
d1e200a54f Refactor code for improved readability and consistency
- Added missing comma in schema migrations index.
- Reformatted long lines in AlertEpisodeFeedService and AlertEpisodeMemberService for better readability.
- Improved formatting in AlertEpisodeService for destructured variables.
- Enhanced readability in AlertGroupingEngineService by restructuring filter and map functions.
- Cleaned up permission descriptions in Permission.ts for consistency.
- Standardized description formatting in ChangeState and AlertGroupingRules components.
- Improved formatting in Episodes and AlertView components for better readability.
- Added comments for clarity in AutoResolve and BreakInactive jobs.
2026-01-20 20:50:09 +00:00
Nawaz Dhandala
8220b0356c Merge branch 'master' into alert-episode 2026-01-20 20:46:58 +00:00
Nawaz Dhandala
bc9b09aed5 chore: Bump version to 9.4.2 2026-01-20 20:46:03 +00:00
Nawaz Dhandala
9a935c4e90 feat(AlertEpisode): add services and models for AlertEpisode management 2026-01-20 19:56:41 +00:00
Nawaz Dhandala
6137199e63 feat: add AlertGroupingRule, AlertEpisode, and related tables with foreign key constraints and indexes 2026-01-20 19:42:01 +00:00
Nawaz Dhandala
6e6d989be4 feat: Add Alert Episode Management Features
- Implemented AlertEpisodeViewLayout for displaying episode details.
- Created Owners component to manage team and user ownership of episodes.
- Added RootCause component for documenting the root cause of episodes.
- Developed SideMenu for navigation within the episode view.
- Introduced StateTimeline component to track the status timeline of episodes.
- Created EpisodesPage for listing all alert episodes.
- Added AlertGroupingRulesPage for managing alert grouping rules.
- Implemented UnresolvedEpisodesPage to display active (unresolved) episodes.
- Developed AutoResolve job to automatically resolve episodes based on alert status.
- Created BreakInactive job to resolve inactive episodes after a specified timeout.
2026-01-20 19:35:31 +00:00
1020 changed files with 130671 additions and 8507 deletions

View File

@@ -33,6 +33,15 @@ stop
nohup.out*
# Large directories not needed for Docker builds
E2E/playwright-report
E2E/test-results
Terraform
HelmChart
Scripts
.git
GoSDK
encrypted-credentials.tar
encrypted-credentials/

View File

@@ -389,6 +389,22 @@ jobs:
max_attempts: 3
command: cd MCP && npm update @oneuptime/common && npm install && npm run compile && npm run dep-check
compile-mobile-app:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- name: Compile MobileApp
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd MobileApp && npm install && npm run compile
compile-ai-agent:
runs-on: ubuntu-latest
env:

View File

@@ -1701,7 +1701,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: 'stable'
cache: true
- name: Install GoReleaser
@@ -2200,6 +2200,145 @@ jobs:
tag_name: ${{needs.read-version.outputs.major_minor}}
# Build Android release APK and attach to GitHub Release.
# Required secrets setup guide: MobileApp/docs/RELEASE_SIGNING.md
mobile-app-android-deploy:
needs: [draft-github-release, generate-build-number, read-version]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- name: Setup Java 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- uses: actions/setup-node@v4
with:
node-version: latest
- name: Install dependencies
run: cd MobileApp && npm install
- name: Decode Android keystore
run: |
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > /tmp/release.keystore
- name: Build release APK
env:
ANDROID_KEYSTORE_FILE: /tmp/release.keystore
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
cd MobileApp/android
./gradlew assembleRelease \
-PversionName=${{ needs.read-version.outputs.major_minor }} \
-PversionCode=${{ needs.generate-build-number.outputs.build_number }}
- name: Upload APK to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: MobileApp/android/app/build/outputs/apk/release/*.apk
token: ${{ secrets.GITHUB_TOKEN }}
draft: true
prerelease: false
tag_name: ${{ needs.read-version.outputs.major_minor }}
# Build iOS release IPA and attach to GitHub Release.
# Required secrets setup guide: MobileApp/docs/RELEASE_SIGNING.md
mobile-app-ios-deploy:
needs: [draft-github-release, generate-build-number, read-version]
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- uses: actions/setup-node@v4
with:
node-version: latest
- name: Install dependencies
run: cd MobileApp && npm install
- name: Install CocoaPods dependencies
run: cd MobileApp/ios && pod install
- name: Import signing certificate
env:
IOS_DISTRIBUTION_CERTIFICATE_BASE64: ${{ secrets.IOS_DISTRIBUTION_CERTIFICATE_BASE64 }}
IOS_DISTRIBUTION_CERTIFICATE_PASSWORD: ${{ secrets.IOS_DISTRIBUTION_CERTIFICATE_PASSWORD }}
run: |
CERTIFICATE_PATH=$RUNNER_TEMP/distribution.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
echo "$IOS_DISTRIBUTION_CERTIFICATE_BASE64" | base64 --decode > "$CERTIFICATE_PATH"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security import "$CERTIFICATE_PATH" -P "$IOS_DISTRIBUTION_CERTIFICATE_PASSWORD" \
-A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
- name: Install provisioning profile
env:
IOS_PROVISIONING_PROFILE_BASE64: ${{ secrets.IOS_PROVISIONING_PROFILE_BASE64 }}
run: |
PROFILE_PATH=$RUNNER_TEMP/profile.mobileprovision
echo "$IOS_PROVISIONING_PROFILE_BASE64" | base64 --decode > "$PROFILE_PATH"
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "$PROFILE_PATH" ~/Library/MobileDevice/Provisioning\ Profiles/
- name: Build archive
run: |
cd MobileApp
xcodebuild -workspace ios/OneUptime.xcworkspace \
-scheme OneUptime \
-configuration Release \
-sdk iphoneos \
-archivePath $RUNNER_TEMP/OneUptime.xcarchive \
archive \
MARKETING_VERSION=${{ needs.read-version.outputs.major_minor }} \
CURRENT_PROJECT_VERSION=${{ needs.generate-build-number.outputs.build_number }}
- name: Prepare ExportOptions.plist with team ID
env:
IOS_TEAM_ID: ${{ secrets.IOS_TEAM_ID }}
run: |
/usr/libexec/PlistBuddy -c "Add :teamID string $IOS_TEAM_ID" MobileApp/ios/ExportOptions.plist || \
/usr/libexec/PlistBuddy -c "Set :teamID $IOS_TEAM_ID" MobileApp/ios/ExportOptions.plist
- name: Export IPA
run: |
cd MobileApp
xcodebuild -exportArchive \
-archivePath $RUNNER_TEMP/OneUptime.xcarchive \
-exportOptionsPlist ios/ExportOptions.plist \
-exportPath $RUNNER_TEMP/build
- name: Upload IPA to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: ${{ runner.temp }}/build/*.ipa
token: ${{ secrets.GITHUB_TOKEN }}
draft: true
prerelease: false
tag_name: ${{ needs.read-version.outputs.major_minor }}
- name: Cleanup keychain
if: always()
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true
finalize-github-release:
name: Publish GitHub release
needs: [infrastructure-agent-deploy, generate-build-number, read-version]

View File

@@ -15,7 +15,7 @@ on:
jobs:
terraform-e2e-tests:
runs-on: ubuntu-latest
timeout-minutes: 60
timeout-minutes: 120
env:
CI_PIPELINE_ID: ${{ github.run_number }}
APP_TAG: latest
@@ -34,16 +34,84 @@ jobs:
- name: Additional Disk Cleanup
run: |
echo "=== Initial disk space ==="
df -h
echo "=== Removing unnecessary tools and libraries ==="
# Remove Android SDK (if not already removed)
sudo rm -rf /usr/local/lib/android || true
sudo rm -rf /opt/ghc || true
# Remove .NET SDK and runtime
sudo rm -rf /usr/share/dotnet || true
sudo rm -rf /etc/skel/.dotnet || true
# Remove Haskell/GHC
sudo rm -rf /opt/ghc || true
sudo rm -rf /usr/local/.ghcup || true
# Remove CodeQL
sudo rm -rf /opt/hostedtoolcache/CodeQL || true
# Remove Boost
sudo rm -rf /usr/local/share/boost || true
# Remove Swift
sudo rm -rf /usr/share/swift || true
# Remove Julia
sudo rm -rf /usr/local/julia* || true
# Remove Rust (cargo/rustup)
sudo rm -rf /usr/share/rust || true
sudo rm -rf /home/runner/.rustup || true
sudo rm -rf /home/runner/.cargo || true
# Remove unnecessary hostedtoolcache items
sudo rm -rf /opt/hostedtoolcache/Python || true
sudo rm -rf /opt/hostedtoolcache/PyPy || true
sudo rm -rf /opt/hostedtoolcache/Ruby || true
sudo rm -rf /opt/hostedtoolcache/Java* || true
# Remove additional large directories
sudo rm -rf /usr/share/miniconda || true
sudo rm -rf /usr/local/graalvm || true
sudo rm -rf /usr/local/share/chromium || true
sudo rm -rf /usr/local/share/powershell || true
sudo rm -rf /usr/share/az_* || true
# Remove documentation
sudo rm -rf /usr/share/doc || true
sudo rm -rf /usr/share/man || true
# Remove unnecessary locales
sudo rm -rf /usr/share/locale || true
# Clean apt cache
sudo apt-get clean || true
sudo rm -rf /var/lib/apt/lists/* || true
sudo rm -rf /var/cache/apt/archives/* || true
# Clean tmp
sudo rm -rf /tmp/* || true
echo "=== Moving Docker data to /mnt for more space ==="
# Stop docker
sudo systemctl stop docker || true
# Move docker data directory to /mnt (which has ~70GB)
sudo mv /var/lib/docker /mnt/docker || true
sudo mkdir -p /var/lib/docker || true
sudo mount --bind /mnt/docker /var/lib/docker || true
# Restart docker
sudo systemctl start docker || true
echo "=== Final disk space ==="
df -h
echo "=== Docker info ==="
docker info | grep -E "Docker Root Dir|Storage Driver" || true
- name: Checkout code
uses: actions/checkout@v4
@@ -56,7 +124,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: 'stable'
cache: true
- name: Setup Terraform
@@ -66,6 +134,10 @@ jobs:
terraform_wrapper: false
- name: Run E2E Tests
run: |
chmod +x ./E2E/Terraform/e2e-tests/scripts/*.sh
./E2E/Terraform/e2e-tests/scripts/index.sh
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
max_attempts: 3
command: |
chmod +x ./E2E/Terraform/e2e-tests/scripts/*.sh
./E2E/Terraform/e2e-tests/scripts/index.sh

View File

@@ -28,7 +28,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: 'stable'
cache: true
- name: Install Common dependencies

39
.github/workflows/test.mobile-app.yaml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: MobileApp Test
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*' # excludes hotfix branches
- 'release'
jobs:
expo-doctor:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd MobileApp && npm install
- name: Run Expo Doctor
run: cd MobileApp && npx expo-doctor@latest
expo-web-export:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd MobileApp && npm install
- name: Export Web Bundle
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd MobileApp && npx expo export --platform web

View File

@@ -73,6 +73,7 @@
"ejs": "^3.1.10",
"elkjs": "^0.10.0",
"esbuild": "^0.25.5",
"expo-server-sdk": "^3.15.0",
"express": "^4.21.1",
"formik": "^2.4.6",
"history": "^5.3.0",
@@ -82,6 +83,7 @@
"jsonwebtoken": "^9.0.0",
"jwt-decode": "^4.0.0",
"marked": "^12.0.2",
"mermaid": "^11.12.2",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
"multer": "^2.0.2",
@@ -101,7 +103,7 @@
"react-dropzone": "^14.2.2",
"react-error-boundary": "^4.0.13",
"react-highlight": "^0.15.0",
"react-markdown": "^8.0.3",
"react-markdown": "^9.0.0",
"react-router-dom": "^6.30.1",
"react-select": "^5.4.0",
"react-spinners": "^0.14.1",
@@ -111,7 +113,7 @@
"recharts": "^2.12.7",
"redis-semaphore": "^5.5.1",
"reflect-metadata": "^0.2.2",
"remark-gfm": "^3.0.1",
"remark-gfm": "^4.0.0",
"slackify-markdown": "^4.4.0",
"slugify": "^1.6.5",
"socket.io": "^4.7.4",
@@ -1808,9 +1810,9 @@
}
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"

View File

@@ -1,5 +1,6 @@
import AuthenticationServiceHandler from "./Service/Authentication";
import DataTypeServiceHandler from "./Service/DataType";
import DataTypeDetailServiceHandler from "./Service/DataTypeDetail";
import ErrorServiceHandler from "./Service/Errors";
import OpenAPIServiceHandler from "./Service/OpenAPI";
import IntroductionServiceHandler from "./Service/Introduction";
@@ -10,6 +11,7 @@ import PermissionServiceHandler from "./Service/Permissions";
import StatusServiceHandler from "./Service/Status";
import { StaticPath } from "./Utils/Config";
import ResourceUtil, { ModelDocumentation } from "./Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "./Utils/DataTypes";
import Dictionary from "Common/Types/Dictionary";
import FeatureSet from "Common/Server/Types/FeatureSet";
import Express, {
@@ -24,6 +26,9 @@ const APIReferenceFeatureSet: FeatureSet = {
const ResourceDictionary: Dictionary<ModelDocumentation> =
ResourceUtil.getResourceDictionaryByPath();
const DataTypeDictionary: Dictionary<DataTypeDocumentation> =
DataTypeUtil.getDataTypeDictionaryByPath();
const app: ExpressApplication = Express.getExpressApp();
// Serve static files for the API reference with a cache max age of 30 days
@@ -72,6 +77,8 @@ const APIReferenceFeatureSet: FeatureSet = {
return StatusServiceHandler.executeResponse(req, res);
} else if (req.params["page"] === "data-types") {
return DataTypeServiceHandler.executeResponse(req, res);
} else if (DataTypeDictionary[page]) {
return DataTypeDetailServiceHandler.executeResponse(req, res);
} else if (currentResource) {
return ModelServiceHandler.executeResponse(req, res);
}

View File

@@ -1,11 +1,13 @@
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import Dictionary from "Common/Types/Dictionary";
// Retrieve resources documentation
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
public static async executeResponse(
@@ -27,6 +29,7 @@ export default class ServiceHandler {
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
dataTypes: DataTypes,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled,
pageDescription: pageDescription,

View File

@@ -1,12 +1,14 @@
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import { CodeExamplesPath, ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import LocalCache from "Common/Server/Infrastructure/LocalCache";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import LocalFile from "Common/Server/Utils/LocalFile";
import Dictionary from "Common/Types/Dictionary";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
public static async executeResponse(
@@ -153,6 +155,7 @@ export default class ServiceHandler {
pageDescription:
"Data Types that can be used to interact with OneUptime API",
resources: Resources,
dataTypes: DataTypes,
pageData: pageData,
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,13 @@
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import Dictionary from "Common/Types/Dictionary";
// Fetch a list of resources used in the application
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
// Handles the HTTP response for a given request
@@ -28,6 +30,7 @@ export default class ServiceHandler {
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
dataTypes: DataTypes,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled,
pageDescription: pageDescription,

View File

@@ -1,11 +1,13 @@
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import Dictionary from "Common/Types/Dictionary";
// Get all resources and featured resources from ResourceUtil
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
const FeaturedResources: Array<ModelDocumentation> =
ResourceUtil.getFeaturedResources();
@@ -34,6 +36,7 @@ export default class ServiceHandler {
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
dataTypes: DataTypes,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled,
pageDescription: pageDescription,

View File

@@ -3,8 +3,10 @@ import CodeExampleGenerator, {
CodeExamples,
} from "../Utils/CodeExampleGenerator";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import PageNotFoundServiceHandler from "./PageNotFound";
import { AppApiRoute } from "Common/ServiceRoute";
import BaseModel from "Common/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
import { ColumnAccessControl } from "Common/Types/BaseDatabase/AccessControl";
import {
getTableColumns,
@@ -314,9 +316,13 @@ function generateApiCodeExamples(
// Get all resources and resource dictionary
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
const ResourceDictionary: Dictionary<ModelDocumentation> =
ResourceUtil.getResourceDictionaryByPath();
// Dynamically built from DataTypes registry — no manual updates needed when new types are added
const TypeToDocPath: Dictionary<string> = DataTypeUtil.getTypeToDocPathMap();
// Get all permission props
const PermissionDictionary: Dictionary<PermissionProps> =
PermissionHelper.getAllPermissionPropsAsDictionary();
@@ -392,6 +398,32 @@ export default class ServiceHandler {
delete tableColumns["deletedByUser"];
delete tableColumns["version"];
// For columns with a modelType (Entity/EntityArray), resolve the related model's documentation path
for (const key in tableColumns) {
const column: TableColumnMetadata | undefined = tableColumns[key];
if (column?.modelType) {
try {
const relatedModelInstance: BaseModel = new column.modelType();
if (relatedModelInstance.enableDocumentation) {
(column as any).modelDocumentationPath =
relatedModelInstance.getAPIDocumentationPath();
(column as any).modelName = relatedModelInstance.singularName;
}
} catch {
// If model instantiation fails, skip linking
}
}
// Resolve non-entity complex types to their documentation paths
if (column?.type && !(column as any).modelDocumentationPath) {
const typeStr: string = column.type.toString();
const docPath: string | undefined = TypeToDocPath[typeStr];
if (docPath) {
(column as any).typeDocumentationPath = docPath;
}
}
}
// Set page data
pageData["title"] = currentResource.model.singularName;
pageData["description"] = currentResource.model.tableDescription;
@@ -586,6 +618,7 @@ export default class ServiceHandler {
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
dataTypes: DataTypes,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled,
pageDescription: pageDescription,

View File

@@ -5,12 +5,14 @@ import {
} from "Common/Server/EnvironmentConfig";
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import URL from "Common/Types/API/URL";
import Dictionary from "Common/Types/Dictionary";
// Fetch a list of resources used in the application
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
// Handles the HTTP response for a given request
@@ -36,6 +38,7 @@ export default class ServiceHandler {
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
dataTypes: DataTypes,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled,
pageDescription: pageDescription,

View File

@@ -1,9 +1,11 @@
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources(); // Get an array of model documentation resources
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
// This is a static method that handles the response
@@ -21,6 +23,7 @@ export default class ServiceHandler {
enableGoogleTagManager: IsBillingEnabled,
pageDescription: "Page you're looking for is not found.", // The page description
resources: Resources, // The array of model documentation resources
dataTypes: DataTypes,
pageData: {}, // An empty object to hold any additional page data
});
}

View File

@@ -1,12 +1,14 @@
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import { CodeExamplesPath, ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import LocalCache from "Common/Server/Infrastructure/LocalCache";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import LocalFile from "Common/Server/Utils/LocalFile";
import Dictionary from "Common/Types/Dictionary";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources(); // Get all resources from ResourceUtil
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
public static async executeResponse(
@@ -49,6 +51,7 @@ export default class ServiceHandler {
return res.render(`${ViewsPath}/pages/index`, {
page: page, // Pass the page parameter
resources: Resources, // Pass all resources
dataTypes: DataTypes,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled, // Pass the page title
pageDescription: pageDescription, // Pass the page description

View File

@@ -1,11 +1,17 @@
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { PermissionHelper, PermissionProps } from "Common/Types/Permission";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import {
PermissionGroup,
PermissionHelper,
PermissionProps,
} from "Common/Types/Permission";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import Dictionary from "Common/Types/Dictionary";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const DataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
public static async executeResponse(
@@ -25,16 +31,39 @@ export default class ServiceHandler {
pageDescription = "Learn how permissions work with OneUptime";
// Filter permissions to only include those assignable to tenants
pageData["permissions"] = PermissionHelper.getAllPermissionProps().filter(
(i: PermissionProps) => {
const tenantPermissions: Array<PermissionProps> =
PermissionHelper.getAllPermissionProps().filter((i: PermissionProps) => {
return i.isAssignableToTenant;
},
);
});
// Group permissions by PermissionGroup
const permissionGroups: Array<{
group: string;
permissions: Array<PermissionProps>;
}> = [];
for (const group of Object.values(PermissionGroup)) {
const groupPermissions: Array<PermissionProps> = tenantPermissions.filter(
(p: PermissionProps) => {
return p.group === group;
},
);
if (groupPermissions.length > 0) {
permissionGroups.push({
group: group,
permissions: groupPermissions,
});
}
}
pageData["permissionGroups"] = permissionGroups;
// Render the page
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
dataTypes: DataTypes,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled,
pageDescription: pageDescription,

View File

@@ -1,10 +1,12 @@
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import DataTypeUtil, { DataTypeDocumentation } from "../Utils/DataTypes";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
// Retrieve resources from ResourceUtil
const resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const dataTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
export default class ServiceHandler {
public static async executeResponse(
@@ -21,6 +23,7 @@ export default class ServiceHandler {
enableGoogleTagManager: IsBillingEnabled,
pageDescription: "200 - Success",
resources: resources, // Pass resources to the template
dataTypes: dataTypes,
pageData: {}, // Pass empty data to the template
});
}

View File

@@ -0,0 +1,422 @@
import Dictionary from "Common/Types/Dictionary";
export interface DataTypeDocumentation {
name: string;
path: string;
description: string;
/*
* Additional column type display strings that should link to this data type page.
* Used for cases where the TableColumnType enum value doesn't match the PascalCase name
* (e.g., enum "Date" should link to the "DateTime" data type page).
*/
columnTypeAliases?: Array<string>;
/*
* Category for grouping in sidebar navigation.
* Types with the same category are grouped under a collapsible heading.
*/
category?: string;
}
export interface DataTypeCategory {
name: string;
types: Array<DataTypeDocumentation>;
}
export default class DataTypeUtil {
public static getDataTypes(): Array<DataTypeDocumentation> {
return [
{
name: "ObjectID",
path: "object-id",
description:
"A unique identifier for objects, typically a UUID string.",
},
{
name: "Decimal",
path: "decimal",
description: "A decimal number type for precise numeric values.",
},
{
name: "Name",
path: "name",
description: "A structured name type representing a text name value.",
},
{
name: "EqualTo",
path: "equal-to",
description:
"A query filter that matches objects where a field is equal to the specified value.",
},
{
name: "EqualToOrNull",
path: "equal-to-or-null",
description:
"A query filter that matches objects where a field is equal to the specified value or is null.",
},
{
name: "MonitorSteps",
path: "monitor-steps",
description:
"Complex nested object describing monitor check configuration including steps and default status.",
category: "Monitor",
},
{
name: "MonitorStep",
path: "monitor-step",
description:
"A single monitor step defining a check target, request configuration, and criteria for determining status.",
category: "Monitor",
},
{
name: "Recurring",
path: "recurring",
description:
"Object describing a recurring interval schedule (e.g., every 5 minutes, daily).",
},
{
name: "RestrictionTimes",
path: "restriction-times",
description:
"Object describing on-call duty time restrictions (daily or weekly windows).",
},
{
name: "MonitorCriteria",
path: "monitor-criteria",
description:
"A collection of monitor criteria instances used to evaluate monitor check results.",
category: "Monitor",
},
{
name: "PositiveNumber",
path: "positive-number",
description: "A number type that must be greater than zero.",
columnTypeAliases: ["Small Positive Number", "Big Positive Number"],
},
{
name: "MonitorCriteriaInstance",
path: "monitor-criteria-instance",
description:
"A single criteria rule defining conditions and the resulting monitor status when conditions are met.",
category: "Monitor",
},
{
name: "NotEqual",
path: "not-equal",
description:
"A query filter that matches objects where a field is not equal to the specified value.",
},
{
name: "Email",
path: "email",
description: "An email address type with built-in format validation.",
},
{
name: "Phone",
path: "phone",
description: "A phone number type with built-in format validation.",
},
{
name: "Color",
path: "color",
description:
"A color value represented as a hex string (e.g., #3498db).",
},
{
name: "Domain",
path: "domain",
description: "A domain name type (e.g., example.com).",
},
{
name: "Version",
path: "version",
description: "A semantic version type (e.g., 1.0.0).",
},
{
name: "IP",
path: "ip",
description:
"An IP address type supporting both IPv4 and IPv6 formats.",
},
{
name: "Route",
path: "route",
description: "A URL route/path segment type.",
},
{
name: "URL",
path: "url",
description: "A full URL type with protocol, host, and path.",
},
{
name: "Permission",
path: "permission",
description:
"A string identifier representing an access control permission in OneUptime.",
},
{
name: "Search",
path: "search",
description:
"A query filter for text search that matches objects containing the specified string.",
},
{
name: "GreaterThan",
path: "greater-than",
description:
"A query filter that matches objects where a field is greater than the specified value.",
},
{
name: "GreaterThanOrEqual",
path: "greater-than-or-equal",
description:
"A query filter that matches objects where a field is greater than or equal to the specified value.",
},
{
name: "GreaterThanOrNull",
path: "greater-than-or-null",
description:
"A query filter that matches objects where a field is greater than the specified value or is null.",
},
{
name: "LessThanOrNull",
path: "less-than-or-null",
description:
"A query filter that matches objects where a field is less than the specified value or is null.",
},
{
name: "LessThan",
path: "less-than",
description:
"A query filter that matches objects where a field is less than the specified value.",
},
{
name: "LessThanOrEqual",
path: "less-than-or-equal",
description:
"A query filter that matches objects where a field is less than or equal to the specified value.",
},
{
name: "Port",
path: "port",
description: "A network port number type (1-65535).",
},
{
name: "Hostname",
path: "hostname",
description: "A hostname type (e.g., api.example.com).",
},
{
name: "HashedString",
path: "hashed-string",
description:
"A string that is stored in hashed form. Used for sensitive data like passwords and API keys.",
},
{
name: "DateTime",
path: "date-time",
description:
"An ISO 8601 date-time string (e.g., 2024-01-15T10:30:00.000Z).",
columnTypeAliases: ["Date"],
},
{
name: "Buffer",
path: "buffer",
description:
"A binary data buffer, typically base64-encoded when serialized to JSON.",
},
{
name: "InBetween",
path: "in-between",
description:
"A query filter that matches objects where a field value is between two specified values (inclusive).",
},
{
name: "NotNull",
path: "not-null",
description:
"A query filter that matches objects where a field is not null.",
},
{
name: "IsNull",
path: "is-null",
description:
"A query filter that matches objects where a field is null.",
},
{
name: "Includes",
path: "includes",
description:
"A query filter that matches objects where a field value is included in the specified array of values.",
},
{
name: "DashboardComponent",
path: "dashboard-component",
description:
"A configuration object for a dashboard component including its type, layout, and settings.",
},
{
name: "DashboardViewConfig",
path: "dashboard-view-config",
description:
"A configuration object for a dashboard view including its components and layout.",
},
{
name: "CriteriaFilter",
path: "criteria-filter",
description:
"A single filter condition within a MonitorCriteriaInstance that defines what to check and how to compare it.",
category: "Monitor",
},
{
name: "CriteriaIncident",
path: "criteria-incident",
description:
"Configuration for an incident that is automatically created when a MonitorCriteriaInstance's conditions are met.",
category: "Monitor",
},
{
name: "CriteriaAlert",
path: "criteria-alert",
description:
"Configuration for an alert that is automatically created when a MonitorCriteriaInstance's conditions are met.",
category: "Monitor",
},
{
name: "CheckOn",
path: "check-on",
description:
"Enum specifying what aspect of a monitor response to evaluate (e.g., response code, response time, body content).",
category: "Monitor",
},
{
name: "FilterType",
path: "filter-type",
description:
"Enum specifying the comparison operator used in a CriteriaFilter (e.g., Equal To, Greater Than, Contains).",
category: "Monitor",
},
{
name: "FilterCondition",
path: "filter-condition",
description:
"Enum specifying how multiple filters are combined: 'All' (AND) or 'Any' (OR).",
category: "Monitor",
},
{
name: "MonitorStepLogMonitor",
path: "monitor-step-log-monitor",
description:
"Configuration for a Log monitor step, defining which logs to query and evaluate.",
category: "Monitor",
},
{
name: "MonitorStepTraceMonitor",
path: "monitor-step-trace-monitor",
description:
"Configuration for a Trace monitor step, defining which spans to query and evaluate.",
category: "Monitor",
},
{
name: "MonitorStepMetricMonitor",
path: "monitor-step-metric-monitor",
description:
"Configuration for a Metric monitor step, defining which metrics to query and evaluate.",
category: "Monitor",
},
{
name: "MonitorStepSnmpMonitor",
path: "monitor-step-snmp-monitor",
description:
"Configuration for an SNMP monitor step, defining the SNMP device connection and OIDs to query.",
category: "Monitor",
},
];
}
public static getDataTypesByCategory(): Array<DataTypeCategory> {
const allTypes: Array<DataTypeDocumentation> = DataTypeUtil.getDataTypes();
const uncategorized: Array<DataTypeDocumentation> = [];
const categoryMap: Dictionary<Array<DataTypeDocumentation>> = {};
const categoryOrder: Array<string> = [];
for (const dt of allTypes) {
if (dt.category) {
if (!categoryMap[dt.category]) {
categoryMap[dt.category] = [];
categoryOrder.push(dt.category);
}
categoryMap[dt.category]!.push(dt);
} else {
uncategorized.push(dt);
}
}
const result: Array<DataTypeCategory> = [];
// Add uncategorized types first under "General"
if (uncategorized.length > 0) {
result.push({ name: "General", types: uncategorized });
}
// Add categorized groups
for (const cat of categoryOrder) {
if (categoryMap[cat]) {
result.push({ name: cat, types: categoryMap[cat]! });
}
}
return result;
}
public static getDataTypeDictionaryByPath(): Dictionary<DataTypeDocumentation> {
const dict: Dictionary<DataTypeDocumentation> = {};
for (const dataType of DataTypeUtil.getDataTypes()) {
dict[dataType.path] = dataType;
}
return dict;
}
/*
* Convert PascalCase name to space-separated display string.
* e.g., "ObjectID" → "Object ID", "MonitorSteps" → "Monitor Steps",
* "HashedString" → "Hashed String", "IP" → "IP"
*/
private static pascalCaseToDisplayString(name: string): string {
return name
.replace(/([a-z])([A-Z])/g, "$1 $2")
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
}
/*
* Build a mapping from column type display strings to data type page paths.
* Automatically derives both PascalCase and display-string variants from each
* data type's name, so adding a new entry to getDataTypes() is all that's needed.
*/
public static getTypeToDocPathMap(): Dictionary<string> {
const map: Dictionary<string> = {};
for (const dt of DataTypeUtil.getDataTypes()) {
// Map PascalCase name: "ObjectID" → "object-id"
map[dt.name] = dt.path;
// Map display string: "Object ID" → "object-id"
const displayName: string = DataTypeUtil.pascalCaseToDisplayString(
dt.name,
);
if (displayName !== dt.name) {
map[displayName] = dt.path;
}
// Map any explicit aliases (for edge cases like enum "Date" → "date-time")
if (dt.columnTypeAliases) {
for (const alias of dt.columnTypeAliases) {
map[alias] = dt.path;
}
}
}
return map;
}
}

View File

@@ -73,6 +73,7 @@
"ejs": "^3.1.10",
"elkjs": "^0.10.0",
"esbuild": "^0.25.5",
"expo-server-sdk": "^3.15.0",
"express": "^4.21.1",
"formik": "^2.4.6",
"history": "^5.3.0",
@@ -82,6 +83,7 @@
"jsonwebtoken": "^9.0.0",
"jwt-decode": "^4.0.0",
"marked": "^12.0.2",
"mermaid": "^11.12.2",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
"multer": "^2.0.2",
@@ -101,7 +103,7 @@
"react-dropzone": "^14.2.2",
"react-error-boundary": "^4.0.13",
"react-highlight": "^0.15.0",
"react-markdown": "^8.0.3",
"react-markdown": "^9.0.0",
"react-router-dom": "^6.30.1",
"react-select": "^5.4.0",
"react-spinners": "^0.14.1",
@@ -111,7 +113,7 @@
"recharts": "^2.12.7",
"redis-semaphore": "^5.5.1",
"reflect-metadata": "^0.2.2",
"remark-gfm": "^3.0.1",
"remark-gfm": "^4.0.0",
"slackify-markdown": "^4.4.0",
"slugify": "^1.6.5",
"socket.io": "^4.7.4",
@@ -277,6 +279,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz",
"integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
"dev": true,
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.23.5",
@@ -1389,7 +1392,8 @@
"node_modules/@types/node": {
"version": "17.0.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
"peer": true
},
"node_modules/@types/prettier": {
"version": "2.7.3",
@@ -1660,6 +1664,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001565",
"electron-to-chromium": "^1.4.601",
@@ -1921,9 +1926,10 @@
}
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
@@ -4006,6 +4012,7 @@
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",

View File

@@ -0,0 +1,179 @@
<main class="py-12">
<article class="prose">
<!-- Type Hierarchy Breadcrumb -->
<% if (pageData.typeHierarchy && pageData.typeHierarchy.length > 0) { %>
<nav class="mb-6">
<ol class="flex items-center flex-wrap gap-1 text-sm">
<% for (var h = 0; h < pageData.typeHierarchy.length; h++) { %>
<% if (h > 0) { %>
<li class="text-slate-400">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
</li>
<% } %>
<% if (pageData.typeHierarchy[h].path && pageData.typeHierarchy[h].name !== pageData.title) { %>
<li><a href="/reference/<%= pageData.typeHierarchy[h].path %>" class="text-indigo-600 hover:text-indigo-700 hover:underline font-medium"><%= pageData.typeHierarchy[h].name %></a></li>
<% } else { %>
<li class="text-slate-900 font-semibold"><%= pageData.typeHierarchy[h].name %></li>
<% } %>
<% } %>
</ol>
</nav>
<% } %>
<!-- Hero Section -->
<div class="mb-8">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-xl bg-emerald-600 shadow-lg shadow-emerald-500/30">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
</svg>
</div>
<span class="text-xs font-semibold text-emerald-600 uppercase tracking-wider"><%= pageData.isEnum ? 'Enum' : 'Data Type' %></span>
</div>
<h1 class="font-bold text-3xl text-slate-900 tracking-tight mb-3"><%= pageData.title %></h1>
<p class="text-lg text-slate-600 leading-relaxed max-w-2xl"><%- pageData.description %></p>
</div>
<!-- At a Glance Summary Box -->
<div class="mb-10 rounded-xl border border-slate-200 bg-slate-50 p-5">
<h4 class="text-xs font-semibold text-slate-500 uppercase tracking-wider mb-3">At a Glance</h4>
<div class="flex flex-wrap gap-x-8 gap-y-3 text-sm">
<div>
<span class="text-slate-500">Kind</span>
<span class="ml-2 font-medium text-slate-900"><%= pageData.isEnum ? 'Enum' : 'Data Type' %></span>
</div>
<% if (pageData.isEnum && pageData.valueCount > 0) { %>
<div>
<span class="text-slate-500">Values</span>
<span class="ml-2 font-medium text-slate-900"><%= pageData.valueCount %></span>
</div>
<% } else if (pageData.propertyCount > 0) { %>
<div>
<span class="text-slate-500">Properties</span>
<span class="ml-2 font-medium text-slate-900"><%= pageData.propertyCount %></span>
</div>
<% } %>
<div>
<span class="text-slate-500">JSON Format</span>
<code class="ml-2 text-xs font-mono bg-white px-2 py-0.5 rounded border border-slate-200 text-slate-700">{"_type": "<%= pageData.jsonWrapperType %>", "value": ...}</code>
</div>
</div>
</div>
<% if (pageData.isEnum) { %>
<!-- Quick Navigation for Enum Values -->
<% if (pageData.values.length >= 4) { %>
<div class="mb-6">
<div class="flex flex-wrap gap-1.5">
<% for (var qv = 0; qv < pageData.values.length; qv++) { %>
<a href="#value-<%= pageData.values[qv].value.toLowerCase().replace(/\s+/g, '-') %>" class="rounded-md bg-white px-2.5 py-1 text-xs font-medium text-slate-600 ring-1 ring-inset ring-slate-200 hover:bg-slate-50 hover:text-slate-900 transition-colors no-underline"><%= pageData.values[qv].value %></a>
<% } %>
</div>
</div>
<% } %>
<h3 id="values" class="text-base font-semibold text-slate-800 mb-4 scroll-mt-24">Possible Values</h3>
<div class="my-6 rounded-xl border border-slate-200 bg-white overflow-hidden">
<ul role="list" class="m-0 w-full list-none divide-y divide-slate-100 p-0">
<% for (var v = 0; v < pageData.values.length; v++) { %>
<li id="value-<%= pageData.values[v].value.toLowerCase().replace(/\s+/g, '-') %>" class="m-0 px-5 py-5 hover:bg-slate-50/50 transition-colors scroll-mt-24">
<dl class="m-0 flex flex-wrap items-start gap-x-3 gap-y-2">
<dt class="sr-only">Index</dt>
<dd class="text-xs font-mono text-slate-300 w-6 pt-0.5 flex-shrink-0"><%= v + 1 %>.</dd>
<dt class="sr-only">Value</dt>
<dd><code class="model-inline-code"><%= pageData.values[v].value %></code></dd>
<dt class="sr-only">Description</dt>
<dd class="w-full flex-none pl-9 text-sm text-slate-600"><%- pageData.values[v].description %></dd>
</dl>
</li>
<% } %>
</ul>
</div>
<% } else if (pageData.properties && pageData.properties.length > 0) { %>
<!-- Quick Navigation for Properties -->
<% if (pageData.properties.length >= 4) { %>
<div class="mb-6">
<div class="flex flex-wrap gap-1.5">
<% for (var qp = 0; qp < pageData.properties.length; qp++) { %>
<a href="#prop-<%= pageData.properties[qp].name %>" class="rounded-md bg-white px-2.5 py-1 text-xs font-medium text-slate-600 ring-1 ring-inset ring-slate-200 hover:bg-slate-50 hover:text-slate-900 transition-colors no-underline"><%= pageData.properties[qp].name %></a>
<% } %>
</div>
</div>
<% } %>
<h3 id="properties" class="text-base font-semibold text-slate-800 mb-4 scroll-mt-24">Properties</h3>
<div class="my-6 rounded-xl border border-slate-200 bg-white overflow-hidden">
<ul role="list" class="m-0 w-full list-none divide-y divide-slate-100 p-0">
<% for (var p = 0; p < pageData.properties.length; p++) { %>
<li id="prop-<%= pageData.properties[p].name %>" class="m-0 px-5 py-5 hover:bg-slate-50/50 transition-colors scroll-mt-24">
<div class="mb-1.5">
<code class="text-sm font-semibold text-slate-900"><%= pageData.properties[p].name %></code>
<% if (pageData.properties[p].required) { %>
<span class="ml-2 inline-flex items-center rounded-full bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-600/20">Required</span>
<% } %>
</div>
<div class="mb-2">
<span class="inline-flex items-center rounded-md bg-slate-100 px-2 py-0.5 text-xs font-mono text-slate-600">
<% if (pageData.properties[p].typeLinks && pageData.properties[p].typeLinks.length > 0) { %>
<% var typeLinks = pageData.properties[p].typeLinks; %>
<% for (var tl = 0; tl < typeLinks.length; tl++) { %>
<% if (typeLinks[tl].path) { %>
<a href="/reference/<%= typeLinks[tl].path %>" class="text-indigo-600 hover:text-indigo-700 hover:underline font-medium"><%= typeLinks[tl].label %></a>
<% } else { %>
<%= typeLinks[tl].label %>
<% } %>
<% } %>
<% } else { %>
<%= pageData.properties[p].type %>
<% } %>
</span>
</div>
<p class="m-0 text-sm text-slate-600 leading-relaxed"><%- pageData.properties[p].description %></p>
</li>
<% } %>
</ul>
</div>
<% } %>
<!-- JSON Example Section -->
<div class="border-t border-slate-200 pt-8 mt-10">
<h3 id="example" class="text-base font-semibold text-slate-800 mb-4 scroll-mt-24">JSON Example</h3>
<%- include('../partials/code', { title: "JSON", code: pageData.jsonExample, requestType: "", requestUrl: "" }) %>
</div>
<% if (pageData.title === "Permission") { %>
<div class="mt-6 rounded-lg border border-indigo-100 bg-indigo-50 p-4">
<p class="text-sm text-indigo-800 m-0">
For a complete list of all available permissions and their descriptions, see the
<a href="/reference/permissions" class="font-medium text-indigo-600 hover:text-indigo-700 hover:underline">Permissions guide</a>.
</p>
</div>
<% } %>
<!-- Related Types Section -->
<% if (pageData.relatedTypes && pageData.relatedTypes.length > 0) { %>
<div class="border-t border-slate-200 pt-8 mt-10">
<h3 id="related-types" class="text-base font-semibold text-slate-800 mb-4 scroll-mt-24">Related Types</h3>
<div class="my-6 grid grid-cols-1 sm:grid-cols-2 gap-3">
<% for (var r = 0; r < pageData.relatedTypes.length; r++) { %>
<a href="/reference/<%= pageData.relatedTypes[r].path %>" class="group flex items-start gap-3 rounded-xl border border-slate-200 bg-white p-5 hover:border-indigo-300 hover:shadow-sm transition-all no-underline">
<div class="flex-shrink-0 mt-0.5">
<div class="flex items-center justify-center w-8 h-8 rounded-lg bg-indigo-50 group-hover:bg-indigo-100 transition-colors">
<svg class="w-4 h-4 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"></path></svg>
</div>
</div>
<div>
<div class="text-sm font-semibold text-slate-900 group-hover:text-indigo-600 transition-colors"><%= pageData.relatedTypes[r].name %></div>
<div class="text-xs text-slate-500 mt-0.5"><%= pageData.relatedTypes[r].relationship %></div>
<% if (pageData.relatedTypes[r].description) { %>
<div class="text-xs text-slate-400 mt-1 line-clamp-2"><%= pageData.relatedTypes[r].description %></div>
<% } %>
</div>
</a>
<% } %>
</div>
</div>
<% } %>
</article>
</main>

View File

@@ -47,7 +47,13 @@
<dd><code class="model-inline-code"><%= Object.keys(pageData.columns)[i] -%></code></dd>
<dt class="sr-only">Type</dt>
<dd class="font-mono text-xs text-slate-500">
<%= pageData.columns[Object.keys(pageData.columns)[i]].type -%>
<% if(pageData.columns[Object.keys(pageData.columns)[i]].modelDocumentationPath) { %>
<a href="/reference/<%= pageData.columns[Object.keys(pageData.columns)[i]].modelDocumentationPath -%>" class="text-indigo-600 hover:text-indigo-700 hover:underline font-medium"><%= pageData.columns[Object.keys(pageData.columns)[i]].modelName -%></a>
<% } else if(pageData.columns[Object.keys(pageData.columns)[i]].typeDocumentationPath) { %>
<a href="/reference/<%= pageData.columns[Object.keys(pageData.columns)[i]].typeDocumentationPath -%>" class="text-indigo-600 hover:text-indigo-700 hover:underline font-medium"><%= pageData.columns[Object.keys(pageData.columns)[i]].type -%></a>
<% } else { %>
<%= pageData.columns[Object.keys(pageData.columns)[i]].type -%>
<% } %>
<% if(pageData.columns[Object.keys(pageData.columns)[i]].required){ %>
<span class="ml-1.5 inline-flex items-center rounded-full bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-600/20">Required</span>
<% } %>

View File

@@ -14,23 +14,49 @@
<p class="text-lg text-slate-600 leading-relaxed max-w-2xl">Your API Token needs permissions to create, update, read or delete any resource. If you do not have permissions to make a request a <code class="inline-code">4xx</code> status will be sent as response. You can manage permissions for your API Key in Project Settings > API Keys.</p>
</div>
<h2 id="consuming-webhooks" class="scroll-mt-24 text-xl font-semibold text-slate-900 mb-6 mt-12">
Permissions List
</h2>
<p class="text-slate-600 leading-relaxed mb-6">Here is a list of all the permissions:</p>
<div class="rounded-xl border border-slate-200 bg-white overflow-hidden">
<ul role="list" class="m-0 divide-y divide-slate-100 p-0">
<% for(var i=0; i<pageData.permissions.length; i++) {%>
<li class="m-0 px-5 py-4 hover:bg-slate-50/50 transition-colors">
<dl class="m-0 flex flex-wrap items-center gap-x-3 gap-y-2">
<dd><code class="inline-code"><%= pageData.permissions[i].permission -%></code></dd>
<dd class="font-mono text-xs text-slate-500"><%= pageData.permissions[i].title -%></dd>
<dd class="w-full flex-none text-sm text-slate-600 mt-1"><%= pageData.permissions[i].description -%></dd>
</dl>
</li>
<% } %>
</ul>
<!-- Quick Navigation -->
<div class="my-6 flex gap-3 rounded-xl border border-indigo-500/20 bg-indigo-50/50 p-4">
<div class="flex-shrink-0">
<svg viewBox="0 0 16 16" aria-hidden="true" class="h-5 w-5 fill-indigo-500 stroke-white">
<circle cx="8" cy="8" r="8" stroke-width="0"></circle>
<path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.75 7.75h1.5v3.5"></path>
<circle cx="8" cy="4" r=".5" fill="none"></circle>
</svg>
</div>
<div>
<p class="text-sm font-medium text-indigo-900 mb-2">Jump to a category</p>
<div class="flex flex-wrap gap-2">
<% for(var g=0; g<pageData.permissionGroups.length; g++) { %>
<a href="#<%= pageData.permissionGroups[g].group.toLowerCase().replace(/ /g, '-') -%>"
class="inline-flex items-center gap-1.5 rounded-md bg-white px-2.5 py-1 text-xs font-medium text-slate-700 ring-1 ring-inset ring-slate-200 hover:bg-indigo-50 hover:text-indigo-700 hover:ring-indigo-200 transition-colors">
<%= pageData.permissionGroups[g].group %>
<span class="text-slate-400">(<%= pageData.permissionGroups[g].permissions.length %>)</span>
</a>
<% } %>
</div>
</div>
</div>
<% for(var g=0; g<pageData.permissionGroups.length; g++) { %>
<h2 id="<%= pageData.permissionGroups[g].group.toLowerCase().replace(/ /g, '-') -%>"
class="scroll-mt-24 text-xl font-semibold text-slate-900 mb-4 mt-12 <%= g > 0 ? 'pt-8 border-t border-slate-200' : '' %>">
<%= pageData.permissionGroups[g].group %>
<span class="ml-2 align-middle inline-flex items-center rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-medium text-slate-600"><%= pageData.permissionGroups[g].permissions.length %></span>
</h2>
<div class="rounded-xl border border-slate-200 bg-white overflow-hidden">
<ul role="list" class="m-0 list-none divide-y divide-slate-100 p-0">
<% for(var i=0; i<pageData.permissionGroups[g].permissions.length; i++) { %>
<li class="m-0 px-5 py-4 hover:bg-slate-50/50 transition-colors">
<dl class="m-0 flex flex-wrap items-center gap-x-3 gap-y-2">
<dd><code class="inline-code"><%= pageData.permissionGroups[g].permissions[i].permission -%></code></dd>
<dd class="font-mono text-xs text-slate-500"><%= pageData.permissionGroups[g].permissions[i].title -%></dd>
<dd class="w-full flex-none text-sm text-slate-600 mt-1"><%= pageData.permissionGroups[g].permissions[i].description -%></dd>
</dl>
</li>
<% } %>
</ul>
</div>
<% } %>
</article>
</main>
</main>

View File

@@ -406,6 +406,52 @@
</ul>
</div>
</li>
<% if (typeof dataTypes !== 'undefined' && dataTypes && dataTypes.length > 0) { %>
<%
// Group data types by category
var _dtGeneral = [];
var _dtCategories = {};
var _dtCatOrder = [];
for (var _di = 0; _di < dataTypes.length; _di++) {
var _dt = dataTypes[_di];
if (_dt.category) {
if (!_dtCategories[_dt.category]) {
_dtCategories[_dt.category] = [];
_dtCatOrder.push(_dt.category);
}
_dtCategories[_dt.category].push(_dt);
} else {
_dtGeneral.push(_dt);
}
}
%>
<li class="relative mt-6">
<h6 class="text-xs font-semibold text-slate-900 uppercase tracking-wide">Data Types</h6>
<div class="relative mt-3 pl-2">
<div class="absolute inset-y-0 left-2 w-px bg-slate-200"></div>
<ul role="list" class="border-l border-transparent space-y-1">
<% for(var i=0; i<_dtGeneral.length; i++) {%>
<li class="relative"><a
class="nav-link flex justify-between gap-2 py-1.5 pr-3 text-sm transition pl-4 text-slate-600 hover:text-slate-900 -ml-px border-l-2 border-transparent hover:border-slate-300"
href="/reference/<%= _dtGeneral[i].path -%>"><span class="truncate"><%= _dtGeneral[i].name -%></span></a></li>
<% } %>
</ul>
<% for (var _ci = 0; _ci < _dtCatOrder.length; _ci++) { %>
<% var _catName = _dtCatOrder[_ci]; var _catTypes = _dtCategories[_catName]; %>
<div class="mt-3 mb-1 pl-4">
<span class="text-[10px] font-semibold text-slate-400 uppercase tracking-wider"><%= _catName %></span>
</div>
<ul role="list" class="border-l border-transparent space-y-1">
<% for(var _ti=0; _ti<_catTypes.length; _ti++) {%>
<li class="relative"><a
class="nav-link flex justify-between gap-2 py-1.5 pr-3 text-sm transition pl-4 text-slate-600 hover:text-slate-900 -ml-px border-l-2 border-transparent hover:border-slate-300"
href="/reference/<%= _catTypes[_ti].path -%>"><span class="truncate"><%= _catTypes[_ti].name -%></span></a></li>
<% } %>
</ul>
<% } %>
</div>
</li>
<% } %>
<li class="sticky bottom-0 z-10 mt-6 min-[416px]:hidden"><a
class="inline-flex gap-0.5 justify-center overflow-hidden text-sm font-medium transition rounded-full bg-indigo-600 py-1.5 px-4 text-white hover:bg-indigo-700 shadow-sm w-full"
href="/#">Sign in</a></li>
@@ -537,6 +583,45 @@
<% } %>
</ul>
</li>
<% if (typeof dataTypes !== 'undefined' && dataTypes && dataTypes.length > 0) { %>
<%
// Group data types by category for mobile nav
var _mGeneral = [];
var _mCategories = {};
var _mCatOrder = [];
for (var _mi = 0; _mi < dataTypes.length; _mi++) {
var _mdt = dataTypes[_mi];
if (_mdt.category) {
if (!_mCategories[_mdt.category]) {
_mCategories[_mdt.category] = [];
_mCatOrder.push(_mdt.category);
}
_mCategories[_mdt.category].push(_mdt);
} else {
_mGeneral.push(_mdt);
}
}
%>
<li class="relative">
<h6 class="text-xs font-semibold text-slate-900 uppercase tracking-wide mb-3">Data Types</h6>
<ul role="list" class="space-y-1 border-l border-slate-200 ml-2">
<% for(var i=0; i<_mGeneral.length; i++) {%>
<li><a class="mobile-nav-link block py-2 pl-4 text-sm text-slate-600 hover:text-slate-900 border-l-2 border-transparent hover:border-slate-300 -ml-px transition truncate" href="/reference/<%= _mGeneral[i].path -%>"><%= _mGeneral[i].name -%></a></li>
<% } %>
</ul>
<% for (var _mci = 0; _mci < _mCatOrder.length; _mci++) { %>
<% var _mCatName = _mCatOrder[_mci]; var _mCatTypes = _mCategories[_mCatName]; %>
<div class="mt-3 mb-1 ml-4">
<span class="text-[10px] font-semibold text-slate-400 uppercase tracking-wider"><%= _mCatName %></span>
</div>
<ul role="list" class="space-y-1 border-l border-slate-200 ml-2">
<% for(var _mti=0; _mti<_mCatTypes.length; _mti++) {%>
<li><a class="mobile-nav-link block py-2 pl-4 text-sm text-slate-600 hover:text-slate-900 border-l-2 border-transparent hover:border-slate-300 -ml-px transition truncate" href="/reference/<%= _mCatTypes[_mti].path -%>"><%= _mCatTypes[_mti].name -%></a></li>
<% } %>
</ul>
<% } %>
</li>
<% } %>
</ul>
</nav>

View File

@@ -77,6 +77,7 @@
"ejs": "^3.1.10",
"elkjs": "^0.10.0",
"esbuild": "^0.25.5",
"expo-server-sdk": "^3.15.0",
"express": "^4.21.1",
"formik": "^2.4.6",
"history": "^5.3.0",
@@ -86,6 +87,7 @@
"jsonwebtoken": "^9.0.0",
"jwt-decode": "^4.0.0",
"marked": "^12.0.2",
"mermaid": "^11.12.2",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
"multer": "^2.0.2",
@@ -105,7 +107,7 @@
"react-dropzone": "^14.2.2",
"react-error-boundary": "^4.0.13",
"react-highlight": "^0.15.0",
"react-markdown": "^8.0.3",
"react-markdown": "^9.0.0",
"react-router-dom": "^6.30.1",
"react-select": "^5.4.0",
"react-spinners": "^0.14.1",
@@ -115,7 +117,7 @@
"recharts": "^2.12.7",
"redis-semaphore": "^5.5.1",
"reflect-metadata": "^0.2.2",
"remark-gfm": "^3.0.1",
"remark-gfm": "^4.0.0",
"slackify-markdown": "^4.4.0",
"slugify": "^1.6.5",
"socket.io": "^4.7.4",
@@ -658,10 +660,11 @@
}
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}

View File

@@ -32,6 +32,7 @@ import Reseller from "Common/Models/DatabaseModels/Reseller";
import User from "Common/Models/DatabaseModels/User";
import React, { useState } from "react";
import useAsyncEffect from "use-async-effect";
import { IsBillingEnabled } from "Common/Server/EnvironmentConfig";
const RegisterPage: () => JSX.Element = () => {
const apiUrl: URL = SIGNUP_API_URL;
@@ -172,6 +173,36 @@ const RegisterPage: () => JSX.Element = () => {
}
}
if (!BILLING_ENABLED) {
formFields = formFields.concat([
{
overrideField: {
selfHostedCompanyName: true,
},
overrideFieldKey: "selfHostedCompanyName",
fieldType: FormFieldSchemaType.Text,
placeholder: "Acme, Inc.",
required: false,
title: "Company Name",
dataTestId: "selfHostedCompanyName",
showEvenIfPermissionDoesNotExist: true,
disableSpellCheck: true,
},
{
overrideField: {
selfHostedPhoneNumber: true,
},
overrideFieldKey: "selfHostedPhoneNumber",
fieldType: FormFieldSchemaType.Phone,
required: false,
placeholder: "+11234567890",
title: "Phone Number",
dataTestId: "selfHostedPhoneNumber",
showEvenIfPermissionDoesNotExist: true,
},
]);
}
formFields = formFields.concat([
{
field: {
@@ -206,6 +237,25 @@ const RegisterPage: () => JSX.Element = () => {
},
]);
if (!IsBillingEnabled) {
formFields = formFields.concat([
{
overrideField: {
notifySelfHosted: true,
},
overrideFieldKey: "notifySelfHosted",
fieldType: FormFieldSchemaType.Checkbox,
required: false,
defaultValue: true,
title: "Notify me about security patches and new releases",
dataTestId: "notifySelfHosted",
showEvenIfPermissionDoesNotExist: true,
spanFullRow: true,
},
]);
}
if (isCaptchaEnabled) {
formFields = formFields.concat([
{
@@ -330,6 +380,7 @@ const RegisterPage: () => JSX.Element = () => {
if (value && value.email) {
UiAnalytics.userAuth(value.email);
UiAnalytics.capture("accounts/register");
UiAnalytics.capture("sign_up");
}
LoginUtil.login({

View File

@@ -76,6 +76,7 @@
"ejs": "^3.1.10",
"elkjs": "^0.10.0",
"esbuild": "^0.25.5",
"expo-server-sdk": "^3.15.0",
"express": "^4.21.1",
"formik": "^2.4.6",
"history": "^5.3.0",
@@ -85,6 +86,7 @@
"jsonwebtoken": "^9.0.0",
"jwt-decode": "^4.0.0",
"marked": "^12.0.2",
"mermaid": "^11.12.2",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
"multer": "^2.0.2",
@@ -104,7 +106,7 @@
"react-dropzone": "^14.2.2",
"react-error-boundary": "^4.0.13",
"react-highlight": "^0.15.0",
"react-markdown": "^8.0.3",
"react-markdown": "^9.0.0",
"react-router-dom": "^6.30.1",
"react-select": "^5.4.0",
"react-spinners": "^0.14.1",
@@ -114,7 +116,7 @@
"recharts": "^2.12.7",
"redis-semaphore": "^5.5.1",
"reflect-metadata": "^0.2.2",
"remark-gfm": "^3.0.1",
"remark-gfm": "^4.0.0",
"slackify-markdown": "^4.4.0",
"slugify": "^1.6.5",
"socket.io": "^4.7.4",
@@ -577,10 +579,11 @@
}
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}

View File

@@ -4,6 +4,7 @@ import Logout from "./Pages/Logout/Logout";
import Projects from "./Pages/Projects/Index";
import SettingsAPIKey from "./Pages/Settings/APIKey/Index";
import SettingsAuthentication from "./Pages/Settings/Authentication/Index";
import SettingsDataRetention from "./Pages/Settings/DataRetention/Index";
import SettingsCallSMS from "./Pages/Settings/CallSMS/Index";
import SettingsWhatsApp from "./Pages/Settings/WhatsApp/Index";
// Settings Pages.
@@ -143,6 +144,11 @@ const App: () => JSX.Element = () => {
path={RouteMap[PageMap.SETTINGS_API_KEY]?.toString() || ""}
element={<SettingsAPIKey />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_DATA_RETENTION]?.toString() || ""}
element={<SettingsDataRetention />}
/>
</Routes>
</MasterPage>
);

View File

@@ -12,7 +12,6 @@ import Toggle from "Common/UI/Components/Toggle/Toggle";
import FieldType from "Common/UI/Components/Types/FieldType";
import { BILLING_ENABLED, getAllEnvVars } from "Common/UI/Config";
import { GetReactElementFunction } from "Common/UI/Types/FunctionTypes";
import Navigation from "Common/UI/Utils/Navigation";
import Project from "Common/Models/DatabaseModels/Project";
import User from "Common/Models/DatabaseModels/User";
import React, {
@@ -21,6 +20,7 @@ import React, {
useEffect,
useState,
} from "react";
import Navigation from "Common/UI/Utils/Navigation";
const Projects: FunctionComponent = (): ReactElement => {
const [isSubscriptionPlanYearly, setIsSubscriptionPlanYearly] =

View File

@@ -1,3 +1,4 @@
import AdminModelAPI from "../../../Utils/ModelAPI";
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
@@ -17,6 +18,7 @@ const DeletePage: FunctionComponent = (): ReactElement => {
modelId={modelId}
modelNameField="name"
modelType={Project}
modelAPI={AdminModelAPI}
title={"Project"}
breadcrumbLinks={[
{
@@ -41,6 +43,7 @@ const DeletePage: FunctionComponent = (): ReactElement => {
<ModelDelete
modelType={Project}
modelId={modelId}
modelAPI={AdminModelAPI}
onDeleteSuccess={() => {
Navigation.navigate(RouteMap[PageMap.PROJECTS] as Route);
}}

View File

@@ -1,3 +1,4 @@
import AdminModelAPI from "../../../Utils/ModelAPI";
import ObjectID from "Common/Types/ObjectID";
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
@@ -19,6 +20,7 @@ const Projects: FunctionComponent = (): ReactElement => {
modelId={modelId}
modelNameField="name"
modelType={Project}
modelAPI={AdminModelAPI}
title={"Project"}
breadcrumbLinks={[
{
@@ -43,6 +45,7 @@ const Projects: FunctionComponent = (): ReactElement => {
<div>
<CardModelDetail<Project>
name="Project"
modelAPI={AdminModelAPI}
cardProps={{
title: "Project",
description: "Project details",

View File

@@ -0,0 +1,85 @@
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import DashboardSideMenu from "../SideMenu";
import Route from "Common/Types/API/Route";
import ObjectID from "Common/Types/ObjectID";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "Common/UI/Components/ModelDetail/CardModelDetail";
import Page from "Common/UI/Components/Page/Page";
import FieldType from "Common/UI/Components/Types/FieldType";
import GlobalConfig from "Common/Models/DatabaseModels/GlobalConfig";
import React, { FunctionComponent, ReactElement } from "react";
const Settings: FunctionComponent = (): ReactElement => {
return (
<Page
title={"Admin Settings"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
},
{
title: "Settings",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route,
),
},
{
title: "Data Retention",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_DATA_RETENTION] as Route,
),
},
]}
sideMenu={<DashboardSideMenu />}
>
<CardModelDetail
name="Monitor Log Retention Settings"
cardProps={{
title: "Monitor Log Retention",
description:
"Configure how long monitor logs are retained before being automatically deleted.",
}}
isEditable={true}
editButtonText="Edit Settings"
formFields={[
{
field: {
monitorLogRetentionInDays: true,
},
title: "Monitor Log Retention (Days)",
fieldType: FormFieldSchemaType.PositiveNumber,
required: false,
description:
"Number of days to retain monitor logs. Monitor logs older than this will be automatically deleted. Default is 1 day if not set. Minimum: 1 day, Maximum: 365 days.",
validation: {
minValue: 1,
maxValue: 365,
},
placeholder: "1",
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config-data-retention",
fields: [
{
field: {
monitorLogRetentionInDays: true,
},
fieldType: FieldType.Number,
title: "Monitor Log Retention (Days)",
placeholder: "1 (default)",
description:
"Number of days to retain monitor logs. Monitor logs older than this will be automatically deleted.",
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
</Page>
);
};
export default Settings;

View File

@@ -72,6 +72,17 @@ const DashboardSideMenu: () => JSX.Element = (): ReactElement => {
icon={IconProp.Signal}
/>
</SideMenuSection>
<SideMenuSection title="Data Retention">
<SideMenuItem
link={{
title: "Data Retention",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_DATA_RETENTION] as Route,
),
}}
icon={IconProp.Database}
/>
</SideMenuSection>
<SideMenuSection title="AI">
<SideMenuItem
link={{

View File

@@ -1,3 +1,4 @@
import AdminModelAPI from "../../../Utils/ModelAPI";
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
@@ -17,6 +18,7 @@ const DeletePage: FunctionComponent = (): ReactElement => {
modelId={modelId}
modelNameField="email"
modelType={User}
modelAPI={AdminModelAPI}
title={"User"}
breadcrumbLinks={[
{
@@ -39,6 +41,7 @@ const DeletePage: FunctionComponent = (): ReactElement => {
<ModelDelete
modelType={User}
modelId={modelId}
modelAPI={AdminModelAPI}
onDeleteSuccess={() => {
Navigation.navigate(RouteMap[PageMap.USERS] as Route);
}}

View File

@@ -1,3 +1,4 @@
import AdminModelAPI from "../../../Utils/ModelAPI";
import ObjectID from "Common/Types/ObjectID";
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
@@ -19,6 +20,7 @@ const Users: FunctionComponent = (): ReactElement => {
modelId={modelId}
modelNameField="email"
modelType={User}
modelAPI={AdminModelAPI}
title={"User"}
breadcrumbLinks={[
{
@@ -41,6 +43,7 @@ const Users: FunctionComponent = (): ReactElement => {
<div>
<CardModelDetail<User>
name="User"
modelAPI={AdminModelAPI}
cardProps={{
title: "User",
description: "User details",

View File

@@ -1,3 +1,4 @@
import AdminModelAPI from "../../../Utils/ModelAPI";
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
@@ -19,6 +20,7 @@ const UserSettings: FunctionComponent = (): ReactElement => {
modelId={modelId}
modelNameField="email"
modelType={User}
modelAPI={AdminModelAPI}
title={"User"}
breadcrumbLinks={[
{
@@ -52,6 +54,7 @@ const UserSettings: FunctionComponent = (): ReactElement => {
>
<CardModelDetail<User>
name="user-master-admin-settings"
modelAPI={AdminModelAPI}
cardProps={{
title: "Master Admin Access",
description:

View File

@@ -22,6 +22,7 @@ enum PageMap {
SETTINGS_LLM_PROVIDERS = "SETTINGS_LLM_PROVIDERS",
SETTINGS_AUTHENTICATION = "SETTINGS_AUTHENTICATION",
SETTINGS_API_KEY = "SETTINGS_API_KEY",
SETTINGS_DATA_RETENTION = "SETTINGS_DATA_RETENTION",
}
export default PageMap;

View File

@@ -36,6 +36,9 @@ const RouteMap: Dictionary<Route> = {
`/admin/settings/authentication`,
),
[PageMap.SETTINGS_API_KEY]: new Route(`/admin/settings/api-key`),
[PageMap.SETTINGS_DATA_RETENTION]: new Route(
`/admin/settings/data-retention`,
),
};
export class RouteUtil {

View File

@@ -23,6 +23,7 @@ import WhatsAppLogAPI from "./WhatsAppLogAPI";
// Import API
import ResellerPlanAPI from "Common/Server/API/ResellerPlanAPI";
import EnterpriseLicenseAPI from "Common/Server/API/EnterpriseLicenseAPI";
import OpenSourceDeploymentAPI from "Common/Server/API/OpenSourceDeploymentAPI";
import MonitorAPI from "Common/Server/API/MonitorAPI";
import ShortLinkAPI from "Common/Server/API/ShortLinkAPI";
import StatusPageAPI from "Common/Server/API/StatusPageAPI";
@@ -35,9 +36,11 @@ import UserWebAuthnAPI from "Common/Server/API/UserWebAuthnAPI";
import MonitorTest from "Common/Models/DatabaseModels/MonitorTest";
import IncidentInternalNoteAPI from "Common/Server/API/IncidentInternalNoteAPI";
import IncidentPublicNoteAPI from "Common/Server/API/IncidentPublicNoteAPI";
import IncidentEpisodePublicNoteAPI from "Common/Server/API/IncidentEpisodePublicNoteAPI";
import ScheduledMaintenanceInternalNoteAPI from "Common/Server/API/ScheduledMaintenanceInternalNoteAPI";
import ScheduledMaintenancePublicNoteAPI from "Common/Server/API/ScheduledMaintenancePublicNoteAPI";
import IncidentAPI from "Common/Server/API/IncidentAPI";
import IncidentEpisodeAPI from "Common/Server/API/IncidentEpisodeAPI";
import ScheduledMaintenanceAPI from "Common/Server/API/ScheduledMaintenanceAPI";
import AlertAPI from "Common/Server/API/AlertAPI";
// User Notification methods.
@@ -106,6 +109,70 @@ import AlertStateTimelineService, {
Service as AlertStateTimelineServiceType,
} from "Common/Server/Services/AlertStateTimelineService";
// AlertEpisode Services
import AlertEpisodeService, {
Service as AlertEpisodeServiceType,
} from "Common/Server/Services/AlertEpisodeService";
import AlertEpisodeFeedService, {
Service as AlertEpisodeFeedServiceType,
} from "Common/Server/Services/AlertEpisodeFeedService";
import AlertEpisodeInternalNoteService, {
Service as AlertEpisodeInternalNoteServiceType,
} from "Common/Server/Services/AlertEpisodeInternalNoteService";
import AlertEpisodeMemberService, {
Service as AlertEpisodeMemberServiceType,
} from "Common/Server/Services/AlertEpisodeMemberService";
import AlertEpisodeOwnerTeamService, {
Service as AlertEpisodeOwnerTeamServiceType,
} from "Common/Server/Services/AlertEpisodeOwnerTeamService";
import AlertEpisodeOwnerUserService, {
Service as AlertEpisodeOwnerUserServiceType,
} from "Common/Server/Services/AlertEpisodeOwnerUserService";
import AlertEpisodeStateTimelineService, {
Service as AlertEpisodeStateTimelineServiceType,
} from "Common/Server/Services/AlertEpisodeStateTimelineService";
// IncidentEpisode Services
import IncidentEpisodeFeedService, {
Service as IncidentEpisodeFeedServiceType,
} from "Common/Server/Services/IncidentEpisodeFeedService";
import IncidentEpisodeInternalNoteService, {
Service as IncidentEpisodeInternalNoteServiceType,
} from "Common/Server/Services/IncidentEpisodeInternalNoteService";
import IncidentEpisodeMemberService, {
Service as IncidentEpisodeMemberServiceType,
} from "Common/Server/Services/IncidentEpisodeMemberService";
import IncidentEpisodeOwnerTeamService, {
Service as IncidentEpisodeOwnerTeamServiceType,
} from "Common/Server/Services/IncidentEpisodeOwnerTeamService";
import IncidentEpisodeOwnerUserService, {
Service as IncidentEpisodeOwnerUserServiceType,
} from "Common/Server/Services/IncidentEpisodeOwnerUserService";
import IncidentEpisodeStateTimelineService, {
Service as IncidentEpisodeStateTimelineServiceType,
} from "Common/Server/Services/IncidentEpisodeStateTimelineService";
import IncidentEpisodeRoleMemberService, {
Service as IncidentEpisodeRoleMemberServiceType,
} from "Common/Server/Services/IncidentEpisodeRoleMemberService";
import AlertGroupingRuleService, {
Service as AlertGroupingRuleServiceType,
} from "Common/Server/Services/AlertGroupingRuleService";
import IncidentGroupingRuleService, {
Service as IncidentGroupingRuleServiceType,
} from "Common/Server/Services/IncidentGroupingRuleService";
import IncidentSlaService, {
Service as IncidentSlaServiceType,
} from "Common/Server/Services/IncidentSlaService";
import IncidentSlaRuleService, {
Service as IncidentSlaRuleServiceType,
} from "Common/Server/Services/IncidentSlaRuleService";
import IncidentCustomFieldService, {
Service as IncidentCustomFieldServiceType,
} from "Common/Server/Services/IncidentCustomFieldService";
@@ -127,6 +194,12 @@ import IncidentOwnerUserService, {
import IncidentSeverityService, {
Service as IncidentSeverityServiceType,
} from "Common/Server/Services/IncidentSeverityService";
import IncidentRoleService, {
Service as IncidentRoleServiceType,
} from "Common/Server/Services/IncidentRoleService";
import IncidentMemberService, {
Service as IncidentMemberServiceType,
} from "Common/Server/Services/IncidentMemberService";
import IncidentStateService, {
Service as IncidentStateServiceType,
} from "Common/Server/Services/IncidentStateService";
@@ -237,6 +310,9 @@ import OnCallDutyPolicyScheduleService, {
import ProjectCallSMSConfigService, {
Service as ProjectCallSMSConfigServiceType,
} from "Common/Server/Services/ProjectCallSMSConfigService";
import ProjectUserProfileService, {
Service as ProjectUserProfileServiceType,
} from "Common/Server/Services/ProjectUserProfileService";
import ProjectSmtpConfigService, {
Service as ProjectSMTPConfigServiceType,
} from "Common/Server/Services/ProjectSmtpConfigService";
@@ -336,6 +412,9 @@ import StatusPageSSOService, {
import TeamMemberService, {
TeamMemberService as TeamMemberServiceType,
} from "Common/Server/Services/TeamMemberService";
import TeamMemberCustomFieldService, {
Service as TeamMemberCustomFieldServiceType,
} from "Common/Server/Services/TeamMemberCustomFieldService";
import TeamPermissionService, {
Service as TeamPermissionServiceType,
} from "Common/Server/Services/TeamPermissionService";
@@ -422,12 +501,36 @@ import AlertSeverity from "Common/Models/DatabaseModels/AlertSeverity";
import AlertState from "Common/Models/DatabaseModels/AlertState";
import AlertStateTimeline from "Common/Models/DatabaseModels/AlertStateTimeline";
// AlertEpisode Models
import AlertEpisode from "Common/Models/DatabaseModels/AlertEpisode";
import AlertEpisodeFeed from "Common/Models/DatabaseModels/AlertEpisodeFeed";
import AlertEpisodeInternalNote from "Common/Models/DatabaseModels/AlertEpisodeInternalNote";
import AlertEpisodeMember from "Common/Models/DatabaseModels/AlertEpisodeMember";
import AlertEpisodeOwnerTeam from "Common/Models/DatabaseModels/AlertEpisodeOwnerTeam";
import AlertEpisodeOwnerUser from "Common/Models/DatabaseModels/AlertEpisodeOwnerUser";
import AlertEpisodeStateTimeline from "Common/Models/DatabaseModels/AlertEpisodeStateTimeline";
import AlertGroupingRule from "Common/Models/DatabaseModels/AlertGroupingRule";
import IncidentGroupingRule from "Common/Models/DatabaseModels/IncidentGroupingRule";
import IncidentSla from "Common/Models/DatabaseModels/IncidentSla";
import IncidentSlaRule from "Common/Models/DatabaseModels/IncidentSlaRule";
// IncidentEpisode Models
import IncidentEpisodeFeed from "Common/Models/DatabaseModels/IncidentEpisodeFeed";
import IncidentEpisodeInternalNote from "Common/Models/DatabaseModels/IncidentEpisodeInternalNote";
import IncidentEpisodeMember from "Common/Models/DatabaseModels/IncidentEpisodeMember";
import IncidentEpisodeOwnerTeam from "Common/Models/DatabaseModels/IncidentEpisodeOwnerTeam";
import IncidentEpisodeOwnerUser from "Common/Models/DatabaseModels/IncidentEpisodeOwnerUser";
import IncidentEpisodeStateTimeline from "Common/Models/DatabaseModels/IncidentEpisodeStateTimeline";
import IncidentEpisodeRoleMember from "Common/Models/DatabaseModels/IncidentEpisodeRoleMember";
import IncidentCustomField from "Common/Models/DatabaseModels/IncidentCustomField";
import IncidentNoteTemplate from "Common/Models/DatabaseModels/IncidentNoteTemplate";
import IncidentPostmortemTemplate from "Common/Models/DatabaseModels/IncidentPostmortemTemplate";
import IncidentOwnerTeam from "Common/Models/DatabaseModels/IncidentOwnerTeam";
import IncidentOwnerUser from "Common/Models/DatabaseModels/IncidentOwnerUser";
import IncidentSeverity from "Common/Models/DatabaseModels/IncidentSeverity";
import IncidentRole from "Common/Models/DatabaseModels/IncidentRole";
import IncidentMember from "Common/Models/DatabaseModels/IncidentMember";
import IncidentState from "Common/Models/DatabaseModels/IncidentState";
import IncidentStateTimeline from "Common/Models/DatabaseModels/IncidentStateTimeline";
import IncidentTemplate from "Common/Models/DatabaseModels/IncidentTemplate";
@@ -463,6 +566,7 @@ import OnCallDutyPolicyScheduleLayer from "Common/Models/DatabaseModels/OnCallDu
import OnCallDutyPolicyScheduleLayerUser from "Common/Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser";
import ProjectCallSMSConfig from "Common/Models/DatabaseModels/ProjectCallSMSConfig";
import ProjectSmtpConfig from "Common/Models/DatabaseModels/ProjectSmtpConfig";
import ProjectUserProfile from "Common/Models/DatabaseModels/ProjectUserProfile";
import PromoCode from "Common/Models/DatabaseModels/PromoCode";
import CodeRepository from "Common/Models/DatabaseModels/CodeRepository";
import Reseller from "Common/Models/DatabaseModels/Reseller";
@@ -491,6 +595,7 @@ import StatusPageResource from "Common/Models/DatabaseModels/StatusPageResource"
import StatusPageSSO from "Common/Models/DatabaseModels/StatusPageSso";
import Team from "Common/Models/DatabaseModels/Team";
import TeamMember from "Common/Models/DatabaseModels/TeamMember";
import TeamMemberCustomField from "Common/Models/DatabaseModels/TeamMemberCustomField";
import TeamPermission from "Common/Models/DatabaseModels/TeamPermission";
import TeamComplianceSetting from "Common/Models/DatabaseModels/TeamComplianceSetting";
import TelemetryUsageBilling from "Common/Models/DatabaseModels/TelemetryUsageBilling";
@@ -905,6 +1010,171 @@ const BaseAPIFeatureSet: FeatureSet = {
).getRouter(),
);
// AlertEpisode Routes
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertEpisode, AlertEpisodeServiceType>(
AlertEpisode,
AlertEpisodeService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertEpisodeFeed, AlertEpisodeFeedServiceType>(
AlertEpisodeFeed,
AlertEpisodeFeedService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<
AlertEpisodeInternalNote,
AlertEpisodeInternalNoteServiceType
>(AlertEpisodeInternalNote, AlertEpisodeInternalNoteService).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertEpisodeMember, AlertEpisodeMemberServiceType>(
AlertEpisodeMember,
AlertEpisodeMemberService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertEpisodeOwnerTeam, AlertEpisodeOwnerTeamServiceType>(
AlertEpisodeOwnerTeam,
AlertEpisodeOwnerTeamService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertEpisodeOwnerUser, AlertEpisodeOwnerUserServiceType>(
AlertEpisodeOwnerUser,
AlertEpisodeOwnerUserService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<
AlertEpisodeStateTimeline,
AlertEpisodeStateTimelineServiceType
>(
AlertEpisodeStateTimeline,
AlertEpisodeStateTimelineService,
).getRouter(),
);
// IncidentEpisode Routes
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new IncidentEpisodeAPI().getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentEpisodeFeed, IncidentEpisodeFeedServiceType>(
IncidentEpisodeFeed,
IncidentEpisodeFeedService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<
IncidentEpisodeInternalNote,
IncidentEpisodeInternalNoteServiceType
>(
IncidentEpisodeInternalNote,
IncidentEpisodeInternalNoteService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentEpisodeMember, IncidentEpisodeMemberServiceType>(
IncidentEpisodeMember,
IncidentEpisodeMemberService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<
IncidentEpisodeOwnerTeam,
IncidentEpisodeOwnerTeamServiceType
>(IncidentEpisodeOwnerTeam, IncidentEpisodeOwnerTeamService).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<
IncidentEpisodeOwnerUser,
IncidentEpisodeOwnerUserServiceType
>(IncidentEpisodeOwnerUser, IncidentEpisodeOwnerUserService).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<
IncidentEpisodeStateTimeline,
IncidentEpisodeStateTimelineServiceType
>(
IncidentEpisodeStateTimeline,
IncidentEpisodeStateTimelineService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<
IncidentEpisodeRoleMember,
IncidentEpisodeRoleMemberServiceType
>(
IncidentEpisodeRoleMember,
IncidentEpisodeRoleMemberService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<AlertGroupingRule, AlertGroupingRuleServiceType>(
AlertGroupingRule,
AlertGroupingRuleService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentGroupingRule, IncidentGroupingRuleServiceType>(
IncidentGroupingRule,
IncidentGroupingRuleService,
).getRouter(),
);
// IncidentSla
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentSla, IncidentSlaServiceType>(
IncidentSla,
IncidentSlaService,
).getRouter(),
);
// IncidentSlaRule
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentSlaRule, IncidentSlaRuleServiceType>(
IncidentSlaRule,
IncidentSlaRuleService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAnalyticsAPI<ExceptionInstance, ExceptionInstanceServiceType>(
@@ -1160,6 +1430,14 @@ const BaseAPIFeatureSet: FeatureSet = {
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<ProjectUserProfile, ProjectUserProfileServiceType>(
ProjectUserProfile,
ProjectUserProfileService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<MonitorGroupResource, MonitorGroupResourceServiceType>(
@@ -1176,6 +1454,14 @@ const BaseAPIFeatureSet: FeatureSet = {
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<TeamMemberCustomField, TeamMemberCustomFieldServiceType>(
TeamMemberCustomField,
TeamMemberCustomFieldService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<TeamPermission, TeamPermissionServiceType>(
@@ -1362,6 +1648,22 @@ const BaseAPIFeatureSet: FeatureSet = {
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentRole, IncidentRoleServiceType>(
IncidentRole,
IncidentRoleService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentMember, IncidentMemberServiceType>(
IncidentMember,
IncidentMemberService,
).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<IncidentOwnerUser, IncidentOwnerUserServiceType>(
@@ -1706,6 +2008,10 @@ const BaseAPIFeatureSet: FeatureSet = {
`/${APP_NAME.toLocaleLowerCase()}`,
new EnterpriseLicenseAPI().getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new OpenSourceDeploymentAPI().getRouter(),
);
app.use(`/${APP_NAME.toLocaleLowerCase()}`, new SlackAPI().getRouter());
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
@@ -1840,6 +2146,11 @@ const BaseAPIFeatureSet: FeatureSet = {
new IncidentPublicNoteAPI().getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new IncidentEpisodePublicNoteAPI().getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new IncidentInternalNoteAPI().getRouter(),

View File

@@ -17,9 +17,11 @@ import ObjectID from "Common/Types/ObjectID";
import PositiveNumber from "Common/Types/PositiveNumber";
import DatabaseConfig from "Common/Server/DatabaseConfig";
import {
AppVersion,
EncryptionSecret,
IsBillingEnabled,
} from "Common/Server/EnvironmentConfig";
import API from "Common/Utils/API";
import AccessTokenService from "Common/Server/Services/AccessTokenService";
import EmailVerificationTokenService from "Common/Server/Services/EmailVerificationTokenService";
import MailService from "Common/Server/Services/MailService";
@@ -29,6 +31,7 @@ import UserSessionService, {
SessionMetadata,
} from "Common/Server/Services/UserSessionService";
import CookieUtil from "Common/Server/Utils/Cookie";
import JSONWebToken from "Common/Server/Utils/JsonWebToken";
import Express, {
ExpressRequest,
ExpressResponse,
@@ -54,6 +57,11 @@ const router: ExpressRouter = Express.getRouter();
const ACCESS_TOKEN_EXPIRY_SECONDS: number = 15 * 60;
interface FinalizeUserLoginResult {
sessionMetadata: SessionMetadata;
accessToken: string;
}
type FinalizeUserLoginInput = {
req: ExpressRequest;
res: ExpressResponse;
@@ -63,9 +71,9 @@ type FinalizeUserLoginInput = {
const finalizeUserLogin: (
data: FinalizeUserLoginInput,
) => Promise<SessionMetadata> = async (
) => Promise<FinalizeUserLoginResult> = async (
data: FinalizeUserLoginInput,
): Promise<SessionMetadata> => {
): Promise<FinalizeUserLoginResult> => {
const { req, res, user, isGlobalLogin } = data;
const sessionMetadata: SessionMetadata =
@@ -87,7 +95,21 @@ const finalizeUserLogin: (
accessTokenExpiresInSeconds: ACCESS_TOKEN_EXPIRY_SECONDS,
});
return sessionMetadata;
// Generate access token for response body (used by mobile clients)
const accessToken: string = JSONWebToken.signUserLoginToken({
tokenData: {
userId: user.id!,
email: user.email!,
name: user.name!,
timezone: user.timezone || null,
isMasterAdmin: user.isMasterAdmin!,
isGlobalLogin: isGlobalLogin,
sessionId: sessionMetadata.session.id!,
},
expiresInSeconds: ACCESS_TOKEN_EXPIRY_SECONDS,
});
return { sessionMetadata, accessToken };
};
router.post(
@@ -251,6 +273,28 @@ router.post(
logger.info("User signed up: " + savedUser.email?.toString());
if (!IsBillingEnabled && miscDataProps["notifySelfHosted"] === true) {
const instanceUrl: string = new URL(httpProtocol, host).toString();
API.post({
url: URL.fromString(
"https://oneuptime.com/api/open-source-deployment/register",
),
data: {
email: savedUser.email?.toString() || "",
name: savedUser.name?.toString() || "",
companyName:
(miscDataProps["selfHostedCompanyName"] as string) || undefined,
companyPhoneNumber:
(miscDataProps["selfHostedPhoneNumber"] as string) || undefined,
oneuptimeVersion: AppVersion,
instanceUrl: instanceUrl,
},
}).catch((err: Error) => {
logger.error(err);
});
}
return Response.sendEntityResponse(req, res, savedUser, User);
}
@@ -552,8 +596,10 @@ router.post(
next: NextFunction,
): Promise<void> => {
try {
// Try cookie first, then fallback to request body (for mobile clients)
const refreshToken: string | undefined =
CookieUtil.getRefreshTokenFromExpressRequest(req);
CookieUtil.getRefreshTokenFromExpressRequest(req) ||
(req.body.refreshToken as string | undefined);
if (!refreshToken) {
CookieUtil.removeAllCookies(req, res);
@@ -658,7 +704,26 @@ router.post(
accessTokenExpiresInSeconds: ACCESS_TOKEN_EXPIRY_SECONDS,
});
return Response.sendEmptySuccessResponse(req, res);
// Generate access token for response body (used by mobile clients)
const newAccessToken: string = JSONWebToken.signUserLoginToken({
tokenData: {
userId: user.id!,
email: user.email!,
name: user.name!,
timezone: user.timezone || null,
isMasterAdmin: user.isMasterAdmin!,
isGlobalLogin: isGlobalLogin,
sessionId: renewedSession.session.id!,
},
expiresInSeconds: ACCESS_TOKEN_EXPIRY_SECONDS,
});
return Response.sendJsonObjectResponse(req, res, {
accessToken: newAccessToken,
refreshToken: renewedSession.refreshToken,
refreshTokenExpiresAt:
renewedSession.refreshTokenExpiresAt.toISOString(),
});
} catch (err) {
return next(err);
}
@@ -673,8 +738,10 @@ router.post(
next: NextFunction,
): Promise<void> => {
try {
// Try cookie first, then fallback to request body (for mobile clients)
const refreshToken: string | undefined =
CookieUtil.getRefreshTokenFromExpressRequest(req);
CookieUtil.getRefreshTokenFromExpressRequest(req) ||
(req.body.refreshToken as string | undefined);
if (refreshToken) {
await UserSessionService.revokeSessionByRefreshToken(refreshToken, {
@@ -987,14 +1054,21 @@ const login: LoginFunction = async (options: {
if (alreadySavedUser.password.toString() === user.password!.toString()) {
logger.info("User logged in: " + alreadySavedUser.email?.toString());
await finalizeUserLogin({
const loginResult: FinalizeUserLoginResult = await finalizeUserLogin({
req,
res,
user: alreadySavedUser,
isGlobalLogin: true,
});
return Response.sendEntityResponse(req, res, alreadySavedUser, User);
return Response.sendEntityResponse(req, res, alreadySavedUser, User, {
miscData: {
accessToken: loginResult.accessToken,
refreshToken: loginResult.sessionMetadata.refreshToken,
refreshTokenExpiresAt:
loginResult.sessionMetadata.refreshTokenExpiresAt.toISOString(),
},
});
}
}
return Response.sendErrorResponse(

View File

@@ -3480,6 +3480,26 @@ router.post(
logger.debug(
`SCIM Create user - user already exists with id: ${user.id}`,
);
// Update user's name if provided in SCIM request and user's name is missing or different
if (name) {
const currentName: string = user.name?.toString() || "";
if (!currentName || currentName !== name) {
executionSteps.push(
`Updating user name from "${currentName || "(empty)"}" to "${name}"`,
);
await UserService.updateOneById({
id: user.id!,
data: {
name: new Name(name),
},
props: { isRoot: true },
});
// Update local user object so response reflects the new name
user.name = new Name(name);
executionSteps.push(`User name updated successfully`);
}
}
}
// Add user to default teams if configured and push groups is not enabled

View File

@@ -13,6 +13,7 @@ import ObjectID from "Common/Types/ObjectID";
import DatabaseConfig from "Common/Server/DatabaseConfig";
import { EncryptionSecret } from "Common/Server/EnvironmentConfig";
import MailService from "Common/Server/Services/MailService";
import ProjectSMTPConfigService from "Common/Server/Services/ProjectSmtpConfigService";
import StatusPagePrivateUserService from "Common/Server/Services/StatusPagePrivateUserService";
import StatusPageService from "Common/Server/Services/StatusPageService";
import StatusPagePrivateUserSessionService, {
@@ -468,6 +469,16 @@ router.post(
logoFileId: true,
requireSsoForLogin: true,
projectId: true,
smtpConfig: {
_id: true,
hostname: true,
port: true,
username: true,
password: true,
fromEmail: true,
fromName: true,
secure: true,
},
},
},
);
@@ -547,6 +558,9 @@ router.post(
},
{
projectId: statusPage.projectId!,
mailServer: ProjectSMTPConfigService.toEmailServer(
statusPage.smtpConfig,
),
statusPageId: statusPage.id!,
},
).catch((err: Error) => {
@@ -632,6 +646,16 @@ router.post(
logoFileId: true,
requireSsoForLogin: true,
projectId: true,
smtpConfig: {
_id: true,
hostname: true,
port: true,
username: true,
password: true,
fromEmail: true,
fromName: true,
secure: true,
},
},
},
);
@@ -689,6 +713,9 @@ router.post(
},
{
projectId: statusPage.projectId!,
mailServer: ProjectSMTPConfigService.toEmailServer(
statusPage.smtpConfig,
),
statusPageId: statusPage.id!,
},
).catch((err: Error) => {

View File

@@ -70,6 +70,7 @@ export default class CallService {
customTwilioConfig?: TwilioConfig | undefined;
incidentId?: ObjectID | undefined;
alertId?: ObjectID | undefined;
monitorId?: ObjectID | undefined;
scheduledMaintenanceId?: ObjectID | undefined;
statusPageId?: ObjectID | undefined;
statusPageAnnouncementId?: ObjectID | undefined;
@@ -144,6 +145,10 @@ export default class CallService {
callLog.alertId = options.alertId;
}
if (options.monitorId) {
callLog.monitorId = options.monitorId;
}
if (options.scheduledMaintenanceId) {
callLog.scheduledMaintenanceId = options.scheduledMaintenanceId;
}

View File

@@ -5,7 +5,7 @@ import {
getSendgridConfig,
} from "../Config";
import SMTPOAuthService from "./SMTPOAuthService";
import SendgridMail, { MailDataRequired } from "@sendgrid/mail";
import SendgridMail, { ClientResponse, MailDataRequired } from "@sendgrid/mail";
import Hostname from "Common/Types/API/Hostname";
import OneUptimeDate from "Common/Types/Date";
import Dictionary from "Common/Types/Dictionary";
@@ -433,12 +433,17 @@ export default class MailService {
try {
for (let attempt: number = 1; attempt <= maxRetries; attempt++) {
try {
await mailer.sendMail({
from: `${options.emailServer.fromName.toString()} <${options.emailServer.fromEmail.toString()}>`,
to: mail.toEmail.toString(),
subject: mail.subject,
html: mail.body,
});
const sendMailResponse: SMTPTransport.SentMessageInfo =
await mailer.sendMail({
from: `${options.emailServer.fromName.toString()} <${options.emailServer.fromEmail.toString()}>`,
to: mail.toEmail.toString(),
subject: mail.subject,
html: mail.body,
});
logger.debug("SMTP Email Provider Response:");
logger.debug(JSON.stringify(sendMailResponse, null, 2));
return; // Success, exit the function
} catch (error) {
lastError = error;
@@ -478,6 +483,7 @@ export default class MailService {
timeout?: number | undefined;
incidentId?: ObjectID | undefined;
alertId?: ObjectID | undefined;
monitorId?: ObjectID | undefined;
scheduledMaintenanceId?: ObjectID | undefined;
statusPageId?: ObjectID | undefined;
statusPageAnnouncementId?: ObjectID | undefined;
@@ -511,6 +517,10 @@ export default class MailService {
emailLog.alertId = options.alertId;
}
if (options.monitorId) {
emailLog.monitorId = options.monitorId;
}
if (options.scheduledMaintenanceId) {
emailLog.scheduledMaintenanceId = options.scheduledMaintenanceId;
}
@@ -652,7 +662,21 @@ export default class MailService {
emailLog.fromEmail = sendgridConfig.fromEmail;
}
await SendgridMail.send(msg);
const sendgridResponse: [ClientResponse, Record<string, unknown>] =
await SendgridMail.send(msg);
logger.debug("SendGrid Email Provider Response:");
logger.debug(
JSON.stringify(
{
statusCode: sendgridResponse[0]?.statusCode,
headers: sendgridResponse[0]?.headers,
body: sendgridResponse[0]?.body,
},
null,
2,
),
);
if (emailLog) {
emailLog.status = MailStatus.Success;

View File

@@ -33,6 +33,7 @@ export default class SmsService {
userOnCallLogTimelineId?: ObjectID | undefined;
incidentId?: ObjectID | undefined;
alertId?: ObjectID | undefined;
monitorId?: ObjectID | undefined;
scheduledMaintenanceId?: ObjectID | undefined;
statusPageId?: ObjectID | undefined;
statusPageAnnouncementId?: ObjectID | undefined;
@@ -91,6 +92,10 @@ export default class SmsService {
smsLog.alertId = options.alertId;
}
if (options.monitorId) {
smsLog.monitorId = options.monitorId;
}
if (options.scheduledMaintenanceId) {
smsLog.scheduledMaintenanceId = options.scheduledMaintenanceId;
}

View File

@@ -41,6 +41,7 @@ export default class WhatsAppService {
userOnCallLogTimelineId?: ObjectID | undefined;
incidentId?: ObjectID | undefined;
alertId?: ObjectID | undefined;
monitorId?: ObjectID | undefined;
scheduledMaintenanceId?: ObjectID | undefined;
statusPageId?: ObjectID | undefined;
statusPageAnnouncementId?: ObjectID | undefined;
@@ -96,6 +97,10 @@ export default class WhatsAppService {
whatsAppLog.alertId = options.alertId;
}
if (options.monitorId) {
whatsAppLog.monitorId = options.monitorId;
}
if (options.scheduledMaintenanceId) {
whatsAppLog.scheduledMaintenanceId = options.scheduledMaintenanceId;
}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> EmailTitle title=(concat "Alert " alertNumber ": " alertTitle) }}
{{> InfoBlock info=(concat "A new alert has been created in the project - " projectName)}}

View File

@@ -0,0 +1,66 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert Episode " episodeNumber ": " alertEpisodeTitle) }}
{{> InfoBlock info=(concat "A new alert episode has been created in the project - " projectName)}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Alert Episode Title:" text=alertEpisodeTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Severity: " text=alertEpisodeSeverity }}
{{> DetailBoxField title="Root Cause: " text=rootCause }}
{{> DetailBoxField title="Description: " text=alertEpisodeDescription }}
{{> DetailBoxEnd this }}
{{#if alertsList}}
{{> TitleBlock title=(concat "Alerts in this Episode (" alertsCount ")") }}
<!-- Alerts List Container -->
<table class="st-Copy st-Width st-Width--mobile" border="0" cellpadding="0" cellspacing="0"
width="600" style="min-width: 600px;">
<tbody>
<tr>
<td class="st-Spacer st-Spacer--gutter"
style="border: 0; margin:0; padding: 0; font-size: 1px; line-height: 1px; mso-line-height-rule: exactly;"
width="64">
<div class="st-Spacer st-Spacer--filler"></div>
</td>
<td style="border: 0; margin: 0; padding: 0;">
{{{alertsList}}}
</td>
<td class="st-Spacer st-Spacer--gutter"
style="border: 0; margin:0; padding: 0; font-size: 1px; line-height: 1px; mso-line-height-rule: exactly;"
width="64">
<div class="st-Spacer st-Spacer--filler"></div>
</td>
</tr>
<tr>
<td class="st-Spacer st-Spacer--stacked" colspan="3" height="16"
style="border: 0; margin: 0; padding: 0; font-size: 1px; line-height: 1px; mso-line-height-rule: exactly;">
<div class="st-Spacer st-Spacer--filler"></div>
</td>
</tr>
</tbody>
</table>
<!-- /Alerts List Container -->
{{/if}}
{{> InfoBlock info="ACTION REQUIRED: Please acknowledge this alert episode by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=acknowledgeAlertEpisodeLink buttonText="Acknowledge Alert Episode"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=acknowledgeAlertEpisodeLink}}
{{> InfoBlock info="You will be notified when the status of this alert episode 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 episode or you are currently on-call."}}
{{> Footer this }}
{{> End this}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Incident: " incidentTitle) }}
{{> EmailTitle title=(concat "Incident " incidentNumber ": " incidentTitle) }}
{{> InfoBlock info=(concat "A new incident has been created in the project - " projectName)}}

View File

@@ -0,0 +1,66 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Incident Episode " episodeNumber ": " incidentEpisodeTitle) }}
{{> InfoBlock info=(concat "A new incident episode has been created in the project - " projectName)}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Incident Episode Title:" text=incidentEpisodeTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Severity: " text=incidentEpisodeSeverity }}
{{> DetailBoxField title="Root Cause: " text=rootCause }}
{{> DetailBoxField title="Description: " text=incidentEpisodeDescription }}
{{> DetailBoxEnd this }}
{{#if incidentsList}}
{{> TitleBlock title=(concat "Incidents in this Episode (" incidentsCount ")") }}
<!-- Incidents List Container -->
<table class="st-Copy st-Width st-Width--mobile" border="0" cellpadding="0" cellspacing="0"
width="600" style="min-width: 600px;">
<tbody>
<tr>
<td class="st-Spacer st-Spacer--gutter"
style="border: 0; margin:0; padding: 0; font-size: 1px; line-height: 1px; mso-line-height-rule: exactly;"
width="64">
<div class="st-Spacer st-Spacer--filler"></div>
</td>
<td style="border: 0; margin: 0; padding: 0;">
{{{incidentsList}}}
</td>
<td class="st-Spacer st-Spacer--gutter"
style="border: 0; margin:0; padding: 0; font-size: 1px; line-height: 1px; mso-line-height-rule: exactly;"
width="64">
<div class="st-Spacer st-Spacer--filler"></div>
</td>
</tr>
<tr>
<td class="st-Spacer st-Spacer--stacked" colspan="3" height="16"
style="border: 0; margin: 0; padding: 0; font-size: 1px; line-height: 1px; mso-line-height-rule: exactly;">
<div class="st-Spacer st-Spacer--filler"></div>
</td>
</tr>
</tbody>
</table>
<!-- /Incidents List Container -->
{{/if}}
{{> InfoBlock info="ACTION REQUIRED: Please acknowledge this incident episode by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=acknowledgeIncidentEpisodeLink buttonText="Acknowledge Incident Episode"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=acknowledgeIncidentEpisodeLink}}
{{> InfoBlock info="You will be notified when the status of this incident episode 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 incident episode or you are currently on-call."}}
{{> Footer this }}
{{> End this}}

View File

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

View File

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

View File

@@ -0,0 +1,35 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert Episode " episodeNumber ": " episodeTitle) }}
{{> InfoBlock info=(concat "A new alert episode has been created in the project - " projectName)}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Episode Title:" text=episodeTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Episode Created By: " text=declaredBy }}
{{> DetailBoxField title="Episode Created At: " text=declaredAt }}
{{> DetailBoxField title="Severity: " text=episodeSeverity }}
{{> DetailBoxField title="Description: " text=episodeDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this alert episode by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=episodeViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=episodeViewLink}}
{{> InfoBlock info="You will be notified when the status of this alert episode changes."}}
{{> OwnerInfo this }}
{{> UnsubscribeOwnerEmail this }}
{{> Footer this }}
{{> End this}}

View File

@@ -0,0 +1,37 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Alert Episode " episodeNumber ": " episodeTitle) }}
{{> InfoBlock info="Alert episode state has changed"}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> StateTransition this}}
{{#ifNotCond previousStateDurationText ""}}
{{> DetailBoxField title="Duration in Previous State:" text=previousStateDurationText }}
{{/ifNotCond}}
{{> DetailBoxField title="Episode Title:" text=episodeTitle }}
{{> DetailBoxField title="State changed at:" text=stateChangedAt }}
{{> DetailBoxField title="Severity:" text=episodeSeverity }}
{{> DetailBoxField title="Description:" text=episodeDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this alert episode by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=episodeViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=episodeViewLink}}
{{> InfoBlock info="You will be notified when the status of this alert episode changes."}}
{{> OwnerInfo this }}
{{> UnsubscribeOwnerEmail this }}
{{> Footer this }}
{{> End this}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> EmailTitle title=(concat "Alert " alertNumber ": " alertTitle) }}
{{> InfoBlock info="You have been added as the owner of this alert."}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> EmailTitle title=(concat "Alert " alertNumber ": " alertTitle) }}
{{> InfoBlock info="A new note has been posted on this alert."}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> EmailTitle title=(concat "Alert " alertNumber ": " alertTitle) }}
{{> InfoBlock info=(concat "A new alert has been created in the project - " projectName)}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Alert: " alertTitle) }}
{{> EmailTitle title=(concat "Alert " alertNumber ": " alertTitle) }}
{{> InfoBlock info="Alert state has changed"}}

View File

@@ -0,0 +1,30 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Incident Episode " episodeNumber ": " episodeTitle) }}
{{> InfoBlock info="You have been added as the owner of this incident episode."}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Episode Title:" text=episodeTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Severity: " text=episodeSeverity }}
{{> DetailBoxField title="Description: " text=episodeDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this incident episode by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=episodeViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=episodeViewLink}}
{{> InfoBlock info="You will be notified when the status of this incident episode changes."}}
{{> Footer this }}
{{> End this}}

View File

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

View File

@@ -0,0 +1,35 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Incident Episode " episodeNumber ": " episodeTitle) }}
{{> InfoBlock info=(concat "A new incident episode has been created in the project - " projectName)}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Episode Title:" text=episodeTitle }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Episode Created By: " text=declaredBy }}
{{> DetailBoxField title="Episode Created At: " text=declaredAt }}
{{> DetailBoxField title="Severity: " text=episodeSeverity }}
{{> DetailBoxField title="Description: " text=episodeDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this incident episode by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=episodeViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=episodeViewLink}}
{{> InfoBlock info="You will be notified when the status of this incident episode changes."}}
{{> OwnerInfo this }}
{{> UnsubscribeOwnerEmail this }}
{{> Footer this }}
{{> End this}}

View File

@@ -0,0 +1,37 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Incident Episode " episodeNumber ": " episodeTitle) }}
{{> InfoBlock info="Incident episode state has changed"}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> StateTransition this}}
{{#ifNotCond previousStateDurationText ""}}
{{> DetailBoxField title="Duration in Previous State:" text=previousStateDurationText }}
{{/ifNotCond}}
{{> DetailBoxField title="Episode Title:" text=episodeTitle }}
{{> DetailBoxField title="State changed at:" text=stateChangedAt }}
{{> DetailBoxField title="Severity:" text=episodeSeverity }}
{{> DetailBoxField title="Description:" text=episodeDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this incident episode by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=episodeViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=episodeViewLink}}
{{> InfoBlock info="You will be notified when the status of this incident episode changes."}}
{{> OwnerInfo this }}
{{> UnsubscribeOwnerEmail this }}
{{> Footer this }}
{{> End this}}

View File

@@ -0,0 +1,32 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title=(concat "Incident " incidentNumber ": " incidentTitle) }}
{{> InfoBlock info=(concat "You have been assigned as " incidentRole " to this incident.")}}
{{> InfoBlock info="Here are the details: "}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Incident Title:" text=incidentTitle }}
{{> DetailBoxField title="Your Role: " text=incidentRole }}
{{> DetailBoxField title="Current State: " text=currentState }}
{{> DetailBoxField title="Resources Affected: " text=resourcesAffected }}
{{> DetailBoxField title="Severity: " text=incidentSeverity }}
{{> DetailBoxField title="Description: " text=incidentDescription }}
{{> DetailBoxEnd this }}
{{> InfoBlock info="You can view this incident by clicking on the button below - "}}
{{> ButtonBlock buttonUrl=incidentViewLink buttonText="View on Dashboard"}}
{{> InfoBlock info="You can also copy and paste this link:"}}
{{> InfoBlock info=incidentViewLink}}
{{> InfoBlock info="You will be notified when the status of this incident changes."}}
{{> Footer this }}
{{> End this}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Incident: " incidentTitle) }}
{{> EmailTitle title=(concat "Incident " incidentNumber ": " incidentTitle) }}
{{> InfoBlock info="You have been added as the owner of this incident."}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Incident: " incidentTitle) }}
{{> EmailTitle title=(concat "Incident " incidentNumber ": " incidentTitle) }}
{{> InfoBlock info="A new note has been posted on this incident."}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Incident: " incidentTitle) }}
{{> EmailTitle title=(concat "Incident " incidentNumber ": " incidentTitle) }}
{{> InfoBlock info=(concat "A new incident has been created in the project - " projectName)}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Incident: " incidentTitle) }}
{{> EmailTitle title=(concat "Incident " incidentNumber ": " incidentTitle) }}
{{> InfoBlock info="Incident state has changed"}}

View File

@@ -0,0 +1,37 @@
{{> Start this}}
{{> Logo this}}
{{> EmailTitle title="Invoice from OneUptime" }}
{{> InfoBlock info="A new invoice has been generated for your account. Here are the details:"}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Invoice Number:" text=invoiceNumber }}
{{> DetailBoxField title="Invoice Date:" text=invoiceDate }}
{{> DetailBoxField title="Amount:" text=amount }}
{{#if description}}
{{> DetailBoxField title="Description:" text=description }}
{{/if}}
{{> DetailBoxEnd this }}
{{#if invoicePdfUrl}}
{{> InfoBlock info="You can view and download your invoice by clicking the button below:"}}
{{> ButtonBlock buttonUrl=invoicePdfUrl buttonText="View Invoice PDF"}}
{{> InfoBlock info="Or copy and paste this link:"}}
{{> InfoBlock info=invoicePdfUrl}}
{{/if}}
{{#if dashboardLink}}
{{> InfoBlock info="You can also view all your invoices in your dashboard:"}}
{{> ButtonBlock buttonUrl=dashboardLink buttonText="View Billing Dashboard"}}
{{/if}}
{{> InfoBlock info="You have received this email because you are subscribed to receive invoice notifications for this project."}}
{{> Footer this }}
{{> End this}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Scheduled Maintenance: " scheduledMaintenanceTitle) }}
{{> EmailTitle title=(concat "Scheduled Maintenance " scheduledMaintenanceNumber ": " scheduledMaintenanceTitle) }}
{{> InfoBlock info="You have been added as the owner of this scheduled maintenance event."}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Scheduled Maintenance: " scheduledMaintenanceTitle) }}
{{> EmailTitle title=(concat "Scheduled Maintenance " scheduledMaintenanceNumber ": " scheduledMaintenanceTitle) }}
{{> InfoBlock info="A new note has been posted on this scheduled maintenance event"}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Scheduled Maintenance: " scheduledMaintenanceTitle) }}
{{> EmailTitle title=(concat "Scheduled Maintenance " scheduledMaintenanceNumber ": " scheduledMaintenanceTitle) }}
{{> InfoBlock info=(concat "A new scheduled maintenance has been created in the project - " projectName)}}

View File

@@ -2,7 +2,7 @@
{{> Logo this}}
{{> EmailTitle title=(concat "Scheduled Maintenance: " scheduledMaintenanceTitle) }}
{{> EmailTitle title=(concat "Scheduled Maintenance " scheduledMaintenanceNumber ": " scheduledMaintenanceTitle) }}
{{> InfoBlock info="Scheduled Maintenance state has changed"}}

View File

@@ -0,0 +1,36 @@
{{> Start this}}
{{> CustomLogo this}}
{{> EmailTitle title=(concat "New Incident: " episodeTitle) }}
{{> InfoBlock info="A new incident has been reported that may affect the services you're subscribed to."}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Incident" text=episodeTitle }}
{{#if episodeSeverity}}
{{> DetailBoxField title="Severity" text=episodeSeverity }}
{{/if}}
{{> DetailBoxField title="Affected Resources" text=resourcesAffected }}
{{#if episodeDescription}}
{{> DetailBoxField title="Description" text=episodeDescription }}
{{/if}}
{{> DetailBoxEnd this }}
{{#if detailsUrl}}
{{> ButtonBlock buttonUrl=detailsUrl buttonText="View Incident Details"}}
{{else}}
{{> ButtonBlock buttonUrl=statusPageUrl buttonText="View Status Page"}}
{{/if}}
{{> VerticalSpace this}}
{{#if subscriberEmailNotificationFooterText}}
{{> InfoBlock info=subscriberEmailNotificationFooterText }}
{{/if}}
{{> UnsubscribeBlock this}}
{{> Footer this}}
{{> End this}}

View File

@@ -0,0 +1,30 @@
{{> Start this}}
{{> CustomLogo this}}
{{> EmailTitle title=(concat "Incident: " episodeTitle) }}
{{> InfoBlock info="A new note has been added to the incident. Here are the details:"}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Incident Title" text=episodeTitle }}
{{> DetailBoxField title="Resources Affected" text=resourcesAffected }}
{{#if episodeSeverity}}
{{> DetailBoxField title="Severity" text=episodeSeverity }}
{{/if}}
{{> DetailBoxField title="Note" text=note }}
{{> DetailBoxEnd this }}
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
{{#if detailsUrl}}
{{> InfoBlock info=(concat "Find further information here: " detailsUrl)}}
{{else}}
{{> InfoBlock info=(concat "Find further information here: " statusPageUrl)}}
{{/if}}
{{> UnsubscribeBlock this}}
{{> VerticalSpace this}}
{{> End this}}

View File

@@ -0,0 +1,34 @@
{{> Start this}}
{{> CustomLogo this}}
{{> EmailTitle title=emailTitle }}
{{> InfoBlock info="The status of an incident affecting services you're subscribed to has been updated."}}
{{> DetailBoxStart this }}
{{> DetailBoxField title="Incident" text=episodeTitle }}
{{> DetailBoxField title="Current State" text=episodeState }}
{{#if episodeSeverity}}
{{> DetailBoxField title="Severity" text=episodeSeverity }}
{{/if}}
{{> DetailBoxField title="Affected Resources" text=resourcesAffected }}
{{> DetailBoxEnd this }}
{{#if detailsUrl}}
{{> ButtonBlock buttonUrl=detailsUrl buttonText="View Incident Details"}}
{{else}}
{{> ButtonBlock buttonUrl=statusPageUrl buttonText="View Status Page"}}
{{/if}}
{{> VerticalSpace this}}
{{#if subscriberEmailNotificationFooterText}}
{{> InfoBlock info=subscriberEmailNotificationFooterText }}
{{/if}}
{{> UnsubscribeBlock this}}
{{> Footer this}}
{{> End this}}

29
App/package-lock.json generated
View File

@@ -83,6 +83,7 @@
"ejs": "^3.1.10",
"elkjs": "^0.10.0",
"esbuild": "^0.25.5",
"expo-server-sdk": "^3.15.0",
"express": "^4.21.1",
"formik": "^2.4.6",
"history": "^5.3.0",
@@ -92,6 +93,7 @@
"jsonwebtoken": "^9.0.0",
"jwt-decode": "^4.0.0",
"marked": "^12.0.2",
"mermaid": "^11.12.2",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
"multer": "^2.0.2",
@@ -111,7 +113,7 @@
"react-dropzone": "^14.2.2",
"react-error-boundary": "^4.0.13",
"react-highlight": "^0.15.0",
"react-markdown": "^8.0.3",
"react-markdown": "^9.0.0",
"react-router-dom": "^6.30.1",
"react-select": "^5.4.0",
"react-spinners": "^0.14.1",
@@ -121,7 +123,7 @@
"recharts": "^2.12.7",
"redis-semaphore": "^5.5.1",
"reflect-metadata": "^0.2.2",
"remark-gfm": "^3.0.1",
"remark-gfm": "^4.0.0",
"slackify-markdown": "^4.4.0",
"slugify": "^1.6.5",
"socket.io": "^4.7.4",
@@ -1608,13 +1610,13 @@
"license": "MIT"
},
"node_modules/axios": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz",
"integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==",
"version": "1.13.5",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
"integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"follow-redirects": "^1.15.11",
"form-data": "^4.0.5",
"proxy-from-env": "^1.1.0"
}
},
@@ -2085,9 +2087,10 @@
}
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
@@ -2386,9 +2389,9 @@
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",

View File

@@ -77,6 +77,7 @@ export enum AIAgentConnectionStatus {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgent,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -99,7 +100,11 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.ProjectOwner, Permission.ProjectAdmin],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
@@ -126,7 +131,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.Public],
read: [Permission.Public, Permission.ReadAllProjectResources],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
@@ -154,7 +159,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.Public],
read: [Permission.Public, Permission.ReadAllProjectResources],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
@@ -176,7 +181,7 @@ export default class AIAgent extends BaseModel {
@ColumnAccessControl({
create: [],
read: [Permission.Public],
read: [Permission.Public, Permission.ReadAllProjectResources],
update: [],
})
@TableColumn({
@@ -202,7 +207,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.Public],
read: [Permission.Public, Permission.ReadAllProjectResources],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
@@ -231,6 +236,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgent,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -258,6 +264,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgent,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -299,6 +306,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgent,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -328,7 +336,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.Public],
read: [Permission.Public, Permission.ReadAllProjectResources],
update: [],
})
@TableColumn({
@@ -358,7 +366,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.Public],
read: [Permission.Public, Permission.ReadAllProjectResources],
update: [],
})
@TableColumn({
@@ -421,7 +429,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.ProjectOwner],
read: [Permission.ProjectOwner, Permission.ReadAllProjectResources],
update: [],
})
@TableColumn({ type: TableColumnType.Entity, modelType: User })
@@ -446,7 +454,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.ProjectOwner],
read: [Permission.ProjectOwner, Permission.ReadAllProjectResources],
update: [],
})
@TableColumn({
@@ -490,6 +498,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgent,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -515,7 +524,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectMember,
Permission.CreateProjectAIAgent,
],
read: [Permission.Public],
read: [Permission.Public, Permission.ReadAllProjectResources],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
@@ -552,6 +561,7 @@ export default class AIAgent extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgent,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,

View File

@@ -41,6 +41,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -85,6 +86,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -122,6 +124,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -153,6 +156,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -191,6 +195,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -222,6 +227,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -259,6 +265,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -290,6 +297,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -328,6 +336,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -352,6 +361,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -386,6 +396,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -410,6 +421,7 @@ export default class AIAgentOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -40,6 +40,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -84,6 +85,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -121,6 +123,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -152,6 +155,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -190,6 +194,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -221,6 +226,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -258,6 +264,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -289,6 +296,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -327,6 +335,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -351,6 +360,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -385,6 +395,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -409,6 +420,7 @@ export default class AIAgentOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAIAgentOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -55,6 +55,7 @@ import { AIAgentTaskMetadata } from "../../Types/AI/AIAgentTaskMetadata";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -82,6 +83,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -120,6 +122,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -150,6 +153,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -183,6 +187,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -216,6 +221,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -258,6 +264,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -293,6 +300,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -323,6 +331,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -354,6 +363,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -387,6 +397,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -415,6 +426,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -438,6 +450,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -495,7 +508,11 @@ export default class AIAgentTask extends BaseModel {
@ColumnAccessControl({
create: [],
read: [Permission.ProjectOwner, Permission.ProjectAdmin],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({ type: TableColumnType.Entity, modelType: User })
@@ -515,7 +532,11 @@ export default class AIAgentTask extends BaseModel {
@ColumnAccessControl({
create: [],
read: [Permission.ProjectOwner, Permission.ProjectAdmin],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
@@ -543,6 +564,7 @@ export default class AIAgentTask extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -53,6 +53,7 @@ import LogSeverity from "../../Types/Log/LogSeverity";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -80,6 +81,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -118,6 +120,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -148,6 +151,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -186,6 +190,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -216,6 +221,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -254,6 +260,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -284,6 +291,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -318,6 +326,7 @@ export default class AIAgentTaskLog extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -379,7 +388,11 @@ export default class AIAgentTaskLog extends BaseModel {
@ColumnAccessControl({
create: [],
read: [Permission.ProjectOwner, Permission.ProjectAdmin],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({ type: TableColumnType.Entity, modelType: User })
@@ -399,7 +412,11 @@ export default class AIAgentTaskLog extends BaseModel {
@ColumnAccessControl({
create: [],
read: [Permission.ProjectOwner, Permission.ProjectAdmin],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({

View File

@@ -55,6 +55,7 @@ import EnableDocumentation from "../../Types/Database/EnableDocumentation";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -82,6 +83,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -120,6 +122,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -150,6 +153,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -188,6 +192,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -218,6 +223,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -256,6 +262,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -286,6 +293,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -324,6 +332,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -354,6 +363,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -388,6 +398,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -420,6 +431,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -454,6 +466,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -483,6 +496,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -512,6 +526,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -548,6 +563,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -577,6 +593,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -606,6 +623,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -635,6 +653,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTask,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -693,7 +712,11 @@ export default class AIAgentTaskPullRequest extends BaseModel {
@ColumnAccessControl({
create: [],
read: [Permission.ProjectOwner, Permission.ProjectAdmin],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({ type: TableColumnType.Entity, modelType: User })
@@ -713,7 +736,11 @@ export default class AIAgentTaskPullRequest extends BaseModel {
@ColumnAccessControl({
create: [],
read: [Permission.ProjectOwner, Permission.ProjectAdmin],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({

View File

@@ -40,6 +40,7 @@ import TelemetryException from "./TelemetryException";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -79,6 +80,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -115,6 +117,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -145,6 +148,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -181,6 +185,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -211,6 +216,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -247,6 +253,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -277,6 +284,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -314,6 +322,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -337,6 +346,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -370,6 +380,7 @@ export default class AIAgentTaskTelemetryException extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectAIAgentTaskTelemetryException,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -1,3 +1,4 @@
import AlertEpisode from "./AlertEpisode";
import AlertSeverity from "./AlertSeverity";
import AlertState from "./AlertState";
import Label from "./Label";
@@ -56,6 +57,7 @@ import NotificationRuleWorkspaceChannel from "../../Types/Workspace/Notification
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -105,6 +107,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -141,6 +144,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -172,6 +176,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -208,6 +213,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -243,6 +249,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -280,6 +287,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -356,6 +364,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -398,6 +407,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -408,9 +418,8 @@ export default class Alert extends BaseModel {
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "Deleted by User ID",
description:
"User ID who deleted this object (if this object was deleted by a User)",
title: "Monitor ID",
description: "ID of the monitor this alert belongs to",
})
@Column({
type: ColumnType.ObjectID,
@@ -431,6 +440,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -442,9 +452,9 @@ export default class Alert extends BaseModel {
@TableColumn({
required: false,
type: TableColumnType.EntityArray,
modelType: Monitor,
modelType: OnCallDutyPolicy,
title: "On-Call Duty Policies",
description: "List of on-call duty policy affected by this alert.",
description: "List of on-call duty policies affected by this alert.",
})
@ManyToMany(
() => {
@@ -455,15 +465,15 @@ export default class Alert extends BaseModel {
@JoinTable({
name: "AlertOnCallDutyPolicy",
inverseJoinColumn: {
name: "monitorId",
referencedColumnName: "_id",
},
joinColumn: {
name: "onCallDutyPolicyId",
referencedColumnName: "_id",
},
joinColumn: {
name: "alertId",
referencedColumnName: "_id",
},
})
public onCallDutyPolicies?: Array<OnCallDutyPolicy> = undefined; // monitors affected by this alert.
public onCallDutyPolicies?: Array<OnCallDutyPolicy> = undefined; // on-call duty policies affected by this alert.
@ColumnAccessControl({
create: [
@@ -477,6 +487,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -524,6 +535,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -565,6 +577,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -578,13 +591,13 @@ export default class Alert extends BaseModel {
type: TableColumnType.ObjectID,
required: true,
isDefaultValueColumn: true,
canReadOnRelationQuery: true,
title: "Current Alert State ID",
description: "Current Alert State ID",
example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
@@ -602,6 +615,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -643,6 +657,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -678,13 +693,14 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "monitorStatusWhenThisAlertWasCreatedId",
type: TableColumnType.Entity,
modelType: AlertState,
modelType: MonitorStatus,
title: "Monitor status when this alert was created",
description: "Monitor status when this alert was created",
})
@@ -713,6 +729,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -747,6 +764,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -775,6 +793,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -808,6 +827,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -833,6 +853,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -840,6 +861,7 @@ export default class Alert extends BaseModel {
isDefaultValueColumn: false,
required: false,
type: TableColumnType.JSON,
computed: true,
})
@Column({
type: ColumnType.JSON,
@@ -855,6 +877,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -880,6 +903,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -912,6 +936,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -938,6 +963,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -967,6 +993,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -1001,6 +1028,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -1034,6 +1062,7 @@ export default class Alert extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -1043,6 +1072,7 @@ export default class Alert extends BaseModel {
required: false,
type: TableColumnType.Number,
computed: true,
canReadOnRelationQuery: true,
title: "Alert Number",
description: "Alert Number",
example: 42,
@@ -1053,6 +1083,33 @@ export default class Alert extends BaseModel {
})
public alertNumber?: number = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
isDefaultValueColumn: false,
required: false,
type: TableColumnType.ShortText,
title: "Alert Number With Prefix",
description: "Alert number with prefix (e.g., 'ALT-42' or '#42')",
computed: true,
canReadOnRelationQuery: true,
})
@Column({
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
nullable: true,
})
public alertNumberWithPrefix?: string = undefined;
@ColumnAccessControl({
create: [],
read: [],
@@ -1071,4 +1128,81 @@ export default class Alert extends BaseModel {
})
public postUpdatesToWorkspaceChannels?: Array<NotificationRuleWorkspaceChannel> =
undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlert,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlert,
],
})
@TableColumn({
manyToOneRelationColumn: "alertEpisodeId",
type: TableColumnType.Entity,
modelType: AlertEpisode,
title: "Alert Episode",
description: "The episode this alert belongs to (if grouped)",
})
@ManyToOne(
() => {
return AlertEpisode;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertEpisodeId" })
public alertEpisode?: AlertEpisode = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlert,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlert,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlert,
],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: false,
title: "Alert Episode ID",
description: "The ID of the episode this alert belongs to (if grouped)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertEpisodeId?: ObjectID = undefined;
}

View File

@@ -40,6 +40,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -75,6 +76,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -110,6 +112,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -140,6 +143,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -174,6 +178,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -208,6 +213,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -236,6 +242,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -272,6 +279,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -296,6 +304,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -329,6 +338,7 @@ export default class AlertCustomField extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertCustomField,
Permission.ReadAllProjectResources,
],
update: [],
})

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,543 @@
import AlertEpisode from "./AlertEpisode";
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 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 ColorField from "../../Types/Database/ColorField";
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 Color from "../../Types/Color";
import IconProp from "../../Types/Icon/IconProp";
import ObjectID from "../../Types/ObjectID";
import Permission from "../../Types/Permission";
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
export enum AlertEpisodeFeedEventType {
EpisodeCreated = "EpisodeCreated",
EpisodeStateChanged = "EpisodeStateChanged",
EpisodeUpdated = "EpisodeUpdated",
AlertAdded = "AlertAdded",
AlertRemoved = "AlertRemoved",
OwnerUserAdded = "OwnerUserAdded",
OwnerTeamAdded = "OwnerTeamAdded",
OwnerUserRemoved = "OwnerUserRemoved",
OwnerTeamRemoved = "OwnerTeamRemoved",
OwnerNotificationSent = "OwnerNotificationSent",
PrivateNote = "PrivateNote",
RootCause = "RootCause",
OnCallPolicy = "OnCallPolicy",
OnCallNotification = "OnCallNotification",
SeverityChanged = "SeverityChanged",
}
@EnableDocumentation()
@CanAccessIfCanReadOn("alertEpisode")
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
delete: [],
update: [],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-episode-feed"))
@Entity({
name: "AlertEpisodeFeed",
})
@TableMetadata({
tableName: "AlertEpisodeFeed",
singularName: "Alert Episode Feed",
pluralName: "Alert Episode Feeds",
icon: IconProp.List,
tableDescription:
"Log of the entire alert episode activity. This is a log of all the episode state changes, alerts added/removed, notes, etc.",
})
export default class AlertEpisodeFeed extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertEpisodeId",
type: TableColumnType.Entity,
modelType: AlertEpisode,
title: "Alert Episode",
description: "Relation to Alert Episode in which this resource belongs",
})
@ManyToOne(
() => {
return AlertEpisode;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertEpisodeId" })
public alertEpisode?: AlertEpisode = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
title: "Alert Episode ID",
description: "Relation to Alert Episode ID in which this resource belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertEpisodeId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
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",
modelType: 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.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
type: TableColumnType.Markdown,
required: true,
title: "Log (in Markdown)",
description: "Log of the entire alert episode activity in Markdown",
})
@Column({
type: ColumnType.Markdown,
nullable: false,
unique: false,
})
public feedInfoInMarkdown?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
type: TableColumnType.Markdown,
required: false,
title: "More Information (in Markdown)",
description: "More information in Markdown",
})
@Column({
type: ColumnType.Markdown,
nullable: true,
unique: false,
})
public moreInformationInMarkdown?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
type: TableColumnType.ShortText,
required: true,
title: "Alert Episode Feed Event",
description: "Alert Episode Feed Event Type",
})
@Column({
type: ColumnType.ShortText,
nullable: false,
unique: false,
})
public alertEpisodeFeedEventType?: AlertEpisodeFeedEventType = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@ColorField()
@TableColumn({
type: TableColumnType.Color,
required: true,
title: "Color",
description: "Display color for the alert episode log",
})
@Column({
type: ColumnType.Color,
length: ColumnLength.Color,
nullable: false,
unique: false,
transformer: Color.getDatabaseTransformer(),
})
public displayColor?: Color = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "userId",
type: TableColumnType.Entity,
modelType: User,
title: "User",
description:
"Relation to User who this feed belongs to (if this feed belongs to a User)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "userId" })
public user?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
type: TableColumnType.ObjectID,
title: "User ID",
description:
"User who this feed belongs to (if this feed belongs to a User)",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public userId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeFeed,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
title: "Feed Posted At",
description: "Date and time when the feed was posted",
type: TableColumnType.Date,
})
@Column({
type: ColumnType.Date,
nullable: true,
unique: false,
})
public postedAt?: Date = undefined;
}

View File

@@ -0,0 +1,466 @@
import AlertEpisode from "./AlertEpisode";
import File from "./File";
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,
JoinTable,
ManyToMany,
ManyToOne,
} from "typeorm";
@EnableDocumentation()
@CanAccessIfCanReadOn("alertEpisode")
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertEpisodeInternalNote,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeInternalNote,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-episode-internal-note"))
@Entity({
name: "AlertEpisodeInternalNote",
})
@TableMetadata({
tableName: "AlertEpisodeInternalNote",
singularName: "Alert Episode Internal Note",
pluralName: "Alert Episode Internal Notes",
icon: IconProp.Lock,
tableDescription: "Manage internal notes for your alert episodes",
})
export default class AlertEpisodeInternalNote extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertEpisodeId",
type: TableColumnType.Entity,
modelType: AlertEpisode,
title: "Alert Episode",
description: "Relation to Alert Episode in which this resource belongs",
})
@ManyToOne(
() => {
return AlertEpisode;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertEpisodeId" })
public alertEpisode?: AlertEpisode = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
title: "Alert Episode ID",
description: "Relation to Alert Episode ID in which this resource belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertEpisodeId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
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",
modelType: 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.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeInternalNote,
],
})
@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.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeInternalNote,
],
})
@TableColumn({
type: TableColumnType.EntityArray,
modelType: File,
title: "Attachments",
description: "Files attached to this note",
required: false,
})
@ManyToMany(
() => {
return File;
},
{
eager: false,
},
)
@JoinTable({
name: "AlertEpisodeInternalNoteFile",
joinColumn: {
name: "alertEpisodeInternalNoteId",
referencedColumnName: "_id",
},
inverseJoinColumn: {
name: "fileId",
referencedColumnName: "_id",
},
})
public attachments?: Array<File> = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of this resource ownership?",
defaultValue: false,
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeInternalNote,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.LongText,
title: "Posted from Slack Message ID",
description:
"Unique identifier for the Slack message this note was created from (channel_id:message_ts). Used to prevent duplicate notes when multiple users react to the same message.",
required: false,
example: "C1234567890:1234567890.123456",
})
@Column({
type: ColumnType.LongText,
nullable: true,
})
public postedFromSlackMessageId?: string = undefined;
}

View File

@@ -0,0 +1,603 @@
import Alert from "./Alert";
import AlertEpisode from "./AlertEpisode";
import AlertGroupingRule from "./AlertGroupingRule";
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";
export enum AlertEpisodeMemberAddedBy {
Rule = "rule",
Manual = "manual",
API = "api",
}
@EnableDocumentation()
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertEpisodeMember,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeMember,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-episode-member"))
@TableMetadata({
tableName: "AlertEpisodeMember",
singularName: "Alert Episode Member",
pluralName: "Alert Episode Members",
icon: IconProp.Layers,
tableDescription: "Link between alerts and episodes",
})
@Entity({
name: "AlertEpisodeMember",
})
@Index(["alertEpisodeId", "alertId", "projectId"])
export default class AlertEpisodeMember extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertEpisodeId",
type: TableColumnType.Entity,
modelType: AlertEpisode,
title: "Alert Episode",
description: "Relation to Alert Episode that this alert belongs to",
})
@ManyToOne(
() => {
return AlertEpisode;
},
{
eager: false,
nullable: false,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertEpisodeId" })
public alertEpisode?: AlertEpisode = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Alert Episode ID",
description: "ID of the Alert Episode that this alert belongs to",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertEpisodeId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertId",
type: TableColumnType.Entity,
modelType: Alert,
title: "Alert",
description: "Relation to Alert that is a member of this episode",
})
@ManyToOne(
() => {
return Alert;
},
{
eager: false,
nullable: false,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertId" })
public alert?: Alert = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Alert ID",
description: "ID of the Alert that is a member of this episode",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Date,
title: "Added At",
description: "When this alert was added to the episode",
})
@Column({
type: ColumnType.Date,
nullable: true,
unique: false,
})
public addedAt?: Date = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
type: TableColumnType.ShortText,
required: true,
isDefaultValueColumn: true,
title: "Added By",
description:
"How this alert was added to the episode (rule, manual, or api)",
defaultValue: AlertEpisodeMemberAddedBy.Rule,
})
@Column({
type: ColumnType.ShortText,
nullable: false,
default: AlertEpisodeMemberAddedBy.Rule,
length: ColumnLength.ShortText,
})
public addedBy?: AlertEpisodeMemberAddedBy = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "addedByUserId",
type: TableColumnType.Entity,
modelType: User,
title: "Added By User",
description:
"User who manually added this alert to the episode (if applicable)",
})
@ManyToOne(
() => {
return User;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "addedByUserId" })
public addedByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: false,
title: "Added By User ID",
description: "User ID who manually added this alert to the episode",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public addedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "matchedRuleId",
type: TableColumnType.Entity,
modelType: AlertGroupingRule,
title: "Matched Rule",
description: "The grouping rule that matched this alert (if applicable)",
})
@ManyToOne(
() => {
return AlertGroupingRule;
},
{
eager: false,
nullable: true,
onDelete: "SET NULL",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "matchedRuleId" })
public matchedRule?: AlertGroupingRule = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: false,
title: "Matched Rule ID",
description: "ID of the grouping rule that matched this alert",
})
@Column({
type: ColumnType.ObjectID,
nullable: true,
transformer: ObjectID.getDatabaseTransformer(),
})
public matchedRuleId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeMember,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
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.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
modelType: 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.ReadAlertEpisodeMember,
Permission.ReadAllProjectResources,
],
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,433 @@
import AlertEpisode from "./AlertEpisode";
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.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertEpisodeOwnerTeam,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeOwnerTeam,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-episode-owner-team"))
@TableMetadata({
tableName: "AlertEpisodeOwnerTeam",
singularName: "Alert Episode Team Owner",
pluralName: "Alert Episode Team Owners",
icon: IconProp.Team,
tableDescription: "Add teams as owners to your alert episodes.",
})
@Entity({
name: "AlertEpisodeOwnerTeam",
})
@Index(["alertEpisodeId", "teamId", "projectId"])
export default class AlertEpisodeOwnerTeam extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertEpisodeId",
type: TableColumnType.Entity,
modelType: AlertEpisode,
title: "Alert Episode",
description:
"Relation to Alert Episode Resource in which this object belongs",
})
@ManyToOne(
() => {
return AlertEpisode;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertEpisodeId" })
public alertEpisode?: AlertEpisode = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Alert Episode ID",
description:
"ID of your OneUptime Alert Episode in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertEpisodeId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
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.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
modelType: 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.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerTeam,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of this resource ownership?",
defaultValue: false,
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
}

View File

@@ -0,0 +1,431 @@
import AlertEpisode from "./AlertEpisode";
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.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertEpisodeOwnerUser,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeOwnerUser,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-episode-owner-user"))
@TableMetadata({
tableName: "AlertEpisodeOwnerUser",
singularName: "Alert Episode User Owner",
pluralName: "Alert Episode User Owners",
icon: IconProp.User,
tableDescription: "Add users as owners to your alert episodes.",
})
@Entity({
name: "AlertEpisodeOwnerUser",
})
@Index(["alertEpisodeId", "userId", "projectId"])
export default class AlertEpisodeOwnerUser extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "userId",
type: TableColumnType.Entity,
modelType: User,
title: "User",
description: "User that is the owner of this episode",
})
@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.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "User ID",
description: "ID of the user who is the owner",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public userId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertEpisodeId",
type: TableColumnType.Entity,
modelType: AlertEpisode,
title: "Alert Episode",
description:
"Relation to Alert Episode Resource in which this object belongs",
})
@ManyToOne(
() => {
return AlertEpisode;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertEpisodeId" })
public alertEpisode?: AlertEpisode = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
canReadOnRelationQuery: true,
title: "Alert Episode ID",
description:
"ID of your OneUptime Alert Episode in which this object belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertEpisodeId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
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.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "deletedByUserId",
type: TableColumnType.Entity,
title: "Deleted by User",
modelType: 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.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeOwnerUser,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of this resource ownership?",
defaultValue: false,
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
}

View File

@@ -0,0 +1,538 @@
import AlertEpisode from "./AlertEpisode";
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("alertEpisode")
@TenantColumn("projectId")
@TableAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.DeleteAlertEpisodeStateTimeline,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeStateTimeline,
],
})
@EnableWorkflow({
create: true,
delete: true,
update: true,
read: true,
})
@CrudApiEndpoint(new Route("/alert-episode-state-timeline"))
@Entity({
name: "AlertEpisodeStateTimeline",
})
@Index(["alertEpisodeId", "startsAt"])
@TableMetadata({
tableName: "AlertEpisodeStateTimeline",
singularName: "Alert Episode State Timeline",
pluralName: "Alert Episode State Timelines",
icon: IconProp.List,
tableDescription:
"Change state of the alert episodes (Created to Acknowledged for example)",
})
export default class AlertEpisodeStateTimeline extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: "alertEpisodeId",
type: TableColumnType.Entity,
modelType: AlertEpisode,
title: "Alert Episode",
description: "Relation to Alert Episode in which this resource belongs",
})
@ManyToOne(
() => {
return AlertEpisode;
},
{
eager: false,
nullable: true,
onDelete: "CASCADE",
orphanedRowAction: "nullify",
},
)
@JoinColumn({ name: "alertEpisodeId" })
public alertEpisode?: AlertEpisode = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
title: "Alert Episode ID",
description: "Relation to Alert Episode ID in which this resource belongs",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertEpisodeId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
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",
modelType: 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.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeStateTimeline,
],
})
@TableColumn({
manyToOneRelationColumn: "alertStateId",
type: TableColumnType.Entity,
modelType: AlertState,
title: "Alert State",
description:
"Alert State Relation. Which alert state does this episode 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.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditAlertEpisodeStateTimeline,
],
})
@Index()
@TableColumn({
type: TableColumnType.ObjectID,
required: true,
title: "Alert State ID",
description:
"Alert State ID Relation. Which alert state does this episode change to?",
})
@Column({
type: ColumnType.ObjectID,
nullable: false,
transformer: ObjectID.getDatabaseTransformer(),
})
public alertStateId?: ObjectID = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
update: [],
})
@Index()
@TableColumn({
type: TableColumnType.Boolean,
required: true,
isDefaultValueColumn: true,
title: "Are Owners Notified",
description: "Are owners notified of state change?",
defaultValue: false,
})
@Column({
type: ColumnType.Boolean,
nullable: false,
default: false,
})
public isOwnerNotified?: boolean = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
isDefaultValueColumn: false,
required: false,
type: TableColumnType.JSON,
computed: true,
})
@Column({
type: ColumnType.JSON,
nullable: true,
unique: false,
})
public stateChangeLog?: JSONObject = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
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.CreateAlertEpisodeStateTimeline,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertEpisodeStateTimeline,
Permission.ReadAllProjectResources,
],
update: [],
})
@TableColumn({
type: TableColumnType.Date,
title: "Starts At",
description: "When did this status change?",
})
@Column({
type: ColumnType.Date,
nullable: true,
unique: false,
})
public startsAt?: Date = undefined;
}

View File

@@ -38,6 +38,8 @@ export enum AlertFeedEventType {
OwnerTeamRemoved = "OwnerTeamRemoved",
OnCallPolicy = "OnCallPolicy",
OnCallNotification = "OnCallNotification",
AddedToEpisode = "AddedToEpisode",
RemovedFromEpisode = "RemovedFromEpisode",
}
@EnableDocumentation()
@@ -55,6 +57,7 @@ export enum AlertFeedEventType {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
delete: [],
update: [],
@@ -90,6 +93,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -126,6 +130,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -157,6 +162,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -193,6 +199,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -223,6 +230,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -260,6 +268,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -335,6 +344,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -365,6 +375,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -393,6 +404,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -422,6 +434,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -454,6 +467,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -491,6 +505,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -520,6 +535,7 @@ export default class AlertFeed extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertFeed,
Permission.ReadAllProjectResources,
],
update: [],
})

File diff suppressed because it is too large Load Diff

View File

@@ -43,6 +43,7 @@ import {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -87,6 +88,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -123,6 +125,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -154,6 +157,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -190,6 +194,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -220,6 +225,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -257,6 +263,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -333,6 +340,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -367,6 +375,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -410,6 +419,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -443,6 +453,7 @@ export default class AlertInternalNote extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertInternalNote,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -40,6 +40,7 @@ import { PlanType } from "../../Types/Billing/SubscriptionPlan";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -84,6 +85,7 @@ export default class AlertNoteTemplate extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -121,6 +123,7 @@ export default class AlertNoteTemplate extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -152,6 +155,7 @@ export default class AlertNoteTemplate extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -188,6 +192,7 @@ export default class AlertNoteTemplate extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -223,6 +228,7 @@ export default class AlertNoteTemplate extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -259,6 +265,7 @@ export default class AlertNoteTemplate extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -297,6 +304,7 @@ export default class AlertNoteTemplate extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertNoteTemplate,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -33,6 +33,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -78,6 +79,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -115,6 +117,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -146,6 +149,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -184,6 +188,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -215,6 +220,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -252,6 +258,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -283,6 +290,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -321,6 +329,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -345,6 +354,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -379,6 +389,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -408,6 +419,7 @@ export default class AlertOwnerTeam extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerTeam,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -32,6 +32,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -77,6 +78,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -114,6 +116,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -145,6 +148,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -183,6 +187,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -214,6 +219,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -251,6 +257,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -282,6 +289,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -320,6 +328,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -344,6 +353,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -378,6 +388,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -407,6 +418,7 @@ export default class AlertOwnerUser extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertOwnerUser,
Permission.ReadAllProjectResources,
],
update: [],
})

View File

@@ -44,6 +44,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
delete: [
Permission.ProjectOwner,
@@ -91,6 +92,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -127,6 +129,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -158,6 +161,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -189,6 +193,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -219,6 +224,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -254,6 +260,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -291,6 +298,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -314,6 +322,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -347,6 +356,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [],
})
@@ -375,6 +385,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,
@@ -414,6 +425,7 @@ export default class AlertSeverity extends BaseModel {
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadAlertSeverity,
Permission.ReadAllProjectResources,
],
update: [
Permission.ProjectOwner,

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