diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 81dcf7078..4452a25aa 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,8 @@ updates: directory: "/" schedule: interval: "weekly" + - package-ecosystem: "github-actions" + # Workflow files stored in the default location of `.github/workflows`. (You don't need to specify `/.github/workflows` for `directory`. You can use `directory: "/"`.) + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index aa7713131..dddc44420 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -4,9 +4,6 @@ on: workflow_dispatch: push: branches: [ 'develop', 'master', 'releases/**' ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ 'develop', 'master', 'releases/**' ] schedule: - cron: '19 7 * * 4' diff --git a/.github/workflows/scp-deploy.yml b/.github/workflows/scp-deploy.yml index 1ea4bfdf8..19a266d87 100644 --- a/.github/workflows/scp-deploy.yml +++ b/.github/workflows/scp-deploy.yml @@ -7,9 +7,9 @@ jobs: scp-deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 21 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 21 distribution: 'temurin' diff --git a/docs-private/Developer-How-To-Start.md b/docs-private/Developer-How-To-Start.md index f8be00deb..798cf8582 100644 --- a/docs-private/Developer-How-To-Start.md +++ b/docs-private/Developer-How-To-Start.md @@ -21,3 +21,24 @@ Others (like URL, username, password) depend on your environment. ```shell liquibase --changelog-file=./docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml --url=jdbc:postgresql://localhost:5432/powerauth --username=powerauth status ``` + +To generate SQL script run following command: + +#### PostgreSQL + +```shell +liquibase --changeLogFile=./docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml --output-file=./docs/sql/postgresql/migration_1.7.0_1.8.0.sql updateSQL --url=offline:postgresql +``` + +#### Oracle + +```shell +liquibase --changeLogFile=./docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml --output-file=./docs/sql/oracle/migration_1.7.0_1.8.0.sql updateSQL --url=offline:oracle +``` + + +#### MSSQL + +```shell +liquibase --changeLogFile=./docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml --output-file=./docs/sql/mssql/migration_1.7.0_1.8.0.sql updateSQL --url=offline:mssql +``` diff --git a/docs/Configuration-Properties.md b/docs/Configuration-Properties.md index abf29072c..e46015565 100644 --- a/docs/Configuration-Properties.md +++ b/docs/Configuration-Properties.md @@ -14,12 +14,14 @@ The Push Server uses the following public configuration properties: ## PowerAuth Service Configuration -| Property | Default | Note | -|---|---|---| -| `powerauth.service.url` | `http://localhost:8080/powerauth-java-server/rest` | PowerAuth service REST API base URL | -| `powerauth.service.security.clientToken` | `_empty_` | PowerAuth REST API authentication token | -| `powerauth.service.security.clientSecret` | `_empty_` | PowerAuth REST API authentication secret / password | -| `powerauth.service.ssl.acceptInvalidSslCertificate` | `false` | Flag indicating if connections using untrusted TLS certificate should be made to the PowerAuth Service | +| Property | Default | Note | +|------------------------------------------------------|----------------------------------------------------|--------------------------------------------------------------------------------------------------------| +| `powerauth.service.url` | `http://localhost:8080/powerauth-java-server/rest` | PowerAuth service REST API base URL | +| `powerauth.service.restClientConfig.responseTimeout` | `60s` | PowerAuth REST API response timeout. | +| `powerauth.service.restClientConfig.maxIdleTime` | `200s` | PowerAuth REST API max idle time. | +| `powerauth.service.security.clientToken` | `_empty_` | PowerAuth REST API authentication token | +| `powerauth.service.security.clientSecret` | `_empty_` | PowerAuth REST API authentication secret / password | +| `powerauth.service.ssl.acceptInvalidSslCertificate` | `false` | Flag indicating if connections using untrusted TLS certificate should be made to the PowerAuth Service | ## PowerAuth Push Service Configuration @@ -99,8 +101,10 @@ The Push Server uses the following public configuration properties: ## Monitoring and Observability + | Property | Default | Note | |-------------------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `management.tracing.sampling.probability` | `1.0` | Specifies the proportion of requests that are sampled for tracing. A value of 1.0 means that 100% of requests are sampled, while a value of 0 effectively disables tracing. | + The WAR file includes the `micrometer-registry-prometheus` dependency. Discuss its configuration with the [Spring Boot documentation](https://docs.spring.io/spring-boot/docs/3.1.x/reference/html/actuator.html#actuator.metrics). diff --git a/docs/Deploying-Push-Server.md b/docs/Deploying-Push-Server.md index 825c5744f..5d1bf96ea 100644 --- a/docs/Deploying-Push-Server.md +++ b/docs/Deploying-Push-Server.md @@ -46,14 +46,6 @@ powerauth.service.url=http://localhost:8080/powerauth-java-server/rest There are several optional configuration options you may want to set up. -### Configuration of Push service URL - -Push server contains REST API which needs to be configured in case Push Server runs on non-standard port, non-standard context path or uses HTTPS. You can configure the service URL using following property: - -``` -powerauth.push.service.url=http://localhost:8080/powerauth-push-server -``` - ### Enabling Storing of Sent Push Messages You can enable storing of sent messages in database using following property: diff --git a/docs/Deploying-Wildfly.md b/docs/Deploying-Wildfly.md index 05b2cbeaa..5c93838ce 100644 --- a/docs/Deploying-Wildfly.md +++ b/docs/Deploying-Wildfly.md @@ -6,7 +6,7 @@ Push Server contains the following configuration in `jboss-deployment-structure. ```xml - + @@ -83,15 +83,14 @@ Use the `logback.xml` file to configure logging, for example: The `application-ext.properties` file is used to override default configuration properties, for example: ``` +spring.datasource.jndi-name=java:/jdbc/powerauth + # PowerAuth 2.0 Client configuration powerauth.service.url=https://[host]:[port]/powerauth-java-server/rest ``` -Push Server Spring application uses the `ext` Spring profile which activates overriding of default properties by `application-ext.properties`. - -### Bouncy Castle Installation +Mind that you should specify `spring.datasource.jndi-name` to use the application server datasource (its declaration is out of the scope of this guideline). +When configure `spring.datasource.url`, the hikari connection pool is used. +Spring Boot running on WildFly or JBoos initializes [JtaTransactionManager](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/jta/JtaTransactionManager.html). -The Bouncy Castle module for JBoss / Wildfly needs to be enabled as a global module for Push Server. - -Follow the instructions in the [Installing Bouncy Castle](https://github.com/wultra/powerauth-server/blob/develop/docs/Installing-Bouncy-Castle.md) chapter of PowerAuth Server documentation. -Note that the instructions differ based on Java version and application server type. +Push Server Spring application uses the `ext` Spring profile which activates overriding of default properties by `application-ext.properties`. diff --git a/docs/Migration-Instructions.md b/docs/Migration-Instructions.md index 4a5193988..c44f1837a 100644 --- a/docs/Migration-Instructions.md +++ b/docs/Migration-Instructions.md @@ -2,6 +2,7 @@ This page contains PowerAuth Push Server migration instructions. +- [PowerAuth Push Server 1.8.0](./PowerAuth-Push-Server-1.8.0.md) - [PowerAuth Push Server 1.7.0](./PowerAuth-Push-Server-1.7.0.md) - [PowerAuth Push Server 1.6.0](./PowerAuth-Push-Server-1.6.0.md) - [PowerAuth Push Server 1.5.0](./PowerAuth-Push-Server-1.5.0.md) diff --git a/docs/PowerAuth-Push-Server-1.8.0.md b/docs/PowerAuth-Push-Server-1.8.0.md new file mode 100644 index 000000000..2a8b84815 --- /dev/null +++ b/docs/PowerAuth-Push-Server-1.8.0.md @@ -0,0 +1,16 @@ +# Migration from 1.7.x to 1.8.x + +This guide contains instructions for migration from PowerAuth Push Server version `1.7.x` to version `1.8.x`. + + +## Database Changes + +For convenience, you can use liquibase for your database migration. + +**Important: Upgrading to version 1.8.x includes database column renaming required for the Inbox functionality, resulting in incompatible changes. Therefore, ensure all Push Server nodes are upgraded simultaneously during a scheduled service window.** + +If you prefer to make manual DB schema changes, please use the following SQL scripts: + +- [PostgreSQL script](./sql/postgresql/migration_1.7.0_1.8.0.sql) +- [Oracle script](./sql/oracle/migration_1.7.0_1.8.0.sql) +- [MSSQL script](./sql/mssql/migration_1.7.0_1.8.0.sql) \ No newline at end of file diff --git a/docs/db/changelog/changesets/powerauth-push-server/1.8.x/20240708-column-renaming-keywords.xml b/docs/db/changelog/changesets/powerauth-push-server/1.8.x/20240708-column-renaming-keywords.xml new file mode 100644 index 000000000..33ccdc4bb --- /dev/null +++ b/docs/db/changelog/changesets/powerauth-push-server/1.8.x/20240708-column-renaming-keywords.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + Rename columns read to is_read and type to message_type in push_inbox table + + + + + \ No newline at end of file diff --git a/docs/db/changelog/changesets/powerauth-push-server/1.8.x/db.changelog-version.xml b/docs/db/changelog/changesets/powerauth-push-server/1.8.x/db.changelog-version.xml new file mode 100644 index 000000000..934825527 --- /dev/null +++ b/docs/db/changelog/changesets/powerauth-push-server/1.8.x/db.changelog-version.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml b/docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml index 0253cdde1..9b81cae22 100644 --- a/docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml +++ b/docs/db/changelog/changesets/powerauth-push-server/db.changelog-module.xml @@ -10,5 +10,6 @@ + diff --git a/docs/sql/mssql/create_push_server_schema.sql b/docs/sql/mssql/create_push_server_schema.sql new file mode 100644 index 000000000..056c68a0d --- /dev/null +++ b/docs/sql/mssql/create_push_server_schema.sql @@ -0,0 +1,148 @@ +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::1::Lubos Racansky +-- Create a new sequence push_credentials_seq +CREATE SEQUENCE push_credentials_seq START WITH 1 INCREMENT BY 1; +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::2::Lubos Racansky +-- Create a new sequence sequence push_device_registration_seq +CREATE SEQUENCE push_device_registration_seq START WITH 1 INCREMENT BY 1; +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::3::Lubos Racansky +-- Create a new sequence sequence push_message_seq +CREATE SEQUENCE push_message_seq START WITH 1 INCREMENT BY 1; +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::4::Lubos Racansky +-- Create a new sequence sequence push_campaign_seq +CREATE SEQUENCE push_campaign_seq START WITH 1 INCREMENT BY 1; +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::5::Lubos Racansky +-- Create a new sequence sequence push_campaign_user_seq +CREATE SEQUENCE push_campaign_user_seq START WITH 1 INCREMENT BY 1; +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::6::Lubos Racansky +-- Create a new sequence sequence push_inbox_seq +CREATE SEQUENCE push_inbox_seq START WITH 1 INCREMENT BY 1; +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::7::Lubos Racansky +-- Create a new sequence push_app_credentials +CREATE TABLE push_app_credentials (id int NOT NULL, app_id varchar(255) NOT NULL, ios_key_id varchar(255), ios_private_key varbinary(MAX), ios_team_id varchar(255), ios_bundle varchar(255), ios_environment varchar(32), android_private_key varbinary(MAX), android_project_id varchar(255), CONSTRAINT PK_PUSH_APP_CREDENTIALS PRIMARY KEY (id)); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::8::Lubos Racansky +-- Create a new sequence push_device_registration +CREATE TABLE push_device_registration (id int NOT NULL, activation_id varchar(37), user_id varchar(255), app_id int NOT NULL, platform varchar(255) NOT NULL, push_token varchar(255) NOT NULL, timestamp_last_registered datetime2(6) NOT NULL, is_active bit, CONSTRAINT PK_PUSH_DEVICE_REGISTRATION PRIMARY KEY (id)); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::9::Lubos Racansky +-- Create a new sequence push_message +CREATE TABLE push_message (id int NOT NULL, device_registration_id int NOT NULL, user_id varchar(255) NOT NULL, activation_id varchar(37), is_silent bit CONSTRAINT DF_push_message_is_silent DEFAULT 0 NOT NULL, is_personal bit CONSTRAINT DF_push_message_is_personal DEFAULT 0 NOT NULL, message_body varchar(2048) NOT NULL, timestamp_created datetime2(6) NOT NULL, status int NOT NULL, CONSTRAINT PK_PUSH_MESSAGE PRIMARY KEY (id)); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::10::Lubos Racansky +-- Create a new sequence push_campaign +CREATE TABLE push_campaign (id int NOT NULL, app_id int NOT NULL, message varchar(4000) NOT NULL, is_sent bit CONSTRAINT DF_push_campaign_is_sent DEFAULT 0 NOT NULL, timestamp_created datetime2(6) NOT NULL, timestamp_sent datetime2(6), timestamp_completed datetime2(6), CONSTRAINT PK_PUSH_CAMPAIGN PRIMARY KEY (id)); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::11::Lubos Racansky +-- Create a new sequence push_campaign_user +CREATE TABLE push_campaign_user (id int NOT NULL, campaign_id int NOT NULL, user_id varchar(255) NOT NULL, timestamp_created datetime2(6) NOT NULL, CONSTRAINT PK_PUSH_CAMPAIGN_USER PRIMARY KEY (id)); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::12::Lubos Racansky +-- Create a new table push_inbox +CREATE TABLE push_inbox (id int NOT NULL, inbox_id varchar(37) NOT NULL, user_id varchar(255) NOT NULL, type varchar(32) NOT NULL, subject varchar (max) NOT NULL, summary varchar (max) NOT NULL, body varchar (max) NOT NULL, [read] bit CONSTRAINT DF_push_inbox_read DEFAULT 0 NOT NULL, timestamp_created datetime2 NOT NULL, timestamp_read datetime2, CONSTRAINT PK_PUSH_INBOX PRIMARY KEY (id)); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::13::Lubos Racansky +-- Create a new sequence push_inbox_app +CREATE TABLE push_inbox_app (app_credentials_id int NOT NULL, inbox_id int NOT NULL, CONSTRAINT PK_PUSH_INBOX_APP PRIMARY KEY (app_credentials_id, inbox_id)); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::14::Lubos Racansky +-- Create a new unique index on push_app_credentials(app_id) +CREATE UNIQUE NONCLUSTERED INDEX push_app_cred_app ON push_app_credentials(app_id); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::15::Lubos Racansky +-- Create a new index on push_device_registration(app_id, push_token) +CREATE NONCLUSTERED INDEX push_device_app_token ON push_device_registration(app_id, push_token); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::16::Lubos Racansky +-- Create a new index on push_device_registration(user_id, app_id) +CREATE NONCLUSTERED INDEX push_device_user_app ON push_device_registration(user_id, app_id); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::17::Lubos Racansky +-- Create a new unique index on push_device_registration(activation_id) +CREATE UNIQUE NONCLUSTERED INDEX push_device_activation ON push_device_registration(activation_id); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::18::Lubos Racansky +-- Create a new unique index on push_device_registration(activation_id, push_token) +CREATE UNIQUE NONCLUSTERED INDEX push_device_activation_token ON push_device_registration(activation_id, push_token); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::19::Lubos Racansky +-- Create a new index on push_message(status) +CREATE NONCLUSTERED INDEX push_message_status ON push_message(status); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::20::Lubos Racansky +-- Create a new index on push_campaign(is_sent) +CREATE NONCLUSTERED INDEX push_campaign_sent ON push_campaign(is_sent); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::21::Lubos Racansky +-- Create a new index on push_campaign_user(campaign_id, user_id) +CREATE NONCLUSTERED INDEX push_campaign_user_campaign ON push_campaign_user(campaign_id, user_id); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::22::Lubos Racansky +-- Create a new index on push_campaign_user(user_id) +CREATE NONCLUSTERED INDEX push_campaign_user_detail ON push_campaign_user(user_id); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::23::Lubos Racansky +-- Create a new index on push_inbox(inbox_id) +CREATE NONCLUSTERED INDEX push_inbox_id ON push_inbox(inbox_id); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::24::Lubos Racansky +-- Create a new index on push_inbox(user_id) +CREATE NONCLUSTERED INDEX push_inbox_user ON push_inbox(user_id); +GO + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::25::Lubos Racansky +-- Create a new index on push_inbox(user_id, read) +CREATE NONCLUSTERED INDEX push_inbox_user_read ON push_inbox(user_id, [read]); +GO + +-- Changeset powerauth-push-server/1.4.x/20230322-add-tag-1.4.0.xml::1::Lubos Racansky +-- Changeset powerauth-push-server/1.5.x/20230905-add-tag-1.5.0.xml::1::Lubos Racansky +-- Changeset powerauth-push-server/1.7.x/20240119-push_app_credentials-hms.xml::1::Lubos Racansky +-- Add hms_project_id, hms_client_id, and hms_client_secret columns to push_app_credentials +ALTER TABLE push_app_credentials ADD hms_project_id varchar(255); +GO + +ALTER TABLE push_app_credentials ADD hms_client_id varchar(255); +GO + +ALTER TABLE push_app_credentials ADD hms_client_secret varchar(255); +GO + +IF EXISTS( SELECT extended_properties.value FROM sys.extended_properties WHERE major_id = OBJECT_ID('dbo.push_app_credentials') AND name = N'MS_DESCRIPTION' AND minor_id = ( SELECT column_id FROM sys.columns WHERE name = 'hms_project_id' AND object_id = OBJECT_ID('dbo.push_app_credentials')) ) BEGIN EXEC sys.sp_updateextendedproperty @name = N'MS_Description' , @value = N'Project ID defined in Huawei AppGallery Connect.' , @level0type = N'SCHEMA' , @level0name = N'dbo' , @level1type = N'TABLE' , @level1name = N'push_app_credentials' , @level2type = N'COLUMN' , @level2name = N'hms_project_id' END ELSE BEGIN EXEC sys.sp_addextendedproperty @name = N'MS_Description' , @value = N'Project ID defined in Huawei AppGallery Connect.' , @level0type = N'SCHEMA' , @level0name = N'dbo' , @level1type = N'TABLE' , @level1name = N'push_app_credentials' , @level2type = N'COLUMN' , @level2name = N'hms_project_id' END; +GO + +IF EXISTS( SELECT extended_properties.value FROM sys.extended_properties WHERE major_id = OBJECT_ID('dbo.push_app_credentials') AND name = N'MS_DESCRIPTION' AND minor_id = ( SELECT column_id FROM sys.columns WHERE name = 'hms_client_id' AND object_id = OBJECT_ID('dbo.push_app_credentials')) ) BEGIN EXEC sys.sp_updateextendedproperty @name = N'MS_Description' , @value = N'Huawei OAuth 2.0 Client ID.' , @level0type = N'SCHEMA' , @level0name = N'dbo' , @level1type = N'TABLE' , @level1name = N'push_app_credentials' , @level2type = N'COLUMN' , @level2name = N'hms_client_id' END ELSE BEGIN EXEC sys.sp_addextendedproperty @name = N'MS_Description' , @value = N'Huawei OAuth 2.0 Client ID.' , @level0type = N'SCHEMA' , @level0name = N'dbo' , @level1type = N'TABLE' , @level1name = N'push_app_credentials' , @level2type = N'COLUMN' , @level2name = N'hms_client_id' END; +GO + +IF EXISTS( SELECT extended_properties.value FROM sys.extended_properties WHERE major_id = OBJECT_ID('dbo.push_app_credentials') AND name = N'MS_DESCRIPTION' AND minor_id = ( SELECT column_id FROM sys.columns WHERE name = 'hms_client_secret' AND object_id = OBJECT_ID('dbo.push_app_credentials')) ) BEGIN EXEC sys.sp_updateextendedproperty @name = N'MS_Description' , @value = N'Huawei OAuth 2.0 Client Secret.' , @level0type = N'SCHEMA' , @level0name = N'dbo' , @level1type = N'TABLE' , @level1name = N'push_app_credentials' , @level2type = N'COLUMN' , @level2name = N'hms_client_secret' END ELSE BEGIN EXEC sys.sp_addextendedproperty @name = N'MS_Description' , @value = N'Huawei OAuth 2.0 Client Secret.' , @level0type = N'SCHEMA' , @level0name = N'dbo' , @level1type = N'TABLE' , @level1name = N'push_app_credentials' , @level2type = N'COLUMN' , @level2name = N'hms_client_secret' END; +GO + +-- Changeset powerauth-push-server/1.7.x/20240222-add-tag-1.7.0.xml::1::Lubos Racansky diff --git a/docs/sql/mssql/migration_1.7.0_1.8.0.sql b/docs/sql/mssql/migration_1.7.0_1.8.0.sql new file mode 100644 index 000000000..c71950896 --- /dev/null +++ b/docs/sql/mssql/migration_1.7.0_1.8.0.sql @@ -0,0 +1,7 @@ +-- Changeset powerauth-push-server/1.8.x/20240708-column-renaming-keywords.xml::1::Roman Strobl +-- Rename columns read to is_read and type to message_type in push_inbox table +exec sp_rename 'push_inbox.[read]', 'is_read', 'COLUMN'; +GO + +exec sp_rename 'push_inbox.type', 'message_type', 'COLUMN'; +GO diff --git a/docs/sql/oracle/create_push_server_schema.sql b/docs/sql/oracle/create_push_server_schema.sql index 0531c62ba..e33f545c9 100644 --- a/docs/sql/oracle/create_push_server_schema.sql +++ b/docs/sql/oracle/create_push_server_schema.sql @@ -1,103 +1,117 @@ -CREATE SEQUENCE PUSH_CREDENTIALS_SEQ START WITH 1 INCREMENT BY 1; -CREATE SEQUENCE PUSH_DEVICE_REGISTRATION_SEQ START WITH 1 INCREMENT BY 1; -CREATE SEQUENCE PUSH_MESSAGE_SEQ START WITH 1 INCREMENT BY 1; -CREATE SEQUENCE PUSH_CAMPAIGN_SEQ START WITH 1 INCREMENT BY 1; -CREATE SEQUENCE PUSH_CAMPAIGN_USER_SEQ START WITH 1 INCREMENT BY 1; -CREATE SEQUENCE PUSH_INBOX_SEQ START WITH 1 INCREMENT BY 1; - -CREATE TABLE PUSH_APP_CREDENTIALS -( - ID NUMBER(19) PRIMARY KEY NOT NULL, - APP_ID VARCHAR2(255) NOT NULL, - IOS_KEY_ID VARCHAR2(255 CHAR), - IOS_PRIVATE_KEY BLOB, - IOS_TEAM_ID VARCHAR2(255 CHAR), - IOS_BUNDLE VARCHAR2(255 CHAR), - IOS_ENVIRONMENT VARCHAR2(32 CHAR), - ANDROID_PRIVATE_KEY BLOB, - ANDROID_PROJECT_ID VARCHAR2(255 CHAR) -); - -CREATE TABLE PUSH_DEVICE_REGISTRATION -( - ID NUMBER(19) PRIMARY KEY NOT NULL, - ACTIVATION_ID VARCHAR2(37 CHAR), - USER_ID VARCHAR2(255 CHAR), - APP_ID NUMBER(19) NOT NULL, - PLATFORM VARCHAR2(255 CHAR) NOT NULL, - PUSH_TOKEN VARCHAR2(255 CHAR) NOT NULL, - TIMESTAMP_LAST_REGISTERED TIMESTAMP(6) NOT NULL, - IS_ACTIVE NUMBER(1) -); - -CREATE TABLE PUSH_MESSAGE -( - ID NUMBER(19) PRIMARY KEY NOT NULL, - DEVICE_REGISTRATION_ID NUMBER(19) NOT NULL, - USER_ID VARCHAR2(255 CHAR) NOT NULL, - ACTIVATION_ID VARCHAR2(37 CHAR), - IS_SILENT NUMBER(1) NOT NULL, - IS_PERSONAL NUMBER(1) NOT NULL, - MESSAGE_BODY VARCHAR2(2048 CHAR) NOT NULL, - TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL, - STATUS NUMBER(10) NOT NULL -); - -CREATE TABLE PUSH_CAMPAIGN ( - ID NUMBER(19) PRIMARY KEY NOT NULL, - APP_ID NUMBER(19) NOT NULL, - MESSAGE VARCHAR2(4000 CHAR) NOT NULL, - IS_SENT NUMBER(1) DEFAULT 0, - TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL, - TIMESTAMP_SENT TIMESTAMP(6), - TIMESTAMP_COMPLETED TIMESTAMP(6) -); - -CREATE TABLE PUSH_CAMPAIGN_USER ( - ID NUMBER(19) PRIMARY KEY NOT NULL, - CAMPAIGN_ID NUMBER(19) NOT NULL, - USER_ID VARCHAR2(255 CHAR) NOT NULL, - TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL -); - -CREATE TABLE PUSH_INBOX ( - ID NUMBER(19) PRIMARY KEY NOT NULL, - INBOX_ID VARCHAR2(37 CHAR) NOT NULL, - USER_ID VARCHAR2(255 CHAR) NOT NULL, - TYPE VARCHAR2(32 CHAR) NOT NULL, - SUBJECT VARCHAR2(4000 CHAR) NOT NULL, - SUMMARY VARCHAR2(4000 CHAR) NOT NULL, - BODY CLOB NOT NULL, - READ NUMBER(1) DEFAULT 0 NOT NULL, - TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL, - TIMESTAMP_READ TIMESTAMP(6) -); - --- Create table for assignment of inbox messages to apps -CREATE TABLE PUSH_INBOX_APP ( - APP_CREDENTIALS_ID NUMBER(19) NOT NULL, - INBOX_ID NUMBER(19) NOT NULL, - CONSTRAINT PUSH_INBOX_APP_PK PRIMARY KEY (INBOX_ID, APP_CREDENTIALS_ID) -); - ---- ---- Indexes for better performance. ---- - -CREATE UNIQUE INDEX PUSH_APP_CRED_APP ON PUSH_APP_CREDENTIALS(APP_ID); - -CREATE INDEX PUSH_DEVICE_APP_TOKEN ON PUSH_DEVICE_REGISTRATION(APP_ID, PUSH_TOKEN); -CREATE INDEX PUSH_DEVICE_USER_APP ON PUSH_DEVICE_REGISTRATION(USER_ID, APP_ID); -CREATE UNIQUE INDEX PUSH_DEVICE_ACTIVATION ON PUSH_DEVICE_REGISTRATION(ACTIVATION_ID); -CREATE UNIQUE INDEX PUSH_DEVICE_ACTIVATION_TOKEN ON PUSH_DEVICE_REGISTRATION(ACTIVATION_ID, PUSH_TOKEN); - -CREATE INDEX PUSH_MESSAGE_STATUS ON PUSH_MESSAGE(STATUS); - -CREATE INDEX PUSH_CAMPAIGN_SENT ON PUSH_CAMPAIGN(IS_SENT); - -CREATE INDEX PUSH_CAMPAIGN_USER_CAMPAIGN ON PUSH_CAMPAIGN_USER(CAMPAIGN_ID, USER_ID); -CREATE INDEX PUSH_CAMPAIGN_USER_DETAIL ON PUSH_CAMPAIGN_USER(USER_ID); - -CREATE INDEX PUSH_INBOX_ID ON PUSH_INBOX(INBOX_ID); -CREATE INDEX PUSH_INBOX_USER ON PUSH_INBOX(USER_ID); -CREATE INDEX PUSH_INBOX_USER_READ ON PUSH_INBOX(USER_ID, READ); +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::1::Lubos Racansky +-- Create a new sequence push_credentials_seq +CREATE SEQUENCE push_credentials_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::2::Lubos Racansky +-- Create a new sequence sequence push_device_registration_seq +CREATE SEQUENCE push_device_registration_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::3::Lubos Racansky +-- Create a new sequence sequence push_message_seq +CREATE SEQUENCE push_message_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::4::Lubos Racansky +-- Create a new sequence sequence push_campaign_seq +CREATE SEQUENCE push_campaign_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::5::Lubos Racansky +-- Create a new sequence sequence push_campaign_user_seq +CREATE SEQUENCE push_campaign_user_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::6::Lubos Racansky +-- Create a new sequence sequence push_inbox_seq +CREATE SEQUENCE push_inbox_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::7::Lubos Racansky +-- Create a new sequence push_app_credentials +CREATE TABLE push_app_credentials (id INTEGER NOT NULL, app_id VARCHAR2(255) NOT NULL, ios_key_id VARCHAR2(255), ios_private_key BLOB, ios_team_id VARCHAR2(255), ios_bundle VARCHAR2(255), ios_environment VARCHAR2(32), android_private_key BLOB, android_project_id VARCHAR2(255), CONSTRAINT PK_PUSH_APP_CREDENTIALS PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::8::Lubos Racansky +-- Create a new sequence push_device_registration +CREATE TABLE push_device_registration (id INTEGER NOT NULL, activation_id VARCHAR2(37), user_id VARCHAR2(255), app_id INTEGER NOT NULL, platform VARCHAR2(255) NOT NULL, push_token VARCHAR2(255) NOT NULL, timestamp_last_registered TIMESTAMP(6) NOT NULL, is_active BOOLEAN, CONSTRAINT PK_PUSH_DEVICE_REGISTRATION PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::9::Lubos Racansky +-- Create a new sequence push_message +CREATE TABLE push_message (id INTEGER NOT NULL, device_registration_id INTEGER NOT NULL, user_id VARCHAR2(255) NOT NULL, activation_id VARCHAR2(37), is_silent BOOLEAN DEFAULT 0 NOT NULL, is_personal BOOLEAN DEFAULT 0 NOT NULL, message_body VARCHAR2(2048) NOT NULL, timestamp_created TIMESTAMP(6) NOT NULL, status INTEGER NOT NULL, CONSTRAINT PK_PUSH_MESSAGE PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::10::Lubos Racansky +-- Create a new sequence push_campaign +CREATE TABLE push_campaign (id INTEGER NOT NULL, app_id INTEGER NOT NULL, message VARCHAR2(4000) NOT NULL, is_sent BOOLEAN DEFAULT 0 NOT NULL, timestamp_created TIMESTAMP(6) NOT NULL, timestamp_sent TIMESTAMP(6), timestamp_completed TIMESTAMP(6), CONSTRAINT PK_PUSH_CAMPAIGN PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::11::Lubos Racansky +-- Create a new sequence push_campaign_user +CREATE TABLE push_campaign_user (id INTEGER NOT NULL, campaign_id INTEGER NOT NULL, user_id VARCHAR2(255) NOT NULL, timestamp_created TIMESTAMP(6) NOT NULL, CONSTRAINT PK_PUSH_CAMPAIGN_USER PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::12::Lubos Racansky +-- Create a new table push_inbox +CREATE TABLE push_inbox (id INTEGER NOT NULL, inbox_id VARCHAR2(37) NOT NULL, user_id VARCHAR2(255) NOT NULL, type VARCHAR2(32) NOT NULL, subject CLOB NOT NULL, summary CLOB NOT NULL, body CLOB NOT NULL, read BOOLEAN DEFAULT 0 NOT NULL, timestamp_created TIMESTAMP NOT NULL, timestamp_read TIMESTAMP, CONSTRAINT PK_PUSH_INBOX PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::13::Lubos Racansky +-- Create a new sequence push_inbox_app +CREATE TABLE push_inbox_app (app_credentials_id INTEGER NOT NULL, inbox_id INTEGER NOT NULL, CONSTRAINT PK_PUSH_INBOX_APP PRIMARY KEY (app_credentials_id, inbox_id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::14::Lubos Racansky +-- Create a new unique index on push_app_credentials(app_id) +CREATE UNIQUE INDEX push_app_cred_app ON push_app_credentials(app_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::15::Lubos Racansky +-- Create a new index on push_device_registration(app_id, push_token) +CREATE INDEX push_device_app_token ON push_device_registration(app_id, push_token); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::16::Lubos Racansky +-- Create a new index on push_device_registration(user_id, app_id) +CREATE INDEX push_device_user_app ON push_device_registration(user_id, app_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::17::Lubos Racansky +-- Create a new unique index on push_device_registration(activation_id) +CREATE UNIQUE INDEX push_device_activation ON push_device_registration(activation_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::18::Lubos Racansky +-- Create a new unique index on push_device_registration(activation_id, push_token) +CREATE UNIQUE INDEX push_device_activation_token ON push_device_registration(activation_id, push_token); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::19::Lubos Racansky +-- Create a new index on push_message(status) +CREATE INDEX push_message_status ON push_message(status); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::20::Lubos Racansky +-- Create a new index on push_campaign(is_sent) +CREATE INDEX push_campaign_sent ON push_campaign(is_sent); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::21::Lubos Racansky +-- Create a new index on push_campaign_user(campaign_id, user_id) +CREATE INDEX push_campaign_user_campaign ON push_campaign_user(campaign_id, user_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::22::Lubos Racansky +-- Create a new index on push_campaign_user(user_id) +CREATE INDEX push_campaign_user_detail ON push_campaign_user(user_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::23::Lubos Racansky +-- Create a new index on push_inbox(inbox_id) +CREATE INDEX push_inbox_id ON push_inbox(inbox_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::24::Lubos Racansky +-- Create a new index on push_inbox(user_id) +CREATE INDEX push_inbox_user ON push_inbox(user_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::25::Lubos Racansky +-- Create a new index on push_inbox(user_id, read) +CREATE INDEX push_inbox_user_read ON push_inbox(user_id, read); + +-- Changeset powerauth-push-server/1.4.x/20230322-add-tag-1.4.0.xml::1::Lubos Racansky +-- Changeset powerauth-push-server/1.5.x/20230905-add-tag-1.5.0.xml::1::Lubos Racansky +-- Changeset powerauth-push-server/1.7.x/20240119-push_app_credentials-hms.xml::1::Lubos Racansky +-- Add hms_project_id, hms_client_id, and hms_client_secret columns to push_app_credentials +ALTER TABLE push_app_credentials ADD hms_project_id VARCHAR2(255); + +ALTER TABLE push_app_credentials ADD hms_client_id VARCHAR2(255); + +ALTER TABLE push_app_credentials ADD hms_client_secret VARCHAR2(255); + +COMMENT ON COLUMN push_app_credentials.hms_project_id IS 'Project ID defined in Huawei AppGallery Connect.'; + +COMMENT ON COLUMN push_app_credentials.hms_client_id IS 'Huawei OAuth 2.0 Client ID.'; + +COMMENT ON COLUMN push_app_credentials.hms_client_secret IS 'Huawei OAuth 2.0 Client Secret.'; + +-- Changeset powerauth-push-server/1.7.x/20240222-add-tag-1.7.0.xml::1::Lubos Racansky diff --git a/docs/sql/oracle/migration_1.7.0_1.8.0.sql b/docs/sql/oracle/migration_1.7.0_1.8.0.sql new file mode 100644 index 000000000..0633d1873 --- /dev/null +++ b/docs/sql/oracle/migration_1.7.0_1.8.0.sql @@ -0,0 +1,5 @@ +-- Changeset powerauth-push-server/1.8.x/20240708-column-renaming-keywords.xml::1::Roman Strobl +-- Rename columns read to is_read and type to message_type in push_inbox table +ALTER TABLE push_inbox RENAME COLUMN read TO is_read; + +ALTER TABLE push_inbox RENAME COLUMN type TO message_type; diff --git a/docs/sql/postgresql/create_push_server_schema.sql b/docs/sql/postgresql/create_push_server_schema.sql index 4cfef0259..a5ea7663d 100644 --- a/docs/sql/postgresql/create_push_server_schema.sql +++ b/docs/sql/postgresql/create_push_server_schema.sql @@ -1,122 +1,117 @@ ---- ---- DB Sequences ---- - -CREATE SEQUENCE push_credentials_seq; -CREATE SEQUENCE push_device_registration_seq; -CREATE SEQUENCE push_message_seq; -CREATE SEQUENCE push_campaign_seq; -CREATE SEQUENCE push_campaign_user_seq; -CREATE SEQUENCE push_inbox_seq; - ---- ---- DB Tables ---- - --- Create table for application credentials used for APNS and FCM -CREATE TABLE push_app_credentials ( - id INTEGER NOT NULL CONSTRAINT push_app_credentials_pkey PRIMARY KEY, - app_id VARCHAR(255) NOT NULL, - ios_key_id VARCHAR(255), - ios_private_key BYTEA, - ios_team_id VARCHAR(255), - ios_bundle VARCHAR(255), - ios_environment VARCHAR(32), - android_private_key BYTEA, - android_project_id VARCHAR(255) -); - - --- Create table for registered devices -CREATE TABLE push_device_registration ( - id INTEGER NOT NULL CONSTRAINT push_device_registration_pkey PRIMARY KEY, - activation_id VARCHAR(37), - user_id VARCHAR(255), - app_id INTEGER NOT NULL, - platform VARCHAR(255) NOT NULL, - push_token VARCHAR(255) NOT NULL, - timestamp_last_registered TIMESTAMP(6) NOT NULL, - is_active BOOLEAN -); - - --- Create table for optional auditing of sent push messages -CREATE TABLE push_message ( - id INTEGER NOT NULL CONSTRAINT push_message_pkey PRIMARY KEY, - device_registration_id INTEGER NOT NULL, - user_id VARCHAR(255) NOT NULL, - activation_id VARCHAR(37), - is_silent BOOLEAN DEFAULT false NOT NULL, - is_personal BOOLEAN DEFAULT false NOT NULL, - message_body VARCHAR(2048) NOT NULL, - timestamp_created TIMESTAMP(6) NOT NULL, - status INTEGER NOT NULL -); - - --- Create table for push message campaigns -CREATE TABLE push_campaign ( - id INTEGER NOT NULL CONSTRAINT push_campaign_pkey PRIMARY KEY, - app_id INTEGER NOT NULL, - message VARCHAR(4000) NOT NULL, - is_sent BOOLEAN DEFAULT false NOT NULL, - timestamp_created TIMESTAMP(6) NOT NULL, - timestamp_sent TIMESTAMP(6), - timestamp_completed TIMESTAMP(6) -); - - --- Create table for push campaign user list -CREATE TABLE push_campaign_user ( - id INTEGER NOT NULL CONSTRAINT push_campaign_user_pkey PRIMARY KEY, - campaign_id INTEGER NOT NULL, - user_id VARCHAR(255) NOT NULL, - timestamp_created TIMESTAMP(6) NOT NULL -); - --- Create table for message inbox -CREATE TABLE push_inbox ( - id INTEGER NOT NULL CONSTRAINT push_inbox_pk PRIMARY KEY, - inbox_id VARCHAR(37) NOT NULL, - user_id VARCHAR(255) NOT NULL, - type VARCHAR(32) NOT NULL, - subject TEXT NOT NULL, - summary TEXT NOT NULL, - body TEXT NOT NULL, - read BOOLEAN DEFAULT false NOT NULL, - timestamp_created TIMESTAMP NOT NULL, - timestamp_read TIMESTAMP -); - --- Create table for assignment of inbox messages to apps -CREATE TABLE push_inbox_app ( - app_credentials_id INTEGER NOT NULL, - inbox_id INTEGER NOT NULL, - CONSTRAINT push_inbox_app_pk PRIMARY KEY (inbox_id, app_credentials_id) -); - --- --- DB Indexes (recommended for better performance) --- - -CREATE UNIQUE INDEX push_app_cred_app ON push_app_credentials (app_id); - -CREATE INDEX push_device_app_token ON push_device_registration (app_id, push_token); - -CREATE INDEX push_device_user_app ON push_device_registration (user_id, app_id); - -CREATE UNIQUE INDEX push_device_activation ON push_device_registration (activation_id); - -CREATE UNIQUE INDEX push_device_activation_token ON push_device_registration (activation_id, push_token); - -CREATE INDEX push_message_status ON push_message (status); - -CREATE INDEX push_campaign_sent ON push_campaign (is_sent); - -CREATE INDEX push_campaign_user_campaign ON push_campaign_user (campaign_id, user_id); - -CREATE INDEX push_campaign_user_detail ON push_campaign_user (user_id); - -CREATE INDEX push_inbox_id ON push_inbox (inbox_id); -CREATE INDEX push_inbox_user ON push_inbox (user_id); -CREATE INDEX push_inbox_user_read ON push_inbox (user_id, read); +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::1::Lubos Racansky +-- Create a new sequence push_credentials_seq +CREATE SEQUENCE IF NOT EXISTS push_credentials_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::2::Lubos Racansky +-- Create a new sequence sequence push_device_registration_seq +CREATE SEQUENCE IF NOT EXISTS push_device_registration_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::3::Lubos Racansky +-- Create a new sequence sequence push_message_seq +CREATE SEQUENCE IF NOT EXISTS push_message_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::4::Lubos Racansky +-- Create a new sequence sequence push_campaign_seq +CREATE SEQUENCE IF NOT EXISTS push_campaign_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::5::Lubos Racansky +-- Create a new sequence sequence push_campaign_user_seq +CREATE SEQUENCE IF NOT EXISTS push_campaign_user_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::6::Lubos Racansky +-- Create a new sequence sequence push_inbox_seq +CREATE SEQUENCE IF NOT EXISTS push_inbox_seq START WITH 1 INCREMENT BY 1 CACHE 20; + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::7::Lubos Racansky +-- Create a new sequence push_app_credentials +CREATE TABLE push_app_credentials (id INTEGER NOT NULL, app_id VARCHAR(255) NOT NULL, ios_key_id VARCHAR(255), ios_private_key BYTEA, ios_team_id VARCHAR(255), ios_bundle VARCHAR(255), ios_environment VARCHAR(32), android_private_key BYTEA, android_project_id VARCHAR(255), CONSTRAINT push_app_credentials_pkey PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::8::Lubos Racansky +-- Create a new sequence push_device_registration +CREATE TABLE push_device_registration (id INTEGER NOT NULL, activation_id VARCHAR(37), user_id VARCHAR(255), app_id INTEGER NOT NULL, platform VARCHAR(255) NOT NULL, push_token VARCHAR(255) NOT NULL, timestamp_last_registered TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL, is_active BOOLEAN, CONSTRAINT push_device_registration_pkey PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::9::Lubos Racansky +-- Create a new sequence push_message +CREATE TABLE push_message (id INTEGER NOT NULL, device_registration_id INTEGER NOT NULL, user_id VARCHAR(255) NOT NULL, activation_id VARCHAR(37), is_silent BOOLEAN DEFAULT FALSE NOT NULL, is_personal BOOLEAN DEFAULT FALSE NOT NULL, message_body VARCHAR(2048) NOT NULL, timestamp_created TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL, status INTEGER NOT NULL, CONSTRAINT push_message_pkey PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::10::Lubos Racansky +-- Create a new sequence push_campaign +CREATE TABLE push_campaign (id INTEGER NOT NULL, app_id INTEGER NOT NULL, message VARCHAR(4000) NOT NULL, is_sent BOOLEAN DEFAULT FALSE NOT NULL, timestamp_created TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL, timestamp_sent TIMESTAMP(6) WITHOUT TIME ZONE, timestamp_completed TIMESTAMP(6) WITHOUT TIME ZONE, CONSTRAINT push_campaign_pkey PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::11::Lubos Racansky +-- Create a new sequence push_campaign_user +CREATE TABLE push_campaign_user (id INTEGER NOT NULL, campaign_id INTEGER NOT NULL, user_id VARCHAR(255) NOT NULL, timestamp_created TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL, CONSTRAINT push_campaign_user_pkey PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::12::Lubos Racansky +-- Create a new table push_inbox +CREATE TABLE push_inbox (id INTEGER NOT NULL, inbox_id VARCHAR(37) NOT NULL, user_id VARCHAR(255) NOT NULL, type VARCHAR(32) NOT NULL, subject TEXT NOT NULL, summary TEXT NOT NULL, body TEXT NOT NULL, read BOOLEAN DEFAULT FALSE NOT NULL, timestamp_created TIMESTAMP WITHOUT TIME ZONE NOT NULL, timestamp_read TIMESTAMP WITHOUT TIME ZONE, CONSTRAINT push_inbox_pkey PRIMARY KEY (id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::13::Lubos Racansky +-- Create a new sequence push_inbox_app +CREATE TABLE push_inbox_app (app_credentials_id INTEGER NOT NULL, inbox_id INTEGER NOT NULL, CONSTRAINT push_inbox_app_pkey PRIMARY KEY (app_credentials_id, inbox_id)); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::14::Lubos Racansky +-- Create a new unique index on push_app_credentials(app_id) +CREATE UNIQUE INDEX push_app_cred_app ON push_app_credentials(app_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::15::Lubos Racansky +-- Create a new index on push_device_registration(app_id, push_token) +CREATE INDEX push_device_app_token ON push_device_registration(app_id, push_token); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::16::Lubos Racansky +-- Create a new index on push_device_registration(user_id, app_id) +CREATE INDEX push_device_user_app ON push_device_registration(user_id, app_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::17::Lubos Racansky +-- Create a new unique index on push_device_registration(activation_id) +CREATE UNIQUE INDEX push_device_activation ON push_device_registration(activation_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::18::Lubos Racansky +-- Create a new unique index on push_device_registration(activation_id, push_token) +CREATE UNIQUE INDEX push_device_activation_token ON push_device_registration(activation_id, push_token); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::19::Lubos Racansky +-- Create a new index on push_message(status) +CREATE INDEX push_message_status ON push_message(status); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::20::Lubos Racansky +-- Create a new index on push_campaign(is_sent) +CREATE INDEX push_campaign_sent ON push_campaign(is_sent); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::21::Lubos Racansky +-- Create a new index on push_campaign_user(campaign_id, user_id) +CREATE INDEX push_campaign_user_campaign ON push_campaign_user(campaign_id, user_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::22::Lubos Racansky +-- Create a new index on push_campaign_user(user_id) +CREATE INDEX push_campaign_user_detail ON push_campaign_user(user_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::23::Lubos Racansky +-- Create a new index on push_inbox(inbox_id) +CREATE INDEX push_inbox_id ON push_inbox(inbox_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::24::Lubos Racansky +-- Create a new index on push_inbox(user_id) +CREATE INDEX push_inbox_user ON push_inbox(user_id); + +-- Changeset powerauth-push-server/1.4.x/20230321-init-db.xml::25::Lubos Racansky +-- Create a new index on push_inbox(user_id, read) +CREATE INDEX push_inbox_user_read ON push_inbox(user_id, read); + +-- Changeset powerauth-push-server/1.4.x/20230322-add-tag-1.4.0.xml::1::Lubos Racansky +-- Changeset powerauth-push-server/1.5.x/20230905-add-tag-1.5.0.xml::1::Lubos Racansky +-- Changeset powerauth-push-server/1.7.x/20240119-push_app_credentials-hms.xml::1::Lubos Racansky +-- Add hms_project_id, hms_client_id, and hms_client_secret columns to push_app_credentials +ALTER TABLE push_app_credentials ADD hms_project_id VARCHAR(255); + +ALTER TABLE push_app_credentials ADD hms_client_id VARCHAR(255); + +ALTER TABLE push_app_credentials ADD hms_client_secret VARCHAR(255); + +COMMENT ON COLUMN push_app_credentials.hms_project_id IS 'Project ID defined in Huawei AppGallery Connect.'; + +COMMENT ON COLUMN push_app_credentials.hms_client_id IS 'Huawei OAuth 2.0 Client ID.'; + +COMMENT ON COLUMN push_app_credentials.hms_client_secret IS 'Huawei OAuth 2.0 Client Secret.'; + +-- Changeset powerauth-push-server/1.7.x/20240222-add-tag-1.7.0.xml::1::Lubos Racansky diff --git a/docs/sql/postgresql/migration_1.7.0_1.8.0.sql b/docs/sql/postgresql/migration_1.7.0_1.8.0.sql new file mode 100644 index 000000000..0633d1873 --- /dev/null +++ b/docs/sql/postgresql/migration_1.7.0_1.8.0.sql @@ -0,0 +1,5 @@ +-- Changeset powerauth-push-server/1.8.x/20240708-column-renaming-keywords.xml::1::Roman Strobl +-- Rename columns read to is_read and type to message_type in push_inbox table +ALTER TABLE push_inbox RENAME COLUMN read TO is_read; + +ALTER TABLE push_inbox RENAME COLUMN type TO message_type; diff --git a/pom.xml b/pom.xml index eff381176..b8bae66fd 100644 --- a/pom.xml +++ b/pom.xml @@ -8,13 +8,13 @@ io.getlime.security powerauth-push-server-parent - 1.7.0 + 1.8.0 pom org.springframework.boot spring-boot-starter-parent - 3.2.4 + 3.3.2 @@ -69,21 +69,20 @@ - 1.9.0 - 1.7.0 - 1.7.0 - 1.7.0 + 1.10.0 + 1.8.0 + 1.8.0 + 1.8.0 0.15.4 - 2.4.0 - 9.2.0 - 1.77 + 2.6.0 + 9.3.0 7.4 - 2.5.0 - 2.2.21 + 2.6.0 + 2.2.22 3.5.0 diff --git a/powerauth-push-client/pom.xml b/powerauth-push-client/pom.xml index 0dba6b8e5..811553898 100644 --- a/powerauth-push-client/pom.xml +++ b/powerauth-push-client/pom.xml @@ -10,7 +10,7 @@ powerauth-push-server-parent io.getlime.security - 1.7.0 + 1.8.0 diff --git a/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClient.java b/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClient.java index 4d9966c3e..bd99bdccb 100644 --- a/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClient.java +++ b/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClient.java @@ -16,8 +16,10 @@ package io.getlime.push.client; +import com.fasterxml.jackson.databind.Module; import com.wultra.core.rest.client.base.DefaultRestClient; import com.wultra.core.rest.client.base.RestClient; +import com.wultra.core.rest.client.base.RestClientConfiguration; import com.wultra.core.rest.client.base.RestClientException; import io.getlime.core.rest.model.base.entity.Error; import io.getlime.core.rest.model.base.request.ObjectRequest; @@ -64,7 +66,22 @@ public PushServerClient(String serviceBaseUrl) throws PushServerClientException try { this.restClient = DefaultRestClient.builder().baseUrl(serviceBaseUrl).build(); } catch (RestClientException ex) { - throw new PushServerClientException("Rest client initialization failed, error: " + ex.getMessage()); + throw new PushServerClientException("Rest client initialization failed, error: " + ex.getMessage(), ex); + } + } + + /** + * Construct the push server client with the given configuration. + * + * @param config REST client configuration. + * @param modules Optional jackson modules. + * @throws PushServerClientException Thrown in case REST client initialization fails. + */ + public PushServerClient(final RestClientConfiguration config, final Module... modules) throws PushServerClientException { + try { + this.restClient = new DefaultRestClient(config, modules); + } catch (RestClientException ex) { + throw new PushServerClientException("Rest client initialization failed, error: " + ex.getMessage(), ex); } } diff --git a/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClientException.java b/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClientException.java index 9bdba1d3c..f623e56c3 100644 --- a/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClientException.java +++ b/powerauth-push-client/src/main/java/io/getlime/push/client/PushServerClientException.java @@ -30,7 +30,7 @@ public class PushServerClientException extends Exception { /** * Error object. */ - private Error error; + private final Error error; /** * Constructor with message. @@ -71,6 +71,16 @@ public PushServerClientException(String message, Throwable cause, Error error) { this.error = error; } + /** + * Constructor with message, cause and error object. + * @param message Message. + * @param cause Cause. + */ + public PushServerClientException(String message, Throwable cause) { + super(message, cause); + this.error = new PushServerClientError(message); + } + /** * Constructor with cause and error object. * @param cause Cause. @@ -95,14 +105,6 @@ public PushServerClientException(String message, Throwable cause, boolean enable this.error = error; } - /** - * Set error object. - * @param error Error object. - */ - public void setError(Error error) { - this.error = error; - } - /** * Get error object. * @return Error object. diff --git a/powerauth-push-model/pom.xml b/powerauth-push-model/pom.xml index fbe90959a..dada08e8d 100644 --- a/powerauth-push-model/pom.xml +++ b/powerauth-push-model/pom.xml @@ -11,7 +11,7 @@ powerauth-push-server-parent io.getlime.security - 1.7.0 + 1.8.0 diff --git a/powerauth-push-server/pom.xml b/powerauth-push-server/pom.xml index d08bb9ab8..ff1d29afa 100644 --- a/powerauth-push-server/pom.xml +++ b/powerauth-push-server/pom.xml @@ -11,7 +11,7 @@ io.getlime.security powerauth-push-server-parent - 1.7.0 + 1.8.0 @@ -200,12 +200,6 @@ ${powerauth-restful-integration.version} test - - org.bouncycastle - bcprov-jdk18on - ${bc.version} - test - @@ -230,18 +224,6 @@ - - org.apache.maven.plugins - maven-war-plugin - - - - - jdk.unsupported - - - - diff --git a/powerauth-push-server/src/main/java/io/getlime/push/configuration/PowerAuthWebServiceConfiguration.java b/powerauth-push-server/src/main/java/io/getlime/push/configuration/PowerAuthWebServiceConfiguration.java index 1bfe23bc7..ae20dcad2 100644 --- a/powerauth-push-server/src/main/java/io/getlime/push/configuration/PowerAuthWebServiceConfiguration.java +++ b/powerauth-push-server/src/main/java/io/getlime/push/configuration/PowerAuthWebServiceConfiguration.java @@ -19,13 +19,14 @@ import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; import com.wultra.security.powerauth.rest.client.PowerAuthRestClient; import com.wultra.security.powerauth.rest.client.PowerAuthRestClientConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import java.time.Duration; + /** * Default PowerAuth Service configuration. * @@ -33,13 +34,18 @@ */ @Configuration @ComponentScan(basePackages = {"io.getlime.security", "io.getlime.push"}) +@Slf4j public class PowerAuthWebServiceConfiguration { - private static final Logger logger = LoggerFactory.getLogger(PowerAuthWebServiceConfiguration.class); - @Value("${powerauth.service.url}") private String powerAuthRestUrl; + @Value("${powerauth.service.restClientConfig.responseTimeout}") + private Duration powerAuthServiceTimeout; + + @Value("${powerauth.service.restClientConfig.maxIdleTime}") + private Duration powerAuthServiceMaxIdleTime; + @Value("${powerauth.service.ssl.acceptInvalidSslCertificate}") private boolean acceptInvalidSslCertificate; @@ -54,17 +60,15 @@ public class PowerAuthWebServiceConfiguration { * @return PowerAuth REST client. */ @Bean - public PowerAuthClient powerAuthClient() { - PowerAuthRestClientConfiguration config = new PowerAuthRestClientConfiguration(); + public PowerAuthClient powerAuthClient() throws PowerAuthClientException { + logger.info("Configuring PowerAuthRestClient for URL: {}", powerAuthRestUrl); + final PowerAuthRestClientConfiguration config = new PowerAuthRestClientConfiguration(); + config.setResponseTimeout(powerAuthServiceTimeout); + config.setMaxIdleTime(powerAuthServiceMaxIdleTime); config.setPowerAuthClientToken(clientToken); config.setPowerAuthClientSecret(clientSecret); config.setAcceptInvalidSslCertificate(acceptInvalidSslCertificate); - try { - return new PowerAuthRestClient(powerAuthRestUrl, config); - } catch (PowerAuthClientException ex) { - logger.error(ex.getMessage(), ex); - return null; - } + return new PowerAuthRestClient(powerAuthRestUrl, config); } } diff --git a/powerauth-push-server/src/main/java/io/getlime/push/repository/InboxRepository.java b/powerauth-push-server/src/main/java/io/getlime/push/repository/InboxRepository.java index 22089d8b1..8e7bb8a4e 100644 --- a/powerauth-push-server/src/main/java/io/getlime/push/repository/InboxRepository.java +++ b/powerauth-push-server/src/main/java/io/getlime/push/repository/InboxRepository.java @@ -44,7 +44,10 @@ public interface InboxRepository extends PagingAndSortingRepository findInboxMessagesForUserAndApplications(String userId, List applicationIds, Pageable pageable); /** @@ -55,7 +58,10 @@ public interface InboxRepository extends PagingAndSortingRepository findAllByUserIdAndApplicationsContainingAndReadOrderByTimestampCreatedDesc(String userId, List applicationIds, boolean read, Pageable pageable); /** @@ -69,10 +75,10 @@ public interface InboxRepository extends PagingAndSortingRepository apps = fetchAppsForAppIds(request.getApplications()); if (apps.size() != request.getApplications().size()) { - logger.info("Application list received: {}, apps configured in the system: {}.", request.getApplications(), apps.stream().map(AppCredentialsEntity::getAppId)); + logger.info("Application list received: {}, apps configured in the system: {}.", request.getApplications(), apps.stream().map(AppCredentialsEntity::getAppId).toList()); throw new AppNotFoundException("Application list contained an app that is not configured in the system."); } final String userId = request.getUserId(); @@ -98,7 +98,7 @@ public GetInboxMessageDetailResponse postMessage(CreateInboxMessageRequest reque public ListOfInboxMessages fetchMessageListForUser(String userId, List appIds, boolean onlyUnread, Pageable pageable) throws AppNotFoundException { final List apps = fetchAppsForAppIds(appIds); if (apps.size() != appIds.size()) { - logger.info("Application list received: {}, apps configured in the system: {}.", appIds, apps.stream().map(AppCredentialsEntity::getAppId)); + logger.info("Application list received: {}, apps configured in the system: {}.", appIds, apps.stream().map(AppCredentialsEntity::getAppId).toList()); throw new AppNotFoundException("Application list contained an app that is not configured in the system."); } @@ -134,7 +134,7 @@ public GetInboxMessageDetailResponse fetchMessageDetail(String inboxId) throws I @Transactional(readOnly=true) public GetInboxMessageCountResponse fetchMessageCountForUser(String userId, String appId) throws AppNotFoundException { final AppCredentialsEntity app = fetchAppForAppId(appId); - final long countUnread = inboxRepository.countAllByUserIdAndApplicationsContainingAndRead(userId, app,false); + final long countUnread = inboxRepository.countAllByUserIdAndApplicationsContainingAndIsRead(userId, app,false); return new GetInboxMessageCountResponse(countUnread); } diff --git a/powerauth-push-server/src/main/java/io/getlime/push/service/PushMessageSenderService.java b/powerauth-push-server/src/main/java/io/getlime/push/service/PushMessageSenderService.java index 3b93e5319..bb3cca164 100644 --- a/powerauth-push-server/src/main/java/io/getlime/push/service/PushMessageSenderService.java +++ b/powerauth-push-server/src/main/java/io/getlime/push/service/PushMessageSenderService.java @@ -182,8 +182,8 @@ private PushSendingCallback createPushSendingCallback(final Mode mode, final Pus } } platformResult.setTotal(platformResult.getTotal() + 1); - } catch (Throwable t) { - logger.error("System error when sending notification: {}", t.getMessage(), t); + } catch (Exception e) { + logger.error("System error when sending notification: {}", e.getMessage(), e); } finally { arriveAndDeregisterPhaserForMode(phaser, mode); } diff --git a/powerauth-push-server/src/main/java/io/getlime/push/service/PushSendingWorker.java b/powerauth-push-server/src/main/java/io/getlime/push/service/PushSendingWorker.java index 0d6c2d5f7..8613a6d17 100644 --- a/powerauth-push-server/src/main/java/io/getlime/push/service/PushSendingWorker.java +++ b/powerauth-push-server/src/main/java/io/getlime/push/service/PushSendingWorker.java @@ -188,7 +188,7 @@ void sendMessageToAndroid(final FcmClient fcmClient, final PushMessageBody pushM final MessagingErrorCode errorCode = fcmConverter.convertExceptionToErrorCode(restClientException); logger.warn("FCM server returned error response: {}.", (restClientException).getResponse()); switch (errorCode) { - case UNREGISTERED -> { + case UNREGISTERED, INVALID_ARGUMENT -> { logger.info("Push message rejected by FCM gateway, device registration for token: {} is invalid and will be removed. Error: {}", pushToken, errorCode); callback.didFinishSendingMessage(PushSendingCallback.Result.FAILED_DELETE); return; @@ -200,7 +200,7 @@ void sendMessageToAndroid(final FcmClient fcmClient, final PushMessageBody pushM callback.didFinishSendingMessage(PushSendingCallback.Result.PENDING); return; } - case SENDER_ID_MISMATCH, THIRD_PARTY_AUTH_ERROR, INVALID_ARGUMENT -> { + case SENDER_ID_MISMATCH, THIRD_PARTY_AUTH_ERROR -> { logger.warn("Push message rejected by FCM gateway. Error: {}", errorCode); callback.didFinishSendingMessage(PushSendingCallback.Result.FAILED); return; diff --git a/powerauth-push-server/src/main/resources/application.properties b/powerauth-push-server/src/main/resources/application.properties index dd8c9ed88..c18cd6176 100644 --- a/powerauth-push-server/src/main/resources/application.properties +++ b/powerauth-push-server/src/main/resources/application.properties @@ -6,6 +6,7 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/powerauth spring.datasource.username=powerauth spring.datasource.password= spring.datasource.hikari.auto-commit=false +spring.datasource.hikari.pool-name=HikariPool-Push-Server spring.jpa.properties.hibernate.connection.characterEncoding=utf8 spring.jpa.properties.hibernate.connection.useUnicode=true @@ -25,6 +26,8 @@ spring.jpa.hibernate.ddl-auto=none # PowerAuth Service Configuration powerauth.service.url=http://localhost:8080/powerauth-java-server/rest +powerauth.service.restClientConfig.responseTimeout=60s +powerauth.service.restClientConfig.maxIdleTime=200s powerauth.service.security.clientToken= powerauth.service.security.clientSecret= powerauth.service.ssl.acceptInvalidSslCertificate=false @@ -119,4 +122,6 @@ management.tracing.sampling.probability=1.0 #management.endpoint.prometheus.enabled=true #management.prometheus.metrics.export.enabled=true -spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration +spring.autoconfigure.exclude=\ + org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\ + org.springframework.boot.actuate.autoconfigure.metrics.jersey.JerseyServerMetricsAutoConfiguration diff --git a/powerauth-push-server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/powerauth-push-server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml index 6112c1b87..bb131d13f 100644 --- a/powerauth-push-server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml +++ b/powerauth-push-server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -1,10 +1,9 @@ - + - diff --git a/powerauth-push-server/src/test/java/io/getlime/push/service/PushSendingWorkerTest.java b/powerauth-push-server/src/test/java/io/getlime/push/service/PushSendingWorkerTest.java new file mode 100644 index 000000000..ddd4f13b1 --- /dev/null +++ b/powerauth-push-server/src/test/java/io/getlime/push/service/PushSendingWorkerTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2024 Wultra s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.getlime.push.service; + +import com.google.firebase.messaging.MessagingErrorCode; +import com.wultra.core.rest.client.base.RestClientException; +import io.getlime.push.configuration.PushServiceConfiguration; +import io.getlime.push.errorhandling.exceptions.FcmMissingTokenException; +import io.getlime.push.model.entity.PushMessageAttributes; +import io.getlime.push.model.entity.PushMessageBody; +import io.getlime.push.model.enumeration.Priority; +import io.getlime.push.service.fcm.FcmClient; +import io.getlime.push.service.fcm.FcmModelConverter; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.util.function.Consumer; + +import static org.mockito.Mockito.*; + +/** + * Tests of {@link PushSendingWorker} + * + * @author Jan Dusil, jan.dusil@wultra.com + */ +@SpringBootTest +@ActiveProfiles("test") +class PushSendingWorkerTest { + + @Mock + private FcmClient fcmClient; + + @Mock + private PushSendingCallback callback; + + @Mock + private PushServiceConfiguration pushServiceConfiguration; + + @Mock + private FcmModelConverter fcmModelConverter; + + @InjectMocks + private PushSendingWorker tested; + + @Test + void testSendMessageToAndroidError() throws FcmMissingTokenException { + final RestClientException simulatedException = new RestClientException("Simulated INVALID_ARGUMENT error"); + when(fcmModelConverter.convertExceptionToErrorCode(simulatedException)).thenReturn(MessagingErrorCode.INVALID_ARGUMENT); + doAnswer(invocation -> { + final Consumer onError = invocation.getArgument(3); + onError.accept(simulatedException); + return null; + }).when(fcmClient).exchange(any(), anyBoolean(), any(), any()); + + tested.sendMessageToAndroid(fcmClient, new PushMessageBody(), new PushMessageAttributes(), Priority.HIGH, "dummyToken", callback); + verify(callback).didFinishSendingMessage(PushSendingCallback.Result.FAILED_DELETE); + } + +} +