Compare commits

...

595 Commits

Author SHA1 Message Date
Simon Larsen
ba6ac2e32e refactor: Update symbol type to use lowercase 'symbol' in ColumnAccessControl files 2024-06-14 12:34:56 +01:00
Simon Larsen
1498656a43 refactor: Update symbol type to use lowercase 'symbol' in ColumnAccessControl files 2024-06-14 12:15:36 +01:00
Simon Larsen
70a2a3993b refactor: Update symbol type to use lowercase 'symbol' in ColumnAccessControl files 2024-06-14 12:09:53 +01:00
Simon Larsen
5152d5de12 refactor: Remove @trivago/prettier-plugin-sort-imports and update eslint configuration
This commit removes the "@trivago/prettier-plugin-sort-imports" plugin from the ".prettierrc.json" file and updates the eslint configuration in the "package.json" file. The plugin was removed because it is no longer needed and caused conflicts with the updated eslint configuration. This change improves the codebase by simplifying the prettier configuration and ensuring compatibility with the updated eslint rules.
2024-06-14 12:07:16 +01:00
Simon Larsen
2999e539b3 refactor: Update symbol type to use lowercase 'symbol' in ColumnAccessControl files 2024-06-14 12:01:14 +01:00
Simon Larsen
8ce432256c refactor: Update symbol type to use lowercase 'symbol' in ColumnAccessControl files
This commit updates the symbol type from 'Symbol' to 'symbol' in the ColumnAccessControl files. The use of 'symbol' aligns with the TypeScript convention for symbol types. This change improves code consistency and readability.
2024-06-14 11:53:27 +01:00
Simon Larsen
ddbfbac802 refactor: Remove unused files and update eslint configuration 2024-06-14 11:51:38 +01:00
Simon Larsen
1d6a7ee1fa feat: Add timezone dropdown to user profile page
This commit adds a new dropdown component for selecting the timezone on the user profile page. The dropdown options are populated using the `TimezoneCode` enum from the `Common/Types/TimezoneCode.ts` file. Users can now select their timezone, which will be used for all date and time related notifications sent to them. This enhancement improves the user experience by providing a convenient way to set the timezone preference.
2024-06-14 11:21:25 +01:00
Simon Larsen
0d97f0447a refactor: Improve error handling in API class
This commit refactors the API class in API.ts to improve error handling. The `getFriendlyErrorMessage` method now includes additional error cases and returns more specific error messages for network errors, timeouts, request aborts, cancellations, connection issues, and SSL certificate expiration. This change enhances the user experience by providing clearer and more informative error messages.
2024-06-14 10:57:19 +01:00
Simon Larsen
36a13b60fe refactor: Update notification subjects for incidents and announcements 2024-06-14 10:20:57 +01:00
Simon Larsen
64f4fcf829 refactor: Update notification subjects for incidents and announcements 2024-06-14 10:06:38 +01:00
Simon Larsen
1ff7c84d82 refactor: Update notification subjects for incidents and announcements
This commit updates the notification subjects for incidents and announcements in the SendNotificationToSubscribers.ts files. The subjects now include a prefix indicating the type of notification (e.g., [Incident], [Announcement]) followed by the status page name. This change improves the clarity and consistency of the notification emails and SMS messages sent to subscribers.
2024-06-14 10:05:48 +01:00
Simon Larsen
da623d4d34 increase timeout 2024-06-14 10:00:03 +01:00
Simon Larsen
affa492ce3 refactor: Improve SSL certificate error handling
This commit refactors the API class in API.ts to improve the handling of SSL certificate errors. The `getFriendlyErrorMessage` method now includes specific error messages for different SSL certificate issues, such as expired certificates, certificates signed by unknown authorities, and self-signed certificates. This enhancement enhances the user experience by providing clearer and more informative error messages for SSL certificate errors.
2024-06-13 21:50:59 +01:00
Simon Larsen
5ae3a5b5ee refactor: Improve error handling in API class
The API class in API.ts has been updated to improve error handling. The getFriendlyErrorMessage method now includes additional error cases and returns more specific error messages for network errors, timeouts, request aborts, cancellations, connection issues, and SSL certificate expiration. This change enhances the user experience by providing clearer and more informative error messages.
2024-06-13 21:50:10 +01:00
Simon Larsen
5716ab2445 refactor: Update API error handling and display
The API class in API.ts has been updated to improve error handling and display. The getFriendlyErrorMessage method now includes additional error cases and returns more specific error messages for network errors, timeouts, request aborts, cancellations, connection issues, and SSL certificate expiration. This change enhances the user experience by providing clearer and more informative error messages.
2024-06-13 21:45:56 +01:00
Simon Larsen
a66a04456b refactor: Update endpoint URLs for status check script 2024-06-13 21:44:49 +01:00
Simon Larsen
e97a78eaeb Merge branch 'ai-copilot-main' 2024-06-13 21:12:48 +01:00
Simon Larsen
57f41a908a refactor: Improve login test to handle missing user credentials 2024-06-13 21:11:54 +01:00
Simon Larsen
f42291a428 refactor: Update status check URLs for Dashboard, Status Page, and Accounts
The status-check.sh script has been modified to update the endpoint URLs for checking the status of the Dashboard, Status Page, and Accounts services. The URLs now include "/status/ready" at the end, ensuring that the services are ready to handle requests. This change improves the accuracy and reliability of the status check script.
2024-06-13 21:05:37 +01:00
Simon Larsen
4fa9adfc7d refactor: Update login test to handle missing user credentials
The login test in Login.spec.ts has been updated to handle cases where the user credentials (email and password) are missing. Previously, the test would only check if the user is registered, but now it also checks if the registered user email and password are available. This change ensures that the test behaves correctly in all scenarios and improves the reliability of the login functionality.
2024-06-13 18:49:19 +01:00
Simon Larsen
3e2e581e52 ```text
refactor: Update artifact upload paths in release and test workflows

The artifact upload paths in the release.yml, test-release.yaml, and test.e2e.yaml workflows have been updated to include the entire E2E directory instead of specific subdirectories. This change simplifies the configuration and ensures that all necessary files are included in the artifacts.
2024-06-13 18:39:02 +01:00
Simon Larsen
2a3c34af95 refactor: Add endpoint to retrieve Copilot events by file
This commit adds a new endpoint to the CodeRepositoryAPI class in CodeRepositoryAPI.ts. The endpoint allows users to retrieve Copilot events for a specific file in the code repository. It takes in a secret key, file path, and service catalog ID as parameters and returns a list of Copilot events. This enhancement improves the functionality and usability of the API.
2024-06-13 14:55:31 +01:00
Simon Larsen
170b79e4cf refactor: Add CopilotEventStatus column to CopilotEvent model
This commit adds a new column, CopilotEventStatus, to the CopilotEvent model in the CopilotEvent.ts file. The CopilotEventStatus column represents the status of a Copilot event that was triggered for a file in the code repository. This enhancement improves the functionality and flexibility of the CopilotEvent model.
2024-06-13 14:39:26 +01:00
Simon Larsen
c15b8bb951 refactor: Update CodeRepositoryUtil to include serviceRepository parameter in createBranch and createOrCheckoutBranch 2024-06-13 14:11:09 +01:00
Simon Larsen
17c47f7d89 refactor: Update ServiceFileTypesUtil to include common directories and files to ignore 2024-06-13 13:32:16 +01:00
Simon Larsen
a406287215 refactor: Update branch name in Copilot/Index.ts and add GITHUB_USERNAME to .env.example
This commit updates the branch name in Copilot/Index.ts from 'test-branch-3' to 'test-branch-4'. Additionally, it adds the GITHUB_USERNAME variable to the .env.example file. These changes improve the accuracy and functionality of the code.
2024-06-13 13:10:14 +01:00
Simon Larsen
a73b050a4d refactor: Update CodeRepositoryUtil to include serviceRepository parameter in createBranch and createOrCheckoutBranch
This commit modifies the CodeRepositoryUtil class in CodeRepository.ts to include a new parameter, serviceRepository, in the createBranch and createOrCheckoutBranch methods. This change allows for better integration with the ServiceRepository class and improves the flexibility and maintainability of the code.
2024-06-13 12:47:42 +01:00
Simon Larsen
224fb2e887 Merge pull request #1479 from OneUptime/snyk-upgrade-fb48859c6d1e1f5c6c32c4f5abf203c1
[Snyk] Upgrade posthog-js from 1.132.0 to 1.133.0
2024-06-13 12:34:04 +01:00
Simon Larsen
96d4131614 refactor: Add createPullRequest method to HostedCodeRepository
The HostedCodeRepository class in HostedCodeRepository.ts has been updated to include a new method, createPullRequest. This method allows for the creation of pull requests in the code repository. This change enhances the functionality and flexibility of the HostedCodeRepository class.
2024-06-13 12:26:49 +01:00
snyk-bot
cda00d5238 fix: upgrade posthog-js from 1.132.0 to 1.133.0
Snyk has created this PR to upgrade posthog-js from 1.132.0 to 1.133.0.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-13 00:27:42 +00:00
Simon Larsen
dea385ad44 refactor: Update ServiceFileTypesUtil to include common directories and files to ignore
The ServiceFileTypesUtil class in ServiceFileTypes.ts has been updated to include two new methods: getCommonDirectoriesToIgnore and getCommonFilesToIgnore. These methods return arrays of common directories and files that should be ignored in code repositories. This change improves the functionality and maintainability of the code by providing a centralized way to define and retrieve the directories and files to ignore.
2024-06-12 22:10:47 +01:00
Simon Larsen
21973401fb refactor: Improve file extension handling in CodeRepositoryUtil
The CodeRepositoryUtil class in CodeRepository.ts has been refactored to improve the handling of file extensions. The changes include:
- Simplifying the logic for skipping files with unsupported extensions
- Adding support for accepted file extensions in the getFilesInDirectory method

These improvements enhance the functionality and maintainability of the code.
2024-06-12 22:07:01 +01:00
Simon Larsen
d153ad9bf7 refactor: Update ServiceRepository to include serviceLanguage field
The ServiceRepository class in ServiceRepository.ts has been updated to include a new field, serviceLanguage. This field is of type ServiceLanguage and is required. This change allows for better organization and identification of code repositories based on their programming language.
2024-06-12 21:27:00 +01:00
Simon Larsen
2ce8ba6295 refactor: Sanitize file paths in CodeRepositoryUtil and LocalFile
This commit refactors the CodeRepositoryUtil and LocalFile classes to include a new method, sanitizeFilePath, which removes double slashes from file paths. This change ensures that file paths are properly formatted and improves the reliability and maintainability of the code.
2024-06-12 21:05:37 +01:00
Simon Larsen
572130d349 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-06-12 20:21:07 +01:00
Simon Larsen
f0cb049266 refactor: Update CodeRepositoryView component in Index.tsx
The CodeRepositoryView component in Index.tsx has been updated to include a new field for the repository name. This change allows for better organization and identification of code repositories within the system.
2024-06-12 20:20:40 +01:00
Simon Larsen
cab5af6645 refactor: Add organizationName and repositoryName fields to CodeRepository
The CodeRepository entity has been updated to include two new fields: organizationName and repositoryName. These fields are of type character varying(100) and are required. This change allows for better organization and identification of code repositories within the system.
2024-06-12 20:18:30 +01:00
Simon Larsen
e77b923dc1 Merge pull request #1472 from OneUptime/ai-copilot-main
Copilot Main
2024-06-12 19:20:49 +01:00
Simon Larsen
8325c06ca3 refactor: Update status check URLs for Dashboard and Status Page
The status-check.sh script has been modified to update the endpoint URLs for checking the status of the Dashboard and Status Page services. The URLs now include "/status/ready" at the end, ensuring that the services are ready to handle requests. This change improves the accuracy and reliability of the status check script.
2024-06-12 17:27:22 +01:00
Simon Larsen
b66f56bc12 refactor: Update endpoint status check URLs to include "/ready"
The status-check.sh script has been updated to modify the endpoint URLs for checking the status of various services. The URLs now include "/ready" at the end, indicating that the services are ready to handle requests. This change ensures that the status check accurately reflects the readiness of the services and improves the reliability of the script.
2024-06-12 17:25:08 +01:00
Simon Larsen
2de2926d79 refactor: Add MigrationName1718203144945 to SchemaMigrations/Index.ts
The SchemaMigrations/Index.ts file has been updated to include the MigrationName1718203144945 migration. This change ensures that the new migration is included in the list of schema migrations, allowing for proper database versioning and management.
2024-06-12 15:39:55 +01:00
Simon Larsen
fd13e91aac refactor: Update ServiceRepository to use number type for limitNumberOfOpenPullRequestsCount
The ServiceRepository class in ServiceRepository.ts has been updated to use the number type for the limitNumberOfOpenPullRequestsCount property instead of the string type. This change ensures that the property is correctly typed and improves the accuracy and reliability of the code.
2024-06-12 15:38:54 +01:00
Simon Larsen
cf7d4c7720 refactor: Update GitHubUtil to use HostedCodeRepository/HostedCodeRepository 2024-06-12 15:11:50 +01:00
Simon Larsen
b1a76e97ce Merge pull request #1477 from OneUptime/snyk-upgrade-4dc39844f330c9a5f3d5be2668e24709
[Snyk] Upgrade axios from 1.7.0 to 1.7.2
2024-06-12 14:19:29 +01:00
Simon Larsen
7d8036e3eb refactor: Update GitHubUtil to use HostedCodeRepository/HostedCodeRepository
The GitHubUtil class in GitHub.ts has been updated to import the HostedCodeRepository class from the correct file path, "HostedCodeRepository/HostedCodeRepository". This change ensures that the correct class is imported and used, improving the functionality and maintainability of the code.
2024-06-12 13:18:20 +01:00
Simon Larsen
c7344a7624 refactor: Remove commented out code and unused imports
The CodeRepositoryType.ts file has been refactored to remove commented out code and unused imports. This change improves code cleanliness and reduces unnecessary clutter in the file.
2024-06-12 12:25:12 +01:00
Simon Larsen
42253e4e50 refactor: Update GitHub token handling in Config.ts 2024-06-12 11:59:22 +01:00
Simon Larsen
64acf372d6 refactor: Update GitHub token handling in Config.ts
The Config.ts file has been updated to handle the GitHub token more efficiently. The GetGitHubToken function now checks the repository type and throws an exception if a GitHub token is required but not provided. This change improves the security and reliability of the application by ensuring that the correct token is used for GitHub repositories.
2024-06-12 11:31:50 +01:00
snyk-bot
80f4238618 fix: upgrade axios from 1.7.0 to 1.7.2
Snyk has created this PR to upgrade axios from 1.7.0 to 1.7.2.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/49c81d9c-12c2-4e8e-b9e8-72f98b1b595c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-12 04:53:12 +00:00
Simon Larsen
2fe54c46c1 Merge pull request #1475 from OneUptime/snyk-upgrade-d4dca93f2a1a1e81fe41908a5a826632
[Snyk] Upgrade posthog-js from 1.131.4 to 1.132.0
2024-06-11 19:55:56 +01:00
Simon Larsen
266b046b9e Merge pull request #1474 from OneUptime/snyk-upgrade-8df461c2c34dd57552a05c7122331e04
[Snyk] Upgrade axios from 1.7.1 to 1.7.2
2024-06-11 19:55:45 +01:00
snyk-bot
f311841df2 fix: upgrade posthog-js from 1.131.4 to 1.132.0
Snyk has created this PR to upgrade posthog-js from 1.131.4 to 1.132.0.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-11 18:09:12 +00:00
snyk-bot
26319ff3c8 fix: upgrade axios from 1.7.1 to 1.7.2
Snyk has created this PR to upgrade axios from 1.7.1 to 1.7.2.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-11 18:09:07 +00:00
Simon Larsen
e719bb3b70 refactor: Add doNotShowWhenEditing flag to ServiceRepositoryPage component
The ServiceRepositoryPage component has been updated to include a new flag, doNotShowWhenEditing, which controls whether a certain field should be displayed when editing a service. This change improves the user experience by allowing for more flexibility in customizing the form fields based on the editing mode.
2024-06-11 18:38:37 +01:00
Simon Larsen
d0255c1e33 feat: Enable editing of services in ServiceRepositoryPage 2024-06-11 18:37:49 +01:00
Simon Larsen
52f4c74908 refactor: Update noItemsMessage prop types to include ReactElement
The prop types for the noItemsMessage prop have been updated in multiple components to include the ReactElement type. This change allows for passing React elements as the no items message, providing more flexibility in customizing the message's content and appearance.
2024-06-11 18:34:25 +01:00
Simon Larsen
eeb6904c2d refactor: Update title of Service Catalog field in ServiceRepositoryPage
The title of the Service Catalog field in the ServiceRepositoryPage component has been updated from "Service Catalog" to "Service". This change improves clarity and consistency in the user interface.
2024-06-11 18:31:10 +01:00
Simon Larsen
6fd37c62b8 refactor: Add MigrationName1718126316684 to SchemaMigrations/Index.ts
This commit adds the MigrationName1718126316684 to the list of schema migrations in the Index.ts file. The new migration introduces changes to the database schema and ensures that the codebase is up to date with the latest schema changes. This enhancement improves the maintainability and functionality of the application.
2024-06-11 18:29:19 +01:00
Simon Larsen
16b761e498 feat: Add option to enable pull requests for services in ServiceRepositoryPage
This commit adds a new field to the ServiceRepositoryPage component, allowing users to enable or disable pull requests for a service. When enabled, OneUptime will create pull requests for the service and automatically improve the code. This enhancement provides more control over pull request generation and improves the functionality of the ServiceRepositoryPage.
2024-06-11 18:21:51 +01:00
Simon Larsen
9b1e702c64 refactor: Add enablePullRequests property to ServiceRepository model
The enablePullRequests property has been added to the ServiceRepository model. This property allows for enabling or disabling automatic pull request creation by Copilot for this service. By default, enablePullRequests is set to true, indicating that Copilot will create pull requests for this service to automatically improve the codebase. This change enhances the functionality of the ServiceRepository model and provides more control over pull request generation.
2024-06-11 18:19:51 +01:00
Simon Larsen
f10fa9a48e ```text
refactor: Update defaultValue property in Field interface

The defaultValue property in the Field interface has been updated to include the number type. This change allows for setting default values of type number in form fields.
2024-06-11 18:15:09 +01:00
Simon Larsen
de91346155 refactor: Remove CopilotServiceService and update references to ServiceRepositoryService 2024-06-11 17:49:14 +01:00
Simon Larsen
629a442ff7 refactor: Remove CopilotServiceService and update references to ServiceRepositoryService
This commit removes the CopilotServiceService module, which is no longer needed. It also updates the references to the CopilotService class to use the ServiceRepository class instead. This change improves code organization and consistency by using the appropriate service class for managing service repositories.
2024-06-11 17:38:18 +01:00
Simon Larsen
be54d782e5 refactor: Update page title in CodeRepositoryViewLayout component 2024-06-11 17:30:39 +01:00
Simon Larsen
029c1b0704 refactor: Add CopilotService to BaseAPIFeatureSet
This commit adds the CopilotService to the BaseAPIFeatureSet in the Index.ts file. The CopilotService is imported from the CopilotServiceService module and is used to create a new router for the "/app" endpoint. This change allows for handling requests related to the CopilotService in the application.
2024-06-11 16:56:42 +01:00
Simon Larsen
36cfb7e20f refactor: Add new migrations for SchemaMigrations and Models
New migrations have been added to the SchemaMigrations and Models directories. These migrations introduce new changes to the database schema and model definitions. This commit ensures that the codebase is up to date with the latest schema changes and improves the maintainability of the application.
2024-06-11 16:52:56 +01:00
Simon Larsen
02046a525e refactor: Update service catalog titles to use consistent naming convention
The titles of the ServiceCatalog and ServiceCatalogOwnerTeam classes have been updated to use a consistent naming convention. The "ServiceCatalog" title has been changed to "Service Catalog" and the "ServiceCatalog ID" title has been changed to "Service Catalog ID". This change improves clarity and readability in the codebase.
2024-06-11 16:51:12 +01:00
Simon Larsen
c9a998da0b refactor: Add service language dropdown in ServiceCatalog form 2024-06-11 16:35:23 +01:00
Simon Larsen
7fc192e466 refactor: Quote the value of ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN in _helpers.tpl
The value of ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN in _helpers.tpl has been updated to be quoted using the | quote filter. This change ensures that the value is treated as a string, improving consistency and compatibility with other parts of the codebase.
2024-06-11 16:24:55 +01:00
Simon Larsen
eae8b79b2e refactor: Add debug configuration for running Copilot locally
A new debug configuration has been added to the launch.json file. This configuration allows for launching Copilot locally by running the "start" script using npm. It skips files in the "<node_internals>" directory and is specifically configured for debugging Node.js applications. This change improves the development experience by enabling easy debugging of Copilot locally.
2024-06-11 15:11:00 +01:00
Simon Larsen
08c6cf31a0 refactor: Update linting configuration to exclude .tsx files
The linting configuration in the package.json file has been updated to exclude .tsx files from linting. This change ensures that the linting process only targets .ts files and improves the efficiency of the linting process.
2024-06-11 15:04:28 +01:00
Simon Larsen
dfb7f2320c refactor: Update jest.config.json files with testPathIgnorePatterns
The jest.config.json files in the Model, Probe, Common, Copilot, CommonUI, Ingestor, IsolatedVM, TestServer, and CommonServer directories have been updated. The "testPathIgnorePatterns" property has been added to each file, excluding the "node_modules" and "dist" directories from test path matching. This change improves test performance and ensures that unnecessary files are not included in the test coverage.
2024-06-11 14:52:55 +01:00
Simon Larsen
c53b14f88f refactor: Update CodeRepositoryUtil methods to accept repoPath parameter
The CodeRepositoryUtil methods getGitCommitHashForFile and getFilesInDirectory have been updated to accept a repoPath parameter. This change allows for specifying the repository path when retrieving the git commit hash for a file or getting the files in a directory. It improves the flexibility and reusability of the CodeRepositoryUtil class.
2024-06-11 14:24:19 +01:00
Simon Larsen
c5680f6c26 refactor: Update import statements in MonitorService.ts
The import statements in the MonitorService.ts file have been updated to import the AllowedActiveMonitorCountInFreePlan and IsBillingEnabled constants from the EnvironmentConfig module. This change ensures that the codebase is using the correct import paths and improves code readability.
2024-06-11 13:53:05 +01:00
Simon Larsen
d2a1385123 refactor: Update ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN to 10
The ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN constant has been updated to 10 in multiple files. This change aligns the codebase with the new limit for active monitors allowed in the free plan.
2024-06-11 13:50:55 +01:00
Simon Larsen
feda1b0426 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-06-11 13:26:28 +01:00
Simon Larsen
b97cc46a1e refactor: Remove commented code in NavBar.tsx
The commented code in the NavBar.tsx file has been removed. This change cleans up the codebase and improves readability.
2024-06-11 13:26:00 +01:00
Simon Larsen
41a8101b54 refactor: Update CodeRepositoryAPI endpoint to use POST method for getting code repository 2024-06-11 13:25:41 +01:00
Simon Larsen
676a2b18b3 refactor: Update CodeRepositoryAPI endpoint to use POST method for getting code repository 2024-06-11 13:20:52 +01:00
Simon Larsen
df7477929b refactor: Update CodeRepositoryAPI endpoint to use POST method for getting code repository
This code change updates the CodeRepositoryAPI endpoint in the CodeRepositoryAPI.ts file to use the POST method instead of the GET method for getting the code repository. The route has also been modified to "/get-code-repository/:secretkey" to align with the API design. This change ensures that the code repository is retrieved securely and follows the recommended RESTful API practices.
2024-06-11 13:00:33 +01:00
Simon Larsen
c1ebe14c50 refactor: Add CodeRepositoryAPI to BaseAPIFeatureSet
This code change adds the CodeRepositoryAPI endpoint to the BaseAPIFeatureSet in the App/FeatureSet/BaseAPI/Index.ts file. It imports the CodeRepository model and service, and includes the necessary routing and configuration for the endpoint. This change allows for the CRUD operations on CodeRepository data through the API.
2024-06-11 12:47:47 +01:00
Simon Larsen
2b478e7a13 refactor: Add TableBillingAccessControl to MonitorOwnerTeam, MonitorOwnerUser, StatusPageOwnerTeam, MonitorGroupOwnerTeam, MonitorGroupOwnerUser models
This code change adds the TableBillingAccessControl decorator to the MonitorOwnerTeam, MonitorOwnerUser, StatusPageOwnerTeam, MonitorGroupOwnerTeam, and MonitorGroupOwnerUser models. The decorator configures the access control settings for these models based on the specified subscription plans. This change ensures that the appropriate access control rules are applied when creating, reading, updating, or deleting records in these models.
2024-06-11 12:37:48 +01:00
Simon Larsen
3bb1d93f3e feat: Add forceNavigate option when navigating to new item
The DuplicateModel component in CommonUI has been updated to include a new option, forceNavigate, when navigating to a new item. This option allows for forced navigation to the new item, bypassing any checks or validations. This change provides more control over the navigation behavior and ensures consistent navigation to the new item.
2024-06-11 12:29:50 +01:00
Simon Larsen
703c4b7685 feat: Add doNotShowWhenCreating option to Field interface
The Field interface in the CommonUI project has been updated to include a new property, doNotShowWhenCreating. This property allows developers to specify whether a field should be shown in the form when creating a new entity. By setting doNotShowWhenCreating to true, the field will be hidden during the creation process. This change provides more control over the visibility of fields in the form based on the create or edit mode.
2024-06-11 11:33:26 +01:00
Simon Larsen
d7e9776a3c refactor: Update CodeRepository.getRepository() to return a Promise
Update CodeRepository.getRepository() to return a Promise<CodeRepositoryModel> instead of a string. This change improves the functionality and flexibility of the CodeRepository class.
2024-06-11 11:10:36 +01:00
Simon Larsen
3cb29b63fe refactor: Update CodeRepository.getRepository() to return a Promise
The CodeRepository.getRepository() method has been updated to return a Promise<CodeRepositoryModel> instead of a string. This change ensures that the method is asynchronous and can handle asynchronous operations, improving the overall functionality and flexibility of the CodeRepository class.
2024-06-10 22:10:29 +01:00
Simon Larsen
e7f4a36ec9 refactor: Update Copilot startup message for clarity
The startup message in the Copilot/Index.ts file has been updated to provide a clearer description of the application. This change improves the readability and understanding of the log output during the startup process.
2024-06-10 22:09:25 +01:00
Simon Larsen
be78862e49 Merge pull request #1470 from OneUptime/snyk-upgrade-ff9eba0658b72fe88ae2d11836a86990
[Snyk] Upgrade axios from 1.6.8 to 1.7.1
2024-06-10 19:45:41 +01:00
Simon Larsen
64ae5eeb89 add code repository basic functions 2024-06-10 19:40:27 +01:00
Simon Larsen
78bdc42534 refactor: Update SelfSignedSSL class to use async/await for generating SSL certificates 2024-06-10 19:25:41 +01:00
snyk-bot
68c81734e8 fix: upgrade axios from 1.6.8 to 1.7.1
Snyk has created this PR to upgrade axios from 1.6.8 to 1.7.1.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-10 17:16:56 +00:00
Simon Larsen
bf081d1ebe refactor: Update file paths in code changes 2024-06-10 17:59:22 +01:00
Simon Larsen
3de407842e refactor: Add CopilotEvent API endpoint to BaseAPIFeatureSet
This code change adds the CopilotEvent API endpoint to the BaseAPIFeatureSet in the App/FeatureSet/BaseAPI/Index.ts file. It imports the CopilotEvent model and service, and includes the necessary routing and configuration for the endpoint. This change allows for the CRUD operations on CopilotEvent data through the API.
2024-06-10 17:45:00 +01:00
Simon Larsen
a4a9e45fe0 refactor: Update Dockerfile and build steps for Copilot service
This code change updates the Dockerfile and build steps for the Copilot service. It adds a new workflow job, `docker-build-copilot`, which builds the Docker image for the Copilot service. The job includes steps to checkout the code, preinstall dependencies, and build the Docker image using the specified Dockerfile. This change ensures that the Copilot service is built and deployed correctly in the CI/CD pipeline.
2024-06-10 17:19:25 +01:00
Simon Larsen
f9c9480434 refactor: Update logger to use configured log level
This code change updates the logger class to use the configured log level from the environment configuration. The getLogLevel method is added to retrieve the log level, and the info, error, warn, and debug methods are updated to check the log level before logging the message. This change ensures that the logger behaves according to the configured log level, improving the consistency and control of log output.
2024-06-10 17:00:07 +01:00
Simon Larsen
eb644ad2f2 Merge branch 'master' into ai-copilot-main 2024-06-10 16:45:19 +01:00
Simon Larsen
5186e193a8 Merge pull request #1468 from OneUptime/snyk-upgrade-d773ac20b9cf77163d96fbbdf2660a1f
[Snyk] Upgrade axios from 1.6.8 to 1.7.0
2024-06-10 14:39:04 +01:00
Simon Larsen
55d947fb39 refactor: Add isMonotonic column to Metric model
This code change adds a new column, 'isMonotonic', to the Metric model in the AnalyticsModels directory. The column is optional and represents whether the metric is monotonic. This change ensures that the necessary data is captured and stored correctly for metrics in the system.
2024-06-10 12:49:29 +01:00
Simon Larsen
77f1262ff5 refactor: Update Telemetry class to add gauge and histogram metrics
This code change updates the Telemetry class in the CommonServer/Utils directory to include methods for creating gauge and histogram metrics. The getGauge and getHistogram methods are added, allowing for the creation of observable gauges and histograms with specified names and descriptions. This change enhances the telemetry capabilities of the application by providing more options for metric tracking and analysis.
2024-06-10 12:39:49 +01:00
Simon Larsen
47bf8f9c89 refactor: Update EventItem component to dynamically apply styles based on event type
This code change updates the EventItem component to dynamically apply styles based on the event type. The classNames for the title and description elements are now generated based on the eventType prop, allowing for more flexibility in styling. This change improves the visual representation of different event types in the application.
2024-06-10 11:48:47 +01:00
Simon Larsen
4ca4f28d1c refactor: Add Point Type to Metric model
This code change adds a new column, 'Metric Point Type', to the Metric model in the AnalyticsModels directory. The column is optional and represents the type of metric point. This change ensures that the necessary data is captured and stored correctly for metrics in the system.
2024-06-10 11:45:23 +01:00
Simon Larsen
b6565ce2bb refactor: Add Aggregation Temporality column to Metric model
This code change adds a new column, 'Aggregation Temporality', to the Metric model in the AnalyticsModels directory. The column is required and represents the aggregation temporality of the metric. This change ensures that the necessary data is captured and stored correctly for metrics in the system.
2024-06-10 11:34:08 +01:00
snyk-bot
0704e1f556 fix: upgrade axios from 1.6.8 to 1.7.0
Snyk has created this PR to upgrade axios from 1.6.8 to 1.7.0.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/49c81d9c-12c2-4e8e-b9e8-72f98b1b595c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-10 04:54:58 +00:00
Simon Larsen
87c16d7bc3 refactor: Update needs array in test-e2e-release-saas and test-e2e-release-self-hosted jobs
This code change updates the needs array in the test-e2e-release-saas and test-e2e-release-self-hosted jobs in the release.yml file. The nginx-docker-image-deploy job has been added to the needs array to ensure that it is executed before these jobs. This change ensures that the necessary dependencies are met for the successful execution of the test-e2e-release-saas and test-e2e-release-self-hosted jobs.
2024-06-09 21:47:31 +01:00
Simon Larsen
cc66820e7b refactor: Remove commented code in NavBar component 2024-06-09 19:45:25 +01:00
Simon Larsen
a478f60a39 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-06-09 19:45:00 +01:00
Simon Larsen
5637f12d3a refactor: Remove commented code in NavBar component
This code change removes the commented code in the NavBar component that was no longer needed. The commented code was related to the AI Copilot feature and the Service Catalog feature, which have been refactored or removed from the application. Removing this commented code improves code readability and reduces clutter in the component.
2024-06-09 19:44:57 +01:00
Simon Larsen
27c28b17af refactor: Update viewPageRoute in CodeRepositoryPage component 2024-06-09 19:44:41 +01:00
Simon Larsen
c55b169488 Merge pull request #1460 from OneUptime/snyk-upgrade-46c810649599bbd5f034d681106116a8
[Snyk] Upgrade react-big-calendar from 1.12.1 to 1.12.2
2024-06-09 19:36:50 +01:00
Simon Larsen
9b584d69ff refactor: Update viewPageRoute in CodeRepositoryPage component 2024-06-09 19:35:28 +01:00
Simon Larsen
05c090445a change job names 2024-06-09 19:29:59 +01:00
Simon Larsen
597aeb74f4 add e2e to test release 2024-06-09 19:29:23 +01:00
Simon Larsen
b7191a9c2e update github e2e jobs 2024-06-09 19:25:34 +01:00
Simon Larsen
c686030014 ```text
refactor: Update viewPageRoute in CodeRepositoryPage component

This code change updates the viewPageRoute prop in the CodeRepositoryPage component to use the new route generated by the Navigation utility. This ensures that the component navigates to the correct view page when a code repository is clicked.
2024-06-09 19:21:02 +01:00
Simon Larsen
eed1078f06 refactor: Add viewPageRoute prop to CodeRepositoryPage component
This code change adds the viewPageRoute prop to the CodeRepositoryPage component in order to specify the route for viewing a code repository. This prop is set to the corresponding route from the RouteMap. By including this prop, the component will correctly navigate to the view page when the user clicks on a code repository.
2024-06-09 19:15:30 +01:00
Simon Larsen
051a3c43b2 refactor: Update Git Repository name to "Git Repositories" 2024-06-09 19:04:45 +01:00
Simon Larsen
a152813535 refactor: Add CodeRepository model and service
This code change adds the CodeRepository model and service to the project. It includes the following modifications:

- Added CodeRepository model to the Models/Index.ts file.
- Added CodeRepositoryService to the Services/Index.ts file.
- Created CodeRepositoryService.ts file with the necessary implementation.

These changes enable the project to manage code repositories.
2024-06-09 19:03:54 +01:00
Simon Larsen
decea5acfc refactor: Add AI Copilot breadcrumbs and code repository view 2024-06-09 19:03:23 +01:00
Simon Larsen
4c2dfb0f92 refactor: Add CodeRepository model, service, and permissions
This code change adds the CodeRepository model, service, and permissions to the project. It includes the following modifications:

- Added CodeRepository model to the Models/Index.ts file.
- Added CodeRepositoryService to the Services/Index.ts file.
- Created CodeRepositoryService.ts file with the necessary implementation.
- Updated Permission enum in the Permission.ts file to include CreateCodeRepository, DeleteCodeRepository, EditCodeRepository, and ReadCodeRepository permissions.

These changes enable the project to manage code repositories and define the necessary permissions for them.
2024-06-09 15:03:56 +01:00
Simon Larsen
a24bf077ce refactor: Improve error message in endpoint-status.sh
This code change updates the endpoint-status.sh script to improve the error message when the endpoint returns an HTTP status other than 200. The previous message mentioned that it usually takes a few minutes for the app to boot, which is not accurate. The updated message removes this misleading information and provides a more accurate description of the retry behavior.
2024-06-09 14:49:48 +01:00
Simon Larsen
2d82f50789 refactor: Enable cleanup and e2e cron jobs for development purposes 2024-06-09 14:39:14 +01:00
Simon Larsen
3e13776252 refactor: Improve BaseModelTable actions column logic
This code change updates the BaseModelTable component to improve the logic for determining whether to show the actions column. Previously, the actions column was shown based on various conditions, including permissions, action buttons, and the showViewIdButton prop. This logic has been refactored to simplify the conditions and make it easier to understand.

- The showActionsColumn variable is now initialized with the result of the Boolean function, which checks if any of the conditions are met.
- Additionally, if the user is a master admin, the actions column will always be shown, regardless of other conditions.

These changes enhance the readability and maintainability of the code, ensuring that the actions column is displayed correctly based on the specified conditions.
2024-06-09 13:18:56 +01:00
Simon Larsen
463bb32872 refactor: Enable cleanup and e2e cron jobs for development purposes
This code change updates the values.yaml file in the HelmChart/Public/oneuptime directory. It enables the cleanup and e2e cron jobs for development purposes. Please note that these cron jobs should not be enabled in production environments. This change allows for easier testing and debugging during development.
2024-06-09 12:48:42 +01:00
Simon Larsen
99dcee80cd refactor: Add support for Go language in CodeQL analysis workflow 2024-06-08 14:54:28 +01:00
Simon Larsen
c418dc41dd refactor: Add TypeScript support to CodeQL analysis workflow
This code change updates the CodeQL analysis workflow in the .github/workflows/codeql-analysis.yml file. It adds TypeScript as a supported language for CodeQL analysis, in addition to JavaScript. This ensures that the codebase can be thoroughly analyzed for potential security vulnerabilities and bugs in both JavaScript and TypeScript code.
2024-06-08 14:54:02 +01:00
Simon Larsen
c0678c410d refactor: Update SideMenu.tsx to fix indentation issue
This code change updates the SideMenu.tsx file in the ServiceCatalog/View directory. It fixes an indentation issue in the SideMenuItem component by properly aligning the opening tag. This ensures consistent code formatting and improves code readability.
2024-06-08 14:34:56 +01:00
Simon Larsen
081359f7e0 refactor: Update Delete.tsx to navigate to Service Catalog page after successful deletion
This code change updates the Delete.tsx file in the ServiceCatalog/View directory. It modifies the onDeleteSuccess callback function to navigate to the Service Catalog page (RouteMap[PageMap.SERVICE_CATALOG]) after a successful deletion. This ensures a smooth user experience by redirecting them to the appropriate page after completing the deletion process.
2024-06-08 14:26:02 +01:00
Simon Larsen
cc0cfe4f8c refactor: Update Settings.tsx to import ServiceCatalog instead of TelemetryService 2024-06-08 14:24:42 +01:00
Simon Larsen
dc87905f05 refactor: Update ServiceCatalogPage to include lazy loading for ServiceCatalogElement 2024-06-08 14:24:05 +01:00
Simon Larsen
9c31047d52 refactor: Update ServiceCatalogPage to include lazy loading for ServiceCatalogElement
This code change updates the ServiceCatalogPage component in ServiceCatalog.tsx to include lazy loading for the ServiceCatalogElement component. By implementing lazy loading, the page load performance is improved as the ServiceCatalogElement component is only loaded when it is actually needed. This enhances the overall user experience by reducing initial page load time.
2024-06-08 14:20:21 +01:00
Simon Larsen
91d196ddea refactor: Update ServiceCatalogRoutePath in RouteMap.ts
This code change updates the ServiceCatalogRoutePath in the RouteMap.ts file to include new routes for viewing, managing owners, and deleting service catalogs. This ensures that the application can properly handle these actions related to service catalogs within the dashboard.
2024-06-08 14:12:41 +01:00
Simon Larsen
78db5cab39 refactor: Update ServiceCatalogRoutePath in RouteMap.ts 2024-06-08 14:12:06 +01:00
Simon Larsen
689e72e5ec refactor: Update ServiceCatalogRoutePath in RouteMap.ts
This code change updates the ServiceCatalogRoutePath in the RouteMap.ts file to include new routes for viewing, managing owners, and deleting service catalogs. This ensures that the application can properly handle these actions related to service catalogs within the dashboard.
2024-06-08 14:05:24 +01:00
Simon Larsen
bc9e97f67c refactor: Fix typo in status pages description 2024-06-08 13:57:48 +01:00
Simon Larsen
19550c23ed refactor: Add ServiceCatalogOwnerTeamService and ServiceCatalogOwnerUserService to Services/Index.ts
This code change adds the ServiceCatalogOwnerTeamService and ServiceCatalogOwnerUserService to the Services/Index.ts file. These services are necessary for managing ownership of Service Catalogs, allowing teams and individual users to be assigned as owners of specific Service Catalogs.
2024-06-08 13:33:53 +01:00
Simon Larsen
2d09df2d87 feat: Add ServiceCatalogOwnerTeam and ServiceCatalogOwnerUser models
This code change adds the ServiceCatalogOwnerTeam and ServiceCatalogOwnerUser models to the project. These models are necessary for managing ownership of Service Catalogs, allowing teams and individual users to be assigned as owners of specific Service Catalogs.
2024-06-08 13:31:40 +01:00
Simon Larsen
2dfebdd2e4 refactor: Update SchemaMigrations/Index.ts to fix formatting
This code change fixes the formatting in the SchemaMigrations/Index.ts file. The changes include removing unnecessary whitespace and ensuring consistent indentation. This improves code readability and maintainability.
2024-06-08 13:16:51 +01:00
Simon Larsen
ebec143c9c refactor: Import and include ServiceCatalogService and ServiceCatalog model
This code change updates the Index.ts and Models/Index.ts files to import and include the ServiceCatalogService and ServiceCatalog model respectively. This allows for the management of Service Catalogs, including creating, deleting, editing, and reading them within the project.
2024-06-08 10:35:17 +01:00
Simon Larsen
aa68a6316a feat: Add Service Catalog permissions
This code change adds new permissions for managing Service Catalogs. The permissions include creating, deleting, editing, and reading Service Catalogs. These permissions allow users to perform various actions related to Service Catalogs within the project.

Refactor: Update Index.ts and Models/Index.ts to import and include the ServiceCatalogService and ServiceCatalog model respectively.
2024-06-08 10:25:37 +01:00
Simon Larsen
27a37581e4 Merge pull request #1461 from OneUptime/metric-detail
refactor: Update Navigation class to use getLastParamAsString method
2024-06-08 09:51:32 +01:00
Simon Larsen
091622f8cf refactor: Update StatementGenerator.ts to improve code readability and maintainability 2024-06-08 09:49:49 +01:00
Simon Larsen
87caae077c ```text
refactor: Change metric column types to decimal

This code change modifies the Metric model in the AnalyticsModels directory to change the column types of various metrics from TableColumnType.Number to TableColumnType.Decimal. This update ensures more accurate and precise calculations for the metrics.
2024-06-07 22:55:39 +01:00
Simon Larsen
a146691773 refactor: Improve code readability and maintainability in LogItem.tsx 2024-06-07 22:16:36 +01:00
Simon Larsen
9fce103b11 refactor: Update ResetPassword.tsx to improve password confirmation validation 2024-06-07 22:04:56 +01:00
Simon Larsen
2aa0ae89fc refactor: Improve code readability and maintainability in OTelIngest.ts 2024-06-07 21:45:09 +01:00
Simon Larsen
0a16f6bf44 refactor: Update OTelIngest.ts to improve code readability and maintainability 2024-06-07 21:27:11 +01:00
Simon Larsen
0f49e6e100 refactor: Improve code readability and maintainability in OTelIngest.ts 2024-06-07 17:49:58 +01:00
Simon Larsen
d954b4a5df refactor: Add unit column to metrics table and improve code readability in StatementGenerator.ts 2024-06-07 17:36:09 +01:00
Simon Larsen
e762778fc6 refactor: Improve code readability and maintainability in StatementGenerator.ts 2024-06-07 17:33:23 +01:00
Simon Larsen
4cced50857 feat: Add unit column to metrics table 2024-06-07 17:00:30 +01:00
Simon Larsen
26c900d8e2 refactor: Update CommonServer/package.json and Ingestor/Service/OTelIngest.ts
This code change updates the CommonServer/package.json file to remove the "@opentelemetry/metrics" dependency and adds the "@opentelemetry/sdk-metrics" dependency with version "^1.21.0". It also updates the Ingestor/Service/OTelIngest.ts file to import the "JSONFunctions" module from "Common/Types/JSONFunctions" and use the "flattenObject" function from that module to flatten the final object before returning it.
2024-06-07 16:57:24 +01:00
Simon Larsen
63461343ba refactor: Update OTelIngest.ts to improve code readability and maintainability
This code change updates the OTelIngest.ts file to improve code readability and maintainability. It includes formatting changes such as indentation and line breaks to enhance code structure and organization. These modifications make the code easier to understand and maintain for future development.
2024-06-07 14:57:24 +01:00
Simon Larsen
931abc522b refactor: Update Telemetry class to include new metrics for status checks 2024-06-07 14:54:39 +01:00
Simon Larsen
054592eed3 refactor: Update Telemetry class to include new metrics for status checks
This code change updates the Telemetry class to include new metrics for status checks. It adds counters for successful and failed status checks, including separate counters for ready and live checks. This modification enhances the monitoring capabilities of the application and provides more granular insights into the status of the system.
2024-06-07 14:25:40 +01:00
Simon Larsen
82b2307b51 Merge branch 'master' into metric-detail 2024-06-07 12:50:17 +01:00
Simon Larsen
b1dba73842 refactor: Update external database configuration in HelmChart
This code change updates the external database configuration in the HelmChart. It adds support for using an existing secret for the password instead of directly specifying the password. This modification enhances security and allows for easier management of the database credentials.
2024-06-07 10:11:27 +01:00
Simon Larsen
babbf5f8a6 refactor: Update external database configuration in HelmChart 2024-06-07 10:10:55 +01:00
Simon Larsen
39c7da79ab refactor: Update external database configuration in HelmChart
This code change updates the external database configuration in the HelmChart. It adds support for using an existing secret for the password instead of directly specifying the password. This modification enhances security and allows for easier management of the database credentials.
2024-06-07 10:10:00 +01:00
Simon Larsen
938bd32915 refactor: Update PageMap and RouteMap to include new telemetry metric page
This code change updates the PageMap and RouteMap files to include a new telemetry metric page. The new page, TELEMETRY_SERVICES_VIEW_METRIC, is added to both files with its corresponding route path. This modification ensures that the new page is properly mapped and accessible within the application.
2024-06-07 10:08:40 +01:00
Simon Larsen
f8e1ace311 refactor: Update Navigation class to use getLastParamAsString method 2024-06-06 21:45:29 +01:00
Simon Larsen
05e2e22e1d refactor: Update DATABASE_USERNAME value in _helpers.tpl
This code change updates the value of DATABASE_USERNAME in the _helpers.tpl file. The value is changed to "postgres" when the postgresql.enabled flag is true, and to the value of $.Values.externalPostgres.username when the flag is false. This modification ensures that the correct username is used for the database connection.
2024-06-06 21:19:19 +01:00
Simon Larsen
9054c49b3e refactor: Update Kubernetes secret retrieval commands
The code changes update the commands used to retrieve secrets from Kubernetes. The previous commands were using the deprecated `go-template` option, which has been replaced with the `jsonpath` option. This refactor ensures that the correct commands are used to retrieve the secrets, improving the reliability and maintainability of the code.
2024-06-06 18:36:05 +01:00
Simon Larsen
5d5468603f refactor: Add lazy loading for images in DateFilter component
This code change adds lazy loading for images in the DateFilter component. By implementing lazy loading, the images in the component will only load when they are in the viewport, improving the page load performance. This enhancement provides a better user experience by reducing the initial load time of the page.
2024-06-06 17:49:43 +01:00
Simon Larsen
4c6979cfa1 refactor: Add date filter to FiltersForm and FilterViewer components
This code change adds a new date filter to the FiltersForm and FilterViewer components. The date filter allows users to filter data based on a specific date range. This enhancement improves the filtering capabilities of the components and provides users with more flexibility in data analysis.
2024-06-06 17:40:24 +01:00
Simon Larsen
714a4be2b0 refactor: Update DatabaseService to set isRoot flag when updating items
This code change updates the DatabaseService class to set the isRoot flag to true when updating items. Previously, the props object in the update query only included the ignoreHooks flag. By adding the isRoot flag, we ensure that the update operation is performed as a root user, bypassing any access restrictions or hooks. This modification enhances the flexibility and control of the update process.
2024-06-06 14:43:11 +01:00
Simon Larsen
b935443f96 refactor: Update PingMonitorView to display monitor destination and port
This code change updates the PingMonitorView component to display the monitor destination and port. It ensures that the destination URL or IP address and the corresponding port are correctly displayed in the component. This enhancement improves the visibility of the monitoring information for users.
2024-06-06 14:28:32 +01:00
Simon Larsen
d3a3f01f20 refactor: Update monitorDestination and monitorDestinationPort in ProbeMonitorResponse interface
This code change updates the ProbeMonitorResponse interface to include the monitorDestination and monitorDestinationPort properties. These properties represent the destination URL or IP address and the corresponding port for monitoring. By adding these properties to the interface, we ensure that the necessary information is available for monitoring purposes.
2024-06-06 13:58:51 +01:00
snyk-bot
56b0fea04a fix: upgrade react-big-calendar from 1.12.1 to 1.12.2
Snyk has created this PR to upgrade react-big-calendar from 1.12.1 to 1.12.2.

See this package in npm:
react-big-calendar

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-06 03:46:25 +00:00
Simon Larsen
2605140166 refactor: Update DATABASE_USERNAME value in _helpers.tpl
This code change updates the value of DATABASE_USERNAME in the _helpers.tpl file. The value is changed to "postgres" when the postgresql.enabled flag is true, and to the value of $.Values.externalPostgres.username when the flag is false. This modification ensures that the correct username is used for the database connection.
2024-06-05 19:03:49 +01:00
Simon Larsen
8b9611e145 refactor: Update import statement for InitialMigration in Postgres SchemaMigrations 2024-06-05 17:52:16 +01:00
Simon Larsen
21057038d1 refactor: Update import statement for InitialMigration in Postgres SchemaMigrations
This code change updates the import statement for the InitialMigration file in the Postgres SchemaMigrations folder. The file name was changed from "1717605043663-MigrationName.ts" to "1717605043663-InitialMigration.ts". This refactor ensures that the correct file is imported and used for schema migrations.
2024-06-05 17:36:45 +01:00
Simon Larsen
e587d4ba19 refactor: Update Postgres migration generation command to use correct file path 2024-06-05 17:33:30 +01:00
Simon Larsen
14da201c8d refactor: Remove unused PostgresConfig file and update PostgresDatabase imports 2024-06-05 17:26:48 +01:00
Simon Larsen
f5584a5037 Add error handling to monitor probing in the FetchListAndProbe class. This change modifies the code to catch any errors that occur during the probing process and log them using the logger. This enhancement improves the robustness of the monitoring functionality by ensuring that errors are properly handled and logged. 2024-06-05 13:30:33 +01:00
Simon Larsen
157f8e95d7 refactor: Update TableRow component to include padding in drag handle 2024-06-05 12:59:35 +01:00
Simon Larsen
fb83126f37 Update Postgres password retrieval in Helm chart documentation 2024-06-05 12:27:31 +01:00
Simon Larsen
964def0c45 refactor: Disable ClickHouse when not enabled in values.yaml 2024-06-05 12:16:40 +01:00
Simon Larsen
650d7cc939 refactor: Add support for HTTPS in ClickHouse configuration 2024-06-05 11:42:01 +01:00
Simon Larsen
bfb4c46bd0 refactor: Update ClickHouse configuration to support HTTPS
This code change updates the ClickHouse configuration to support HTTPS. It introduces a new environment variable, `ClickHouseIsHostHttps`, which is set to `true` in the `EnvironmentConfig.ts` file. The `ClickhouseConfig.ts` file is modified to conditionally set the host protocol to `https` based on the value of `ClickHouseIsHostHttps`. This enhancement allows users to easily configure ClickHouse to use HTTPS when connecting to the host.
2024-06-05 11:41:39 +01:00
Simon Larsen
149c8c763d refactor: Remove empty line in values.yaml 2024-06-05 10:57:57 +01:00
Simon Larsen
fdbcace48c refactor: Update ClickHouse TLS configuration to use "tls" instead of "ssl" in values.yaml 2024-06-05 10:53:47 +01:00
Simon Larsen
3cfe0517a8 refactor: Update ClickHouse environment variables 2024-06-05 10:53:05 +01:00
Simon Larsen
9a32a47146 refactor: Update Redis and ClickHouse TLS configuration
This code change updates the Redis and ClickHouse TLS configuration to support the new `RedisTlsCert`, `RedisTlsKey`, `ClickhouseTlsCert`, and `ClickhouseTlsKey` environment variables. It modifies the `Redis.ts` and `ClickhouseConfig.ts` files to conditionally set the TLS options based on the presence of these variables. This enhancement allows users to easily enable TLS for Redis and ClickHouse by providing the necessary certificate and key files.
2024-06-05 10:49:01 +01:00
Simon Larsen
fd83a71a56 refactor: Enable Redis and ClickHouse in Helm chart
This code change enables Redis and ClickHouse in the Helm chart by setting the `enabled` flag to `true` for both services in the `values.yaml` file. This enhancement allows users to utilize Redis and ClickHouse functionalities when deploying the Helm chart.
2024-06-05 10:08:11 +01:00
Simon Larsen
e9bdbb3414 refactor: Update Postgres configuration in Helm chart
This code change updates the Postgres configuration in the Helm chart to support both internal and external Postgres databases. It adds the necessary environment variables and secrets blocks to handle the external Postgres database configuration. This enhancement allows users to easily switch between using an internal or external Postgres database when deploying the Helm chart.
2024-06-05 10:05:45 +01:00
Simon Larsen
3b65d1f4d6 refactor: Update Postgres configuration in Helm chart
This code change updates the Postgres configuration in the Helm chart to support both internal and external Postgres databases. It adds the `applicationName` property to the `dataSourceOptions` object in `PostgresConfig.ts` to set the application name to 'oneuptime'. Additionally, it adds new blocks in `secrets.yaml` to handle secrets for the external Postgres database, including the password and SSL options. This enhancement allows users to easily switch between using an internal or external Postgres database when deploying the Helm chart.
2024-06-05 09:28:10 +01:00
Simon Larsen
ed0f92f480 refactor: Update Postgres configuration in Helm chart
This code change updates the Postgres configuration in the Helm chart to support both internal and external Postgres databases. The `DATABASE_NAME` environment variable is renamed from `DATABASE_DATABASE` to improve clarity. Additionally, a new block for configuring SSL options for the external Postgres database is added. This enhancement allows users to easily switch between using an internal or external Postgres database when deploying the Helm chart.
2024-06-04 22:51:53 +01:00
Simon Larsen
6cc0f9deaf refactor: Update Postgres configuration in Helm chart
This code change updates the Postgres configuration in the Helm chart to support both internal and external Postgres databases. The `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_USERNAME`, `DATABASE_PASSWORD`, and `DATABASE_DATABASE` environment variables are now conditionally set based on the `postgresql.enabled` flag in the `values.yaml` file. If `postgresql.enabled` is `true`, the values are set to the internal Postgres service details. Otherwise, they are set to the corresponding values from the `externalPostgres` configuration. This enhancement allows users to easily switch between using an internal or external Postgres database when deploying the Helm chart.
2024-06-04 21:44:17 +01:00
Simon Larsen
06be3d2f58 ```text
refactor: Enable external Postgres support in Helm chart

This code change modifies the Helm chart to enable support for using an external Postgres database. The `postgresql.enabled` flag in the `values.yaml` file is set to `true` to indicate that an external Postgres database will be used. This enhancement allows users to configure the Helm chart to connect to an existing Postgres database instead of deploying a new one.
2024-06-04 21:42:17 +01:00
Simon Larsen
da8045271f Merge branch 'master' of github.com:OneUptime/oneuptime 2024-06-04 21:31:17 +01:00
Simon Larsen
cfc45efadf chore: Update Docker login action to v2.2.0 2024-06-04 21:31:15 +01:00
Simon Larsen
6b92440c74 Merge pull request #1457 from OneUptime/snyk-upgrade-ec107bb76f5f3418659be75ddc87b6bd
[Snyk] Upgrade @nivo/line from 0.86.0 to 0.87.0
2024-06-04 21:30:51 +01:00
Simon Larsen
c2d3123263 Merge pull request #1456 from OneUptime/snyk-upgrade-f550bab384e19de47906237ddf6f8910
[Snyk] Upgrade react-router-dom from 6.23.0 to 6.23.1
2024-06-04 21:30:40 +01:00
Simon Larsen
3a277db0d5 chore: Update Docker login action to v2.2.0
This code change updates the Docker login action to version 2.2.0 in the build.yml file. The new version provides improved functionality and security for logging in to Docker Hub. This chore ensures that the latest stable version of the Docker login action is used in the build process.
2024-06-04 21:29:22 +01:00
Simon Larsen
f084058b67 feat: Add error message component to BasicFormModal
This code change adds the ErrorMessage component to the BasicFormModal component in BasicFormModal.tsx. The ErrorMessage component is rendered when the props.error value is truthy, displaying the error message to the user. This enhancement improves the user experience by providing clear feedback when an error occurs during form submission.
2024-06-04 21:17:10 +01:00
Simon Larsen
9dbe33bfcc refactor: Add doNotShowWhenEditing flag to form fields
This code change adds the `doNotShowWhenEditing` flag to the form fields in the `ModelTable` component. When set to `true`, this flag prevents certain fields from being shown in the form when it is in edit mode. This improvement provides better control over which fields are displayed in the form during editing, enhancing the user experience and reducing clutter.
2024-06-04 21:01:36 +01:00
Simon Larsen
085e1a5d76 ```text
refactor: Update DatabaseService encrypt method to handle PartialEntity

This code change updates the `encrypt` method in the `DatabaseService` class to handle `PartialEntity` as an input parameter. Previously, the method only accepted `TBaseModel` as the input type. This improvement allows for encrypting both complete entities and partial entities, providing more flexibility in data encryption.
2024-06-04 20:41:23 +01:00
Simon Larsen
9a3fa080ea refactor: Update MonitorSecret model permissions
This code change updates the permissions for the MonitorSecret model in MonitorSecret.ts. The update includes adding the Permission.EditMonitorSecret permission to the update operation, allowing project owners, project admins, and users with the EditMonitorSecret permission to update MonitorSecret records. This improvement provides better control over who can modify MonitorSecrets and ensures that only authorized users can make changes to sensitive information.
2024-06-04 20:33:35 +01:00
Simon Larsen
db3d1e90f2 refactor: Remove unused Permission.ProjectMember from Label model
This code change removes the unused Permission.ProjectMember from the Label model in Label.ts. The Permission.ProjectMember was mistakenly included in the create, read, update, and delete arrays, but it is not required for these operations. Removing the unused permission improves code clarity and reduces potential confusion.
2024-06-04 20:31:15 +01:00
Simon Larsen
c02d8d8d8c Merge branch 'master' of github.com:OneUptime/oneuptime 2024-06-04 20:21:54 +01:00
Simon Larsen
1fad1d7c29 refactor: Update TableRow component to align top in Table
This code change updates the TableRow component in the Table module to align the content at the top of the table cells. The classNames "align-top" are added to the relevant table cells to achieve this alignment. This improvement ensures consistent vertical alignment of content in the table rows.
2024-06-04 20:21:51 +01:00
snyk-bot
ef610e104a fix: upgrade @nivo/line from 0.86.0 to 0.87.0
Snyk has created this PR to upgrade @nivo/line from 0.86.0 to 0.87.0.

See this package in npm:
@nivo/line

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-04 17:45:55 +00:00
snyk-bot
8f7bec00d4 fix: upgrade react-router-dom from 6.23.0 to 6.23.1
Snyk has created this PR to upgrade react-router-dom from 6.23.0 to 6.23.1.

See this package in npm:
react-router-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-04 17:45:49 +00:00
Simon Larsen
ae2a70eb64 Merge pull request #1455 from OneUptime/snyk-upgrade-454393c152713d89bbfd42d5ff28384a
[Snyk] Upgrade react-router-dom from 6.23.0 to 6.23.1
2024-06-04 12:00:54 +01:00
snyk-bot
e56e6a7f8d fix: upgrade react-router-dom from 6.23.0 to 6.23.1
Snyk has created this PR to upgrade react-router-dom from 6.23.0 to 6.23.1.

See this package in npm:
react-router-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/11bb5528-45f9-473c-a635-dc097fd03b3c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-04 05:13:42 +00:00
Simon Larsen
1141d47df7 Merge pull request #1452 from OneUptime/snyk-upgrade-b6c3fc62e0b59f937a4fb3dfd69a2be9
[Snyk] Upgrade react-router-dom from 6.23.0 to 6.23.1
2024-06-04 00:08:03 +01:00
Simon Larsen
9dea2c3bdd Merge pull request #1454 from OneUptime/snyk-upgrade-b79fc44de9934f0f4d9d7f32c5c1fb97
[Snyk] Upgrade @nivo/core from 0.86.0 to 0.87.0
2024-06-04 00:07:51 +01:00
Simon Larsen
9b465badda refactor: Update AnalyticsDatabaseService to handle group by count
This code change updates the AnalyticsDatabaseService to handle the count operation when a group by clause is used. Previously, the count operation would return the total number of rows, but now it correctly counts the number of groups. This improvement ensures accurate counting when grouping data in the analytics database.
2024-06-04 00:05:40 +01:00
Simon Larsen
073f84fe00 refactor: Update secrets.yaml to dynamically generate probe secrets
This code change updates the secrets.yaml file to dynamically generate probe secrets based on the values provided in the $.Values.probes object. If a probe secret already exists, it is used. Otherwise, a new random 32-character alphanumeric string is generated and encoded. This improvement ensures that probe secrets are properly managed and provides better security for sensitive information.
2024-06-03 23:46:04 +01:00
Simon Larsen
c6850f5a0b refactor: Add TableBillingAccessControl to MonitorSecret model
This code change adds the TableBillingAccessControl decorator to the MonitorSecret model in MonitorSecret.ts. The decorator sets the access control permissions for creating, reading, updating, and deleting MonitorSecret records to the Growth subscription plan. This improvement ensures that only users with the Growth plan can perform these actions on MonitorSecrets, providing better control over access to sensitive information.
2024-06-03 23:40:39 +01:00
Simon Larsen
636de9cd57 feat: Add banner with video link for MonitorSecrets page
The code change adds a banner component to the MonitorSecrets page. The banner displays a title, description, and a link to a video tutorial on how to use monitor secrets to store sensitive information. This enhancement provides users with a quick resource to learn about using monitor secrets effectively.
2024-06-03 20:26:39 +01:00
Simon Larsen
79ace6d183 erge branch 'release' 2024-06-03 13:37:43 +01:00
Simon Larsen
366b195152 refactor: Update environment variable setup in test-setup.sh
This code change updates the environment variable setup in the test-setup.sh script. The sed command is used to modify the config.env file, setting the NODE_ENV to 'test' and BILLING_ENABLED to 'true'. Additionally, the DATABASE_HOST is set to 'localhost', DATABASE_PORT to '5400', REDIS_HOST to 'localhost', REDIS_PORT to '6379', REDIS_DB to '0', and REDIS_USERNAME to 'default'. This improvement ensures that the test environment is properly configured with the correct values for testing.
2024-06-03 13:37:23 +01:00
Simon Larsen
bc687bdcdd add tag name 2024-06-03 13:27:08 +01:00
Simon Larsen
bc205a8686 fix infra release 2024-06-03 13:09:48 +01:00
Simon Larsen
e095715a52 feat: Add banner with video link for APIKeyView and TeamView
This code change adds a banner component to the APIKeyView and TeamView pages. The banner displays a title, description, and a link to a 5-minute video tutorial about permissions in OneUptime. This enhancement provides users with a quick resource to learn about permissions and how they work in the application.
2024-06-03 12:28:39 +01:00
Simon Larsen
e634ae0c1e refactor: Update ReadPermission to use object syntax for access control column assignment 2024-06-03 12:09:19 +01:00
Simon Larsen
ee080271e5 refactor: Update ReadPermission to use object syntax for access control column assignment 2024-06-03 11:43:49 +01:00
Simon Larsen
f07346a719 refactor: Improve checkReadBlockPermission method in ReadPermission 2024-06-03 11:30:11 +01:00
Simon Larsen
ace95bf75a refactor: Add checkReadBlockPermission method to ReadPermission
This code change adds the checkReadBlockPermission method to the ReadPermission class in ReadPermission.ts. The method is responsible for checking the block permissions for reading records. It allows the query to run if the system is making the query or if the user has root or master admin privileges. This enhancement provides better control over the reading of records and improves the security of the application.
2024-06-03 11:24:28 +01:00
Simon Larsen
4c53dc15e3 refactor: Add block permission checks to CreatePermission and DeletePermission
This code change adds block permission checks to the CreatePermission and DeletePermission classes. The checkCreateBlockPermissions method is added to the CreatePermission class to check block permissions for creating a new record. Similarly, the checkDeleteBlockPermissions method is added to the DeletePermission class to check block permissions for deleting a record. These enhancements provide better control over the creation and deletion of records and improve the security of the application.
2024-06-03 10:47:36 +01:00
Simon Larsen
ac286e0903 refactor: Add checkCreateBlockPermissions method to CreatePermission
This code change adds the checkCreateBlockPermissions method to the CreatePermission class in CreatePermission.ts. The method is responsible for checking the block permissions for creating a new record. It allows the query to run if the system is making the query or if the user has root or master admin privileges. This enhancement provides better control over the creation of records and improves the security of the application.
2024-06-03 10:16:34 +01:00
Simon Larsen
6595202093 refactor: Add isBlockPermission property to UserPermission and TeamPermission
This code change adds the isBlockPermission property to the UserPermission and TeamPermission interfaces and models. The isBlockPermission property allows for blocking specific permissions for users and teams. This enhancement provides greater control and flexibility in managing permissions within the application.
2024-06-03 09:48:02 +01:00
Simon Larsen
1ff5150765 ```text
refactor: Add user2 to TeamMemberService test for improved coverage

The TeamMemberService test in TeamMemberService.test.ts has been updated to include the addition of user2. This change improves the test coverage by testing the behavior with multiple users.
2024-06-03 09:26:17 +01:00
snyk-bot
13be411fc0 fix: upgrade @nivo/core from 0.86.0 to 0.87.0
Snyk has created this PR to upgrade @nivo/core from 0.86.0 to 0.87.0.

See this package in npm:
@nivo/core

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-03 04:20:36 +00:00
Simon Larsen
9d596c00da refactor: Update BaseAPI test to use updateOneById instead of updateOneBy
The BaseAPI test in BaseAPI.test.ts has been updated to use the updateOneById method instead of the updateOneBy method. This change ensures consistency in method naming and improves code readability.
2024-06-02 23:10:03 +01:00
Simon Larsen
6a285df796 refactor: Simplify generatePhone method in Faker.ts
The `generatePhone` method in `Faker.ts` has been simplified to remove unnecessary character replacements and instead directly generate a random 10-digit phone number. This change improves the efficiency and readability of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 22:54:59 +01:00
Simon Larsen
a053cc53eb refactor: Remove unnecessary characters from generated phone numbers in Faker.ts 2024-06-02 22:48:25 +01:00
Simon Larsen
14647f6bd5 refactor: Update BaseAPI test to use updateOneById instead of updateOneBy
The BaseAPI test in BaseAPI.test.ts has been updated to use the updateOneById method instead of the updateOneBy method. This change ensures consistency in method naming and improves code readability.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 22:19:36 +01:00
Simon Larsen
bc1d629576 refactor: Add notInBetween method to QueryHelper for querying records not in a specified range
The `notInBetween` method has been added to the `QueryHelper` class in `Database/QueryHelper.ts`. This method allows for querying records that are not within a specified range of values. It accepts a start value and an end value, and generates a `NOT IN` clause for the query. This enhancement provides greater flexibility in constructing complex queries and improves the overall query capabilities of the application.
2024-06-02 21:58:05 +01:00
Simon Larsen
c19b4e7040 refactor: Add notIn method to QueryHelper for improved query flexibility
The `notIn` method has been added to the `QueryHelper` class in `Database/QueryHelper.ts`. This method allows for querying records that are not in a specified list of values. It accepts an array of strings or ObjectIDs and generates a `NOT IN` clause for the query. This enhancement provides greater flexibility in constructing complex queries and improves the overall query capabilities of the application.
2024-06-02 21:45:18 +01:00
Simon Larsen
fca2c74817 refactor: Improve generatePhone method in Faker.ts
The `generatePhone` method in `Faker.ts` has been updated to remove unnecessary characters from the generated phone number. This change improves the consistency and simplicity of generating phone numbers using the Faker library.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 21:38:26 +01:00
Simon Larsen
737c785e73 refactor: Update APIKeyView table descriptions for better clarity
The table descriptions in the APIKeyView component have been updated to provide clearer information about managing permissions for API keys. This change improves the user experience and ensures that the purpose of the table is easily understood.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 21:31:26 +01:00
Simon Larsen
25edb45e10 refactor: Add isBlockPermission property to UserPermission and TeamPermission
This code change adds the isBlockPermission property to the UserPermission and TeamPermission interfaces and models. The isBlockPermission property allows for blocking specific permissions for users and teams. This enhancement provides greater control and flexibility in managing permissions within the application.
2024-06-02 21:27:23 +01:00
Simon Larsen
17308692b0 refactor: Update generatePhone method in Faker.ts 2024-06-02 21:08:29 +01:00
Simon Larsen
6785e62edd refactor: Update generatePhone method in Faker.ts
The `generatePhone` method in `Faker.ts` has been updated to remove the country code parameter from the `faker.phone.number` function call. This change improves the consistency and simplicity of generating phone numbers using the Faker library.
2024-06-02 21:06:10 +01:00
Simon Larsen
a1c761f618 refactor: Add validation for required fields in ApiKeyPermissionService and TeamPermissionService
This code change adds validation for the required fields in the ApiKeyPermissionService and TeamPermissionService. It throws a BadDataException if any of the required fields (apiKeyId, projectId, permission) are missing when creating a permission. Additionally, it checks if the permission is already assigned to the API key or team and throws an error if it is. These enhancements improve data integrity and prevent invalid permissions from being created.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 20:52:32 +01:00
Simon Larsen
29686f8167 feat: Add isBlockPermission property to UserPermission, UserTenantAccessPermission, ApiKeyPermission, and TeamPermission
This code change adds the isBlockPermission property to the UserPermission, UserTenantAccessPermission, ApiKeyPermission, and TeamPermission interfaces and models. The isBlockPermission property allows for blocking specific permissions for users, tenants, API keys, and teams. This enhancement provides greater control and flexibility in managing permissions within the application.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 20:47:49 +01:00
Simon Larsen
235fd6722e refactor: Remove BlockedApiKeyPermissionService and BlockedTeamPermissionService
This code change removes the BlockedApiKeyPermissionService and BlockedTeamPermissionService files, as well as their corresponding models. These services and models are no longer needed and have been deleted to improve code organization and maintainability.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 20:42:18 +01:00
snyk-bot
7286825f82 fix: upgrade react-router-dom from 6.23.0 to 6.23.1
Snyk has created this PR to upgrade react-router-dom from 6.23.0 to 6.23.1.

See this package in npm:
react-router-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/5dd2ef9c-1270-4729-aff4-e407805f7a9c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-02 17:43:19 +00:00
Simon Larsen
e344c6d3d1 refactor: Add BlockedApiKeyPermission and BlockedTeamPermission services and models
This code change adds the BlockedApiKeyPermissionService and BlockedTeamPermissionService services, as well as the BlockedApiKeyPermission and BlockedTeamPermission models. These additions provide functionality for managing blocked permissions for API keys and teams. This enhancement improves the flexibility and security of the application.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 13:38:07 +01:00
Simon Larsen
2751beae1d refactor: Update TeamMemberService.test.ts for better readability and maintainability 2024-06-02 13:27:17 +01:00
Simon Larsen
f1919d3964 refactor: Update TeamMemberService.test.ts for better readability and maintainability
This code change updates the TeamMemberService.test.ts file to improve readability and maintainability. It refactors the code to remove duplicated lines and uses jest.spyOn to mock the AccessTokenService methods. These changes enhance the code quality and test coverage.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 13:02:31 +01:00
Simon Larsen
de261142e5 refactor: Improve clarity and maintainability in BaseAPI.test.ts
This code change improves the clarity and maintainability of the BaseAPI.test.ts file. It removes unnecessary code and updates the logic for deleting and updating items. These changes enhance the code quality and test coverage.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 12:35:48 +01:00
Simon Larsen
0bfc28fedc refactor: Rename deleteById method to deleteOneById in BaseAPI and DatabaseService
This code change renames the deleteById method to deleteOneById in the BaseAPI and DatabaseService classes. The new method name provides better clarity and consistency with other methods in the codebase. This change improves the readability and maintainability of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 12:29:04 +01:00
Simon Larsen
a59e4cb76b refactor: Add deleteById and updateById methods to DatabaseService
This code change adds the deleteById and updateById methods to the DatabaseService class. These methods allow for more efficient deletion and updating of records in the database by directly targeting the record's ID. This enhancement improves the performance and flexibility of the DatabaseService.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 11:58:10 +01:00
Simon Larsen
ebb9c58758 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-06-02 11:48:52 +01:00
Simon Larsen
ee2df1a132 refactor: Improve clarity and maintainability in AccessControlPermission.ts 2024-06-02 11:48:48 +01:00
Simon Larsen
b33dc0ff69 Merge pull request #1448 from OneUptime/snyk-upgrade-0032ed3b91a482732c24656615bdd970
[Snyk] Upgrade react-router-dom from 6.23.0 to 6.23.1
2024-06-02 11:48:33 +01:00
Simon Larsen
80c3bb9dda Merge pull request #1449 from OneUptime/snyk-upgrade-21c5f91e22e4be5a53b1778c80645f80
[Snyk] Upgrade posthog-js from 1.131.3 to 1.131.4
2024-06-02 11:48:24 +01:00
Simon Larsen
283fbda8ee refactor: Improve clarity and maintainability in AccessControlPermission.ts
This code change improves the clarity and maintainability of the AccessControlPermission.ts file. It removes unnecessary code and updates the logic for checking user permissions to delete or update objects in the table. These changes enhance the code quality and user experience.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 11:44:24 +01:00
Simon Larsen
a67c70396f refactor: Improve clarity and maintainability in TeamView and APIKeyView components
This code change improves the clarity and maintainability of the TeamView and APIKeyView components. The commit updates the rendering of the permission restrictions messages to have consistent line breaks and spacing. It also adds missing punctuation and capitalization for better readability. These changes enhance the user experience and code quality.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 11:33:21 +01:00
Simon Larsen
3aeb22a253 refactor: Update APIKeyView and TeamView titles for better clarity
This code change updates the titles of the APIKeyView and TeamView components to improve clarity. The titles "API Key Permissions" and "Team Permissions" are changed to "Allow Permissions" to better reflect their purpose. This change enhances the user understanding and usability of the components.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 11:20:12 +01:00
Simon Larsen
070031d703 refactor: Update DatabaseService.ts to set access control column with specific properties
This code change updates the DatabaseService.ts file to set the access control column with specific properties when retrieving data. Instead of setting it to a boolean value, the access control column is now set to an object with the properties _id and name set to true. This change enhances the flexibility and maintainability of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 09:58:49 +01:00
Simon Larsen
a30104fe06 refactor: Remove unused code and improve type safety in AccessControlModel.ts, DatabaseService.ts, LabelService.ts, and ColumnPermission.ts 2024-06-02 09:36:33 +01:00
Simon Larsen
76677233df refactor: Update DatabaseService.ts and ColumnPermission.ts for improved type safety
This code change updates the DatabaseService.ts and ColumnPermission.ts files to improve type safety. In DatabaseService.ts, the type of the projectIdColumn variable is changed from keyof TBaseModel | null to string | null, ensuring compatibility with the getTenantColumn() method. In ColumnPermission.ts, the type of the permissionColumns variable is changed from Columns<TBaseModel> to Columns, removing unnecessary type specificity. These changes enhance the code's clarity and maintainability.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 09:34:03 +01:00
Simon Larsen
e1054c2572 refactor: Improve flexibility and maintainability in LabelService.ts and TableColumn.ts
This code change adds flexibility and maintainability improvements to the LabelService.ts and TableColumn.ts files. In LabelService.ts, a constructor is added to the Service class, allowing for the injection of a PostgresDatabase instance. In TableColumn.ts, the propertyKey parameter in the getTableColumn function is changed from keyof T to string, providing more flexibility in handling property keys. These changes enhance the usability and maintainability of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-02 09:32:06 +01:00
Simon Larsen
e3e684352f refactor: Override name property in Label class
This code change overrides the name property in the Label class to allow for more flexibility in handling scenarios where the name is not specified. By setting the name property to undefined, it improves the usability and maintainability of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 22:44:18 +01:00
snyk-bot
f9472a1308 fix: upgrade posthog-js from 1.131.3 to 1.131.4
Snyk has created this PR to upgrade posthog-js from 1.131.3 to 1.131.4.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-01 21:36:34 +00:00
snyk-bot
2113022d11 fix: upgrade react-router-dom from 6.23.0 to 6.23.1
Snyk has created this PR to upgrade react-router-dom from 6.23.0 to 6.23.1.

See this package in npm:
react-router-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/40b17bc5-1bd4-48b1-88f1-5b4dc1400e80?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-01 21:21:09 +00:00
Simon Larsen
f21cb43b5b refactor: Update DeleteOneBy.ts to allow undefined deletedByUser
This code change updates the DeleteOneBy.ts file to allow the `deletedByUser` property to be undefined. This change provides more flexibility in handling scenarios where the deletedByUser is not specified. It improves the usability and maintainability of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 20:54:48 +01:00
Simon Larsen
5e7285fa66 refactor: Update ModelPermission.ts to use specific query permission methods
This code change updates the ModelPermission.ts file to use specific query permission methods for delete, update, and read operations. The checkDeleteQueryPermission, checkUpdateQueryPermissions, and checkReadQueryPermission methods provide more granular control and improve the clarity and maintainability of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 19:40:30 +01:00
Simon Larsen
ff1195c837 refactor: Remove unnecessary code in DatabaseService.ts 2024-06-01 19:37:32 +01:00
Simon Larsen
2f5f147ab4 refactor: Remove debugger statements and improve code readability in DatabaseService.ts
This code change removes the debugger statements from the _deleteBy method in DatabaseService.ts and improves code readability by reformatting the code and removing unnecessary comments. The changes enhance the maintainability and clarity of the code.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 19:37:02 +01:00
Simon Larsen
f4005ee351 refactor: Update queries to use QueryHelper.inRelationArray for monitors
This code change updates the queries in DatabaseService.ts, IncidentService.ts, and ScheduledMaintenanceStateTimelineService.ts to use the QueryHelper.inRelationArray method instead of QueryHelper.anyRelationArray for the "monitors" property. This change provides a more accurate and efficient way to query for records related to specific monitors. It improves the accuracy and performance of the queries.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 19:33:53 +01:00
Simon Larsen
549e41119c refactor: Update createdAt queries to use QueryHelper.inBetween
This code change updates the createdAt queries in multiple files to use the QueryHelper.inBetween method instead of QueryHelper.anyBetween. The inBetween method provides a more accurate and efficient way to query for records within a specific date range. This change improves the accuracy and performance of the queries.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 19:32:12 +01:00
Simon Larsen
0f76e075ce refactor: Update QueryHelper to use FindOperator for any and in methods
This code change updates the QueryHelper class to use the FindOperator type for the any and in methods. This allows for more flexibility in querying by accepting an array of values or a single value. The change improves code readability and maintainability.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 19:31:20 +01:00
Simon Larsen
7212b93836 refactor: Simplify adding access control IDs to query in BasePermission.ts 2024-06-01 18:04:46 +01:00
Simon Larsen
aca335aa8f refactor: Update ModelPermission.ts to improve code readability and maintainability 2024-06-01 17:45:14 +01:00
Simon Larsen
1053f52b2b Merge branch 'release' 2024-06-01 17:28:50 +01:00
Simon Larsen
4ef8a8d0f9 refactor: Update Go version and use specific ref in release workflow
This code change updates the Go version used in the release workflow and modifies the "Checkout" step to use a specific ref instead of fetching the entire history. By specifying the ref, the workflow will only fetch the necessary code, reducing the time and resources required for the checkout process.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 17:27:18 +01:00
Simon Larsen
8d183ceee6 refactor: Update checkout step in release workflow
This code change updates the checkout step in the release workflow to use the `ref` parameter instead of `fetch-depth`. This ensures that the correct branch or tag is checked out during the workflow execution.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 17:26:52 +01:00
Simon Larsen
d2a58fbe97 refactor: Reorder imports in CreatePermission.ts and UpdatePermission.ts
This code change reorders the imports in the CreatePermission.ts and UpdatePermission.ts files to group related imports together and improve code readability. The imports are now organized in the following order:
1. External dependencies
2. Internal dependencies
3. Local dependencies

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 17:21:01 +01:00
Simon Larsen
9b115da0be Merge branch 'master' of github.com:OneUptime/oneuptime 2024-06-01 17:20:20 +01:00
Simon Larsen
e46133d678 refactor: Update ModelPermission.ts to improve code readability and maintainability 2024-06-01 17:20:14 +01:00
Simon Larsen
c9bf2e3bf1 Merge pull request #1445 from OneUptime/snyk-upgrade-af76d864ab171838e05700ac0e1500b0
[Snyk] Upgrade protobufjs from 7.2.6 to 7.3.0
2024-06-01 16:50:34 +01:00
Simon Larsen
2c16b5ab7d Merge pull request #1447 from OneUptime/snyk-fix-418ca58fe385c0a1a5ff7575c3cda99b
[Snyk] Security upgrade nginx from 1.25.5-alpine to 1.26.1-alpine
2024-06-01 16:50:26 +01:00
Simon Larsen
f7339723cd refactor: Update ModelPermission.ts to improve code readability and maintainability 2024-06-01 15:17:26 +01:00
Simon Larsen
c2e04e94e2 refactor: Update ModelPermission.ts to improve code readability and maintainability
This code change in ModelPermission.ts improves code readability and maintainability by removing unnecessary code, updating function parameters, and adding comments for clarity. The changes include:
- Removing unused function parameters in CheckReadPermissionType and checkReadPermission functions
- Updating the checkIfUserIsLoggedIn function call to include the type parameter
- Refactoring the checkModelLevelPermissions function to include the type parameter
- Adding a comment to clarify the purpose of the checkBillingPermissions function

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 15:09:42 +01:00
Simon Larsen
bbb2f8d154 refactor: Remove unnecessary code in ModelPermission.ts
This code change removes unnecessary code in the ModelPermission.ts file. The empty lines and unused function parameters have been removed to improve code readability and maintainability.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 14:50:17 +01:00
Simon Larsen
4ab9e8b398 refactor: Update access control permissions in PermissionHelper
This code change updates the access control permissions in the PermissionHelper class. The "isAccessControlPermission" property for various permissions has been changed from "true" to "false". This ensures that the specified permissions no longer have access control restrictions.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 14:49:35 +01:00
Simon Larsen
d0e6153758 refactor: Import Stripe and mockStripe together in BillingService.test.ts
This code change updates the import statements in BillingService.test.ts to import both the Stripe and mockStripe modules from the same line. This improves code readability and ensures that both modules are imported consistently.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-06-01 14:36:16 +01:00
Simon Larsen
f308407f68 refactor: Update TeamPermissionService to include projectId in select props
This code change updates the TeamPermissionService to include the "projectId" property in the select props when querying for team members. This ensures that the "projectId" value is retrieved along with the "userId" value, allowing for easier access to the project ID in subsequent code logic.
2024-06-01 14:35:25 +01:00
Simon Larsen
93ba752e8c refactor: Update TeamPermissionService to include projectId in select props
This code change updates the TeamPermissionService to include the "projectId" property in the select props when querying for team members. This ensures that the "projectId" value is retrieved along with the "userId" value, allowing for easier access to the project ID in subsequent code logic.
2024-05-31 22:00:13 +01:00
Simon Larsen
230d345406 refactor: Remove unused "RemoveCanFromPermissions" import in DataMigrations/Index.ts 2024-05-31 21:54:37 +01:00
Simon Larsen
7e51da56f6 refactor: Update TeamPermissionService to include projectId in select props
This code change updates the TeamPermissionService to include the "projectId" property in the select props when querying for team members. This ensures that the "projectId" value is retrieved along with the "userId" value, allowing for easier access to the project ID in subsequent code logic.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 21:52:01 +01:00
Simon Larsen
cab9fd08fa refactor: Remove unused "RemoveCanFromPermissions" import in DataMigrations/Index.ts
This code change removes the unused import statement for "RemoveCanFromPermissions" in the "DataMigrations/Index.ts" file. The import is no longer needed and can be safely removed to improve code readability and maintainability.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 19:33:33 +01:00
Simon Larsen
461f69b11e refactor: Update permission names in NotificationAPI.ts, DataMigration.ts, BillingPaymentMethodAPI.ts, BillingInvoiceAPI.ts, and PromoCode.ts
This code change updates the permission names in multiple files to align with the latest naming conventions. The following changes were made:

- In NotificationAPI.ts, the permission name "CanManageProjectBilling" was changed to "ManageProjectBilling".
- In DataMigration.ts, the permission names "CanCreateProjectLabel" and "CanReadProjectLabel" were changed to "CreateProjectLabel" and "ReadProjectLabel" respectively.
- In BillingPaymentMethodAPI.ts, the permission name "CanCreateBillingPaymentMethod" was changed to "CreateBillingPaymentMethod".
- In BillingInvoiceAPI.ts, the permission name "CanEditInvoices" was changed to "EditInvoices".
- In PromoCode.ts, the permission names "CanCreateProjectLabel" and "CanReadProjectLabel" were changed to "CreateProjectLabel" and "ReadProjectLabel" respectively. Additionally, the permission names "CanReadProject" and "CanEditProject" were changed to "ReadProject" and "EditProject" respectively.

These updates ensure that the permission names are consistent and reflect the intended functionality.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 19:23:45 +01:00
Simon Larsen
ad7a5bddcb remove dup service 2024-05-31 19:01:29 +01:00
Simon Larsen
a64feacb5c refactor: Update TeamPermissionService to refresh access permissions for team members
This code change updates the TeamPermissionService to refresh access permissions for team members when they are deleted. Previously, only the user's global access permission was refreshed, but now both the global and tenant access permissions are refreshed. This ensures that the user's access permissions are up to date after a team member is deleted.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 17:55:39 +01:00
Simon Larsen
a27b51ea94 refactor: Update Prettier configuration to include @trivago/prettier-plugin-sort-imports
This code change updates the .prettierrc.json file to include the @trivago/prettier-plugin-sort-imports plugin. By adding this plugin, the codebase will automatically sort imports according to specified rules. This improves code organization and maintainability.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 17:44:51 +01:00
Simon Larsen
a0f7324c01 refactor: Simplify getTestDataSourceOptions in PostgresConfig.ts 2024-05-31 17:40:25 +01:00
Simon Larsen
c3b0302cbe revert haraka changes 2024-05-31 17:35:21 +01:00
snyk-bot
0c264bcd32 fix: Nginx/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE319-BUSYBOX-6913413
- https://snyk.io/vuln/SNYK-ALPINE319-BUSYBOX-6913413
- https://snyk.io/vuln/SNYK-ALPINE319-BUSYBOX-6928845
- https://snyk.io/vuln/SNYK-ALPINE319-BUSYBOX-6928846
- https://snyk.io/vuln/SNYK-ALPINE319-BUSYBOX-6928847
2024-05-31 15:49:59 +00:00
Simon Larsen
abc7a43d1b refactor: Simplify getTestDataSourceOptions in PostgresConfig.ts
This code change simplifies the `getTestDataSourceOptions` function in `PostgresConfig.ts` by using `process.env` values directly. By removing the conditional fallback to `'localhost'`, the function now relies solely on the environment variable `DATABASE_HOST` for the host value. This change ensures that the function always retrieves the latest values during test runs, as `process.env` can change dynamically.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 14:06:53 +01:00
Simon Larsen
05e9282d7f Update Haraka SMTP and TLS configurations to listen on port 25 instead of port 2525
This code change modifies the Haraka SMTP and TLS configurations to listen on port 25 instead of port 2525. The previous configuration used port 2525, but it has been changed to align with the standard SMTP port. This update ensures that the Haraka server can receive incoming emails on the correct port.
2024-05-31 13:35:35 +01:00
Simon Larsen
75d2a01a5a refactor: Use process.env values directly in getTestDataSourceOptions
This code change refactors the `getTestDataSourceOptions` function in `PostgresConfig.ts` to use `process.env` values directly. This change is made to ensure that the function always retrieves the latest values during test runs, as `process.env` can change dynamically. By removing the conditional fallback to `'localhost'`, the function relies solely on the environment variable `DATABASE_HOST` for the host value. This simplifies the code and improves consistency.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 13:27:46 +01:00
Simon Larsen
8d02eddfc6 Update PostgresConfig.ts and PostgresDatabase.ts to use a function for testDataSourceOptions 2024-05-31 13:27:02 +01:00
Simon Larsen
33d38611e2 chore: Update Stripe.mock.ts to allow null value for mockStripe
This code change updates the Stripe.mock.ts file to allow the mockStripe variable to have a null value. This change is necessary to properly handle scenarios where the Stripe library is not mocked. By allowing the variable to be null, it ensures that the code can handle both mocked and non-mocked scenarios without causing errors.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-31 13:03:59 +01:00
Simon Larsen
31335ee6b5 Update host_list configuration file path in Dockerfile 2024-05-31 13:01:11 +01:00
Simon Larsen
6eb228d0b8 chore: Add INCOMING_EMAIL_DOMAIN to host_list configuration
This code change adds the INCOMING_EMAIL_DOMAIN variable to the host_list configuration in the Haraka init.sh script. This ensures that incoming emails from the specified domain are accepted by the Haraka application. The INCOMING_EMAIL_DOMAIN value is appended to the host_list file, allowing the application to properly handle emails from this domain.
2024-05-31 12:59:23 +01:00
snyk-bot
0ef82aef01 fix: upgrade protobufjs from 7.2.6 to 7.3.0
Snyk has created this PR to upgrade protobufjs from 7.2.6 to 7.3.0.

See this package in npm:
protobufjs

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/89d21457-97ad-4d10-9b37-253f0b4cc388?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-31 04:55:47 +00:00
Simon Larsen
f644ac117f chore: Update Dockerfile to include loglevel configuration 2024-05-30 21:25:44 +01:00
Simon Larsen
08ddfb1017 chore: Update Dockerfile to include email_parser.js plugin and install dependencies
This code change updates the Dockerfile for the Haraka application. It adds the email_parser.js plugin to the /harakaapp/plugins directory and installs the necessary dependencies by copying the package.json and package-lock.json files to the /harakaapp directory and running npm install. This update ensures that the email parsing functionality is properly configured and all required dependencies are installed.
2024-05-30 21:07:05 +01:00
Simon Larsen
68724478da chore: Update HelmChart values.yaml to use ClusterIP for internalSmtp type
This code change updates the HelmChart values.yaml file to change the type of the internalSmtp service from LoadBalancer to ClusterIP. The LoadBalancer type was causing issues with receiving emails from the internet, so this change provides a workaround by using the ClusterIP type instead. This update ensures that the internalSmtp service can properly receive emails and improves the functionality of the application.
2024-05-30 20:34:14 +01:00
Simon Larsen
ca621bf41c feat: Add support for additional email ports
This code change adds support for additional email ports in the Haraka configuration. It exposes ports 110, 25, 587, 465, 143, 993, and 995 for POP3, SMTP, IMAP, and their secure variants. This enhancement allows for more flexible email communication options.
2024-05-30 20:30:44 +01:00
Simon Larsen
c470abf36c feat: Add host_list.ini configuration file and update email_parser.js plugin
The code changes include adding a new configuration file `host_list.ini` to the Haraka config directory. This file will be used to store a list of allowed hosts for incoming emails. Additionally, the `email_parser.js` plugin file has been moved to the correct directory in the Haraka config. This update ensures that the email parsing functionality is properly configured and the list of allowed hosts is maintained.
2024-05-30 20:12:07 +01:00
Simon Larsen
39bd722cf5 chore: Update Haraka config plugins
This code change updates the Haraka config plugins file to include additional plugins for blocking mails from known bad hosts, blocking mail from known bad HELOs, blocking mail from known bad email addresses, and accepting mail only from domains with resolvable MX records. It also removes the emailParser.js plugin file.

Note: This commit message follows the established convention of starting with a verb in the imperative form (e.g., "Update", "Add", "Fix") and providing a concise summary of the changes made.
2024-05-30 20:04:12 +01:00
Simon Larsen
3851827afb feat: Add mailparser npm dependency 2024-05-30 19:39:07 +01:00
Simon Larsen
cd5c333d97 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-30 19:35:40 +01:00
Simon Larsen
fee16520df change default log level 2024-05-30 19:35:22 +01:00
Simon Larsen
025648482e Merge pull request #1443 from OneUptime/snyk-upgrade-e1f8734d934eff9fb30ddb40ca654522
[Snyk] Upgrade posthog-js from 1.130.2 to 1.131.3
2024-05-30 10:46:53 +01:00
Simon Larsen
89a3d3a6ac refactor: Update secrets.yaml to handle release upgrades
This code change updates the secrets.yaml file to handle release upgrades. It introduces a workaround to keep the secrets unchanged during upgrades by retrieving the existing secrets if the release is an upgrade. For new installations, it generates new secrets using the randAlphaNum function. This enhancement ensures that secrets are properly managed during upgrades and installations.
2024-05-30 10:43:25 +01:00
Simon Larsen
e4da9c5212 refactor: Improve password reset email functionality
This code change refactors the `Authentication.ts` file to improve the functionality of the password reset email. It updates the logic for generating the password reset URL and adds logging statements to track the user's email and the generated URL. This enhancement ensures a smoother password reset process and improves the visibility of user actions in the system.
2024-05-30 10:15:31 +01:00
Simon Larsen
1e61fec929 feat: Set current project in App component
This code change adds logic to set the current project in the `App` component. It checks if a `selectedProject` is available and if so, it calls the `ProjectUtil.setCurrentProject` function with the `selectedProject`. This enhancement ensures that the current project is correctly set and improves the functionality of the application.
2024-05-30 09:56:59 +01:00
Simon Larsen
6a76665c79 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-30 09:55:13 +01:00
Simon Larsen
2d3d0449e5 feat: Add ProjectUtil.setCurrentProject to App component
This code change adds the import statement for `ProjectUtil` and calls the `setCurrentProject` function with the `selectedProject` in the `App` component. This enhancement ensures that the current project is set correctly and improves the functionality of the application.
2024-05-30 09:54:33 +01:00
snyk-bot
fee5132e7e fix: upgrade posthog-js from 1.130.2 to 1.131.3
Snyk has created this PR to upgrade posthog-js from 1.130.2 to 1.131.3.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-30 03:30:10 +00:00
Simon Larsen
2dbb91ba24 Merge pull request #1442 from OneUptime/release
refactor: Improve event item descriptions and labels
2024-05-29 17:47:50 +01:00
Simon Larsen
9a37c4b031 refactor: Improve event item descriptions and labels
This code change refactors the EventItem component to improve the display of event descriptions and labels. It updates the CSS classes for the event descriptions to enhance readability and adds CSS classes for the event labels to improve their styling. This enhancement improves the overall appearance and user experience of the EventItem component.
2024-05-29 16:52:53 +01:00
Simon Larsen
d3d64979e0 refactor: Add logging statements for status checks
The code change adds logging statements for the status checks in the StatusAPI file. The logging statements provide information about the status checks being performed, including the result of each check. This enhancement improves the visibility and monitoring of the status checks in the system.
2024-05-29 16:37:11 +01:00
Simon Larsen
c6efe40f3b refactor: Add logging statements for user sign up, email verification, password reset, and login
This code change adds logging statements for user sign up, email verification, password reset, and login in the Authentication.ts and SSO.ts files. The logging statements provide information about the corresponding user actions, including the user's email. This enhancement improves the visibility and monitoring of user activities in the system.
2024-05-29 15:45:48 +01:00
Simon Larsen
d0ace48aeb refactor: Add selectedProject prop to DashboardHeader component
This code change adds the selectedProject prop to the DashboardHeader component in the Header.tsx file. The prop is used to pass the currently selected project to the component, allowing it to display the selected project's information. This enhancement improves the functionality and user experience of the DashboardHeader component.
2024-05-29 15:27:37 +01:00
Simon Larsen
faf0641503 refactor: Update package.json and Encryption.ts to use latest version of crypto-js 2024-05-29 15:25:09 +01:00
Simon Larsen
4fcc066971 Merge remote-tracking branch 'origin/snyk-upgrade-9bde7b8ad7df926b5588a93ac9081118' 2024-05-29 13:59:08 +01:00
Simon Larsen
e37347a611 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-29 13:58:24 +01:00
Simon Larsen
95dbeaddba refactor: Update DocsNav to include Monitor Secrets page
This code change updates the DocsNav file to include a new navigation item for the Monitor Secrets page. It adds a new object to the DocsNav array with the title "Monitor Secrets" and the URL "/docs/monitor/monitor-secrets". This enhancement improves the navigation experience for users accessing the Monitor Secrets documentation.
2024-05-29 13:56:38 +01:00
Simon Larsen
5a12e70742 refactor: Update Encryption.ts to use Utf8 encoding for decryption
This code change updates the Encryption.ts file to use the Utf8 encoding for decryption in the `decrypt` method. Previously, it was using the default encoding, which could lead to incorrect results for certain inputs. This update ensures the correct decoding of the encrypted text and improves the reliability of the decryption process.
2024-05-29 13:20:56 +01:00
Simon Larsen
ab0b7bb6ec refactor: Update MonitorSecrets page to display monitors with access to secrets 2024-05-29 12:47:21 +01:00
Simon Larsen
c9874df43f refactor: Add null checks in DatabaseService and Encryption
This code change adds null checks in the DatabaseService and Encryption classes to handle cases where the input data is null or undefined. It prevents potential errors and improves the robustness of the code.
2024-05-29 11:52:50 +01:00
Simon Larsen
594a44392d Merge pull request #1438 from OneUptime/snyk-upgrade-0f21f366f23af175b83fbe7a993653de
[Snyk] Upgrade posthog-js from 1.130.1 to 1.130.2
2024-05-29 11:41:24 +01:00
Simon Larsen
5b9232c785 ```text
refactor: Update package.json and Encryption.ts to use latest version of crypto-js

This code change updates the package.json and Encryption.ts files to use the latest version (4.2.0) of the crypto-js library. It adds the "@types/crypto-js" package as a dependency in the package.json file and updates the import statements in the Encryption.ts file to use the updated library. This update ensures compatibility with the latest features and improvements in crypto-js.
2024-05-29 11:41:05 +01:00
Simon Larsen
06b7f5c236 refactor: Update JSON.ts imports
This code change updates the imports in the JSON.ts file to remove unused imports and organize the imports alphabetically. It improves code readability and maintainability.
2024-05-28 21:33:44 +01:00
Simon Larsen
f20f833720 refactor: Update MonitorSecrets page to display monitors with access to secrets
This code change updates the MonitorSecrets page to display the monitors that have access to the secrets. It adds a new field in the form to select the monitors and renders the selected monitors using the MonitorsElement component. This enhancement improves the visibility and management of secret access for monitors.
2024-05-28 20:13:58 +01:00
Simon Larsen
91c37a2a9e refactor: Update MonitorSecretService to use MonitorSecret model 2024-05-28 20:10:15 +01:00
Simon Larsen
937879aa68 refactor: Update MonitorSecretService to use MonitorSecret model
This code change updates the MonitorSecretService to use the MonitorSecret model instead of the deprecated MonitorProbe model. This refactor ensures consistency and improves code maintainability.
2024-05-28 20:09:25 +01:00
Simon Larsen
df77fdac74 feat: Add Monitor Secrets functionality
This code change adds the necessary functionality for managing Monitor Secrets. It includes updates to the PageMap, SettingsBreadcrumbs, and RouteMap files to support the new "SETTINGS_MONITOR_SECRETS" page. Additionally, the "SETTINGS_MONITOR_SECRETS" route is added to the SettingsRoutePath dictionary. This enhancement improves the application's security and access control.
2024-05-28 20:01:51 +01:00
Simon Larsen
28917b3fcb Merge pull request #1440 from OneUptime/snyk-upgrade-24a45d8b5a59e57a4cd97e1bc201f713
[Snyk] Upgrade @types/lodash from 4.17.0 to 4.17.1
2024-05-28 19:57:25 +01:00
Simon Larsen
853715b17c refactor: Update .prettierrc.json with importOrderParserPlugins option
This code change updates the .prettierrc.json file by adding the "importOrderParserPlugins" option with the values ["typescript", "decorators"]. This enhancement allows the Prettier formatter to correctly parse and sort imports that include TypeScript and decorators. It improves the code formatting and organization.
2024-05-28 19:57:03 +01:00
Simon Larsen
5bdc381925 refactor: Add MonitorSecret permissions 2024-05-28 19:54:50 +01:00
Simon Larsen
c499df2812 ```text
refactor: Add @trivago/prettier-plugin-sort-imports to package.json and .prettierrc.json

This code change adds the "@trivago/prettier-plugin-sort-imports" package as a dependency in the package.json file and includes it in the "plugins" array in the .prettierrc.json file. It also sets the "importOrderSeparation" and "importOrderSortSpecifiers" options to true. This enhancement improves the code formatting and organization by automatically sorting imports.
2024-05-28 19:53:53 +01:00
Simon Larsen
5ef5dbf562 refactor: Add MonitorSecret permissions
This code change adds the necessary permissions for managing MonitorSecrets. The new permissions include CanCreateMonitorSecret, CanEditMonitorSecret, CanDeleteMonitorSecret, and CanReadMonitorSecret. These permissions allow users to create, edit, delete, and read MonitorSecrets respectively. This enhancement improves the access control and security of the application.
2024-05-28 19:46:59 +01:00
Simon Larsen
332aa47e63 refactor: Remove unnecessary checks for event.monitors in SendNotificationToSubscribers.ts 2024-05-28 17:07:23 +01:00
snyk-bot
cb1ddfe0df fix: upgrade @types/lodash from 4.17.0 to 4.17.1
Snyk has created this PR to upgrade @types/lodash from 4.17.0 to 4.17.1.

See this package in npm:
@types/lodash

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/c3622982-05c8-495c-809c-20f301c75f92?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-25 23:09:44 +00:00
Simon Larsen
d5bb29f9b4 Merge pull request #1439 from OneUptime/metrics-box
Metrics box
2024-05-24 13:23:59 +01:00
Simon Larsen
5f851b6936 refactor: Remove server monitor from SummaryView
This code change removes the rendering of the server monitor from the SummaryView component. The monitorType prop is checked, and if it is set to MonitorType.Server, the server monitor is not rendered. This change simplifies the SummaryView component and improves code organization.
2024-05-24 13:19:00 +01:00
Simon Larsen
5fa7c5baaa refactor: Remove Webkit browser support
The code changes in this commit remove support for the Webkit browser in the BrowserType enum and SyntheticMonitor module. The Webkit browser was commented out and not being used, so it was decided to remove it to simplify the codebase and reduce unnecessary dependencies. This refactor improves code organization and maintainability.
2024-05-24 13:14:02 +01:00
Simon Larsen
557c3f1427 refactor: Update title in CustomMonitorSummaryView and SyntheticMonitorItemView components
The code changes in this commit update the title in the CustomMonitorSummaryView and SyntheticMonitorItemView components. The title "Is Error" is changed to "Error" to provide clearer and more concise information to users. This enhancement improves the user experience and readability of the components.
2024-05-24 12:58:07 +01:00
Simon Larsen
a14614b7de refactor: Improve page load performance with lazy loading for images 2024-05-24 12:44:34 +01:00
Simon Larsen
cc1c968d3c refactor: Remove unused Metrics components
The code changes in this commit remove the unused Metrics components: ProbeNowButton.tsx, MetricsScreenshot.tsx, MetricsScreenshotGroup.tsx, PingMonitorView.tsx, and ProbePicker.tsx. These components are no longer needed and removing them improves code organization and maintainability.
2024-05-24 12:37:36 +01:00
Simon Larsen
1830f031e9 refactor: Update email verification confirmation message
The code changes in this commit update the confirmation message for email verification. Instead of just displaying the user's email, it now includes the text "Are you sure you want to verify the email -" before the email address. This change provides clearer context and improves the user experience.
2024-05-24 11:39:58 +01:00
Simon Larsen
5d8dd6ef3c refactor: Add email verification functionality to Users page
The code changes in this commit add email verification functionality to the Users page. This includes adding a "Verify Email" button to each user's row in the table. Clicking the button opens a confirmation modal asking if the user's email should be verified. Upon confirmation, the user's email is marked as verified in the database. This enhancement improves the user experience and provides better control over email verification.
2024-05-24 11:39:43 +01:00
Simon Larsen
d0b63b5c8b Refactor ProbeMonitorResponseService and Metrics component
The code changes refactor the ProbeMonitorResponseService and Metrics component. This includes removing redundant code in ProbeMonitorResponseService and simplifying the Metrics component by removing unnecessary props. These changes improve code organization and maintainability.
2024-05-23 20:31:16 +01:00
Simon Larsen
e94cc8083a refactor: Improve error messages in MetricsInfo and SSLCertificateMonitorView components 2024-05-23 18:58:43 +01:00
Simon Larsen
847f426bc6 refactor: Improve error messages in MetricsInfo and SSLCertificateMonitorView components
The code changes in this commit improve the error messages in the MetricsInfo and SSLCertificateMonitorView components. The updated error messages provide more helpful information to users, indicating that it may take a few minutes for metrics to show up for the selected probe. This enhancement improves the user experience and reduces confusion when metrics are not immediately available.
2024-05-23 18:49:30 +01:00
Simon Larsen
74bcadb2e7 refactor: Update MonitorView and Metrics components
The code changes in this commit update the MonitorView and Metrics components. Specifically, the changes introduce type annotations and improve the readability of the code by using more descriptive variable names. These updates enhance the maintainability and understanding of the codebase.
2024-05-23 18:16:24 +01:00
Simon Larsen
3e255e6dd1 refactor: Remove unused isHeadRequest property in MonitorUtil and ApiMonitor 2024-05-23 17:41:37 +01:00
snyk-bot
eb5cf5a3cb fix: upgrade posthog-js from 1.130.1 to 1.130.2
Snyk has created this PR to upgrade posthog-js from 1.130.1 to 1.130.2.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-23 12:51:38 +00:00
Simon Larsen
df7bd46428 Remove unused isHeadRequest property in MonitorUtil and ApiMonitor 2024-05-23 13:40:34 +01:00
Simon Larsen
e6dadd0673 refactor: Remove unused isHeadRequest property in MonitorUtil and ApiMonitor 2024-05-23 11:43:54 +01:00
Simon Larsen
ee8706e75b refactor: Remove unused isHeadRequest property in MonitorUtil and ApiMonitor
The code changes remove the unused `isHeadRequest` property in the `MonitorUtil` and `ApiMonitor` classes. This cleanup improves code readability and eliminates unnecessary code.
2024-05-23 10:22:09 +01:00
Simon Larsen
da70359945 feat: Add resourcesAffected field to maintenance event notification templates 2024-05-22 21:13:35 +01:00
Simon Larsen
3622021e57 refactor: Update screenshot handling in monitor scripts 2024-05-22 20:21:22 +01:00
Simon Larsen
5aeada377a feat: Add screenshot functionality to synthetic monitor script 2024-05-22 20:18:13 +01:00
Simon Larsen
d34a493724 feat: Add timeout configuration for monitor scripts
The commit updates the README.md file to include new configurable parameters for timeout values in the monitor scripts. This allows users to set specific timeout values for synthetic monitor scripts, custom code monitor scripts, and workflow scripts. The addition of these timeout configurations improves the flexibility and reliability of the monitoring system.
2024-05-22 20:08:35 +01:00
Simon Larsen
5f7dcf7433 refactor: Update timeout handling in monitor scripts
This commit updates the timeout handling in the monitor scripts to use the `WorkflowScriptTimeoutInMS` and `PROBE_CUSTOM_CODE_MONITOR_SCRIPT_TIMEOUT_IN_MS` values from the environment configuration. This ensures that the monitor scripts have consistent and configurable timeout values, improving the reliability and performance of the monitoring system.
2024-05-22 20:06:32 +01:00
Simon Larsen
39407795a2 refactor: Update logger.debug calls in AnalyticsDatabaseService tests 2024-05-22 14:10:22 +01:00
Simon Larsen
63dfb56da3 refactor: Update return value in StatusPageDomainService
The return value in the `getStatusPageDomain` method of the `StatusPageDomainService` class was updated to `true` to fix a bug where it was always returning `false`. This change ensures that the method returns the correct value based on the success or failure of the database query.
2024-05-22 13:35:18 +01:00
Simon Larsen
ed8714cc34 refactor: Update logger.debug calls in AnalyticsDatabaseService tests
The logger.debug calls in the AnalyticsDatabaseService tests were updated to improve logging consistency and accuracy.
2024-05-22 13:22:37 +01:00
Simon Larsen
dedda5b53b refactor: Add screenshot functionality to synthetic monitor script 2024-05-22 12:39:31 +01:00
Simon Larsen
df2af5858c Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-22 12:34:59 +01:00
Simon Larsen
e25d38ee74 refactor: Update axios dependency to version 1.6.8 2024-05-22 12:34:57 +01:00
Simon Larsen
2b0dd6687d Merge pull request #1435 from OneUptime/snyk-upgrade-8ff00708899512e4a35ebf204a59691e
[Snyk] Upgrade @nivo/core from 0.85.1 to 0.86.0
2024-05-22 12:30:14 +01:00
Simon Larsen
22f08a4c47 refactor: Add timeout information to monitor documentation 2024-05-22 12:26:16 +01:00
Simon Larsen
fda11d81c0 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-22 12:17:27 +01:00
Simon Larsen
18e68b3505 refactor: Remove unnecessary hyphen in monitor documentation
This commit removes an unnecessary hyphen in the monitor documentation by correcting the spelling of "Synthetic Monitor" in both the custom-code-monitor.md and synthetic-monitor.md files. The typo was causing inconsistency in the naming of the monitor, and this fix ensures accuracy and clarity in the documentation.
2024-05-22 12:17:09 +01:00
Simon Larsen
a8a550809d refactor: Fix typo in monitor documentation
This commit fixes a typo in the monitor documentation by correcting the spelling of "Synthetic Monitor" in both the custom-code-monitor.md and synthetic-monitor.md files. The typo was causing inconsistency in the naming of the monitor, and this fix ensures accuracy and clarity in the documentation.
2024-05-22 12:16:42 +01:00
Simon Larsen
dbacf998ff refactor: Add new monitor links to DocsNav
This commit adds new monitor links to the DocsNav utility in the FeatureSet/Docs/Utils/Nav.ts file. The links include "Custom Code Monitor" and "Synthetic Monitor" with their respective URLs. This enhancement improves the navigation experience for users accessing the monitor documentation section.
2024-05-22 12:13:38 +01:00
Simon Larsen
0d41d97b8d refactor: Fix syntax error in MonitorStep and CriteriaFilterUtil 2024-05-22 11:59:33 +01:00
Simon Larsen
36ecf78c4c refactor: Update executionTimeInMS type to number in CustomCodeMonitorResponse
This commit updates the type of the executionTimeInMS property in the CustomCodeMonitorResponse interface from PositiveNumber to number. The PositiveNumber type was unnecessary and caused compatibility issues with other parts of the codebase. Changing it to number simplifies the code and ensures consistency across the application.
2024-05-22 11:57:57 +01:00
Simon Larsen
3eb0eb4289 refactor: Fix syntax error in MonitorStep and CriteriaFilterUtil
This commit fixes a syntax error in the MonitorStep and CriteriaFilterUtil files. In MonitorStep, the syntax error was caused by an extra semicolon (;) in the screenshotDataInBase64 assignment. In CriteriaFilterUtil, the return statement was incorrectly set to true instead of false. These changes ensure that the code is correct and functioning as intended.
2024-05-22 11:47:13 +01:00
Simon Larsen
01c214b51e refactor: Update CodeEditor placeholder for JavaScript type
This commit updates the CodeEditor component to improve the placeholder text for the JavaScript type. The placeholder now includes additional line breaks and indentation for better readability and code organization. This change enhances the user experience when working with JavaScript code in the CodeEditor.
2024-05-22 11:33:54 +01:00
snyk-bot
f756df1e5f fix: upgrade @nivo/core from 0.85.1 to 0.86.0
Snyk has created this PR to upgrade @nivo/core from 0.85.1 to 0.86.0.

See this package in npm:
@nivo/core

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-22 10:21:17 +00:00
Simon Larsen
e2a7f7efc5 refactor: Add support for ArrayOfText field type in Detail component
This commit adds support for the ArrayOfText field type in the Detail component. When the field type is ArrayOfText and there is data available, the data is joined with commas and displayed in the UI. This enhancement improves the user experience by properly rendering and handling the ArrayOfText field type in the Detail component.
2024-05-22 10:58:34 +01:00
Simon Larsen
3bf4137db2 refactor: Update Dockerfile to install necessary dependencies
This commit updates the Dockerfile to install necessary dependencies for the application. It adds the installation of bash, curl, python3, make, g++, and various libraries required for playwright. Additionally, it installs net-tools for network-related functionality. These changes ensure that the application has all the required dependencies to run properly in the Docker environment.
2024-05-22 10:24:06 +01:00
Simon Larsen
f592e852f2 refactor: Update logger.error statements for exiting node process 2024-05-22 10:09:16 +01:00
Simon Larsen
a5f05376b0 refactor: Update logger.debug statements for exiting node process
This commit updates the logger.debug statements in multiple files to log the message 'Exiting node process' instead of 'Exiting node process'. This change improves the logging consistency and ensures that the appropriate log level is used for this message.
2024-05-22 10:04:41 +01:00
Simon Larsen
89e08614f4 refactor: Update RunWorkflow to use VMAPI for replacing values in argumentContent
This commit refactors the RunWorkflow class to use the VMAPI module instead of the deprecated VMUtil module for replacing values in the argumentContent. The VMAPI module provides a more up-to-date and efficient method for replacing values, improving the performance and maintainability of the code.
2024-05-21 20:51:16 +01:00
Simon Larsen
631c22aa64 refactor: Update SyntheticMonitor to use async/await for CustomCodeMonitoringCriteria
This commit updates the SyntheticMonitor class to use async/await when calling the CustomCodeMonitoringCriteria.isMonitorInstanceCriteriaFilterMet() method. This change ensures that the method is properly awaited, allowing for better control flow and error handling. The use of async/await improves the readability and maintainability of the code.
2024-05-21 20:48:46 +01:00
Simon Larsen
0c4ad712b0 refactor: Update CriteriaFilterUtil to filter options based on checkOn value 2024-05-21 20:47:40 +01:00
Simon Larsen
0e4f54d048 refactor: Update CriteriaFilterUtil to filter options based on checkOn value 2024-05-21 20:39:42 +01:00
Simon Larsen
80ede00ced refactor: Update CriteriaFilterUtil to filter options based on checkOn value 2024-05-21 20:37:04 +01:00
Simon Larsen
40b9573324 refactor: Update CriteriaFilterUtil to filter options based on checkOn value
This commit refactors the CriteriaFilterUtil class to improve the filtering of options based on the checkOn value. It removes the unnecessary check for CheckOn.Error in the if statement and adds a new if statement specifically for CheckOn.Error. This change ensures that the options are filtered correctly for each checkOn value, enhancing the accuracy and effectiveness of the criteria filtering functionality.
2024-05-21 20:12:14 +01:00
Simon Larsen
e09f856c92 refactor: Update ProbeApiIngestResponse and APIRequestCriteria
This commit updates the `ProbeApiIngestResponse` interface to include a comment indicating that the `rootCause` property is in markdown format. Additionally, it modifies the `APIRequestCriteria` class to use the `convertToNumber` method from the `CompareCriteria` class instead of the deprecated `convertThresholdToNumber` method. These changes improve the clarity and maintainability of the code.
2024-05-21 19:42:38 +01:00
Simon Larsen
9db5aa56e6 refactor: Update MonitorMetricsByMinute to include browser type and screen size type
This commit modifies the MonitorMetricsByMinute class to include the browserType and screenSizeType properties in the MonitorMetricsMiscData interface. This allows for capturing additional information about the browser type and screen size during monitoring. The changes enhance the accuracy and completeness of the monitoring data.
2024-05-21 15:37:07 +01:00
Simon Larsen
f8c43136e9 refactor: Close browser and page in SyntheticMonitor
This commit refactors the SyntheticMonitor class to ensure that the browser and page are properly closed after use. The code now checks if the page and browser objects exist before attempting to close them, preventing potential memory leaks. This improvement enhances the reliability and efficiency of the SyntheticMonitor functionality.
2024-05-21 15:29:47 +01:00
Simon Larsen
3fb804c4e7 Update import paths for BrowserType and ScreenSizeType enums 2024-05-21 14:49:17 +01:00
Simon Larsen
dad1f1a464 feat: Add support for CustomCodeMonitor in MonitorUtil
This commit adds support for the CustomCodeMonitor type in the MonitorUtil class. It includes the necessary code to execute custom JavaScript code provided in the monitor step data. This enhancement improves the flexibility of the monitoring system by allowing users to define and execute their own custom code for monitoring purposes.
2024-05-21 14:43:03 +01:00
Simon Larsen
95e9eacc83 refactor: Update import paths for VMUtil in JavaScript and IfElse components 2024-05-21 14:42:13 +01:00
Simon Larsen
14b5da110f feat: Update BrowserType enum values
This commit updates the values of the BrowserType enum in the file `Common/Types/BrowserType.ts`. The `Chrome` value is changed to `Chromium`, and the `Safari` value is changed to `Webkit`. This change reflects more accurate and up-to-date browser names, improving the clarity and consistency of the code.
2024-05-21 14:38:15 +01:00
Simon Larsen
b66cd889c0 feat: Update import paths for VMUtil in JavaScript and IfElse components 2024-05-21 14:17:49 +01:00
Simon Larsen
d323c70a51 feat: Add support for SyntheticMonitorResponse in ProbeMonitorResponse
This commit adds the `syntheticMonitorResponse` property to the `ProbeMonitorResponse` interface in order to support the `SyntheticMonitorResponse` type. This allows for the inclusion of synthetic monitor data in the probe monitor response, providing more comprehensive monitoring information.
2024-05-21 13:29:11 +01:00
Simon Larsen
8962ecf42a Merge pull request #1431 from OneUptime/snyk-upgrade-ffa44874323f7156fd8e796f35bbdac2
[Snyk] Upgrade posthog-js from 1.130.0 to 1.130.1
2024-05-21 12:23:42 +01:00
Simon Larsen
31f92c3611 Merge pull request #1433 from OneUptime/snyk-upgrade-43877da1161195f77e3cab219ba9ecab
[Snyk] Upgrade @nivo/line from 0.85.1 to 0.86.0
2024-05-21 12:23:28 +01:00
Simon Larsen
6bed753de3 feat: Add playwright module to VMRunner for browser automation
This commit adds the playwright module to the VMRunner class in order to enable browser automation capabilities. By including playwright, we can now execute code that interacts with web browsers, allowing for more advanced testing and automation scenarios.
2024-05-21 12:08:50 +01:00
Simon Larsen
4017e7ce0e feat: Update import paths for VMUtil in JavaScript and IfElse components
This commit updates the import paths for the VMUtil module in the JavaScript and IfElse components. The new import path is '../../../Utils/VM/VMAPI'. This change ensures that the correct module is imported and used in the components, improving the reliability and maintainability of the code.
2024-05-21 12:07:26 +01:00
Simon Larsen
ccaaaa1823 feat: Fix pagination bug in Pagination component
This commit fixes a bug in the Pagination component where the currentPageNumber was not being properly converted to a number before performing calculations. The bug caused incorrect navigation to the previous and next pages. The issue is resolved by adding a check to convert the currentPageNumber to a number if it is a string.
2024-05-21 12:04:32 +01:00
Simon Larsen
7d7fa2b8f1 feat: Remove unnecessary error message in MonitorStepsElement component 2024-05-21 11:50:47 +01:00
Simon Larsen
2ca57ac8bf feat: Add support for SyntheticMonitor and CustomJavaScriptCode in MonitorTypeHelper
The code changes in `MonitorType.ts` and `MonitorService.ts` add support for the `SyntheticMonitor` and `CustomJavaScriptCode` monitor types in the `MonitorTypeHelper` class. This allows for easier identification of probeable monitor types and improves the flexibility of the monitoring system.
2024-05-21 11:22:26 +01:00
Simon Larsen
a75f655f72 feat: Update code editor placeholders for MonitorStep
This commit updates the code editor placeholders in the MonitorStep component to provide example code using axios and playwright modules. This allows users to easily understand and customize the code for their specific monitoring needs.
2024-05-21 11:13:29 +01:00
Simon Larsen
6ca38a1adb feat: Update MonitorStep to remove unnecessary documentation line 2024-05-21 10:57:41 +01:00
Simon Larsen
46a095569d feat: Update code editor placeholders for CustomJavaScriptCode and SyntheticMonitor
This commit updates the code editor placeholders in the MonitorStep component for the CustomJavaScriptCode and SyntheticMonitor types. The placeholders now provide example code using axios and playwright modules, allowing users to easily understand and customize the code for their specific monitoring needs.
2024-05-21 10:55:29 +01:00
Simon Larsen
cec38190fd feat: Update fetchDropdownOptions to accept item parameter
This commit modifies the `fetchDropdownOptions` function in the `Field` interface to accept an additional `item` parameter of type `FormValues<TEntity>`. This change allows for more dynamic fetching of dropdown options based on the current form values, improving the flexibility and customization of the form fields.
2024-05-21 10:44:49 +01:00
Simon Larsen
ca746d1436 feat: Update CategoryCheckboxType to make categoryId optional
This commit updates the `CategoryCheckboxType` interface to make the `categoryId` property optional. This change allows for more flexibility when working with category checkboxes, as the `categoryId` is not always required.
2024-05-21 10:20:46 +01:00
snyk-bot
2f6133bba0 fix: upgrade @nivo/line from 0.85.1 to 0.86.0
Snyk has created this PR to upgrade @nivo/line from 0.85.1 to 0.86.0.

See this package in npm:
@nivo/line

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-21 08:38:52 +00:00
snyk-bot
d1f62d3c66 fix: upgrade @nivo/core from 0.85.1 to 0.86.0
Snyk has created this PR to upgrade @nivo/core from 0.85.1 to 0.86.0.

See this package in npm:
@nivo/core

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-21 08:38:48 +00:00
snyk-bot
db2c6b0ea5 fix: upgrade posthog-js from 1.130.0 to 1.130.1
Snyk has created this PR to upgrade posthog-js from 1.130.0 to 1.130.1.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-21 08:22:26 +00:00
Simon Larsen
a2033b94dd feat: Add checkbox lists for browser type and screen type in SyntheticMonitor
This commit adds checkbox lists for selecting the browser type and screen type in the SyntheticMonitor step of the MonitorStep component. This allows users to choose the desired browser and screen type for running the test in SyntheticMonitor.
2024-05-20 21:37:27 +01:00
Simon Larsen
d23c62d30a feat: Update CheckOn enum value to 'ResultValue'
This commit updates the CheckOn enum value in the CriteriaFilter module from 'Result' to 'ResultValue'. This change provides a more descriptive and accurate representation of the value being checked in custom code or JavaScript monitors.
2024-05-20 21:26:28 +01:00
Simon Larsen
6ca5b9572e feat: Add setCustomCode method to MonitorStep class
The code changes include adding a new method, `setCustomCode`, to the `MonitorStep` class. This method allows for setting custom code for a monitor step, enabling the execution of custom JavaScript code in certain types of monitors.
2024-05-20 21:08:51 +01:00
Simon Larsen
f5f62d905b feat: Add custom code support for monitor steps
The code changes include adding support for custom code in monitor steps. This allows for the execution of custom code or JavaScript in certain types of monitors.
2024-05-20 21:03:08 +01:00
Simon Larsen
876de677cd refactor: Update MonitorType descriptions for clarity and consistency 2024-05-20 20:18:23 +01:00
Simon Larsen
19cb221f33 feat: Add isEditable prop to StatusPageDelete component 2024-05-20 19:19:54 +01:00
Simon Larsen
f0f774ecdb Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-20 15:20:08 +01:00
Simon Larsen
e333c2d43b Merge remote-tracking branch 'origin/snyk-upgrade-74c46bacccd4fb74e83b0646ec8750cb' 2024-05-20 15:20:05 +01:00
Simon Larsen
4cdb832b34 Merge remote-tracking branch 'origin/snyk-upgrade-462450f669807b7eb04e4c4d125fbf2b' into release 2024-05-20 15:17:36 +01:00
Simon Larsen
367715c077 Merge pull request #1428 from OneUptime/snyk-upgrade-3b57e17a87dddbfededa11f5d0e72927
[Snyk] Upgrade: react, react-dom
2024-05-19 09:01:40 +01:00
Simon Larsen
945eb3d11b Merge pull request #1429 from OneUptime/snyk-upgrade-69be6d2a85331ea8cb47b3e28bcc2efe
[Snyk] Upgrade: react, react-dom
2024-05-19 09:01:35 +01:00
snyk-bot
b4c4273485 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.3.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.3.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/11bb5528-45f9-473c-a635-dc097fd03b3c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-19 06:44:45 +00:00
snyk-bot
1c319bb432 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/8ca4ee75-8bc5-43a1-a3bc-244ceebf1437?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-19 06:42:42 +00:00
Simon Larsen
6fc8bc3628 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-18 20:33:28 +01:00
Simon Larsen
33e9c8fbe7 refactor: Optimize bulk item deselection logic in Table component 2024-05-18 20:33:11 +01:00
Simon Larsen
6f4da22874 refactor: Update ProgressBar component to support different sizes 2024-05-18 19:53:04 +01:00
Simon Larsen
772341a15c refactor: Update Table and FilterViewer components
This code change updates the Table and FilterViewer components to improve their functionality and user experience.

In the Table component, the onActionEnd callback is modified to reset the state of isAllItemsSelected, setBulkSelectedItems, and then call the props.onBulkActionEnd function. This change ensures that the bulk action end event is handled correctly.

In the FilterViewer component, the styling of the filter criteria section is updated to improve readability. The font size and spacing are adjusted to provide a better visual presentation of the filter criteria.

These refactorings enhance the overall performance and usability of the components.
2024-05-18 19:41:05 +01:00
Simon Larsen
387fdd7b15 Merge pull request #1426 from OneUptime/snyk-upgrade-424acac7465574c09845de51ffbb9e27
[Snyk] Upgrade posthog-js from 1.129.0 to 1.130.0
2024-05-18 19:18:05 +01:00
Simon Larsen
16bad74c4d Merge pull request #1427 from OneUptime/snyk-upgrade-977cadc46113d94d06a8445c04bd36a6
[Snyk] Upgrade: react, react-dom
2024-05-18 19:18:00 +01:00
Simon Larsen
054242df60 refactor: Optimize bulk item deselection in Table component 2024-05-18 19:13:38 +01:00
snyk-bot
3d4aecb896 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.3.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.3.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-18 17:51:55 +00:00
snyk-bot
26c8712fce fix: upgrade posthog-js from 1.129.0 to 1.130.0
Snyk has created this PR to upgrade posthog-js from 1.129.0 to 1.130.0.

See this package in npm:
posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-18 17:41:08 +00:00
Simon Larsen
ab090ab016 refactor: Optimize bulk item deselection in Table component
This code change optimizes the bulk item deselection functionality in the Table component. Instead of using the `filter` method to remove the deselected item from the `bulkSelectedItems` array, it now uses the `findIndex` method to locate the index of the item and then removes it using the `splice` method. This approach improves the performance of bulk item deselection, especially when dealing with large datasets.
2024-05-18 16:34:00 +01:00
Simon Larsen
4653711b58 refactor: Improve error handling in BulkUpdateForm
This code change improves the error handling in the BulkUpdateForm component. The error handling logic is updated to display a more informative error message when a bulk update action fails. This refactor enhances the user experience by providing clearer feedback on failed bulk actions.
2024-05-18 16:28:52 +01:00
Simon Larsen
9aa1876e70 refactor: Update SimpleLogViewer component to be used in BulkUpdateForm
This code change updates the SimpleLogViewer component to be used in the BulkUpdateForm. The component is imported and rendered in the BulkUpdateForm to display logs in a consistent and reusable way. This refactor improves code reusability and reduces duplication by leveraging an existing component for log viewing.
2024-05-18 16:25:14 +01:00
Simon Larsen
40d9aff56a refactor: Update SimpleLogViewer component to use in CallLog, Probes, Workflow, and StatusTimeline pages
This code change updates the SimpleLogViewer component to be used in the CallLog, Probes, Workflow, and StatusTimeline pages. The component is imported and rendered in these pages to display logs in a consistent and reusable way. This refactor improves code reusability and reduces duplication across multiple pages.
2024-05-18 16:20:11 +01:00
Simon Larsen
3c88a1b879 refactor: Update ProgressBar component to support different sizes
This code change updates the ProgressBar component to support different sizes. A new enum `ProgressBarSize` is introduced to define the available sizes: Small, Medium, and Large. The `size` prop is added to the `ComponentProps` interface, allowing the user to specify the desired size of the progress bar. This enhancement provides more flexibility in customizing the appearance of the progress bar based on the UI requirements.
2024-05-18 16:07:32 +01:00
Simon Larsen
149baf17ef refactor: Optimize bulk item deselection in Table component
This code change optimizes the bulk item deselection functionality in the Table component. Instead of using the `filter` method to remove the deselected item from the `bulkSelectedItems` array, it now uses the `findIndex` method to locate the index of the item and then removes it using the `splice` method. This approach improves the performance of bulk item deselection, especially when dealing with large datasets.
2024-05-18 15:57:38 +01:00
Simon Larsen
424cfa2094 refactor: Fix bulk action end event handling in Table component 2024-05-18 15:49:32 +01:00
Simon Larsen
d114c52d6f refactor: Optimize bulk item deselection in Table component 2024-05-18 14:55:30 +01:00
Simon Larsen
213e2111a5 refactor: Optimize bulk item deselection in Table component
This code change optimizes the bulk item deselection functionality in the Table component. Instead of using the `filter` method to remove the deselected item from the `bulkSelectedItems` array, it now uses the `findIndex` method to locate the index of the item and then removes it using the `splice` method. This approach improves the performance of bulk item deselection, especially when dealing with large datasets.
2024-05-18 14:30:47 +01:00
Simon Larsen
31837ef1f5 feat: Add support for bulk actions in Table component 2024-05-18 14:29:22 +01:00
Simon Larsen
b906ff1dce Merge pull request #1423 from OneUptime/snyk-upgrade-853a678be23c5b34b8ae866769c5a56d
[Snyk] Upgrade: react, react-dom
2024-05-18 13:42:04 +01:00
Simon Larsen
cc4d6514cc Merge pull request #1422 from OneUptime/snyk-upgrade-f86bfe08d4514e02784875637d35f3da
[Snyk] Upgrade react-router-dom from 6.22.3 to 6.23.0
2024-05-18 13:41:34 +01:00
Simon Larsen
005256084e Merge pull request #1424 from OneUptime/snyk-upgrade-79a48669a7990a61a83374567c38f84c
[Snyk] Upgrade: react, react-dom
2024-05-18 13:41:28 +01:00
Simon Larsen
67b542d828 feat: Add bulk actions to Table component
The code changes in this commit add support for bulk actions in the Table component. The `BulkActionProps` interface is introduced to define the bulk action buttons, and the `BulkUpdateForm` component is rendered to display the bulk action buttons when provided. This enhancement allows users to perform actions on multiple items in the table simultaneously, improving the efficiency of managing data.
2024-05-17 21:40:10 +01:00
snyk-bot
c147c49465 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/5dd2ef9c-1270-4729-aff4-e407805f7a9c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-17 18:05:45 +00:00
snyk-bot
9428d08def fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/40b17bc5-1bd4-48b1-88f1-5b4dc1400e80?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-17 17:38:03 +00:00
snyk-bot
79f27550df fix: upgrade react-router-dom from 6.22.3 to 6.23.0
Snyk has created this PR to upgrade react-router-dom from 6.22.3 to 6.23.0.

See this package in npm:
https://www.npmjs.com/package/react-router-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/8ca4ee75-8bc5-43a1-a3bc-244ceebf1437?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-17 17:08:53 +00:00
snyk-bot
21d62eab18 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.2.0 to 18.3.1.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/8ca4ee75-8bc5-43a1-a3bc-244ceebf1437?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-17 17:08:48 +00:00
Simon Larsen
f011559cd2 chore: Add disableSubmitButton prop to ConfirmModal 2024-05-17 18:05:29 +01:00
Simon Larsen
4bb5a29963 refactor: Update axios and posthog-js dependencies
This code change updates the axios and posthog-js dependencies to their latest versions. The axios dependency is updated from 1.6.7 to 1.6.8, and the posthog-js dependency is updated from 1.115.0 to 1.129.0. This update ensures that we have the latest bug fixes and improvements for these libraries, improving the overall stability and performance of our application.
2024-05-17 15:19:16 +01:00
Simon Larsen
e771172b79 refactor: Remove unused code in FilterViewer.tsx 2024-05-17 15:13:07 +01:00
Simon Larsen
9476327a6a Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-17 14:31:01 +01:00
Simon Larsen
7c14931bb9 refactor: Remove unused @types/markdown-it dependency 2024-05-17 14:30:39 +01:00
Simon Larsen
2ad245083d Merge pull request #1416 from OneUptime/snyk-upgrade-87afa35300d240576e9a2e10b5028185
[Snyk] Upgrade @opentelemetry/instrumentation-xml-http-request from 0.50.0 to 0.51.0
2024-05-17 14:03:54 +01:00
Simon Larsen
81da1546d9 Merge pull request #1419 from OneUptime/markdown-refactor
refactor: Update dependencies and scripts in package.json files
2024-05-17 14:00:41 +01:00
Simon Larsen
a48f472c52 refactor: Update Markdown import in UserNotificationRuleService.ts 2024-05-17 14:00:19 +01:00
Simon Larsen
2a9b3db168 Merge pull request #1418 from OneUptime/snyk-upgrade-4dfc247506d9048ad782d9cdb39ee861
[Snyk] Upgrade: react, react-dom
2024-05-17 13:40:42 +01:00
Simon Larsen
bbc95a3a1d Merge pull request #1417 from OneUptime/snyk-upgrade-2b094c75c37c28e17e318b9fecab3c1a
[Snyk] Upgrade formik from 2.4.5 to 2.4.6
2024-05-17 13:40:37 +01:00
Simon Larsen
0bbb35ff43 Merge pull request #1415 from OneUptime/snyk-upgrade-98c666ed907eebd3249d1581c5f9aca0
[Snyk] Upgrade: react, react-dom
2024-05-17 13:40:27 +01:00
Simon Larsen
7edd8f197a refactor: Remove unused code in Markdown.ts
This code change removes the unused code in the Markdown.ts file that was responsible for customizing the rendering of paragraphs, blockquotes, images, and headings. This code is no longer needed and can be safely removed, simplifying the codebase and improving maintainability.
2024-05-17 13:32:56 +01:00
Simon Larsen
1ad239a9fe Remove unused Tailwind CSS configuration code from the End.hbs template file. The removed code was setting the font family for the display and body elements. This code is no longer needed and can be safely removed. 2024-05-17 13:26:46 +01:00
Simon Larsen
eeae73b7a4 refactor: Update Markdown import in UserNotificationRuleService.ts
This code change updates the import statement for the Markdown module in the UserNotificationRuleService.ts file. It now imports the Markdown module along with the MarkdownContentType enum from the Types/Markdown file. This update ensures that the MarkdownContentType.Email is used when converting the incident description to HTML. This change improves the handling of Markdown content in the UserNotificationRuleService.
2024-05-17 13:24:51 +01:00
Simon Larsen
026997a679 refactor: Update dependencies and scripts in package.json files 2024-05-17 13:17:56 +01:00
Simon Larsen
aa83db3e48 refactor: Add deletedByUser and deletedByUserId columns to User model
This code change adds the `deletedByUser` and `deletedByUserId` columns to the `User` model. These columns are used to track the user who deleted the object and their corresponding user ID. This enhancement allows for better auditing and tracking of deleted objects in the system.
2024-05-17 12:08:05 +01:00
snyk-bot
5725c6a17a fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.2.0 to 18.3.0.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.2.0 to 18.3.0.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/11bb5528-45f9-473c-a635-dc097fd03b3c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-16 21:55:07 +00:00
snyk-bot
79171c93d9 fix: upgrade formik from 2.4.5 to 2.4.6
Snyk has created this PR to upgrade formik from 2.4.5 to 2.4.6.

See this package in npm:
https://www.npmjs.com/package/formik

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-16 21:39:13 +00:00
snyk-bot
5073a15bf1 fix: upgrade @opentelemetry/instrumentation-xml-http-request from 0.50.0 to 0.51.0
Snyk has created this PR to upgrade @opentelemetry/instrumentation-xml-http-request from 0.50.0 to 0.51.0.

See this package in npm:
https://www.npmjs.com/package/@opentelemetry/instrumentation-xml-http-request

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-16 21:39:09 +00:00
snyk-bot
9285e9b401 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - react from 18.2.0 to 18.3.0.
    See this package in npm: https://www.npmjs.com/package/react
  - react-dom from 18.2.0 to 18.3.0.
    See this package in npm: https://www.npmjs.com/package/react-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-16 21:39:02 +00:00
Simon Larsen
b6adf3fb40 refactor: Improve JSON filter handling in StatementGenerator.ts 2024-05-16 17:46:43 +01:00
Simon Larsen
164e6062c9 refactor: Improve JSON filter handling in StatementGenerator.ts 2024-05-16 17:38:21 +01:00
Simon Larsen
1ebc8a9d91 feat: Add support for JSON filters in BaseModelTable
This commit adds support for JSON filters in the `BaseModelTable` component. It checks if a filter is of type `FieldType.JSON` and if the filter data is of type `Object`. If both conditions are met, the filter data is included in the query. This enhancement allows for more flexible filtering options when working with JSON data in the table.
2024-05-16 17:32:03 +01:00
Simon Larsen
3205453608 refactor: Update Dictionary component to handle different value types 2024-05-16 16:28:56 +01:00
Simon Larsen
be3d4b2ce0 refactor: Update Dictionary component to handle different value types
The code changes in the Dictionary component refactor the implementation to handle different value types, including strings, numbers, and booleans. This allows for more flexibility and accuracy when working with dictionary data in the component.
2024-05-16 16:20:59 +01:00
Simon Larsen
7c8aabe3e8 feat: Improve formatJson function in FilterViewer component
The code changes in the FilterViewer component improve the formatJson function by updating the styling and layout of the rendered JSON elements. This enhances the readability and visual presentation of the JSON data in the component.
2024-05-16 14:07:20 +01:00
Simon Larsen
b0c62ed827 Merge branch 'master' into attributes-filter 2024-05-16 13:32:07 +01:00
Simon Larsen
80a1827455 chore: Update ServerMonitorDocumentation script to use sudo for agent installation and configuration 2024-05-16 13:28:31 +01:00
Simon Larsen
bbb1b2e944 feat: Add equals icon to Dictionary component
The code changes add the `Equals` icon to the `Dictionary` component in the `CommonUI` module. This icon is used to visually represent the equality operator in the component.
2024-05-16 13:27:01 +01:00
Simon Larsen
f70878317a Merge branch 'master' into attributes-filter 2024-05-16 12:40:58 +01:00
Simon Larsen
f5184db0fa feat: Update UptimeUtil to sort monitor status timeline items by start date 2024-05-16 11:47:03 +01:00
Simon Larsen
19128a50d2 feat: Sort monitor status timeline items by start date in UptimeUtil.getMonitorEventsForId() 2024-05-16 11:45:35 +01:00
Simon Larsen
8fbb3774d1 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-16 10:53:42 +01:00
Simon Larsen
441efb3d1a chore: Update ServerMonitorDocumentation script to use sudo for agent installation and configuration 2024-05-16 10:53:39 +01:00
Simon Larsen
180491fa57 Merge pull request #1410 from OneUptime/snyk-upgrade-15b470e61c0a4d4baa2eaa864ea3be83
[Snyk] Upgrade react-router-dom from 6.22.2 to 6.23.0
2024-05-16 09:36:07 +01:00
Simon Larsen
7269e93967 Merge pull request #1411 from OneUptime/snyk-upgrade-e4184b69842e3f221e7c756fa028c1da
[Snyk] Upgrade posthog-js from 1.128.3 to 1.129.0
2024-05-16 09:36:02 +01:00
Simon Larsen
a754ec094b Merge pull request #1412 from OneUptime/snyk-upgrade-306eaee1a74876bbe32ce542109f7a61
[Snyk] Upgrade @opentelemetry/exporter-trace-otlp-http from 0.50.0 to 0.51.0
2024-05-16 09:35:47 +01:00
Simon Larsen
d9e097eeb2 Merge pull request #1414 from OneUptime/snyk-upgrade-1581bc45275ce8db68d7fda22e605ad3
[Snyk] Upgrade @opentelemetry/instrumentation-fetch from 0.50.0 to 0.51.0
2024-05-16 09:35:40 +01:00
snyk-bot
53d7aab558 fix: upgrade @opentelemetry/instrumentation-fetch from 0.50.0 to 0.51.0
Snyk has created this PR to upgrade @opentelemetry/instrumentation-fetch from 0.50.0 to 0.51.0.

See this package in npm:
https://www.npmjs.com/package/@opentelemetry/instrumentation-fetch

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-15 21:28:18 +00:00
snyk-bot
dcf2584987 fix: upgrade @opentelemetry/instrumentation from 0.50.0 to 0.51.0
Snyk has created this PR to upgrade @opentelemetry/instrumentation from 0.50.0 to 0.51.0.

See this package in npm:
https://www.npmjs.com/package/@opentelemetry/instrumentation

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-15 21:28:14 +00:00
snyk-bot
d18310ec69 fix: upgrade @opentelemetry/exporter-trace-otlp-http from 0.50.0 to 0.51.0
Snyk has created this PR to upgrade @opentelemetry/exporter-trace-otlp-http from 0.50.0 to 0.51.0.

See this package in npm:
https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-15 21:28:09 +00:00
snyk-bot
f61d603e21 fix: upgrade posthog-js from 1.128.3 to 1.129.0
Snyk has created this PR to upgrade posthog-js from 1.128.3 to 1.129.0.

See this package in npm:
https://www.npmjs.com/package/posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-15 21:14:16 +00:00
snyk-bot
52a44a8383 fix: upgrade react-router-dom from 6.22.2 to 6.23.0
Snyk has created this PR to upgrade react-router-dom from 6.22.2 to 6.23.0.

See this package in npm:
https://www.npmjs.com/package/react-router-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/5dd2ef9c-1270-4729-aff4-e407805f7a9c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-15 17:51:59 +00:00
Simon Larsen
be848d37a2 Update field descriptions in MonitorCriteriaInstance and MonitorSteps components to improve clarity and consistency. 2024-05-15 17:23:21 +01:00
Simon Larsen
df3a7e1a99 Merge pull request #1408 from OneUptime/snyk-upgrade-1bf0797993f09a9d25f81a37ef931556
[Snyk] Upgrade react-router-dom from 6.22.3 to 6.23.0
2024-05-15 16:46:41 +01:00
Simon Larsen
a6e9f7cd1e feat: Add startsAt and endsAt fields to MonitorView component 2024-05-15 10:59:10 +01:00
Simon Larsen
2e29a63f7b chore: Use explicit type annotation in UptimeUtil loop 2024-05-15 10:38:25 +01:00
Simon Larsen
c153c8c656 chore: Add YouTube tutorial link to README.md 2024-05-15 10:22:56 +01:00
Simon Larsen
61cbaaf4f0 chore: Fix missing end dates in MonitorStatusTimeline 2024-05-15 10:21:58 +01:00
Simon Larsen
70aae76ae3 Merge branch 'master' of github.com:OneUptime/oneuptime 2024-05-14 19:13:08 +01:00
Simon Larsen
972bc9c4cf chore: Update E2E test environment variables in config.example.env 2024-05-14 19:12:52 +01:00
snyk-bot
fb902170e2 fix: upgrade react-router-dom from 6.22.3 to 6.23.0
Snyk has created this PR to upgrade react-router-dom from 6.22.3 to 6.23.0.

See this package in npm:
https://www.npmjs.com/package/react-router-dom

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/40b17bc5-1bd4-48b1-88f1-5b4dc1400e80?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-14 17:21:26 +00:00
Simon Larsen
286429b58f Merge pull request #1404 from OneUptime/snyk-upgrade-9daf4730397a2c5fc08ea00edc4e2109
[Snyk] Upgrade posthog-js from 1.128.1 to 1.128.3
2024-05-14 18:09:32 +01:00
Simon Larsen
b799ce08a9 Merge pull request #1405 from OneUptime/snyk-upgrade-ad84e59eae164272636397edd988457f
[Snyk] Upgrade reactflow from 11.11.1 to 11.11.2
2024-05-14 18:09:25 +01:00
Simon Larsen
b30bb4c95e chore: Update infrastructure agent installation script and documentation 2024-05-14 17:55:15 +01:00
Simon Larsen
0e3eb81ae4 chore: Fix missing end dates in MonitorStatusTimeline 2024-05-14 17:01:57 +01:00
Simon Larsen
b997520977 Merge pull request #1407 from OneUptime/semaphore-monitor-status-timeline
chore: Add mutex lock and release for MonitorStatusTimeline creation
2024-05-14 16:55:50 +01:00
Simon Larsen
29675f2624 Update GoReleaser command in release workflow to include GORELEASER_CURRENT_TAG environment variable 2024-05-14 16:54:45 +01:00
Simon Larsen
fb83476795 chore: Add new data migration to include missing end dates in MonitorStatusTimeline 2024-05-14 16:43:42 +01:00
Simon Larsen
0420586a0e chore: Add mutex lock and release for MonitorStatusTimeline creation 2024-05-14 16:36:25 +01:00
Simon Larsen
900f76f8c8 chore: Update GoReleaser command in release workflow to include GORELEASER_CURRENT_TAG environment variable 2024-05-14 16:27:13 +01:00
Simon Larsen
082c5732c0 chore: Improve UptimeUtil logic for calculating end date 2024-05-14 16:11:46 +01:00
Simon Larsen
20c03c5fd9 chore: Update GoReleaser to version 1 and run release command for InfrastructureAgent 2024-05-14 15:59:52 +01:00
Simon Larsen
5adb8f0d38 chore: Update E2E test environment variables in config.example.env 2024-05-14 15:39:19 +01:00
Simon Larsen
a54037408e Update docker-compose.md with installation tutorial link 2024-05-14 15:37:14 +01:00
Simon Larsen
4c0cf60c42 chore: Update docker-compose.md with sudo command for binding ports 2024-05-14 15:19:16 +01:00
Simon Larsen
6aac72a226 chore: Update dependencies and job dependencies for infrastructure-agent-deploy 2024-05-14 12:56:43 +01:00
Simon Larsen
d1424840d8 chore: Update infrastructure-agent-deploy job dependency to github-release 2024-05-14 12:55:32 +01:00
Simon Larsen
0a90736338 chore: Configure OneUptime Infrastructure Agent as a system service
```
2024-05-14 12:23:15 +01:00
Simon Larsen
6c2144d77e chore: Update go version to 1.22.0 in go.mod file 2024-05-14 12:09:08 +01:00
Simon Larsen
e208b7cc78 Refactor .goreleaser.yaml to use string values for goarm instead of integers 2024-05-14 12:05:37 +01:00
Simon Larsen
69ff3dfe17 Refactor .goreleaser.yaml to use string values for goarm instead of integers 2024-05-14 11:55:48 +01:00
Simon Larsen
29d2abf226 Refactor .gitignore to include InfrastructureAgent/oneuptime-infrastructure-agent 2024-05-14 11:51:44 +01:00
Simon Larsen
1cf7cc4664 Refactor main.go to improve service control commands and error handling 2024-05-14 11:51:36 +01:00
Simon Larsen
d29991117a chore: Update actions/checkout and actions/setup-go versions 2024-05-14 11:46:13 +01:00
Simon Larsen
0bf8713b60 Refactor error handling in main.go for better clarity and instructions 2024-05-14 11:15:15 +01:00
Simon Larsen
dcc9d4fdf2 Refactor error messages in main.go for better clarity and instructions 2024-05-14 10:05:54 +01:00
Simon Larsen
db32292d33 chore: Update launch.json and config.go for InfrastructureAgent 2024-05-14 10:02:48 +01:00
snyk-bot
2b66c52907 fix: upgrade reactflow from 11.11.1 to 11.11.2
Snyk has created this PR to upgrade reactflow from 11.11.1 to 11.11.2.

See this package in npm:
https://www.npmjs.com/package/reactflow

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/8ca4ee75-8bc5-43a1-a3bc-244ceebf1437?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-13 21:23:21 +00:00
snyk-bot
d6b1edb8cb fix: upgrade posthog-js from 1.128.1 to 1.128.3
Snyk has created this PR to upgrade posthog-js from 1.128.1 to 1.128.3.

See this package in npm:
https://www.npmjs.com/package/posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-13 20:56:52 +00:00
Simon Larsen
c7f62fac65 Refactor InfrastructureAgent code to add help command 2024-05-13 21:22:49 +01:00
Simon Larsen
db0aee6c0f chore: Refactor code to use model package for memory, processes, disk, and CPU metrics 2024-05-13 21:12:45 +01:00
Simon Larsen
1f53ecb093 Refactor package names and imports in InfrastructureAgent code files 2024-05-13 20:37:27 +01:00
Simon Larsen
d0325f2d7d chore: Remove unused code files for memory, processes, disk, and CPU metrics 2024-05-13 20:28:21 +01:00
Simon Larsen
a1461a4019 chore: Refactor package imports in InfrastructureAgent code files 2024-05-13 17:49:53 +01:00
Simon Larsen
d3096510bd chore: Refactor package names in InfrastructureAgent code files 2024-05-13 17:15:42 +01:00
Simon Larsen
8dac1a845a chore: Refactor package names in InfrastructureAgent code files 2024-05-13 16:48:47 +01:00
Simon Larsen
da26400aa7 chore: Refactor package names in InfrastructureAgent code files 2024-05-13 14:00:48 +01:00
Simon Larsen
c909d02a5d chore: Refactor package names in InfrastructureAgent code files 2024-05-13 13:41:33 +01:00
Simon Larsen
58e817cecd chore: Update workflow to use Go instead of Node.js for InfrastructureAgent 2024-05-13 09:41:39 +01:00
Simon Larsen
f9a784422d Merge pull request #1399 from anxuanzi/infra-agent-go
Remove the nodejs version agent, rewrite in Golang
2024-05-13 08:28:37 +01:00
Simon Larsen
6494ab9a71 Merge pull request #1400 from neurekadev/update-docker-compose-docs
docs: export env variables in a subshell
2024-05-13 08:16:57 +01:00
Neureka
a3cf038d38 docs: export env variables in a subshell 2024-05-12 12:02:32 -07:00
Simon Larsen
99a88ea6d7 Merge pull request #1397 from OneUptime/snyk-fix-3892a7e111663caea5c508696d2964c1
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-11 21:09:44 +01:00
Simon Larsen
d46604da53 Merge pull request #1398 from OneUptime/snyk-fix-3b2b2fa56f80398bc77252e1d04e6fcc
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-11 21:09:34 +01:00
Tony An
4a05ee22be ♻️ remove the nodejs version agent, rewrite in Golang 2024-05-10 19:37:40 -05:00
snyk-bot
28e809c493 fix: Probe/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-UPSTREAM-NODE-6615824
2024-05-10 23:23:48 +00:00
snyk-bot
610373525b fix: StatusPage/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-UPSTREAM-NODE-6615824
2024-05-10 23:12:01 +00:00
Simon Larsen
e84d1c2960 Merge pull request #1396 from OneUptime/snyk-fix-45b3084604f2d5d8f141f074ac048cd5
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-10 23:26:19 +01:00
snyk-bot
17cb699751 fix: AdminDashboard/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-UPSTREAM-NODE-6615824
2024-05-10 22:04:51 +00:00
Simon Larsen
c3bf383e89 refactor: Update Dictionary component dropdown options
This commit updates the dropdown options in the Dictionary component to use more descriptive variable names. The previous variable names, trueDropdwonOption and falseDropdwonOption, have been changed to trueDropdownOption and falseDropdownOption respectively. This change improves code readability and maintainability.
2024-05-10 11:29:45 +01:00
Simon Larsen
a3e5288737 feat: Add JSONFilter component to FiltersForm
This commit adds the JSONFilter component to the FiltersForm in order to support filtering based on JSON data. The JSONFilter component is imported and rendered within the FiltersForm component, allowing users to input JSON filter criteria. This enhancement expands the filtering capabilities of the application.
2024-05-10 11:20:24 +01:00
Simon Larsen
14cf0d9343 refactor: Update DictionaryOfStrings component
This commit refactors the DictionaryOfStrings component by removing unused imports and simplifying the code structure. The useState hook is now used to manage the component's data state, and the useEffect hook is used to handle changes in the data. The component now uses the DictionaryForm component for rendering and handling user input. These changes improve the readability and maintainability of the code.
2024-05-10 11:09:41 +01:00
Simon Larsen
4ed613bf2c refactor: Update filter labels and submit button text in FilterViewer.tsx 2024-05-10 10:29:06 +01:00
Simon Larsen
f07da41cca Merge remote-tracking branch 'origin/snyk-upgrade-b5d9f77f3c65feeabefe361b92d3d1c8' 2024-05-10 10:27:59 +01:00
Simon Larsen
fe2300146d Merge remote-tracking branch 'origin/snyk-upgrade-ac3f89b452385bc8a0a778616c176acd' 2024-05-10 10:27:07 +01:00
Simon Larsen
207108dc2d Merge remote-tracking branch 'origin/snyk-upgrade-660a96f185a31fad496e714aa07c52b5' 2024-05-10 10:26:23 +01:00
Simon Larsen
b728256c63 refactor: Update font size for filter label in FilterViewer.tsx 2024-05-10 10:23:14 +01:00
Simon Larsen
0e5b71070c refactor: Update filter labels and submit button text in FilterViewer.tsx
This commit updates the filter labels and submit button text in the FilterViewer component. The 'FILTER BY' label is changed to 'FILTER' and the labels are now capitalized. Additionally, the submit button text is changed to 'Apply Filters'. These changes improve the clarity and consistency of the user interface.
2024-05-10 09:55:32 +01:00
Simon Larsen
4c4bc92a14 chore: Update font weight for filter label in FilterViewer.tsx 2024-05-10 09:48:35 +01:00
Simon Larsen
40dccbb382 refactor: Simplify SQL query construction in AnalyticsDatabaseService.ts 2024-05-10 09:42:50 +01:00
Simon Larsen
eedb7173db chore: Update submit button text in FilterViewer.tsx 2024-05-10 08:31:55 +01:00
Simon Larsen
917d12d7f0 refactor: Update FilterViewerItem and DropdownFilter components
This commit refactors the FilterViewerItem and DropdownFilter components to handle changes in the ComponentProps interface. The 'text' prop in FilterViewerItem now accepts a string or ReactElement, and the 'onFilterModalClose' and 'onFilterModalOpen' props in DropdownFilter are now optional. These changes ensure compatibility with the latest version of the codebase and improve code readability and maintainability.
2024-05-10 08:19:10 +01:00
Simon Larsen
11a9cfcb98 Merge pull request #1381 from OneUptime/snyk-upgrade-497decbbac4afbc555f4ba887111dc9a
[Snyk] Upgrade posthog-js from 1.126.0 to 1.128.1
2024-05-10 07:31:54 +01:00
Simon Larsen
172c3dacbe Merge pull request #1382 from OneUptime/snyk-fix-6736c09b254d6ed19f0c345a7715e526
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-10 07:31:43 +01:00
Simon Larsen
a9381e09c1 Merge pull request #1385 from OneUptime/snyk-fix-6370d57d4cb33cebd301a9f8099f0700
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-10 07:31:38 +01:00
Simon Larsen
f0816f6fa5 Merge pull request #1383 from OneUptime/snyk-fix-1337460fdd963d53e523192123f3d100
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-10 07:31:08 +01:00
Simon Larsen
ad95971f46 Merge pull request #1384 from OneUptime/snyk-fix-36290d6a0a64cee8ddc0de0f03f981a7
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-10 07:31:04 +01:00
Simon Larsen
bb59a365b7 Merge pull request #1386 from OneUptime/snyk-fix-a7809d569ba1546656fa651f1bb77337
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-10 07:30:57 +01:00
Simon Larsen
503dcffa87 Merge pull request #1387 from OneUptime/snyk-fix-f6067898842e100de3b29fb82f59daf0
[Snyk] Security upgrade node from 21.7.2-alpine3.18 to 21.7.3-alpine3.18
2024-05-10 07:30:51 +01:00
Simon Larsen
42a91415da refactor: Update FilterUtil to handle FieldType.Boolean filters 2024-05-10 07:30:16 +01:00
snyk-bot
09c6160a15 fix: Ingestor/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
2024-05-09 21:47:35 +00:00
snyk-bot
0638b797b3 fix: TestServer/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
2024-05-09 21:46:36 +00:00
snyk-bot
c6020a8eb6 fix: Accounts/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
2024-05-09 21:41:32 +00:00
snyk-bot
2023f37ab7 fix: Dashboard/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
2024-05-09 21:25:59 +00:00
snyk-bot
65f024c3f6 fix: Tests/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
2024-05-09 21:10:47 +00:00
snyk-bot
06936f0065 fix: Haraka/Dockerfile.tpl to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
- https://snyk.io/vuln/SNYK-ALPINE318-OPENSSL-6593964
2024-05-09 20:35:05 +00:00
Simon Larsen
41a2e2cdbe refactor: Update Dropdown and EntityFilter to handle multi-select values 2024-05-09 20:24:41 +01:00
Simon Larsen
96cfe4c1fd refactor: Update DropdownFilter and EntityFilter to use DropdownOption type for dropdown values 2024-05-09 20:16:19 +01:00
snyk-bot
0096860584 fix: upgrade posthog-js from 1.126.0 to 1.128.1
Snyk has created this PR to upgrade posthog-js from 1.126.0 to 1.128.1.

See this package in npm:
https://www.npmjs.com/package/posthog-js

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/f6446ec8-d441-487e-b58f-38373430e213?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-09 17:37:39 +00:00
Simon Larsen
da90c9b733 refactor: Update FilterViewer to use showFilterModal instead of showFilter prop 2024-05-09 17:09:25 +01:00
Simon Larsen
5cef1bacb7 refactor: Update FilterViewer to use showFilterModal instead of showFilter prop 2024-05-09 14:47:50 +01:00
Simon Larsen
9560883954 refactor: Update FilterData type to use Query object for improved database querying 2024-05-09 13:47:47 +01:00
Simon Larsen
f84a8d6d7a refactor: Include createdAt in SELECT query in StatementGenerator.test.ts 2024-05-09 12:50:46 +01:00
snyk-bot
97e1688b50 fix: upgrade @opentelemetry/sdk-trace-web from 1.22.0 to 1.23.0
Snyk has created this PR to upgrade @opentelemetry/sdk-trace-web from 1.22.0 to 1.23.0.

See this package in npm:
https://www.npmjs.com/package/@opentelemetry/sdk-trace-web

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-07 21:06:45 +00:00
snyk-bot
f0acbc6eb0 fix: upgrade @opentelemetry/instrumentation from 0.49.1 to 0.50.0
Snyk has created this PR to upgrade @opentelemetry/instrumentation from 0.49.1 to 0.50.0.

See this package in npm:
https://www.npmjs.com/package/@opentelemetry/instrumentation

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-07 21:06:37 +00:00
snyk-bot
07f99b8796 fix: upgrade @opentelemetry/semantic-conventions from 1.22.0 to 1.23.0
Snyk has created this PR to upgrade @opentelemetry/semantic-conventions from 1.22.0 to 1.23.0.

See this package in npm:
https://www.npmjs.com/package/@opentelemetry/semantic-conventions

See this project in Snyk:
https://app.snyk.io/org/oneuptime-RsC2nshvQ2Vnr35jHvMnMP/project/47001ef1-7b3a-49c2-88cd-8025c56346d0?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-05-05 22:21:21 +00:00
1882 changed files with 258195 additions and 226255 deletions

View File

@@ -1,28 +0,0 @@
*/node_modules/*
*/build/*
*/coverage/*
*/dist/*
*/public/*
*/views/*
*fonts*
*logos*
.*
*.png
*.sh
*.txt
*.snap
*.enc
Dockerfile
CHANGELOG
LICENSE
marketing/*/*
licenses/*
certifications/*
ApiReference/public/assets/*
JavaScriptSDK/src/cli/server-monitor/out/scripts/prettify/*
_test/*

View File

@@ -1,216 +0,0 @@
{
"parserOptions": {
"ecmaVersion": 8,
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true,
"tsx": true,
"spread": true
},
"sourceType": "module",
"project": [
"./tsconfig.json"
]
},
"env": {
"browser": true,
"node": true,
"jquery": true,
"es6": true,
"jest": true,
"jasmine": true
},
"plugins": [
"react",
"jsx-a11y",
"progress",
"@typescript-eslint",
"unused-imports"
],
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:prettier/recommended",
"prettier"
],
"globals": {
"describe": true,
"context": true,
"before": true,
"beforeEach": true,
"after": true,
"afterEach": true,
"it": true,
"expect": true,
"workbox": true,
"importScripts": true,
"$TSFixMe": true,
"NodeJS": true,
"JSX": true
},
"parser": "@typescript-eslint/parser",
"rules": {
"no-fallthrough": "error",
"no-unreachable": "error",
"no-cond-assign": "error",
"valid-typeof": "error",
"no-func-assign": "error",
"curly": "error",
"no-extra-semi": "error",
"no-else-return": "error",
"no-div-regex": "error",
"no-octal": "error",
"no-extra-bind": "error",
"unicode-bom": "error",
"no-extra-boolean-cast": "error",
"wrap-regex": "error",
"wrap-iife": "error",
"yield-star-spacing": "error",
"no-implicit-coercion": "error",
"no-extra-label": "error",
"multiline-comment-style": "off",
"no-lonely-if": "error",
"no-floating-decimal": "error",
"eqeqeq": "error",
"dot-notation": "off", // Off because it messes up with typescript compiler.
"@typescript-eslint/dot-notation": "off", //temp off.
"progress/activate": 1,
"linebreak-style": [
"error",
"unix"
],
"@typescript-eslint/no-empty-interface": [
"error",
{
"allowSingleExtends": true
}
],
// https://www.npmjs.com/package/eslint-plugin-unused-imports
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"error",
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/explicit-member-accessibility": [
"error"
],
"no-console": "error",
"no-undef": "error",
"no-empty": "error",
"no-control-regex": "off",
"prefer-arrow-callback": "error",
"constructor-super": "error",
"no-case-declarations": "error",
"no-mixed-spaces-and-tabs": "error",
"no-useless-escape": "error",
"prettier/prettier": "error",
"react/jsx-no-undef": "error",
"react/jsx-no-bind": [
"error",
{
"allowArrowFunctions": true,
"allowBind": false,
"ignoreRefs": false
}
],
"react/no-children-prop": "error",
"react/no-deprecated": "error",
"react/boolean-prop-naming": "error",
"react/no-is-mounted": "error",
"react/no-find-dom-node": "error",
"one-var-declaration-per-line": "error",
"arrow-parens": "error",
"arrow-body-style": [
"error",
"always"
],
"@typescript-eslint/typedef": [
"error",
{
"arrowParameter": true,
"variableDeclaration": true
}
],
"@typescript-eslint/strict-boolean-expressions": "off", //Need to enable this very soon
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowExpressions": true
}
],
"react/no-did-update-set-state": "error",
"react/no-unknown-property": "error",
"react/no-unused-prop-types": "error",
"react/jsx-no-duplicate-props": "error",
"react/no-unused-state": "error",
"react/jsx-uses-vars": "error",
"react/prop-types": "error",
"react/react-in-jsx-scope": "error",
"react/no-string-refs": "error",
"jsx-a11y/href-no-hash": [
0
],
"react/no-unescaped-entities": "error",
"react/display-name": "error",
"react/jsx-pascal-case": "error",
"array-callback-return": "error",
"no-loop-func": "error",
"no-duplicate-imports": "error",
"no-promise-executor-return": "error",
"capitalized-comments": "off", // this is turned off because come commented code should not be capitalized.
"for-direction": "error",
"getter-return": "error",
"jsx-a11y/anchor-is-valid": "error",
"no-async-promise-executor": "error",
"prefer-const": [
"error",
{
"destructuring": "any",
"ignoreReadBeforeAssign": false
}
],
"no-var": "error",
"object-curly-spacing": [
"error",
"always"
],
"no-unneeded-ternary": "error",
"@typescript-eslint/ban-types": [
"error",
{
"types": {
"String": true,
"Boolean": true,
"Number": true,
"Symbol": false,
"{}": true,
"Object": true,
"object": true,
"Function": true
},
"extendDefaults": true
}
]
},
"settings": {
"react": {
"version": "18.1.0"
}
}
}

View File

@@ -72,6 +72,22 @@ jobs:
- name: build docker image
run: sudo docker build -f ./App/Dockerfile .
docker-build-copilot:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
run: sudo docker build -f ./Copilot/Dockerfile .
docker-build-e2e:
runs-on: ubuntu-latest
env:
@@ -179,21 +195,6 @@ jobs:
- name: build docker image
run: sudo docker build -f ./StatusPage/Dockerfile .
docker-build-infrastructure-agent:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for mail service
- name: build docker image
run: sudo docker build -f ./InfrastructureAgent/Dockerfile .
docker-build-test-server:
runs-on: ubuntu-latest
env:

View File

@@ -34,7 +34,7 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
language: [ 'javascript', 'typescript', 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support

View File

@@ -91,6 +91,20 @@ jobs:
- run: cd CommonUI && npm install --force
- run: cd App && npm install && npm run compile && npm run dep-check
compile-copilot:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd Copilot && npm install && npm run compile && npm run dep-check
compile-nginx:
runs-on: ubuntu-latest
env:
@@ -111,14 +125,10 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd InfrastructureAgent && npm install && npm run compile && npm run dep-check
- uses: actions/checkout@v4
# Setup Go
- uses: actions/setup-go@v5
- run: cd InfrastructureAgent && go build .
compile-admin-dashboard:

View File

@@ -19,7 +19,7 @@ jobs:
- run: echo "Build number is ${{ steps.buildnumber.outputs.build_number }}"
github-release:
needs: generate-build-number
needs: [generate-build-number]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/release'
permissions:
@@ -46,7 +46,7 @@ jobs:
helm-chart-deploy:
runs-on: ubuntu-latest
needs: generate-build-number
needs: [generate-build-number, github-release]
env:
CI_COMMIT_AUTHOR: Continuous Integration
steps:
@@ -92,7 +92,7 @@ jobs:
git push origin master
nginx-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -152,7 +152,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
e2e-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -212,7 +212,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
isolated-vm-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -272,7 +272,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
test-server-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -332,7 +332,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
otel-collector-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -394,7 +394,7 @@ jobs:
status-page-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -454,7 +454,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
test-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -514,7 +514,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
ingestor-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -574,7 +574,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
probe-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -635,7 +635,7 @@ jobs:
haraka-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -695,7 +695,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
admin-dashboard-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -756,7 +756,7 @@ jobs:
dashboard-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -816,7 +816,7 @@ jobs:
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
app-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -875,8 +875,69 @@ jobs:
GIT_SHA=${{ github.sha }}
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
copilot-docker-image-deploy:
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
oneuptime/copilot
ghcr.io/oneuptime/copilot
tags: |
type=raw,value=release,enable=true
type=semver,value=7.0.${{needs.generate-build-number.outputs.build_number}},pattern={{version}},enable=true
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Generate Dockerfile from Dockerfile.tpl
run: npm run prerun
# Build and deploy app.
- name: Login to Docker Hub
uses: docker/login-action@v2.2.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
file: ./Copilot/Dockerfile
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
GIT_SHA=${{ github.sha }}
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
accounts-docker-image-deploy:
needs: generate-build-number
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
@@ -935,39 +996,10 @@ jobs:
GIT_SHA=${{ github.sha }}
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
# We dont need any of this because we are using the npm package
# infrastructure-agent-macos-binary-release:
# runs-on: macos-latest
# steps:
# - uses: actions/checkout@v2
# - uses: actions/setup-node@v2
# with:
# node-version: 21.6.2
# - run: cd InfrastructureAgent && bash Scripts/Build/Mac.sh
# We dont need any of this because we are using the npm package
# infrastructure-agent-windows-binary-release:
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v2
# - uses: actions/setup-node@v2
# with:
# node-version: 21.6.2
# - run: cd InfrastructureAgent && ./Scripts/Build/Windows.ps1
# We dont need any of this because we are using the npm package
# infrastructure-agent-linux-binary-release:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - uses: actions/setup-node@v2
# with:
# node-version: 21.6.2
# - run: cd InfrastructureAgent && bash ./Scripts/Build/Linux.sh
publish-npm-packages:
runs-on: ubuntu-latest
needs: generate-build-number
needs: [generate-build-number, github-release]
env:
CI_PIPELINE_ID: ${{github.run_number}}
NPM_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}
@@ -980,64 +1012,140 @@ jobs:
- name: Publish Infrastructure Agent
run: bash ./Scripts/NPM/PublishAllPackages.sh
infrastructure-agent-docker-image-deploy:
needs: generate-build-number
infrastructure-agent-deploy:
needs: [generate-build-number, github-release]
runs-on: ubuntu-latest
steps:
- name: Docker Meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
oneuptime/infrastructure-agent
ghcr.io/oneuptime/infrastructure-agent
tags: |
type=raw,value=release,enable=true
type=semver,value=7.0.${{needs.generate-build-number.outputs.build_number}},pattern={{version}},enable=true
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- name: Set up Go
uses: actions/setup-go@v4
- name: Install GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
install-only: true
- name: Show GoReleaser version
run: goreleaser -v
- name: Run GoReleaser
run: cd InfrastructureAgent && export GORELEASER_CURRENT_TAG=7.0.${{needs.generate-build-number.outputs.build_number}} && goreleaser release --clean --snapshot
# Upload binaries to github release
- name: Release
uses: softprops/action-gh-release@v2
with:
files: |
InfrastructureAgent/dist/*
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
prerelease: false
tag_name: 7.0.${{needs.generate-build-number.outputs.build_number}}
test-e2e-release-saas:
runs-on: ubuntu-latest
needs: [copilot-docker-image-deploy, accounts-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, dashboard-docker-image-deploy, haraka-docker-image-deploy, ingestor-docker-image-deploy, isolated-vm-docker-image-deploy, otel-collector-docker-image-deploy, probe-docker-image-deploy, status-page-docker-image-deploy, test-docker-image-deploy, test-server-docker-image-deploy, infrastructure-agent-deploy, publish-npm-packages, e2e-docker-image-deploy, helm-chart-deploy, github-release, generate-build-number, nginx-docker-image-deploy]
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Generate Dockerfile from Dockerfile.tpl
run: npm run prerun
# Build and deploy infrastructure-agent.
- name: Login to Docker Hub
uses: docker/login-action@v2.2.0
- run: npm run prerun && bash ./Tests/Scripts/enable-billing-env-var.sh
- name: Start Server with release tag
run: npm run start
- name: Wait for server to start
run: bash ./Tests/Scripts/status-check.sh http://localhost
- name: Run E2E Tests. Run docker container e2e in docker compose file
run: export $(grep -v '^#' config.env | xargs) && docker-compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker-compose -f docker-compose.dev.yml logs e2e && exit 1)
- name: Upload test results
uses: actions/upload-artifact@v4
# Run this on failure
if: failure()
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
# Name of the artifact to upload.
# Optional. Default is 'artifact'
name: test-results
# A file, directory or wildcard pattern that describes what to upload
# Required.
path: |
./E2E
# Duration after which artifact will expire in days. 0 means using default retention.
# Minimum 1 day.
# Maximum 90 days unless changed from the repository settings page.
# Optional. Defaults to repository settings.
retention-days: 7
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.2.0
test-e2e-release-self-hosted:
runs-on: ubuntu-latest
# After all the jobs runs
needs: [copilot-docker-image-deploy, accounts-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, dashboard-docker-image-deploy, haraka-docker-image-deploy, ingestor-docker-image-deploy, isolated-vm-docker-image-deploy, otel-collector-docker-image-deploy, probe-docker-image-deploy, status-page-docker-image-deploy, test-docker-image-deploy, test-server-docker-image-deploy, infrastructure-agent-deploy, publish-npm-packages, e2e-docker-image-deploy, helm-chart-deploy, github-release, generate-build-number, nginx-docker-image-deploy]
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
file: ./InfrastructureAgent/Dockerfile
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
GIT_SHA=${{ github.sha }}
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
node-version: 18.3.0
- run: npm run prerun
- name: Start Server with release tag
run: npm run start
- name: Wait for server to start
run: bash ./Tests/Scripts/status-check.sh http://localhost
- name: Run E2E Tests. Run docker container e2e in docker compose file
run: export $(grep -v '^#' config.env | xargs) && docker-compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker-compose -f docker-compose.dev.yml logs e2e && exit 1)
- name: Upload test results
uses: actions/upload-artifact@v4
# Run this on failure
if: failure()
with:
# Name of the artifact to upload.
# Optional. Default is 'artifact'
name: test-results
# A file, directory or wildcard pattern that describes what to upload
# Required.
path: |
./E2E
# Duration after which artifact will expire in days. 0 means using default retention.
# Minimum 1 day.
# Maximum 90 days unless changed from the repository settings page.
# Optional. Defaults to repository settings.
retention-days: 7

View File

@@ -876,8 +876,8 @@ jobs:
GIT_SHA=${{ github.sha }}
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
infrastructure-agent-docker-image-deploy:
copilot-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
steps:
@@ -886,8 +886,8 @@ jobs:
uses: docker/metadata-action@v4
with:
images: |
oneuptime/infrastructure
ghcr.io/oneuptime/infrastructure
oneuptime/copilot
ghcr.io/oneuptime/copilot
tags: |
type=raw,value=test,enable=true
type=semver,value=7.0.${{needs.generate-build-number.outputs.build_number}}-test,pattern={{version}},enable=true
@@ -910,7 +910,7 @@ jobs:
- name: Generate Dockerfile from Dockerfile.tpl
run: npm run prerun
# Build and deploy infrastructure.
# Build and deploy accounts.
- name: Login to Docker Hub
uses: docker/login-action@v2.2.0
@@ -928,7 +928,7 @@ jobs:
- name: Build and push
uses: docker/build-push-action@v4
with:
file: ./InfrastructureAgent/Dockerfile
file: ./Copilot/Dockerfile
context: .
platforms: linux/amd64,linux/arm64
push: true
@@ -938,11 +938,10 @@ jobs:
GIT_SHA=${{ github.sha }}
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
test-helm-chart:
runs-on: ubuntu-latest
needs: [ infrastructure-agent-docker-image-deploy, isolated-vm-docker-image-deploy, test-server-docker-image-deploy, test-docker-image-deploy, ingestor-docker-image-deploy, probe-docker-image-deploy, haraka-docker-image-deploy, dashboard-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, accounts-docker-image-deploy, otel-collector-docker-image-deploy, status-page-docker-image-deploy, nginx-docker-image-deploy, e2e-docker-image-deploy]
needs: [copilot-docker-image-deploy, isolated-vm-docker-image-deploy, test-server-docker-image-deploy, test-docker-image-deploy, ingestor-docker-image-deploy, probe-docker-image-deploy, haraka-docker-image-deploy, dashboard-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, accounts-docker-image-deploy, otel-collector-docker-image-deploy, status-page-docker-image-deploy, nginx-docker-image-deploy, e2e-docker-image-deploy]
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
@@ -951,3 +950,111 @@ jobs:
with:
node-version: 18.3.0
- run: cd HelmChart && cd Tests && bash index.sh
test-e2e-test-saas:
runs-on: ubuntu-latest
needs: [test-helm-chart]
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun && bash ./Tests/Scripts/change-release-to-test-tag.sh
- name: Start Server with release tag
run: npm run start
- name: Wait for server to start
run: bash ./Tests/Scripts/status-check.sh http://localhost
- name: Run E2E Tests. Run docker container e2e in docker compose file
run: export $(grep -v '^#' config.env | xargs) && docker-compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker-compose -f docker-compose.dev.yml logs e2e && exit 1)
- name: Upload test results
uses: actions/upload-artifact@v4
# Run this on failure
if: failure()
with:
# Name of the artifact to upload.
# Optional. Default is 'artifact'
name: test-results
# A file, directory or wildcard pattern that describes what to upload
# Required.
path: |
./E2E
# Duration after which artifact will expire in days. 0 means using default retention.
# Minimum 1 day.
# Maximum 90 days unless changed from the repository settings page.
# Optional. Defaults to repository settings.
retention-days: 7
test-e2e-test-self-hosted:
runs-on: ubuntu-latest
# After all the jobs runs
needs: [test-helm-chart]
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun && bash ./Tests/Scripts/change-release-to-test-tag.sh
- name: Start Server with release tag
run: npm run start
- name: Wait for server to start
run: bash ./Tests/Scripts/status-check.sh http://localhost
- name: Run E2E Tests. Run docker container e2e in docker compose file
run: export $(grep -v '^#' config.env | xargs) && docker-compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker-compose -f docker-compose.dev.yml logs e2e && exit 1)
- name: Upload test results
uses: actions/upload-artifact@v4
# Run this on failure
if: failure()
with:
# Name of the artifact to upload.
# Optional. Default is 'artifact'
name: test-results
# A file, directory or wildcard pattern that describes what to upload
# Required.
path: |
./E2E
# Duration after which artifact will expire in days. 0 means using default retention.
# Minimum 1 day.
# Maximum 90 days unless changed from the repository settings page.
# Optional. Defaults to repository settings.
retention-days: 7

View File

@@ -32,8 +32,10 @@ jobs:
node-version: 18.3.0
- run: npm run prerun && bash ./Tests/Scripts/enable-billing-env-var.sh
- run: npm run dev
- name: Sleep for 2 minutes to wait for server to start
run: sleep 120
- name: Wait for server to start
run: bash ./Tests/Scripts/status-check.sh http://localhost
run: bash ./Tests/Scripts/status-check.sh http://localhost
- name: Run E2E Tests. Run docker container e2e in docker compose file
run: export $(grep -v '^#' config.env | xargs) && docker-compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker-compose -f docker-compose.dev.yml logs e2e && exit 1)
- name: Upload test results
@@ -48,15 +50,11 @@ jobs:
# A file, directory or wildcard pattern that describes what to upload
# Required.
path: |
./E2E/playwright-report
./E2E/test-results
./E2E
# Duration after which artifact will expire in days. 0 means using default retention.
# Minimum 1 day.
# Maximum 90 days unless changed from the repository settings page.
# Optional. Defaults to repository settings.
retention-days: 7
retention-days: 7

2
.gitignore vendored
View File

@@ -111,3 +111,5 @@ InfrastructureAgent/daemon.pid
App/greenlock/.greenlockrc
App/greenlock/greenlock.d/config.json
App/greenlock/greenlock.d/config.json.bak
Examples/otel-dotnet/bin/Debug/net6.0/Grpc.Core.Api.dll.txt
InfrastructureAgent/oneuptime-infrastructure-agent

View File

@@ -50,4 +50,7 @@ marketing/*/*
licenses/*
certifications/*
ApiReference/public/assets/*
JavaScriptSDK/src/cli/server-monitor/out/scripts/prettify/*
JavaScriptSDK/src/cli/server-monitor/out/scripts/prettify/*
CommonServer/Tests/TestingUtils/__mocks__/Stripe.mock.ts

View File

@@ -1,8 +0,0 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": true,
"singleQuote": true,
"bracketSpacing": true,
"arrowParens": "avoid"
}

35
.vscode/launch.json vendored
View File

@@ -19,6 +19,28 @@
}
],
"configurations": [
{
"name": "Debug: Copilot Locally",
"request": "launch",
"localRoot": "${workspaceFolder}/Copilot",
"runtimeArgs": [
"run-script",
"start"
],
"runtimeExecutable": "npm",
"skipFiles": [
"<node_internals>/**"
],
"type": "node"
},
{
"name": "Debug Infrastructure Agent",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "./InfrastructureAgent",
"args": ["start"],
},
{
"name": "Node.js - Debug Current File",
"type": "node",
@@ -208,19 +230,6 @@
"debug:test"
],
},
{
"name": "Probe: Debug Tests",
"type": "node",
"restart": true,
"autoAttachChildProcesses": true,
"request": "launch",
"cwd": "${workspaceRoot}/Probe",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run-script",
"debug:test"
],
},
{
"name": "Accounts: Debug Local Files",
"type": "node",

View File

@@ -3,7 +3,7 @@
#
# Pull base image nodejs image.
FROM node:21.7.2-alpine3.18
FROM node:21.7.3-alpine3.18
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global

View File

@@ -1,37 +1,37 @@
import App from 'CommonServer/Utils/StartServer';
import { PromiseVoidFunction } from 'Common/Types/FunctionTypes';
import Express, { ExpressApplication } from 'CommonServer/Utils/Express';
import logger from 'CommonServer/Utils/Logger';
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import Express, { ExpressApplication } from "CommonServer/Utils/Express";
import logger from "CommonServer/Utils/Logger";
import App from "CommonServer/Utils/StartServer";
export const APP_NAME: string = 'accounts';
export const APP_NAME: string = "accounts";
const app: ExpressApplication = Express.getExpressApp();
const init: PromiseVoidFunction = async (): Promise<void> => {
try {
// init the app
await App.init({
appName: APP_NAME,
port: undefined,
isFrontendApp: true,
statusOptions: {
liveCheck: async () => {},
readyCheck: async () => {},
},
});
// add default routes
await App.addDefaultRoutes();
} catch (err) {
logger.error('App Init Failed:');
logger.error(err);
throw err;
}
try {
// init the app
await App.init({
appName: APP_NAME,
port: undefined,
isFrontendApp: true,
statusOptions: {
liveCheck: async () => {},
readyCheck: async () => {},
},
});
// add default routes
await App.addDefaultRoutes();
} catch (err) {
logger.error("App Init Failed:");
logger.error(err);
throw err;
}
};
init().catch((err: Error) => {
logger.error(err);
logger.info('Exiting node process');
process.exit(1);
logger.error(err);
logger.error("Exiting node process");
process.exit(1);
});
export default app;

8
Accounts/index.d.ts vendored
View File

@@ -1,4 +1,4 @@
declare module '*.png';
declare module '*.svg';
declare module '*.jpg';
declare module '*.gif';
declare module "*.png";
declare module "*.svg";
declare module "*.jpg";
declare module "*.gif";

View File

@@ -16,9 +16,9 @@
"express": "^4.19.2",
"file-loader": "^6.2.0",
"Model": "file:../Model",
"react": "^18.2.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.22.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"sass-loader": "^13.3.3",
"style-loader": "^3.3.4",
"ts-loader": "^9.5.1",
@@ -267,9 +267,10 @@
}
},
"node_modules/@remix-run/router": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
"integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==",
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
"integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
@@ -2064,9 +2065,9 @@
}
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -2075,23 +2076,24 @@
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.2.0"
"react": "^18.3.1"
}
},
"node_modules/react-router": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz",
"integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==",
"version": "6.23.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz",
"integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.15.3"
"@remix-run/router": "1.16.1"
},
"engines": {
"node": ">=14.0.0"
@@ -2101,12 +2103,13 @@
}
},
"node_modules/react-router-dom": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz",
"integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==",
"version": "6.23.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz",
"integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.15.3",
"react-router": "6.22.3"
"@remix-run/router": "1.16.1",
"react-router": "6.23.1"
},
"engines": {
"node": ">=14.0.0"
@@ -2189,9 +2192,9 @@
}
},
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dependencies": {
"loose-envify": "^1.1.0"
}

View File

@@ -34,9 +34,9 @@
"express": "^4.19.2",
"file-loader": "^6.2.0",
"Model": "file:../Model",
"react": "^18.2.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.22.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"sass-loader": "^13.3.3",
"style-loader": "^3.3.4",
"ts-loader": "^9.5.1",

View File

@@ -1,47 +1,44 @@
import React, { ReactElement } from 'react';
import ForgotPasswordPage from "./Pages/ForgotPassword";
import LoginPage from "./Pages/Login";
import NotFound from "./Pages/NotFound";
import RegisterPage from "./Pages/Register";
import ResetPasswordPage from "./Pages/ResetPassword";
import VerifyEmail from "./Pages/VerifyEmail";
import Navigation from "CommonUI/src/Utils/Navigation";
import React, { ReactElement } from "react";
import {
Routes,
Route,
useNavigate,
useLocation,
useParams,
} from 'react-router-dom';
import LoginPage from './Pages/Login';
import NotFound from './Pages/NotFound';
import ForgotPasswordPage from './Pages/ForgotPassword';
import RegisterPage from './Pages/Register';
import Navigation from 'CommonUI/src/Utils/Navigation';
import VerifyEmail from './Pages/VerifyEmail';
import ResetPasswordPage from './Pages/ResetPassword';
Route,
Routes,
useLocation,
useNavigate,
useParams,
} from "react-router-dom";
function App(): ReactElement {
Navigation.setNavigateHook(useNavigate());
Navigation.setLocation(useLocation());
Navigation.setParams(useParams());
Navigation.setNavigateHook(useNavigate());
Navigation.setLocation(useLocation());
Navigation.setParams(useParams());
return (
<div className="m-auto h-screen">
<Routes>
<Route path="/accounts" element={<LoginPage />} />
<Route path="/accounts/login" element={<LoginPage />} />
<Route
path="/accounts/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route
path="/accounts/reset-password/:token"
element={<ResetPasswordPage />}
/>
<Route path="/accounts/register" element={<RegisterPage />} />
<Route
path="/accounts/verify-email/:token"
element={<VerifyEmail />}
/>
{/* 👇️ only match this when no other routes match */}
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
return (
<div className="m-auto h-screen">
<Routes>
<Route path="/accounts" element={<LoginPage />} />
<Route path="/accounts/login" element={<LoginPage />} />
<Route
path="/accounts/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route
path="/accounts/reset-password/:token"
element={<ResetPasswordPage />}
/>
<Route path="/accounts/register" element={<RegisterPage />} />
<Route path="/accounts/verify-email/:token" element={<VerifyEmail />} />
{/* 👇️ only match this when no other routes match */}
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
}
export default App;

View File

@@ -1,20 +1,20 @@
import React from 'react';
import { Link } from 'react-router-dom';
import React from "react";
import { Link } from "react-router-dom";
const Footer: () => JSX.Element = () => {
return (
<div className="footer">
<p>
<Link to="/">&copy; OneUptime</Link>
</p>
<p>
<Link to="/">Contact</Link>
</p>
<p>
<Link to="/">Privacy &amp; terms</Link>
</p>
</div>
);
return (
<div className="footer">
<p>
<Link to="/">&copy; OneUptime</Link>
</p>
<p>
<Link to="/">Contact</Link>
</p>
<p>
<Link to="/">Privacy &amp; terms</Link>
</p>
</div>
);
};
export default Footer;

View File

@@ -1,20 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import Telemetry from 'CommonUI/src/Utils/Telemetry';
import App from "./App";
import Telemetry from "CommonUI/src/Utils/Telemetry";
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
Telemetry.init({
serviceName: 'Accounts',
serviceName: "Accounts",
});
const root: any = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
document.getElementById("root") as HTMLElement,
);
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
<BrowserRouter>
<App />
</BrowserRouter>,
);

View File

@@ -1,99 +1,99 @@
import React, { useState } from 'react';
import ModelForm, { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
import User from 'Model/Models/User';
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg';
import Link from 'CommonUI/src/Components/Link/Link';
import { FORGOT_PASSWORD_API_URL } from '../Utils/ApiPaths';
import URL from 'Common/Types/API/URL';
import { FORGOT_PASSWORD_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import User from "Model/Models/User";
import React, { useState } from "react";
const ForgotPassword: () => JSX.Element = () => {
const apiUrl: URL = FORGOT_PASSWORD_API_URL;
const apiUrl: URL = FORGOT_PASSWORD_API_URL;
const [isSuccess, setIsSuccess] = useState<boolean>(false);
const [isSuccess, setIsSuccess] = useState<boolean>(false);
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="Your Company"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Forgot your password
</h2>
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="Your Company"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Forgot your password
</h2>
{!isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
Please enter your email and the password reset link will
be sent to you.
</p>
)}
{!isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
Please enter your email and the password reset link will be sent to
you.
</p>
)}
{isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
We have emailed you the password reset link. Please do
not forget to check spam.
</p>
)}
</div>
{isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
We have emailed you the password reset link. Please do not forget to
check spam.
</p>
)}
</div>
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
{!isSuccess && (
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
name="Forgot Password"
id="login-form"
createOrUpdateApiUrl={apiUrl}
fields={[
{
field: {
email: true,
},
title: 'Email',
fieldType: FormFieldSchemaType.Email,
required: true,
},
]}
onSuccess={() => {
setIsSuccess(true);
}}
submitButtonText={'Send Password Reset Link'}
formType={FormType.Create}
maxPrimaryButtonWidth={true}
footer={
<div className="actions pointer text-center mt-4 hover:underline fw-semibold">
<p>
<Link
to={new Route('/accounts/login')}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm"
>
Return to Sign in.
</Link>
</p>
</div>
}
/>
</div>
)}
<div className="mt-5 text-center">
<p className="text-muted mb-0 text-gray-500">
Remember your password?{' '}
<Link
to={new Route('/accounts/login')}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Login.
</Link>
</p>
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
{!isSuccess && (
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
name="Forgot Password"
id="login-form"
createOrUpdateApiUrl={apiUrl}
fields={[
{
field: {
email: true,
},
title: "Email",
fieldType: FormFieldSchemaType.Email,
required: true,
},
]}
onSuccess={() => {
setIsSuccess(true);
}}
submitButtonText={"Send Password Reset Link"}
formType={FormType.Create}
maxPrimaryButtonWidth={true}
footer={
<div className="actions pointer text-center mt-4 hover:underline fw-semibold">
<p>
<Link
to={new Route("/accounts/login")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm"
>
Return to Sign in.
</Link>
</p>
</div>
</div>
}
/>
</div>
)}
<div className="mt-5 text-center">
<p className="text-muted mb-0 text-gray-500">
Remember your password?{" "}
<Link
to={new Route("/accounts/login")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Login.
</Link>
</p>
</div>
);
</div>
</div>
);
};
export default ForgotPassword;

View File

@@ -1,167 +1,161 @@
import React, { useState } from 'react';
import User from 'Model/Models/User';
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg';
import Link from 'CommonUI/src/Components/Link/Link';
import ModelForm, { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
import { LOGIN_API_URL } from '../Utils/ApiPaths';
import URL from 'Common/Types/API/URL';
import { JSONObject } from 'Common/Types/JSON';
import LoginUtil from 'CommonUI/src/Utils/Login';
import UserUtil from 'CommonUI/src/Utils/User';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { DASHBOARD_URL } from 'CommonUI/src/Config';
import Alert, { AlertType } from 'CommonUI/src/Components/Alerts/Alert';
import UiAnalytics from 'CommonUI/src/Utils/Analytics';
import useAsyncEffect from 'use-async-effect';
import { LOGIN_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import { JSONObject } from "Common/Types/JSON";
import Alert, { AlertType } from "CommonUI/src/Components/Alerts/Alert";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import { DASHBOARD_URL } from "CommonUI/src/Config";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import UiAnalytics from "CommonUI/src/Utils/Analytics";
import LoginUtil from "CommonUI/src/Utils/Login";
import Navigation from "CommonUI/src/Utils/Navigation";
import UserUtil from "CommonUI/src/Utils/User";
import User from "Model/Models/User";
import React, { useState } from "react";
import useAsyncEffect from "use-async-effect";
const LoginPage: () => JSX.Element = () => {
const apiUrl: URL = LOGIN_API_URL;
const apiUrl: URL = LOGIN_API_URL;
if (UserUtil.isLoggedIn()) {
Navigation.navigate(DASHBOARD_URL);
if (UserUtil.isLoggedIn()) {
Navigation.navigate(DASHBOARD_URL);
}
const showSsoMessage: boolean = Boolean(
Navigation.getQueryStringByName("sso"),
);
const [showSsoTip, setShowSSOTip] = useState<boolean>(false);
const [initialValues, setInitialValues] = React.useState<JSONObject>({});
useAsyncEffect(async () => {
if (Navigation.getQueryStringByName("email")) {
setInitialValues({
email: Navigation.getQueryStringByName("email"),
});
}
}, []);
const showSsoMessage: boolean = Boolean(
Navigation.getQueryStringByName('sso')
);
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="OneUptime"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them stay online
all the time.
</p>
</div>
const [showSsoTip, setShowSSOTip] = useState<boolean>(false);
const [initialValues, setInitialValues] = React.useState<JSONObject>({});
useAsyncEffect(async () => {
if (Navigation.getQueryStringByName('email')) {
setInitialValues({
email: Navigation.getQueryStringByName('email'),
});
}
}, []);
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="OneUptime"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them
stay online all the time.
</p>
</div>
{showSsoMessage && (
<div className="sm:mx-auto sm:w-full sm:max-w-md mt-8">
{' '}
<Alert
type={AlertType.DANGER}
title="You must be logged into OneUptime account to use single sign-on (SSO) for your project. Logging in to OneUptime account and single sign on (SSO) for your project are two separate steps. Please use the form below to log in to your OneUptime account before you use SSO."
/>{' '}
</div>
)}
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
id="login-form"
name="Login"
fields={[
{
field: {
email: true,
},
fieldType: FormFieldSchemaType.Email,
placeholder: 'jeff@example.com',
required: true,
disabled: Boolean(
initialValues && initialValues['email']
),
title: 'Email',
dataTestId: 'email',
},
{
field: {
password: true,
},
title: 'Password',
required: true,
validation: {
minLength: 6,
},
fieldType: FormFieldSchemaType.Password,
sideLink: {
text: 'Forgot password?',
url: new Route('/accounts/forgot-password'),
openLinkInNewTab: false,
},
dataTestId: 'password',
},
]}
createOrUpdateApiUrl={apiUrl}
formType={FormType.Create}
submitButtonText={'Login'}
onSuccess={(
value: User,
miscData: JSONObject | undefined
) => {
if (value && value.email) {
UiAnalytics.userAuth(value.email);
UiAnalytics.capture('accounts/login');
}
LoginUtil.login({
user: value,
token: miscData ? miscData['token'] : undefined,
});
}}
maxPrimaryButtonWidth={true}
footer={
<div className="actions text-center mt-4 hover:underline fw-semibold">
<div>
{!showSsoTip && (
<div
onClick={() => {
setShowSSOTip(true);
}}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm"
>
Use single sign-on (SSO) instead
</div>
)}
{showSsoTip && (
<div className="text-gray-500 text-sm">
Please sign in with your SSO
provider like Okta, Auth0, Entra ID
or any other SAML 2.0 provider.
</div>
)}
</div>
</div>
}
/>
</div>
<div className="mt-10 text-center">
<div className="text-muted mb-0 text-gray-500">
Don&apos;t have an account?{' '}
<Link
to={new Route('/accounts/register')}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Register.
</Link>
</div>
</div>
</div>
{showSsoMessage && (
<div className="sm:mx-auto sm:w-full sm:max-w-md mt-8">
{" "}
<Alert
type={AlertType.DANGER}
title="You must be logged into OneUptime account to use single sign-on (SSO) for your project. Logging in to OneUptime account and single sign on (SSO) for your project are two separate steps. Please use the form below to log in to your OneUptime account before you use SSO."
/>{" "}
</div>
);
)}
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
id="login-form"
name="Login"
fields={[
{
field: {
email: true,
},
fieldType: FormFieldSchemaType.Email,
placeholder: "jeff@example.com",
required: true,
disabled: Boolean(initialValues && initialValues["email"]),
title: "Email",
dataTestId: "email",
},
{
field: {
password: true,
},
title: "Password",
required: true,
validation: {
minLength: 6,
},
fieldType: FormFieldSchemaType.Password,
sideLink: {
text: "Forgot password?",
url: new Route("/accounts/forgot-password"),
openLinkInNewTab: false,
},
dataTestId: "password",
},
]}
createOrUpdateApiUrl={apiUrl}
formType={FormType.Create}
submitButtonText={"Login"}
onSuccess={(value: User, miscData: JSONObject | undefined) => {
if (value && value.email) {
UiAnalytics.userAuth(value.email);
UiAnalytics.capture("accounts/login");
}
LoginUtil.login({
user: value,
token: miscData ? miscData["token"] : undefined,
});
}}
maxPrimaryButtonWidth={true}
footer={
<div className="actions text-center mt-4 hover:underline fw-semibold">
<div>
{!showSsoTip && (
<div
onClick={() => {
setShowSSOTip(true);
}}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm"
>
Use single sign-on (SSO) instead
</div>
)}
{showSsoTip && (
<div className="text-gray-500 text-sm">
Please sign in with your SSO provider like Okta, Auth0,
Entra ID or any other SAML 2.0 provider.
</div>
)}
</div>
</div>
}
/>
</div>
<div className="mt-10 text-center">
<div className="text-muted mb-0 text-gray-500">
Don&apos;t have an account?{" "}
<Link
to={new Route("/accounts/register")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Register.
</Link>
</div>
</div>
</div>
</div>
);
};
export default LoginPage;

View File

@@ -1,18 +1,18 @@
import React from 'react';
import React from "react";
const LoginPage: () => JSX.Element = () => {
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Page not found
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Page you are looking for does not exist.
</p>
</div>
</div>
);
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Page not found
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Page you are looking for does not exist.
</p>
</div>
</div>
);
};
export default LoginPage;

View File

@@ -1,276 +1,267 @@
import React, { useState } from 'react';
import ModelForm, { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
import User from 'Model/Models/User';
import Link from 'CommonUI/src/Components/Link/Link';
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg';
import LoginUtil from 'CommonUI/src/Utils/Login';
import { JSONObject } from 'Common/Types/JSON';
import UserUtil from 'CommonUI/src/Utils/User';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { BILLING_ENABLED, DASHBOARD_URL } from 'CommonUI/src/Config';
import URL from 'Common/Types/API/URL';
import { SIGNUP_API_URL } from '../Utils/ApiPaths';
import Fields from 'CommonUI/src/Components/Forms/Types/Fields';
import Dictionary from 'Common/Types/Dictionary';
import UiAnalytics from 'CommonUI/src/Utils/Analytics';
import LocalStorage from 'CommonUI/src/Utils/LocalStorage';
import Reseller from 'Model/Models/Reseller';
import ModelAPI, { ListResult } from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
import BaseAPI from 'CommonUI/src/Utils/API/API';
import ErrorMessage from 'CommonUI/src/Components/ErrorMessage/ErrorMessage';
import PageLoader from 'CommonUI/src/Components/Loader/PageLoader';
import useAsyncEffect from 'use-async-effect';
import { SIGNUP_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import Dictionary from "Common/Types/Dictionary";
import { JSONObject } from "Common/Types/JSON";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import Fields from "CommonUI/src/Components/Forms/Types/Fields";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import { BILLING_ENABLED, DASHBOARD_URL } from "CommonUI/src/Config";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import BaseAPI from "CommonUI/src/Utils/API/API";
import UiAnalytics from "CommonUI/src/Utils/Analytics";
import LocalStorage from "CommonUI/src/Utils/LocalStorage";
import LoginUtil from "CommonUI/src/Utils/Login";
import ModelAPI, { ListResult } from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import Navigation from "CommonUI/src/Utils/Navigation";
import UserUtil from "CommonUI/src/Utils/User";
import Reseller from "Model/Models/Reseller";
import User from "Model/Models/User";
import React, { useState } from "react";
import useAsyncEffect from "use-async-effect";
const RegisterPage: () => JSX.Element = () => {
const apiUrl: URL = SIGNUP_API_URL;
const apiUrl: URL = SIGNUP_API_URL;
const [initialValues, setInitialValues] = React.useState<JSONObject>({});
const [initialValues, setInitialValues] = React.useState<JSONObject>({});
const [error, setError] = useState<string>('');
const [error, setError] = useState<string>("");
const [isLoading, setIsLoading] = React.useState<boolean>(false);
const [isLoading, setIsLoading] = React.useState<boolean>(false);
const [reseller, setResller] = React.useState<Reseller | undefined>(
undefined
);
const [reseller, setResller] = React.useState<Reseller | undefined>(
undefined,
);
if (UserUtil.isLoggedIn()) {
Navigation.navigate(DASHBOARD_URL);
if (UserUtil.isLoggedIn()) {
Navigation.navigate(DASHBOARD_URL);
}
type FetchResellerFunction = (resellerId: string) => Promise<void>;
const fetchReseller: FetchResellerFunction = async (
resellerId: string,
): Promise<void> => {
setIsLoading(true);
try {
const reseller: ListResult<Reseller> = await ModelAPI.getList<Reseller>({
modelType: Reseller,
query: {
resellerId: resellerId,
},
limit: 1,
skip: 0,
select: {
hidePhoneNumberOnSignup: true,
},
sort: {},
requestOptions: {},
});
if (reseller.data.length > 0) {
setResller(reseller.data[0]);
}
} catch (err) {
setError(BaseAPI.getFriendlyMessage(err));
}
type FetchResellerFunction = (resellerId: string) => Promise<void>;
setIsLoading(false);
};
const fetchReseller: FetchResellerFunction = async (
resellerId: string
): Promise<void> => {
setIsLoading(true);
try {
const reseller: ListResult<Reseller> =
await ModelAPI.getList<Reseller>({
modelType: Reseller,
query: {
resellerId: resellerId,
},
limit: 1,
skip: 0,
select: {
hidePhoneNumberOnSignup: true,
},
sort: {},
requestOptions: {},
});
if (reseller.data.length > 0) {
setResller(reseller.data[0]);
}
} catch (err) {
setError(BaseAPI.getFriendlyMessage(err));
}
setIsLoading(false);
};
useAsyncEffect(async () => {
// if promo code is found, please save it in localstorage.
if (Navigation.getQueryStringByName('promoCode')) {
LocalStorage.setItem(
'promoCode',
Navigation.getQueryStringByName('promoCode')
);
}
if (Navigation.getQueryStringByName('email')) {
setInitialValues({
email: Navigation.getQueryStringByName('email'),
});
}
// if promo code is found, please save it in localstorage.
if (Navigation.getQueryStringByName('partnerId')) {
await fetchReseller(Navigation.getQueryStringByName('partnerId')!);
}
}, []);
let formFields: Fields<User> = [
{
field: {
email: true,
},
fieldType: FormFieldSchemaType.Email,
placeholder: 'jeff@example.com',
required: true,
disabled: Boolean(initialValues && initialValues['email']),
title: 'Email',
dataTestId: 'email',
},
{
field: {
name: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Jeff Smith',
required: true,
title: 'Full Name',
dataTestId: 'name',
},
];
if (BILLING_ENABLED) {
formFields = formFields.concat([
{
field: {
companyName: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Acme, Inc.',
required: true,
title: 'Company Name',
dataTestId: 'companyName',
},
]);
// If reseller wants to hide phone number on sign up, we hide it.
if (!reseller || !reseller.hidePhoneNumberOnSignup) {
formFields.push({
field: {
companyPhoneNumber: true,
},
fieldType: FormFieldSchemaType.Phone,
required: true,
placeholder: '+11234567890',
title: 'Phone Number',
dataTestId: 'companyPhoneNumber',
});
}
useAsyncEffect(async () => {
// if promo code is found, please save it in localstorage.
if (Navigation.getQueryStringByName("promoCode")) {
LocalStorage.setItem(
"promoCode",
Navigation.getQueryStringByName("promoCode"),
);
}
if (Navigation.getQueryStringByName("email")) {
setInitialValues({
email: Navigation.getQueryStringByName("email"),
});
}
// if promo code is found, please save it in localstorage.
if (Navigation.getQueryStringByName("partnerId")) {
await fetchReseller(Navigation.getQueryStringByName("partnerId")!);
}
}, []);
let formFields: Fields<User> = [
{
field: {
email: true,
},
fieldType: FormFieldSchemaType.Email,
placeholder: "jeff@example.com",
required: true,
disabled: Boolean(initialValues && initialValues["email"]),
title: "Email",
dataTestId: "email",
},
{
field: {
name: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: "Jeff Smith",
required: true,
title: "Full Name",
dataTestId: "name",
},
];
if (BILLING_ENABLED) {
formFields = formFields.concat([
{
field: {
password: true,
},
fieldType: FormFieldSchemaType.Password,
validation: {
minLength: 6,
},
placeholder: 'Password',
title: 'Password',
required: true,
dataTestId: 'password',
},
{
field: {
confirmPassword: true,
} as any,
validation: {
minLength: 6,
toMatchField: 'password',
},
fieldType: FormFieldSchemaType.Password,
placeholder: 'Confirm Password',
title: 'Confirm Password',
overrideFieldKey: 'confirmPassword',
required: true,
showEvenIfPermissionDoesNotExist: true,
dataTestId: 'confirmPassword',
{
field: {
companyName: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: "Acme, Inc.",
required: true,
title: "Company Name",
dataTestId: "companyName",
},
]);
if (error) {
return <ErrorMessage error={error} />;
// If reseller wants to hide phone number on sign up, we hide it.
if (!reseller || !reseller.hidePhoneNumberOnSignup) {
formFields.push({
field: {
companyPhoneNumber: true,
},
fieldType: FormFieldSchemaType.Phone,
required: true,
placeholder: "+11234567890",
title: "Phone Number",
dataTestId: "companyPhoneNumber",
});
}
}
if (isLoading) {
return <PageLoader isVisible={true} />;
}
formFields = formFields.concat([
{
field: {
password: true,
},
fieldType: FormFieldSchemaType.Password,
validation: {
minLength: 6,
},
placeholder: "Password",
title: "Password",
required: true,
dataTestId: "password",
},
{
field: {
confirmPassword: true,
} as any,
validation: {
minLength: 6,
toMatchField: "password",
},
fieldType: FormFieldSchemaType.Password,
placeholder: "Confirm Password",
title: "Confirm Password",
overrideFieldKey: "confirmPassword",
required: true,
showEvenIfPermissionDoesNotExist: true,
dataTestId: "confirmPassword",
},
]);
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="OneUptime"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Create your OneUptime account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them
stay online all the time.
</p>
<p className="mt-2 text-center text-sm text-gray-600">
No credit card required.
</p>
</div>
if (error) {
return <ErrorMessage error={error} />;
}
<div className="mt-8 lg:mx-auto lg:w-full lg:max-w-2xl">
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
id="register-form"
showAsColumns={reseller ? 1 : 2}
name="Register"
initialValues={initialValues}
maxPrimaryButtonWidth={true}
fields={formFields}
createOrUpdateApiUrl={apiUrl}
onBeforeCreate={(item: User): Promise<User> => {
const utmParams: Dictionary<string> =
UserUtil.getUtmParams();
if (isLoading) {
return <PageLoader isVisible={true} />;
}
if (
utmParams &&
Object.keys(utmParams).length > 0
) {
item.utmSource = utmParams['utmSource'] || '';
item.utmMedium = utmParams['utmMedium'] || '';
item.utmCampaign =
utmParams['utmCampaign'] || '';
item.utmTerm = utmParams['utmTerm'] || '';
item.utmContent = utmParams['utmContent'] || '';
item.utmUrl = utmParams['utmUrl'] || '';
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="OneUptime"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Create your OneUptime account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them stay online
all the time.
</p>
<p className="mt-2 text-center text-sm text-gray-600">
No credit card required.
</p>
</div>
UiAnalytics.capture('utm_event', utmParams);
}
<div className="mt-8 lg:mx-auto lg:w-full lg:max-w-2xl">
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
id="register-form"
showAsColumns={reseller ? 1 : 2}
name="Register"
initialValues={initialValues}
maxPrimaryButtonWidth={true}
fields={formFields}
createOrUpdateApiUrl={apiUrl}
onBeforeCreate={(item: User): Promise<User> => {
const utmParams: Dictionary<string> = UserUtil.getUtmParams();
return Promise.resolve(item);
}}
formType={FormType.Create}
submitButtonText={'Sign Up'}
onSuccess={(
value: User,
miscData: JSONObject | undefined
) => {
if (value && value.email) {
UiAnalytics.userAuth(value.email);
UiAnalytics.capture('accounts/register');
}
if (utmParams && Object.keys(utmParams).length > 0) {
item.utmSource = utmParams["utmSource"] || "";
item.utmMedium = utmParams["utmMedium"] || "";
item.utmCampaign = utmParams["utmCampaign"] || "";
item.utmTerm = utmParams["utmTerm"] || "";
item.utmContent = utmParams["utmContent"] || "";
item.utmUrl = utmParams["utmUrl"] || "";
LoginUtil.login({
user: value,
token: miscData ? miscData['token'] : undefined,
});
}}
/>
</div>
<div className="mt-5 text-center text-gray-500">
<p className="text-muted mb-0">
Already have an account?{' '}
<Link
to={new Route('/accounts/login')}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Log in.
</Link>
</p>
</div>
</div>
UiAnalytics.capture("utm_event", utmParams);
}
return Promise.resolve(item);
}}
formType={FormType.Create}
submitButtonText={"Sign Up"}
onSuccess={(value: User, miscData: JSONObject | undefined) => {
if (value && value.email) {
UiAnalytics.userAuth(value.email);
UiAnalytics.capture("accounts/register");
}
LoginUtil.login({
user: value,
token: miscData ? miscData["token"] : undefined,
});
}}
/>
</div>
);
<div className="mt-5 text-center text-gray-500">
<p className="text-muted mb-0">
Already have an account?{" "}
<Link
to={new Route("/accounts/login")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Log in.
</Link>
</p>
</div>
</div>
</div>
);
};
export default RegisterPage;

View File

@@ -1,114 +1,114 @@
import React, { useState } from 'react';
import ModelForm, { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
import User from 'Model/Models/User';
import Link from 'CommonUI/src/Components/Link/Link';
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg';
import URL from 'Common/Types/API/URL';
import { RESET_PASSWORD_API_URL } from '../Utils/ApiPaths';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { RESET_PASSWORD_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "Model/Models/User";
import React, { useState } from "react";
const RegisterPage: () => JSX.Element = () => {
const apiUrl: URL = RESET_PASSWORD_API_URL;
const [isSuccess, setIsSuccess] = useState<boolean>(false);
const apiUrl: URL = RESET_PASSWORD_API_URL;
const [isSuccess, setIsSuccess] = useState<boolean>(false);
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="Your Company"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Reset your password
</h2>
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<img
className="mx-auto h-12 w-auto"
src={OneUptimeLogo}
alt="Your Company"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Reset your password
</h2>
{!isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
Please enter your new password and we will have it
updated.{' '}
</p>
)}
{!isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
Please enter your new password and we will have it updated.{" "}
</p>
)}
{isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
Your password has been updated. Please log in.
</p>
)}
</div>
{isSuccess && (
<p className="mt-2 text-center text-sm text-gray-600">
Your password has been updated. Please log in.
</p>
)}
</div>
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
{!isSuccess && (
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
id="register-form"
name="Reset Password"
onBeforeCreate={(item: User): Promise<User> => {
item.resetPasswordToken =
Navigation.getLastParam()
?.toString()
.replace('/', '')
.toString() || '';
return Promise.resolve(item);
}}
showAsColumns={1}
maxPrimaryButtonWidth={true}
fields={[
{
field: {
password: true,
},
fieldType: FormFieldSchemaType.Password,
validation: {
minLength: 6,
},
placeholder: 'New Password',
title: 'New Password',
required: true,
},
{
field: {
password: true,
},
validation: {
minLength: 6,
toMatchField: 'password',
},
fieldType: FormFieldSchemaType.Password,
placeholder: 'Confirm Password',
title: 'Confirm Password',
overrideFieldKey: 'confirmPassword',
required: true,
},
]}
createOrUpdateApiUrl={apiUrl}
formType={FormType.Create}
submitButtonText={'Reset Password'}
onSuccess={() => {
setIsSuccess(true);
}}
/>
</div>
)}
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
{!isSuccess && (
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<ModelForm<User>
modelType={User}
id="register-form"
name="Reset Password"
onBeforeCreate={(item: User): Promise<User> => {
item.resetPasswordToken =
Navigation.getLastParam()
?.toString()
.replace("/", "")
.toString() || "";
return Promise.resolve(item);
}}
showAsColumns={1}
maxPrimaryButtonWidth={true}
fields={[
{
field: {
password: true,
},
fieldType: FormFieldSchemaType.Password,
validation: {
minLength: 6,
},
placeholder: "New Password",
title: "New Password",
required: true,
showEvenIfPermissionDoesNotExist: true,
},
{
field: {
confirmPassword: true,
} as any,
validation: {
minLength: 6,
toMatchField: "password",
},
fieldType: FormFieldSchemaType.Password,
placeholder: "Confirm Password",
title: "Confirm Password",
overrideFieldKey: "confirmPassword",
required: true,
showEvenIfPermissionDoesNotExist: true,
},
]}
createOrUpdateApiUrl={apiUrl}
formType={FormType.Create}
submitButtonText={"Reset Password"}
onSuccess={() => {
setIsSuccess(true);
}}
/>
</div>
)}
<div className="mt-5 text-center">
<p className="text-muted mb-0 text-gray-500">
Know your password?{' '}
<Link
to={new Route('/accounts/login')}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Log in.
</Link>
</p>
</div>
</div>
<div className="mt-5 text-center">
<p className="text-muted mb-0 text-gray-500">
Know your password?{" "}
<Link
to={new Route("/accounts/login")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Log in.
</Link>
</p>
</div>
);
</div>
</div>
);
};
export default RegisterPage;

View File

@@ -1,132 +1,121 @@
import React, { useEffect, useState } from 'react';
import Route from 'Common/Types/API/Route';
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg';
import Link from 'CommonUI/src/Components/Link/Link';
import PageLoader from 'CommonUI/src/Components/Loader/PageLoader';
import ModelAPI from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
import EmailVerificationToken from 'Model/Models/EmailVerificationToken';
import { VERIFY_EMAIL_API_URL } from '../Utils/ApiPaths';
import { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
import Navigation from 'CommonUI/src/Utils/Navigation';
import ObjectID from 'Common/Types/ObjectID';
import URL from 'Common/Types/API/URL';
import API from 'CommonUI/src/Utils/API/API';
import { PromiseVoidFunction } from 'Common/Types/FunctionTypes';
import { VERIFY_EMAIL_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import ObjectID from "Common/Types/ObjectID";
import { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import Link from "CommonUI/src/Components/Link/Link";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import API from "CommonUI/src/Utils/API/API";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import Navigation from "CommonUI/src/Utils/Navigation";
import EmailVerificationToken from "Model/Models/EmailVerificationToken";
import React, { useEffect, useState } from "react";
const VerifyEmail: () => JSX.Element = () => {
const apiUrl: URL = VERIFY_EMAIL_API_URL;
const [error, setError] = useState<string>('');
const [isLoading, setIsLoading] = useState<boolean>(true);
const apiUrl: URL = VERIFY_EMAIL_API_URL;
const [error, setError] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(true);
const init: PromiseVoidFunction = async (): Promise<void> => {
// Ping an API here.
setError('');
setIsLoading(true);
const init: PromiseVoidFunction = async (): Promise<void> => {
// Ping an API here.
setError("");
setIsLoading(true);
try {
// strip data.
const emailverificationToken: EmailVerificationToken =
new EmailVerificationToken();
emailverificationToken.token = new ObjectID(
Navigation.getLastParam()?.toString().replace('/', '') || ''
);
try {
// strip data.
const emailverificationToken: EmailVerificationToken =
new EmailVerificationToken();
emailverificationToken.token = new ObjectID(
Navigation.getLastParam()?.toString().replace("/", "") || "",
);
await ModelAPI.createOrUpdate<EmailVerificationToken>({
model: emailverificationToken,
modelType: EmailVerificationToken,
formType: FormType.Create,
miscDataProps: {},
requestOptions: {
overrideRequestUrl: apiUrl,
},
});
} catch (err) {
setError(API.getFriendlyMessage(err));
}
setIsLoading(false);
};
useEffect(() => {
init().catch((err: Error) => {
setError(err.toString());
});
}, []);
if (isLoading) {
return <PageLoader isVisible={true} />;
await ModelAPI.createOrUpdate<EmailVerificationToken>({
model: emailverificationToken,
modelType: EmailVerificationToken,
formType: FormType.Create,
miscDataProps: {},
requestOptions: {
overrideRequestUrl: apiUrl,
},
});
} catch (err) {
setError(API.getFriendlyMessage(err));
}
return (
<div className="auth-page">
<div className="container-fluid p-0">
<div className="row g-0">
<div className="col-xxl-4 col-lg-4 col-md-3"></div>
setIsLoading(false);
};
<div className="col-xxl-4 col-lg-4 col-md-6">
<div className="auth-full-page-content d-flex p-sm-5 p-4">
<div className="w-100">
<div className="d-flex flex-column h-100">
<div className="auth-content my-auto">
<div
className="mt-4 text-center flex justify-center"
style={{ marginBottom: '40px' }}
>
<img
style={{ height: '50px' }}
src={`${OneUptimeLogo}`}
/>
</div>
{!error && (
<div className="text-center">
<h5 className="mb-0">
Your email is verified.
</h5>
<p className="text-muted mt-2 mb-0">
Thank you for verifying your
email. You can now log in to
OneUptime.{' '}
</p>
</div>
)}
useEffect(() => {
init().catch((err: Error) => {
setError(err.toString());
});
}, []);
{error && (
<div className="text-center">
<h5 className="mb-0">
Sorry, something went wrong!
</h5>
<p className="text-muted mt-2 mb-0">
{error}
</p>
</div>
)}
if (isLoading) {
return <PageLoader isVisible={true} />;
}
<div className="mt-5 text-center">
<p className="text-muted mb-0">
Return to sign in?{' '}
<Link
to={
new Route(
'/accounts/login'
)
}
className="hover:underline text-primary fw-semibold"
>
Login.
</Link>
</p>
</div>
</div>
</div>
</div>
</div>
return (
<div className="auth-page">
<div className="container-fluid p-0">
<div className="row g-0">
<div className="col-xxl-4 col-lg-4 col-md-3"></div>
<div className="col-xxl-4 col-lg-4 col-md-6">
<div className="auth-full-page-content d-flex p-sm-5 p-4">
<div className="w-100">
<div className="d-flex flex-column h-100">
<div className="auth-content my-auto">
<div
className="mt-4 text-center flex justify-center"
style={{ marginBottom: "40px" }}
>
<img
style={{ height: "50px" }}
src={`${OneUptimeLogo}`}
/>
</div>
{!error && (
<div className="text-center">
<h5 className="mb-0">Your email is verified.</h5>
<p className="text-muted mt-2 mb-0">
Thank you for verifying your email. You can now log in
to OneUptime.{" "}
</p>
</div>
)}
<div className="col-xxl-4 col-lg-4 col-md-3"></div>
{error && (
<div className="text-center">
<h5 className="mb-0">Sorry, something went wrong!</h5>
<p className="text-muted mt-2 mb-0">{error}</p>
</div>
)}
<div className="mt-5 text-center">
<p className="text-muted mb-0">
Return to sign in?{" "}
<Link
to={new Route("/accounts/login")}
className="hover:underline text-primary fw-semibold"
>
Login.
</Link>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="col-xxl-4 col-lg-4 col-md-3"></div>
</div>
);
</div>
</div>
);
};
export default VerifyEmail;

View File

@@ -1,22 +1,22 @@
import Route from 'Common/Types/API/Route';
import URL from 'Common/Types/API/URL';
import { IDENTITY_URL } from 'CommonUI/src/Config';
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import { IDENTITY_URL } from "CommonUI/src/Config";
export const SIGNUP_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route('/signup')
new Route("/signup"),
);
export const LOGIN_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route('/login')
new Route("/login"),
);
export const FORGOT_PASSWORD_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route('/forgot-password')
new Route("/forgot-password"),
);
export const VERIFY_EMAIL_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route('/verify-email')
new Route("/verify-email"),
);
export const RESET_PASSWORD_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route('/reset-password')
new Route("/reset-password"),
);

View File

@@ -1,83 +1,84 @@
require('ts-loader');
require('file-loader');
require('style-loader');
require('css-loader');
require('sass-loader');
require("ts-loader");
require("file-loader");
require("style-loader");
require("css-loader");
require("sass-loader");
const path = require("path");
const webpack = require("webpack");
const dotenv = require('dotenv');
const express = require('express');
const dotenv = require("dotenv");
const express = require("express");
const readEnvFile = (pathToFile) => {
const parsed = dotenv.config({ path: pathToFile }).parsed;
const parsed = dotenv.config({ path: pathToFile }).parsed;
const env = {};
const env = {
};
for (const key in parsed) {
env[key] = JSON.stringify(parsed[key]);
}
for (const key in parsed) {
env[key] = JSON.stringify(parsed[key]);
}
return env;
}
return env;
};
module.exports = {
entry: "./src/Index.tsx",
mode: "development",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "public", "dist"),
publicPath: "/accounts/dist/",
entry: "./src/Index.tsx",
mode: "development",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "public", "dist"),
publicPath: "/accounts/dist/",
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx", ".json", ".css", ".scss"],
alias: {
react: path.resolve("./node_modules/react"),
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.css', '.scss'],
alias: {
react: path.resolve('./node_modules/react'),
}
},
externals: {
'react-native-sqlite-storage': 'react-native-sqlite-storage'
},
plugins: [
new webpack.DefinePlugin({
'process': {
'env': {
...readEnvFile('/usr/src/app/dev-env/.env')
}
}
}),
],
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: 'ts-loader'
},
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', "sass-loader"]
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: 'file-loader'
}
],
},
devServer: {
historyApiFallback: true,
devMiddleware: {
writeToDisk: true,
},
externals: {
"react-native-sqlite-storage": "react-native-sqlite-storage",
},
plugins: [
new webpack.DefinePlugin({
process: {
env: {
...readEnvFile("/usr/src/app/dev-env/.env"),
},
allowedHosts: "all",
setupMiddlewares: (middlewares, devServer) => {
devServer.app.use('/accounts/assets', express.static(path.resolve(__dirname, 'public', 'assets')));
return middlewares;
}
},
}),
],
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: "ts-loader",
},
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: "file-loader",
},
],
},
devServer: {
historyApiFallback: true,
devMiddleware: {
writeToDisk: true,
},
devtool: 'eval-source-map',
}
allowedHosts: "all",
setupMiddlewares: (middlewares, devServer) => {
devServer.app.use(
"/accounts/assets",
express.static(path.resolve(__dirname, "public", "assets")),
);
return middlewares;
},
},
devtool: "eval-source-map",
};

View File

@@ -3,7 +3,7 @@
#
# Pull base image nodejs image.
FROM node:21.7.2-alpine3.18
FROM node:21.7.3-alpine3.18
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global

View File

@@ -1,38 +1,38 @@
import App from 'CommonServer/Utils/StartServer';
import Express, { ExpressApplication } from 'CommonServer/Utils/Express';
import logger from 'CommonServer/Utils/Logger';
import { PromiseVoidFunction } from 'Common/Types/FunctionTypes';
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import Express, { ExpressApplication } from "CommonServer/Utils/Express";
import logger from "CommonServer/Utils/Logger";
import App from "CommonServer/Utils/StartServer";
export const APP_NAME: string = 'admin';
export const APP_NAME: string = "admin";
const app: ExpressApplication = Express.getExpressApp();
const init: PromiseVoidFunction = async (): Promise<void> => {
try {
// init the app
await App.init({
appName: APP_NAME,
port: undefined,
isFrontendApp: true,
statusOptions: {
liveCheck: async () => {},
readyCheck: async () => {},
},
});
try {
// init the app
await App.init({
appName: APP_NAME,
port: undefined,
isFrontendApp: true,
statusOptions: {
liveCheck: async () => {},
readyCheck: async () => {},
},
});
// add default routes
await App.addDefaultRoutes();
} catch (err) {
logger.error('App Init Failed:');
logger.error(err);
throw err;
}
// add default routes
await App.addDefaultRoutes();
} catch (err) {
logger.error("App Init Failed:");
logger.error(err);
throw err;
}
};
init().catch((err: Error) => {
logger.error(err);
logger.info('Exiting node process');
process.exit(1);
logger.error(err);
logger.error("Exiting node process");
process.exit(1);
});
export default app;

View File

@@ -1,4 +1,4 @@
declare module '*.png';
declare module '*.svg';
declare module '*.jpg';
declare module '*.gif';
declare module "*.png";
declare module "*.svg";
declare module "*.jpg";
declare module "*.gif";

View File

@@ -14,9 +14,9 @@
"dotenv": "^16.4.5",
"file-loader": "^6.2.0",
"Model": "file:../Model",
"react": "^18.2.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.22.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"style-loader": "^3.3.4"
},
"devDependencies": {
@@ -35,21 +35,21 @@
}
},
"../Common": {
"name": "common",
"name": "@oneuptime/common",
"version": "1.0.0",
"license": "MIT",
"license": "Apache-2.0",
"dependencies": {
"@types/crypto-js": "^4.1.1",
"@types/crypto-js": "^4.2.2",
"@types/uuid": "^8.3.4",
"axios": "^1.6.2",
"axios": "^1.6.8",
"crypto-js": "^4.1.1",
"json5": "^2.2.3",
"moment": "^2.29.2",
"moment-timezone": "^0.5.40",
"posthog-js": "^1.77.0",
"reflect-metadata": "^0.1.13",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
"posthog-js": "^1.130.1",
"reflect-metadata": "^0.2.2",
"slugify": "^1.6.5",
"typeorm": "^0.3.6",
"typeorm": "^0.3.20",
"uuid": "^8.3.2"
},
"devDependencies": {
@@ -61,40 +61,47 @@
}
},
"../CommonServer": {
"name": "common-server",
"name": "@oneuptime/common-server",
"version": "1.0.0",
"license": "MIT",
"license": "Apache-2.0",
"dependencies": {
"@clickhouse/client": "^0.2.1",
"@elastic/elasticsearch": "^8.1.0",
"@clickhouse/client": "^0.2.10",
"@elastic/elasticsearch": "^8.12.1",
"@opentelemetry/api": "^1.7.0",
"@opentelemetry/auto-instrumentations-node": "^0.40.1",
"@opentelemetry/sdk-node": "^0.45.1",
"@socket.io/redis-adapter": "^8.2.1",
"@opentelemetry/api-logs": "^0.49.1",
"@opentelemetry/auto-instrumentations-node": "^0.43.0",
"@opentelemetry/exporter-logs-otlp-http": "^0.49.1",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.49.1",
"@opentelemetry/exporter-trace-otlp-proto": "^0.49.1",
"@opentelemetry/id-generator-aws-xray": "^1.2.1",
"@opentelemetry/sdk-logs": "^0.49.1",
"@opentelemetry/sdk-metrics": "^1.21.0",
"@opentelemetry/sdk-node": "^0.48.0",
"@opentelemetry/sdk-trace-node": "^1.21.0",
"acme-client": "^5.3.0",
"airtable": "^0.12.2",
"axios": "^1.6.2",
"bullmq": "^3.6.6",
"bullmq": "^5.3.3",
"Common": "file:../Common",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"cron-parser": "^4.8.1",
"dotenv": "^16.0.0",
"ejs": "^3.1.8",
"express": "^4.17.3",
"dotenv": "^16.4.4",
"ejs": "^3.1.10",
"express": "^4.19.2",
"ioredis": "^5.3.2",
"json2csv": "^5.0.7",
"jsonwebtoken": "^9.0.0",
"markdown-it": "^13.0.1",
"marked": "^12.0.2",
"Model": "file:../Model",
"nodemailer": "^6.7.3",
"node-cron": "^3.0.3",
"nodemailer": "^6.9.10",
"pg": "^8.7.3",
"socket.io": "^4.7.2",
"redis-semaphore": "^5.5.1",
"socket.io": "^4.7.4",
"stripe": "^10.17.0",
"twilio": "^4.19.3",
"typeorm": "^0.3.10",
"typeorm-extension": "^2.2.13",
"vm2": "^3.9.14",
"winston": "^3.6.0"
"twilio": "^4.22.0",
"typeorm": "^0.3.20",
"typeorm-extension": "^2.2.13"
},
"devDependencies": {
"@faker-js/faker": "^6.3.1",
@@ -105,8 +112,8 @@
"@types/jest": "^27.4.1",
"@types/json2csv": "^5.0.3",
"@types/jsonwebtoken": "^8.5.9",
"@types/markdown-it": "^12.2.3",
"@types/node": "^17.0.22",
"@types/node-cron": "^3.0.7",
"@types/nodemailer": "^6.4.7",
"jest": "^27.5.1",
"jest-mock-extended": "^3.0.5",
@@ -114,34 +121,48 @@
}
},
"../CommonUI": {
"name": "common-ui",
"name": "@oneuptime/common-ui",
"version": "1.0.0",
"license": "MIT",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.24.1",
"@monaco-editor/react": "^4.4.6",
"@nivo/core": "^0.86.0",
"@nivo/line": "^0.86.0",
"@opentelemetry/api": "^1.8.0",
"@opentelemetry/context-zone": "^1.23.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.51.0",
"@opentelemetry/instrumentation": "^0.51.0",
"@opentelemetry/instrumentation-fetch": "^0.51.0",
"@opentelemetry/instrumentation-xml-http-request": "^0.51.0",
"@opentelemetry/resources": "^1.23.0",
"@opentelemetry/sdk-trace-web": "^1.23.0",
"@opentelemetry/semantic-conventions": "^1.23.0",
"@tippyjs/react": "^4.2.6",
"@types/react-highlight": "^0.12.8",
"Common": "file:../Common",
"formik": "^2.2.9",
"formik": "^2.4.6",
"history": "^5.3.0",
"lodash": "^4.17.21",
"Model": "file:../Model",
"moment-timezone": "^0.5.43",
"moment-timezone": "^0.5.45",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react": "^18.3.1",
"react-beautiful-dnd": "^13.1.1",
"react-big-calendar": "^1.8.5",
"react-big-calendar": "^1.11.2",
"react-color": "^2.19.3",
"react-dom": "^18.1.0",
"react-dom": "^18.3.1",
"react-dropzone": "^14.2.2",
"react-error-boundary": "^4.0.11",
"react-error-boundary": "^4.0.13",
"react-highlight": "^0.15.0",
"react-markdown": "^8.0.3",
"react-router-dom": "^6.3.0",
"react-router-dom": "^6.22.3",
"react-select": "^5.4.0",
"react-spinners": "^0.13.6",
"react-toggle": "^4.1.3",
"reactflow": "^11.5.3",
"reactflow": "^11.11.1",
"remark-gfm": "^3.0.1",
"socket.io-client": "^4.7.2",
"socket.io-client": "^4.7.5",
"tippy.js": "^6.3.7",
"universal-cookie": "^4.0.4",
"use-async-effect": "^2.2.6"
@@ -167,12 +188,12 @@
}
},
"../Model": {
"name": "model",
"name": "@oneuptime/model",
"version": "1.0.0",
"license": "ISC",
"license": "Apache-2.0",
"dependencies": {
"Common": "file:../Common",
"typeorm": "^0.3.17"
"typeorm": "^0.3.20"
},
"devDependencies": {
"@types/jest": "^27.4.1",
@@ -4009,9 +4030,10 @@
}
},
"node_modules/@remix-run/router": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.2.tgz",
"integrity": "sha512-+Rnav+CaoTE5QJc4Jcwh5toUpnVLKYbpU6Ys0zqbakqbaLQHeglLVHPfxOiQqdNmUy5C2lXz5dwC6tQNX2JW2Q==",
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
"integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
@@ -16705,9 +16727,9 @@
}
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -16900,15 +16922,15 @@
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.2.0"
"react": "^18.3.1"
}
},
"node_modules/react-error-overlay": {
@@ -16936,11 +16958,12 @@
}
},
"node_modules/react-router": {
"version": "6.22.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.2.tgz",
"integrity": "sha512-YD3Dzprzpcq+tBMHBS822tCjnWD3iIZbTeSXMY9LPSG541EfoBGyZ3bS25KEnaZjLcmQpw2AVLkFyfgXY8uvcw==",
"version": "6.23.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz",
"integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.15.2"
"@remix-run/router": "1.16.1"
},
"engines": {
"node": ">=14.0.0"
@@ -16950,12 +16973,13 @@
}
},
"node_modules/react-router-dom": {
"version": "6.22.2",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.2.tgz",
"integrity": "sha512-WgqxD2qySEIBPZ3w0sHH+PUAiamDeszls9tzqMPBDA1YYVucTBXLU7+gtRfcSnhe92A3glPnvSxK2dhNoAVOIQ==",
"version": "6.23.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz",
"integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.15.2",
"react-router": "6.22.2"
"@remix-run/router": "1.16.1",
"react-router": "6.23.1"
},
"engines": {
"node": ">=14.0.0"
@@ -17681,9 +17705,9 @@
}
},
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dependencies": {
"loose-envify": "^1.1.0"
}

View File

@@ -9,9 +9,9 @@
"dotenv": "^16.4.5",
"file-loader": "^6.2.0",
"Model": "file:../Model",
"react": "^18.2.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.22.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"style-loader": "^3.3.4"
},
"scripts": {

View File

@@ -1,113 +1,103 @@
import React from 'react';
import {
Routes,
Route as PageRoute,
useNavigate,
useLocation,
useParams,
} from 'react-router-dom';
import Navigation from 'CommonUI/src/Utils/Navigation';
import User from 'CommonUI/src/Utils/User';
import URL from 'Common/Types/API/URL';
import { ACCOUNTS_URL, DASHBOARD_URL } from 'CommonUI/src/Config';
import MasterPage from './Components/MasterPage/MasterPage';
import RouteMap from './Utils/RouteMap';
import PageMap from './Utils/PageMap';
import Init from './Pages/Init/Init';
import Projects from './Pages/Projects/Index';
import Users from './Pages/Users/Index';
import Logout from './Pages/Logout/Logout';
import MasterPage from "./Components/MasterPage/MasterPage";
import Init from "./Pages/Init/Init";
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 SettingsCallSMS from "./Pages/Settings/CallSMS/Index";
// Settings Pages.
import SettingsEmail from './Pages/Settings/Email/Index';
import SettingsCallSMS from './Pages/Settings/CallSMS/Index';
import SettingsProbes from './Pages/Settings/Probes/Index';
import SettingsAuthentication from './Pages/Settings/Authentication/Index';
import SettingsAPIKey from './Pages/Settings/APIKey/Index';
import SettingsEmail from "./Pages/Settings/Email/Index";
import SettingsProbes from "./Pages/Settings/Probes/Index";
import Users from "./Pages/Users/Index";
import PageMap from "./Utils/PageMap";
import RouteMap from "./Utils/RouteMap";
import URL from "Common/Types/API/URL";
import { ACCOUNTS_URL, DASHBOARD_URL } from "CommonUI/src/Config";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "CommonUI/src/Utils/User";
import React from "react";
import {
Route as PageRoute,
Routes,
useLocation,
useNavigate,
useParams,
} from "react-router-dom";
const App: () => JSX.Element = () => {
Navigation.setNavigateHook(useNavigate());
Navigation.setLocation(useLocation());
Navigation.setParams(useParams());
Navigation.setNavigateHook(useNavigate());
Navigation.setLocation(useLocation());
Navigation.setParams(useParams());
if (!User.isLoggedIn()) {
if (Navigation.getQueryStringByName('sso_token')) {
Navigation.navigate(
URL.fromString(ACCOUNTS_URL.toString()).addQueryParam(
'sso',
'true'
)
);
} else {
Navigation.navigate(URL.fromString(ACCOUNTS_URL.toString()));
}
if (!User.isLoggedIn()) {
if (Navigation.getQueryStringByName("sso_token")) {
Navigation.navigate(
URL.fromString(ACCOUNTS_URL.toString()).addQueryParam("sso", "true"),
);
} else {
Navigation.navigate(URL.fromString(ACCOUNTS_URL.toString()));
}
}
if (!User.isMasterAdmin()) {
Navigation.navigate(URL.fromString(DASHBOARD_URL.toString()));
}
if (!User.isMasterAdmin()) {
Navigation.navigate(URL.fromString(DASHBOARD_URL.toString()));
}
return (
<MasterPage>
<Routes>
<PageRoute
path={RouteMap[PageMap.INIT]?.toString() || ''}
element={<Init />}
/>
return (
<MasterPage>
<Routes>
<PageRoute
path={RouteMap[PageMap.INIT]?.toString() || ""}
element={<Init />}
/>
<PageRoute
path={RouteMap[PageMap.PROJECTS]?.toString() || ''}
element={<Projects />}
/>
<PageRoute
path={RouteMap[PageMap.PROJECTS]?.toString() || ""}
element={<Projects />}
/>
<PageRoute
path={RouteMap[PageMap.USERS]?.toString() || ''}
element={<Users />}
/>
<PageRoute
path={RouteMap[PageMap.USERS]?.toString() || ""}
element={<Users />}
/>
<PageRoute
path={RouteMap[PageMap.LOGOUT]?.toString() || ''}
element={<Logout />}
/>
<PageRoute
path={RouteMap[PageMap.LOGOUT]?.toString() || ""}
element={<Logout />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS]?.toString() || ''}
element={<SettingsAuthentication />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS]?.toString() || ""}
element={<SettingsAuthentication />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_SMTP]?.toString() || ''}
element={<SettingsEmail />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_SMTP]?.toString() || ""}
element={<SettingsEmail />}
/>
<PageRoute
path={
RouteMap[PageMap.SETTINGS_CALL_AND_SMS]?.toString() ||
''
}
element={<SettingsCallSMS />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_CALL_AND_SMS]?.toString() || ""}
element={<SettingsCallSMS />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_PROBES]?.toString() || ''}
element={<SettingsProbes />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_PROBES]?.toString() || ""}
element={<SettingsProbes />}
/>
<PageRoute
path={
RouteMap[PageMap.SETTINGS_AUTHENTICATION]?.toString() ||
''
}
element={<SettingsAuthentication />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_AUTHENTICATION]?.toString() || ""}
element={<SettingsAuthentication />}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_API_KEY]?.toString() || ''}
element={<SettingsAPIKey />}
/>
</Routes>
</MasterPage>
);
<PageRoute
path={RouteMap[PageMap.SETTINGS_API_KEY]?.toString() || ""}
element={<SettingsAPIKey />}
/>
</Routes>
</MasterPage>
);
};
export default App;

View File

@@ -1,122 +1,114 @@
import React from 'react';
import Footer from 'CommonUI/src/Components/Footer/Footer';
import URL from 'Common/Types/API/URL';
import API from 'Common/Utils/API';
import { HOST, HTTP_PROTOCOL } from 'CommonUI/src/Config';
import { JSONObject } from 'Common/Types/JSON';
import BadDataException from 'Common/Types/Exception/BadDataException';
import ConfirmModal from 'CommonUI/src/Components/Modal/ConfirmModal';
import Dictionary from 'Common/Types/Dictionary';
import HTTPResponse from 'Common/Types/API/HTTPResponse';
import { PromiseVoidFunction } from 'Common/Types/FunctionTypes';
import HTTPResponse from "Common/Types/API/HTTPResponse";
import URL from "Common/Types/API/URL";
import Dictionary from "Common/Types/Dictionary";
import BadDataException from "Common/Types/Exception/BadDataException";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import { JSONObject } from "Common/Types/JSON";
import API from "Common/Utils/API";
import Footer from "CommonUI/src/Components/Footer/Footer";
import ConfirmModal from "CommonUI/src/Components/Modal/ConfirmModal";
import { HOST, HTTP_PROTOCOL } from "CommonUI/src/Config";
import React from "react";
const DashboardFooter: () => JSX.Element = () => {
const [showAboutModal, setShowAboutModal] = React.useState<boolean>(false);
const [isAboutModalLoading, setIsAboutModalLoading] =
React.useState<boolean>(false);
const [versionText, setVersionText] = React.useState<Dictionary<string>>(
{}
const [showAboutModal, setShowAboutModal] = React.useState<boolean>(false);
const [isAboutModalLoading, setIsAboutModalLoading] =
React.useState<boolean>(false);
const [versionText, setVersionText] = React.useState<Dictionary<string>>({});
const fetchVersions: PromiseVoidFunction = async (): Promise<void> => {
setIsAboutModalLoading(true);
try {
const verText: Dictionary<string> = {};
const apps: Array<{
name: string;
path: string;
}> = [
{
name: "API",
path: "/api",
},
{
name: "Dashboard",
path: "/dashboard",
},
];
for (const app of apps) {
const version: JSONObject = await fetchAppVersion(app.path);
verText[app.name] =
`${app.name}: ${version["version"]} (${version["commit"]})`;
}
setVersionText(verText);
} catch (err) {
setVersionText({
error: "Version data is not available: " + (err as Error).message,
});
}
setIsAboutModalLoading(false);
};
const fetchAppVersion: (appName: string) => Promise<JSONObject> = async (
appName: string,
): Promise<JSONObject> => {
const response: HTTPResponse<JSONObject> = await API.get<JSONObject>(
URL.fromString(`${HTTP_PROTOCOL}/${HOST}${appName}/version`),
);
const fetchVersions: PromiseVoidFunction = async (): Promise<void> => {
setIsAboutModalLoading(true);
if (response.data) {
return response.data as JSONObject;
}
throw new BadDataException("Version data is not available");
};
try {
const verText: Dictionary<string> = {};
const apps: Array<{
name: string;
path: string;
}> = [
{
name: 'API',
path: '/api',
},
{
name: 'Dashboard',
path: '/dashboard',
},
];
return (
<>
<Footer
className="bg-white h-16 inset-x-0 bottom-0 px-8"
copyright="HackerBay, Inc."
links={[
{
title: "Help and Support",
to: URL.fromString("https://oneuptime.com/support"),
},
{
title: "Legal",
to: URL.fromString("https://oneuptime.com/legal"),
},
{
title: "Version",
onClick: async () => {
setShowAboutModal(true);
await fetchVersions();
},
},
]}
/>
for (const app of apps) {
const version: JSONObject = await fetchAppVersion(app.path);
verText[
app.name
] = `${app.name}: ${version['version']} (${version['commit']})`;
}
setVersionText(verText);
} catch (err) {
setVersionText({
error:
'Version data is not available: ' + (err as Error).message,
});
}
setIsAboutModalLoading(false);
};
const fetchAppVersion: (appName: string) => Promise<JSONObject> = async (
appName: string
): Promise<JSONObject> => {
const response: HTTPResponse<JSONObject> = await API.get<JSONObject>(
URL.fromString(`${HTTP_PROTOCOL}/${HOST}${appName}/version`)
);
if (response.data) {
return response.data as JSONObject;
}
throw new BadDataException('Version data is not available');
};
return (
<>
<Footer
className="bg-white h-16 inset-x-0 bottom-0 px-8"
copyright="HackerBay, Inc."
links={[
{
title: 'Help and Support',
to: URL.fromString('https://oneuptime.com/support'),
},
{
title: 'Legal',
to: URL.fromString('https://oneuptime.com/legal'),
},
{
title: 'Version',
onClick: async () => {
setShowAboutModal(true);
await fetchVersions();
},
},
]}
/>
{showAboutModal ? (
<ConfirmModal
title={`OneUptime Version`}
description={
<div>
{Object.keys(versionText).map(
(key: string, i: number) => {
return (
<div key={i}>{versionText[key]}</div>
);
}
)}
</div>
}
isLoading={isAboutModalLoading}
submitButtonText={'Close'}
onSubmit={() => {
return setShowAboutModal(false);
}}
/>
) : (
<></>
)}
</>
);
{showAboutModal ? (
<ConfirmModal
title={`OneUptime Version`}
description={
<div>
{Object.keys(versionText).map((key: string, i: number) => {
return <div key={i}>{versionText[key]}</div>;
})}
</div>
}
isLoading={isAboutModalLoading}
submitButtonText={"Close"}
onSubmit={() => {
return setShowAboutModal(false);
}}
/>
) : (
<></>
)}
</>
);
};
export default DashboardFooter;

View File

@@ -1,46 +1,46 @@
import React, { FunctionComponent, ReactElement } from 'react';
import Help from './Help';
import Header from 'CommonUI/src/Components/Header/Header';
import Logo from './Logo';
import Button, { ButtonStyleType } from 'CommonUI/src/Components/Button/Button';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { DASHBOARD_URL } from 'CommonUI/src/Config';
import UserProfile from './UserProfile';
import Help from "./Help";
import Logo from "./Logo";
import UserProfile from "./UserProfile";
import Button, { ButtonStyleType } from "CommonUI/src/Components/Button/Button";
import Header from "CommonUI/src/Components/Header/Header";
import { DASHBOARD_URL } from "CommonUI/src/Config";
import Navigation from "CommonUI/src/Utils/Navigation";
import React, { FunctionComponent, ReactElement } from "react";
const DashboardHeader: FunctionComponent = (): ReactElement => {
return (
<>
<Header
leftComponents={
<>
<Logo onClick={() => {}} />
</>
}
centerComponents={
<>
{/* <SearchBox
return (
<>
<Header
leftComponents={
<>
<Logo onClick={() => {}} />
</>
}
centerComponents={
<>
{/* <SearchBox
key={2}
selectedProject={props.selectedProject}
onChange={(_value: string) => { }}
/>{' '} */}
</>
}
rightComponents={
<>
<Button
title="Exit Admin"
buttonStyle={ButtonStyleType.NORMAL}
onClick={() => {
Navigation.navigate(DASHBOARD_URL);
}}
/>
<Help />
<UserProfile />
</>
}
</>
}
rightComponents={
<>
<Button
title="Exit Admin"
buttonStyle={ButtonStyleType.NORMAL}
onClick={() => {
Navigation.navigate(DASHBOARD_URL);
}}
/>
</>
);
<Help />
<UserProfile />
</>
}
/>
</>
);
};
export default DashboardHeader;

View File

@@ -1,60 +1,58 @@
import React, { ReactElement, useState } from 'react';
import HeaderIconDropdownButton from 'CommonUI/src/Components/Header/HeaderIconDropdownButton';
import IconDropdownItem from 'CommonUI/src/Components/Header/IconDropdown/IconDropdownItem';
import IconDropdownMenu from 'CommonUI/src/Components/Header/IconDropdown/IconDropdownMenu';
import IconDropdownRow from 'CommonUI/src/Components/Header/IconDropdown/IconDropdownRow';
import IconProp from 'Common/Types/Icon/IconProp';
import URL from 'Common/Types/API/URL';
import URL from "Common/Types/API/URL";
import IconProp from "Common/Types/Icon/IconProp";
import HeaderIconDropdownButton from "CommonUI/src/Components/Header/HeaderIconDropdownButton";
import IconDropdownItem from "CommonUI/src/Components/Header/IconDropdown/IconDropdownItem";
import IconDropdownMenu from "CommonUI/src/Components/Header/IconDropdown/IconDropdownMenu";
import IconDropdownRow from "CommonUI/src/Components/Header/IconDropdown/IconDropdownRow";
import React, { ReactElement, useState } from "react";
const Help: () => JSX.Element = (): ReactElement => {
const [isDropdownVisible, setIsDropdownVisible] = useState<boolean>(false);
const [isDropdownVisible, setIsDropdownVisible] = useState<boolean>(false);
return (
<HeaderIconDropdownButton
icon={IconProp.Help}
name="Help"
showDropdown={isDropdownVisible}
return (
<HeaderIconDropdownButton
icon={IconProp.Help}
name="Help"
showDropdown={isDropdownVisible}
onClick={() => {
setIsDropdownVisible(true);
}}
>
<IconDropdownMenu>
<IconDropdownRow>
<IconDropdownItem
title="Support Email"
icon={IconProp.Email}
openInNewTab={true}
url={URL.fromString("mailto:support@oneuptime.com")}
onClick={() => {
setIsDropdownVisible(true);
setIsDropdownVisible(false);
}}
>
<IconDropdownMenu>
<IconDropdownRow>
<IconDropdownItem
title="Support Email"
icon={IconProp.Email}
openInNewTab={true}
url={URL.fromString('mailto:support@oneuptime.com')}
onClick={() => {
setIsDropdownVisible(false);
}}
/>
<IconDropdownItem
title="Chat on Slack"
icon={IconProp.Slack}
openInNewTab={true}
onClick={() => {
setIsDropdownVisible(false);
}}
url={URL.fromString(
'https://join.slack.com/t/oneuptimesupport/shared_invite/zt-1kavkds2f-gegm_wePorvwvM3M_SaoCQ'
)}
/>
<IconDropdownItem
title="Request Demo"
icon={IconProp.Window}
onClick={() => {
setIsDropdownVisible(false);
}}
openInNewTab={true}
url={URL.fromString(
'https://oneuptime.com/enterprise/demo'
)}
/>
</IconDropdownRow>
</IconDropdownMenu>
</HeaderIconDropdownButton>
);
/>
<IconDropdownItem
title="Chat on Slack"
icon={IconProp.Slack}
openInNewTab={true}
onClick={() => {
setIsDropdownVisible(false);
}}
url={URL.fromString(
"https://join.slack.com/t/oneuptimesupport/shared_invite/zt-1kavkds2f-gegm_wePorvwvM3M_SaoCQ",
)}
/>
<IconDropdownItem
title="Request Demo"
icon={IconProp.Window}
onClick={() => {
setIsDropdownVisible(false);
}}
openInNewTab={true}
url={URL.fromString("https://oneuptime.com/enterprise/demo")}
/>
</IconDropdownRow>
</IconDropdownMenu>
</HeaderIconDropdownButton>
);
};
export default Help;

View File

@@ -1,31 +1,30 @@
// Tailwind
import React, { FunctionComponent, ReactElement } from 'react';
import Image from 'CommonUI/src/Components/Image/Image';
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg';
import Route from 'Common/Types/API/Route';
import Route from "Common/Types/API/Route";
import Image from "CommonUI/src/Components/Image/Image";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import React, { FunctionComponent, ReactElement } from "react";
export interface ComponentProps {
onClick: () => void;
onClick: () => void;
}
const Logo: FunctionComponent<ComponentProps> = (
props: ComponentProps
props: ComponentProps,
): ReactElement => {
return (
<div className="relative z-10 flex px-2 lg:px-0">
<div className="flex flex-shrink-0 items-center">
<Image
className="block h-8 w-auto"
onClick={() => {
props.onClick && props.onClick();
}}
imageUrl={Route.fromString(`${OneUptimeLogo}`)}
alt={'OneUptime'}
/>
</div>
</div>
);
return (
<div className="relative z-10 flex px-2 lg:px-0">
<div className="flex flex-shrink-0 items-center">
<Image
className="block h-8 w-auto"
onClick={() => {
props.onClick && props.onClick();
}}
imageUrl={Route.fromString(`${OneUptimeLogo}`)}
alt={"OneUptime"}
/>
</div>
</div>
);
};
export default Logo;

View File

@@ -1,35 +1,35 @@
import React, { ReactElement, useState } from 'react';
import HeaderIconDropdownButton from 'CommonUI/src/Components/Header/HeaderIconDropdownButton';
import Notifications from 'CommonUI/src/Components/Header/Notifications/Notifications';
import NotificationItem from 'CommonUI/src/Components/Header/Notifications/NotificationItem';
import IconProp from 'Common/Types/Icon/IconProp';
import IconProp from "Common/Types/Icon/IconProp";
import HeaderIconDropdownButton from "CommonUI/src/Components/Header/HeaderIconDropdownButton";
import NotificationItem from "CommonUI/src/Components/Header/Notifications/NotificationItem";
import Notifications from "CommonUI/src/Components/Header/Notifications/Notifications";
import React, { ReactElement, useState } from "react";
const DashboardHeader: () => JSX.Element = (): ReactElement => {
const [isDropdownVisible, setIsDropdownVisible] = useState<boolean>(false);
const [isDropdownVisible, setIsDropdownVisible] = useState<boolean>(false);
return (
<HeaderIconDropdownButton
name="Notifications"
onClick={() => {
setIsDropdownVisible(true);
}}
showDropdown={isDropdownVisible}
icon={IconProp.Notification}
badge={4}
>
<Notifications>
<NotificationItem
title="Sample Title"
description="Sample Description"
createdAt={new Date()}
icon={IconProp.Home}
onClick={() => {
setIsDropdownVisible(false);
}}
/>
</Notifications>
</HeaderIconDropdownButton>
);
return (
<HeaderIconDropdownButton
name="Notifications"
onClick={() => {
setIsDropdownVisible(true);
}}
showDropdown={isDropdownVisible}
icon={IconProp.Notification}
badge={4}
>
<Notifications>
<NotificationItem
title="Sample Title"
description="Sample Description"
createdAt={new Date()}
icon={IconProp.Home}
onClick={() => {
setIsDropdownVisible(false);
}}
/>
</Notifications>
</HeaderIconDropdownButton>
);
};
export default DashboardHeader;

View File

@@ -1,286 +1,273 @@
import SubscriptionPlan from "Common/Types/Billing/SubscriptionPlan";
import IconProp from "Common/Types/Icon/IconProp";
import { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import Field from "CommonUI/src/Components/Forms/Types/Field";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ProjectPicker from "CommonUI/src/Components/Header/ProjectPicker/ProjectPicker";
import ModelFormModal from "CommonUI/src/Components/ModelFormModal/ModelFormModal";
import { RadioButton } from "CommonUI/src/Components/RadioButtons/GroupRadioButtons";
import Toggle from "CommonUI/src/Components/Toggle/Toggle";
import { BILLING_ENABLED, getAllEnvVars } from "CommonUI/src/Config";
import { GetReactElementFunction } from "CommonUI/src/Types/FunctionTypes";
import ProjectUtil from "CommonUI/src/Utils/Project";
import Project from "Model/Models/Project";
import React, {
FunctionComponent,
ReactElement,
useState,
useEffect,
} from 'react';
import ProjectPicker from 'CommonUI/src/Components/Header/ProjectPicker/ProjectPicker';
import IconProp from 'Common/Types/Icon/IconProp';
import Project from 'Model/Models/Project';
import ModelFormModal from 'CommonUI/src/Components/ModelFormModal/ModelFormModal';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
import ProjectUtil from 'CommonUI/src/Utils/Project';
import { BILLING_ENABLED, getAllEnvVars } from 'CommonUI/src/Config';
import SubscriptionPlan from 'Common/Types/Billing/SubscriptionPlan';
import Field from 'CommonUI/src/Components/Forms/Types/Field';
import { RadioButton } from 'CommonUI/src/Components/RadioButtons/GroupRadioButtons';
import Toggle from 'CommonUI/src/Components/Toggle/Toggle';
import { GetReactElementFunction } from 'CommonUI/src/Types/FunctionTypes';
FunctionComponent,
ReactElement,
useEffect,
useState,
} from "react";
export interface ComponentProps {
projects: Array<Project>;
onProjectSelected: (project: Project) => void;
showProjectModal: boolean;
onProjectModalClose: () => void;
projects: Array<Project>;
onProjectSelected: (project: Project) => void;
showProjectModal: boolean;
onProjectModalClose: () => void;
}
const DashboardProjectPicker: FunctionComponent<ComponentProps> = (
props: ComponentProps
props: ComponentProps,
): ReactElement => {
const [showModal, setShowModal] = useState<boolean>(false);
const [selectedProject, setSelectedProject] = useState<Project | null>(
null
);
const [showModal, setShowModal] = useState<boolean>(false);
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
const getFooter: GetReactElementFunction = (): ReactElement => {
if (!BILLING_ENABLED) {
return <></>;
}
return (
<Toggle
title="Yearly Plan"
value={isSubscriptionPlanYearly}
description="(Save 20%)"
onChange={(value: boolean) => {
setIsSubscriptionPlanYearly(value);
}}
/>
);
};
const [isSubscriptionPlanYearly, setIsSubscriptionPlanYearly] =
useState<boolean>(true);
const [fields, setFields] = useState<Array<Field<Project>>>([]);
useEffect(() => {
if (props.showProjectModal) {
setShowModal(true);
}
}, [props.showProjectModal]);
useEffect(() => {
const currentProject: Project | null = ProjectUtil.getCurrentProject();
setSelectedProject(currentProject);
if (currentProject && props.onProjectSelected) {
props.onProjectSelected(currentProject);
}
}, []);
useEffect(() => {
if (selectedProject) {
ProjectUtil.setCurrentProject(selectedProject);
if (props.onProjectSelected) {
props.onProjectSelected(selectedProject);
}
}
}, [selectedProject]);
useEffect(() => {
if (
props.projects &&
props.projects.length > 0 &&
!selectedProject &&
props.projects[0]
) {
const currentProject: Project | null =
ProjectUtil.getCurrentProject();
if (!currentProject) {
setSelectedProject(props.projects[0]);
} else if (
props.projects.filter((project: Project) => {
return project._id === currentProject._id;
}).length > 0
) {
setSelectedProject(
props.projects.filter((project: Project) => {
return project._id === currentProject._id;
})[0] as Project
);
} else {
setSelectedProject(props.projects[0]);
}
}
}, [props.projects]);
useEffect(() => {
refreshFields();
}, [isSubscriptionPlanYearly]);
const refreshFields: VoidFunction = (): void => {
let formFields: Array<Field<Project>> = [
{
field: {
name: true,
},
validation: {
minLength: 4,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'My Project',
description: 'Pick a friendly name.',
title: 'Project Name',
required: true,
stepId: BILLING_ENABLED ? 'basic' : undefined,
},
];
if (BILLING_ENABLED) {
formFields = [
...formFields,
{
field: {
paymentProviderPlanId: true,
},
stepId: 'plan',
validation: {
minLength: 6,
},
footerElement: getFooter(),
fieldType: FormFieldSchemaType.RadioButton,
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
getAllEnvVars()
).map((plan: SubscriptionPlan): RadioButton => {
let description: string = plan.isCustomPricing()
? `Our sales team will contact you soon.`
: `Billed ${
isSubscriptionPlanYearly
? 'yearly'
: 'monthly'
}. ${
plan.getTrialPeriod() > 0
? `Free ${plan.getTrialPeriod()} days trial.`
: ''
}`;
if (
isSubscriptionPlanYearly &&
plan.getYearlySubscriptionAmountInUSD() === 0
) {
description = 'This plan is free, forever. ';
}
if (
!isSubscriptionPlanYearly &&
plan.getMonthlySubscriptionAmountInUSD() === 0
) {
description = 'This plan is free, forever. ';
}
return {
value: isSubscriptionPlanYearly
? plan.getYearlyPlanId()
: plan.getMonthlyPlanId(),
title: plan.getName(),
description: description,
sideTitle: plan.isCustomPricing()
? 'Custom Price'
: isSubscriptionPlanYearly
? '$' +
plan
.getYearlySubscriptionAmountInUSD()
.toString() +
'/mo billed yearly'
: '$' +
plan
.getMonthlySubscriptionAmountInUSD()
.toString(),
sideDescription: plan.isCustomPricing()
? ''
: isSubscriptionPlanYearly
? `~ $${
plan.getYearlySubscriptionAmountInUSD() *
12
} per user / year`
: `/month per user`,
};
}),
title: 'Please select a plan.',
required: true,
},
{
field: {
paymentProviderPromoCode: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Promo Code (Optional)',
description: 'If you have a coupon code, enter it here.',
title: 'Promo Code',
required: false,
stepId: 'plan',
},
];
}
setFields(formFields);
};
const getFooter: GetReactElementFunction = (): ReactElement => {
if (!BILLING_ENABLED) {
return <></>;
}
return (
<>
{props.projects.length !== 0 && (
<ProjectPicker
selectedProjectName={selectedProject?.name || ''}
selectedProjectIcon={IconProp.Folder}
projects={props.projects}
onCreateProjectButtonClicked={() => {
setShowModal(true);
props.onProjectModalClose();
}}
onProjectSelected={(project: Project) => {
setSelectedProject(project);
}}
/>
)}
{showModal ? (
<ModelFormModal<Project>
modelType={Project}
name="Create New Project"
title="Create New Project"
description="Please create a new OneUptime project to get started."
onClose={() => {
setShowModal(false);
props.onProjectModalClose();
}}
submitButtonText="Create Project"
onSuccess={(project: Project | null) => {
setSelectedProject(project);
if (project && props.onProjectSelected) {
props.onProjectSelected(project);
}
setShowModal(false);
props.onProjectModalClose();
}}
formProps={{
name: 'Create New Project',
steps: BILLING_ENABLED
? [
{
title: 'Basic',
id: 'basic',
},
{
title: 'Select Plan',
id: 'plan',
},
]
: undefined,
saveRequestOptions: {
isMultiTenantRequest: true, // because this is a tenant request, we do not have to include the header in the request
},
modelType: Project,
id: 'create-project-from',
fields: [...fields],
formType: FormType.Create,
}}
/>
) : (
<></>
)}
</>
<Toggle
title="Yearly Plan"
value={isSubscriptionPlanYearly}
description="(Save 20%)"
onChange={(value: boolean) => {
setIsSubscriptionPlanYearly(value);
}}
/>
);
};
const [isSubscriptionPlanYearly, setIsSubscriptionPlanYearly] =
useState<boolean>(true);
const [fields, setFields] = useState<Array<Field<Project>>>([]);
useEffect(() => {
if (props.showProjectModal) {
setShowModal(true);
}
}, [props.showProjectModal]);
useEffect(() => {
const currentProject: Project | null = ProjectUtil.getCurrentProject();
setSelectedProject(currentProject);
if (currentProject && props.onProjectSelected) {
props.onProjectSelected(currentProject);
}
}, []);
useEffect(() => {
if (selectedProject) {
ProjectUtil.setCurrentProject(selectedProject);
if (props.onProjectSelected) {
props.onProjectSelected(selectedProject);
}
}
}, [selectedProject]);
useEffect(() => {
if (
props.projects &&
props.projects.length > 0 &&
!selectedProject &&
props.projects[0]
) {
const currentProject: Project | null = ProjectUtil.getCurrentProject();
if (!currentProject) {
setSelectedProject(props.projects[0]);
} else if (
props.projects.filter((project: Project) => {
return project._id === currentProject._id;
}).length > 0
) {
setSelectedProject(
props.projects.filter((project: Project) => {
return project._id === currentProject._id;
})[0] as Project,
);
} else {
setSelectedProject(props.projects[0]);
}
}
}, [props.projects]);
useEffect(() => {
refreshFields();
}, [isSubscriptionPlanYearly]);
const refreshFields: VoidFunction = (): void => {
let formFields: Array<Field<Project>> = [
{
field: {
name: true,
},
validation: {
minLength: 4,
},
fieldType: FormFieldSchemaType.Text,
placeholder: "My Project",
description: "Pick a friendly name.",
title: "Project Name",
required: true,
stepId: BILLING_ENABLED ? "basic" : undefined,
},
];
if (BILLING_ENABLED) {
formFields = [
...formFields,
{
field: {
paymentProviderPlanId: true,
},
stepId: "plan",
validation: {
minLength: 6,
},
footerElement: getFooter(),
fieldType: FormFieldSchemaType.RadioButton,
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
getAllEnvVars(),
).map((plan: SubscriptionPlan): RadioButton => {
let description: string = plan.isCustomPricing()
? `Our sales team will contact you soon.`
: `Billed ${isSubscriptionPlanYearly ? "yearly" : "monthly"}. ${
plan.getTrialPeriod() > 0
? `Free ${plan.getTrialPeriod()} days trial.`
: ""
}`;
if (
isSubscriptionPlanYearly &&
plan.getYearlySubscriptionAmountInUSD() === 0
) {
description = "This plan is free, forever. ";
}
if (
!isSubscriptionPlanYearly &&
plan.getMonthlySubscriptionAmountInUSD() === 0
) {
description = "This plan is free, forever. ";
}
return {
value: isSubscriptionPlanYearly
? plan.getYearlyPlanId()
: plan.getMonthlyPlanId(),
title: plan.getName(),
description: description,
sideTitle: plan.isCustomPricing()
? "Custom Price"
: isSubscriptionPlanYearly
? "$" +
plan.getYearlySubscriptionAmountInUSD().toString() +
"/mo billed yearly"
: "$" + plan.getMonthlySubscriptionAmountInUSD().toString(),
sideDescription: plan.isCustomPricing()
? ""
: isSubscriptionPlanYearly
? `~ $${
plan.getYearlySubscriptionAmountInUSD() * 12
} per user / year`
: `/month per user`,
};
}),
title: "Please select a plan.",
required: true,
},
{
field: {
paymentProviderPromoCode: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: "Promo Code (Optional)",
description: "If you have a coupon code, enter it here.",
title: "Promo Code",
required: false,
stepId: "plan",
},
];
}
setFields(formFields);
};
return (
<>
{props.projects.length !== 0 && (
<ProjectPicker
selectedProjectName={selectedProject?.name || ""}
selectedProjectIcon={IconProp.Folder}
projects={props.projects}
onCreateProjectButtonClicked={() => {
setShowModal(true);
props.onProjectModalClose();
}}
onProjectSelected={(project: Project) => {
setSelectedProject(project);
}}
/>
)}
{showModal ? (
<ModelFormModal<Project>
modelType={Project}
name="Create New Project"
title="Create New Project"
description="Please create a new OneUptime project to get started."
onClose={() => {
setShowModal(false);
props.onProjectModalClose();
}}
submitButtonText="Create Project"
onSuccess={(project: Project | null) => {
setSelectedProject(project);
if (project && props.onProjectSelected) {
props.onProjectSelected(project);
}
setShowModal(false);
props.onProjectModalClose();
}}
formProps={{
name: "Create New Project",
steps: BILLING_ENABLED
? [
{
title: "Basic",
id: "basic",
},
{
title: "Select Plan",
id: "plan",
},
]
: undefined,
saveRequestOptions: {
isMultiTenantRequest: true, // because this is a tenant request, we do not have to include the header in the request
},
modelType: Project,
id: "create-project-from",
fields: [...fields],
formType: FormType.Create,
}}
/>
) : (
<></>
)}
</>
);
};
export default DashboardProjectPicker;

View File

@@ -1,20 +1,20 @@
import React, { FunctionComponent, ReactElement } from 'react';
import SearchBox from 'CommonUI/src/Components/Header/SearchBox';
import Project from 'Model/Models/Project';
import SearchBox from "CommonUI/src/Components/Header/SearchBox";
import Project from "Model/Models/Project";
import React, { FunctionComponent, ReactElement } from "react";
export interface ComponentProps {
onChange: (search: string) => void;
selectedProject: Project | null;
onChange: (search: string) => void;
selectedProject: Project | null;
}
const Search: FunctionComponent<ComponentProps> = (
props: ComponentProps
props: ComponentProps,
): ReactElement => {
if (!props.selectedProject) {
return <></>;
}
if (!props.selectedProject) {
return <></>;
}
return <SearchBox key={2} onChange={props.onChange} />;
return <SearchBox key={2} onChange={props.onChange} />;
};
export default Search;

View File

@@ -1,57 +1,57 @@
import React, { FunctionComponent, ReactElement, useState } from 'react';
import IconProp from 'Common/Types/Icon/IconProp';
import Route from 'Common/Types/API/Route';
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
import PageMap from '../../Utils/PageMap';
import BlankProfilePic from 'CommonUI/src/Images/users/blank-profile.svg';
import HeaderIconDropdownButton from 'CommonUI/src/Components/Header/HeaderIconDropdownButton';
import IconDropdownItem from 'CommonUI/src/Components/Header/IconDropdown/IconDropdownItem';
import IconDropdownMenu from 'CommonUI/src/Components/Header/IconDropdown/IconDropdownMenu';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { DASHBOARD_URL } from 'CommonUI/src/Config';
import User from 'CommonUI/src/Utils/User';
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import IconProp from "Common/Types/Icon/IconProp";
import HeaderIconDropdownButton from "CommonUI/src/Components/Header/HeaderIconDropdownButton";
import IconDropdownItem from "CommonUI/src/Components/Header/IconDropdown/IconDropdownItem";
import IconDropdownMenu from "CommonUI/src/Components/Header/IconDropdown/IconDropdownMenu";
import { DASHBOARD_URL } from "CommonUI/src/Config";
import BlankProfilePic from "CommonUI/src/Images/users/blank-profile.svg";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "CommonUI/src/Utils/User";
import React, { FunctionComponent, ReactElement, useState } from "react";
const DashboardUserProfile: FunctionComponent = (): ReactElement => {
const [isDropdownVisible, setIsDropdownVisible] = useState<boolean>(false);
const [isDropdownVisible, setIsDropdownVisible] = useState<boolean>(false);
return (
<>
<HeaderIconDropdownButton
iconImageUrl={BlankProfilePic}
name="User Profile"
showDropdown={isDropdownVisible}
onClick={() => {
setIsDropdownVisible(true);
}}
>
<IconDropdownMenu>
{User.isMasterAdmin() ? (
<IconDropdownItem
title="Exit Admin"
onClick={() => {
setIsDropdownVisible(false);
Navigation.navigate(DASHBOARD_URL);
}}
icon={IconProp.ExternalLink}
/>
) : (
<></>
)}
return (
<>
<HeaderIconDropdownButton
iconImageUrl={BlankProfilePic}
name="User Profile"
showDropdown={isDropdownVisible}
onClick={() => {
setIsDropdownVisible(true);
}}
>
<IconDropdownMenu>
{User.isMasterAdmin() ? (
<IconDropdownItem
title="Exit Admin"
onClick={() => {
setIsDropdownVisible(false);
Navigation.navigate(DASHBOARD_URL);
}}
icon={IconProp.ExternalLink}
/>
) : (
<></>
)}
<IconDropdownItem
title="Log out"
onClick={() => {
setIsDropdownVisible(false);
}}
url={RouteUtil.populateRouteParams(
RouteMap[PageMap.LOGOUT] as Route
)}
icon={IconProp.Logout}
/>
</IconDropdownMenu>
</HeaderIconDropdownButton>
</>
);
<IconDropdownItem
title="Log out"
onClick={() => {
setIsDropdownVisible(false);
}}
url={RouteUtil.populateRouteParams(
RouteMap[PageMap.LOGOUT] as Route,
)}
icon={IconProp.Logout}
/>
</IconDropdownMenu>
</HeaderIconDropdownButton>
</>
);
};
export default DashboardUserProfile;

View File

@@ -1,35 +1,35 @@
import MasterPage from 'CommonUI/src/Components/MasterPage/MasterPage';
import Footer from '../Footer/Footer';
import Header from '../Header/Header';
import NavBar from '../NavBar/NavBar';
import React, { FunctionComponent, ReactElement } from 'react';
import TopAlert from 'CommonUI/src/Components/TopAlert/TopAlert';
import Footer from "../Footer/Footer";
import Header from "../Header/Header";
import NavBar from "../NavBar/NavBar";
import MasterPage from "CommonUI/src/Components/MasterPage/MasterPage";
import TopAlert from "CommonUI/src/Components/TopAlert/TopAlert";
import React, { FunctionComponent, ReactElement } from "react";
export interface ComponentProps {
children: ReactElement | Array<ReactElement>;
children: ReactElement | Array<ReactElement>;
}
const DashboardMasterPage: FunctionComponent<ComponentProps> = (
props: ComponentProps
props: ComponentProps,
): ReactElement => {
return (
<div>
<TopAlert
title="OneUptime Admin Dashboard"
description="You can perform your OneUptime server related tasks on this dashboard."
/>
<MasterPage
footer={<Footer />}
header={<Header />}
navBar={<NavBar />}
isLoading={false}
error={''}
className="flex flex-col h-screen justify-between"
>
{props.children}
</MasterPage>
</div>
);
return (
<div>
<TopAlert
title="OneUptime Admin Dashboard"
description="You can perform your OneUptime server related tasks on this dashboard."
/>
<MasterPage
footer={<Footer />}
header={<Header />}
navBar={<NavBar />}
isLoading={false}
error={""}
className="flex flex-col h-screen justify-between"
>
{props.children}
</MasterPage>
</div>
);
};
export default DashboardMasterPage;

View File

@@ -1,39 +1,37 @@
import React, { FunctionComponent, ReactElement } from 'react';
import NavBar from 'CommonUI/src/Components/Navbar/NavBar';
import NavBarItem from 'CommonUI/src/Components/Navbar/NavBarItem';
import Route from 'Common/Types/API/Route';
import IconProp from 'Common/Types/Icon/IconProp';
import PageMap from '../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import IconProp from "Common/Types/Icon/IconProp";
import NavBar from "CommonUI/src/Components/Navbar/NavBar";
import NavBarItem from "CommonUI/src/Components/Navbar/NavBarItem";
import React, { FunctionComponent, ReactElement } from "react";
const DashboardNavbar: FunctionComponent = (): ReactElement => {
return (
<NavBar>
<NavBarItem
title="Users"
icon={IconProp.User}
route={RouteUtil.populateRouteParams(
RouteMap[PageMap.USERS] as Route
)}
></NavBarItem>
return (
<NavBar>
<NavBarItem
title="Users"
icon={IconProp.User}
route={RouteUtil.populateRouteParams(RouteMap[PageMap.USERS] as Route)}
></NavBarItem>
<NavBarItem
title="Projects"
icon={IconProp.Folder}
route={RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECTS] as Route
)}
></NavBarItem>
<NavBarItem
title="Projects"
icon={IconProp.Folder}
route={RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECTS] as Route,
)}
></NavBarItem>
<NavBarItem
title="Settings"
icon={IconProp.Settings}
route={RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route
)}
></NavBarItem>
</NavBar>
);
<NavBarItem
title="Settings"
icon={IconProp.Settings}
route={RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route,
)}
></NavBarItem>
</NavBar>
);
};
export default DashboardNavbar;

View File

@@ -1,19 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import Telemetry from 'CommonUI/src/Utils/Telemetry';
import App from "./App";
import Telemetry from "CommonUI/src/Utils/Telemetry";
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
Telemetry.init({
serviceName: 'AdminDashboard',
serviceName: "AdminDashboard",
});
const root: any = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
document.getElementById("root") as HTMLElement,
);
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
<BrowserRouter>
<App />
</BrowserRouter>,
);

View File

@@ -1,22 +1,22 @@
import PageLoader from 'CommonUI/src/Components/Loader/PageLoader';
import Page from 'CommonUI/src/Components/Page/Page';
import Navigation from 'CommonUI/src/Utils/Navigation';
import React, { FunctionComponent, ReactElement, useEffect } from 'react';
import RouteMap from '../../Utils/RouteMap';
import PageMap from '../../Utils/PageMap';
import PageMap from "../../Utils/PageMap";
import RouteMap from "../../Utils/RouteMap";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import Page from "CommonUI/src/Components/Page/Page";
import Navigation from "CommonUI/src/Utils/Navigation";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
const Init: FunctionComponent = (): ReactElement => {
useEffect(() => {
Navigation.navigate(RouteMap[PageMap.USERS]!, {
forceNavigate: true,
});
}, []);
useEffect(() => {
Navigation.navigate(RouteMap[PageMap.USERS]!, {
forceNavigate: true,
});
}, []);
return (
<Page title={''} breadcrumbLinks={[]}>
<PageLoader isVisible={true} />
</Page>
);
return (
<Page title={""} breadcrumbLinks={[]}>
<PageLoader isVisible={true} />
</Page>
);
};
export default Init;

View File

@@ -1,54 +1,49 @@
import React, { FunctionComponent, ReactElement, useEffect } from 'react';
import Page from 'CommonUI/src/Components/Page/Page';
import Route from 'Common/Types/API/Route';
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
import PageMap from '../../Utils/PageMap';
import PageLoader from 'CommonUI/src/Components/Loader/PageLoader';
import UserUtil from 'CommonUI/src/Utils/User';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { ACCOUNTS_URL } from 'CommonUI/src/Config';
import UiAnalytics from 'CommonUI/src/Utils/Analytics';
import ErrorMessage from 'CommonUI/src/Components/ErrorMessage/ErrorMessage';
import { PromiseVoidFunction } from 'Common/Types/FunctionTypes';
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import Page from "CommonUI/src/Components/Page/Page";
import { ACCOUNTS_URL } from "CommonUI/src/Config";
import UiAnalytics from "CommonUI/src/Utils/Analytics";
import Navigation from "CommonUI/src/Utils/Navigation";
import UserUtil from "CommonUI/src/Utils/User";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
const Logout: FunctionComponent = (): ReactElement => {
const [error, setError] = React.useState<string | null>(null);
const [error, setError] = React.useState<string | null>(null);
const logout: PromiseVoidFunction = async (): Promise<void> => {
UiAnalytics.logout();
await UserUtil.logout();
Navigation.navigate(ACCOUNTS_URL);
};
const logout: PromiseVoidFunction = async (): Promise<void> => {
UiAnalytics.logout();
await UserUtil.logout();
Navigation.navigate(ACCOUNTS_URL);
};
useEffect(() => {
logout().catch((error: Error) => {
setError(error.message || error.toString());
});
}, []);
useEffect(() => {
logout().catch((error: Error) => {
setError(error.message || error.toString());
});
}, []);
return (
<Page
title={'Logout'}
breadcrumbLinks={[
{
title: 'Admin Dashboard',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.INIT] as Route
),
},
{
title: 'Logout',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.LOGOUT] as Route
),
},
]}
>
{!error ? <PageLoader isVisible={true} /> : <></>}
{error ? <ErrorMessage error={error} /> : <></>}
</Page>
);
return (
<Page
title={"Logout"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.INIT] as Route),
},
{
title: "Logout",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.LOGOUT] as Route),
},
]}
>
{!error ? <PageLoader isVisible={true} /> : <></>}
{error ? <ErrorMessage error={error} /> : <></>}
</Page>
);
};
export default Logout;

View File

@@ -1,263 +1,251 @@
import Route from 'Common/Types/API/Route';
import Page from 'CommonUI/src/Components/Page/Page';
import AdminModelAPI from "../../Utils/ModelAPI";
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import SubscriptionPlan from "Common/Types/Billing/SubscriptionPlan";
import Field from "CommonUI/src/Components/Forms/Types/Field";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import Page from "CommonUI/src/Components/Page/Page";
import { RadioButton } from "CommonUI/src/Components/RadioButtons/GroupRadioButtons";
import Toggle from "CommonUI/src/Components/Toggle/Toggle";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import { BILLING_ENABLED, getAllEnvVars } from "CommonUI/src/Config";
import { GetReactElementFunction } from "CommonUI/src/Types/FunctionTypes";
import Navigation from "CommonUI/src/Utils/Navigation";
import Project from "Model/Models/Project";
import User from "Model/Models/User";
import React, {
FunctionComponent,
ReactElement,
useEffect,
useState,
} from 'react';
import PageMap from '../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import Navigation from 'CommonUI/src/Utils/Navigation';
import Project from 'Model/Models/Project';
import User from 'Model/Models/User';
import { BILLING_ENABLED, getAllEnvVars } from 'CommonUI/src/Config';
import Field from 'CommonUI/src/Components/Forms/Types/Field';
import SubscriptionPlan from 'Common/Types/Billing/SubscriptionPlan';
import { RadioButton } from 'CommonUI/src/Components/RadioButtons/GroupRadioButtons';
import Toggle from 'CommonUI/src/Components/Toggle/Toggle';
import AdminModelAPI from '../../Utils/ModelAPI';
import { GetReactElementFunction } from 'CommonUI/src/Types/FunctionTypes';
FunctionComponent,
ReactElement,
useEffect,
useState,
} from "react";
const Projects: FunctionComponent = (): ReactElement => {
const [isSubscriptionPlanYearly, setIsSubscriptionPlanYearly] =
useState<boolean>(true);
const [isSubscriptionPlanYearly, setIsSubscriptionPlanYearly] =
useState<boolean>(true);
useEffect(() => {
refreshFields();
}, [isSubscriptionPlanYearly]);
useEffect(() => {
refreshFields();
}, [isSubscriptionPlanYearly]);
const refreshFields: VoidFunction = (): void => {
let formFields: Array<Field<Project>> = [
{
field: {
name: true,
},
validation: {
minLength: 4,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'My Project',
description: 'Pick a friendly name.',
title: 'Project Name',
required: true,
stepId: BILLING_ENABLED ? 'basic' : undefined,
},
{
field: {
createdByUser: true,
},
title: 'Owner',
description:
'Who would you like the owner of this project to be? If you leave this blank - you will be the owner of the project',
fieldType: FormFieldSchemaType.Dropdown,
stepId: BILLING_ENABLED ? 'basic' : undefined,
dropdownModal: {
type: User,
labelField: 'email',
valueField: '_id',
},
},
];
const refreshFields: VoidFunction = (): void => {
let formFields: Array<Field<Project>> = [
{
field: {
name: true,
},
validation: {
minLength: 4,
},
fieldType: FormFieldSchemaType.Text,
placeholder: "My Project",
description: "Pick a friendly name.",
title: "Project Name",
required: true,
stepId: BILLING_ENABLED ? "basic" : undefined,
},
{
field: {
createdByUser: true,
},
title: "Owner",
description:
"Who would you like the owner of this project to be? If you leave this blank - you will be the owner of the project",
fieldType: FormFieldSchemaType.Dropdown,
stepId: BILLING_ENABLED ? "basic" : undefined,
dropdownModal: {
type: User,
labelField: "email",
valueField: "_id",
},
},
];
if (BILLING_ENABLED) {
formFields = [
...formFields,
{
field: {
paymentProviderPlanId: true,
},
stepId: 'plan',
validation: {
minLength: 6,
},
footerElement: getFooter(),
fieldType: FormFieldSchemaType.RadioButton,
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
getAllEnvVars()
).map((plan: SubscriptionPlan): RadioButton => {
let description: string = plan.isCustomPricing()
? `Our sales team will contact you soon.`
: `Billed ${
isSubscriptionPlanYearly
? 'yearly'
: 'monthly'
}. ${
plan.getTrialPeriod() > 0
? `Free ${plan.getTrialPeriod()} days trial.`
: ''
}`;
if (BILLING_ENABLED) {
formFields = [
...formFields,
{
field: {
paymentProviderPlanId: true,
},
stepId: "plan",
validation: {
minLength: 6,
},
footerElement: getFooter(),
fieldType: FormFieldSchemaType.RadioButton,
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
getAllEnvVars(),
).map((plan: SubscriptionPlan): RadioButton => {
let description: string = plan.isCustomPricing()
? `Our sales team will contact you soon.`
: `Billed ${isSubscriptionPlanYearly ? "yearly" : "monthly"}. ${
plan.getTrialPeriod() > 0
? `Free ${plan.getTrialPeriod()} days trial.`
: ""
}`;
if (
isSubscriptionPlanYearly &&
plan.getYearlySubscriptionAmountInUSD() === 0
) {
description = 'This plan is free, forever. ';
}
if (
isSubscriptionPlanYearly &&
plan.getYearlySubscriptionAmountInUSD() === 0
) {
description = "This plan is free, forever. ";
}
if (
!isSubscriptionPlanYearly &&
plan.getMonthlySubscriptionAmountInUSD() === 0
) {
description = 'This plan is free, forever. ';
}
if (
!isSubscriptionPlanYearly &&
plan.getMonthlySubscriptionAmountInUSD() === 0
) {
description = "This plan is free, forever. ";
}
return {
value: isSubscriptionPlanYearly
? plan.getYearlyPlanId()
: plan.getMonthlyPlanId(),
title: plan.getName(),
description: description,
sideTitle: plan.isCustomPricing()
? 'Custom Price'
: isSubscriptionPlanYearly
? '$' +
plan
.getYearlySubscriptionAmountInUSD()
.toString() +
'/mo billed yearly'
: '$' +
plan
.getMonthlySubscriptionAmountInUSD()
.toString(),
sideDescription: plan.isCustomPricing()
? ''
: isSubscriptionPlanYearly
? `~ $${
plan.getYearlySubscriptionAmountInUSD() *
12
} per user / year`
: `/month per user`,
};
}),
title: 'Please select a plan.',
required: true,
},
{
field: {
paymentProviderPromoCode: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Promo Code (Optional)',
description: 'If you have a coupon code, enter it here.',
title: 'Promo Code',
required: false,
stepId: 'plan',
disabled: false,
},
];
}
return {
value: isSubscriptionPlanYearly
? plan.getYearlyPlanId()
: plan.getMonthlyPlanId(),
title: plan.getName(),
description: description,
sideTitle: plan.isCustomPricing()
? "Custom Price"
: isSubscriptionPlanYearly
? "$" +
plan.getYearlySubscriptionAmountInUSD().toString() +
"/mo billed yearly"
: "$" + plan.getMonthlySubscriptionAmountInUSD().toString(),
sideDescription: plan.isCustomPricing()
? ""
: isSubscriptionPlanYearly
? `~ $${
plan.getYearlySubscriptionAmountInUSD() * 12
} per user / year`
: `/month per user`,
};
}),
title: "Please select a plan.",
required: true,
},
{
field: {
paymentProviderPromoCode: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: "Promo Code (Optional)",
description: "If you have a coupon code, enter it here.",
title: "Promo Code",
required: false,
stepId: "plan",
disabled: false,
},
];
}
setFields(formFields);
};
setFields(formFields);
};
const [fields, setFields] = useState<Array<Field<Project>>>([]);
const [fields, setFields] = useState<Array<Field<Project>>>([]);
const getFooter: GetReactElementFunction = (): ReactElement => {
if (!BILLING_ENABLED) {
return <></>;
}
return (
<Toggle
title="Yearly Plan"
value={isSubscriptionPlanYearly}
description="(Save 20%)"
onChange={(value: boolean) => {
setIsSubscriptionPlanYearly(value);
}}
/>
);
};
const getFooter: GetReactElementFunction = (): ReactElement => {
if (!BILLING_ENABLED) {
return <></>;
}
return (
<Page
title={'Projects'}
breadcrumbLinks={[
{
title: 'Admin Dashboard',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.HOME] as Route
),
},
{
title: 'Projects',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECTS] as Route
),
},
]}
>
<ModelTable<Project>
modelType={Project}
modelAPI={AdminModelAPI}
id="projects-table"
isDeleteable={false}
isEditable={false}
isCreateable={true}
name="Projects"
isViewable={false}
cardProps={{
title: 'Projects',
description: 'Here is a list of proejcts in OneUptime.',
}}
showViewIdButton={true}
formSteps={
BILLING_ENABLED
? [
{
title: 'Basic',
id: 'basic',
},
{
title: 'Select Plan',
id: 'plan',
},
]
: undefined
}
noItemsMessage={'No projects found.'}
formFields={fields}
showRefreshButton={true}
viewPageRoute={Navigation.getCurrentRoute()}
filters={[
{
field: {
name: true,
},
title: 'Name',
type: FieldType.Text,
},
{
field: {
createdAt: true,
},
title: 'Created At',
type: FieldType.DateTime,
},
]}
columns={[
{
field: {
name: true,
},
title: 'Name',
type: FieldType.Text,
},
{
field: {
createdAt: true,
},
title: 'Created At',
type: FieldType.DateTime,
},
]}
/>
</Page>
<Toggle
title="Yearly Plan"
value={isSubscriptionPlanYearly}
description="(Save 20%)"
onChange={(value: boolean) => {
setIsSubscriptionPlanYearly(value);
}}
/>
);
};
return (
<Page
title={"Projects"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
},
{
title: "Projects",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECTS] as Route,
),
},
]}
>
<ModelTable<Project>
modelType={Project}
modelAPI={AdminModelAPI}
id="projects-table"
isDeleteable={false}
isEditable={false}
isCreateable={true}
name="Projects"
isViewable={false}
cardProps={{
title: "Projects",
description: "Here is a list of proejcts in OneUptime.",
}}
showViewIdButton={true}
formSteps={
BILLING_ENABLED
? [
{
title: "Basic",
id: "basic",
},
{
title: "Select Plan",
id: "plan",
},
]
: undefined
}
noItemsMessage={"No projects found."}
formFields={fields}
showRefreshButton={true}
viewPageRoute={Navigation.getCurrentRoute()}
filters={[
{
field: {
name: true,
},
title: "Name",
type: FieldType.Text,
},
{
field: {
createdAt: true,
},
title: "Created At",
type: FieldType.DateTime,
},
]}
columns={[
{
field: {
name: true,
},
title: "Name",
type: FieldType.Text,
},
{
field: {
createdAt: true,
},
title: "Created At",
type: FieldType.DateTime,
},
]}
/>
</Page>
);
};
export default Projects;

View File

@@ -1,102 +1,100 @@
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail';
import Page from 'CommonUI/src/Components/Page/Page';
import React, { FunctionComponent, ReactElement } from 'react';
import PageMap from '../../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
import DashboardSideMenu from '../SideMenu';
import GlobalConfig from 'Model/Models/GlobalConfig';
import ObjectID from 'Common/Types/ObjectID';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
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 "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import GlobalConfig from "Model/Models/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: 'API Key',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_HOST] as Route
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<CardModelDetail
name="API Key Settings"
cardProps={{
title: 'Master API Key Settings',
description:
'This API key has root access to all the resources in all the projects on OneUptime.',
}}
isEditable={true}
editButtonText="Edit API Key Settings"
formFields={[
{
field: {
masterApiKey: true,
},
title: 'Master API Key',
fieldType: FormFieldSchemaType.ObjectID,
required: false,
},
{
field: {
isMasterApiKeyEnabled: true,
},
title: 'Enabled',
fieldType: FormFieldSchemaType.Toggle,
required: false,
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: 'model-detail-global-config',
fields: [
{
field: {
masterApiKey: true,
},
title: 'Master API Key',
description:
'This API key has root access to all the resources in all the projects on OneUptime.',
fieldType: FieldType.HiddenText,
opts: {
isCopyable: true,
},
placeholder: 'API Key not generated yet.',
},
{
field: {
isMasterApiKeyEnabled: true,
},
title: 'Enabled',
description:
'Enable or disable the master API key. If disabled, all requests using this key will fail.',
fieldType: FieldType.Boolean,
placeholder: 'Not Enabled',
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
</Page>
);
return (
<Page
title={"Admin Settings"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
},
{
title: "Settings",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route,
),
},
{
title: "API Key",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_HOST] as Route,
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<CardModelDetail
name="API Key Settings"
cardProps={{
title: "Master API Key Settings",
description:
"This API key has root access to all the resources in all the projects on OneUptime.",
}}
isEditable={true}
editButtonText="Edit API Key Settings"
formFields={[
{
field: {
masterApiKey: true,
},
title: "Master API Key",
fieldType: FormFieldSchemaType.ObjectID,
required: false,
},
{
field: {
isMasterApiKeyEnabled: true,
},
title: "Enabled",
fieldType: FormFieldSchemaType.Toggle,
required: false,
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config",
fields: [
{
field: {
masterApiKey: true,
},
title: "Master API Key",
description:
"This API key has root access to all the resources in all the projects on OneUptime.",
fieldType: FieldType.HiddenText,
opts: {
isCopyable: true,
},
placeholder: "API Key not generated yet.",
},
{
field: {
isMasterApiKeyEnabled: true,
},
title: "Enabled",
description:
"Enable or disable the master API key. If disabled, all requests using this key will fail.",
fieldType: FieldType.Boolean,
placeholder: "Not Enabled",
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
</Page>
);
};
export default Settings;

View File

@@ -1,83 +1,80 @@
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail';
import Page from 'CommonUI/src/Components/Page/Page';
import React, { FunctionComponent, ReactElement } from 'react';
import PageMap from '../../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
import DashboardSideMenu from '../SideMenu';
import GlobalConfig from 'Model/Models/GlobalConfig';
import ObjectID from 'Common/Types/ObjectID';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
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 "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import GlobalConfig from "Model/Models/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: 'Authentication',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_AUTHENTICATION] as Route
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<CardModelDetail
name="Authentication Settings"
cardProps={{
title: 'Authentication Settings',
description:
'Authentication Settings for this OneUptime Server instance.',
}}
isEditable={true}
editButtonText="Edit Settings"
formFields={[
{
field: {
disableSignup: true,
},
title: 'Disable Sign Up',
fieldType: FormFieldSchemaType.Toggle,
required: false,
description:
'Should we disable sign up of new users to OneUptime?',
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: 'model-detail-global-config',
fields: [
{
field: {
disableSignup: true,
},
fieldType: FieldType.Boolean,
title: 'Disable Sign Up',
placeholder: 'No',
description:
'Should we disable sign up of new users to OneUptime?',
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
</Page>
);
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: "Authentication",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_AUTHENTICATION] as Route,
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<CardModelDetail
name="Authentication Settings"
cardProps={{
title: "Authentication Settings",
description:
"Authentication Settings for this OneUptime Server instance.",
}}
isEditable={true}
editButtonText="Edit Settings"
formFields={[
{
field: {
disableSignup: true,
},
title: "Disable Sign Up",
fieldType: FormFieldSchemaType.Toggle,
required: false,
description: "Should we disable sign up of new users to OneUptime?",
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config",
fields: [
{
field: {
disableSignup: true,
},
fieldType: FieldType.Boolean,
title: "Disable Sign Up",
placeholder: "No",
description:
"Should we disable sign up of new users to OneUptime?",
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
</Page>
);
};
export default Settings;

View File

@@ -1,119 +1,114 @@
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail';
import Page from 'CommonUI/src/Components/Page/Page';
import React, { FunctionComponent, ReactElement } from 'react';
import PageMap from '../../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
import DashboardSideMenu from '../SideMenu';
import GlobalConfig from 'Model/Models/GlobalConfig';
import ObjectID from 'Common/Types/ObjectID';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
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 "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import GlobalConfig from "Model/Models/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: 'Calls and SMS',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_CALL_AND_SMS] as Route
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<CardModelDetail
name="Call and SMS Settings"
cardProps={{
title: 'Twilio Config',
description: 'This will be used to make Call and send SMS.',
}}
isEditable={true}
editButtonText="Edit Twilio Config"
formFields={[
{
field: {
twilioAccountSID: true,
},
title: 'Twilio Account SID',
fieldType: FormFieldSchemaType.Text,
required: true,
description:
'You can find this in your Twilio console.',
placeholder: '',
validation: {
minLength: 2,
},
},
{
field: {
twilioAuthToken: true,
},
title: 'Twilio Auth Token',
fieldType: FormFieldSchemaType.Text,
required: true,
description:
'You can find this in your Twilio console.',
placeholder: '',
validation: {
minLength: 2,
},
},
{
field: {
twilioPhoneNumber: true,
},
title: 'Twilio Phone Number',
fieldType: FormFieldSchemaType.Phone,
required: true,
description:
'You can find this in your Twilio console.',
placeholder: '',
validation: {
minLength: 2,
},
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: 'model-detail-global-config',
fields: [
{
field: {
twilioAccountSID: true,
},
title: 'Twilio Account SID',
placeholder: 'None',
},
{
field: {
twilioPhoneNumber: true,
},
title: 'Twilio Phone Number',
fieldType: FieldType.Phone,
placeholder: 'None',
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
</Page>
);
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: "Calls and SMS",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_CALL_AND_SMS] as Route,
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<CardModelDetail
name="Call and SMS Settings"
cardProps={{
title: "Twilio Config",
description: "This will be used to make Call and send SMS.",
}}
isEditable={true}
editButtonText="Edit Twilio Config"
formFields={[
{
field: {
twilioAccountSID: true,
},
title: "Twilio Account SID",
fieldType: FormFieldSchemaType.Text,
required: true,
description: "You can find this in your Twilio console.",
placeholder: "",
validation: {
minLength: 2,
},
},
{
field: {
twilioAuthToken: true,
},
title: "Twilio Auth Token",
fieldType: FormFieldSchemaType.Text,
required: true,
description: "You can find this in your Twilio console.",
placeholder: "",
validation: {
minLength: 2,
},
},
{
field: {
twilioPhoneNumber: true,
},
title: "Twilio Phone Number",
fieldType: FormFieldSchemaType.Phone,
required: true,
description: "You can find this in your Twilio console.",
placeholder: "",
validation: {
minLength: 2,
},
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config",
fields: [
{
field: {
twilioAccountSID: true,
},
title: "Twilio Account SID",
placeholder: "None",
},
{
field: {
twilioPhoneNumber: true,
},
title: "Twilio Phone Number",
fieldType: FieldType.Phone,
placeholder: "None",
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
</Page>
);
};
export default Settings;

View File

@@ -1,427 +1,419 @@
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail';
import Page from 'CommonUI/src/Components/Page/Page';
import React, { FunctionComponent, ReactElement, useEffect } from 'react';
import PageMap from '../../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
import DashboardSideMenu from '../SideMenu';
import GlobalConfig, { EmailServerType } from 'Model/Models/GlobalConfig';
import ObjectID from 'Common/Types/ObjectID';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
import ModelAPI from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
import PageLoader from 'CommonUI/src/Components/Loader/PageLoader';
import ErrorMessage from 'CommonUI/src/Components/ErrorMessage/ErrorMessage';
import DropdownUtil from 'CommonUI/src/Utils/Dropdown';
import Pill from 'CommonUI/src/Components/Pill/Pill';
import { Green, Red } from 'Common/Types/BrandColors';
import { PromiseVoidFunction } from 'Common/Types/FunctionTypes';
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import DashboardSideMenu from "../SideMenu";
import Route from "Common/Types/API/Route";
import { Green, Red } from "Common/Types/BrandColors";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import ObjectID from "Common/Types/ObjectID";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import Pill from "CommonUI/src/Components/Pill/Pill";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import DropdownUtil from "CommonUI/src/Utils/Dropdown";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import GlobalConfig, { EmailServerType } from "Model/Models/GlobalConfig";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
const Settings: FunctionComponent = (): ReactElement => {
const [emailServerType, setemailServerType] =
React.useState<EmailServerType>(EmailServerType.Internal);
const [emailServerType, setemailServerType] = React.useState<EmailServerType>(
EmailServerType.Internal,
);
const [isLoading, setIsLoading] = React.useState<boolean>(true);
const [isLoading, setIsLoading] = React.useState<boolean>(true);
const [error, setError] = React.useState<string>('');
const [error, setError] = React.useState<string>("");
const fetchItem: PromiseVoidFunction = async (): Promise<void> => {
setIsLoading(true);
const fetchItem: PromiseVoidFunction = async (): Promise<void> => {
setIsLoading(true);
const globalConfig: GlobalConfig | null =
await ModelAPI.getItem<GlobalConfig>({
modelType: GlobalConfig,
id: ObjectID.getZeroObjectID(),
select: {
_id: true,
emailServerType: true,
},
});
const globalConfig: GlobalConfig | null =
await ModelAPI.getItem<GlobalConfig>({
modelType: GlobalConfig,
id: ObjectID.getZeroObjectID(),
select: {
_id: true,
emailServerType: true,
},
});
if (globalConfig) {
setemailServerType(
globalConfig.emailServerType || EmailServerType.Internal
);
}
setIsLoading(false);
};
useEffect(() => {
fetchItem().catch((err: Error) => {
setError(err.message);
});
}, []);
if (isLoading) {
return <PageLoader isVisible={true} />;
if (globalConfig) {
setemailServerType(
globalConfig.emailServerType || EmailServerType.Internal,
);
}
if (error) {
return <ErrorMessage error={error} />;
}
setIsLoading(false);
};
return (
<Page
title={'Admin Settings'}
breadcrumbLinks={[
{
title: 'Admin Dashboard',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.HOME] as Route
),
useEffect(() => {
fetchItem().catch((err: Error) => {
setError(err.message);
});
}, []);
if (isLoading) {
return <PageLoader isVisible={true} />;
}
if (error) {
return <ErrorMessage error={error} />;
}
return (
<Page
title={"Admin Settings"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
},
{
title: "Settings",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route,
),
},
{
title: "Email Settings",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_SMTP] as Route,
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<CardModelDetail
name="Admin Notification Email"
cardProps={{
title: "Admin Notification Email",
description:
"Enter the email address where you would like to receive admin-level notifications.",
}}
isEditable={true}
editButtonText="Edit Email"
formFields={[
{
field: {
adminNotificationEmail: true,
},
title: "Admin Notification Email",
fieldType: FormFieldSchemaType.Email,
required: false,
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config",
fields: [
{
field: {
adminNotificationEmail: true,
},
title: "Admin Notification Email",
fieldType: FieldType.Email,
placeholder: "None",
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
<CardModelDetail
name="Internal SMTP Settings"
cardProps={{
title: "Email Server Settings",
description:
"Pick which email server you would like to use to send emails.",
}}
isEditable={true}
editButtonText="Edit Server"
onSaveSuccess={() => {
window.location.reload();
}}
formFields={[
{
field: {
emailServerType: true,
},
title: "Email Server Type",
fieldType: FormFieldSchemaType.Dropdown,
dropdownOptions:
DropdownUtil.getDropdownOptionsFromEnum(EmailServerType),
required: true,
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config",
fields: [
{
field: {
emailServerType: true,
},
title: "Email Server Type",
fieldType: FieldType.Text,
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
{emailServerType === EmailServerType.CustomSMTP ? (
<CardModelDetail
name="Host Settings"
cardProps={{
title: "Custom Email and SMTP Settings",
description:
"If you have not enabled Internal SMTP server to send emails. Please configure your SMTP server here.",
}}
isEditable={true}
editButtonText="Edit SMTP Config"
formSteps={[
{
title: "SMTP Server",
id: "server-info",
},
{
title: "Authentication",
id: "authentication",
},
{
title: "Email",
id: "email-info",
},
]}
formFields={[
{
field: {
smtpHost: true,
},
title: "Hostname",
stepId: "server-info",
fieldType: FormFieldSchemaType.Hostname,
required: true,
placeholder: "smtp.server.com",
},
{
field: {
smtpPort: true,
},
title: "Port",
stepId: "server-info",
fieldType: FormFieldSchemaType.Port,
required: true,
placeholder: "587",
},
{
field: {
isSMTPSecure: true,
},
title: "Use SSL / TLS",
stepId: "server-info",
fieldType: FormFieldSchemaType.Toggle,
description:
"If you use port 465, please enable this. Do not enable this if you use port 587.",
},
{
field: {
smtpUsername: true,
},
title: "Username",
stepId: "authentication",
fieldType: FormFieldSchemaType.Text,
required: false,
placeholder: "emailuser",
},
{
field: {
smtpPassword: true,
},
title: "Password",
stepId: "authentication",
fieldType: FormFieldSchemaType.EncryptedText,
required: false,
placeholder: "Password",
},
{
field: {
smtpFromEmail: true,
},
title: "Email From",
stepId: "email-info",
fieldType: FormFieldSchemaType.Email,
required: true,
description:
"This is the display email your team and customers see, when they receive emails from OneUptime.",
placeholder: "email@company.com",
},
{
field: {
smtpFromName: true,
},
title: "From Name",
stepId: "email-info",
fieldType: FormFieldSchemaType.Text,
required: true,
description:
"This is the display name your team and customers see, when they receive emails from OneUptime.",
placeholder: "Company, Inc.",
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config",
fields: [
{
field: {
smtpHost: true,
},
{
title: 'Settings',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route
),
title: "SMTP Host",
placeholder: "None",
},
{
field: {
smtpPort: true,
},
{
title: 'Email Settings',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_SMTP] as Route
),
title: "SMTP Port",
placeholder: "None",
},
{
field: {
smtpUsername: true,
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
title: "SMTP Username",
placeholder: "None",
},
{
field: {
smtpFromEmail: true,
},
title: "SMTP Email",
placeholder: "None",
fieldType: FieldType.Email,
},
{
field: {
smtpFromName: true,
},
title: "SMTP From Name",
placeholder: "None",
},
{
field: {
isSMTPSecure: true,
},
title: "Use SSL/TLS",
placeholder: "No",
fieldType: FieldType.Boolean,
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
) : (
<></>
)}
<CardModelDetail
name="Admin Notification Email"
cardProps={{
title: 'Admin Notification Email',
description:
'Enter the email address where you would like to receive admin-level notifications.',
}}
isEditable={true}
editButtonText="Edit Email"
formFields={[
{
field: {
adminNotificationEmail: true,
},
title: 'Admin Notification Email',
fieldType: FormFieldSchemaType.Email,
required: false,
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: 'model-detail-global-config',
fields: [
{
field: {
adminNotificationEmail: true,
},
title: 'Admin Notification Email',
fieldType: FieldType.Email,
placeholder: 'None',
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
{emailServerType === EmailServerType.Sendgrid ? (
<CardModelDetail<GlobalConfig>
name="Sendgrid Settings"
cardProps={{
title: "Sendgrid Settings",
description:
"Enter your Sendgrid API key to send emails through Sendgrid.",
}}
isEditable={true}
editButtonText="Edit API Key"
formFields={[
{
field: {
sendgridApiKey: true,
},
title: "Sendgrid API Key",
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: "Sendgrid API Key",
},
{
field: {
sendgridFromEmail: true,
},
title: "From Email",
fieldType: FormFieldSchemaType.Email,
required: true,
placeholder: "email@yourcompany.com",
},
{
field: {
sendgridFromName: true,
},
title: "From Name",
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: "Acme, Inc.",
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: "model-detail-global-config",
selectMoreFields: {
sendgridFromEmail: true,
sendgridFromName: true,
},
fields: [
{
field: {
sendgridApiKey: true,
},
title: "",
placeholder: "None",
getElement: (item: GlobalConfig) => {
if (
item["sendgridApiKey"] &&
item["sendgridFromEmail"] &&
item["sendgridFromName"]
) {
return <Pill text="Enabled" color={Green} />;
} else if (!item["sendgridApiKey"]) {
return (
<Pill
text="Not Enabled. Please add the API key."
color={Red}
/>
);
} else if (!item["sendgridFromEmail"]) {
return (
<Pill
text="Not Enabled. Please add the From Email."
color={Red}
/>
);
} else if (!item["sendgridFromName"]) {
return (
<Pill
text="Not Enabled. Please add the From Name."
color={Red}
/>
);
}
<CardModelDetail
name="Internal SMTP Settings"
cardProps={{
title: 'Email Server Settings',
description:
'Pick which email server you would like to use to send emails.',
}}
isEditable={true}
editButtonText="Edit Server"
onSaveSuccess={() => {
window.location.reload();
}}
formFields={[
{
field: {
emailServerType: true,
},
title: 'Email Server Type',
fieldType: FormFieldSchemaType.Dropdown,
dropdownOptions:
DropdownUtil.getDropdownOptionsFromEnum(
EmailServerType
),
required: true,
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: 'model-detail-global-config',
fields: [
{
field: {
emailServerType: true,
},
title: 'Email Server Type',
fieldType: FieldType.Text,
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
{emailServerType === EmailServerType.CustomSMTP ? (
<CardModelDetail
name="Host Settings"
cardProps={{
title: 'Custom Email and SMTP Settings',
description:
'If you have not enabled Internal SMTP server to send emails. Please configure your SMTP server here.',
}}
isEditable={true}
editButtonText="Edit SMTP Config"
formSteps={[
{
title: 'SMTP Server',
id: 'server-info',
},
{
title: 'Authentication',
id: 'authentication',
},
{
title: 'Email',
id: 'email-info',
},
]}
formFields={[
{
field: {
smtpHost: true,
},
title: 'Hostname',
stepId: 'server-info',
fieldType: FormFieldSchemaType.Hostname,
required: true,
placeholder: 'smtp.server.com',
},
{
field: {
smtpPort: true,
},
title: 'Port',
stepId: 'server-info',
fieldType: FormFieldSchemaType.Port,
required: true,
placeholder: '587',
},
{
field: {
isSMTPSecure: true,
},
title: 'Use SSL / TLS',
stepId: 'server-info',
fieldType: FormFieldSchemaType.Toggle,
description:
'If you use port 465, please enable this. Do not enable this if you use port 587.',
},
{
field: {
smtpUsername: true,
},
title: 'Username',
stepId: 'authentication',
fieldType: FormFieldSchemaType.Text,
required: false,
placeholder: 'emailuser',
},
{
field: {
smtpPassword: true,
},
title: 'Password',
stepId: 'authentication',
fieldType: FormFieldSchemaType.EncryptedText,
required: false,
placeholder: 'Password',
},
{
field: {
smtpFromEmail: true,
},
title: 'Email From',
stepId: 'email-info',
fieldType: FormFieldSchemaType.Email,
required: true,
description:
'This is the display email your team and customers see, when they receive emails from OneUptime.',
placeholder: 'email@company.com',
},
{
field: {
smtpFromName: true,
},
title: 'From Name',
stepId: 'email-info',
fieldType: FormFieldSchemaType.Text,
required: true,
description:
'This is the display name your team and customers see, when they receive emails from OneUptime.',
placeholder: 'Company, Inc.',
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: 'model-detail-global-config',
fields: [
{
field: {
smtpHost: true,
},
title: 'SMTP Host',
placeholder: 'None',
},
{
field: {
smtpPort: true,
},
title: 'SMTP Port',
placeholder: 'None',
},
{
field: {
smtpUsername: true,
},
title: 'SMTP Username',
placeholder: 'None',
},
{
field: {
smtpFromEmail: true,
},
title: 'SMTP Email',
placeholder: 'None',
fieldType: FieldType.Email,
},
{
field: {
smtpFromName: true,
},
title: 'SMTP From Name',
placeholder: 'None',
},
{
field: {
isSMTPSecure: true,
},
title: 'Use SSL/TLS',
placeholder: 'No',
fieldType: FieldType.Boolean,
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
) : (
<></>
)}
{emailServerType === EmailServerType.Sendgrid ? (
<CardModelDetail<GlobalConfig>
name="Sendgrid Settings"
cardProps={{
title: 'Sendgrid Settings',
description:
'Enter your Sendgrid API key to send emails through Sendgrid.',
}}
isEditable={true}
editButtonText="Edit API Key"
formFields={[
{
field: {
sendgridApiKey: true,
},
title: 'Sendgrid API Key',
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: 'Sendgrid API Key',
},
{
field: {
sendgridFromEmail: true,
},
title: 'From Email',
fieldType: FormFieldSchemaType.Email,
required: true,
placeholder: 'email@yourcompany.com',
},
{
field: {
sendgridFromName: true,
},
title: 'From Name',
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: 'Acme, Inc.',
},
]}
modelDetailProps={{
modelType: GlobalConfig,
id: 'model-detail-global-config',
selectMoreFields: {
sendgridFromEmail: true,
sendgridFromName: true,
},
fields: [
{
field: {
sendgridApiKey: true,
},
title: '',
placeholder: 'None',
getElement: (item: GlobalConfig) => {
if (
item['sendgridApiKey'] &&
item['sendgridFromEmail'] &&
item['sendgridFromName']
) {
return (
<Pill
text="Enabled"
color={Green}
/>
);
} else if (!item['sendgridApiKey']) {
return (
<Pill
text="Not Enabled. Please add the API key."
color={Red}
/>
);
} else if (!item['sendgridFromEmail']) {
return (
<Pill
text="Not Enabled. Please add the From Email."
color={Red}
/>
);
} else if (!item['sendgridFromName']) {
return (
<Pill
text="Not Enabled. Please add the From Name."
color={Red}
/>
);
}
return <></>;
},
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
) : (
<></>
)}
</Page>
);
return <></>;
},
},
],
modelId: ObjectID.getZeroObjectID(),
}}
/>
) : (
<></>
)}
</Page>
);
};
export default Settings;

View File

@@ -1,251 +1,243 @@
import Route from 'Common/Types/API/Route';
import Page from 'CommonUI/src/Components/Page/Page';
import React, { FunctionComponent, ReactElement, useState } from 'react';
import PageMap from '../../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
import DashboardSideMenu from '../SideMenu';
import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable';
import Probe from 'Model/Models/Probe';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
import OneUptimeDate from 'Common/Types/Date';
import { Green, Red } from 'Common/Types/BrandColors';
import Statusbubble from 'CommonUI/src/Components/StatusBubble/StatusBubble';
import ProbeElement from 'CommonUI/src/Components/Probe/Probe';
import IsNull from 'Common/Types/BaseDatabase/IsNull';
import Banner from 'CommonUI/src/Components/Banner/Banner';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import { ButtonStyleType } from 'CommonUI/src/Components/Button/Button';
import ConfirmModal from 'CommonUI/src/Components/Modal/ConfirmModal';
import AdminModelAPI from '../../../Utils/ModelAPI';
import { ErrorFunction, VoidFunction } from 'Common/Types/FunctionTypes';
import AdminModelAPI from "../../../Utils/ModelAPI";
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import DashboardSideMenu from "../SideMenu";
import Route from "Common/Types/API/Route";
import IsNull from "Common/Types/BaseDatabase/IsNull";
import { Green, Red } from "Common/Types/BrandColors";
import OneUptimeDate from "Common/Types/Date";
import { ErrorFunction, VoidFunction } from "Common/Types/FunctionTypes";
import Banner from "CommonUI/src/Components/Banner/Banner";
import { ButtonStyleType } from "CommonUI/src/Components/Button/Button";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ConfirmModal from "CommonUI/src/Components/Modal/ConfirmModal";
import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import Page from "CommonUI/src/Components/Page/Page";
import ProbeElement from "CommonUI/src/Components/Probe/Probe";
import Statusbubble from "CommonUI/src/Components/StatusBubble/StatusBubble";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import Probe from "Model/Models/Probe";
import React, { FunctionComponent, ReactElement, useState } from "react";
const Settings: FunctionComponent = (): ReactElement => {
const [showKeyModal, setShowKeyModal] = useState<boolean>(false);
const [showKeyModal, setShowKeyModal] = useState<boolean>(false);
const [currentProbe, setCurrentProbe] = useState<Probe | null>(null);
const [currentProbe, setCurrentProbe] = useState<Probe | null>(null);
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: 'Global Probes',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_PROBES] as Route
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
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: "Global Probes",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_PROBES] as Route,
),
},
]}
sideMenu={<DashboardSideMenu />}
>
{/* Project Settings View */}
<Banner
openInNewTab={true}
title="Need help with setting up Global Probes?"
description="Here is a guide which will help you get set up"
link={Route.fromString('/docs/probe/custom-probe')}
/>
<Banner
openInNewTab={true}
title="Need help with setting up Global Probes?"
description="Here is a guide which will help you get set up"
link={Route.fromString("/docs/probe/custom-probe")}
/>
<ModelTable<Probe>
modelType={Probe}
id="probes-table"
name="Settings > Global Probes"
isDeleteable={true}
isEditable={true}
isCreateable={true}
cardProps={{
title: 'Global Probes',
description:
'Global Probes help you monitor external resources from different locations around the world.',
}}
query={{
projectId: new IsNull(),
isGlobalProbe: true,
}}
modelAPI={AdminModelAPI}
noItemsMessage={'No probes found.'}
showRefreshButton={true}
onBeforeCreate={(item: Probe) => {
item.isGlobalProbe = true;
return Promise.resolve(item);
}}
formFields={[
{
field: {
name: true,
},
title: 'Name',
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: 'internal-probe',
validation: {
minLength: 2,
},
},
<ModelTable<Probe>
modelType={Probe}
id="probes-table"
name="Settings > Global Probes"
isDeleteable={true}
isEditable={true}
isCreateable={true}
cardProps={{
title: "Global Probes",
description:
"Global Probes help you monitor external resources from different locations around the world.",
}}
query={{
projectId: new IsNull(),
isGlobalProbe: true,
}}
modelAPI={AdminModelAPI}
noItemsMessage={"No probes found."}
showRefreshButton={true}
onBeforeCreate={(item: Probe) => {
item.isGlobalProbe = true;
return Promise.resolve(item);
}}
formFields={[
{
field: {
name: true,
},
title: "Name",
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: "internal-probe",
validation: {
minLength: 2,
},
},
{
field: {
description: true,
},
title: 'Description',
fieldType: FormFieldSchemaType.LongText,
required: true,
placeholder:
'This probe is to monitor all the internal services.',
},
{
field: {
description: true,
},
title: "Description",
fieldType: FormFieldSchemaType.LongText,
required: true,
placeholder: "This probe is to monitor all the internal services.",
},
{
field: {
iconFile: true,
},
title: 'Probe Logo',
fieldType: FormFieldSchemaType.ImageFile,
required: false,
placeholder: 'Upload logo',
},
]}
selectMoreFields={{
key: true,
iconFileId: true,
}}
actionButtons={[
{
title: 'Show ID and Key',
buttonStyleType: ButtonStyleType.NORMAL,
onClick: async (
item: Probe,
onCompleteAction: VoidFunction,
onError: ErrorFunction
) => {
try {
setCurrentProbe(item);
setShowKeyModal(true);
{
field: {
iconFile: true,
},
title: "Probe Logo",
fieldType: FormFieldSchemaType.ImageFile,
required: false,
placeholder: "Upload logo",
},
]}
selectMoreFields={{
key: true,
iconFileId: true,
}}
actionButtons={[
{
title: "Show ID and Key",
buttonStyleType: ButtonStyleType.NORMAL,
onClick: async (
item: Probe,
onCompleteAction: VoidFunction,
onError: ErrorFunction,
) => {
try {
setCurrentProbe(item);
setShowKeyModal(true);
onCompleteAction();
} catch (err) {
onCompleteAction();
onError(err as Error);
}
},
},
]}
filters={[
{
field: {
name: true,
},
title: 'Name',
type: FieldType.Text,
},
{
field: {
description: true,
},
title: 'Description',
type: FieldType.Text,
},
]}
columns={[
{
field: {
name: true,
},
title: 'Name',
type: FieldType.Text,
onCompleteAction();
} catch (err) {
onCompleteAction();
onError(err as Error);
}
},
},
]}
filters={[
{
field: {
name: true,
},
title: "Name",
type: FieldType.Text,
},
{
field: {
description: true,
},
title: "Description",
type: FieldType.Text,
},
]}
columns={[
{
field: {
name: true,
},
title: "Name",
type: FieldType.Text,
getElement: (item: Probe): ReactElement => {
return <ProbeElement probe={item} />;
},
},
{
field: {
description: true,
},
title: 'Description',
type: FieldType.Text,
},
{
field: {
lastAlive: true,
},
title: 'Status',
type: FieldType.Text,
getElement: (item: Probe): ReactElement => {
if (
item &&
item['lastAlive'] &&
OneUptimeDate.getNumberOfMinutesBetweenDates(
OneUptimeDate.fromString(item['lastAlive']),
OneUptimeDate.getCurrentDate()
) < 5
) {
return (
<Statusbubble
text={'Connected'}
color={Green}
shouldAnimate={true}
/>
);
}
getElement: (item: Probe): ReactElement => {
return <ProbeElement probe={item} />;
},
},
{
field: {
description: true,
},
title: "Description",
type: FieldType.Text,
},
{
field: {
lastAlive: true,
},
title: "Status",
type: FieldType.Text,
getElement: (item: Probe): ReactElement => {
if (
item &&
item["lastAlive"] &&
OneUptimeDate.getNumberOfMinutesBetweenDates(
OneUptimeDate.fromString(item["lastAlive"]),
OneUptimeDate.getCurrentDate(),
) < 5
) {
return (
<Statusbubble
text={"Connected"}
color={Green}
shouldAnimate={true}
/>
);
}
return (
<Statusbubble
text={'Disconnected'}
color={Red}
shouldAnimate={false}
/>
);
},
},
]}
/>
{showKeyModal && currentProbe ? (
<ConfirmModal
title={`Probe Key`}
description={
<div>
<span>
Here is your probe key. Please keep this a
secret.
</span>
<br />
<br />
<span>
<b>Probe ID: </b>{' '}
{currentProbe['_id']?.toString()}
</span>
<br />
<br />
<span>
<b>Probe Key: </b>{' '}
{currentProbe['key']?.toString()}
</span>
</div>
}
submitButtonText={'Close'}
submitButtonType={ButtonStyleType.NORMAL}
onSubmit={async () => {
setShowKeyModal(false);
}}
return (
<Statusbubble
text={"Disconnected"}
color={Red}
shouldAnimate={false}
/>
) : (
<></>
)}
</Page>
);
);
},
},
]}
/>
{showKeyModal && currentProbe ? (
<ConfirmModal
title={`Probe Key`}
description={
<div>
<span>Here is your probe key. Please keep this a secret.</span>
<br />
<br />
<span>
<b>Probe ID: </b> {currentProbe["_id"]?.toString()}
</span>
<br />
<br />
<span>
<b>Probe Key: </b> {currentProbe["key"]?.toString()}
</span>
</div>
}
submitButtonText={"Close"}
submitButtonType={ButtonStyleType.NORMAL}
onSubmit={async () => {
setShowKeyModal(false);
}}
/>
) : (
<></>
)}
</Page>
);
};
export default Settings;

View File

@@ -1,17 +1,17 @@
import React, { ReactElement } from 'react';
import Route from 'Common/Types/API/Route';
import IconProp from 'Common/Types/Icon/IconProp';
import SideMenu from 'CommonUI/src/Components/SideMenu/SideMenu';
import SideMenuItem from 'CommonUI/src/Components/SideMenu/SideMenuItem';
import SideMenuSection from 'CommonUI/src/Components/SideMenu/SideMenuSection';
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
import PageMap from '../../Utils/PageMap';
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import IconProp from "Common/Types/Icon/IconProp";
import SideMenu from "CommonUI/src/Components/SideMenu/SideMenu";
import SideMenuItem from "CommonUI/src/Components/SideMenu/SideMenuItem";
import SideMenuSection from "CommonUI/src/Components/SideMenu/SideMenuSection";
import React, { ReactElement } from "react";
const DashboardSideMenu: () => JSX.Element = (): ReactElement => {
return (
<SideMenu>
<SideMenuSection title="Basic">
{/* <SideMenuItem
return (
<SideMenu>
<SideMenuSection title="Basic">
{/* <SideMenuItem
link={{
title: 'Host',
to: RouteUtil.populateRouteParams(
@@ -20,62 +20,62 @@ const DashboardSideMenu: () => JSX.Element = (): ReactElement => {
}}
icon={IconProp.Globe}
/> */}
<SideMenuItem
link={{
title: 'Authentication',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_AUTHENTICATION] as Route
),
}}
icon={IconProp.Lock}
/>
</SideMenuSection>
<SideMenuItem
link={{
title: "Authentication",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_AUTHENTICATION] as Route,
),
}}
icon={IconProp.Lock}
/>
</SideMenuSection>
<SideMenuSection title="Notifications">
<SideMenuItem
link={{
title: 'Emails',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_SMTP] as Route
),
}}
icon={IconProp.Email}
/>
<SideMenuItem
link={{
title: 'Call and SMS',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_CALL_AND_SMS] as Route
),
}}
icon={IconProp.Call}
/>
</SideMenuSection>
<SideMenuSection title="Notifications">
<SideMenuItem
link={{
title: "Emails",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_SMTP] as Route,
),
}}
icon={IconProp.Email}
/>
<SideMenuItem
link={{
title: "Call and SMS",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_CALL_AND_SMS] as Route,
),
}}
icon={IconProp.Call}
/>
</SideMenuSection>
<SideMenuSection title="Monitoring">
<SideMenuItem
link={{
title: 'Global Probes',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_PROBES] as Route
),
}}
icon={IconProp.Signal}
/>
</SideMenuSection>
<SideMenuSection title="API and Integrations">
<SideMenuItem
link={{
title: 'API Key',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_API_KEY] as Route
),
}}
icon={IconProp.Code}
/>
</SideMenuSection>
</SideMenu>
);
<SideMenuSection title="Monitoring">
<SideMenuItem
link={{
title: "Global Probes",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_PROBES] as Route,
),
}}
icon={IconProp.Signal}
/>
</SideMenuSection>
<SideMenuSection title="API and Integrations">
<SideMenuItem
link={{
title: "API Key",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_API_KEY] as Route,
),
}}
icon={IconProp.Code}
/>
</SideMenuSection>
</SideMenu>
);
};
export default DashboardSideMenu;

View File

@@ -1,127 +1,218 @@
import Route from 'Common/Types/API/Route';
import Page from 'CommonUI/src/Components/Page/Page';
import React, { FunctionComponent, ReactElement } from 'react';
import PageMap from '../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import Navigation from 'CommonUI/src/Utils/Navigation';
import User from 'Model/Models/User';
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import { ErrorFunction } from "Common/Types/FunctionTypes";
import { ButtonStyleType } from "CommonUI/src/Components/Button/Button";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ConfirmModal from "CommonUI/src/Components/Modal/ConfirmModal";
import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import API from "CommonUI/src/Utils/API/API";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "Model/Models/User";
import React, { FunctionComponent, ReactElement, useState } from "react";
const Users: FunctionComponent = (): ReactElement => {
return (
<Page
title={'Users'}
breadcrumbLinks={[
{
title: 'Admin Dashboard',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.HOME] as Route
),
const [showConfirmVerifyEmailModal, setShowConfirmVerifyEmailModal] =
useState<boolean>(false);
const [selectedUser, setSelectedUser] = useState<User | null>(null);
const [error, setError] = useState<string | null>(null);
const [isConfimModalLoading, setIsConfirmModalLoading] =
useState<boolean>(false);
const [refreshItemsTrigger, setRefreshItemsTrigger] =
useState<boolean>(false);
return (
<Page
title={"Users"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
},
{
title: "Users",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.USERS] as Route),
},
]}
>
<ModelTable<User>
modelType={User}
id="users-table"
isDeleteable={false}
isEditable={false}
showViewIdButton={true}
refreshToggle={refreshItemsTrigger}
isCreateable={true}
name="Users"
isViewable={false}
cardProps={{
title: "Users",
description: "Here is a list of users in OneUptime.",
}}
actionButtons={[
{
title: "Verify Email",
buttonStyleType: ButtonStyleType.NORMAL,
isVisible: (item: User) => {
return !item.isEmailVerified;
},
onClick: async (
item: User,
onCompleteAction: VoidFunction,
onError: ErrorFunction,
) => {
try {
setSelectedUser(item);
setShowConfirmVerifyEmailModal(true);
onCompleteAction();
} catch (err) {
onCompleteAction();
onError(err as Error);
}
},
},
]}
noItemsMessage={"No users found."}
formFields={[
{
field: {
email: true,
},
title: "Email",
fieldType: FormFieldSchemaType.Email,
required: true,
placeholder: "email@company.com",
},
{
field: {
password: true,
},
title: "Password",
fieldType: FormFieldSchemaType.Password,
required: true,
placeholder: "Password",
},
{
field: {
name: true,
},
title: "Full Name",
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: "John Smith",
},
]}
showRefreshButton={true}
viewPageRoute={Navigation.getCurrentRoute()}
filters={[
{
field: {
name: true,
},
title: "Full Name",
type: FieldType.Text,
},
{
field: {
email: true,
},
title: "Email",
type: FieldType.Email,
},
{
field: {
createdAt: true,
},
title: "Created At",
type: FieldType.DateTime,
},
]}
columns={[
{
field: {
name: true,
},
title: "Full Name",
type: FieldType.Text,
},
{
field: {
email: true,
},
title: "Email",
type: FieldType.Email,
},
{
field: {
isEmailVerified: true,
},
title: "Email Verified",
type: FieldType.Boolean,
},
{
field: {
createdAt: true,
},
title: "Created At",
type: FieldType.DateTime,
},
]}
/>
{error ? (
<ConfirmModal
title={`Error`}
description={error}
submitButtonText={"Close"}
onSubmit={async () => {
setError(null);
}}
submitButtonType={ButtonStyleType.NORMAL}
/>
) : (
<></>
)}
{showConfirmVerifyEmailModal && selectedUser ? (
<ConfirmModal
title={`Verify Email`}
description={`Are you sure you want to verify the email - ${selectedUser.email}?`}
isLoading={isConfimModalLoading}
submitButtonText={"Verify Email"}
onClose={async () => {
setShowConfirmVerifyEmailModal(false);
setSelectedUser(null);
}}
onSubmit={async () => {
try {
setIsConfirmModalLoading(true);
await ModelAPI.updateById<User>({
modelType: User,
id: selectedUser.id!,
data: {
isEmailVerified: true,
},
{
title: 'Users',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.USERS] as Route
),
},
]}
>
<ModelTable<User>
modelType={User}
id="users-table"
isDeleteable={false}
isEditable={false}
showViewIdButton={true}
isCreateable={true}
name="Users"
isViewable={false}
cardProps={{
title: 'Users',
description: 'Here is a list of users in OneUptime.',
}}
noItemsMessage={'No users found.'}
formFields={[
{
field: {
email: true,
},
title: 'Email',
fieldType: FormFieldSchemaType.Email,
required: true,
placeholder: 'email@company.com',
},
{
field: {
password: true,
},
title: 'Password',
fieldType: FormFieldSchemaType.Password,
required: true,
placeholder: 'Password',
},
{
field: {
name: true,
},
title: 'Full Name',
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: 'John Smith',
},
]}
showRefreshButton={true}
viewPageRoute={Navigation.getCurrentRoute()}
filters={[
{
field: {
name: true,
},
title: 'Full Name',
type: FieldType.Text,
},
{
field: {
email: true,
},
title: 'Email',
type: FieldType.Email,
},
{
field: {
createdAt: true,
},
title: 'Created At',
type: FieldType.DateTime,
},
]}
columns={[
{
field: {
name: true,
},
title: 'Full Name',
type: FieldType.Text,
},
{
field: {
email: true,
},
title: 'Email',
type: FieldType.Email,
},
{
field: {
createdAt: true,
},
title: 'Created At',
type: FieldType.DateTime,
},
]}
/>
</Page>
);
});
} catch (err) {
setError(API.getFriendlyMessage(err as Error));
}
setRefreshItemsTrigger(!refreshItemsTrigger);
setIsConfirmModalLoading(false);
setShowConfirmVerifyEmailModal(false);
}}
/>
) : (
<></>
)}
</Page>
);
};
export default Users;

View File

@@ -1,8 +1,8 @@
import Dictionary from 'Common/Types/Dictionary';
import ModelAPI from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
import Dictionary from "Common/Types/Dictionary";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
export default class AdminModelAPI extends ModelAPI {
public static override getCommonHeaders(): Dictionary<string> {
return {};
}
public static override getCommonHeaders(): Dictionary<string> {
return {};
}
}

View File

@@ -1,17 +1,17 @@
enum PageMap {
INIT = 'INIT',
HOME = 'HOME',
LOGOUT = 'LOGOUT',
SETTINGS = 'SETTINGS',
USERS = 'USERS',
PROJECTS = 'PROJECTS',
INIT = "INIT",
HOME = "HOME",
LOGOUT = "LOGOUT",
SETTINGS = "SETTINGS",
USERS = "USERS",
PROJECTS = "PROJECTS",
SETTINGS_HOST = 'SETTINGS_HOST',
SETTINGS_SMTP = 'SETTINGS_SMTP',
SETTINGS_CALL_AND_SMS = 'SETTINGS_CALL_AND_SMS',
SETTINGS_PROBES = 'SETTINGS_PROBES',
SETTINGS_AUTHENTICATION = 'SETTINGS_AUTHENTICATION',
SETTINGS_API_KEY = 'SETTINGS_API_KEY',
SETTINGS_HOST = "SETTINGS_HOST",
SETTINGS_SMTP = "SETTINGS_SMTP",
SETTINGS_CALL_AND_SMS = "SETTINGS_CALL_AND_SMS",
SETTINGS_PROBES = "SETTINGS_PROBES",
SETTINGS_AUTHENTICATION = "SETTINGS_AUTHENTICATION",
SETTINGS_API_KEY = "SETTINGS_API_KEY",
}
export default PageMap;

View File

@@ -1,54 +1,54 @@
import Route from 'Common/Types/API/Route';
import Dictionary from 'Common/Types/Dictionary';
import PageMap from './PageMap';
import RouteParams from './RouteParams';
import ObjectID from 'Common/Types/ObjectID';
import PageMap from "./PageMap";
import RouteParams from "./RouteParams";
import Route from "Common/Types/API/Route";
import Dictionary from "Common/Types/Dictionary";
import ObjectID from "Common/Types/ObjectID";
const RouteMap: Dictionary<Route> = {
[PageMap.INIT]: new Route(`/admin`),
[PageMap.HOME]: new Route(`/admin`),
[PageMap.LOGOUT]: new Route(`/admin/logout`),
[PageMap.SETTINGS]: new Route(`/admin/settings/host`),
[PageMap.PROJECTS]: new Route(`/admin/projects`),
[PageMap.USERS]: new Route(`/admin/users`),
[PageMap.SETTINGS_HOST]: new Route(`/admin/settings/host`),
[PageMap.SETTINGS_SMTP]: new Route(`/admin/settings/smtp`),
[PageMap.SETTINGS_CALL_AND_SMS]: new Route(`/admin/settings/call-and-sms`),
[PageMap.SETTINGS_PROBES]: new Route(`/admin/settings/probes`),
[PageMap.SETTINGS_AUTHENTICATION]: new Route(
`/admin/settings/authentication`
),
[PageMap.SETTINGS_API_KEY]: new Route(`/admin/settings/api-key`),
[PageMap.INIT]: new Route(`/admin`),
[PageMap.HOME]: new Route(`/admin`),
[PageMap.LOGOUT]: new Route(`/admin/logout`),
[PageMap.SETTINGS]: new Route(`/admin/settings/host`),
[PageMap.PROJECTS]: new Route(`/admin/projects`),
[PageMap.USERS]: new Route(`/admin/users`),
[PageMap.SETTINGS_HOST]: new Route(`/admin/settings/host`),
[PageMap.SETTINGS_SMTP]: new Route(`/admin/settings/smtp`),
[PageMap.SETTINGS_CALL_AND_SMS]: new Route(`/admin/settings/call-and-sms`),
[PageMap.SETTINGS_PROBES]: new Route(`/admin/settings/probes`),
[PageMap.SETTINGS_AUTHENTICATION]: new Route(
`/admin/settings/authentication`,
),
[PageMap.SETTINGS_API_KEY]: new Route(`/admin/settings/api-key`),
};
export class RouteUtil {
public static populateRouteParams(
route: Route,
props?: {
modelId?: ObjectID;
subModelId?: ObjectID;
}
): Route {
// populate projectid
public static populateRouteParams(
route: Route,
props?: {
modelId?: ObjectID;
subModelId?: ObjectID;
},
): Route {
// populate projectid
const tempRoute: Route = new Route(route.toString());
const tempRoute: Route = new Route(route.toString());
if (props && props.modelId) {
route = tempRoute.addRouteParam(
RouteParams.ModelID,
props.modelId.toString()
);
}
if (props && props.subModelId) {
route = tempRoute.addRouteParam(
RouteParams.SubModelID,
props.subModelId.toString()
);
}
return tempRoute;
if (props && props.modelId) {
route = tempRoute.addRouteParam(
RouteParams.ModelID,
props.modelId.toString(),
);
}
if (props && props.subModelId) {
route = tempRoute.addRouteParam(
RouteParams.SubModelID,
props.subModelId.toString(),
);
}
return tempRoute;
}
}
export default RouteMap;

View File

@@ -1,6 +1,6 @@
enum RouteParams {
ModelID = ':id',
SubModelID = ':subModelId',
ModelID = ":id",
SubModelID = ":subModelId",
}
export default RouteParams;

View File

@@ -1,82 +1,84 @@
require('ts-loader');
require('file-loader');
require('style-loader');
require('css-loader');
require('sass-loader');
require("ts-loader");
require("file-loader");
require("style-loader");
require("css-loader");
require("sass-loader");
const path = require("path");
const webpack = require("webpack");
const dotenv = require('dotenv');
const express = require('express');
const dotenv = require("dotenv");
const express = require("express");
const readEnvFile = (pathToFile) => {
const parsed = dotenv.config({ path: pathToFile }).parsed;
const parsed = dotenv.config({ path: pathToFile }).parsed;
const env = {};
const env = {};
for (const key in parsed) {
env[key] = JSON.stringify(parsed[key]);
}
for (const key in parsed) {
env[key] = JSON.stringify(parsed[key]);
}
return env;
}
return env;
};
module.exports = {
entry: "./src/Index.tsx",
mode: "development",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "public", "dist"),
publicPath: "/admin/dist/",
entry: "./src/Index.tsx",
mode: "development",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "public", "dist"),
publicPath: "/admin/dist/",
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx", ".json", ".css", ".scss"],
alias: {
react: path.resolve("./node_modules/react"),
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.css', '.scss'],
alias: {
react: path.resolve('./node_modules/react'),
}
},
externals: {
'react-native-sqlite-storage': 'react-native-sqlite-storage'
},
plugins: [
new webpack.DefinePlugin({
'process': {
'env': {
...readEnvFile('/usr/src/app/dev-env/.env')
}
}
}),
],
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: 'ts-loader'
},
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', "sass-loader"]
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: 'file-loader'
}
],
},
devServer: {
historyApiFallback: true,
devMiddleware: {
writeToDisk: true,
},
externals: {
"react-native-sqlite-storage": "react-native-sqlite-storage",
},
plugins: [
new webpack.DefinePlugin({
process: {
env: {
...readEnvFile("/usr/src/app/dev-env/.env"),
},
allowedHosts: "all",
setupMiddlewares: (middlewares, devServer) => {
devServer.app.use('/admin/assets', express.static(path.resolve(__dirname, 'public', 'assets')));
return middlewares;
}
},
}),
],
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: "ts-loader",
},
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: "file-loader",
},
],
},
devServer: {
historyApiFallback: true,
devMiddleware: {
writeToDisk: true,
},
devtool: 'eval-source-map',
}
allowedHosts: "all",
setupMiddlewares: (middlewares, devServer) => {
devServer.app.use(
"/admin/assets",
express.static(path.resolve(__dirname, "public", "assets")),
);
return middlewares;
},
},
devtool: "eval-source-map",
};

View File

@@ -1,89 +1,83 @@
import AuthenticationServiceHandler from "./Service/Authentication";
import DataTypeServiceHandler from "./Service/DataType";
import ErrorServiceHandler from "./Service/Errors";
import IntroductionServiceHandler from "./Service/Introduction";
import ModelServiceHandler from "./Service/Model";
import PageNotFoundServiceHandler from "./Service/PageNotFound";
import PaginationServiceHandler from "./Service/Pagination";
import PermissionServiceHandler from "./Service/Permissions";
import StatusServiceHandler from "./Service/Status";
import { StaticPath } from "./Utils/Config";
import ResourceUtil, { ModelDocumentation } from "./Utils/Resources";
import Dictionary from "Common/Types/Dictionary";
import FeatureSet from "CommonServer/Types/FeatureSet";
import Express, {
ExpressApplication,
ExpressRequest,
ExpressResponse,
ExpressStatic,
} from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from './Utils/Resources';
import IntroductionServiceHandler from './Service/Introduction';
import ErrorServiceHandler from './Service/Errors';
import PermissionServiceHandler from './Service/Permissions';
import AuthenticationServiceHandler from './Service/Authentication';
import PageNotFoundServiceHandler from './Service/PageNotFound';
import ModelServiceHandler from './Service/Model';
import PaginationServiceHandler from './Service/Pagination';
import StatusServiceHandler from './Service/Status';
import DataTypeServiceHandler from './Service/DataType';
import Dictionary from 'Common/Types/Dictionary';
import { StaticPath } from './Utils/Config';
import FeatureSet from 'CommonServer/Types/FeatureSet';
ExpressApplication,
ExpressRequest,
ExpressResponse,
ExpressStatic,
} from "CommonServer/Utils/Express";
const APIReferenceFeatureSet: FeatureSet = {
init: async (): Promise<void> => {
const ResourceDictionary: Dictionary<ModelDocumentation> =
ResourceUtil.getResourceDictionaryByPath();
init: async (): Promise<void> => {
const ResourceDictionary: Dictionary<ModelDocumentation> =
ResourceUtil.getResourceDictionaryByPath();
const app: ExpressApplication = Express.getExpressApp();
const app: ExpressApplication = Express.getExpressApp();
app.use('/reference', ExpressStatic(StaticPath, { maxAge: 2592000 }));
app.use("/reference", ExpressStatic(StaticPath, { maxAge: 2592000 }));
// Index page
app.get(
['/reference'],
(_req: ExpressRequest, res: ExpressResponse) => {
return res.redirect('/reference/introduction');
}
);
// Index page
app.get(["/reference"], (_req: ExpressRequest, res: ExpressResponse) => {
return res.redirect("/reference/introduction");
});
app.get(
['/reference/page-not-found'],
(req: ExpressRequest, res: ExpressResponse) => {
return PageNotFoundServiceHandler.executeResponse(req, res);
}
);
app.get(
["/reference/page-not-found"],
(req: ExpressRequest, res: ExpressResponse) => {
return PageNotFoundServiceHandler.executeResponse(req, res);
},
);
// All Pages
app.get(
['/reference/:page'],
(req: ExpressRequest, res: ExpressResponse) => {
const page: string | undefined = req.params['page'];
// All Pages
app.get(
["/reference/:page"],
(req: ExpressRequest, res: ExpressResponse) => {
const page: string | undefined = req.params["page"];
if (!page) {
return PageNotFoundServiceHandler.executeResponse(req, res);
}
if (!page) {
return PageNotFoundServiceHandler.executeResponse(req, res);
}
const currentResource: ModelDocumentation | undefined =
ResourceDictionary[page];
const currentResource: ModelDocumentation | undefined =
ResourceDictionary[page];
if (req.params['page'] === 'permissions') {
return PermissionServiceHandler.executeResponse(req, res);
} else if (req.params['page'] === 'authentication') {
return AuthenticationServiceHandler.executeResponse(
req,
res
);
} else if (req.params['page'] === 'pagination') {
return PaginationServiceHandler.executeResponse(req, res);
} else if (req.params['page'] === 'errors') {
return ErrorServiceHandler.executeResponse(req, res);
} else if (req.params['page'] === 'introduction') {
return IntroductionServiceHandler.executeResponse(req, res);
} else if (req.params['page'] === 'status') {
return StatusServiceHandler.executeResponse(req, res);
} else if (req.params['page'] === 'data-types') {
return DataTypeServiceHandler.executeResponse(req, res);
} else if (currentResource) {
return ModelServiceHandler.executeResponse(req, res);
}
// page not found
return PageNotFoundServiceHandler.executeResponse(req, res);
}
);
if (req.params["page"] === "permissions") {
return PermissionServiceHandler.executeResponse(req, res);
} else if (req.params["page"] === "authentication") {
return AuthenticationServiceHandler.executeResponse(req, res);
} else if (req.params["page"] === "pagination") {
return PaginationServiceHandler.executeResponse(req, res);
} else if (req.params["page"] === "errors") {
return ErrorServiceHandler.executeResponse(req, res);
} else if (req.params["page"] === "introduction") {
return IntroductionServiceHandler.executeResponse(req, res);
} else if (req.params["page"] === "status") {
return StatusServiceHandler.executeResponse(req, res);
} else if (req.params["page"] === "data-types") {
return DataTypeServiceHandler.executeResponse(req, res);
} else if (currentResource) {
return ModelServiceHandler.executeResponse(req, res);
}
// page not found
return PageNotFoundServiceHandler.executeResponse(req, res);
},
);
app.get('/reference/*', (req: ExpressRequest, res: ExpressResponse) => {
return PageNotFoundServiceHandler.executeResponse(req, res);
});
},
app.get("/reference/*", (req: ExpressRequest, res: ExpressResponse) => {
return PageNotFoundServiceHandler.executeResponse(req, res);
});
},
};
export default APIReferenceFeatureSet;

View File

@@ -1,29 +1,28 @@
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import { ViewsPath } from '../Utils/Config';
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
let pageTitle: string = '';
let pageDescription: string = '';
const page: string | undefined = req.params['page'];
const pageData: any = {};
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
let pageTitle: string = "";
let pageDescription: string = "";
const page: string | undefined = req.params["page"];
const pageData: any = {};
pageTitle = 'Authentication';
pageDescription =
'Learn how to authenticate requests with OneUptime API';
pageTitle = "Authentication";
pageDescription = "Learn how to authenticate requests with OneUptime API";
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
}

View File

@@ -1,136 +1,126 @@
import LocalCache from 'CommonServer/Infrastructure/LocalCache';
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import LocalFile from 'CommonServer/Utils/LocalFile';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import { CodeExamplesPath, ViewsPath } from '../Utils/Config';
import { CodeExamplesPath, ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import LocalCache from "CommonServer/Infrastructure/LocalCache";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
import LocalFile from "CommonServer/Utils/LocalFile";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
public static async executeResponse(
_req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
const pageData: any = {};
public static async executeResponse(
_req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
const pageData: any = {};
pageData.selectCode = await LocalCache.getOrSetString(
'data-type',
'select',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/Select.md`
);
}
pageData.selectCode = await LocalCache.getOrSetString(
"data-type",
"select",
async () => {
return await LocalFile.read(`${CodeExamplesPath}/DataTypes/Select.md`);
},
);
pageData.sortCode = await LocalCache.getOrSetString(
"data-type",
"sort",
async () => {
return await LocalFile.read(`${CodeExamplesPath}/DataTypes/Sort.md`);
},
);
pageData.equalToCode = await LocalCache.getOrSetString(
"data-type",
"equal-to",
async () => {
return await LocalFile.read(`${CodeExamplesPath}/DataTypes/EqualTo.md`);
},
);
pageData.equalToOrNullCode = await LocalCache.getOrSetString(
"data-type",
"equal-to-or-null",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/EqualToOrNull.md`,
);
},
);
pageData.sortCode = await LocalCache.getOrSetString(
'data-type',
'sort',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/Sort.md`
);
}
pageData.greaterThanCode = await LocalCache.getOrSetString(
"data-type",
"greater-than",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/GreaterThan.md`,
);
},
);
pageData.equalToCode = await LocalCache.getOrSetString(
'data-type',
'equal-to',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/EqualTo.md`
);
}
pageData.greaterThanOrEqualCode = await LocalCache.getOrSetString(
"data-type",
"greater-than-or-equal",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/GreaterThanOrEqual.md`,
);
},
);
pageData.equalToOrNullCode = await LocalCache.getOrSetString(
'data-type',
'equal-to-or-null',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/EqualToOrNull.md`
);
}
pageData.lessThanCode = await LocalCache.getOrSetString(
"data-type",
"less-than",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/LessThan.md`,
);
},
);
pageData.greaterThanCode = await LocalCache.getOrSetString(
'data-type',
'greater-than',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/GreaterThan.md`
);
}
pageData.lessThanOrEqualCode = await LocalCache.getOrSetString(
"data-type",
"less-than-or-equal",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/LessThanOrEqual.md`,
);
},
);
pageData.greaterThanOrEqualCode = await LocalCache.getOrSetString(
'data-type',
'greater-than-or-equal',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/GreaterThanOrEqual.md`
);
}
pageData.isNullCode = await LocalCache.getOrSetString(
"data-type",
"is-null",
async () => {
return await LocalFile.read(`${CodeExamplesPath}/DataTypes/IsNull.md`);
},
);
pageData.notNullCode = await LocalCache.getOrSetString(
"data-type",
"not-null",
async () => {
return await LocalFile.read(`${CodeExamplesPath}/DataTypes/NotNull.md`);
},
);
pageData.notEqualToCode = await LocalCache.getOrSetString(
"data-type",
"not-equals",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/NotEqualTo.md`,
);
},
);
pageData.lessThanCode = await LocalCache.getOrSetString(
'data-type',
'less-than',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/LessThan.md`
);
}
);
pageData.lessThanOrEqualCode = await LocalCache.getOrSetString(
'data-type',
'less-than-or-equal',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/LessThanOrEqual.md`
);
}
);
pageData.isNullCode = await LocalCache.getOrSetString(
'data-type',
'is-null',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/IsNull.md`
);
}
);
pageData.notNullCode = await LocalCache.getOrSetString(
'data-type',
'not-null',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/NotNull.md`
);
}
);
pageData.notEqualToCode = await LocalCache.getOrSetString(
'data-type',
'not-equals',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/DataTypes/NotEqualTo.md`
);
}
);
res.status(200);
return res.render(`${ViewsPath}/pages/index`, {
page: 'data-types',
pageTitle: 'Data Types',
pageDescription:
'Data Types that can be used to interact with OneUptime API',
resources: Resources,
pageData: pageData,
});
}
res.status(200);
return res.render(`${ViewsPath}/pages/index`, {
page: "data-types",
pageTitle: "Data Types",
pageDescription:
"Data Types that can be used to interact with OneUptime API",
resources: Resources,
pageData: pageData,
});
}
}

View File

@@ -1,28 +1,28 @@
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import { ViewsPath } from '../Utils/Config';
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
let pageTitle: string = '';
let pageDescription: string = '';
const page: string | undefined = req.params['page'];
const pageData: any = {};
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
let pageTitle: string = "";
let pageDescription: string = "";
const page: string | undefined = req.params["page"];
const pageData: any = {};
pageTitle = 'Errors';
pageDescription = 'Learn more about how we return errors from API';
pageTitle = "Errors";
pageDescription = "Learn more about how we return errors from API";
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
}

View File

@@ -1,31 +1,31 @@
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import { ViewsPath } from '../Utils/Config';
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const FeaturedResources: Array<ModelDocumentation> =
ResourceUtil.getFeaturedResources();
ResourceUtil.getFeaturedResources();
export default class ServiceHandler {
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
let pageTitle: string = '';
let pageDescription: string = '';
const page: string | undefined = req.params['page'];
const pageData: any = {};
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
let pageTitle: string = "";
let pageDescription: string = "";
const page: string | undefined = req.params["page"];
const pageData: any = {};
pageData.featuredResources = FeaturedResources;
pageTitle = 'Introduction';
pageDescription = 'API Reference for OneUptime';
pageData.featuredResources = FeaturedResources;
pageTitle = "Introduction";
pageDescription = "API Reference for OneUptime";
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
}

View File

@@ -1,244 +1,238 @@
import { ColumnAccessControl } from 'Common/Types/BaseDatabase/AccessControl';
import { getTableColumns } from 'Common/Types/Database/TableColumn';
import Dictionary from 'Common/Types/Dictionary';
import ObjectID from 'Common/Types/ObjectID';
import { CodeExamplesPath, ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import PageNotFoundServiceHandler from "./PageNotFound";
import { AppApiRoute } from "Common/ServiceRoute";
import { ColumnAccessControl } from "Common/Types/BaseDatabase/AccessControl";
import { getTableColumns } from "Common/Types/Database/TableColumn";
import Dictionary from "Common/Types/Dictionary";
import ObjectID from "Common/Types/ObjectID";
import Permission, {
PermissionHelper,
PermissionProps,
} from 'Common/Types/Permission';
import { AppApiRoute } from 'Common/ServiceRoute';
import LocalCache from 'CommonServer/Infrastructure/LocalCache';
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import LocalFile from 'CommonServer/Utils/LocalFile';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import PageNotFoundServiceHandler from './PageNotFound';
import { CodeExamplesPath, ViewsPath } from '../Utils/Config';
PermissionHelper,
PermissionProps,
} from "Common/Types/Permission";
import LocalCache from "CommonServer/Infrastructure/LocalCache";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
import LocalFile from "CommonServer/Utils/LocalFile";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const ResourceDictionary: Dictionary<ModelDocumentation> =
ResourceUtil.getResourceDictionaryByPath();
ResourceUtil.getResourceDictionaryByPath();
const PermissionDictionary: Dictionary<PermissionProps> =
PermissionHelper.getAllPermissionPropsAsDictionary();
PermissionHelper.getAllPermissionPropsAsDictionary();
export default class ServiceHandler {
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
let pageTitle: string = '';
let pageDescription: string = '';
let page: string | undefined = req.params['page'];
const pageData: any = {};
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
let pageTitle: string = "";
let pageDescription: string = "";
let page: string | undefined = req.params["page"];
const pageData: any = {};
if (!page) {
return PageNotFoundServiceHandler.executeResponse(req, res);
}
const currentResource: ModelDocumentation | undefined =
ResourceDictionary[page];
if (!currentResource) {
return PageNotFoundServiceHandler.executeResponse(req, res);
}
// Resource Page.
pageTitle = currentResource.name;
pageDescription = currentResource.description;
page = 'model';
const tableColumns: any = getTableColumns(currentResource.model);
for (const key in tableColumns) {
const accessControl: ColumnAccessControl | null =
currentResource.model.getColumnAccessControlFor(key);
if (!accessControl) {
// remove columns with no access
delete tableColumns[key];
continue;
}
if (
accessControl?.create.length === 0 &&
accessControl?.read.length === 0 &&
accessControl?.update.length === 0
) {
// remove columns with no access
delete tableColumns[key];
continue;
}
tableColumns[key].permissions = accessControl;
}
delete tableColumns['deletedAt'];
delete tableColumns['deletedByUserId'];
delete tableColumns['deletedByUser'];
delete tableColumns['version'];
pageData.title = currentResource.model.singularName;
pageData.description = currentResource.model.tableDescription;
pageData.columns = tableColumns;
pageData.tablePermissions = {
read: currentResource.model.readRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
}
),
update: currentResource.model.updateRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
}
),
delete: currentResource.model.deleteRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
}
),
create: currentResource.model.createRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
}
),
};
pageData.listRequest = await LocalCache.getOrSetString(
'model',
'list-request',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/ListRequest.md`
);
}
);
pageData.itemRequest = await LocalCache.getOrSetString(
'model',
'item-request',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/ItemRequest.md`
);
}
);
pageData.itemResponse = await LocalCache.getOrSetString(
'model',
'item-response',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/ItemResponse.md`
);
}
);
pageData.countRequest = await LocalCache.getOrSetString(
'model',
'count-request',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CountRequest.md`
);
}
);
pageData.countResponse = await LocalCache.getOrSetString(
'model',
'count-response',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CountResponse.md`
);
}
);
pageData.updateRequest = await LocalCache.getOrSetString(
'model',
'update-request',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/UpdateRequest.md`
);
}
);
pageData.updateResponse = await LocalCache.getOrSetString(
'model',
'update-response',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/UpdateResponse.md`
);
}
);
pageData.createRequest = await LocalCache.getOrSetString(
'model',
'create-request',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CreateRequest.md`
);
}
);
pageData.createResponse = await LocalCache.getOrSetString(
'model',
'create-response',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CreateResponse.md`
);
}
);
pageData.deleteRequest = await LocalCache.getOrSetString(
'model',
'delete-request',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/DeleteRequest.md`
);
}
);
pageData.deleteResponse = await LocalCache.getOrSetString(
'model',
'delete-response',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/DeleteResponse.md`
);
}
);
pageData.listResponse = await LocalCache.getOrSetString(
'model',
'list-response',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/ListResponse.md`
);
}
);
pageData.exampleObjectID = ObjectID.generate();
pageData.apiPath =
AppApiRoute.toString() +
currentResource.model.crudApiPath?.toString();
pageData.isMasterAdminApiDocs =
currentResource.model.isMasterAdminApiDocs;
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
if (!page) {
return PageNotFoundServiceHandler.executeResponse(req, res);
}
const currentResource: ModelDocumentation | undefined =
ResourceDictionary[page];
if (!currentResource) {
return PageNotFoundServiceHandler.executeResponse(req, res);
}
// Resource Page.
pageTitle = currentResource.name;
pageDescription = currentResource.description;
page = "model";
const tableColumns: any = getTableColumns(currentResource.model);
for (const key in tableColumns) {
const accessControl: ColumnAccessControl | null =
currentResource.model.getColumnAccessControlFor(key);
if (!accessControl) {
// remove columns with no access
delete tableColumns[key];
continue;
}
if (
accessControl?.create.length === 0 &&
accessControl?.read.length === 0 &&
accessControl?.update.length === 0
) {
// remove columns with no access
delete tableColumns[key];
continue;
}
tableColumns[key].permissions = accessControl;
}
delete tableColumns["deletedAt"];
delete tableColumns["deletedByUserId"];
delete tableColumns["deletedByUser"];
delete tableColumns["version"];
pageData.title = currentResource.model.singularName;
pageData.description = currentResource.model.tableDescription;
pageData.columns = tableColumns;
pageData.tablePermissions = {
read: currentResource.model.readRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
},
),
update: currentResource.model.updateRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
},
),
delete: currentResource.model.deleteRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
},
),
create: currentResource.model.createRecordPermissions.map(
(permission: Permission) => {
return PermissionDictionary[permission];
},
),
};
pageData.listRequest = await LocalCache.getOrSetString(
"model",
"list-request",
async () => {
return await LocalFile.read(`${CodeExamplesPath}/Model/ListRequest.md`);
},
);
pageData.itemRequest = await LocalCache.getOrSetString(
"model",
"item-request",
async () => {
return await LocalFile.read(`${CodeExamplesPath}/Model/ItemRequest.md`);
},
);
pageData.itemResponse = await LocalCache.getOrSetString(
"model",
"item-response",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/ItemResponse.md`,
);
},
);
pageData.countRequest = await LocalCache.getOrSetString(
"model",
"count-request",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CountRequest.md`,
);
},
);
pageData.countResponse = await LocalCache.getOrSetString(
"model",
"count-response",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CountResponse.md`,
);
},
);
pageData.updateRequest = await LocalCache.getOrSetString(
"model",
"update-request",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/UpdateRequest.md`,
);
},
);
pageData.updateResponse = await LocalCache.getOrSetString(
"model",
"update-response",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/UpdateResponse.md`,
);
},
);
pageData.createRequest = await LocalCache.getOrSetString(
"model",
"create-request",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CreateRequest.md`,
);
},
);
pageData.createResponse = await LocalCache.getOrSetString(
"model",
"create-response",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/CreateResponse.md`,
);
},
);
pageData.deleteRequest = await LocalCache.getOrSetString(
"model",
"delete-request",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/DeleteRequest.md`,
);
},
);
pageData.deleteResponse = await LocalCache.getOrSetString(
"model",
"delete-response",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/DeleteResponse.md`,
);
},
);
pageData.listResponse = await LocalCache.getOrSetString(
"model",
"list-response",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Model/ListResponse.md`,
);
},
);
pageData.exampleObjectID = ObjectID.generate();
pageData.apiPath =
AppApiRoute.toString() + currentResource.model.crudApiPath?.toString();
pageData.isMasterAdminApiDocs = currentResource.model.isMasterAdminApiDocs;
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
}

View File

@@ -1,21 +1,21 @@
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import { ViewsPath } from '../Utils/Config';
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
public static async executeResponse(
_req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
res.status(404);
return res.render(`${ViewsPath}/pages/index`, {
page: '404',
pageTitle: 'Page Not Found',
pageDescription: "Page you're looking for is not found.",
resources: Resources,
pageData: {},
});
}
public static async executeResponse(
_req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
res.status(404);
return res.render(`${ViewsPath}/pages/index`, {
page: "404",
pageTitle: "Page Not Found",
pageDescription: "Page you're looking for is not found.",
resources: Resources,
pageData: {},
});
}
}

View File

@@ -1,50 +1,50 @@
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import LocalFile from 'CommonServer/Utils/LocalFile';
import LocalCache from 'CommonServer/Infrastructure/LocalCache';
import { CodeExamplesPath, ViewsPath } from '../Utils/Config';
import { CodeExamplesPath, ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import LocalCache from "CommonServer/Infrastructure/LocalCache";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
import LocalFile from "CommonServer/Utils/LocalFile";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
let pageTitle: string = '';
let pageDescription: string = '';
const page: string | undefined = req.params['page'];
const pageData: any = {};
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
let pageTitle: string = "";
let pageDescription: string = "";
const page: string | undefined = req.params["page"];
const pageData: any = {};
pageTitle = 'Pagination';
pageDescription = 'Learn how to paginate requests with OneUptime API';
pageTitle = "Pagination";
pageDescription = "Learn how to paginate requests with OneUptime API";
pageData.responseCode = await LocalCache.getOrSetString(
'pagination',
'response',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Pagination/Response.md`
);
}
pageData.responseCode = await LocalCache.getOrSetString(
"pagination",
"response",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Pagination/Response.md`,
);
},
);
pageData.requestCode = await LocalCache.getOrSetString(
'pagination',
'request',
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Pagination/Request.md`
);
}
pageData.requestCode = await LocalCache.getOrSetString(
"pagination",
"request",
async () => {
return await LocalFile.read(
`${CodeExamplesPath}/Pagination/Request.md`,
);
},
);
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
}

View File

@@ -1,35 +1,35 @@
import { PermissionHelper, PermissionProps } from 'Common/Types/Permission';
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import { ViewsPath } from '../Utils/Config';
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { PermissionHelper, PermissionProps } from "Common/Types/Permission";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
let pageTitle: string = '';
let pageDescription: string = '';
const page: string | undefined = req.params['page'];
const pageData: any = {};
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
let pageTitle: string = "";
let pageDescription: string = "";
const page: string | undefined = req.params["page"];
const pageData: any = {};
pageTitle = 'Permissions';
pageDescription = 'Learn how permissions work with OneUptime';
pageTitle = "Permissions";
pageDescription = "Learn how permissions work with OneUptime";
pageData.permissions = PermissionHelper.getAllPermissionProps().filter(
(i: PermissionProps) => {
return i.isAssignableToTenant;
}
);
pageData.permissions = PermissionHelper.getAllPermissionProps().filter(
(i: PermissionProps) => {
return i.isAssignableToTenant;
},
);
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
pageDescription: pageDescription,
pageData: pageData,
});
}
}

View File

@@ -1,21 +1,21 @@
import { ExpressRequest, ExpressResponse } from 'CommonServer/Utils/Express';
import ResourceUtil, { ModelDocumentation } from '../Utils/Resources';
import { ViewsPath } from '../Utils/Config';
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { ExpressRequest, ExpressResponse } from "CommonServer/Utils/Express";
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
public static async executeResponse(
_req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
res.status(200);
return res.render(`${ViewsPath}/pages/index`, {
page: 'status',
pageTitle: 'Status',
pageDescription: '200 - Success',
resources: Resources,
pageData: {},
});
}
public static async executeResponse(
_req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
res.status(200);
return res.render(`${ViewsPath}/pages/index`, {
page: "status",
pageTitle: "Status",
pageDescription: "200 - Success",
resources: Resources,
pageData: {},
});
}
}

View File

@@ -1,4 +1,4 @@
export const ViewsPath: string = '/usr/src/app/FeatureSet/ApiReference/views';
export const StaticPath: string = '/usr/src/app/FeatureSet/ApiReference/Static';
export const ViewsPath: string = "/usr/src/app/FeatureSet/ApiReference/views";
export const StaticPath: string = "/usr/src/app/FeatureSet/ApiReference/Static";
export const CodeExamplesPath: string =
'/usr/src/app/FeatureSet/ApiReference/CodeExamples';
"/usr/src/app/FeatureSet/ApiReference/CodeExamples";

View File

@@ -1,74 +1,73 @@
import BaseModel from 'Common/Models/BaseModel';
import Models from 'Model/Models/Index';
import ArrayUtil from 'Common/Types/ArrayUtil';
import Dictionary from 'Common/Types/Dictionary';
import { IsBillingEnabled } from 'CommonServer/EnvironmentConfig';
import BaseModel from "Common/Models/BaseModel";
import ArrayUtil from "Common/Types/ArrayUtil";
import Dictionary from "Common/Types/Dictionary";
import { IsBillingEnabled } from "CommonServer/EnvironmentConfig";
import Models from "Model/Models/Index";
export interface ModelDocumentation {
name: string;
path: string;
model: BaseModel;
description: string;
name: string;
path: string;
model: BaseModel;
description: string;
}
export default class ResourceUtil {
public static getResources(): Array<ModelDocumentation> {
const resources: Array<ModelDocumentation> = Models.filter(
(model: typeof BaseModel) => {
const modelInstance: BaseModel = new model();
let showDocs: boolean = modelInstance.enableDocumentation;
public static getResources(): Array<ModelDocumentation> {
const resources: Array<ModelDocumentation> = Models.filter(
(model: typeof BaseModel) => {
const modelInstance: BaseModel = new model();
let showDocs: boolean = modelInstance.enableDocumentation;
if (modelInstance.isMasterAdminApiDocs && IsBillingEnabled) {
showDocs = false;
}
return showDocs;
}
)
.map((model: typeof BaseModel) => {
const modelInstance: BaseModel = new model();
return {
name: modelInstance.singularName!,
path: modelInstance.getAPIDocumentationPath(),
model: modelInstance,
description: modelInstance.tableDescription!,
};
})
.sort(ArrayUtil.sortByFieldName('name'));
return resources;
}
public static getFeaturedResources(): Array<ModelDocumentation> {
const featuredResources: Array<string> = [
'Monitor',
'Scheduled Maintenance Event',
'Status Page',
'Incident',
'Team',
'On-Call Duty',
'Label',
'Team Member',
];
return ResourceUtil.getResources().filter(
(resource: ModelDocumentation) => {
return featuredResources.includes(resource.name);
}
);
}
public static getResourceDictionaryByPath(): Dictionary<ModelDocumentation> {
const dict: Dictionary<ModelDocumentation> = {};
const resources: Array<ModelDocumentation> =
ResourceUtil.getResources();
for (const resource of resources) {
dict[resource.path] = resource;
if (modelInstance.isMasterAdminApiDocs && IsBillingEnabled) {
showDocs = false;
}
return dict;
return showDocs;
},
)
.map((model: typeof BaseModel) => {
const modelInstance: BaseModel = new model();
return {
name: modelInstance.singularName!,
path: modelInstance.getAPIDocumentationPath(),
model: modelInstance,
description: modelInstance.tableDescription!,
};
})
.sort(ArrayUtil.sortByFieldName("name"));
return resources;
}
public static getFeaturedResources(): Array<ModelDocumentation> {
const featuredResources: Array<string> = [
"Monitor",
"Scheduled Maintenance Event",
"Status Page",
"Incident",
"Team",
"On-Call Duty",
"Label",
"Team Member",
];
return ResourceUtil.getResources().filter(
(resource: ModelDocumentation) => {
return featuredResources.includes(resource.name);
},
);
}
public static getResourceDictionaryByPath(): Dictionary<ModelDocumentation> {
const dict: Dictionary<ModelDocumentation> = {};
const resources: Array<ModelDocumentation> = ResourceUtil.getResources();
for (const resource of resources) {
dict[resource.path] = resource;
}
return dict;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,9 @@ Depending on your usage and budget, you can choose from different system require
#### Prerequisites for Single-Server Deployment
Installation tutorial: [https://youtu.be/j1SWmMW2oL4](https://youtu.be/j1SWmMW2oL4)
Before you start the deployment process, please make sure you have:
- A server running Debian, Ubuntu, or RHEL derivative
@@ -47,7 +50,10 @@ If you don't like to use npm or do not have it installed, run this instead:
```
# Read env vars from config.env file and run docker-compose up.
export $(grep -v '^#' config.env | xargs) && docker compose up --remove-orphans -d
(export $(grep -v '^#' config.env | xargs) && docker compose up --remove-orphans -d)
# Use sudo if you're having permission issues with binding ports.
sudo bash -c "(export $(grep -v '^#' config.env | xargs) && docker compose up --remove-orphans -d)"
```
To update:

View File

@@ -0,0 +1,27 @@
# Custom Code Monitor
Custom Code Monitor allows you to write custom scripts to monitor your applications. You can use this feature to monitor your applications in a way that is not possible with the existing monitors. For example, you can have multi-step API requests.
#### Example
The following example shows how to use a Synthetic Monitor:
```javascript
// You can use axios module.
await axios.get('https://api.example.com/');
// Axios Documentation here: https://axios-http.com/docs/intro
return {
data: 'Hello World' // return any data you like here.
};
```
### Things to consider
- You can use `console.log` to log the data in the console. This will be available in the logs section of the monitor.
- You can return the data from the script using the `return` statement.
- This is a JavaScript script, so you can use all the JavaScript features in the script.
- You can use `axios` module to make HTTP requests in the script. You can use it to make API calls from the script.
- Timeout for the script is 2 minutes. If the script takes more than 2 mins, it will be terminated.

View File

@@ -0,0 +1,34 @@
# Monitor Secrets
You can use secrets to store sensitive information that you want to use in your monitoring checks. Secrets are encrypted and stored securely.
### Adding a secret
To add a secret, please go to OneUptime Dashboard -> Project Settings -> Monitor Secrets -> Create Monitor Secret.
![Create Secret](/docs/static/images/CreateMonitorSecret.png)
You can select which monitors have access to the secret. In this case we added `ApiKey` secret and selected monitors to have access to it.
**Please note**: Secrets are encrypted and stored securely. If you lose the secret, you will need to create a new secret. You cannot view or update the secret after its saved.
### Using a secret
You can use secrets in the following monitoring types:
- API (in request headers, request body, and URL)
- Website, IP, Port, Ping, SSL Certificate (in URL)
- Synthetic Monitor, Custom Code Monitor (in the code)
![Using Secret](/docs/static/images/UsingMonitorSecret.png)
To use a secret, add `{{monitorSecrets.SECRET_NAME}}` in the field where you want to use the secret. For example, in this case we added `{{monitorSecrets.ApiKey}}` in the Requets Header field.
### Monitor Secret Permissions
You can select which monitors have access to the secret. You can also update the permissions at any time. So, if you want to add a new monitor to have access to the secret, you can do so by updating the permissions.

View File

@@ -0,0 +1,71 @@
# Synthetic Monitor
Synthetic monitoring is a way to proactively monitor your applications by simulating user interactions. You can create a synthetic monitor to check the availability and performance of your applications from different locations around the world.
#### Example
The following example shows how to use a Synthetic Monitor:
```javascript
// You can use axios module, and page object from Playwright here.
// Page Object is a class that represents a single page in a browser.
await page.goto('https://playwright.dev/');
// Playwright Documentation here: https://playwright.dev/docs/intro
// Here are some of the variables that you can use in the context of the monitored object:
console.log(browserType) // This will list the browser type in the current run context - Chromium, Firefox, Webkit
console.log(screenSizeType) // This will list the screen size type in the current run context - Mobile, Tablet, Desktop
// Playwright page object belongs to that specific browser context, so you can use it to interact with the browser.
// To take screenshots,
const screenshots = {};
screenshots['screenshot-name'] = await page.screenshot(); // you can save multiple screenshots and have them with different names.
// when you want to return a value, use return statement with data as a prop. You can also add screenshots in the screenshots array.
return {
data: 'Hello World',
screenshots: screenshots
};
```
### Use of Playwright
We use Playwright to simulate user interactions. You can use Playwright `page` object to interact with the browser and perform actions like clicking buttons, filling forms, and taking screenshots.
### Screenshots
You can take screenshots of the page at any point in the script. You can take multiple screenshots and return them in the screenshots array. These screenshots will be available in the OneUptime Dashboard for that specific monitor.
```javascript
// To take screenshots,
const screenshots = {};
screenshots['screenshot-name'] = await page.screenshot();
return {
data: 'Hello World',
screenshots: screenshots
};
```
### Things to consider
- You only have `page` object available in the context of the script. This is from Playwright Page class. You can use it to run all the interactions with the browser.
- You can use `console.log` to log the data in the console. This will be available in the logs section of the monitor.
- You can return the data from the script using the `return` statement. You can also return screenshots in the screenshots array.
- You can use `browserType` and `screenSizeType` variables to get the browser type and screen size type in the current run context. Feel free to use them in your script if you like.
- This is a JavaScript script, so you can use all the JavaScript features in the script.
- You can use `axios` module to make HTTP requests in the script. You can use it to make API calls from the script.
- If you are using oneuptime.com, you will always have the latest version of Playwright & browsers available in the context of the script. If you're self-hosting, please make sure you update the probes to have the latest version of Playwright and the browsers.
- Timeout for the script is 2 minutes. If the script takes more than 2 mins, it will be terminated.

View File

@@ -1,93 +1,85 @@
import 'ejs';
import { ContentPath, StaticPath, ViewsPath } from "./Utils/Config";
import DocsNav, { NavGroup, NavLink } from "./Utils/Nav";
import DocsRender from "./Utils/Render";
import FeatureSet from "CommonServer/Types/FeatureSet";
import Express, {
ExpressRequest,
ExpressResponse,
ExpressStatic,
ExpressApplication,
} from 'CommonServer/Utils/Express';
import { ContentPath, StaticPath, ViewsPath } from './Utils/Config';
import DocsNav, { NavGroup, NavLink } from './Utils/Nav';
import LocalFile from 'CommonServer/Utils/LocalFile';
import DocsRender from './Utils/Render';
import logger from 'CommonServer/Utils/Logger';
import FeatureSet from 'CommonServer/Types/FeatureSet';
ExpressApplication,
ExpressRequest,
ExpressResponse,
ExpressStatic,
} from "CommonServer/Utils/Express";
import LocalFile from "CommonServer/Utils/LocalFile";
import logger from "CommonServer/Utils/Logger";
import "ejs";
const DocsFeatureSet: FeatureSet = {
init: async (): Promise<void> => {
const app: ExpressApplication = Express.getExpressApp();
init: async (): Promise<void> => {
const app: ExpressApplication = Express.getExpressApp();
app.get('/docs', (_req: ExpressRequest, res: ExpressResponse) => {
res.redirect('/docs/introduction/getting-started');
});
app.get("/docs", (_req: ExpressRequest, res: ExpressResponse) => {
res.redirect("/docs/introduction/getting-started");
});
app.get(
'/docs/:categorypath/:pagepath',
async (_req: ExpressRequest, res: ExpressResponse) => {
try {
const fullPath: string =
`${_req.params['categorypath']}/${_req.params['pagepath']}`.toLowerCase();
app.get(
"/docs/:categorypath/:pagepath",
async (_req: ExpressRequest, res: ExpressResponse) => {
try {
const fullPath: string =
`${_req.params["categorypath"]}/${_req.params["pagepath"]}`.toLowerCase();
// read file from Content folder.
let contentInMarkdown: string = await LocalFile.read(
`${ContentPath}/${fullPath}.md`
);
// read file from Content folder.
let contentInMarkdown: string = await LocalFile.read(
`${ContentPath}/${fullPath}.md`,
);
// remove first line from content because we dont want to show title in content. Title is already in nav.
// remove first line from content because we dont want to show title in content. Title is already in nav.
contentInMarkdown = contentInMarkdown
.split('\n')
.slice(1)
.join('\n');
contentInMarkdown = contentInMarkdown.split("\n").slice(1).join("\n");
const renderedContent: string = await DocsRender.render(
contentInMarkdown
);
const renderedContent: string =
await DocsRender.render(contentInMarkdown);
const currentCategory: NavGroup | undefined = DocsNav.find(
(category: NavGroup) => {
return category.links.find((link: NavLink) => {
return link.url
.toLocaleLowerCase()
.includes(fullPath);
});
}
);
const currentCategory: NavGroup | undefined = DocsNav.find(
(category: NavGroup) => {
return category.links.find((link: NavLink) => {
return link.url.toLocaleLowerCase().includes(fullPath);
});
},
);
const currrentNavLink: NavLink | undefined =
currentCategory?.links.find((link: NavLink) => {
return link.url
.toLocaleLowerCase()
.includes(fullPath);
});
const currrentNavLink: NavLink | undefined =
currentCategory?.links.find((link: NavLink) => {
return link.url.toLocaleLowerCase().includes(fullPath);
});
if (!currentCategory || !currrentNavLink) {
// render not found.
if (!currentCategory || !currrentNavLink) {
// render not found.
res.status(404);
return res.render(`${ViewsPath}/NotFound`, {
nav: DocsNav,
});
}
res.status(404);
return res.render(`${ViewsPath}/NotFound`, {
nav: DocsNav,
});
}
res.render(`${ViewsPath}/Index`, {
nav: DocsNav,
content: renderedContent,
category: currentCategory,
link: currrentNavLink,
githubPath: fullPath,
});
} catch (err) {
logger.error(err);
res.status(500);
return res.render(`${ViewsPath}/ServerError`, {
nav: DocsNav,
});
}
}
);
res.render(`${ViewsPath}/Index`, {
nav: DocsNav,
content: renderedContent,
category: currentCategory,
link: currrentNavLink,
githubPath: fullPath,
});
} catch (err) {
logger.error(err);
res.status(500);
return res.render(`${ViewsPath}/ServerError`, {
nav: DocsNav,
});
}
},
);
app.use('/docs/static', ExpressStatic(StaticPath));
},
app.use("/docs/static", ExpressStatic(StaticPath));
},
};
export default DocsFeatureSet;

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View File

@@ -1,54 +0,0 @@
#!/bin/bash
# Check if this is debian based
# Check if system supports apt-get
if [ -x "$(command -v apt-get)" ]; then
# Update apt-get
sudo apt-get update
# Install build-essential
sudo apt-get install build-essential -y
fi
# Check if system supports yum
if [ -x "$(command -v yum)" ]; then
# Update yum
sudo yum update
# Install build-essential
sudo yum install gcc-c++ make -y
fi
# Check if system supports apk
if [ -x "$(command -v apk)" ]; then
# Update apk
sudo apk update
# Install build-essential
sudo apk add build-base
fi
# Install NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Export to path
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
# Refresh bash
source ~/.bashrc
# Install latest Node.js via NVM
nvm install node
# Make this nodejs version the default
nvm alias default node
# Use the default version
nvm use default
# Now install
npm install -g tsx
npm install -g @oneuptime/infrastructure-agent

View File

@@ -0,0 +1,77 @@
#!/bin/sh
set -e
usage() {
echo "Usage: $0 [-b bindir] [-d]"
echo " -b sets the directory for the binary installation, default is ./bin"
echo " -d enables debug mode"
exit 1
}
# Default parameters
BINDIR=/usr/bin
DEBUG=0
# Parse command-line options
while getopts "b:d" opt; do
case ${opt} in
b )
BINDIR=$OPTARG
;;
d )
set -x
DEBUG=1
;;
\? )
usage
;;
esac
done
echo "Installing to ${BINDIR}"
mkdir -p "${BINDIR}"
# Detect platform and architecture
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case $ARCH in
x86_64)
ARCH=amd64
;;
aarch64)
ARCH=arm64
;;
*arm*)
ARCH=arm
;;
*)
echo "Architecture $ARCH is not supported"
exit 1
;;
esac
# Fetch the latest release tag from GitHub
REPO="oneuptime/oneuptime"
API_URL="https://api.github.com/repos/${REPO}/releases/latest"
TAG=$(curl -s ${API_URL} | grep '"tag_name":' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
if [ "$TAG" = "" ]; then
echo "Failed to find the latest release. Please check your internet connection or GitHub API limits."
exit 1
fi
echo "Fetching the latest release: $TAG"
# Construct the URL for the binary release
URL="https://github.com/${REPO}/releases/download/${TAG}/oneuptime-infrastructure-agent_${OS}_${ARCH}.tar.gz"
# Download and extract the binary
curl -sL "${URL}" | tar xz -C "${BINDIR}"
# Check if the binary is executable
if [ ! -x "${BINDIR}/oneuptime-infrastructure-agent" ]; then
echo "Failed to install oneuptime-infrastructure-agent"
exit 1
fi
echo "oneuptime-infrastructure-agent installed successfully to ${BINDIR}. Please configure the agent using 'oneuptime-infrastructure-agent configure'."

View File

@@ -1,3 +1,3 @@
export const ViewsPath: string = '/usr/src/app/FeatureSet/Docs/Views';
export const StaticPath: string = '/usr/src/app/FeatureSet/Docs/Static';
export const ContentPath: string = '/usr/src/app/FeatureSet/Docs/Content';
export const ViewsPath: string = "/usr/src/app/FeatureSet/Docs/Views";
export const StaticPath: string = "/usr/src/app/FeatureSet/Docs/Static";
export const ContentPath: string = "/usr/src/app/FeatureSet/Docs/Content";

View File

@@ -1,63 +1,75 @@
export interface NavLink {
title: string;
url: string;
title: string;
url: string;
}
export interface NavGroup {
title: string;
links: NavLink[];
title: string;
links: NavLink[];
}
const DocsNav: NavGroup[] = [
{
title: 'Introduction',
links: [
{
title: 'Getting Started',
url: '/docs/introduction/getting-started',
},
],
},
{
title: 'Installation',
links: [
{
title: 'Local Development',
url: '/docs/installation/local-development',
},
{
title: 'Docker Compose',
url: '/docs/installation/docker-compose',
},
{
title: 'Kubernetes and Helm',
url: 'https://artifacthub.io/packages/helm/oneuptime/oneuptime',
},
],
},
{
title: 'Monitor',
links: [
{
title: 'JavaScript Expressions',
url: '/docs/monitor/javascript-expression',
},
],
},
{
title: 'Probe',
links: [
{ title: 'Custom Probes', url: '/docs/probe/custom-probe' },
{ title: 'IP Addresses', url: '/docs/probe/ip-address' },
],
},
{
title: 'Telemetry',
links: [
{ title: 'OpenTelemetry', url: '/docs/telemetry/open-telemetry' },
{ title: 'Fluentd', url: '/docs/telemetry/fluentd' },
],
},
{
title: "Introduction",
links: [
{
title: "Getting Started",
url: "/docs/introduction/getting-started",
},
],
},
{
title: "Installation",
links: [
{
title: "Local Development",
url: "/docs/installation/local-development",
},
{
title: "Docker Compose",
url: "/docs/installation/docker-compose",
},
{
title: "Kubernetes and Helm",
url: "https://artifacthub.io/packages/helm/oneuptime/oneuptime",
},
],
},
{
title: "Monitor",
links: [
{
title: "Custom Code Monitor",
url: "/docs/monitor/custom-code-monitor",
},
{
title: "Synthetic Monitor",
url: "/docs/monitor/synthetic-monitor",
},
{
title: "JavaScript Expressions",
url: "/docs/monitor/javascript-expression",
},
{
title: "Monitor Secrets",
url: "/docs/monitor/monitor-secrets",
},
],
},
{
title: "Probe",
links: [
{ title: "Custom Probes", url: "/docs/probe/custom-probe" },
{ title: "IP Addresses", url: "/docs/probe/ip-address" },
],
},
{
title: "Telemetry",
links: [
{ title: "OpenTelemetry", url: "/docs/telemetry/open-telemetry" },
{ title: "Fluentd", url: "/docs/telemetry/fluentd" },
],
},
];
export default DocsNav;

View File

@@ -1,50 +1,7 @@
import { Renderer, marked } from 'marked';
import Markdown, { MarkdownContentType } from "CommonServer/Types/Markdown";
export default class DocsRender {
public static async render(markdownContent: string): Promise<string> {
const renderer: Renderer = this.getBlogRenderer();
return await marked(markdownContent, {
renderer: renderer,
});
}
private static getBlogRenderer(): Renderer {
const renderer: Renderer = new Renderer();
renderer.paragraph = function (text) {
return `<p class="mt-2 mb-2 leading-8 text-gray-600">${text}</p>`;
};
renderer.blockquote = function (quote) {
return `<blockquote class="p-4 pt-1 pb-1 my-4 border-s-4 border-indigo-500">
<div class="leading-8 text-gray-600">${quote}</div>
</blockquote>`;
};
renderer.image = function (href, _title, text) {
return `<img src="${href}" alt="${text}" class="rounded-md shadow-md" />`;
};
renderer.code = function (code, language) {
return `<pre class="language-${language} rounded-md"><code class="language-${language} rounded-md">${code}</code></pre>`;
};
renderer.heading = function (text, level) {
if (level === 1) {
return `<h1 class="my-5 mt-8 text-4xl font-bold tracking-tight text-gray-800">${text}</h1>`;
} else if (level === 2) {
return `<h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">${text}</h2>`;
} else if (level === 3) {
return `<h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">${text}</h3>`;
} else if (level === 4) {
return `<h4 class="my-5 mt-8 text-xl font-bold tracking-tight text-gray-800">${text}</h4>`;
} else if (level === 5) {
return `<h5 class="my-5 mt-8 text-lg font-bold tracking-tight text-gray-800">${text}</h5>`;
}
return `<h6 class="my-5 tracking-tight font-bold text-gray-800">${text}</h6>`;
};
return renderer;
}
public static async render(markdownContent: string): Promise<string> {
return Markdown.convertToHTML(markdownContent, MarkdownContentType.Docs);
}
}

View File

@@ -1,89 +1,88 @@
import BlogPostUtil, { BlogPost, BlogPostHeader } from "../Utils/BlogPost";
import { ViewsPath } from "../Utils/Config";
import NotFoundUtil from "../Utils/NotFound";
import ServerErrorUtil from "../Utils/ServerError";
import Text from "Common/Types/Text";
import Express, {
ExpressApplication,
ExpressRequest,
ExpressResponse,
} from 'CommonServer/Utils/Express';
import BlogPostUtil, { BlogPost, BlogPostHeader } from '../Utils/BlogPost';
import { ViewsPath } from '../Utils/Config';
import logger from 'CommonServer/Utils/Logger';
import ServerErrorUtil from '../Utils/ServerError';
import NotFoundUtil from '../Utils/NotFound';
import Text from 'Common/Types/Text';
ExpressApplication,
ExpressRequest,
ExpressResponse,
} from "CommonServer/Utils/Express";
import logger from "CommonServer/Utils/Logger";
const app: ExpressApplication = Express.getExpressApp();
app.get(
'/blog/post/:file',
async (req: ExpressRequest, res: ExpressResponse) => {
try {
const fileName: string = req.params['file'] as string;
"/blog/post/:file",
async (req: ExpressRequest, res: ExpressResponse) => {
try {
const fileName: string = req.params["file"] as string;
const blogPost: BlogPost | null = await BlogPostUtil.getBlogPost(
fileName
);
const blogPost: BlogPost | null =
await BlogPostUtil.getBlogPost(fileName);
if (!blogPost) {
return NotFoundUtil.renderNotFound(res);
}
if (!blogPost) {
return NotFoundUtil.renderNotFound(res);
}
res.render(`${ViewsPath}/Blog/Post`, {
support: false,
footerCards: true,
cta: true,
blackLogo: false,
requestDemoCta: false,
blogPost: blogPost,
});
} catch (e) {
logger.error(e);
return ServerErrorUtil.renderServerError(res);
}
res.render(`${ViewsPath}/Blog/Post`, {
support: false,
footerCards: true,
cta: true,
blackLogo: false,
requestDemoCta: false,
blogPost: blogPost,
});
} catch (e) {
logger.error(e);
return ServerErrorUtil.renderServerError(res);
}
},
);
// List all blog posts with tag
app.get(
'/blog/tag/:tagName',
async (req: ExpressRequest, res: ExpressResponse) => {
try {
const tagName: string = req.params['tagName'] as string;
"/blog/tag/:tagName",
async (req: ExpressRequest, res: ExpressResponse) => {
try {
const tagName: string = req.params["tagName"] as string;
const blogPosts: Array<BlogPostHeader> =
await BlogPostUtil.getBlogPostList(tagName);
const blogPosts: Array<BlogPostHeader> =
await BlogPostUtil.getBlogPostList(tagName);
res.render(`${ViewsPath}/Blog/ListByTag`, {
support: false,
footerCards: true,
cta: true,
blackLogo: false,
requestDemoCta: false,
blogPosts: blogPosts,
tagName: Text.fromDashesToPascalCase(tagName),
});
} catch (e) {
logger.error(e);
return ServerErrorUtil.renderServerError(res);
}
res.render(`${ViewsPath}/Blog/ListByTag`, {
support: false,
footerCards: true,
cta: true,
blackLogo: false,
requestDemoCta: false,
blogPosts: blogPosts,
tagName: Text.fromDashesToPascalCase(tagName),
});
} catch (e) {
logger.error(e);
return ServerErrorUtil.renderServerError(res);
}
},
);
// main blog page
app.get('/blog', async (_req: ExpressRequest, res: ExpressResponse) => {
try {
const blogPosts: Array<BlogPostHeader> =
await BlogPostUtil.getBlogPostList();
app.get("/blog", async (_req: ExpressRequest, res: ExpressResponse) => {
try {
const blogPosts: Array<BlogPostHeader> =
await BlogPostUtil.getBlogPostList();
res.render(`${ViewsPath}/Blog/List`, {
support: false,
footerCards: true,
cta: true,
blackLogo: false,
requestDemoCta: false,
blogPosts: blogPosts,
});
} catch (e) {
logger.error(e);
return ServerErrorUtil.renderServerError(res);
}
res.render(`${ViewsPath}/Blog/List`, {
support: false,
footerCards: true,
cta: true,
blackLogo: false,
requestDemoCta: false,
blogPosts: blogPosts,
});
} catch (e) {
logger.error(e);
return ServerErrorUtil.renderServerError(res);
}
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +0,0 @@
(function (e, t) {
var n = e.amplitude || { _q: [], _iq: {} }; var r = t.createElement("script")
; r.type = "text/javascript"
; r.integrity = "sha384-vYYnQ3LPdp/RkQjoKBTGSq0X5F73gXU3G2QopHaIfna0Ct1JRWzwrmEz115NzOta"
; r.crossOrigin = "anonymous"; r.async = true
; r.src = "https://cdn.amplitude.com/libs/amplitude-5.8.0-min.gz.js"
; r.onload = function () {
if (!e.amplitude.runQueuedFunctions) {
console.log("[Amplitude] Error: could not load SDK")
}
}
; var i = t.getElementsByTagName("script")[0]; i.parentNode.insertBefore(r, i)
; function s(e, t) {
e.prototype[t] = function () {
this._q.push([t].concat(Array.prototype.slice.call(arguments, 0))); return this
}
}
var o = function () { this._q = []; return this }
; var a = ["add", "append", "clearAll", "prepend", "set", "setOnce", "unset"]
; for (var u = 0; u < a.length; u++) { s(o, a[u]) } n.Identify = o; var c = function () {
this._q = []
; return this
}
; var l = ["setProductId", "setQuantity", "setPrice", "setRevenueType", "setEventProperties"]
; for (var p = 0; p < l.length; p++) { s(c, l[p]) } n.Revenue = c
; var d = ["init", "logEvent", "logRevenue", "setUserId", "setUserProperties", "setOptOut", "setVersionName", "setDomain", "setDeviceId", "enableTracking", "setGlobalUserProperties", "identify", "clearUserProperties", "setGroup", "logRevenueV2", "regenerateDeviceId", "groupIdentify", "onInit", "logEventWithTimestamp", "logEventWithGroups", "setSessionId", "resetSessionId"]
; function v(e) {
function t(t) {
e[t] = function () {
e._q.push([t].concat(Array.prototype.slice.call(arguments, 0)))
}
}
for (var n = 0; n < d.length; n++) { t(d[n]) }
} v(n); n.getInstance = function (e) {
e = (!e || e.length === 0 ? "$default_instance" : e).toLowerCase()
; if (!n._iq.hasOwnProperty(e)) { n._iq[e] = { _q: [] }; v(n._iq[e]) } return n._iq[e]
}
; e.amplitude = n
})(window, document);
amplitude.getInstance().init("802d95003af23aad17ed068b6cfdeb2b", null, {
// include referrer information in amplitude.
saveEvents: true,
includeUtm: true,
includeReferrer: true,
includeGclid: true
});

View File

@@ -1,94 +1,95 @@
function openTab(evt, tabName) {
// Declare all variables
let i;
// Declare all variables
let i;
// Get all elements with class="tabcontent" and hide them
const tabcontent = document.getElementsByClassName('tabcontent');
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].className = tabcontent[i].className.replace(' active', '');
}
// Get all elements with class="tabcontent" and hide them
const tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].className = tabcontent[i].className.replace(" active", "");
}
// Get all elements with class="tablinks" and remove the class "active"
const tablinks = document.getElementsByClassName('tablinks');
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(' active', '');
}
// Get all elements with class="tablinks" and remove the class "active"
const tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the link that opened the tab
// Show the current tab, and add an "active" class to the link that opened the tab
document.getElementById(tabName).className += ' active';
evt.currentTarget.className += ' active';
document.getElementById(tabName).className += " active";
evt.currentTarget.className += " active";
setTimeout(() => document.getElementById(tabName + '1').parentNode.click(), 200);
setTimeout(
() => document.getElementById(tabName + "1").parentNode.click(),
200,
);
}
function openTooltip(name) {
// Declare all variables
let i;
const element = document.getElementById(name);
// Declare all variables
let i;
const element = document.getElementById(name);
const elclass = element.className;
const elclass = element.className;
const tooltip = document.getElementsByClassName('tooltiptext');
for (i = 0; i < tooltip.length; i++) {
tooltip[i].className = tooltip[i].className.replace(' active', '');
}
if (elclass.indexOf('active') > -1) {
element.className = element.className.replace(' active', '');
}
else {
element.classList.add('active');
}
const tooltip = document.getElementsByClassName("tooltiptext");
for (i = 0; i < tooltip.length; i++) {
tooltip[i].className = tooltip[i].className.replace(" active", "");
}
if (elclass.indexOf("active") > -1) {
element.className = element.className.replace(" active", "");
} else {
element.classList.add("active");
}
}
window.onload = function () {
animateHTML().init();
const tooltext = document.getElementsByClassName('tooltiptext');
for (let i = 0; i < tooltext.length; i++) {
animateHTML().init();
const tooltext = document.getElementsByClassName("tooltiptext");
for (let i = 0; i < tooltext.length; i++) {
tooltext[i].onclick = function (e) {
e.stopPropagation();
};
}
tooltext[i].onclick = function (e) {
e.stopPropagation();
}
document.getElementsByTagName("body")[0].onclick = function (e) {
if (
e.target.className !== "popover-dot" &&
e.target.className !== "tooltiptext" &&
e.target.className !== "tablinks active"
) {
const tooltip = document.getElementsByClassName("tooltiptext");
for (let i = 0; i < tooltip.length; i++) {
tooltip[i].className = tooltip[i].className.replace(" active", "");
}
}
document.getElementsByTagName('body')[0].onclick = function (e) {
if (e.target.className !== 'popover-dot' && e.target.className !== 'tooltiptext' && e.target.className !== 'tablinks active') {
const tooltip = document.getElementsByClassName('tooltiptext');
for (let i = 0; i < tooltip.length; i++) {
tooltip[i].className = tooltip[i].className.replace(' active', '');
}
}
}
}
};
};
const animateHTML = function () {
let elem, windowHeight;
const init = function () {
elem = document.getElementById('Statuspage');
windowHeight = window.innerHeight;
_addEventHandlers();
let elem, windowHeight;
const init = function () {
elem = document.getElementById("Statuspage");
windowHeight = window.innerHeight;
_addEventHandlers();
};
const _addEventHandlers = function () {
window.addEventListener("scroll", _checkPosition);
window.addEventListener("resize", init);
};
const _checkPosition = function () {
if (!elem) {
return;
}
const _addEventHandlers = function () {
window.addEventListener('scroll', _checkPosition)
window.addEventListener('resize', init)
}
const _checkPosition = function () {
if (!elem) {
return;
}
const posFromTop = elem.getBoundingClientRect().top;
const posFromTop = elem.getBoundingClientRect().top;
if (posFromTop - windowHeight <= -400) {
document.getElementById('Statuspage1').parentNode.click();
window.removeEventListener('scroll', _checkPosition);
window.removeEventListener('resize', init);
return;
}
if (posFromTop - windowHeight <= -400) {
document.getElementById("Statuspage1").parentNode.click();
window.removeEventListener("scroll", _checkPosition);
window.removeEventListener("resize", init);
return;
}
return {
init: init
}
}
};
return {
init: init,
};
};

View File

@@ -1,5 +1,5 @@
// This is basicaly meant to get a cookie by name
var getCookiebyName = function (name) {
var pair = document.cookie.match(new RegExp(name + '=([^;]+)'));
return !!pair ? pair[1] : null;
};
var pair = document.cookie.match(new RegExp(name + "=([^;]+)"));
return pair ? pair[1] : null;
};

View File

@@ -1,69 +1,49 @@
!(function () {
function n(n, e) {
$(".hidden", n)
.eq(e)
.css({
transitionDelay: Math.random() + Math.random() + "s",
transitionDuration: 2 * Math.random() + 0.2 + "s",
}),
$(".hidden", n).eq(e).attr("class", "shown");
}
! function () {
function n(n, e) {
$('.hidden', n)
.eq(e)
.css({
transitionDelay: Math.random() + Math.random() + 's',
transitionDuration: 2 * Math.random() + .2 + 's'
}), $('.hidden', n)
.eq(e)
.attr('class', 'shown')
function e(n, e) {
if (n.hasClass("is-visible")) {
const a = $(".shown", n).eq(e);
a.attr("class", "hidden"),
setTimeout(function () {
a.attr("class", "shown");
}, 3e3);
}
function e(n, e) {
if (n.hasClass('is-visible')) {
const a = $('.shown', n)
.eq(e);
a.attr('class', 'hidden'), setTimeout(function () {
a.attr('class', 'shown')
}, 3e3)
}
}
$(".card").each(function (e, a) {
if (window.IntersectionObserver)
(a.observer = new IntersectionObserver((e) => {
e.forEach((e) => {
if (e.isIntersecting || e.intersectionRatio > 0) {
$(a).addClass("is-visible");
for (let t = $(".hidden", a).length; t >= 0; t--) n(a, t);
} else $(a).removeClass("is-visible");
});
})),
a.observer.observe(a);
else {
$(a).addClass("is-visible");
for (let t = $(".hidden", a).length; t >= 0; t--) n(a, t);
}
$('.card')
.each(function (e, a) {
if (window.IntersectionObserver) a.observer = new IntersectionObserver(e => {
e.forEach(e => {
if (e.isIntersecting || e.intersectionRatio > 0) {
$(a)
.addClass('is-visible');
for (let t = $('.hidden', a)
.length; t >= 0; t--) n(a, t)
} else $(a)
.removeClass('is-visible')
})
}), a.observer.observe(a);
else {
$(a)
.addClass('is-visible');
for (let t = $('.hidden', a)
.length; t >= 0; t--) n(a, t)
}
}), setInterval(function () {
let n = $('.card')
.eq(Math.floor(Math.random() * $('.card')
.length));
e(n, Math.floor(Math.random() * $('.shown', n)
.length));
n = $('.card')
.eq(Math.floor(Math.random() * $('.card')
.length));
e(n, Math.floor(Math.random() * $('.shown', n)
.length))
}, 600)
}();
}),
setInterval(function () {
let n = $(".card").eq(Math.floor(Math.random() * $(".card").length));
e(n, Math.floor(Math.random() * $(".shown", n).length));
n = $(".card").eq(Math.floor(Math.random() * $(".card").length));
e(n, Math.floor(Math.random() * $(".shown", n).length));
}, 600);
})();

View File

@@ -1,27 +1,26 @@
let accountsUrl = window.location.origin+'/accounts';
let backendUrl = window.location.hostname==='localhost'? 'http://localhost:3002': window.location.origin+'/api'
let accountsUrl = window.location.origin + "/accounts";
let backendUrl =
window.location.hostname === "localhost"
? "http://localhost:3002"
: window.location.origin + "/api";
//eslint-disable-next-line
function loginUrl(extra) {
if (extra) {
window.location.href = `${accountsUrl}/login${extra}`;
}
else {
window.location.href = `${accountsUrl}/login`;
}
if (extra) {
window.location.href = `${accountsUrl}/login${extra}`;
} else {
window.location.href = `${accountsUrl}/login`;
}
}
//eslint-disable-next-line
function registerUrl(params) {
if (params) {
window.location.href = `${accountsUrl}/register${params}`;
}
else {
window.location.href = `${accountsUrl}/register`;
}
if (params) {
window.location.href = `${accountsUrl}/register${params}`;
} else {
window.location.href = `${accountsUrl}/register`;
}
}
//eslint-disable-next-line
function formUrl() {
return `${backendUrl}/lead/`;
return `${backendUrl}/lead/`;
}

View File

@@ -1,3 +1,3 @@
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
test("two plus two is four", () => {
expect(2 + 2).toBe(4);
});

View File

@@ -1,489 +1,447 @@
import HTTPResponse from 'Common/Types/API/HTTPResponse';
import API from 'Common/Utils/API';
import URL from 'Common/Types/API/URL';
import { marked, Renderer } from 'marked';
import { JSONArray, JSONObject, JSONObjectOrArray } from 'Common/Types/JSON';
import BaseModel from 'Common/Models/BaseModel';
import AnalyticsBaseModel from 'Common/AnalyticsModels/BaseModel';
import LocalCache from 'CommonServer/Infrastructure/LocalCache';
import JSONFunctions from 'Common/Types/JSONFunctions';
import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse';
import OneUptimeDate from 'Common/Types/Date';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Text from 'Common/Types/Text';
import AnalyticsBaseModel from "Common/AnalyticsModels/BaseModel";
import BaseModel from "Common/Models/BaseModel";
import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse";
import HTTPResponse from "Common/Types/API/HTTPResponse";
import URL from "Common/Types/API/URL";
import OneUptimeDate from "Common/Types/Date";
import BadDataException from "Common/Types/Exception/BadDataException";
import { JSONArray, JSONObject, JSONObjectOrArray } from "Common/Types/JSON";
import JSONFunctions from "Common/Types/JSONFunctions";
import Text from "Common/Types/Text";
import API from "Common/Utils/API";
import LocalCache from "CommonServer/Infrastructure/LocalCache";
import Markdown, { MarkdownContentType } from "CommonServer/Types/Markdown";
export interface BlogPostAuthor {
username: string;
githubUrl: string;
profileImageUrl: string;
name: string;
username: string;
githubUrl: string;
profileImageUrl: string;
name: string;
}
export interface BlogPostBaseProps {
title: string;
description: string;
title: string;
description: string;
formattedPostDate: string;
fileName: string;
tags: string[];
postDate: string;
blogUrl: string;
formattedPostDate: string;
fileName: string;
tags: string[];
postDate: string;
blogUrl: string;
}
export interface BlogPostHeader extends BlogPostBaseProps {
authorGitHubUsername: string;
authorGitHubUsername: string;
}
export interface BlogPost extends BlogPostBaseProps {
htmlBody: string;
markdownBody: string;
socialMediaImageUrl: string;
author: BlogPostAuthor | null;
htmlBody: string;
markdownBody: string;
socialMediaImageUrl: string;
author: BlogPostAuthor | null;
}
const GitHubRawUrl: string =
'https://raw.githubusercontent.com/oneuptime/blog/master';
"https://raw.githubusercontent.com/oneuptime/blog/master";
export default class BlogPostUtil {
public static async getBlogPostList(
tagName?: string | undefined
): Promise<BlogPostHeader[]> {
const fileUrl: URL = URL.fromString(`${GitHubRawUrl}/Blogs.json`);
public static async getBlogPostList(
tagName?: string | undefined,
): Promise<BlogPostHeader[]> {
const fileUrl: URL = URL.fromString(`${GitHubRawUrl}/Blogs.json`);
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
if (fileData.isFailure()) {
throw fileData as HTTPErrorResponse;
}
let jsonContent: string | JSONArray =
(fileData.data as string | JSONArray) || [];
if (typeof jsonContent === 'string') {
jsonContent = JSONFunctions.parseJSONArray(jsonContent);
}
const blogs: Array<JSONObject> = JSONFunctions.deserializeArray(
jsonContent as Array<JSONObject>
).reverse(); // reverse so new content comes first
const resultList: Array<BlogPostHeader> = [];
for (const blog of blogs) {
const fileName: string = blog['post'] as string;
const formattedPostDate: string =
this.getFormattedPostDateFromFileName(fileName);
const postDate: string = this.getPostDateFromFileName(fileName);
resultList.push({
title: blog['title'] as string,
description: blog['description'] as string,
fileName,
formattedPostDate,
postDate,
tags: blog['tags'] as string[],
authorGitHubUsername: blog['authorGitHubUsername'] as string,
blogUrl: `/blog/post/${fileName}`,
});
}
if (tagName) {
return resultList.filter((blog: BlogPostHeader) => {
return blog.tags
.map((item: string) => {
return Text.replaceAll(item.toLowerCase(), ' ', '-');
})
.includes(tagName);
});
}
return resultList;
if (fileData.isFailure()) {
throw fileData as HTTPErrorResponse;
}
public static async getBlogPost(
fileName: string
): Promise<BlogPost | null> {
let blogPost: BlogPost | null = this.getBlogPostFromCache(fileName);
let jsonContent: string | JSONArray =
(fileData.data as string | JSONArray) || [];
// if (blogPost) {
// return Promise.resolve(blogPost);
// }
blogPost = await this.getBlogPostFromGitHub(fileName);
// save this to cache
LocalCache.setJSON(
'blog',
fileName,
JSONFunctions.serialize(blogPost as any)
);
return blogPost;
if (typeof jsonContent === "string") {
jsonContent = JSONFunctions.parseJSONArray(jsonContent);
}
public static async getNameOfGitHubUser(username: string): Promise<string> {
const fileUrl: URL = URL.fromString(
`https://api.github.com/users/${username}`
);
const blogs: Array<JSONObject> = JSONFunctions.deserializeArray(
jsonContent as Array<JSONObject>,
).reverse(); // reverse so new content comes first
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
const resultList: Array<BlogPostHeader> = [];
if (fileData.isFailure()) {
throw fileData as HTTPErrorResponse;
}
for (const blog of blogs) {
const fileName: string = blog["post"] as string;
const formattedPostDate: string =
this.getFormattedPostDateFromFileName(fileName);
const postDate: string = this.getPostDateFromFileName(fileName);
const name: string =
(fileData.data as JSONObject)?.['name']?.toString() || '';
return name;
resultList.push({
title: blog["title"] as string,
description: blog["description"] as string,
fileName,
formattedPostDate,
postDate,
tags: blog["tags"] as string[],
authorGitHubUsername: blog["authorGitHubUsername"] as string,
blogUrl: `/blog/post/${fileName}`,
});
}
public static async getGitHubMarkdownFileContent(
githubPath: string
): Promise<string | null> {
const fileUrl: URL = URL.fromString(`${GitHubRawUrl}/${githubPath}`);
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
if (fileData.isFailure()) {
if ((fileData as HTTPErrorResponse).statusCode === 404) {
return null;
}
throw fileData as HTTPErrorResponse;
}
const markdownContent: string =
(fileData.data as JSONObject)?.['data']?.toString() || '';
return markdownContent;
if (tagName) {
return resultList.filter((blog: BlogPostHeader) => {
return blog.tags
.map((item: string) => {
return Text.replaceAll(item.toLowerCase(), " ", "-");
})
.includes(tagName);
});
}
public static async getTags(): Promise<string[]> {
// check if tags are in cache
let tags: string[] = LocalCache.getJSON(
'blog-tags',
'tags'
) as string[];
return resultList;
}
if (tags && tags.length > 0) {
return tags;
}
public static async getBlogPost(fileName: string): Promise<BlogPost | null> {
let blogPost: BlogPost | null = this.getBlogPostFromCache(fileName);
tags = await this.getAllTagsFromGitHub();
// if (blogPost) {
// return Promise.resolve(blogPost);
// }
// save this to cache
blogPost = await this.getBlogPostFromGitHub(fileName);
LocalCache.setJSON(
'blog-tags',
'tags',
JSONFunctions.serialize(tags as any)
);
// save this to cache
LocalCache.setJSON(
"blog",
fileName,
JSONFunctions.serialize(blogPost as any),
);
return tags;
return blogPost;
}
public static async getNameOfGitHubUser(username: string): Promise<string> {
const fileUrl: URL = URL.fromString(
`https://api.github.com/users/${username}`,
);
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
if (fileData.isFailure()) {
throw fileData as HTTPErrorResponse;
}
public static async getAllTagsFromGitHub(): Promise<string[]> {
const tagsMarkdownContent: string | null =
await this.getGitHubMarkdownFileContent('Tags.md');
const name: string =
(fileData.data as JSONObject)?.["name"]?.toString() || "";
return name;
}
if (!tagsMarkdownContent) {
return [];
}
public static async getGitHubMarkdownFileContent(
githubPath: string,
): Promise<string | null> {
const fileUrl: URL = URL.fromString(`${GitHubRawUrl}/${githubPath}`);
const tags: Array<string> = tagsMarkdownContent
.split('\n')
.map((tag: string) => {
return tag.trim();
})
.filter((tag: string) => {
return tag.startsWith('-');
})
.map((tag: string) => {
return tag.replace('-', '').trim();
});
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
return tags;
if (fileData.isFailure()) {
if ((fileData as HTTPErrorResponse).statusCode === 404) {
return null;
}
throw fileData as HTTPErrorResponse;
}
public static async getBlogPostFromGitHub(
fileName: string
): Promise<BlogPost | null> {
const fileUrl: URL = URL.fromString(
`${GitHubRawUrl}/posts/${fileName}/README.md`
);
const markdownContent: string =
(fileData.data as JSONObject)?.["data"]?.toString() || "";
return markdownContent;
}
const postDate: string = this.getPostDateFromFileName(fileName);
const formattedPostDate: string =
this.getFormattedPostDateFromFileName(fileName);
public static async getTags(): Promise<string[]> {
// check if tags are in cache
let tags: string[] = LocalCache.getJSON("blog-tags", "tags") as string[];
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
if (fileData.isFailure()) {
if ((fileData as HTTPErrorResponse).statusCode === 404) {
return null;
}
throw fileData as HTTPErrorResponse;
}
let markdownContent: string =
(fileData.data as JSONObject)?.['data']?.toString() || '';
const blogPostAuthor: BlogPostAuthor | null =
await this.getAuthorFromFileContent(markdownContent);
const title: string = this.getTitleFromFileContent(markdownContent);
const description: string =
this.getDescriptionFromFileContent(markdownContent);
const tags: Array<string> =
this.getTagsFromFileContent(markdownContent);
markdownContent = this.getPostFromMarkdown(markdownContent);
const renderer: Renderer = this.getBlogRenderer();
const htmlBody: string = await marked(markdownContent, {
renderer: renderer,
});
const blogPost: BlogPost = {
title,
description,
author: blogPostAuthor,
htmlBody,
markdownBody: markdownContent,
fileName,
tags,
postDate,
formattedPostDate,
socialMediaImageUrl: `${GitHubRawUrl}/posts/${fileName}/social-media.png`,
blogUrl: `https://oneuptime.com/blog/post/${fileName}`, // this has to be oneuptime.com because its used in twitter cards and faceboomk cards. Please dont change this.
};
return blogPost;
if (tags && tags.length > 0) {
return tags;
}
private static getPostDateFromFileName(fileName: string): string {
const year: string | undefined = fileName.split('-')[0];
const month: string | undefined = fileName.split('-')[1];
const day: string | undefined = fileName.split('-')[2];
tags = await this.getAllTagsFromGitHub();
if (!year || !month || !day) {
throw new BadDataException('Invalid file name');
}
// save this to cache
return `${year}-${month}-${day}`;
LocalCache.setJSON(
"blog-tags",
"tags",
JSONFunctions.serialize(tags as any),
);
return tags;
}
public static async getAllTagsFromGitHub(): Promise<string[]> {
const tagsMarkdownContent: string | null =
await this.getGitHubMarkdownFileContent("Tags.md");
if (!tagsMarkdownContent) {
return [];
}
private static getFormattedPostDateFromFileName(fileName: string): string {
// file name is of the format YYYY-MM-DD-Title.md
const year: string | undefined = fileName.split('-')[0];
const month: string | undefined = fileName.split('-')[1];
const day: string | undefined = fileName.split('-')[2];
const tags: Array<string> = tagsMarkdownContent
.split("\n")
.map((tag: string) => {
return tag.trim();
})
.filter((tag: string) => {
return tag.startsWith("-");
})
.map((tag: string) => {
return tag.replace("-", "").trim();
});
if (!year || !month || !day) {
throw new BadDataException('Invalid file name');
}
return tags;
}
const date: Date = OneUptimeDate.getDateFromYYYYMMDD(year, month, day);
return OneUptimeDate.getDateAsLocalFormattedString(date, true);
public static async getBlogPostFromGitHub(
fileName: string,
): Promise<BlogPost | null> {
const fileUrl: URL = URL.fromString(
`${GitHubRawUrl}/posts/${fileName}/README.md`,
);
const postDate: string = this.getPostDateFromFileName(fileName);
const formattedPostDate: string =
this.getFormattedPostDateFromFileName(fileName);
const fileData:
| HTTPResponse<
| JSONObjectOrArray
| BaseModel
| BaseModel[]
| AnalyticsBaseModel
| AnalyticsBaseModel[]
>
| HTTPErrorResponse = await API.get(fileUrl);
if (fileData.isFailure()) {
if ((fileData as HTTPErrorResponse).statusCode === 404) {
return null;
}
throw fileData as HTTPErrorResponse;
}
private static getBlogRenderer(): Renderer {
const renderer: Renderer = new Renderer();
let markdownContent: string =
(fileData.data as JSONObject)?.["data"]?.toString() || "";
renderer.paragraph = function (text) {
return `<p class="mt-2 mb-2 leading-8 text-gray-600">${text}</p>`;
};
const blogPostAuthor: BlogPostAuthor | null =
await this.getAuthorFromFileContent(markdownContent);
renderer.blockquote = function (quote) {
return `<blockquote class="p-4 pt-1 pb-1 my-4 border-s-4 border-indigo-500">
<div class="leading-8 text-gray-600">${quote}</div>
</blockquote>`;
};
const title: string = this.getTitleFromFileContent(markdownContent);
const description: string =
this.getDescriptionFromFileContent(markdownContent);
const tags: Array<string> = this.getTagsFromFileContent(markdownContent);
renderer.code = function (code, language) {
return `<pre class="language-${language} rounded-md"><code class="language-${language} rounded-md">${code}</code></pre>`;
};
markdownContent = this.getPostFromMarkdown(markdownContent);
renderer.heading = function (text, level) {
if (level === 1) {
return `<h1 class="my-5 mt-8 text-4xl font-bold tracking-tight text-gray-800">${text}</h1>`;
} else if (level === 2) {
return `<h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">${text}</h2>`;
} else if (level === 3) {
return `<h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">${text}</h3>`;
} else if (level === 4) {
return `<h4 class="my-5 mt-8 text-xl font-bold tracking-tight text-gray-800">${text}</h4>`;
} else if (level === 5) {
return `<h5 class="my-5 mt-8 text-lg font-bold tracking-tight text-gray-800">${text}</h5>`;
}
return `<h6 class="my-5 tracking-tight font-bold text-gray-800">${text}</h6>`;
};
const htmlBody: string = await Markdown.convertToHTML(
markdownContent,
MarkdownContentType.Blog,
);
return renderer;
const blogPost: BlogPost = {
title,
description,
author: blogPostAuthor,
htmlBody,
markdownBody: markdownContent,
fileName,
tags,
postDate,
formattedPostDate,
socialMediaImageUrl: `${GitHubRawUrl}/posts/${fileName}/social-media.png`,
blogUrl: `https://oneuptime.com/blog/post/${fileName}`, // this has to be oneuptime.com because its used in twitter cards and faceboomk cards. Please dont change this.
};
return blogPost;
}
private static getPostDateFromFileName(fileName: string): string {
const year: string | undefined = fileName.split("-")[0];
const month: string | undefined = fileName.split("-")[1];
const day: string | undefined = fileName.split("-")[2];
if (!year || !month || !day) {
throw new BadDataException("Invalid file name");
}
private static getPostFromMarkdown(markdownContent: string): string {
const authorLine: string | undefined = markdownContent
.split('\n')
.find((line: string) => {
return line.startsWith('Author:');
});
const titleLine: string | undefined = markdownContent
.split('\n')
.find((line: string) => {
return line.startsWith('#');
});
const descriptionLine: string | undefined =
markdownContent.split('\n').find((line: string) => {
return line.startsWith('Description:');
}) || '';
return `${year}-${month}-${day}`;
}
const tagsLine: string | undefined =
markdownContent.split('\n').find((line: string) => {
return line.startsWith('Tags:');
}) || '';
private static getFormattedPostDateFromFileName(fileName: string): string {
// file name is of the format YYYY-MM-DD-Title.md
const year: string | undefined = fileName.split("-")[0];
const month: string | undefined = fileName.split("-")[1];
const day: string | undefined = fileName.split("-")[2];
if (!authorLine && !titleLine && !descriptionLine && !tagsLine) {
return markdownContent;
}
const lines: string[] = markdownContent.split('\n');
if (authorLine) {
const authorLineIndex: number = lines.indexOf(authorLine);
lines.splice(authorLineIndex, 1);
}
if (titleLine) {
const titleLineIndex: number = lines.indexOf(titleLine);
lines.splice(titleLineIndex, 1);
}
if (descriptionLine) {
const descriptionLineIndex: number = lines.indexOf(descriptionLine);
lines.splice(descriptionLineIndex, 1);
}
if (tagsLine) {
const tagsLineIndex: number = lines.indexOf(tagsLine);
lines.splice(tagsLineIndex, 1);
}
return lines.join('\n').trim();
if (!year || !month || !day) {
throw new BadDataException("Invalid file name");
}
public static getBlogPostFromCache(fileName: string): BlogPost | null {
const blogPost: BlogPost | null = LocalCache.getJSON(
'blog',
fileName
) as BlogPost | null;
return blogPost;
const date: Date = OneUptimeDate.getDateFromYYYYMMDD(year, month, day);
return OneUptimeDate.getDateAsLocalFormattedString(date, true);
}
private static getPostFromMarkdown(markdownContent: string): string {
const authorLine: string | undefined = markdownContent
.split("\n")
.find((line: string) => {
return line.startsWith("Author:");
});
const titleLine: string | undefined = markdownContent
.split("\n")
.find((line: string) => {
return line.startsWith("#");
});
const descriptionLine: string | undefined =
markdownContent.split("\n").find((line: string) => {
return line.startsWith("Description:");
}) || "";
const tagsLine: string | undefined =
markdownContent.split("\n").find((line: string) => {
return line.startsWith("Tags:");
}) || "";
if (!authorLine && !titleLine && !descriptionLine && !tagsLine) {
return markdownContent;
}
public static getTitleFromFileContent(fileContent: string): string {
// title is the first line that stars with "#"
const lines: string[] = markdownContent.split("\n");
const titleLine: string =
fileContent
.split('\n')
.find((line: string) => {
return line.startsWith('#');
})
?.replace('#', '') || 'OneUptime Blog';
return titleLine;
if (authorLine) {
const authorLineIndex: number = lines.indexOf(authorLine);
lines.splice(authorLineIndex, 1);
}
public static getTagsFromFileContent(fileContent: string): string[] {
// tags is the first line that starts with "Tags:"
const tagsLine: string | undefined =
fileContent
.split('\n')
.find((line: string) => {
return line.startsWith('Tags:');
})
?.replace('Tags:', '') || '';
return tagsLine.split(',').map((tag: string) => {
return tag.trim();
});
if (titleLine) {
const titleLineIndex: number = lines.indexOf(titleLine);
lines.splice(titleLineIndex, 1);
}
public static getDescriptionFromFileContent(fileContent: string): string {
// description is the first line that starts with ">"
const descriptionLine: string | undefined =
fileContent
.split('\n')
.find((line: string) => {
return line.startsWith('Description:');
})
?.replace('Description:', '') || '';
return descriptionLine;
if (descriptionLine) {
const descriptionLineIndex: number = lines.indexOf(descriptionLine);
lines.splice(descriptionLineIndex, 1);
}
public static async getAuthorFromFileContent(
fileContent: string
): Promise<BlogPostAuthor | null> {
// author line is in this format: Author: [username](githubUrl)
const authorLine: string | undefined = fileContent
.split('\n')
.find((line: string) => {
return line.startsWith('Author:');
});
const authorUsername: string | undefined = authorLine
?.split('[')[1]
?.split(']')[0];
const authorGitHubUrl: string | undefined = authorLine
?.split('(')[1]
?.split(')')[0];
const authorProfileImageUrl: string = `https://avatars.githubusercontent.com/${authorUsername}`;
if (!authorUsername || !authorGitHubUrl) {
return null;
}
return {
username: authorUsername,
githubUrl: authorGitHubUrl,
profileImageUrl: authorProfileImageUrl,
name: await this.getNameOfGitHubUser(authorUsername),
};
if (tagsLine) {
const tagsLineIndex: number = lines.indexOf(tagsLine);
lines.splice(tagsLineIndex, 1);
}
return lines.join("\n").trim();
}
public static getBlogPostFromCache(fileName: string): BlogPost | null {
const blogPost: BlogPost | null = LocalCache.getJSON(
"blog",
fileName,
) as BlogPost | null;
return blogPost;
}
public static getTitleFromFileContent(fileContent: string): string {
// title is the first line that stars with "#"
const titleLine: string =
fileContent
.split("\n")
.find((line: string) => {
return line.startsWith("#");
})
?.replace("#", "") || "OneUptime Blog";
return titleLine;
}
public static getTagsFromFileContent(fileContent: string): string[] {
// tags is the first line that starts with "Tags:"
const tagsLine: string | undefined =
fileContent
.split("\n")
.find((line: string) => {
return line.startsWith("Tags:");
})
?.replace("Tags:", "") || "";
return tagsLine.split(",").map((tag: string) => {
return tag.trim();
});
}
public static getDescriptionFromFileContent(fileContent: string): string {
// description is the first line that starts with ">"
const descriptionLine: string | undefined =
fileContent
.split("\n")
.find((line: string) => {
return line.startsWith("Description:");
})
?.replace("Description:", "") || "";
return descriptionLine;
}
public static async getAuthorFromFileContent(
fileContent: string,
): Promise<BlogPostAuthor | null> {
// author line is in this format: Author: [username](githubUrl)
const authorLine: string | undefined = fileContent
.split("\n")
.find((line: string) => {
return line.startsWith("Author:");
});
const authorUsername: string | undefined = authorLine
?.split("[")[1]
?.split("]")[0];
const authorGitHubUrl: string | undefined = authorLine
?.split("(")[1]
?.split(")")[0];
const authorProfileImageUrl: string = `https://avatars.githubusercontent.com/${authorUsername}`;
if (!authorUsername || !authorGitHubUrl) {
return null;
}
return {
username: authorUsername,
githubUrl: authorGitHubUrl,
profileImageUrl: authorProfileImageUrl,
name: await this.getNameOfGitHubUser(authorUsername),
};
}
}

View File

@@ -1,2 +1,2 @@
export const ViewsPath: string = '/usr/src/app/FeatureSet/Home/Views';
export const StaticPath: string = '/usr/src/app/FeatureSet/Home/Static';
export const ViewsPath: string = "/usr/src/app/FeatureSet/Home/Views";
export const StaticPath: string = "/usr/src/app/FeatureSet/Home/Static";

View File

@@ -1,15 +1,15 @@
import { ExpressResponse } from 'CommonServer/Utils/Express';
import { ViewsPath } from './Config';
import { ViewsPath } from "./Config";
import { ExpressResponse } from "CommonServer/Utils/Express";
export default class NotFoundUtil {
public static renderNotFound(res: ExpressResponse): void {
res.status(404);
res.render(`${ViewsPath}/not-found.ejs`, {
footerCards: false,
support: false,
cta: false,
blackLogo: false,
requestDemoCta: false,
});
}
public static renderNotFound(res: ExpressResponse): void {
res.status(404);
res.render(`${ViewsPath}/not-found.ejs`, {
footerCards: false,
support: false,
cta: false,
blackLogo: false,
requestDemoCta: false,
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,15 @@
import { ExpressResponse } from 'CommonServer/Utils/Express';
import { ViewsPath } from './Config';
import { ViewsPath } from "./Config";
import { ExpressResponse } from "CommonServer/Utils/Express";
export default class ServerErrorUtil {
public static renderServerError(res: ExpressResponse): void {
res.status(500);
res.render(`${ViewsPath}/server-error.ejs`, {
footerCards: false,
support: false,
cta: false,
blackLogo: false,
requestDemoCta: false,
});
}
public static renderServerError(res: ExpressResponse): void {
res.status(500);
res.render(`${ViewsPath}/server-error.ejs`, {
footerCards: false,
support: false,
cta: false,
blackLogo: false,
requestDemoCta: false,
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,79 +1,79 @@
import OneUptimeDate from "Common/Types/Date";
import BadDataException from "Common/Types/Exception/BadDataException";
import ResellerService from "CommonServer/Services/ResellerService";
import Express, {
ExpressRequest,
ExpressResponse,
ExpressRouter,
NextFunction,
} from 'CommonServer/Utils/Express';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Reseller from 'Model/Models/Reseller';
import ResellerService from 'CommonServer/Services/ResellerService';
import JSONWebToken from 'CommonServer/Utils/JsonWebToken';
import OneUptimeDate from 'Common/Types/Date';
import Response from 'CommonServer/Utils/Response';
ExpressRequest,
ExpressResponse,
ExpressRouter,
NextFunction,
} from "CommonServer/Utils/Express";
import JSONWebToken from "CommonServer/Utils/JsonWebToken";
import Response from "CommonServer/Utils/Response";
import Reseller from "Model/Models/Reseller";
const router: ExpressRouter = Express.getRouter();
router.post(
'/reseller/auth/:resellerid',
async (
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction
): Promise<void> => {
try {
const resellerId: string | undefined = req.params['resellerid'];
"/reseller/auth/:resellerid",
async (
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction,
): Promise<void> => {
try {
const resellerId: string | undefined = req.params["resellerid"];
if (!resellerId) {
throw new BadDataException('Reseller ID not found');
}
if (!resellerId) {
throw new BadDataException("Reseller ID not found");
}
const username: string = req.body['username'];
const password: string = req.body['password'];
const username: string = req.body["username"];
const password: string = req.body["password"];
if (!username) {
throw new BadDataException('Username not found');
}
if (!username) {
throw new BadDataException("Username not found");
}
if (!password) {
throw new BadDataException('Password not found');
}
if (!password) {
throw new BadDataException("Password not found");
}
// get the reseller user.
const reseller: Reseller | null = await ResellerService.findOneBy({
query: {
resellerId: resellerId,
username: username,
password: password,
},
select: {
_id: true,
resellerId: true,
},
props: {
isRoot: true,
},
});
// get the reseller user.
const reseller: Reseller | null = await ResellerService.findOneBy({
query: {
resellerId: resellerId,
username: username,
password: password,
},
select: {
_id: true,
resellerId: true,
},
props: {
isRoot: true,
},
});
if (!reseller) {
throw new BadDataException(
'Reseller not found or username and password is incorrect'
);
}
if (!reseller) {
throw new BadDataException(
"Reseller not found or username and password is incorrect",
);
}
// if found then generate a token and return it.
// if found then generate a token and return it.
const token: string = JSONWebToken.sign({
data: { resellerId: resellerId },
expiresInSeconds: OneUptimeDate.getDayInSeconds(365),
});
const token: string = JSONWebToken.sign({
data: { resellerId: resellerId },
expiresInSeconds: OneUptimeDate.getDayInSeconds(365),
});
return Response.sendJsonObjectResponse(req, res, {
access: token,
});
} catch (err) {
return next(err);
}
return Response.sendJsonObjectResponse(req, res, {
access: token,
});
} catch (err) {
return next(err);
}
},
);
export default router;

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