diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4de1c9d..2b22ae8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,27 +1,38 @@ ## Summary of change + (A few sentences about this PR) ## Related issues + - Link to issue1 here - Link to issue1 here ## Test Plan -(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Bonus points for screenshots and videos!) + +(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your +changes work. Bonus points for screenshots and videos!) ## Documentation changes -(If relevant, please create a PR in our [docs repo](https://github.com/supertokens/docs), or create a checklist here highlighting the necessary changes) + +(If relevant, please create a PR in our [docs repo](https://github.com/supertokens/docs), or create a checklist here +highlighting the necessary changes) ## Checklist for important updates + - [ ] Changelog has been updated - [ ] `pluginInterfaceSupported.json` file has been updated (if needed) - [ ] Changes to the version if needed - - In `build.gradle` + - In `build.gradle` - [ ] Had installed and ran the pre-commit hook -- [ ] If there are new dependencies that have been added in `build.gradle`, please make sure to add them in `implementationDependencies.json`. +- [ ] If there are new dependencies that have been added in `build.gradle`, please make sure to add them + in `implementationDependencies.json`. - [ ] Issue this PR against the latest non released version branch. - - To know which one it is, run find the latest released tag (`git tag`) in the format `vX.Y.Z`, and then find the latest branch (`git branch --all`) whose `X.Y` is greater than the latest released tag. - - If no such branch exists, then create one from the latest released branch. + - To know which one it is, run find the latest released tag (`git tag`) in the format `vX.Y.Z`, and then find the + latest branch (`git branch --all`) whose `X.Y` is greater than the latest released tag. + - If no such branch exists, then create one from the latest released branch. - [ ] When adding new recipes, ensure that its performance is being measured in the `OneMillionUsersTest` + ## Remaining TODOs for this PR + - [ ] Item1 - [ ] Item2 \ No newline at end of file diff --git a/.github/helpers/package.json b/.github/helpers/package.json index 80ec546..28051cd 100644 --- a/.github/helpers/package.json +++ b/.github/helpers/package.json @@ -1,14 +1,14 @@ { - "name": "helpers", - "version": "1.0.0", - "description": "", - "main": "test-pass-check-pr.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "github-workflow-helpers": "github:supertokens/github-workflow-helpers" - } + "name": "helpers", + "version": "1.0.0", + "description": "", + "main": "test-pass-check-pr.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "github-workflow-helpers": "github:supertokens/github-workflow-helpers" + } } \ No newline at end of file diff --git a/.github/workflows/github-actions-changelog.yml b/.github/workflows/github-actions-changelog.yml index 0007ca9..47aaf4a 100644 --- a/.github/workflows/github-actions-changelog.yml +++ b/.github/workflows/github-actions-changelog.yml @@ -1,15 +1,15 @@ name: "Enforcing changelog in PRs Workflow" on: pull_request: - types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled] + types: [ opened, synchronize, reopened, ready_for_review, labeled, unlabeled ] jobs: # Enforces the update of a changelog file on every pull request changelog: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: dangoslen/changelog-enforcer@v2 - with: - changeLogPath: 'CHANGELOG.md' - skipLabels: 'Skip-Changelog' \ No newline at end of file + - uses: actions/checkout@v2 + - uses: dangoslen/changelog-enforcer@v2 + with: + changeLogPath: 'CHANGELOG.md' + skipLabels: 'Skip-Changelog' \ No newline at end of file diff --git a/.github/workflows/lint-pr-title.yml b/.github/workflows/lint-pr-title.yml index 904efde..96281a7 100644 --- a/.github/workflows/lint-pr-title.yml +++ b/.github/workflows/lint-pr-title.yml @@ -1,20 +1,20 @@ name: "Lint PR Title" on: - pull_request: - types: - - opened - - reopened - - edited - - synchronize + pull_request: + types: + - opened + - reopened + - edited + - synchronize jobs: - pr-title: - name: Lint PR title - runs-on: ubuntu-latest - steps: - - uses: amannn/action-semantic-pull-request@v3 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - validateSingleCommit: true \ No newline at end of file + pr-title: + name: Lint PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + validateSingleCommit: true \ No newline at end of file diff --git a/.github/workflows/tests-pass-check-pr.yml b/.github/workflows/tests-pass-check-pr.yml index 4f03705..07467d9 100644 --- a/.github/workflows/tests-pass-check-pr.yml +++ b/.github/workflows/tests-pass-check-pr.yml @@ -1,24 +1,24 @@ name: "Check if \"Run tests\" action succeeded" on: - pull_request: - types: - - opened - - reopened - - edited - - synchronize + pull_request: + types: + - opened + - reopened + - edited + - synchronize jobs: - pr-run-test-action: - name: Check if "Run tests" action succeeded - timeout-minutes: 60 - concurrency: - group: ${{ github.head_ref }} - cancel-in-progress: true - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: node install - run: cd ./.github/helpers && npm i - - name: Calling github API - run: cd ./.github/helpers && GITHUB_TOKEN=${{ github.token }} REPO=${{ github.repository }} RUN_ID=${{ github.run_id }} BRANCH=${{ github.head_ref }} JOB_ID=${{ github.job }} SOURCE_OWNER=${{ github.event.pull_request.head.repo.owner.login }} CURRENT_SHA=${{ github.event.pull_request.head.sha }} node node_modules/github-workflow-helpers/test-pass-check-pr.js \ No newline at end of file + pr-run-test-action: + name: Check if "Run tests" action succeeded + timeout-minutes: 60 + concurrency: + group: ${{ github.head_ref }} + cancel-in-progress: true + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: node install + run: cd ./.github/helpers && npm i + - name: Calling github API + run: cd ./.github/helpers && GITHUB_TOKEN=${{ github.token }} REPO=${{ github.repository }} RUN_ID=${{ github.run_id }} BRANCH=${{ github.head_ref }} JOB_ID=${{ github.job }} SOURCE_OWNER=${{ github.event.pull_request.head.repo.owner.login }} CURRENT_SHA=${{ github.event.pull_request.head.sha }} node node_modules/github-workflow-helpers/test-pass-check-pr.js \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9634417..dc2030d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,19 +4,19 @@ on: inputs: coreRepoOwnerName: description: 'supertokens-core repo owner name' - default: supertokens + default: supertokens required: true coreRepoBranch: description: 'supertokens-core repos branch name' - default: master + default: master required: true pluginRepoOwnerName: description: 'supertokens-plugin-interface repo owner name' - default: supertokens + default: supertokens required: true pluginInterfaceBranch: description: 'supertokens-plugin-interface repos branch name' - default: master + default: master required: true jobs: @@ -30,10 +30,10 @@ jobs: mysql: image: mysql:latest env: - MYSQL_DATABASE: supertokens - MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: supertokens + MYSQL_ROOT_PASSWORD: root ports: - - 3306 + - 3306 options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5 steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 80688aa..53058ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,8 +29,8 @@ ALTER TABLE tenant_configs ALTER COLUMN is_first_factors_null DROP DEFAULT; - Support for MFA recipe - Adds `firstFactors` and `requiredSecondaryFactors` for tenant config. - Adds a new `useStaticKey` param to `updateSessionInfo_Transaction` - - This enables smooth switching between `useDynamicAccessTokenSigningKey` settings by allowing refresh calls to - change the signing key type of a session + - This enables smooth switching between `useDynamicAccessTokenSigningKey` settings by allowing refresh calls to + change the signing key type of a session - Fixes performance issue with user pagination ### Migration @@ -68,13 +68,13 @@ ALTER TABLE user_roles - Fixes the issue where passwords were inadvertently logged in the logs. - Adds tests to check connection pool behaviour. -- Adds `mysql_idle_connection_timeout` and `mysql_minimum_idle_connections` configs to control active connections to the database. +- Adds `mysql_idle_connection_timeout` and `mysql_minimum_idle_connections` configs to control active connections to the + database. ## [5.0.5] - 2023-12-06 - Validates db config types in `canBeUsed` function - ## [5.0.4] - 2023-11-10 - Adds index on `app_id_to_user_id` table to improve performance of get user by id queries @@ -107,15 +107,16 @@ CREATE INDEX app_id_to_user_id_user_id_index ON app_id_to_user_id (user_id); ### Changes - Support for Account Linking - - Adds columns `primary_or_recipe_user_id`, `is_linked_or_is_a_primary_user` and `primary_or_recipe_user_time_joined` to `all_auth_recipe_users` table - - Adds columns `primary_or_recipe_user_id` and `is_linked_or_is_a_primary_user` to `app_id_to_user_id` table - - Removes index `all_auth_recipe_users_pagination_index` and addes `all_auth_recipe_users_pagination_index1`, - `all_auth_recipe_users_pagination_index2`, `all_auth_recipe_users_pagination_index3` and - `all_auth_recipe_users_pagination_index4` indexes instead on `all_auth_recipe_users` table - - Adds `all_auth_recipe_users_recipe_id_index` on `all_auth_recipe_users` table - - Adds `all_auth_recipe_users_primary_user_id_index` on `all_auth_recipe_users` table - - Adds `email` column to `emailpassword_pswd_reset_tokens` table - - Changes `user_id` foreign key constraint on `emailpassword_pswd_reset_tokens` to `app_id_to_user_id` table + - Adds columns `primary_or_recipe_user_id`, `is_linked_or_is_a_primary_user` + and `primary_or_recipe_user_time_joined` to `all_auth_recipe_users` table + - Adds columns `primary_or_recipe_user_id` and `is_linked_or_is_a_primary_user` to `app_id_to_user_id` table + - Removes index `all_auth_recipe_users_pagination_index` and addes `all_auth_recipe_users_pagination_index1`, + `all_auth_recipe_users_pagination_index2`, `all_auth_recipe_users_pagination_index3` and + `all_auth_recipe_users_pagination_index4` indexes instead on `all_auth_recipe_users` table + - Adds `all_auth_recipe_users_recipe_id_index` on `all_auth_recipe_users` table + - Adds `all_auth_recipe_users_primary_user_id_index` on `all_auth_recipe_users` table + - Adds `email` column to `emailpassword_pswd_reset_tokens` table + - Changes `user_id` foreign key constraint on `emailpassword_pswd_reset_tokens` to `app_id_to_user_id` table ### Migration @@ -200,16 +201,16 @@ CREATE INDEX app_id_to_user_id_user_id_index ON app_id_to_user_id (user_id); - Fixes duplicate users in users search queries when user is associated to multiple tenants - ## [4.0.0] - 2023-06-02 ### Changes - Support for multitenancy - - New tables `apps` and `tenants` have been added. - - Schema of tables have been changed, adding `app_id` and `tenant_id` columns in tables and constraints & indexes have been modified to include this columns. - - New user tables have been added to map users to apps and tenants. - - New tables for multitenancy have been added. + - New tables `apps` and `tenants` have been added. + - Schema of tables have been changed, adding `app_id` and `tenant_id` columns in tables and constraints & indexes + have been modified to include this columns. + - New user tables have been added to map users to apps and tenants. + - New tables for multitenancy have been added. - Increased transaction retry count to 50 from 20. ### Migration @@ -1044,19 +1045,19 @@ CREATE INDEX app_id_to_user_id_user_id_index ON app_id_to_user_id (user_id); ### Migration - If using `access_token_signing_key_dynamic` false in the core: - - ```sql - ALTER TABLE session_info ADD COLUMN use_static_key BOOLEAN NOT NULL DEFAULT true; - ALTER TABLE session_info ALTER COLUMN use_static_key DROP DEFAULT; + - ```sql + ALTER TABLE session_info ADD COLUMN use_static_key BOOLEAN NOT NULL DEFAULT true; + ALTER TABLE session_info ALTER COLUMN use_static_key DROP DEFAULT; ``` - - ```sql + - ```sql INSERT INTO jwt_signing_keys(key_id, key_string, algorithm, created_at) select CONCAT('s-', created_at_time) as key_id, value as key_string, 'RS256' as algorithm, created_at_time as created_at from session_access_token_signing_keys; ``` - If using `access_token_signing_key_dynamic` true (or not set) in the core: - - ```sql - ALTER TABLE session_info ADD COLUMN use_static_key BOOLEAN NOT NULL DEFAULT false; - ALTER TABLE session_info ALTER COLUMN use_static_key DROP DEFAULT; + - ```sql + ALTER TABLE session_info ADD COLUMN use_static_key BOOLEAN NOT NULL DEFAULT false; + ALTER TABLE session_info ALTER COLUMN use_static_key DROP DEFAULT; ``` ## [2.4.0] - 2023-03-30 @@ -1064,15 +1065,17 @@ CREATE INDEX app_id_to_user_id_user_id_index ON app_id_to_user_id (user_id); - Support for Dashboard Search ## [2.3.0] - 2023-03-27 + - Support for TOTP recipe - Support for active users ### Database changes - Add new tables for TOTP recipe: - - `totp_users` that stores the users that have enabled TOTP - - `totp_user_devices` that stores devices (each device has its own secret) for each user - - `totp_used_codes` that stores used codes for each user. This is to implement rate limiting and prevent replay attacks. + - `totp_users` that stores the users that have enabled TOTP + - `totp_user_devices` that stores devices (each device has its own secret) for each user + - `totp_used_codes` that stores used codes for each user. This is to implement rate limiting and prevent replay + attacks. - Add `user_last_active` table to store the last active time of a user. ## [2.2.0] - 2023-02-21 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c03e4a0..12762f3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,30 +1,40 @@ - # Contributing -We're so excited you're interested in helping with SuperTokens! We are happy to help you get started, even if you don't have any previous open-source experience :blush: +We're so excited you're interested in helping with SuperTokens! We are happy to help you get started, even if you don't +have any previous open-source experience :blush: ## New to Open Source? -1. Take a look at [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) -2. Go thorugh the [SuperTokens Code of Conduct](https://github.com/supertokens/supertokens-mysql-plugin/blob/master/CODE_OF_CONDUCT.md) + +1. Take a look + at [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) +2. Go thorugh + the [SuperTokens Code of Conduct](https://github.com/supertokens/supertokens-mysql-plugin/blob/master/CODE_OF_CONDUCT.md) ## Where to ask Questions? -1. Check our [Github Issues](https://github.com/supertokens/supertokens-mysql-plugin/issues) to see if someone has already answered your question. -2. Join our community on [Discord](https://supertokens.io/discord) and feel free to ask us your questions +1. Check our [Github Issues](https://github.com/supertokens/supertokens-mysql-plugin/issues) to see if someone has + already answered your question. +2. Join our community on [Discord](https://supertokens.io/discord) and feel free to ask us your questions ## Development Setup + ### Prerequisites + - OS: Linux or macOS - IDE: Intellij (recommended) or equivalent IDE - MySQL ### Project Setup -1. Setup the `supertokens-core` by following [this guide](https://github.com/supertokens/supertokens-core/blob/master/CONTRIBUTING.md#development-setup). If you are not modifying the `supertokens-core` repo, then you do not need to fork that. + +1. Setup the `supertokens-core` by + following [this guide](https://github.com/supertokens/supertokens-core/blob/master/CONTRIBUTING.md#development-setup). + If you are not modifying the `supertokens-core` repo, then you do not need to fork that. 2. Start MySQL on port `3306`, listening to `locahost` or `0.0.0.0`. 3. Create a MySQL user (if not already exists) with username `root` and password `root` 4. Create a database called `supertokens`. 5. Fork the `supertokens-mysql-plugin` repository -6. Open `modules.txt` in the `supertokens-root` directory and change it so that it looks like (the last line has changed): +6. Open `modules.txt` in the `supertokens-root` directory and change it so that it looks like (the last line has + changed): ``` // put module name like module name,branch name,github username(if contributing with a forked repository) and then call ./loadModules script core,master @@ -32,20 +42,28 @@ We're so excited you're interested in helping with SuperTokens! We are happy to mysql-plugin,master, ``` 7. Run `./loadModules` in the `supertokens-root` directory. This will clone your forked `supertokens-mysql-plugin` repo. -8. Follow the [CONTRIBUTING.md](https://github.com/supertokens/supertokens-core/blob/master/CONTRIBUTING.md#modifying-code) guide from `supertokens-core` repo for modifying and testing. +8. Follow + the [CONTRIBUTING.md](https://github.com/supertokens/supertokens-core/blob/master/CONTRIBUTING.md#modifying-code) + guide from `supertokens-core` repo for modifying and testing. ## Pull Request + 1. Before submitting a pull request make sure all tests have passed -2. Reference the relevant issue or pull request and give a clear description of changes/features added when submitting a pull request +2. Reference the relevant issue or pull request and give a clear description of changes/features added when submitting a + pull request 3. Make sure the PR title follows [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) specification ## SuperTokens Community -SuperTokens is made possible by a passionate team and a strong community of developers. If you have any questions or would like to get more involved in the SuperTokens community you can check out: - - [Github Issues](https://github.com/supertokens/supertokens-mysql-plugin/issues) - - [Discord](https://supertokens.io/discord) - - [Twitter](https://twitter.com/supertokensio) - - or [email us](mailto:team@supertokens.io) - + +SuperTokens is made possible by a passionate team and a strong community of developers. If you have any questions or +would like to get more involved in the SuperTokens community you can check out: + +- [Github Issues](https://github.com/supertokens/supertokens-mysql-plugin/issues) +- [Discord](https://supertokens.io/discord) +- [Twitter](https://twitter.com/supertokensio) +- or [email us](mailto:team@supertokens.io) + Additional resources you might find useful: - - [SuperTokens Docs](https://supertokens.io/docs/community/getting-started/installation) - - [Blog Posts](https://supertokens.io/blog/) + +- [SuperTokens Docs](https://supertokens.io/docs/community/getting-started/installation) +- [Blog Posts](https://supertokens.io/blog/) diff --git a/LICENSE.md b/LICENSE.md index e105852..7a85c9c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,191 +1,192 @@ - Copyright (c) 2020, VRAI Labs and/or its affiliates. All rights reserved. - - This software is licensed under the Apache License, Version 2.0 (the - "License") as published by the Apache Software Foundation. - - You may not use this software except in compliance with the License. A copy - of the License is available below the line. - - 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. +Copyright (c) 2020, VRAI Labs and/or its affiliates. All rights reserved. + +This software is licensed under the Apache License, Version 2.0 (the +"License") as published by the Apache Software Foundation. + +You may not use this software except in compliance with the License. A copy +of the License is available below the line. + +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. ------------------------------------------------------------------------------- + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/README.md b/README.md index b4be068..317b931 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - ![SuperTokens banner](https://raw.githubusercontent.com/supertokens/supertokens-logo/master/images/Artboard%20%E2%80%93%2027%402x.png) # MySQL plugin for SuperTokens Community @@ -8,18 +7,26 @@ alt="chat on Discord"> ## About + This plugin is responsible for interfacing between SuperTokens Community version and an instance of MySQL. Learn more at https://supertokens.io ## Documentation + To see documentation, please click [here](https://supertokens.io/docs/community/introduction). ## Contributing -Please refer to the [CONTRIBUTING.md](https://github.com/supertokens/supertokens-mysql-plugin/blob/master/CONTRIBUTING.md) file in this repo. + +Please refer to +the [CONTRIBUTING.md](https://github.com/supertokens/supertokens-mysql-plugin/blob/master/CONTRIBUTING.md) file in this +repo. ## Contact us -For any queries, or support requests, please email us at team@supertokens.io, or join our [Discord](supertokens.io/discord) server. + +For any queries, or support requests, please email us at team@supertokens.io, or join +our [Discord](supertokens.io/discord) server. # Authors + Created with :heart: by the folks at SuperTokens.io. diff --git a/src/main/java/io/supertokens/storage/mysql/QueryExecutorTemplate.java b/src/main/java/io/supertokens/storage/mysql/QueryExecutorTemplate.java index 91d8760..50e7325 100644 --- a/src/main/java/io/supertokens/storage/mysql/QueryExecutorTemplate.java +++ b/src/main/java/io/supertokens/storage/mysql/QueryExecutorTemplate.java @@ -26,14 +26,14 @@ public interface QueryExecutorTemplate { static T execute(Start start, String QUERY, PreparedStatementValueSetter setter, - ResultSetValueExtractor mapper) throws SQLException, StorageQueryException { + ResultSetValueExtractor mapper) throws SQLException, StorageQueryException { try (Connection con = ConnectionPool.getConnection(start)) { return execute(con, QUERY, setter, mapper); } } static T execute(Connection con, String QUERY, PreparedStatementValueSetter setter, - ResultSetValueExtractor mapper) throws SQLException, StorageQueryException { + ResultSetValueExtractor mapper) throws SQLException, StorageQueryException { if (setter == null) setter = PreparedStatementValueSetter.NO_OP_SETTER; try (PreparedStatement pst = con.prepareStatement(QUERY)) { diff --git a/src/main/java/io/supertokens/storage/mysql/Start.java b/src/main/java/io/supertokens/storage/mysql/Start.java index 3458631..4fd39cd 100644 --- a/src/main/java/io/supertokens/storage/mysql/Start.java +++ b/src/main/java/io/supertokens/storage/mysql/Start.java @@ -45,10 +45,13 @@ import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException; import io.supertokens.pluginInterface.jwt.JWTRecipeStorage; -import io.supertokens.pluginInterface.jwt.JWTSigningKeyInfo; +import io.supertokens.pluginInterface.jwt.JWTSigningKeyInfo; import io.supertokens.pluginInterface.jwt.exceptions.DuplicateKeyIdException; import io.supertokens.pluginInterface.jwt.sqlstorage.JWTRecipeSQLStorage; -import io.supertokens.pluginInterface.multitenancy.*; +import io.supertokens.pluginInterface.multitenancy.AppIdentifier; +import io.supertokens.pluginInterface.multitenancy.MultitenancyStorage; +import io.supertokens.pluginInterface.multitenancy.TenantConfig; +import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; import io.supertokens.pluginInterface.multitenancy.exceptions.DuplicateClientTypeException; import io.supertokens.pluginInterface.multitenancy.exceptions.DuplicateTenantException; import io.supertokens.pluginInterface.multitenancy.exceptions.DuplicateThirdPartyIdException; @@ -68,8 +71,8 @@ import io.supertokens.pluginInterface.totp.TOTPStorage; import io.supertokens.pluginInterface.totp.TOTPUsedCode; import io.supertokens.pluginInterface.totp.exception.DeviceAlreadyExistsException; -import io.supertokens.pluginInterface.totp.exception.UnknownTotpUserIdException; import io.supertokens.pluginInterface.totp.exception.UnknownDeviceException; +import io.supertokens.pluginInterface.totp.exception.UnknownTotpUserIdException; import io.supertokens.pluginInterface.totp.exception.UsedCodeAlreadyExistsException; import io.supertokens.pluginInterface.totp.sqlStorage.TOTPSQLStorage; import io.supertokens.pluginInterface.useridmapping.UserIdMapping; @@ -103,7 +106,6 @@ import java.util.Set; import static io.supertokens.storage.mysql.QueryExecutorTemplate.execute; -import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; public class Start @@ -155,7 +157,8 @@ public STORAGE_TYPE getType() { } @Override - public void loadConfig(JsonObject configJson, Set logLevels, TenantIdentifier tenantIdentifier) throws InvalidConfigException { + public void loadConfig(JsonObject configJson, Set logLevels, TenantIdentifier tenantIdentifier) + throws InvalidConfigException { Config.loadConfig(this, configJson, logLevels, tenantIdentifier); } @@ -277,7 +280,8 @@ public T startTransaction(TransactionLogic logic, TransactionIsolationLev // happen } if ((e instanceof SQLTransactionRollbackException - || (e.getMessage() != null && e.getMessage().toLowerCase().contains("deadlock"))) && tries == NUM_TRIES) { + || (e.getMessage() != null && e.getMessage().toLowerCase().contains("deadlock"))) && + tries == NUM_TRIES) { ProcessState.getInstance(this).addState(ProcessState.PROCESS_STATE.DEADLOCK_NOT_RESOLVED, e); } if (e instanceof StorageQueryException) { @@ -749,7 +753,8 @@ public boolean isUserIdBeingUsedInNonAuthRecipe(AppIdentifier appIdentifier, Str @TestOnly @Override - public void addInfoToNonAuthRecipesBasedOnUserId(TenantIdentifier tenantIdentifier, String className, String userId) throws StorageQueryException { + public void addInfoToNonAuthRecipesBasedOnUserId(TenantIdentifier tenantIdentifier, String className, String userId) + throws StorageQueryException { if (!isTesting) { throw new UnsupportedOperationException(); } @@ -812,14 +817,15 @@ public void addInfoToNonAuthRecipesBasedOnUserId(TenantIdentifier tenantIdentifi } } else if (className.equals(TOTPStorage.class.getName())) { try { - TOTPDevice device = new TOTPDevice(userId, "testDevice", "secret", 0, 30, false, System.currentTimeMillis()); + TOTPDevice device = new TOTPDevice(userId, "testDevice", "secret", 0, 30, false, + System.currentTimeMillis()); this.startTransaction(con -> { try { long now = System.currentTimeMillis(); Connection sqlCon = (Connection) con.getConnection(); TOTPQueries.createDevice_Transaction(this, sqlCon, tenantIdentifier.toAppIdentifier(), device); TOTPQueries.insertUsedCode_Transaction(this, - sqlCon, tenantIdentifier, new TOTPUsedCode(userId, "123456", true, 1000+now, now)); + sqlCon, tenantIdentifier, new TOTPUsedCode(userId, "123456", true, 1000 + now, now)); } catch (SQLException e) { throw new StorageTransactionLogicException(e); } @@ -854,7 +860,7 @@ public String[] getProtectedConfigsFromSuperTokensSaaSUsers() { @Override public AuthRecipeUserInfo signUp(TenantIdentifier tenantIdentifier, String id, String email, String passwordHash, - long timeJoined) + long timeJoined) throws StorageQueryException, DuplicateUserIdException, DuplicateEmailException, TenantOrAppNotFoundException { try { @@ -1162,8 +1168,10 @@ public boolean isEmailVerified(AppIdentifier appIdentifier, String userId, Strin } @Override - public void updateIsEmailVerifiedToExternalUserId(AppIdentifier appIdentifier, String supertokensUserId, String externalUserId) throws StorageQueryException { - EmailVerificationQueries.updateIsEmailVerifiedToExternalUserId(this, appIdentifier, supertokensUserId, externalUserId); + public void updateIsEmailVerifiedToExternalUserId(AppIdentifier appIdentifier, String supertokensUserId, + String externalUserId) throws StorageQueryException { + EmailVerificationQueries.updateIsEmailVerifiedToExternalUserId(this, appIdentifier, supertokensUserId, + externalUserId); } @Override @@ -1301,7 +1309,7 @@ public int countUsersActiveSince(AppIdentifier appIdentifier, long time) throws } } - @Override + @Override public void deleteUserActive_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId) throws StorageQueryException { try { @@ -1423,7 +1431,7 @@ private boolean isForeignKeyConstraintError(String serverMessage, String tableNa public boolean isPrimaryKeyError(String serverMessage, String tableName) { return serverMessage.endsWith("'" + tableName + ".PRIMARY'") - || serverMessage.endsWith("'PRIMARY'"); + || serverMessage.endsWith("'PRIMARY'"); } private boolean isPrimaryKeyError(String serverMessage, String tableName, String value) { @@ -1671,10 +1679,10 @@ public void createCode(TenantIdentifier tenantIdentifier, PasswordlessCode code) @Override public AuthRecipeUserInfo createUser(TenantIdentifier tenantIdentifier, - String id, - @javax.annotation.Nullable String email, - @javax.annotation.Nullable - String phoneNumber, long timeJoined) + String id, + @javax.annotation.Nullable String email, + @javax.annotation.Nullable + String phoneNumber, long timeJoined) throws StorageQueryException, DuplicateEmailException, DuplicatePhoneNumberException, DuplicateUserIdException, TenantOrAppNotFoundException { @@ -2204,7 +2212,8 @@ public void createTenant(TenantConfig tenantConfig) try { MultitenancyQueries.createTenantConfig(this, tenantConfig); } catch (StorageTransactionLogicException e) { - // We are not doing PRIMARY KEY checks here as there are multiple insert queries happening on multiple tables + // We are not doing PRIMARY KEY checks here as there are multiple insert queries happening on multiple + // tables // and it is easier to catch which PRIMARY KEY failed around the insert query itself. if (e.actualException instanceof DuplicateTenantException) { throw (DuplicateTenantException) e.actualException; @@ -2262,7 +2271,8 @@ public void overwriteTenantConfig(TenantConfig tenantConfig) try { MultitenancyQueries.overwriteTenantConfig(this, tenantConfig); } catch (StorageTransactionLogicException e) { - // We are not doing PRIMARY KEY checks here as there are multiple insert queries happening on multiple tables + // We are not doing PRIMARY KEY checks here as there are multiple insert queries happening on multiple + // tables // and it is easier to catch which PRIMARY KEY failed around the insert query itself. if (e.actualException instanceof TenantOrAppNotFoundException) { throw (TenantOrAppNotFoundException) e.actualException; @@ -2306,7 +2316,8 @@ public TenantConfig[] getAllTenants() throws StorageQueryException { } @Override - public boolean addUserIdToTenant_Transaction(TenantIdentifier tenantIdentifier, TransactionConnection con, String userId) + public boolean addUserIdToTenant_Transaction(TenantIdentifier tenantIdentifier, TransactionConnection con, + String userId) throws TenantOrAppNotFoundException, UnknownUserIdException, StorageQueryException, DuplicateEmailException, DuplicateThirdPartyUserException, DuplicatePhoneNumberException { Connection sqlCon = (Connection) con.getConnection(); @@ -2321,12 +2332,12 @@ public boolean addUserIdToTenant_Transaction(TenantIdentifier tenantIdentifier, boolean added; if (recipeId.equals("emailpassword")) { added = EmailPasswordQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier, - userId); + userId); } else if (recipeId.equals("thirdparty")) { added = ThirdPartyQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier, userId); } else if (recipeId.equals("passwordless")) { added = PasswordlessQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier, - userId); + userId); } else { throw new IllegalStateException("Should never come here!"); } @@ -2343,7 +2354,8 @@ public boolean addUserIdToTenant_Transaction(TenantIdentifier tenantIdentifier, if (isUniqueConstraintError(serverErrorMessage, config.getEmailPasswordUserToTenantTable(), "email")) { throw new DuplicateEmailException(); } - if (isUniqueConstraintError(serverErrorMessage, config.getThirdPartyUserToTenantTable(), "third_party_user_id")) { + if (isUniqueConstraintError(serverErrorMessage, config.getThirdPartyUserToTenantTable(), + "third_party_user_id")) { throw new DuplicateThirdPartyUserException(); } if (isUniqueConstraintError(serverErrorMessage, @@ -2598,7 +2610,8 @@ public void createDevice(AppIdentifier appIdentifier, TOTPDevice device) } @Override - public TOTPDevice createDevice_Transaction(TransactionConnection con, AppIdentifier appIdentifier, TOTPDevice device) + public TOTPDevice createDevice_Transaction(TransactionConnection con, AppIdentifier appIdentifier, + TOTPDevice device) throws DeviceAlreadyExistsException, TenantOrAppNotFoundException, StorageQueryException { Connection sqlCon = (Connection) con.getConnection(); try { @@ -2620,7 +2633,8 @@ public TOTPDevice createDevice_Transaction(TransactionConnection con, AppIdentif } @Override - public TOTPDevice getDeviceByName_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId, String deviceName) throws StorageQueryException { + public TOTPDevice getDeviceByName_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId, + String deviceName) throws StorageQueryException { Connection sqlCon = (Connection) con.getConnection(); try { return TOTPQueries.getDeviceByName_Transaction(this, sqlCon, appIdentifier, userId, deviceName); @@ -2693,7 +2707,7 @@ public void updateDeviceName(AppIdentifier appIdentifier, String userId, String throw new DeviceAlreadyExistsException(); } } - throw new StorageQueryException(e); + throw new StorageQueryException(e); } } @@ -2732,7 +2746,8 @@ public void insertUsedCode_Transaction(TransactionConnection con, TenantIdentifi } else if (isForeignKeyConstraintError(e.getMessage(), Config.getConfig(this).getTotpUsedCodesTable(), "user_id")) { throw new UnknownTotpUserIdException(); - } else if (isForeignKeyConstraintError(e.getMessage(), Config.getConfig(this).getTotpUsedCodesTable(), "tenant_id")) { + } else if (isForeignKeyConstraintError(e.getMessage(), Config.getConfig(this).getTotpUsedCodesTable(), + "tenant_id")) { throw new TenantOrAppNotFoundException(tenantIdentifier); } @@ -2898,7 +2913,8 @@ public void linkAccounts_Transaction(AppIdentifier appIdentifier, TransactionCon } @Override - public void unlinkAccounts_Transaction(AppIdentifier appIdentifier, TransactionConnection con, String primaryUserId, String recipeUserId) + public void unlinkAccounts_Transaction(AppIdentifier appIdentifier, TransactionConnection con, String primaryUserId, + String recipeUserId) throws StorageQueryException { try { Connection sqlCon = (Connection) con.getConnection(); @@ -2931,7 +2947,8 @@ public boolean checkIfUsesAccountLinking(AppIdentifier appIdentifier) throws Sto } @Override - public int countUsersThatHaveMoreThanOneLoginMethodAndActiveSince(AppIdentifier appIdentifier, long sinceTime) throws StorageQueryException { + public int countUsersThatHaveMoreThanOneLoginMethodAndActiveSince(AppIdentifier appIdentifier, long sinceTime) + throws StorageQueryException { try { return ActiveUsersQueries.countUsersActiveSinceAndHasMoreThanOneLoginMethod(this, appIdentifier, sinceTime); } catch (SQLException e) { @@ -2960,11 +2977,13 @@ public UserIdMapping getUserIdMapping_Transaction(TransactionConnection con, App try { Connection sqlCon = (Connection) con.getConnection(); if (isSuperTokensUserId) { - return UserIdMappingQueries.getuseraIdMappingWithSuperTokensUserId_Transaction(this, sqlCon, appIdentifier, + return UserIdMappingQueries.getuseraIdMappingWithSuperTokensUserId_Transaction(this, sqlCon, + appIdentifier, userId); } - return UserIdMappingQueries.getUserIdMappingWithExternalUserId_Transaction(this, sqlCon, appIdentifier, userId); + return UserIdMappingQueries.getUserIdMappingWithExternalUserId_Transaction(this, sqlCon, appIdentifier, + userId); } catch (SQLException e) { throw new StorageQueryException(e); } @@ -2985,7 +3004,8 @@ public UserIdMapping[] getUserIdMapping_Transaction(TransactionConnection con, A } @Override - public int getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(AppIdentifier appIdentifier) throws StorageQueryException { + public int getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(AppIdentifier appIdentifier) + throws StorageQueryException { try { return GeneralQueries.getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(this, appIdentifier); } catch (SQLException e) { @@ -2994,9 +3014,12 @@ public int getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(AppIdentifier ap } @Override - public int countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(AppIdentifier appIdentifier, long sinceTime) throws StorageQueryException { + public int countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(AppIdentifier appIdentifier, + long sinceTime) + throws StorageQueryException { try { - return ActiveUsersQueries.countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(this, appIdentifier, sinceTime); + return ActiveUsersQueries.countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(this, + appIdentifier, sinceTime); } catch (SQLException e) { throw new StorageQueryException(e); } @@ -3008,7 +3031,7 @@ public static boolean isEnabledForDeadlockTesting() { @TestOnly public static void setEnableForDeadlockTesting(boolean value) { - assert(isTesting); + assert (isTesting); enableForDeadlockTesting = value; } diff --git a/src/main/java/io/supertokens/storage/mysql/annotations/DashboardInfo.java b/src/main/java/io/supertokens/storage/mysql/annotations/DashboardInfo.java index db55e48..9d7150e 100644 --- a/src/main/java/io/supertokens/storage/mysql/annotations/DashboardInfo.java +++ b/src/main/java/io/supertokens/storage/mysql/annotations/DashboardInfo.java @@ -25,11 +25,15 @@ * Annotation to provide a description for a configuration fields. To be used on the fields of `CoreConfig` and config * class in the plugin like `PostgreSQLConfig`, `MysqlConfig`, etc. */ -@Retention(RetentionPolicy.RUNTIME) // Make annotation accessible at runtime so that config descriptions can be read from API +@Retention(RetentionPolicy.RUNTIME) +// Make annotation accessible at runtime so that config descriptions can be read from API @Target(ElementType.FIELD) // Annotation can only be applied to fields public @interface DashboardInfo { String description() default ""; + boolean isOptional() default false; + String defaultValue() default ""; + boolean isEditable() default false; } \ No newline at end of file diff --git a/src/main/java/io/supertokens/storage/mysql/config/Config.java b/src/main/java/io/supertokens/storage/mysql/config/Config.java index 41cef1f..a45a912 100644 --- a/src/main/java/io/supertokens/storage/mysql/config/Config.java +++ b/src/main/java/io/supertokens/storage/mysql/config/Config.java @@ -53,7 +53,8 @@ private static Config getInstance(Start start) { return (Config) start.getResourceDistributor().getResource(RESOURCE_KEY); } - public static void loadConfig(Start start, JsonObject configJson, Set logLevels, TenantIdentifier tenantIdentifier) + public static void loadConfig(Start start, JsonObject configJson, Set logLevels, + TenantIdentifier tenantIdentifier) throws InvalidConfigException { if (getInstance(start) != null) { return; @@ -93,6 +94,7 @@ public static MySQLConfig getConfig(Start start) { public static Set getLogLevels(Start start) { return getInstance(start).logLevels; } + public static void setLogLevels(Start start, Set logLevels) { getInstance(start).logLevels = logLevels; } diff --git a/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java b/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java index c08a186..ea2f359 100644 --- a/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java +++ b/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java @@ -41,95 +41,135 @@ public class MySQLConfig { @JsonProperty @ConnectionPoolProperty - @DashboardInfo(description = "Defines the connection pool size to MySQL. Please see https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing", defaultValue = "10", isOptional = true, isEditable = true) + @DashboardInfo( + description = "Defines the connection pool size to MySQL. Please see https://github" + + ".com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing", + defaultValue = "10", isOptional = true, isEditable = true) private int mysql_connection_pool_size = 10; @JsonProperty @UserPoolProperty - @DashboardInfo(description = "Specify the mysql host url here. For example: - \"localhost\" - \"192.168.0.1\" - \"\" - \"example.com\"", defaultValue = "\"localhost\"", isOptional = true) + @DashboardInfo( + description = "Specify the mysql host url here. For example: - \"localhost\" - \"192.168.0.1\" - \"\" - \"example.com\"", + defaultValue = "\"localhost\"", isOptional = true) private String mysql_host = "localhost"; @JsonProperty @UserPoolProperty - @DashboardInfo(description = "Specify the port to use when connecting to MySQL instance.", defaultValue = "3306", isOptional = true) + @DashboardInfo(description = "Specify the port to use when connecting to MySQL instance.", defaultValue = "3306", + isOptional = true) private int mysql_port = 3306; @JsonProperty @ConnectionPoolProperty - @DashboardInfo(description = "The MySQL user to use to query the database. If the relevant tables are not already created by you, this user should have the ability to create new tables. To see the tables needed, visit: https://supertokens.com/docs/thirdpartyemailpassword/pre-built-ui/setup/database-setup/mysql", isOptional = true, defaultValue = "\"root\"") + @DashboardInfo( + description = "The MySQL user to use to query the database. If the relevant tables are not already " + + "created by you, this user should have the ability to create new tables. To see the tables " + + "needed, visit: https://supertokens.com/docs/thirdpartyemailpassword/pre-built-ui/setup/database" + + "-setup/mysql", + isOptional = true, defaultValue = "\"root\"") private String mysql_user = null; @JsonProperty @ConnectionPoolProperty - @DashboardInfo(description = "Password for the MySQL user. If you have not set a password make this an empty string.", isOptional = true, defaultValue = "no password") + @DashboardInfo( + description = "Password for the MySQL user. If you have not set a password make this an empty string.", + isOptional = true, defaultValue = "no password") private String mysql_password = null; @JsonProperty @UserPoolProperty - @DashboardInfo(description = "The database name to store SuperTokens related data.", defaultValue = "\"supertokens\"", isOptional = true) + @DashboardInfo(description = "The database name to store SuperTokens related data.", + defaultValue = "\"supertokens\"", isOptional = true) private String mysql_database_name = "supertokens"; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "A prefix to add to all table names managed by SuperTokens. An \"_\" will be added between this prefix and the actual table name if the prefix is defined.", defaultValue = "\"\"", isOptional = true) + @DashboardInfo( + description = "A prefix to add to all table names managed by SuperTokens. An \"_\" will be added between " + + "this prefix and the actual table name if the prefix is defined.", + defaultValue = "\"\"", isOptional = true) private String mysql_table_names_prefix = ""; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "Specify the name of the table that will store secret keys and app info necessary for the functioning sessions.", defaultValue = "\"key_value\"", isOptional = true) + @DashboardInfo( + description = "Specify the name of the table that will store secret keys and app info necessary for the " + + "functioning sessions.", + defaultValue = "\"key_value\"", isOptional = true) private String mysql_key_value_table_name = null; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "Specify the name of the table that will store the session info for users.", defaultValue = "\"session_info\"", isOptional = true) + @DashboardInfo(description = "Specify the name of the table that will store the session info for users.", + defaultValue = "\"session_info\"", isOptional = true) private String mysql_session_info_table_name = null; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "Specify the name of the table that will store the user information, along with their email and hashed password.", defaultValue = "\"emailpassword_users\"", isOptional = true) + @DashboardInfo( + description = "Specify the name of the table that will store the user information, along with their email" + + " and hashed password.", + defaultValue = "\"emailpassword_users\"", isOptional = true) private String mysql_emailpassword_users_table_name = null; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "Specify the name of the table that will store the password reset tokens for users.", defaultValue = "\"emailpassword_pswd_reset_tokens\"", isOptional = true) + @DashboardInfo(description = "Specify the name of the table that will store the password reset tokens for users.", + defaultValue = "\"emailpassword_pswd_reset_tokens\"", isOptional = true) private String mysql_emailpassword_pswd_reset_tokens_table_name = null; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "Specify the name of the table that will store the email verification tokens for users.", defaultValue = "\"emailverification_tokens\"", isOptional = true) + @DashboardInfo( + description = "Specify the name of the table that will store the email verification tokens for users.", + defaultValue = "\"emailverification_tokens\"", isOptional = true) private String mysql_emailverification_tokens_table_name = null; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "Specify the name of the table that will store the verified email addresses.", defaultValue = "\"emailverification_verified_emails\"", isOptional = true) + @DashboardInfo(description = "Specify the name of the table that will store the verified email addresses.", + defaultValue = "\"emailverification_verified_emails\"", isOptional = true) private String mysql_emailverification_verified_emails_table_name = null; @JsonProperty @NotConflictingWithinUserPool - @DashboardInfo(description = "Specify the name of the table that will store the thirdparty recipe users.", defaultValue = "\"thirdparty_users\"", isOptional = true) + @DashboardInfo(description = "Specify the name of the table that will store the thirdparty recipe users.", + defaultValue = "\"thirdparty_users\"", isOptional = true) private String mysql_thirdparty_users_table_name = null; @JsonProperty @IgnoreForAnnotationCheck - @DashboardInfo(description = "Specify the MySQL connection URI in the following format: mysql://[user[:[password]]@]host[:port][/dbname][?attr1=val1&attr2=val2... Values provided via other configs will override values provided by this config.", defaultValue = "null", isOptional = true) + @DashboardInfo( + description = "Specify the MySQL connection URI in the following format: " + + "mysql://[user[:[password]]@]host[:port][/dbname][?attr1=val1&attr2=val2... Values provided via " + + "other configs will override values provided by this config.", + defaultValue = "null", isOptional = true) private String mysql_connection_uri = null; @ConnectionPoolProperty - @DashboardInfo(description = "The connection attributes of the MySQL database.", defaultValue = "\"allowPublicKeyRetrieval=true\"", isOptional = true) + @DashboardInfo(description = "The connection attributes of the MySQL database.", + defaultValue = "\"allowPublicKeyRetrieval=true\"", isOptional = true) private String mysql_connection_attributes = "allowPublicKeyRetrieval=true"; @ConnectionPoolProperty - @DashboardInfo(description = "The scheme of the MySQL database.", defaultValue = "\"postgresql\"", isOptional = true) + @DashboardInfo(description = "The scheme of the MySQL database.", defaultValue = "\"postgresql\"", + isOptional = true) private String mysql_connection_scheme = "mysql"; @JsonProperty @ConnectionPoolProperty - @DashboardInfo(description = "Timeout in milliseconds for the idle connections to be closed.", defaultValue = "60000", isOptional = true, isEditable = true) + @DashboardInfo(description = "Timeout in milliseconds for the idle connections to be closed.", + defaultValue = "60000", isOptional = true, isEditable = true) private long mysql_idle_connection_timeout = 60000; @JsonProperty @ConnectionPoolProperty - @DashboardInfo(description = "Minimum number of idle connections to be kept active. If not set, minimum idle connections will be same as the connection pool size.", defaultValue = "null", isOptional = true, isEditable = true) + @DashboardInfo( + description = "Minimum number of idle connections to be kept active. If not set, minimum idle connections" + + " will be same as the connection pool size.", + defaultValue = "null", isOptional = true, isEditable = true) private Integer mysql_minimum_idle_connections = null; @IgnoreForAnnotationCheck @@ -584,7 +624,8 @@ private void validateAndNormalise(boolean skipValidation) throws InvalidConfigEx } if (mysql_emailverification_verified_emails_table_name == null) { - mysql_emailverification_verified_emails_table_name = addPrefixToTableName("emailverification_verified_emails"); + mysql_emailverification_verified_emails_table_name = addPrefixToTableName( + "emailverification_verified_emails"); } if (mysql_thirdparty_users_table_name == null) { @@ -594,7 +635,8 @@ private void validateAndNormalise(boolean skipValidation) throws InvalidConfigEx isValidAndNormalised = true; } - public void assertThatConfigFromSameUserPoolIsNotConflicting(MySQLConfig otherConfig) throws InvalidConfigException { + public void assertThatConfigFromSameUserPoolIsNotConflicting(MySQLConfig otherConfig) + throws InvalidConfigException { for (Field field : MySQLConfig.class.getDeclaredFields()) { if (field.isAnnotationPresent(NotConflictingWithinUserPool.class)) { try { @@ -634,10 +676,11 @@ public String getConnectionPoolId() { try { String fieldName = field.getName(); String fieldValue = field.get(this) != null ? field.get(this).toString() : null; - if(fieldValue == null) { + if (fieldValue == null) { continue; } - // To ensure a unique connectionPoolId we include the database password and use the "|db_pass|" identifier. + // To ensure a unique connectionPoolId we include the database password and use the "|db_pass|" + // identifier. // This facilitates easy removal of the password from logs when necessary. if (fieldName.equals("mysql_password")) { connectionPoolId.append("|db_pass|" + fieldValue + "|db_pass"); diff --git a/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java index 1905ec2..91fd34a 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java @@ -1,13 +1,13 @@ package io.supertokens.storage.mysql.queries; -import java.sql.Connection; -import java.sql.SQLException; - +import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.storage.mysql.Start; -import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.storage.mysql.config.Config; +import java.sql.Connection; +import java.sql.SQLException; + import static io.supertokens.storage.mysql.QueryExecutorTemplate.execute; import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; @@ -23,7 +23,8 @@ static String getQueryToCreateUserLastActiveTable(Start start) { + " );"; } - public static int countUsersActiveSince(Start start, AppIdentifier appIdentifier, long sinceTime) throws SQLException, StorageQueryException { + public static int countUsersActiveSince(Start start, AppIdentifier appIdentifier, long sinceTime) + throws SQLException, StorageQueryException { String QUERY = "SELECT COUNT(*) as total FROM " + Config.getConfig(start).getUserLastActiveTable() + " WHERE app_id = ? AND last_active_time >= ?"; @@ -38,7 +39,8 @@ public static int countUsersActiveSince(Start start, AppIdentifier appIdentifier }); } - public static int countUsersActiveSinceAndHasMoreThanOneLoginMethod(Start start, AppIdentifier appIdentifier, long sinceTime) + public static int countUsersActiveSinceAndHasMoreThanOneLoginMethod(Start start, AppIdentifier appIdentifier, + long sinceTime) throws SQLException, StorageQueryException { String QUERY = "SELECT count(1) as c FROM (" + " SELECT count(user_id) as num_login_methods, app_id, primary_or_recipe_user_id" @@ -77,10 +79,11 @@ public static int countUsersEnabledTotp(Start start, AppIdentifier appIdentifier public static int countUsersEnabledTotpAndActiveSince(Start start, AppIdentifier appIdentifier, long sinceTime) throws SQLException, StorageQueryException { - String QUERY = "SELECT COUNT(*) as total FROM " + Config.getConfig(start).getTotpUsersTable() + " AS totp_users " - + "INNER JOIN " + Config.getConfig(start).getUserLastActiveTable() + " AS user_last_active " - + "ON totp_users.user_id = user_last_active.user_id " - + "WHERE user_last_active.app_id = ? AND user_last_active.last_active_time >= ?"; + String QUERY = + "SELECT COUNT(*) as total FROM " + Config.getConfig(start).getTotpUsersTable() + " AS totp_users " + + "INNER JOIN " + Config.getConfig(start).getUserLastActiveTable() + " AS user_last_active " + + "ON totp_users.user_id = user_last_active.user_id " + + "WHERE user_last_active.app_id = ? AND user_last_active.last_active_time >= ?"; return execute(start, QUERY, pst -> { pst.setString(1, appIdentifier.getAppId()); @@ -93,7 +96,8 @@ public static int countUsersEnabledTotpAndActiveSince(Start start, AppIdentifier }); } - public static int updateUserLastActive(Start start, AppIdentifier appIdentifier, String userId) throws SQLException, StorageQueryException { + public static int updateUserLastActive(Start start, AppIdentifier appIdentifier, String userId) + throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + Config.getConfig(start).getUserLastActiveTable() + "(app_id, user_id, last_active_time) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE last_active_time = ?"; @@ -138,7 +142,9 @@ public static void deleteUserActive_Transaction(Connection con, Start start, App }); } - public static int countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(Start start, AppIdentifier appIdentifier, long sinceTime) + public static int countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(Start start, + AppIdentifier appIdentifier, + long sinceTime) throws SQLException, StorageQueryException { // TODO: Active users are present only on public tenant and MFA users may be present on different storages String QUERY = diff --git a/src/main/java/io/supertokens/storage/mysql/queries/DashboardQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/DashboardQueries.java index 3978be7..0b5bc3c 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/DashboardQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/DashboardQueries.java @@ -16,12 +16,6 @@ package io.supertokens.storage.mysql.queries; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - import io.supertokens.pluginInterface.RowMapper; import io.supertokens.pluginInterface.dashboard.DashboardSessionInfo; import io.supertokens.pluginInterface.dashboard.DashboardUser; @@ -32,6 +26,12 @@ import io.supertokens.storage.mysql.Start; import io.supertokens.storage.mysql.config.Config; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + public class DashboardQueries { public static String getQueryToCreateDashboardUsersTable(Start start) { @@ -100,7 +100,8 @@ public static boolean deleteDashboardUserWithUserId(Start start, AppIdentifier a } - public static DashboardUser[] getAllDashBoardUsers(Start start, AppIdentifier appIdentifier) throws SQLException, StorageQueryException { + public static DashboardUser[] getAllDashBoardUsers(Start start, AppIdentifier appIdentifier) + throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getDashboardUsersTable() + " WHERE app_id = ? ORDER BY time_joined ASC"; return QueryExecutorTemplate.execute(start, QUERY, @@ -153,7 +154,8 @@ public static boolean updateDashboardUsersPasswordWithUserId_Transaction(Start s return rowsUpdated > 0; } - public static void createDashboardSession(Start start, AppIdentifier appIdentifier, String userId, String sessionId, long timeCreated, + public static void createDashboardSession(Start start, AppIdentifier appIdentifier, String userId, String sessionId, + long timeCreated, long expiry) throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + Config.getConfig(start).getDashboardSessionsTable() + "(app_id, user_id, session_id, time_created, expiry)" + " VALUES(?, ?, ?, ?, ?)"; @@ -166,7 +168,8 @@ public static void createDashboardSession(Start start, AppIdentifier appIdentifi }); } - public static DashboardSessionInfo getSessionInfoWithSessionId(Start start, AppIdentifier appIdentifier, String sessionId) + public static DashboardSessionInfo getSessionInfoWithSessionId(Start start, AppIdentifier appIdentifier, + String sessionId) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getDashboardSessionsTable() + " WHERE app_id = ? AND session_id = ?"; @@ -181,7 +184,8 @@ public static DashboardSessionInfo getSessionInfoWithSessionId(Start start, AppI }); } - public static DashboardSessionInfo[] getAllSessionsForUserId(Start start, AppIdentifier appIdentifier, String userId) + public static DashboardSessionInfo[] getAllSessionsForUserId(Start start, AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getDashboardSessionsTable() + " WHERE app_id = ? AND user_id = ?"; @@ -215,7 +219,8 @@ public static DashboardUser getDashboardUserByEmail(Start start, AppIdentifier a }); } - public static boolean deleteDashboardUserSessionWithSessionId(Start start, AppIdentifier appIdentifier, String sessionId) + public static boolean deleteDashboardUserSessionWithSessionId(Start start, AppIdentifier appIdentifier, + String sessionId) throws SQLException, StorageQueryException { String QUERY = "DELETE FROM " + Config.getConfig(start).getDashboardSessionsTable() + " WHERE app_id = ? AND session_id = ?"; diff --git a/src/main/java/io/supertokens/storage/mysql/queries/EmailPasswordQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/EmailPasswordQueries.java index 3fc0db3..1380efd 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/EmailPasswordQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/EmailPasswordQueries.java @@ -51,7 +51,8 @@ static String getQueryToCreateUsersTable(Start start) { + "time_joined BIGINT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, user_id)," + "FOREIGN KEY(app_id, user_id)" - + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + " (app_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + + " (app_id, user_id) ON DELETE CASCADE" + ");"; } @@ -66,7 +67,8 @@ static String getQueryToCreateEmailPasswordUserToTenantTable(Start start) { + "CONSTRAINT email UNIQUE (app_id, tenant_id, email)," + "PRIMARY KEY (app_id, tenant_id, user_id)," + "FOREIGN KEY (app_id, tenant_id, user_id)" - + " REFERENCES " + Config.getConfig(start).getUsersTable() + "(app_id, tenant_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getUsersTable() + + "(app_id, tenant_id, user_id) ON DELETE CASCADE" + ");"; // @formatter:on } @@ -151,7 +153,7 @@ public static PasswordResetTokenInfo[] getAllPasswordResetTokenInfoForUser(Start throws StorageQueryException, SQLException { String QUERY = "SELECT user_id, token, token_expiry, email FROM " + getConfig(start).getPasswordResetTokensTable() - + " WHERE app_id = ? AND user_id = ?"; + + " WHERE app_id = ? AND user_id = ?"; return execute(start, QUERY, pst -> { pst.setString(1, appIdentifier.getAppId()); @@ -176,7 +178,7 @@ public static PasswordResetTokenInfo[] getAllPasswordResetTokenInfoForUser_Trans String QUERY = "SELECT user_id, token, token_expiry, email FROM " + getConfig(start).getPasswordResetTokensTable() - + " WHERE app_id = ? AND user_id = ? FOR UPDATE"; + + " WHERE app_id = ? AND user_id = ? FOR UPDATE"; return execute(con, QUERY, pst -> { pst.setString(1, appIdentifier.getAppId()); @@ -199,7 +201,7 @@ public static PasswordResetTokenInfo getPasswordResetTokenInfo(Start start, AppI throws SQLException, StorageQueryException { String QUERY = "SELECT user_id, token, token_expiry, email FROM " + getConfig(start).getPasswordResetTokensTable() - + " WHERE app_id = ? AND token = ?"; + + " WHERE app_id = ? AND token = ?"; return execute(start, QUERY, pst -> { pst.setString(1, appIdentifier.getAppId()); pst.setString(2, token); @@ -257,7 +259,9 @@ public static AuthRecipeUserInfo signUp(Start start, TenantIdentifier tenantIden { // all_auth_recipe_users String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, " + + "primary_or_recipe_user_time_joined)" + " VALUES(?, ?, ?, ?, ?, ?, ?)"; update(sqlCon, QUERY, pst -> { pst.setString(1, tenantIdentifier.getAppId()); @@ -313,10 +317,10 @@ public static void deleteUser_Transaction(Connection sqlCon, Start start, AppIde String QUERY = "DELETE FROM " + getConfig(start).getAppIdToUserIdTable() + " WHERE app_id = ? AND user_id = ?"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, appIdentifier.getAppId()); - pst.setString(2, userId); - }); + update(sqlCon, QUERY, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setString(2, userId); + }); } else { { String QUERY = "DELETE FROM " + getConfig(start).getUsersTable() @@ -347,8 +351,10 @@ public static void deleteUser_Transaction(Connection sqlCon, Start start, AppIde } } - private static UserInfoPartial getUserInfoUsingId_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, - String id) throws SQLException, StorageQueryException { + private static UserInfoPartial getUserInfoUsingId_Transaction(Start start, Connection sqlCon, + AppIdentifier appIdentifier, + String id) + throws SQLException, StorageQueryException { // we don't need a FOR UPDATE here because this is already part of a transaction, and locked on // app_id_to_user_id table String QUERY = "SELECT user_id, email, password_hash, time_joined FROM " @@ -398,7 +404,7 @@ public static List getUsersInfoUsingIdList(Start start, Set } public static List getUsersInfoUsingIdList_Transaction(Start start, Connection con, Set ids, - AppIdentifier appIdentifier) + AppIdentifier appIdentifier) throws SQLException, StorageQueryException { if (ids.size() > 0) { // No need to filter based on tenantId because the id list is already filtered for a tenant @@ -428,6 +434,7 @@ public static List getUsersInfoUsingIdList_Transaction(Start start, } return Collections.emptyList(); } + public static String lockEmail_Transaction(Start start, Connection con, AppIdentifier appIdentifier, String email) @@ -447,7 +454,7 @@ public static String lockEmail_Transaction(Start start, Connection con, } public static String getPrimaryUserIdUsingEmail(Start start, TenantIdentifier tenantIdentifier, - String email) + String email) throws StorageQueryException, SQLException { String QUERY = "SELECT DISTINCT all_users.primary_or_recipe_user_id AS user_id " + "FROM " + getConfig(start).getEmailPasswordUserToTenantTable() + " AS ep" + @@ -467,8 +474,9 @@ public static String getPrimaryUserIdUsingEmail(Start start, TenantIdentifier te }); } - public static List getPrimaryUserIdsUsingEmail_Transaction(Start start, Connection con, AppIdentifier appIdentifier, - String email) + public static List getPrimaryUserIdsUsingEmail_Transaction(Start start, Connection con, + AppIdentifier appIdentifier, + String email) throws StorageQueryException, SQLException { String QUERY = "SELECT DISTINCT all_users.primary_or_recipe_user_id AS user_id " + "FROM " + getConfig(start).getEmailPasswordUsersTable() + " AS ep" + @@ -498,12 +506,15 @@ public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlC throw new UnknownUserIdException(); } - GeneralQueries.AccountLinkingInfo accountLinkingInfo = GeneralQueries.getAccountLinkingInfo_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userId); + GeneralQueries.AccountLinkingInfo accountLinkingInfo = GeneralQueries.getAccountLinkingInfo_Transaction(start, + sqlCon, tenantIdentifier.toAppIdentifier(), userId); { // all_auth_recipe_users // ON CONFLICT DO NOTHING String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, is_linked_or_is_a_primary_user, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, is_linked_or_is_a_primary_user, " + + "recipe_id, time_joined, primary_or_recipe_user_time_joined)" + " SELECT ?, ?, ?, ?, ?, ?, ?, ? WHERE NOT EXISTS (" + " SELECT app_id, tenant_id, user_id FROM " + getConfig(start).getUsersTable() + " WHERE app_id = ? AND tenant_id = ? AND user_id = ?" @@ -524,7 +535,8 @@ public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlC pst.setString(11, userId); }); - GeneralQueries.updateTimeJoinedForPrimaryUser_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), finalAccountLinkingInfo.primaryUserId); + GeneralQueries.updateTimeJoinedForPrimaryUser_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), + finalAccountLinkingInfo.primaryUserId); } { // emailpassword_user_to_tenant diff --git a/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java index 5941063..b612b00 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java @@ -46,7 +46,7 @@ static String getQueryToCreateEmailVerificationTable(Start start) { + "email VARCHAR(256) NOT NULL," + "PRIMARY KEY (app_id, user_id, email)," + "FOREIGN KEY(app_id)" - + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" + ");"; } @@ -60,7 +60,7 @@ static String getQueryToCreateEmailVerificationTokensTable(Start start) { + "token_expiry BIGINT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, tenant_id, user_id, email, token)," + "FOREIGN KEY(app_id, tenant_id)" - + " REFERENCES " + Config.getConfig(start).getTenantsTable() + " (app_id, tenant_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getTenantsTable() + " (app_id, tenant_id) ON DELETE CASCADE" + ")"; } @@ -221,7 +221,8 @@ public static boolean isEmailVerified(Start start, AppIdentifier appIdentifier, }, result -> result.next()); } - public static void updateIsEmailVerifiedToExternalUserId(Start start, AppIdentifier appIdentifier, String supertokensUserId, String externalUserId) + public static void updateIsEmailVerifiedToExternalUserId(Start start, AppIdentifier appIdentifier, + String supertokensUserId, String externalUserId) throws StorageQueryException { try { start.startTransaction((TransactionConnection con) -> { @@ -283,8 +284,10 @@ public static List isEmailVerified_transaction(Start start, Connection s // We have external user id stored in the email verification table, so we need to fetch the mapped userids for // calculating the verified emails - HashMap supertokensUserIdToExternalUserIdMap = UserIdMappingQueries.getUserIdMappingWithUserIds_Transaction(start, - sqlCon, appIdentifier, supertokensUserIds); + HashMap supertokensUserIdToExternalUserIdMap = + UserIdMappingQueries.getUserIdMappingWithUserIds_Transaction( + start, + sqlCon, appIdentifier, supertokensUserIds); HashMap externalUserIdToSupertokensUserIdMap = new HashMap<>(); List supertokensOrExternalUserIdsToQuery = new ArrayList<>(); @@ -311,7 +314,8 @@ public static List isEmailVerified_transaction(Start start, Connection s } String QUERY = "SELECT * FROM " + getConfig(start).getEmailVerificationTable() - + " WHERE app_id = ? AND user_id IN (" + Utils.generateCommaSeperatedQuestionMarks(supertokensOrExternalUserIdsToQuery.size()) + + + " WHERE app_id = ? AND user_id IN (" + + Utils.generateCommaSeperatedQuestionMarks(supertokensOrExternalUserIdsToQuery.size()) + ") AND email IN (" + Utils.generateCommaSeperatedQuestionMarks(emails.size()) + ")"; return execute(sqlCon, QUERY, pst -> { @@ -337,7 +341,7 @@ public static List isEmailVerified_transaction(Start start, Connection s } public static List isEmailVerified(Start start, AppIdentifier appIdentifier, - List userIdAndEmail) + List userIdAndEmail) throws SQLException, StorageQueryException { if (userIdAndEmail.isEmpty()) { return new ArrayList<>(); @@ -351,7 +355,8 @@ public static List isEmailVerified(Start start, AppIdentifier appIdentif } // We have external user id stored in the email verification table, so we need to fetch the mapped userids for // calculating the verified emails - HashMap supertokensUserIdToExternalUserIdMap = UserIdMappingQueries.getUserIdMappingWithUserIds(start, + HashMap supertokensUserIdToExternalUserIdMap = UserIdMappingQueries.getUserIdMappingWithUserIds( + start, appIdentifier, supertokensUserIds); HashMap externalUserIdToSupertokensUserIdMap = new HashMap<>(); List supertokensOrExternalUserIdsToQuery = new ArrayList<>(); @@ -377,7 +382,8 @@ public static List isEmailVerified(Start start, AppIdentifier appIdentif supertokensOrExternalUserIdToEmailMap.put(supertokensOrExternalUserId, ue.email); } String QUERY = "SELECT * FROM " + getConfig(start).getEmailVerificationTable() - + " WHERE app_id = ? AND user_id IN (" + Utils.generateCommaSeperatedQuestionMarks(supertokensOrExternalUserIdsToQuery.size()) + + + " WHERE app_id = ? AND user_id IN (" + + Utils.generateCommaSeperatedQuestionMarks(supertokensOrExternalUserIdsToQuery.size()) + ") AND email IN (" + Utils.generateCommaSeperatedQuestionMarks(emails.size()) + ")"; return execute(start, QUERY, pst -> { pst.setString(1, appIdentifier.getAppId()); diff --git a/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java index 8df206c..94af568 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java @@ -47,15 +47,9 @@ import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; import static io.supertokens.storage.mysql.queries.EmailPasswordQueries.getQueryToCreatePasswordResetTokenExpiryIndex; import static io.supertokens.storage.mysql.queries.EmailPasswordQueries.getQueryToCreatePasswordResetTokensTable; -import static io.supertokens.storage.mysql.queries.EmailVerificationQueries.getQueryToCreateEmailVerificationTable; -import static io.supertokens.storage.mysql.queries.EmailVerificationQueries.getQueryToCreateEmailVerificationTokenExpiryIndex; -import static io.supertokens.storage.mysql.queries.EmailVerificationQueries.getQueryToCreateEmailVerificationTokensTable; +import static io.supertokens.storage.mysql.queries.EmailVerificationQueries.*; import static io.supertokens.storage.mysql.queries.JWTSigningQueries.getQueryToCreateJWTSigningTable; -import static io.supertokens.storage.mysql.queries.PasswordlessQueries.getQueryToCreateCodeCreatedAtIndex; -import static io.supertokens.storage.mysql.queries.PasswordlessQueries.getQueryToCreateCodesTable; -import static io.supertokens.storage.mysql.queries.PasswordlessQueries.getQueryToCreateDeviceEmailIndex; -import static io.supertokens.storage.mysql.queries.PasswordlessQueries.getQueryToCreateDevicePhoneNumberIndex; -import static io.supertokens.storage.mysql.queries.PasswordlessQueries.getQueryToCreateDevicesTable; +import static io.supertokens.storage.mysql.queries.PasswordlessQueries.*; import static io.supertokens.storage.mysql.queries.SessionQueries.*; import static io.supertokens.storage.mysql.queries.UserMetadataQueries.getQueryToCreateUserMetadataTable; @@ -90,9 +84,11 @@ static String getQueryToCreateUsersTable(Start start) { + "FOREIGN KEY(app_id, tenant_id)" + " REFERENCES " + Config.getConfig(start).getTenantsTable() + " (app_id, tenant_id) ON DELETE CASCADE," + "FOREIGN KEY(app_id, user_id)" - + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + " (app_id, user_id) ON DELETE CASCADE," + + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + + " (app_id, user_id) ON DELETE CASCADE," + "FOREIGN KEY(app_id, primary_or_recipe_user_id)" - + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + " (app_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + + " (app_id, user_id) ON DELETE CASCADE" + ");"; // @formatter:on } @@ -108,7 +104,9 @@ static String getQueryToCreateUserPaginationIndex1(Start start) { static String getQueryToCreateUserPaginationIndex3(Start start) { return "CREATE INDEX all_auth_recipe_users_pagination_index3 ON " + Config.getConfig(start).getUsersTable() - + "(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);"; + + + "(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id " + + "DESC);"; } static String getQueryToCreatePrimaryUserId(Start start) { @@ -184,7 +182,8 @@ private static String getQueryToCreateAppIdToUserIdTable(Start start) { + "FOREIGN KEY (app_id)" + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE," + "FOREIGN KEY(app_id, primary_or_recipe_user_id)" - + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + " (app_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + + " (app_id, user_id) ON DELETE CASCADE" + ");"; // @formatter:on } @@ -505,7 +504,7 @@ public static long getUsersCount(Start start, AppIdentifier appIdentifier, RECIP throws SQLException, StorageQueryException { StringBuilder QUERY = new StringBuilder( "SELECT COUNT(DISTINCT primary_or_recipe_user_id) AS total FROM " + - Config.getConfig(start).getUsersTable()); + Config.getConfig(start).getUsersTable()); QUERY.append(" WHERE app_id = ?"); if (includeRecipeIds != null && includeRecipeIds.length > 0) { QUERY.append(" AND recipe_id IN ("); @@ -538,7 +537,8 @@ public static long getUsersCount(Start start, AppIdentifier appIdentifier, RECIP public static long getUsersCount(Start start, TenantIdentifier tenantIdentifier, RECIPE_ID[] includeRecipeIds) throws SQLException, StorageQueryException { StringBuilder QUERY = new StringBuilder( - "SELECT COUNT(DISTINCT primary_or_recipe_user_id) AS total FROM " + Config.getConfig(start).getUsersTable()); + "SELECT COUNT(DISTINCT primary_or_recipe_user_id) AS total FROM " + + Config.getConfig(start).getUsersTable()); QUERY.append(" WHERE app_id = ? AND tenant_id = ?"); if (includeRecipeIds != null && includeRecipeIds.length > 0) { QUERY.append(" AND recipe_id IN ("); @@ -581,7 +581,8 @@ public static boolean doesUserIdExist(Start start, AppIdentifier appIdentifier, }, ResultSet::next); } - public static boolean doesUserIdExist_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String userId) + public static boolean doesUserIdExist_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { // We query both tables cause there is a case where a primary user ID exists, but its associated // recipe user ID has been deleted AND there are other recipe user IDs linked to this primary user ID already. @@ -629,12 +630,15 @@ public static AuthRecipeUserInfo[] getUsers(Start start, TenantIdentifier tenant { // check if we should search through the emailpassword table if (dashboardSearchTags.shouldEmailPasswordTableBeSearched()) { - String QUERY = "SELECT allAuthUsersTable.*" + " FROM " + Config.getConfig(start).getUsersTable() - + " AS allAuthUsersTable" + - " JOIN " + Config.getConfig(start).getEmailPasswordUserToTenantTable() - + " AS emailpasswordTable ON allAuthUsersTable.app_id = emailpasswordTable.app_id AND " - + "allAuthUsersTable.tenant_id = emailpasswordTable.tenant_id AND " - + "allAuthUsersTable.user_id = emailpasswordTable.user_id"; + String QUERY = + "SELECT allAuthUsersTable.*" + " FROM " + Config.getConfig(start).getUsersTable() + + " AS allAuthUsersTable" + + " JOIN " + Config.getConfig(start).getEmailPasswordUserToTenantTable() + + + " AS emailpasswordTable ON allAuthUsersTable.app_id = emailpasswordTable" + + ".app_id AND " + + "allAuthUsersTable.tenant_id = emailpasswordTable.tenant_id AND " + + "allAuthUsersTable.user_id = emailpasswordTable.user_id"; // attach email tags to queries QUERY = QUERY + @@ -658,15 +662,20 @@ public static AuthRecipeUserInfo[] getUsers(Start start, TenantIdentifier tenant { // check if we should search through the thirdparty table if (dashboardSearchTags.shouldThirdPartyTableBeSearched()) { - String QUERY = "SELECT allAuthUsersTable.*" + " FROM " + Config.getConfig(start).getUsersTable() - + " AS allAuthUsersTable" - + " JOIN " + Config.getConfig(start).getThirdPartyUserToTenantTable() - + " AS thirdPartyToTenantTable ON allAuthUsersTable.app_id = thirdPartyToTenantTable.app_id AND" - + " allAuthUsersTable.tenant_id = thirdPartyToTenantTable.tenant_id AND" - + " allAuthUsersTable.user_id = thirdPartyToTenantTable.user_id" - + " JOIN " + Config.getConfig(start).getThirdPartyUsersTable() - + " AS thirdPartyTable ON thirdPartyToTenantTable.app_id = thirdPartyTable.app_id AND" - + " thirdPartyToTenantTable.user_id = thirdPartyTable.user_id"; + String QUERY = + "SELECT allAuthUsersTable.*" + " FROM " + Config.getConfig(start).getUsersTable() + + " AS allAuthUsersTable" + + " JOIN " + Config.getConfig(start).getThirdPartyUserToTenantTable() + + + " AS thirdPartyToTenantTable ON allAuthUsersTable.app_id = " + + "thirdPartyToTenantTable.app_id AND" + + " allAuthUsersTable.tenant_id = thirdPartyToTenantTable.tenant_id AND" + + " allAuthUsersTable.user_id = thirdPartyToTenantTable.user_id" + + " JOIN " + Config.getConfig(start).getThirdPartyUsersTable() + + + " AS thirdPartyTable ON thirdPartyToTenantTable.app_id = thirdPartyTable" + + ".app_id AND" + + " thirdPartyToTenantTable.user_id = thirdPartyTable.user_id"; // check if email tag is present if (dashboardSearchTags.emails != null) { @@ -727,12 +736,15 @@ public static AuthRecipeUserInfo[] getUsers(Start start, TenantIdentifier tenant { // check if we should search through the passwordless table if (dashboardSearchTags.shouldPasswordlessTableBeSearched()) { - String QUERY = "SELECT allAuthUsersTable.*" + " FROM " + Config.getConfig(start).getUsersTable() - + " AS allAuthUsersTable" + - " JOIN " + Config.getConfig(start).getPasswordlessUserToTenantTable() - + " AS passwordlessTable ON allAuthUsersTable.app_id = passwordlessTable.app_id AND" - + " allAuthUsersTable.tenant_id = passwordlessTable.tenant_id AND" - + " allAuthUsersTable.user_id = passwordlessTable.user_id"; + String QUERY = + "SELECT allAuthUsersTable.*" + " FROM " + Config.getConfig(start).getUsersTable() + + " AS allAuthUsersTable" + + " JOIN " + Config.getConfig(start).getPasswordlessUserToTenantTable() + + + " AS passwordlessTable ON allAuthUsersTable.app_id = passwordlessTable.app_id" + + " AND" + + " allAuthUsersTable.tenant_id = passwordlessTable.tenant_id AND" + + " allAuthUsersTable.user_id = passwordlessTable.user_id"; // check if email tag is present if (dashboardSearchTags.emails != null) { @@ -791,8 +803,11 @@ public static AuthRecipeUserInfo[] getUsers(Start start, TenantIdentifier tenant usersFromQuery = new ArrayList<>(); } else { - String finalQuery = "SELECT DISTINCT primary_or_recipe_user_id, primary_or_recipe_user_time_joined FROM ( " + USER_SEARCH_TAG_CONDITION.toString() + " )" - + " AS finalResultTable ORDER BY primary_or_recipe_user_time_joined " + timeJoinedOrder + ", primary_or_recipe_user_id " + timeJoinedOrder; + String finalQuery = + "SELECT DISTINCT primary_or_recipe_user_id, primary_or_recipe_user_time_joined FROM ( " + + USER_SEARCH_TAG_CONDITION.toString() + " )" + + " AS finalResultTable ORDER BY primary_or_recipe_user_time_joined " + + timeJoinedOrder + ", primary_or_recipe_user_id " + timeJoinedOrder; usersFromQuery = execute(start, finalQuery, pst -> { for (int i = 1; i <= queryList.size(); i++) { pst.setString(i, queryList.get(i - 1)); @@ -1052,7 +1067,8 @@ public static AuthRecipeUserInfo[] listPrimaryUsersByThirdPartyInfo_Transaction( // now that we have locks on all the relevant tables, we can read from them safely List userIds = ThirdPartyQueries.listUserIdsByThirdPartyInfo_Transaction(start, sqlCon, appIdentifier, thirdPartyId, thirdPartyUserId); - List result = getPrimaryUserInfoForUserIds_Transaction(start, sqlCon, appIdentifier, userIds); + List result = getPrimaryUserInfoForUserIds_Transaction(start, sqlCon, appIdentifier, + userIds); // this is going to order them based on oldest that joined to newest that joined. result.sort(Comparator.comparingLong(o -> o.timeJoined)); @@ -1150,9 +1166,9 @@ public static AuthRecipeUserInfo[] listPrimaryUsersByPhoneNumber(Start start, } public static AuthRecipeUserInfo getPrimaryUserByThirdPartyInfo(Start start, - TenantIdentifier tenantIdentifier, - String thirdPartyId, - String thirdPartyUserId) + TenantIdentifier tenantIdentifier, + String thirdPartyId, + String thirdPartyUserId) throws StorageQueryException, SQLException { String userId = ThirdPartyQueries.getUserIdByThirdPartyInfo(start, tenantIdentifier, thirdPartyId, thirdPartyUserId); @@ -1186,7 +1202,7 @@ public static AuthRecipeUserInfo getPrimaryUserInfoForUserId(Start start, AppIde } public static AuthRecipeUserInfo getPrimaryUserInfoForUserId_Transaction(Start start, Connection con, - AppIdentifier appIdentifier, String id) + AppIdentifier appIdentifier, String id) throws SQLException, StorageQueryException { List ids = new ArrayList<>(); ids.add(id); @@ -1209,14 +1225,18 @@ private static List getPrimaryUserInfoForUserIds(Start start // which is linked to a primary user ID in which case it won't be in the primary_or_recipe_user_id column, // or the input may have a primary user ID whose recipe user ID was removed, so it won't be in the user_id // column - String QUERY = "SELECT au.user_id, au.primary_or_recipe_user_id, au.is_linked_or_is_a_primary_user, au.recipe_id, aaru.tenant_id, aaru.time_joined FROM " + Config.getConfig(start).getAppIdToUserIdTable() + " as au " + - "LEFT JOIN " + Config.getConfig(start).getUsersTable() + " as aaru ON au.app_id = aaru.app_id AND au.user_id = aaru.user_id" + - " WHERE au.primary_or_recipe_user_id IN (SELECT primary_or_recipe_user_id FROM " + - Config.getConfig(start).getAppIdToUserIdTable() + " WHERE (user_id IN (" - + Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + - ") OR primary_or_recipe_user_id IN (" + - Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + - ")) AND app_id = ?) AND au.app_id = ?"; + String QUERY = + "SELECT au.user_id, au.primary_or_recipe_user_id, au.is_linked_or_is_a_primary_user, au.recipe_id, " + + "aaru.tenant_id, aaru.time_joined FROM " + + Config.getConfig(start).getAppIdToUserIdTable() + " as au " + + "LEFT JOIN " + Config.getConfig(start).getUsersTable() + + " as aaru ON au.app_id = aaru.app_id AND au.user_id = aaru.user_id" + + " WHERE au.primary_or_recipe_user_id IN (SELECT primary_or_recipe_user_id FROM " + + Config.getConfig(start).getAppIdToUserIdTable() + " WHERE (user_id IN (" + + Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + + ") OR primary_or_recipe_user_id IN (" + + Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + + ")) AND app_id = ?) AND au.app_id = ?"; List allAuthUsersResult = execute(start, QUERY, pst -> { // IN user_id @@ -1290,8 +1310,8 @@ private static List getPrimaryUserInfoForUserIds(Start start } private static List getPrimaryUserInfoForUserIds_Transaction(Start start, Connection sqlCon, - AppIdentifier appIdentifier, - List userIds) + AppIdentifier appIdentifier, + List userIds) throws StorageQueryException, SQLException { if (userIds.size() == 0) { return new ArrayList<>(); @@ -1301,14 +1321,18 @@ private static List getPrimaryUserInfoForUserIds_Transaction // which is linked to a primary user ID in which case it won't be in the primary_or_recipe_user_id column, // or the input may have a primary user ID whose recipe user ID was removed, so it won't be in the user_id // column - String QUERY = "SELECT au.user_id, au.primary_or_recipe_user_id, au.is_linked_or_is_a_primary_user, au.recipe_id, aaru.tenant_id, aaru.time_joined FROM " + Config.getConfig(start).getAppIdToUserIdTable() + " as au" + - " LEFT JOIN " + Config.getConfig(start).getUsersTable() + " as aaru ON au.app_id = aaru.app_id AND au.user_id = aaru.user_id" + - " WHERE au.primary_or_recipe_user_id IN (SELECT primary_or_recipe_user_id FROM " + - Config.getConfig(start).getAppIdToUserIdTable() + " WHERE (user_id IN (" - + Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + - ") OR primary_or_recipe_user_id IN (" + - Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + - ")) AND app_id = ?) AND au.app_id = ?"; + String QUERY = + "SELECT au.user_id, au.primary_or_recipe_user_id, au.is_linked_or_is_a_primary_user, au.recipe_id, " + + "aaru.tenant_id, aaru.time_joined FROM " + + Config.getConfig(start).getAppIdToUserIdTable() + " as au" + + " LEFT JOIN " + Config.getConfig(start).getUsersTable() + + " as aaru ON au.app_id = aaru.app_id AND au.user_id = aaru.user_id" + + " WHERE au.primary_or_recipe_user_id IN (SELECT primary_or_recipe_user_id FROM " + + Config.getConfig(start).getAppIdToUserIdTable() + " WHERE (user_id IN (" + + Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + + ") OR primary_or_recipe_user_id IN (" + + Utils.generateCommaSeperatedQuestionMarks(userIds.size()) + + ")) AND app_id = ?) AND au.app_id = ?"; List allAuthUsersResult = execute(sqlCon, QUERY, pst -> { // IN user_id @@ -1345,10 +1369,13 @@ private static List getPrimaryUserInfoForUserIds_Transaction List loginMethods = new ArrayList<>(); loginMethods.addAll( - EmailPasswordQueries.getUsersInfoUsingIdList_Transaction(start, sqlCon, recipeUserIdsToFetch, appIdentifier)); - loginMethods.addAll(ThirdPartyQueries.getUsersInfoUsingIdList_Transaction(start, sqlCon, recipeUserIdsToFetch, appIdentifier)); + EmailPasswordQueries.getUsersInfoUsingIdList_Transaction(start, sqlCon, recipeUserIdsToFetch, + appIdentifier)); + loginMethods.addAll(ThirdPartyQueries.getUsersInfoUsingIdList_Transaction(start, sqlCon, recipeUserIdsToFetch, + appIdentifier)); loginMethods.addAll( - PasswordlessQueries.getUsersInfoUsingIdList_Transaction(start, sqlCon, recipeUserIdsToFetch, appIdentifier)); + PasswordlessQueries.getUsersInfoUsingIdList_Transaction(start, sqlCon, recipeUserIdsToFetch, + appIdentifier)); Map recipeUserIdToLoginMethodMap = new HashMap<>(); for (LoginMethod loginMethod : loginMethods) { @@ -1526,7 +1553,7 @@ public static String[] getAllTablesInTheDatabase(Start start) throws SQLExceptio List tableNames = new ArrayList<>(); try (Connection con = ConnectionPool.getConnection(start)) { DatabaseMetaData metadata = con.getMetaData(); - ResultSet resultSet = metadata.getTables(null, null, null, new String[] { "TABLE" }); + ResultSet resultSet = metadata.getTables(null, null, null, new String[]{"TABLE"}); while (resultSet.next()) { String tableName = resultSet.getString("TABLE_NAME"); tableNames.add(tableName); @@ -1538,7 +1565,7 @@ public static String[] getAllTablesInTheDatabase(Start start) throws SQLExceptio @TestOnly public static String[] getAllTablesInTheDatabaseThatHasDataForAppId(Start start, String appId) - throws StorageQueryException, SQLException { + throws StorageQueryException, SQLException { if (!Start.isTesting) { throw new UnsupportedOperationException(); } @@ -1616,7 +1643,8 @@ public static boolean checkIfUsesAccountLinking(Start start, AppIdentifier appId }); } - public static AccountLinkingInfo getAccountLinkingInfo_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String userId) + public static AccountLinkingInfo getAccountLinkingInfo_Transaction(Start start, Connection sqlCon, + AppIdentifier appIdentifier, String userId) throws SQLException, StorageQueryException { GeneralQueries.AccountLinkingInfo accountLinkingInfo = new GeneralQueries.AccountLinkingInfo(userId, false); { @@ -1638,9 +1666,11 @@ public static AccountLinkingInfo getAccountLinkingInfo_Transaction(Start start, return accountLinkingInfo; } - public static void updateTimeJoinedForPrimaryUser_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String primaryUserId) + public static void updateTimeJoinedForPrimaryUser_Transaction(Start start, Connection sqlCon, + AppIdentifier appIdentifier, String primaryUserId) throws SQLException, StorageQueryException { - // Query like postgres causes issue in mysql, so we have to fetch min time joined first on a separate query and then update it + // Query like postgres causes issue in mysql, so we have to fetch min time joined first on a separate query + // and then update it String QUERY1 = "SELECT MIN(time_joined) AS min_time_joined FROM " + Config.getConfig(start).getUsersTable() + " WHERE app_id = ? AND primary_or_recipe_user_id = ?"; long minTimeJoined = execute(sqlCon, QUERY1, pst -> { diff --git a/src/main/java/io/supertokens/storage/mysql/queries/JWTSigningQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/JWTSigningQueries.java index 3e8537c..a3b820d 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/JWTSigningQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/JWTSigningQueries.java @@ -45,13 +45,13 @@ static String getQueryToCreateJWTSigningTable(Start start) { */ return "CREATE TABLE IF NOT EXISTS " + Config.getConfig(start).getJWTSigningKeysTable() + " (" + "app_id VARCHAR(64) DEFAULT 'public'," - + "key_id VARCHAR(255) NOT NULL," - + "key_string TEXT NOT NULL," - + "algorithm VARCHAR(10) NOT NULL," + + "key_id VARCHAR(255) NOT NULL," + + "key_string TEXT NOT NULL," + + "algorithm VARCHAR(10) NOT NULL," + "created_at BIGINT UNSIGNED," + "PRIMARY KEY(app_id, key_id)," + "FOREIGN KEY(app_id)" - + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" + ");"; } @@ -61,7 +61,7 @@ public static List getJWTSigningKeys_Transaction(Start start, String QUERY = "SELECT * FROM " + Config.getConfig(start).getJWTSigningKeysTable() + " WHERE app_id = ? ORDER BY created_at DESC FOR UPDATE"; - return execute(con, QUERY, pst -> pst.setString(1, appIdentifier.getAppId()),result -> { + return execute(con, QUERY, pst -> pst.setString(1, appIdentifier.getAppId()), result -> { List keys = new ArrayList<>(); while (result.next()) { diff --git a/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java index 9761ad2..25d8c86 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java @@ -88,7 +88,8 @@ static String getQueryToCreateTenantThirdPartyProvidersTable(Start start) { + "user_info_map_from_user_info_endpoint_email_verified VARCHAR(64)," + "PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id)," + "FOREIGN KEY(connection_uri_domain, app_id, tenant_id)" - + " REFERENCES " + Config.getConfig(start).getTenantConfigsTable() + " (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getTenantConfigsTable() + + " (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE" + ");"; // @formatter:on } @@ -108,7 +109,8 @@ static String getQueryToCreateTenantThirdPartyProviderClientsTable(Start start) + "additional_config TEXT," + " PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id, client_type)," + "FOREIGN KEY(connection_uri_domain, app_id, tenant_id, third_party_id)" - + " REFERENCES " + Config.getConfig(start).getTenantThirdPartyProvidersTable() + " (connection_uri_domain, app_id, tenant_id, third_party_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getTenantThirdPartyProvidersTable() + + " (connection_uri_domain, app_id, tenant_id, third_party_id) ON DELETE CASCADE" + ");"; } @@ -122,7 +124,8 @@ public static String getQueryToCreateFirstFactorsTable(Start start) { + "factor_id VARCHAR(128)," + "PRIMARY KEY (connection_uri_domain, app_id, tenant_id, factor_id)," + "FOREIGN KEY (connection_uri_domain, app_id, tenant_id)" - + " REFERENCES " + Config.getConfig(start).getTenantConfigsTable() + " (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getTenantConfigsTable() + + " (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE" + ");"; // @formatter:on } @@ -160,7 +163,8 @@ private static void executeCreateTenantQueries(Start start, Connection sqlCon, T try { ThirdPartyProviderSQLHelper.create(start, sqlCon, tenantConfig, provider); } catch (SQLIntegrityConstraintViolationException e) { - if (start.isPrimaryKeyError(e.getMessage(), Config.getConfig(start).getTenantThirdPartyProvidersTable())) { + if (start.isPrimaryKeyError(e.getMessage(), + Config.getConfig(start).getTenantThirdPartyProvidersTable())) { throw new StorageTransactionLogicException(new DuplicateThirdPartyIdException()); } else { throw e; @@ -171,7 +175,8 @@ private static void executeCreateTenantQueries(Start start, Connection sqlCon, T try { ThirdPartyProviderClientSQLHelper.create(start, sqlCon, tenantConfig, provider, providerClient); } catch (SQLIntegrityConstraintViolationException e) { - if (start.isPrimaryKeyError(e.getMessage(), Config.getConfig(start).getTenantThirdPartyProviderClientsTable())) { + if (start.isPrimaryKeyError(e.getMessage(), + Config.getConfig(start).getTenantThirdPartyProviderClientsTable())) { throw new StorageTransactionLogicException(new DuplicateClientTypeException()); } else { throw e; @@ -182,10 +187,12 @@ private static void executeCreateTenantQueries(Start start, Connection sqlCon, T } MfaSqlHelper.createFirstFactors(start, sqlCon, tenantConfig.tenantIdentifier, tenantConfig.firstFactors); - MfaSqlHelper.createRequiredSecondaryFactors(start, sqlCon, tenantConfig.tenantIdentifier, tenantConfig.requiredSecondaryFactors); + MfaSqlHelper.createRequiredSecondaryFactors(start, sqlCon, tenantConfig.tenantIdentifier, + tenantConfig.requiredSecondaryFactors); } - public static void createTenantConfig(Start start, TenantConfig tenantConfig) throws StorageQueryException, StorageTransactionLogicException { + public static void createTenantConfig(Start start, TenantConfig tenantConfig) + throws StorageQueryException, StorageTransactionLogicException { start.startTransaction(con -> { Connection sqlCon = (Connection) con.getConnection(); { @@ -201,7 +208,8 @@ public static void createTenantConfig(Start start, TenantConfig tenantConfig) th }); } - public static boolean deleteTenantConfig(Start start, TenantIdentifier tenantIdentifier) throws StorageQueryException { + public static boolean deleteTenantConfig(Start start, TenantIdentifier tenantIdentifier) + throws StorageQueryException { try { String QUERY = "DELETE FROM " + getConfig(start).getTenantConfigsTable() + " WHERE connection_uri_domain = ? AND app_id = ? AND tenant_id = ?"; @@ -219,7 +227,8 @@ public static boolean deleteTenantConfig(Start start, TenantIdentifier tenantIde } } - public static void overwriteTenantConfig(Start start, TenantConfig tenantConfig) throws StorageQueryException, StorageTransactionLogicException { + public static void overwriteTenantConfig(Start start, TenantConfig tenantConfig) + throws StorageQueryException, StorageTransactionLogicException { start.startTransaction(con -> { Connection sqlCon = (Connection) con.getConnection(); { @@ -233,7 +242,8 @@ public static void overwriteTenantConfig(Start start, TenantConfig tenantConfig) pst.setString(3, tenantConfig.tenantIdentifier.getTenantId()); }); if (rowsAffected == 0) { - throw new StorageTransactionLogicException(new TenantOrAppNotFoundException(tenantConfig.tenantIdentifier)); + throw new StorageTransactionLogicException( + new TenantOrAppNotFoundException(tenantConfig.tenantIdentifier)); } } @@ -256,16 +266,21 @@ public static TenantConfig[] getAllTenants(Start start) throws StorageQueryExcep try { // Map TenantIdentifier -> thirdPartyId -> clientType - HashMap>> providerClientsMap = ThirdPartyProviderClientSQLHelper.selectAll(start); + HashMap>> providerClientsMap = ThirdPartyProviderClientSQLHelper.selectAll( + start); // Map (tenantIdentifier) -> thirdPartyId -> provider - HashMap> providerMap = ThirdPartyProviderSQLHelper.selectAll(start, providerClientsMap); + HashMap> providerMap = + ThirdPartyProviderSQLHelper.selectAll( + start, providerClientsMap); // Map (tenantIdentifier) -> firstFactors HashMap firstFactorsMap = MfaSqlHelper.selectAllFirstFactors(start); // Map (tenantIdentifier) -> requiredSecondaryFactors - HashMap requiredSecondaryFactorsMap = MfaSqlHelper.selectAllRequiredSecondaryFactors(start); + HashMap requiredSecondaryFactorsMap = + MfaSqlHelper.selectAllRequiredSecondaryFactors( + start); return TenantConfigSQLHelper.selectAll(start, providerMap, firstFactorsMap, requiredSecondaryFactorsMap); } catch (SQLException throwables) { @@ -319,7 +334,7 @@ public static void addTenantIdInTargetStorage_Transaction(Start start, Connectio + ")"; update(con, QUERY, pst -> { pst.setString(1, tenantIdentifier.getAppId()); - pst.setLong(2, currentTime); + pst.setLong(2, currentTime); pst.setString(3, tenantIdentifier.getAppId()); }); } @@ -336,7 +351,7 @@ public static void addTenantIdInTargetStorage_Transaction(Start start, Connectio update(con, QUERY, pst -> { pst.setString(1, tenantIdentifier.getAppId()); pst.setString(2, tenantIdentifier.getTenantId()); - pst.setLong(3, currentTime); + pst.setLong(3, currentTime); pst.setString(4, tenantIdentifier.getAppId()); pst.setString(5, tenantIdentifier.getTenantId()); }); @@ -344,7 +359,7 @@ public static void addTenantIdInTargetStorage_Transaction(Start start, Connectio } public static void deleteTenantIdInTargetStorage(Start start, TenantIdentifier tenantIdentifier) - throws StorageQueryException { + throws StorageQueryException { try { if (tenantIdentifier.getTenantId().equals(TenantIdentifier.DEFAULT_TENANT_ID)) { // Delete the app diff --git a/src/main/java/io/supertokens/storage/mysql/queries/PasswordlessQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/PasswordlessQueries.java index 7518f34..ae6b4be 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/PasswordlessQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/PasswordlessQueries.java @@ -55,7 +55,8 @@ public static String getQueryToCreateUsersTable(Start start) { + "time_joined BIGINT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, user_id)," + " FOREIGN KEY(app_id, user_id)" - + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + " (app_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + + " (app_id, user_id) ON DELETE CASCADE" + ");"; } @@ -72,7 +73,8 @@ static String getQueryToCreatePasswordlessUserToTenantTable(Start start) { + "CONSTRAINT phone_number UNIQUE (app_id, tenant_id, phone_number)," + "PRIMARY KEY (app_id, tenant_id, user_id)," + "FOREIGN KEY (app_id, tenant_id, user_id)" - + " REFERENCES " + Config.getConfig(start).getUsersTable() + "(app_id, tenant_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getUsersTable() + + "(app_id, tenant_id, user_id) ON DELETE CASCADE" + ");"; // @formatter:on } @@ -81,14 +83,14 @@ public static String getQueryToCreateDevicesTable(Start start) { return "CREATE TABLE IF NOT EXISTS " + getConfig(start).getPasswordlessDevicesTable() + " (" + "app_id VARCHAR(64) DEFAULT 'public'," + "tenant_id VARCHAR(64) DEFAULT 'public'," - + "device_id_hash CHAR(44) NOT NULL," - + "email VARCHAR(256)," - + "phone_number VARCHAR(256)," - + "link_code_salt CHAR(44) NOT NULL," - + "failed_attempts INT UNSIGNED NOT NULL," + + "device_id_hash CHAR(44) NOT NULL," + + "email VARCHAR(256)," + + "phone_number VARCHAR(256)," + + "link_code_salt CHAR(44) NOT NULL," + + "failed_attempts INT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, tenant_id, device_id_hash)," + "FOREIGN KEY(app_id, tenant_id)" - + " REFERENCES " + Config.getConfig(start).getTenantsTable() + " (app_id, tenant_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getTenantsTable() + " (app_id, tenant_id) ON DELETE CASCADE" + ");"; } @@ -96,14 +98,15 @@ public static String getQueryToCreateCodesTable(Start start) { return "CREATE TABLE IF NOT EXISTS " + getConfig(start).getPasswordlessCodesTable() + " (" + "app_id VARCHAR(64) DEFAULT 'public'," + "tenant_id VARCHAR(64) DEFAULT 'public'," - + "code_id CHAR(36) NOT NULL," - + "device_id_hash CHAR(44) NOT NULL," + + "code_id CHAR(36) NOT NULL," + + "device_id_hash CHAR(44) NOT NULL," + "link_code_hash CHAR(44) NOT NULL," - + "created_at BIGINT UNSIGNED NOT NULL," + + "created_at BIGINT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, tenant_id, code_id)," + "CONSTRAINT link_code_hash UNIQUE (app_id, tenant_id, link_code_hash)," + "FOREIGN KEY (app_id, tenant_id, device_id_hash)" - + " REFERENCES " + getConfig(start).getPasswordlessDevicesTable() + "(app_id, tenant_id, device_id_hash) ON DELETE CASCADE ON UPDATE CASCADE" + + " REFERENCES " + getConfig(start).getPasswordlessDevicesTable() + + "(app_id, tenant_id, device_id_hash) ON DELETE CASCADE ON UPDATE CASCADE" + ");"; } @@ -113,7 +116,8 @@ public static String getQueryToCreateDeviceEmailIndex(Start start) { } public static String getQueryToCreateDevicePhoneNumberIndex(Start start) { - return "CREATE INDEX passwordless_devices_phone_number_index ON " + getConfig(start).getPasswordlessDevicesTable() + return "CREATE INDEX passwordless_devices_phone_number_index ON " + + getConfig(start).getPasswordlessDevicesTable() + " (app_id, tenant_id, phone_number);"; // USING hash } @@ -352,7 +356,8 @@ public static void deleteCode_Transaction(Start start, Connection con, TenantIde }); } - public static AuthRecipeUserInfo createUser(Start start, TenantIdentifier tenantIdentifier, String id, @Nullable String email, + public static AuthRecipeUserInfo createUser(Start start, TenantIdentifier tenantIdentifier, String id, + @Nullable String email, @Nullable String phoneNumber, long timeJoined) throws StorageTransactionLogicException, StorageQueryException { return start.startTransaction(con -> { @@ -371,7 +376,9 @@ public static AuthRecipeUserInfo createUser(Start start, TenantIdentifier tenant { // all_auth_recipe_users String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, " + + "primary_or_recipe_user_time_joined)" + " VALUES(?, ?, ?, ?, ?, ?, ?)"; update(sqlCon, QUERY, pst -> { pst.setString(1, tenantIdentifier.getAppId()); @@ -421,7 +428,7 @@ public static AuthRecipeUserInfo createUser(Start start, TenantIdentifier tenant } private static UserInfoWithTenantId[] getUserInfosWithTenant_Transaction(Start start, Connection con, - AppIdentifier appIdentifier, String userId) + AppIdentifier appIdentifier, String userId) throws StorageQueryException, SQLException { String QUERY = "SELECT pl_users.user_id as user_id, pl_users.email as email, " + "pl_users.phone_number as phone_number, pl_users_to_tenant.tenant_id as tenant_id " @@ -733,7 +740,7 @@ public static List getUsersInfoUsingIdList(Start start, Set } public static List getUsersInfoUsingIdList_Transaction(Start start, Connection con, Set ids, - AppIdentifier appIdentifier) + AppIdentifier appIdentifier) throws SQLException, StorageQueryException { if (ids.size() > 0) { // No need to filter based on tenantId because the id list is already filtered for a tenant @@ -763,7 +770,7 @@ public static List getUsersInfoUsingIdList_Transaction(Start start, } private static UserInfoPartial getUserById_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, - String userId) + String userId) throws StorageQueryException, SQLException { // we don't need a LOCK here because this is already part of a transaction, and locked on app_id_to_user_id // table @@ -801,8 +808,8 @@ public static List lockEmail_Transaction(Start start, Connection con, Ap } public static List lockPhoneAndTenant_Transaction(Start start, Connection con, - AppIdentifier appIdentifier, - String phoneNumber) + AppIdentifier appIdentifier, + String phoneNumber) throws SQLException, StorageQueryException { String QUERY = "SELECT user_id FROM " + getConfig(start).getPasswordlessUsersTable() + @@ -820,7 +827,7 @@ public static List lockPhoneAndTenant_Transaction(Start start, Connectio } public static String getPrimaryUserIdUsingEmail(Start start, TenantIdentifier tenantIdentifier, - String email) + String email) throws StorageQueryException, SQLException { String QUERY = "SELECT DISTINCT all_users.primary_or_recipe_user_id AS user_id " + "FROM " + getConfig(start).getPasswordlessUserToTenantTable() + " AS pless" + @@ -840,8 +847,9 @@ public static String getPrimaryUserIdUsingEmail(Start start, TenantIdentifier te }); } - public static List getPrimaryUserIdsUsingEmail_Transaction(Start start, Connection con, AppIdentifier appIdentifier, - String email) + public static List getPrimaryUserIdsUsingEmail_Transaction(Start start, Connection con, + AppIdentifier appIdentifier, + String email) throws StorageQueryException, SQLException { String QUERY = "SELECT DISTINCT all_users.primary_or_recipe_user_id AS user_id " + "FROM " + getConfig(start).getPasswordlessUsersTable() + " AS pless" + @@ -882,8 +890,9 @@ public static String getPrimaryUserByPhoneNumber(Start start, TenantIdentifier t }); } - public static List listUserIdsByPhoneNumber_Transaction(Start start, Connection con, AppIdentifier appIdentifier, - @Nonnull String phoneNumber) + public static List listUserIdsByPhoneNumber_Transaction(Start start, Connection con, + AppIdentifier appIdentifier, + @Nonnull String phoneNumber) throws StorageQueryException, SQLException { String QUERY = "SELECT DISTINCT all_users.primary_or_recipe_user_id AS user_id " + "FROM " + getConfig(start).getPasswordlessUsersTable() + " AS pless" + @@ -913,12 +922,15 @@ public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlC throw new UnknownUserIdException(); } - GeneralQueries.AccountLinkingInfo accountLinkingInfo = GeneralQueries.getAccountLinkingInfo_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userId); + GeneralQueries.AccountLinkingInfo accountLinkingInfo = GeneralQueries.getAccountLinkingInfo_Transaction(start, + sqlCon, tenantIdentifier.toAppIdentifier(), userId); { // all_auth_recipe_users // ON CONFLICT DO NOTHING String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, is_linked_or_is_a_primary_user, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, is_linked_or_is_a_primary_user, " + + "recipe_id, time_joined, primary_or_recipe_user_time_joined)" + "SELECT ?, ?, ?, ?, ?, ?, ?, ? WHERE NOT EXISTS (" + " SELECT app_id, tenant_id, user_id FROM " + getConfig(start).getUsersTable() + " WHERE app_id = ? AND tenant_id = ? AND user_id = ?" @@ -937,7 +949,8 @@ public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlC pst.setString(11, userInfo.id); }); - GeneralQueries.updateTimeJoinedForPrimaryUser_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), accountLinkingInfo.primaryUserId); + GeneralQueries.updateTimeJoinedForPrimaryUser_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), + accountLinkingInfo.primaryUserId); } { // passwordless_user_to_tenant diff --git a/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java index 12e3cca..93fef07 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java @@ -106,7 +106,7 @@ public static SessionInfo getSessionInfo_Transaction(Start start, Connection con "SELECT session_handle, user_id, refresh_token_hash_2, session_data, " + "expires_at, created_at_time, jwt_user_payload, use_static_key FROM " + Config.getConfig(start).getSessionInfoTable() - + " WHERE app_id = ? AND tenant_id = ? AND session_handle = ? FOR UPDATE"; + + " WHERE app_id = ? AND tenant_id = ? AND session_handle = ? FOR UPDATE"; SessionInfo sessionInfo = execute(con, QUERY, pst -> { pst.setString(1, tenantIdentifier.getAppId()); pst.setString(2, tenantIdentifier.getTenantId()); @@ -327,11 +327,11 @@ public static SessionInfo getSession(Start start, TenantIdentifier tenantIdentif String QUERY = "SELECT sess.session_handle, sess.user_id, sess.refresh_token_hash_2, sess.session_data, sess" + ".expires_at, " - + + + "sess.created_at_time, sess.jwt_user_payload, sess.use_static_key, users" + ".primary_or_recipe_user_id FROM " + Config.getConfig(start).getSessionInfoTable() - + " AS sess LEFT JOIN " + Config.getConfig(start).getUsersTable() + + + " AS sess LEFT JOIN " + Config.getConfig(start).getUsersTable() + " as users ON sess.app_id = users.app_id AND sess.user_id = users.user_id WHERE sess.app_id =" + " ? AND " + "sess.tenant_id = ? AND sess.session_handle = ?"; @@ -412,11 +412,11 @@ public SessionInfo mapOrThrow(ResultSet result, boolean hasPrimaryOrRecipeUserId hasPrimaryOrRecipeUserId ? result.getString("primary_or_recipe_user_id") : result.getString("user_id"), result.getString("user_id"), - result.getString("refresh_token_hash_2"), - jp.parse(result.getString("session_data")).getAsJsonObject(), + result.getString("refresh_token_hash_2"), + jp.parse(result.getString("session_data")).getAsJsonObject(), result.getLong("expires_at"), - jp.parse(result.getString("jwt_user_payload")).getAsJsonObject(), - result.getLong("created_at_time"), result.getBoolean("use_static_key")); + jp.parse(result.getString("jwt_user_payload")).getAsJsonObject(), + result.getLong("created_at_time"), result.getBoolean("use_static_key")); } catch (Exception e) { throw new StorageQueryException(e); } diff --git a/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java index b3536dd..2ccc763 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java @@ -1,14 +1,7 @@ package io.supertokens.storage.mysql.queries; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - import io.supertokens.pluginInterface.RowMapper; import io.supertokens.pluginInterface.exceptions.StorageQueryException; -import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; import io.supertokens.pluginInterface.totp.TOTPDevice; @@ -16,6 +9,12 @@ import io.supertokens.storage.mysql.Start; import io.supertokens.storage.mysql.config.Config; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + import static io.supertokens.storage.mysql.QueryExecutorTemplate.execute; import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; @@ -26,19 +25,19 @@ public static String getQueryToCreateUsersTable(Start start) { + "user_id VARCHAR(128) NOT NULL," + "PRIMARY KEY (app_id, user_id)," + "FOREIGN KEY(app_id)" - + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" + ")"; } public static String getQueryToCreateUserDevicesTable(Start start) { return "CREATE TABLE IF NOT EXISTS " + Config.getConfig(start).getTotpUserDevicesTable() + " (" + "app_id VARCHAR(64) DEFAULT 'public'," - + "user_id VARCHAR(128) NOT NULL," - + "device_name VARCHAR(256) NOT NULL," + + "user_id VARCHAR(128) NOT NULL," + + "device_name VARCHAR(256) NOT NULL," + "secret_key VARCHAR(256) NOT NULL," - + "period INTEGER NOT NULL," - + "skew INTEGER NOT NULL," - + "verified BOOLEAN NOT NULL," + + "period INTEGER NOT NULL," + + "skew INTEGER NOT NULL," + + "verified BOOLEAN NOT NULL," + "created_at BIGINT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, user_id, device_name)," + "FOREIGN KEY (app_id, user_id)" @@ -86,10 +85,13 @@ private static int insertUser_Transaction(Start start, Connection con, AppIdenti }); } - private static int insertDevice_Transaction(Start start, Connection con, AppIdentifier appIdentifier, TOTPDevice device) + private static int insertDevice_Transaction(Start start, Connection con, AppIdentifier appIdentifier, + TOTPDevice device) throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + Config.getConfig(start).getTotpUserDevicesTable() - + " (app_id, user_id, device_name, secret_key, period, skew, verified, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + + + " (app_id, user_id, device_name, secret_key, period, skew, verified, created_at) VALUES (?, ?, ?, ?, " + + "?, ?, ?, ?)"; return update(con, QUERY, pst -> { pst.setString(1, appIdentifier.getAppId()); @@ -103,13 +105,15 @@ private static int insertDevice_Transaction(Start start, Connection con, AppIden }); } - public static void createDevice_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, TOTPDevice device) + public static void createDevice_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, + TOTPDevice device) throws SQLException, StorageQueryException { insertUser_Transaction(start, sqlCon, appIdentifier, device.userId); insertDevice_Transaction(start, sqlCon, appIdentifier, device); } - public static TOTPDevice getDeviceByName_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String userId, String deviceName) + public static TOTPDevice getDeviceByName_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, + String userId, String deviceName) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getTotpUserDevicesTable() + " WHERE app_id = ? AND user_id = ? AND device_name = ? FOR UPDATE;"; @@ -137,7 +141,8 @@ public static int markDeviceAsVerified(Start start, AppIdentifier appIdentifier, }); } - public static int deleteDevice_Transaction(Start start, Connection con, AppIdentifier appIdentifier, String userId, String deviceName) + public static int deleteDevice_Transaction(Start start, Connection con, AppIdentifier appIdentifier, String userId, + String deviceName) throws SQLException, StorageQueryException { String QUERY = "DELETE FROM " + Config.getConfig(start).getTotpUserDevicesTable() + " WHERE app_id = ? AND user_id = ? AND device_name = ?;"; @@ -174,7 +179,8 @@ public static boolean removeUser(Start start, TenantIdentifier tenantIdentifier, return removedUsersCount > 0; } - public static int updateDeviceName(Start start, AppIdentifier appIdentifier, String userId, String oldDeviceName, String newDeviceName) + public static int updateDeviceName(Start start, AppIdentifier appIdentifier, String userId, String oldDeviceName, + String newDeviceName) throws StorageQueryException, SQLException { String QUERY = "UPDATE " + Config.getConfig(start).getTotpUserDevicesTable() + " SET device_name = ? WHERE app_id = ? AND user_id = ? AND device_name = ?;"; @@ -205,7 +211,8 @@ public static TOTPDevice[] getDevices(Start start, AppIdentifier appIdentifier, }); } - public static TOTPDevice[] getDevices_Transaction(Start start, Connection con, AppIdentifier appIdentifier, String userId) + public static TOTPDevice[] getDevices_Transaction(Start start, Connection con, AppIdentifier appIdentifier, + String userId) throws StorageQueryException, SQLException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getTotpUserDevicesTable() + " WHERE app_id = ? AND user_id = ? FOR UPDATE;"; @@ -224,10 +231,13 @@ public static TOTPDevice[] getDevices_Transaction(Start start, Connection con, A } - public static int insertUsedCode_Transaction(Start start, Connection con, TenantIdentifier tenantIdentifier, TOTPUsedCode code) + public static int insertUsedCode_Transaction(Start start, Connection con, TenantIdentifier tenantIdentifier, + TOTPUsedCode code) throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + Config.getConfig(start).getTotpUsedCodesTable() - + " (app_id, tenant_id, user_id, code, is_valid, expiry_time_ms, created_time_ms) VALUES (?, ?, ?, ?, ?, ?, ?);"; + + + " (app_id, tenant_id, user_id, code, is_valid, expiry_time_ms, created_time_ms) VALUES (?, ?, ?, ?, " + + "?, ?, ?);"; return update(con, QUERY, pst -> { pst.setString(1, tenantIdentifier.getAppId()); diff --git a/src/main/java/io/supertokens/storage/mysql/queries/ThirdPartyQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/ThirdPartyQueries.java index ac1b4c4..ea0bc54 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/ThirdPartyQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/ThirdPartyQueries.java @@ -28,7 +28,6 @@ import io.supertokens.storage.mysql.Start; import io.supertokens.storage.mysql.config.Config; import io.supertokens.storage.mysql.utils.Utils; -import org.jetbrains.annotations.NotNull; import java.sql.Connection; import java.sql.ResultSet; @@ -46,13 +45,14 @@ static String getQueryToCreateUsersTable(Start start) { return "CREATE TABLE IF NOT EXISTS " + Config.getConfig(start).getThirdPartyUsersTable() + " (" + "app_id VARCHAR(64) DEFAULT 'public'," + "third_party_id VARCHAR(28) NOT NULL," - + "third_party_user_id VARCHAR(256) NOT NULL," - + "user_id CHAR(36) NOT NULL," - + "email VARCHAR(256) NOT NULL," + + "third_party_user_id VARCHAR(256) NOT NULL," + + "user_id CHAR(36) NOT NULL," + + "email VARCHAR(256) NOT NULL," + "time_joined BIGINT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, user_id)," + "FOREIGN KEY(app_id, user_id)" - + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + " (app_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getAppIdToUserIdTable() + + " (app_id, user_id) ON DELETE CASCADE" + ");"; } @@ -78,7 +78,8 @@ static String getQueryToCreateThirdPartyUserToTenantTable(Start start) { + "CONSTRAINT third_party_user_id UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id)," + "PRIMARY KEY (app_id, tenant_id, user_id)," + "FOREIGN KEY (app_id, tenant_id, user_id)" - + " REFERENCES " + Config.getConfig(start).getUsersTable() + "(app_id, tenant_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + Config.getConfig(start).getUsersTable() + + "(app_id, tenant_id, user_id) ON DELETE CASCADE" + ");"; // @formatter:on } @@ -102,7 +103,9 @@ public static AuthRecipeUserInfo signUp(Start start, TenantIdentifier tenantIden { // all_auth_recipe_users String QUERY = "INSERT INTO " + Config.getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, " + + "primary_or_recipe_user_time_joined)" + " VALUES(?, ?, ?, ?, ?, ?, ?)"; update(sqlCon, QUERY, pst -> { pst.setString(1, tenantIdentifier.getAppId()); @@ -259,7 +262,7 @@ public static List getUsersInfoUsingIdList(Start start, Set } public static List getUsersInfoUsingIdList_Transaction(Start start, Connection con, Set ids, - AppIdentifier appIdentifier) + AppIdentifier appIdentifier) throws SQLException, StorageQueryException { if (ids.size() > 0) { String QUERY = "SELECT user_id, third_party_id, third_party_user_id, email, time_joined " @@ -290,7 +293,7 @@ public static List getUsersInfoUsingIdList_Transaction(Start start, public static List listUserIdsByThirdPartyInfo(Start start, AppIdentifier appIdentifier, - String thirdPartyId, String thirdPartyUserId) + String thirdPartyId, String thirdPartyUserId) throws SQLException, StorageQueryException { String QUERY = "SELECT DISTINCT all_users.primary_or_recipe_user_id AS user_id " @@ -312,7 +315,8 @@ public static List listUserIdsByThirdPartyInfo(Start start, AppIdentifie }); } - public static List listUserIdsByThirdPartyInfo_Transaction(Start start, Connection con, AppIdentifier appIdentifier, + public static List listUserIdsByThirdPartyInfo_Transaction(Start start, Connection con, + AppIdentifier appIdentifier, String thirdPartyId, String thirdPartyUserId) throws SQLException, StorageQueryException { @@ -373,7 +377,7 @@ public static void updateUserEmail_Transaction(Start start, Connection con, AppI } private static UserInfoPartial getUserInfoUsingUserId_Transaction(Start start, Connection con, - AppIdentifier appIdentifier, String userId) + AppIdentifier appIdentifier, String userId) throws SQLException, StorageQueryException { // we don't need a LOCK here because this is already part of a transaction, and locked on app_id_to_user_id @@ -447,12 +451,15 @@ public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlC throw new UnknownUserIdException(); } - GeneralQueries.AccountLinkingInfo accountLinkingInfo = GeneralQueries.getAccountLinkingInfo_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userId); + GeneralQueries.AccountLinkingInfo accountLinkingInfo = GeneralQueries.getAccountLinkingInfo_Transaction(start, + sqlCon, tenantIdentifier.toAppIdentifier(), userId); { // all_auth_recipe_users // ON CONFLICT DO NOTHING String QUERY = "INSERT INTO " + Config.getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, is_linked_or_is_a_primary_user, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, is_linked_or_is_a_primary_user, " + + "recipe_id, time_joined, primary_or_recipe_user_time_joined)" + "SELECT ?, ?, ?, ?, ?, ?, ?, ? WHERE NOT EXISTS (" + " SELECT app_id, tenant_id, user_id FROM " + Config.getConfig(start).getUsersTable() + " WHERE app_id = ? AND tenant_id = ? AND user_id = ?" @@ -471,7 +478,8 @@ public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlC pst.setString(11, userInfo.id); }); - GeneralQueries.updateTimeJoinedForPrimaryUser_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), accountLinkingInfo.primaryUserId); + GeneralQueries.updateTimeJoinedForPrimaryUser_Transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), + accountLinkingInfo.primaryUserId); } { // thirdparty_user_to_tenant @@ -479,7 +487,8 @@ public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlC String QUERY = "INSERT INTO " + Config.getConfig(start).getThirdPartyUserToTenantTable() + "(app_id, tenant_id, user_id, third_party_id, third_party_user_id) " + "SELECT ?, ?, ?, ?, ? WHERE NOT EXISTS (" - + " SELECT app_id, tenant_id, user_id FROM " + Config.getConfig(start).getThirdPartyUserToTenantTable() + + " SELECT app_id, tenant_id, user_id FROM " + + Config.getConfig(start).getThirdPartyUserToTenantTable() + " WHERE app_id = ? AND tenant_id = ? AND user_id = ?" + ")"; int numRows = update(sqlCon, QUERY, pst -> { @@ -566,7 +575,7 @@ private static List fillUserInfoWithTenantIds_transaction(Start Map> tenantIdsForUserIds = GeneralQueries.getTenantIdsForUserIds_transaction(start, sqlCon, appIdentifier, userIds); - for (UserInfoPartial userInfo : userInfos) { + for (UserInfoPartial userInfo : userInfos) { userInfo.tenantIds = tenantIdsForUserIds.get(userInfo.id).toArray(new String[0]); } return userInfos; diff --git a/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java index 355d29e..7effa7a 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java @@ -49,12 +49,13 @@ public static String getQueryToCreateUserIdMappingTable(Start start) { + "CONSTRAINT external_user_id UNIQUE (app_id, external_user_id)," + "PRIMARY KEY (app_id, supertokens_user_id, external_user_id), " + "FOREIGN KEY (app_id, supertokens_user_id)" - + " REFERENCES " + getConfig(start).getAppIdToUserIdTable()+ "(app_id, user_id) ON DELETE CASCADE" + + " REFERENCES " + getConfig(start).getAppIdToUserIdTable() + "(app_id, user_id) ON DELETE CASCADE" + ")"; // @formatter:on } - public static void createUserIdMapping(Start start, AppIdentifier appIdentifier, String superTokensUserId, String externalUserId, + public static void createUserIdMapping(Start start, AppIdentifier appIdentifier, String superTokensUserId, + String externalUserId, String externalUserIdInfo) throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + Config.getConfig(start).getUserIdMappingTable() + " (app_id, supertokens_user_id, external_user_id, external_user_id_info)" + " VALUES(?, ?, ?, ?)"; @@ -67,7 +68,8 @@ public static void createUserIdMapping(Start start, AppIdentifier appIdentifier, }); } - public static UserIdMapping getuseraIdMappingWithSuperTokensUserId(Start start, AppIdentifier appIdentifier, String userId) + public static UserIdMapping getuseraIdMappingWithSuperTokensUserId(Start start, AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND supertokens_user_id = ?"; @@ -82,7 +84,8 @@ public static UserIdMapping getuseraIdMappingWithSuperTokensUserId(Start start, }); } - public static UserIdMapping getUserIdMappingWithExternalUserId(Start start, AppIdentifier appIdentifier, String userId) + public static UserIdMapping getUserIdMappingWithExternalUserId(Start start, AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND external_user_id = ?"; @@ -99,7 +102,9 @@ public static UserIdMapping getUserIdMappingWithExternalUserId(Start start, AppI } public static UserIdMapping[] getUserIdMappingWithEitherSuperTokensUserIdOrExternalUserId(Start start, - AppIdentifier appIdentifier, String userId) throws SQLException, StorageQueryException { + AppIdentifier appIdentifier, + String userId) + throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND (supertokens_user_id = ? OR external_user_id = ?)"; @@ -190,7 +195,8 @@ public static HashMap getUserIdMappingWithUserIds_Transaction(St }); } - public static boolean deleteUserIdMappingWithSuperTokensUserId(Start start, AppIdentifier appIdentifier, String userId) + public static boolean deleteUserIdMappingWithSuperTokensUserId(Start start, AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { String QUERY = "DELETE FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND supertokens_user_id = ?"; @@ -206,7 +212,8 @@ public static boolean deleteUserIdMappingWithSuperTokensUserId(Start start, AppI public static boolean deleteUserIdMappingWithExternalUserId(Start start, AppIdentifier appIdentifier, String userId) throws SQLException, StorageQueryException { - String QUERY = "DELETE FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND external_user_id = ?"; + String QUERY = "DELETE FROM " + Config.getConfig(start).getUserIdMappingTable() + + " WHERE app_id = ? AND external_user_id = ?"; // store the number of rows updated int rowUpdatedCount = update(start, QUERY, pst -> { @@ -218,8 +225,10 @@ public static boolean deleteUserIdMappingWithExternalUserId(Start start, AppIden } public static boolean updateOrDeleteExternalUserIdInfoWithSuperTokensUserId(Start start, - AppIdentifier appIdentifier, String userId, - @Nullable String externalUserIdInfo) throws SQLException, StorageQueryException { + AppIdentifier appIdentifier, + String userId, + @Nullable String externalUserIdInfo) + throws SQLException, StorageQueryException { String QUERY = "UPDATE " + Config.getConfig(start).getUserIdMappingTable() + " SET external_user_id_info = ? WHERE app_id = ? AND supertokens_user_id = ?"; @@ -234,7 +243,8 @@ public static boolean updateOrDeleteExternalUserIdInfoWithSuperTokensUserId(Star public static boolean updateOrDeleteExternalUserIdInfoWithExternalUserId(Start start, AppIdentifier appIdentifier, String userId, - @Nullable String externalUserIdInfo) throws SQLException, StorageQueryException { + @Nullable String externalUserIdInfo) + throws SQLException, StorageQueryException { String QUERY = "UPDATE " + Config.getConfig(start).getUserIdMappingTable() + " SET external_user_id_info = ? WHERE app_id = ? AND external_user_id = ?"; @@ -247,7 +257,9 @@ public static boolean updateOrDeleteExternalUserIdInfoWithExternalUserId(Start s return rowUpdated > 0; } - public static UserIdMapping getuseraIdMappingWithSuperTokensUserId_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String userId) + public static UserIdMapping getuseraIdMappingWithSuperTokensUserId_Transaction(Start start, Connection sqlCon, + AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND supertokens_user_id = ?"; @@ -262,7 +274,9 @@ public static UserIdMapping getuseraIdMappingWithSuperTokensUserId_Transaction(S }); } - public static UserIdMapping getUserIdMappingWithExternalUserId_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String userId) + public static UserIdMapping getUserIdMappingWithExternalUserId_Transaction(Start start, Connection sqlCon, + AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND external_user_id = ?"; @@ -278,8 +292,10 @@ public static UserIdMapping getUserIdMappingWithExternalUserId_Transaction(Start }); } - public static UserIdMapping[] getUserIdMappingWithEitherSuperTokensUserIdOrExternalUserId_Transaction(Start start, Connection sqlCon, - AppIdentifier appIdentifier, String userId) + public static UserIdMapping[] getUserIdMappingWithEitherSuperTokensUserIdOrExternalUserId_Transaction(Start start, + Connection sqlCon, + AppIdentifier appIdentifier, + String userId) throws SQLException, StorageQueryException { String QUERY = "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND (supertokens_user_id = ? OR external_user_id = ?)"; diff --git a/src/main/java/io/supertokens/storage/mysql/queries/UserMetadataQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/UserMetadataQueries.java index a3d7d3a..87e96a7 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/UserMetadataQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/UserMetadataQueries.java @@ -18,7 +18,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; - import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.storage.mysql.Start; @@ -39,9 +38,10 @@ public static String getQueryToCreateUserMetadataTable(Start start) { return "CREATE TABLE IF NOT EXISTS " + tableName + " (" + "app_id VARCHAR(64) DEFAULT 'public'," + "user_id VARCHAR(128) NOT NULL," - + "user_metadata TEXT NOT NULL," + + "user_metadata TEXT NOT NULL," + "PRIMARY KEY(app_id, user_id)," - + "FOREIGN KEY (app_id) REFERENCES " + Config.getConfig(start).getAppsTable() + "(app_id) ON DELETE CASCADE" + + "FOREIGN KEY (app_id) REFERENCES " + Config.getConfig(start).getAppsTable() + + "(app_id) ON DELETE CASCADE" + " );"; // @formatter:on diff --git a/src/main/java/io/supertokens/storage/mysql/queries/UserRolesQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/UserRolesQueries.java index 303bebb..670c1e7 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/UserRolesQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/UserRolesQueries.java @@ -27,19 +27,20 @@ import java.sql.SQLException; import java.util.ArrayList; -import static io.supertokens.storage.mysql.QueryExecutorTemplate.*; +import static io.supertokens.storage.mysql.QueryExecutorTemplate.execute; +import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; public class UserRolesQueries { public static String getQueryToCreateRolesTable(Start start) { String tableName = Config.getConfig(start).getRolesTable(); // @formatter:off - return "CREATE TABLE IF NOT EXISTS " + tableName + " ( " - + "app_id VARCHAR(64) DEFAULT 'public'," - + "role VARCHAR(255) NOT NULL," - + "PRIMARY KEY(app_id, role)," - + "FOREIGN KEY(app_id)" - + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" - + ")"; + return "CREATE TABLE IF NOT EXISTS " + tableName + " ( " + + "app_id VARCHAR(64) DEFAULT 'public'," + + "role VARCHAR(255) NOT NULL," + + "PRIMARY KEY(app_id, role)," + + "FOREIGN KEY(app_id)" + + " REFERENCES " + Config.getConfig(start).getAppsTable() + " (app_id) ON DELETE CASCADE" + + ")"; // @formatter:on } @@ -52,7 +53,7 @@ public static String getQueryToCreateRolePermissionsTable(Start start) { + "permission VARCHAR(255) NOT NULL, " + "PRIMARY KEY (app_id, role, permission), " + "FOREIGN KEY (app_id, role)" - + " REFERENCES " + Config.getConfig(start).getRolesTable()+ "(app_id, role) ON DELETE CASCADE )"; + + " REFERENCES " + Config.getConfig(start).getRolesTable() + "(app_id, role) ON DELETE CASCADE )"; // @formatter:on } @@ -75,7 +76,8 @@ public static String getQueryToCreateUserRolesTable(Start start) { } public static String getQueryToCreateUserRolesRoleIndex(Start start) { - return "CREATE INDEX user_roles_role_index ON " + Config.getConfig(start).getUserRolesTable() + "(app_id, tenant_id, role)"; + return "CREATE INDEX user_roles_role_index ON " + Config.getConfig(start).getUserRolesTable() + + "(app_id, tenant_id, role)"; } public static boolean createNewRoleOrDoNothingIfExists_Transaction(Start start, Connection con, @@ -99,7 +101,8 @@ public static boolean createNewRoleOrDoNothingIfExists_Transaction(Start start, public static void addPermissionToRoleOrDoNothingIfExists_Transaction(Start start, Connection con, AppIdentifier appIdentifier, String role, - String permission) throws SQLException, StorageQueryException { + String permission) + throws SQLException, StorageQueryException { // ON CONFLICT DO NOTHING String QUERY = "INSERT INTO " + Config.getConfig(start).getUserRolesPermissionsTable() + "(app_id, role, permission) " diff --git a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java index 9da3eb5..7c16117 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java @@ -33,11 +33,13 @@ public static HashMap selectAllFirstFactors(Start st throws SQLException, StorageQueryException { String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, factor_id FROM " + getConfig(start).getTenantFirstFactorsTable() + ";"; - return execute(start, QUERY, pst -> {}, result -> { + return execute(start, QUERY, pst -> { + }, result -> { HashMap> firstFactors = new HashMap<>(); while (result.next()) { - TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), result.getString("app_id"), result.getString("tenant_id")); + TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), + result.getString("app_id"), result.getString("tenant_id")); if (!firstFactors.containsKey(tenantIdentifier)) { firstFactors.put(tenantIdentifier, new ArrayList<>()); } @@ -58,7 +60,8 @@ public static HashMap selectAllRequiredSecondaryFact throws SQLException, StorageQueryException { String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, factor_id FROM " + getConfig(start).getTenantRequiredSecondaryFactorsTable() + ";"; - return execute(start, QUERY, pst -> {}, result -> { + return execute(start, QUERY, pst -> { + }, result -> { HashMap> defaultRequiredFactors = new HashMap<>(); while (result.next()) { @@ -80,13 +83,15 @@ public static HashMap selectAllRequiredSecondaryFact }); } - public static void createFirstFactors(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String[] firstFactors) + public static void createFirstFactors(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, + String[] firstFactors) throws SQLException, StorageQueryException { if (firstFactors == null || firstFactors.length == 0) { return; } - String QUERY = "INSERT INTO " + getConfig(start).getTenantFirstFactorsTable() + "(connection_uri_domain, app_id, tenant_id, factor_id) VALUES (?, ?, ?, ?);"; + String QUERY = "INSERT INTO " + getConfig(start).getTenantFirstFactorsTable() + + "(connection_uri_domain, app_id, tenant_id, factor_id) VALUES (?, ?, ?, ?);"; for (String factorId : new HashSet<>(Arrays.asList(firstFactors))) { update(sqlCon, QUERY, pst -> { pst.setString(1, tenantIdentifier.getConnectionUriDomain()); @@ -97,13 +102,15 @@ public static void createFirstFactors(Start start, Connection sqlCon, TenantIden } } - public static void createRequiredSecondaryFactors(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String[] requiredSecondaryFactors) + public static void createRequiredSecondaryFactors(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, + String[] requiredSecondaryFactors) throws SQLException, StorageQueryException { if (requiredSecondaryFactors == null || requiredSecondaryFactors.length == 0) { return; } - String QUERY = "INSERT INTO " + getConfig(start).getTenantRequiredSecondaryFactorsTable() + "(connection_uri_domain, app_id, tenant_id, factor_id) VALUES (?, ?, ?, ?);"; + String QUERY = "INSERT INTO " + getConfig(start).getTenantRequiredSecondaryFactorsTable() + + "(connection_uri_domain, app_id, tenant_id, factor_id) VALUES (?, ?, ?, ?);"; for (String factorId : requiredSecondaryFactors) { update(sqlCon, QUERY, pst -> { pst.setString(1, tenantIdentifier.getConnectionUriDomain()); diff --git a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java index 7501a98..4e91033 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java @@ -40,13 +40,15 @@ public static class TenantConfigRowMapper implements RowMapper> providerMap, HashMap firstFactorsMap, HashMap requiredSecondaryFactorsMap) + public static TenantConfig[] selectAll(Start start, + HashMap> providerMap, + HashMap firstFactorsMap, + HashMap requiredSecondaryFactorsMap) throws SQLException, StorageQueryException { String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, core_config," + " email_password_enabled, passwordless_enabled, third_party_enabled," + " is_first_factors_null FROM " + getConfig(start).getTenantConfigsTable() + ";"; - TenantConfig[] tenantConfigs = execute(start, QUERY, pst -> {}, result -> { + TenantConfig[] tenantConfigs = execute(start, QUERY, pst -> { + }, result -> { List temp = new ArrayList<>(); while (result.next()) { - TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), result.getString("app_id"), result.getString("tenant_id")); + TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), + result.getString("app_id"), result.getString("tenant_id")); ThirdPartyConfig.Provider[] providers; if (providerMap.containsKey(tenantIdentifier)) { providers = providerMap.get(tenantIdentifier).values().toArray(new ThirdPartyConfig.Provider[0]); } else { providers = new ThirdPartyConfig.Provider[0]; } - String[] firstFactors = firstFactorsMap.containsKey(tenantIdentifier) ? firstFactorsMap.get(tenantIdentifier) : new String[0]; + String[] firstFactors = + firstFactorsMap.containsKey(tenantIdentifier) ? firstFactorsMap.get(tenantIdentifier) : + new String[0]; - String[] requiredSecondaryFactors = requiredSecondaryFactorsMap.containsKey(tenantIdentifier) ? requiredSecondaryFactorsMap.get(tenantIdentifier) : new String[0]; + String[] requiredSecondaryFactors = requiredSecondaryFactorsMap.containsKey(tenantIdentifier) ? + requiredSecondaryFactorsMap.get(tenantIdentifier) : new String[0]; - temp.add(TenantConfigSQLHelper.TenantConfigRowMapper.getInstance(providers, firstFactors, requiredSecondaryFactors).mapOrThrow(result)); + temp.add(TenantConfigSQLHelper.TenantConfigRowMapper.getInstance(providers, firstFactors, + requiredSecondaryFactors).mapOrThrow(result)); } TenantConfig[] finalResult = new TenantConfig[temp.size()]; for (int i = 0; i < temp.size(); i++) { diff --git a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderClientSQLHelper.java b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderClientSQLHelper.java index 44d8049..347341e 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderClientSQLHelper.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderClientSQLHelper.java @@ -18,7 +18,6 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; import io.supertokens.pluginInterface.RowMapper; import io.supertokens.pluginInterface.exceptions.StorageQueryException; @@ -29,7 +28,10 @@ import io.supertokens.storage.mysql.Start; import io.supertokens.storage.mysql.queries.utils.JsonUtils; -import java.sql.*; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; import java.util.HashMap; import java.util.Objects; @@ -40,7 +42,8 @@ public class ThirdPartyProviderClientSQLHelper { public static class TenantThirdPartyProviderClientRowMapper implements RowMapper { - public static final TenantThirdPartyProviderClientRowMapper INSTANCE = new TenantThirdPartyProviderClientRowMapper(); + public static final TenantThirdPartyProviderClientRowMapper INSTANCE = + new TenantThirdPartyProviderClientRowMapper(); private TenantThirdPartyProviderClientRowMapper() { } @@ -59,7 +62,7 @@ public ThirdPartyConfig.ProviderClient map(ResultSet result) throws StorageQuery } else { JsonArray scopeArray = new Gson().fromJson(scopeArrayStr, JsonArray.class); scopeStringArray = new String[scopeArray.size()]; - for (int i=0; i < scopeArray.size(); i++) { + for (int i = 0; i < scopeArray.size(); i++) { scopeStringArray[i] = scopeArray.get(i).getAsString(); } } @@ -85,37 +88,47 @@ public ThirdPartyConfig.ProviderClient map(ResultSet result) throws StorageQuery } } - public static HashMap>> selectAll(Start start) + public static HashMap>> selectAll( + Start start) throws SQLException, StorageQueryException { HashMap>> providerClientsMap = new HashMap<>(); - String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, third_party_id, client_type, client_id, client_secret, scope, force_pkce, additional_config FROM " - + getConfig(start).getTenantThirdPartyProviderClientsTable() + ";"; + String QUERY = + "SELECT connection_uri_domain, app_id, tenant_id, third_party_id, client_type, client_id, " + + "client_secret, scope, force_pkce, additional_config FROM " + + getConfig(start).getTenantThirdPartyProviderClientsTable() + ";"; - execute(start, QUERY, pst -> {}, result -> { + execute(start, QUERY, pst -> { + }, result -> { while (result.next()) { - TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), result.getString("app_id"), result.getString("tenant_id")); - ThirdPartyConfig.ProviderClient providerClient = TenantThirdPartyProviderClientRowMapper.getInstance().mapOrThrow(result); + TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), + result.getString("app_id"), result.getString("tenant_id")); + ThirdPartyConfig.ProviderClient providerClient = TenantThirdPartyProviderClientRowMapper.getInstance() + .mapOrThrow(result); if (!providerClientsMap.containsKey(tenantIdentifier)) { providerClientsMap.put(tenantIdentifier, new HashMap<>()); } - if(!providerClientsMap.get(tenantIdentifier).containsKey(result.getString("third_party_id"))) { + if (!providerClientsMap.get(tenantIdentifier).containsKey(result.getString("third_party_id"))) { providerClientsMap.get(tenantIdentifier).put(result.getString("third_party_id"), new HashMap<>()); } - providerClientsMap.get(tenantIdentifier).get(result.getString("third_party_id")).put(providerClient.clientType, providerClient); + providerClientsMap.get(tenantIdentifier).get(result.getString("third_party_id")) + .put(providerClient.clientType, providerClient); } return null; }); return providerClientsMap; } - public static void create(Start start, Connection sqlCon, TenantConfig tenantConfig, ThirdPartyConfig.Provider provider, ThirdPartyConfig.ProviderClient providerClient) + public static void create(Start start, Connection sqlCon, TenantConfig tenantConfig, + ThirdPartyConfig.Provider provider, ThirdPartyConfig.ProviderClient providerClient) throws SQLException, StorageTransactionLogicException { String QUERY = "INSERT INTO " + getConfig(start).getTenantThirdPartyProviderClientsTable() - + "(connection_uri_domain, app_id, tenant_id, third_party_id, client_type, client_id, client_secret, scope, force_pkce, additional_config)" + + + "(connection_uri_domain, app_id, tenant_id, third_party_id, client_type, client_id, client_secret, " + + "scope, force_pkce, additional_config)" + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; String scopeArrayStr; diff --git a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderSQLHelper.java b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderSQLHelper.java index ebe7dc9..b4b3b88 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderSQLHelper.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/ThirdPartyProviderSQLHelper.java @@ -86,21 +86,35 @@ public ThirdPartyConfig.Provider map(ResultSet result) throws StorageQueryExcept } } - public static HashMap> selectAll(Start start, HashMap>> providerClientsMap) + public static HashMap> selectAll(Start start, + HashMap>> providerClientsMap) throws SQLException, StorageQueryException { HashMap> providerMap = new HashMap<>(); - String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, third_party_id, name, authorization_endpoint, authorization_endpoint_query_params, token_endpoint, token_endpoint_body_params, user_info_endpoint, user_info_endpoint_query_params, user_info_endpoint_headers, jwks_uri, oidc_discovery_endpoint, require_email, user_info_map_from_id_token_payload_user_id, user_info_map_from_id_token_payload_email, user_info_map_from_id_token_payload_email_verified, user_info_map_from_user_info_endpoint_user_id, user_info_map_from_user_info_endpoint_email, user_info_map_from_user_info_endpoint_email_verified FROM " - + getConfig(start).getTenantThirdPartyProvidersTable() + ";"; + String QUERY = + "SELECT connection_uri_domain, app_id, tenant_id, third_party_id, name, authorization_endpoint, " + + "authorization_endpoint_query_params, token_endpoint, token_endpoint_body_params, " + + "user_info_endpoint, user_info_endpoint_query_params, user_info_endpoint_headers, jwks_uri, " + + "oidc_discovery_endpoint, require_email, user_info_map_from_id_token_payload_user_id, " + + "user_info_map_from_id_token_payload_email, " + + "user_info_map_from_id_token_payload_email_verified, " + + "user_info_map_from_user_info_endpoint_user_id, user_info_map_from_user_info_endpoint_email, " + + "user_info_map_from_user_info_endpoint_email_verified FROM " + + getConfig(start).getTenantThirdPartyProvidersTable() + ";"; - execute(start, QUERY, pst -> {}, result -> { + execute(start, QUERY, pst -> { + }, result -> { while (result.next()) { - TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), result.getString("app_id"), result.getString("tenant_id")); + TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), + result.getString("app_id"), result.getString("tenant_id")); ThirdPartyConfig.ProviderClient[] clients = null; - if (providerClientsMap.containsKey(tenantIdentifier) && providerClientsMap.get(tenantIdentifier).containsKey(result.getString("third_party_id"))) { - clients = providerClientsMap.get(tenantIdentifier).get(result.getString("third_party_id")).values().toArray(new ThirdPartyConfig.ProviderClient[0]); + if (providerClientsMap.containsKey(tenantIdentifier) && + providerClientsMap.get(tenantIdentifier).containsKey(result.getString("third_party_id"))) { + clients = providerClientsMap.get(tenantIdentifier).get(result.getString("third_party_id")).values() + .toArray(new ThirdPartyConfig.ProviderClient[0]); } - ThirdPartyConfig.Provider provider = TenantThirdPartyProviderRowMapper.getInstance(clients).mapOrThrow(result); + ThirdPartyConfig.Provider provider = TenantThirdPartyProviderRowMapper.getInstance(clients) + .mapOrThrow(result); if (!providerMap.containsKey(tenantIdentifier)) { providerMap.put(tenantIdentifier, new HashMap<>()); @@ -112,10 +126,19 @@ public static HashMap { diff --git a/src/test/java/io/supertokens/storage/mysql/test/ConfigTest.java b/src/test/java/io/supertokens/storage/mysql/test/ConfigTest.java index 8c930fe..479ba1f 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/ConfigTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/ConfigTest.java @@ -59,7 +59,7 @@ public void beforeEach() { @Test public void testThatDefaultConfigLoadsCorrectly() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -75,7 +75,7 @@ public void testThatDefaultConfigLoadsCorrectly() throws Exception { @Test public void testThatCustomConfigLoadsCorrectly() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_pool_size", "5"); @@ -91,7 +91,7 @@ public void testThatCustomConfigLoadsCorrectly() throws Exception { @Test public void testThatInvalidConfigThrowsRightError() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; // mysql_connection_pool_size is not set properly in the config file @@ -111,7 +111,7 @@ public void testThatInvalidConfigThrowsRightError() throws Exception { @Test public void testThatMissingConfigFileThrowsError() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; ProcessBuilder pb = new ProcessBuilder("rm", "-r", "config.yaml"); pb.directory(new File(args[0])); @@ -132,7 +132,7 @@ public void testThatMissingConfigFileThrowsError() throws Exception { @Test public void testCustomLocationForConfigLoadsCorrectly() throws Exception { - String[] args = { "../", "configFile=../temp/config.yaml" }; + String[] args = {"../", "configFile=../temp/config.yaml"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); ProcessState.EventAndException e = process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.INIT_FAILURE); @@ -144,7 +144,7 @@ public void testCustomLocationForConfigLoadsCorrectly() throws Exception { // absolute path File f = new File("../temp/config.yaml"); - args = new String[] { "../", "configFile=" + f.getAbsolutePath() }; + args = new String[]{"../", "configFile=" + f.getAbsolutePath()}; process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -158,7 +158,7 @@ public void testCustomLocationForConfigLoadsCorrectly() throws Exception { @Test public void testBadPortInput() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_port", "8989"); TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false); @@ -185,7 +185,7 @@ public void testBadPortInput() throws Exception { @Test public void storageDisabledAndThenEnabled() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false); process.getProcess().waitToInitStorageModule(); @@ -210,7 +210,7 @@ public void storageDisabledAndThenEnabled() throws Exception { @Test public void testBadHostInput() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_host", "random"); @@ -219,7 +219,8 @@ public void testBadHostInput() throws Exception { assertNotNull(e); assertEquals("Failed to initialize pool: Could not connect to address=(host=random)(port=3306)(type=master) : " - + "Socket fail to connect to host:random, port:3306. random", e.exception.getCause().getCause().getCause().getMessage()); + + "Socket fail to connect to host:random, port:3306. random", + e.exception.getCause().getCause().getCause().getMessage()); process.kill(); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); @@ -228,7 +229,7 @@ public void testBadHostInput() throws Exception { @Test public void testThatChangeInTableNameIsCorrect() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_key_value_table_name", "key_value_table"); Utils.setValueInConfig("mysql_session_info_table_name", "session_info_table"); @@ -251,7 +252,7 @@ public void testThatChangeInTableNameIsCorrect() throws Exception { @Test public void testAddingTableNamePrefixWorks() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_key_value_table_name", "key_value_table"); Utils.setValueInConfig("mysql_table_names_prefix", "some_prefix"); @@ -278,7 +279,7 @@ public void testValidConnectionURI() throws Exception { MySQLConfig userConfig = mapper.readValue(new File("../config.yaml"), MySQLConfig.class); String hostname = userConfig.getHostName(); { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://root:root@" + hostname + ":3306/supertokens"); Utils.commentConfigValue("mysql_password"); @@ -298,7 +299,7 @@ public void testValidConnectionURI() throws Exception { { Utils.reset(); - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://root:root@" + hostname + "/supertokens"); Utils.commentConfigValue("mysql_password"); @@ -318,7 +319,7 @@ public void testValidConnectionURI() throws Exception { { Utils.reset(); - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://" + hostname + ":3306/supertokens"); Utils.commentConfigValue("mysql_port"); @@ -336,7 +337,7 @@ public void testValidConnectionURI() throws Exception { { Utils.reset(); - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://root@" + hostname + ":3306/supertokens"); Utils.commentConfigValue("mysql_user"); @@ -355,7 +356,7 @@ public void testValidConnectionURI() throws Exception { { Utils.reset(); - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://root:root@" + hostname + ":3306"); Utils.commentConfigValue("mysql_password"); @@ -380,7 +381,7 @@ public void testInvalidConnectionURI() throws Exception { MySQLConfig userConfig = mapper.readValue(new File("../config.yaml"), MySQLConfig.class); String hostname = userConfig.getHostName(); { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", ":/" + hostname + ":3306/supertokens"); @@ -399,7 +400,7 @@ public void testInvalidConnectionURI() throws Exception { { Utils.reset(); - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://root:wrongPassword@" + hostname + ":3306/supertokens"); @@ -426,7 +427,7 @@ public void testValidConnectionURIAttributes() throws Exception { MySQLConfig userConfig = mapper.readValue(new File("../config.yaml"), MySQLConfig.class); String hostname = userConfig.getHostName(); { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://root:root@" + hostname + ":3306/supertokens?key1=value1"); @@ -442,7 +443,7 @@ public void testValidConnectionURIAttributes() throws Exception { { Utils.reset(); - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("mysql_connection_uri", "mysql://root:root@" + hostname + ":3306/supertokens?key1=value1&allowPublicKeyRetrieval=false&key2" + "=value2"); @@ -485,9 +486,12 @@ public void testAllConfigsHaveAnAnnotation() throws Exception { continue; } - if (!(field.isAnnotationPresent(UserPoolProperty.class) || field.isAnnotationPresent(ConnectionPoolProperty.class) || field.isAnnotationPresent( + if (!(field.isAnnotationPresent(UserPoolProperty.class) || + field.isAnnotationPresent(ConnectionPoolProperty.class) || field.isAnnotationPresent( NotConflictingWithinUserPool.class))) { - fail(field.getName() + " does not have UserPoolProperty, ConnectionPoolProperty or NotConflictingWithinUserPool annotation"); + fail(field.getName() + + " does not have UserPoolProperty, ConnectionPoolProperty or NotConflictingWithinUserPool " + + "annotation"); } } } diff --git a/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java b/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java index ccfeb27..42bfc17 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java @@ -152,14 +152,15 @@ public void testDownTimeWhenChangingConnectionPoolSize() throws Exception { try { TenantIdentifier t1 = new TenantIdentifier(null, null, "t1"); Storage t1Storage = (StorageLayer.getStorage(t1, process.getProcess())); - ThirdParty.signInUp(t1, t1Storage, process.getProcess(), "google", "googleid"+ finalI, "user" + + ThirdParty.signInUp(t1, t1Storage, process.getProcess(), "google", "googleid" + finalI, "user" + finalI + "@example.com"); if (firstErrorTime.get() != -1 && successAfterErrorTime.get() == -1) { successAfterErrorTime.set(System.currentTimeMillis()); } } catch (StorageQueryException e) { - if (e.getMessage().contains("called on closed connection") || e.getMessage().contains("Connection is closed")) { + if (e.getMessage().contains("called on closed connection") || + e.getMessage().contains("Connection is closed")) { if (firstErrorTime.get() == -1) { firstErrorTime.set(System.currentTimeMillis()); } @@ -354,7 +355,7 @@ public void testIdleConnectionTimeout() throws Exception { try { TenantIdentifier t1 = new TenantIdentifier(null, null, "t1"); Storage t1Storage = (StorageLayer.getStorage(t1, process.getProcess())); - ThirdParty.signInUp(t1, t1Storage, process.getProcess(), "google", "googleid"+ finalI, "user" + + ThirdParty.signInUp(t1, t1Storage, process.getProcess(), "google", "googleid" + finalI, "user" + finalI + "@example.com"); } catch (StorageQueryException e) { diff --git a/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java b/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java index db3633d..0910477 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java @@ -31,12 +31,12 @@ import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.pluginInterface.sqlStorage.SQLStorage; +import io.supertokens.pluginInterface.sqlStorage.SQLStorage.TransactionIsolationLevel; import io.supertokens.pluginInterface.totp.TOTPDevice; import io.supertokens.pluginInterface.totp.TOTPUsedCode; import io.supertokens.pluginInterface.totp.exception.UnknownTotpUserIdException; import io.supertokens.pluginInterface.totp.exception.UsedCodeAlreadyExistsException; import io.supertokens.pluginInterface.totp.sqlStorage.TOTPSQLStorage; -import io.supertokens.pluginInterface.sqlStorage.SQLStorage.TransactionIsolationLevel; import io.supertokens.storage.mysql.Start; import io.supertokens.storageLayer.StorageLayer; import org.junit.AfterClass; @@ -50,13 +50,13 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.*; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongArray; +import java.util.concurrent.atomic.AtomicReference; import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; +import static org.junit.Assert.*; public class DeadlockTest { @Rule @@ -75,7 +75,7 @@ public void beforeEach() { @Test public void transactionDeadlockTesting() throws InterruptedException, StorageQueryException, StorageTransactionLogicException { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -84,7 +84,8 @@ public void transactionDeadlockTesting() sqlStorage.startTransaction(con -> { try { sqlStorage.setKeyValue_Transaction(TenantIdentifier.BASE_TENANT, con, "Key", new KeyValueInfo("Value")); - sqlStorage.setKeyValue_Transaction(TenantIdentifier.BASE_TENANT, con, "Key1", new KeyValueInfo("Value1")); + sqlStorage.setKeyValue_Transaction(TenantIdentifier.BASE_TENANT, con, "Key1", + new KeyValueInfo("Value1")); sqlStorage.commitTransaction(con); } catch (TenantOrAppNotFoundException e) { throw new StorageTransactionLogicException(e); @@ -175,7 +176,7 @@ public void transactionDeadlockTesting() @Test public void testCodeCreationRapidly() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -211,7 +212,7 @@ public void testCodeCreationRapidly() throws Exception { @Test public void testCodeCreationRapidlyWithDifferentEmails() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -260,7 +261,8 @@ public void testCodeCreationRapidlyWithDifferentEmails() throws Exception { System.out.println("Durations: " + durations.toString()); assertNull(process - .checkOrWaitForEventInPlugin(io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_NOT_RESOLVED)); + .checkOrWaitForEventInPlugin( + io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_NOT_RESOLVED)); assertNotNull(process .checkOrWaitForEventInPlugin(io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_FOUND)); assert (pass.get()); @@ -271,7 +273,7 @@ public void testCodeCreationRapidlyWithDifferentEmails() throws Exception { @Test public void testConcurrentDeleteAndInsert() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -392,7 +394,8 @@ public void testConcurrentDeleteAndInsert() throws Exception { TOTPUsedCode code2 = new TOTPUsedCode("user", "1234", false, nextDay, now + 1); try { totpStorage.insertUsedCode_Transaction(con, TenantIdentifier.BASE_TENANT, code2); - } catch (UnknownTotpUserIdException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { + } catch (UnknownTotpUserIdException | UsedCodeAlreadyExistsException | + TenantOrAppNotFoundException e) { // This should not happen throw new StorageTransactionLogicException(e); } @@ -436,7 +439,7 @@ public void testConcurrentDeleteAndInsert() throws Exception { @Test public void testConcurrentDeleteAndUpdate() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -623,7 +626,8 @@ public void testLinkAccountsInParallel() throws Exception { for (int i = 0; i < 3000; i++) { es.execute(() -> { try { - AuthRecipe.linkAccounts(process.getProcess(), user2.getSupertokensUserId(), user1.getSupertokensUserId()); + AuthRecipe.linkAccounts(process.getProcess(), user2.getSupertokensUserId(), + user1.getSupertokensUserId()); AuthRecipe.unlinkAccounts(process.getProcess(), user2.getSupertokensUserId()); } catch (Exception e) { if (e.getMessage().toLowerCase().contains("the transaction might succeed if retried")) { @@ -638,7 +642,8 @@ public void testLinkAccountsInParallel() throws Exception { assert (pass.get()); assertNull(process - .checkOrWaitForEventInPlugin(io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_NOT_RESOLVED)); + .checkOrWaitForEventInPlugin( + io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_NOT_RESOLVED)); assertNotNull(process .checkOrWaitForEventInPlugin(io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_FOUND)); @@ -681,7 +686,8 @@ public void testCreatePrimaryInParallel() throws Exception { assert (pass.get()); assertNull(process - .checkOrWaitForEventInPlugin(io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_NOT_RESOLVED)); + .checkOrWaitForEventInPlugin( + io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_NOT_RESOLVED)); assertNotNull(process .checkOrWaitForEventInPlugin(io.supertokens.storage.mysql.ProcessState.PROCESS_STATE.DEADLOCK_FOUND)); diff --git a/src/test/java/io/supertokens/storage/mysql/test/InMemoryDBTest.java b/src/test/java/io/supertokens/storage/mysql/test/InMemoryDBTest.java index c6494f2..cbaf5ed 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/InMemoryDBTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/InMemoryDBTest.java @@ -56,7 +56,7 @@ public void checkThatInMemDVWorksEvenIfWrongConfig() throws Exception { Utils.commentConfigValue("mysql_user"); Utils.commentConfigValue("mysql_password"); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -72,7 +72,7 @@ public void checkThatInMemDVWorksEvenIfWrongConfig() throws Exception { assert sessionInfo.accessToken != null; assert sessionInfo.refreshToken != null; - assertEquals(((SessionStorage)StorageLayer.getStorage(process.getProcess())).getNumberOfSessions( + assertEquals(((SessionStorage) StorageLayer.getStorage(process.getProcess())).getNumberOfSessions( TenantIdentifier.BASE_TENANT), 1); process.kill(); @@ -80,12 +80,13 @@ public void checkThatInMemDVWorksEvenIfWrongConfig() throws Exception { } { - String[] args = { "../" }; + String[] args = {"../"}; StorageLayer.close(); TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); - assertEquals(((SessionStorage)StorageLayer.getStorage(process.getProcess())).getNumberOfSessions(TenantIdentifier.BASE_TENANT), 0); + assertEquals(((SessionStorage) StorageLayer.getStorage(process.getProcess())).getNumberOfSessions( + TenantIdentifier.BASE_TENANT), 0); process.kill(); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); @@ -95,7 +96,7 @@ public void checkThatInMemDVWorksEvenIfWrongConfig() throws Exception { @Test public void checkThatActualDBWorksIfCorrectConfigDev() throws Exception { { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -111,17 +112,19 @@ public void checkThatActualDBWorksIfCorrectConfigDev() throws Exception { assert sessionInfo.accessToken != null; assert sessionInfo.refreshToken != null; - assertEquals(((SessionStorage)StorageLayer.getStorage(process.getProcess())).getNumberOfSessions(TenantIdentifier.BASE_TENANT), 1); + assertEquals(((SessionStorage) StorageLayer.getStorage(process.getProcess())).getNumberOfSessions( + TenantIdentifier.BASE_TENANT), 1); process.kill(false); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); } { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); - assertEquals(((SessionStorage)StorageLayer.getStorage(process.getProcess())).getNumberOfSessions(TenantIdentifier.BASE_TENANT), 1); + assertEquals(((SessionStorage) StorageLayer.getStorage(process.getProcess())).getNumberOfSessions( + TenantIdentifier.BASE_TENANT), 1); process.kill(); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); @@ -131,7 +134,7 @@ public void checkThatActualDBWorksIfCorrectConfigDev() throws Exception { @Test public void checkThatActualDBWorksIfCorrectConfigProduction() throws Exception { { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -147,17 +150,19 @@ public void checkThatActualDBWorksIfCorrectConfigProduction() throws Exception { assert sessionInfo.accessToken != null; assert sessionInfo.refreshToken != null; - assertEquals(((SessionStorage)StorageLayer.getStorage(process.getProcess())).getNumberOfSessions(TenantIdentifier.BASE_TENANT), 1); + assertEquals(((SessionStorage) StorageLayer.getStorage(process.getProcess())).getNumberOfSessions( + TenantIdentifier.BASE_TENANT), 1); process.kill(false); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); } { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); - assertEquals(((SessionStorage)StorageLayer.getStorage(process.getProcess())).getNumberOfSessions(TenantIdentifier.BASE_TENANT), 1); + assertEquals(((SessionStorage) StorageLayer.getStorage(process.getProcess())).getNumberOfSessions( + TenantIdentifier.BASE_TENANT), 1); process.kill(); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); @@ -166,7 +171,7 @@ public void checkThatActualDBWorksIfCorrectConfigProduction() throws Exception { @Test public void checkThatErrorIsThrownIfIncorrectConfigInProduction() throws IOException, InterruptedException { - String[] args = { "../" }; + String[] args = {"../"}; Utils.commentConfigValue("mysql_user"); @@ -184,7 +189,7 @@ public void checkThatErrorIsThrownIfIncorrectConfigInProduction() throws IOExcep @Test public void ifForceNoInMemoryThenDevShouldThrowError() throws IOException, InterruptedException { - String[] args = { "../", "forceNoInMemDB=true" }; + String[] args = {"../", "forceNoInMemDB=true"}; Utils.commentConfigValue("mysql_user"); diff --git a/src/test/java/io/supertokens/storage/mysql/test/LogLevelTest.java b/src/test/java/io/supertokens/storage/mysql/test/LogLevelTest.java index b26df66..b776d3c 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/LogLevelTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/LogLevelTest.java @@ -52,7 +52,7 @@ public void beforeEach() { public void testLogLevelNoneOutput() throws Exception { { Utils.setValueInConfig("log_level", "NONE"); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -96,7 +96,7 @@ public void testLogLevelNoneOutput() throws Exception { public void testLogLevelErrorOutput() throws Exception { { Utils.setValueInConfig("log_level", "ERROR"); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -150,7 +150,7 @@ public void testLogLevelErrorOutput() throws Exception { public void testLogLevelWarnOutput() throws Exception { { Utils.setValueInConfig("log_level", "WARN"); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -204,7 +204,7 @@ public void testLogLevelWarnOutput() throws Exception { public void testLogLevelInfoOutput() throws Exception { { Utils.setValueInConfig("log_level", "INFO"); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -258,7 +258,7 @@ public void testLogLevelInfoOutput() throws Exception { public void testLogLevelDebugOutput() throws Exception { { Utils.setValueInConfig("log_level", "DEBUG"); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); diff --git a/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java b/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java index 96dbf2a..69a30f0 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java @@ -21,7 +21,6 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; import com.google.gson.JsonObject; - import io.supertokens.Main; import io.supertokens.ProcessState; import io.supertokens.config.Config; @@ -66,7 +65,7 @@ public void beforeEach() { @Test public void defaultLogging() throws Exception { StorageLayer.close(); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -109,7 +108,7 @@ public void defaultLogging() throws Exception { @Test public void customLogging() throws Exception { try { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("info_log_path", "\"tempLogging/info.log\""); Utils.setValueInConfig("error_log_path", "\"tempLogging/error.log\""); @@ -160,7 +159,7 @@ public void customLogging() throws Exception { @Test public void testStandardOutLoggingWithNullStr() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; ByteArrayOutputStream stdOutput = new ByteArrayOutputStream(); ByteArrayOutputStream errorOutput = new ByteArrayOutputStream(); @@ -197,7 +196,7 @@ public void testStandardOutLoggingWithNullStr() throws Exception { @Test public void confirmLoggerClosed() throws Exception { StorageLayer.close(); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -223,7 +222,7 @@ public void confirmLoggerClosed() throws Exception { @Test public void testStandardOutLoggingWithNull() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; ByteArrayOutputStream stdOutput = new ByteArrayOutputStream(); ByteArrayOutputStream errorOutput = new ByteArrayOutputStream(); @@ -260,7 +259,7 @@ public void testStandardOutLoggingWithNull() throws Exception { @Test public void confirmHikariLoggerClosedOnlyWhenProcessEnds() throws Exception { StorageLayer.close(); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false); FeatureFlagTestContent.getInstance(process.getProcess()) .setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[]{EE_FEATURES.MULTI_TENANCY}); @@ -314,7 +313,7 @@ public void confirmHikariLoggerClosedOnlyWhenProcessEnds() throws Exception { @Test public void testDBPasswordMaskingOnDBConnectionFailUsingConnectionUri() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; String dbUser = "db_user"; String dbPassword = "db_password"; @@ -348,7 +347,7 @@ public void testDBPasswordMaskingOnDBConnectionFailUsingConnectionUri() throws E @Test public void testDBPasswordMaskingOnDBConnectionFailUsingCredentials() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; String dbUser = "db_user"; String dbPassword = "db_password"; @@ -382,7 +381,7 @@ public void testDBPasswordMaskingOnDBConnectionFailUsingCredentials() throws Exc @Test public void testDBPasswordMasking() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; ByteArrayOutputStream stdOutput = new ByteArrayOutputStream(); ByteArrayOutputStream errorOutput = new ByteArrayOutputStream(); @@ -417,7 +416,7 @@ public void testDBPasswordMasking() throws Exception { @Test public void testDBPasswordIsNotLoggedWhenProcessStartsEnds() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("error_log_path", "null"); Utils.setValueInConfig("info_log_path", "null"); @@ -481,7 +480,7 @@ public void testDBPasswordIsNotLoggedWhenProcessStartsEnds() throws Exception { @Test public void testDBPasswordIsNotLoggedWhenTenantIsCreated() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; Utils.setValueInConfig("error_log_path", "null"); Utils.setValueInConfig("info_log_path", "null"); @@ -501,14 +500,14 @@ public void testDBPasswordIsNotLoggedWhenTenantIsCreated() throws Exception { assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); Start start = (Start) StorageLayer.getStorage(process.getProcess()); - MySQLConfig userConfig = io.supertokens.storage.mysql.config.Config.getConfig(start);; + MySQLConfig userConfig = io.supertokens.storage.mysql.config.Config.getConfig(start); String dbPasswordFromConfig = userConfig.getPassword(); Main main = process.getProcess(); FeatureFlagTestContent.getInstance(main) - .setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[] { - EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY }); + .setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[]{ + EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY}); JsonObject config = new JsonObject(); TenantIdentifier tenantIdentifier = new TenantIdentifier(null, "a1", null); @@ -549,8 +548,8 @@ public void testDBPasswordIsNotLoggedWhenTenantIsCreated() throws Exception { Main main = process.getProcess(); FeatureFlagTestContent.getInstance(main) - .setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[] { - EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY }); + .setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[]{ + EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY}); TenantIdentifier tenantIdentifier = new TenantIdentifier(null, "a1", null); JsonObject config = new JsonObject(); diff --git a/src/test/java/io/supertokens/storage/mysql/test/MySQLConfigTest.java b/src/test/java/io/supertokens/storage/mysql/test/MySQLConfigTest.java index bf5081b..11f0284 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/MySQLConfigTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/MySQLConfigTest.java @@ -17,20 +17,16 @@ package io.supertokens.storage.mysql.test; +import com.fasterxml.jackson.annotation.JsonProperty; import io.supertokens.ProcessState; import io.supertokens.storage.mysql.annotations.DashboardInfo; import io.supertokens.storage.mysql.config.MySQLConfig; - import org.junit.AfterClass; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; -import com.fasterxml.jackson.annotation.JsonProperty; - -import static org.junit.Assert.*; - import java.io.BufferedReader; import java.io.FileReader; import java.lang.reflect.Field; @@ -39,6 +35,8 @@ import java.util.Map; import java.util.stream.Collectors; +import static org.junit.Assert.*; + public class MySQLConfigTest { @Rule @@ -56,14 +54,14 @@ public void beforeEach() { @Test public void testMatchConfigPropertiesDescription() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); // Skipping mysql_config_version because it doesn't // have a description in the config.yaml file - String[] ignoredProperties = { "mysql_config_version" }; + String[] ignoredProperties = {"mysql_config_version"}; // Match the descriptions in the config.yaml file with the descriptions in the // CoreConfig class @@ -144,8 +142,10 @@ private void matchYamlAndConfigDescriptions(String path, String[] ignoreProperti System.out.println(field.getName()); String descriptionInConfig = field.getAnnotation(DashboardInfo.class).description(); - descriptionInConfig = "(DIFFERENT_ACROSS_TENANTS" + (field.getAnnotation(DashboardInfo.class).isOptional() ? " | OPTIONAL" : " | COMPULSORY") - + (field.getAnnotation(DashboardInfo.class).isOptional() ? " | Default: " + field.getAnnotation(DashboardInfo.class).defaultValue() : "") + descriptionInConfig = "(DIFFERENT_ACROSS_TENANTS" + + (field.getAnnotation(DashboardInfo.class).isOptional() ? " | OPTIONAL" : " | COMPULSORY") + + (field.getAnnotation(DashboardInfo.class).isOptional() ? + " | Default: " + field.getAnnotation(DashboardInfo.class).defaultValue() : "") + ") " + valueInfo + " " + descriptionInConfig; diff --git a/src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java b/src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java index 893fc2c..0a3a591 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java @@ -61,7 +61,6 @@ import java.util.function.Supplier; import static org.junit.Assert.*; -import static org.junit.Assert.assertEquals; public class OneMillionUsersTest { @Rule @@ -110,7 +109,8 @@ private void createEmailPasswordUsers(Main main) throws Exception { String userId = io.supertokens.utils.Utils.getUUID(); long timeJoined = System.currentTimeMillis(); - storage.signUp(TenantIdentifier.BASE_TENANT, userId, "eptest" + finalI + "@example.com", combinedPasswordHash, + storage.signUp(TenantIdentifier.BASE_TENANT, userId, "eptest" + finalI + "@example.com", + combinedPasswordHash, timeJoined); synchronized (lock) { allUserIds.add(userId); @@ -119,7 +119,7 @@ private void createEmailPasswordUsers(Main main) throws Exception { throw new RuntimeException(e); } if (finalI % 10000 == 9999) { - System.out.println("Created " + ((finalI +1)) + " users"); + System.out.println("Created " + ((finalI + 1)) + " users"); } }); } @@ -140,7 +140,8 @@ private void createPasswordlessUsersWithEmail(Main main) throws Exception { String userId = io.supertokens.utils.Utils.getUUID(); long timeJoined = System.currentTimeMillis(); try { - storage.createUser(TenantIdentifier.BASE_TENANT, userId, "pltest" + finalI + "@example.com", null, timeJoined); + storage.createUser(TenantIdentifier.BASE_TENANT, userId, "pltest" + finalI + "@example.com", null, + timeJoined); synchronized (lock) { allUserIds.add(userId); } @@ -149,7 +150,7 @@ private void createPasswordlessUsersWithEmail(Main main) throws Exception { } if (finalI % 10000 == 9999) { - System.out.println("Created " + ((finalI +1)) + " users"); + System.out.println("Created " + ((finalI + 1)) + " users"); } }); } @@ -179,7 +180,7 @@ private void createPasswordlessUsersWithPhone(Main main) throws Exception { } if (finalI % 10000 == 9999) { - System.out.println("Created " + ((finalI +1)) + " users"); + System.out.println("Created " + ((finalI + 1)) + " users"); } }); } @@ -201,7 +202,8 @@ private void createThirdpartyUsers(Main main) throws Exception { long timeJoined = System.currentTimeMillis(); try { - storage.signUp(TenantIdentifier.BASE_TENANT, userId, "tptest" + finalI + "@example.com", new LoginMethod.ThirdParty("google", "googleid" + finalI), timeJoined ); + storage.signUp(TenantIdentifier.BASE_TENANT, userId, "tptest" + finalI + "@example.com", + new LoginMethod.ThirdParty("google", "googleid" + finalI), timeJoined); synchronized (lock) { allUserIds.add(userId); } @@ -210,7 +212,7 @@ private void createThirdpartyUsers(Main main) throws Exception { } if (finalI % 10000 == 9999) { - System.out.println("Created " + (finalI +1) + " users"); + System.out.println("Created " + (finalI + 1) + " users"); } }); } @@ -655,7 +657,8 @@ private void sanityCheckAPIs(Main main) throws Exception { JsonArray userRolesArr = response.getAsJsonArray("roles"); assertEquals(1, userRolesArr.size()); assertTrue( - userRolesArr.get(0).getAsString().equals("admin") || userRolesArr.get(0).getAsString().equals("user") + userRolesArr.get(0).getAsString().equals("admin") || + userRolesArr.get(0).getAsString().equals("user") ); } @@ -800,7 +803,8 @@ private void measureOperations(Main main) throws Exception { int finalI = i; es.execute(() -> { try { - ThirdParty.signInUp(main, "twitter", "twitterid" + finalI, "twitter" + finalI + "@example.com"); + ThirdParty.signInUp(main, "twitter", "twitterid" + finalI, + "twitter" + finalI + "@example.com"); } catch (Exception e) { errorCount.incrementAndGet(); throw new RuntimeException(e); @@ -826,7 +830,8 @@ private void measureOperations(Main main) throws Exception { int finalI = i; es.execute(() -> { try { - ThirdParty.signInUp(main, "twitter", "twitterid" + finalI, "twitter" + finalI + "@example.com"); + ThirdParty.signInUp(main, "twitter", "twitterid" + finalI, + "twitter" + finalI + "@example.com"); } catch (Exception e) { errorCount.incrementAndGet(); throw new RuntimeException(e); diff --git a/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java b/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java index 02d6a74..936e507 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java @@ -20,7 +20,6 @@ import io.supertokens.pluginInterface.totp.exception.UsedCodeAlreadyExistsException; import io.supertokens.pluginInterface.totp.sqlStorage.TOTPSQLStorage; import io.supertokens.storageLayer.StorageLayer; - import io.supertokens.thirdparty.ThirdParty; import org.junit.AfterClass; import org.junit.Before; @@ -70,7 +69,7 @@ public static void insertUsedCodeUtil(TOTPSQLStorage storage, TOTPUsedCode usedC @Test public void totpCodeLengthTest() throws Exception { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); @@ -112,13 +111,18 @@ public void testLinkedAccountUser() throws Exception { AuthRecipeUserInfo user1 = EmailPassword.signUp(process.getProcess(), "test1@example.com", "password"); Thread.sleep(50); - AuthRecipeUserInfo user2 = ThirdParty.signInUp(process.getProcess(), "google", "googleid", "test2@example.com").user; + AuthRecipeUserInfo user2 = ThirdParty.signInUp(process.getProcess(), "google", "googleid", + "test2@example.com").user; Thread.sleep(50); - Passwordless.CreateCodeResponse code1 = Passwordless.createCode(process.getProcess(), "test3@example.com", null, null, null); - AuthRecipeUserInfo user3 = Passwordless.consumeCode(process.getProcess(), code1.deviceId, code1.deviceIdHash, code1.userInputCode, null).user; + Passwordless.CreateCodeResponse code1 = Passwordless.createCode(process.getProcess(), "test3@example.com", null, + null, null); + AuthRecipeUserInfo user3 = Passwordless.consumeCode(process.getProcess(), code1.deviceId, code1.deviceIdHash, + code1.userInputCode, null).user; Thread.sleep(50); - Passwordless.CreateCodeResponse code2 = Passwordless.createCode(process.getProcess(), null, "+919876543210", null, null); - AuthRecipeUserInfo user4 = Passwordless.consumeCode(process.getProcess(), code2.deviceId, code2.deviceIdHash, code2.userInputCode, null).user; + Passwordless.CreateCodeResponse code2 = Passwordless.createCode(process.getProcess(), null, "+919876543210", + null, null); + AuthRecipeUserInfo user4 = Passwordless.consumeCode(process.getProcess(), code2.deviceId, code2.deviceIdHash, + code2.userInputCode, null).user; AuthRecipe.createPrimaryUser(process.getProcess(), user3.getSupertokensUserId()); AuthRecipe.linkAccounts(process.getProcess(), user1.getSupertokensUserId(), user3.getSupertokensUserId()); @@ -132,8 +136,9 @@ public void testLinkedAccountUser() throws Exception { user4.getSupertokensUserId() }; - for (String userId : userIds){ - AuthRecipeUserInfo primaryUser = ((AuthRecipeStorage) StorageLayer.getStorage(process.getProcess())).getPrimaryUserById( + for (String userId : userIds) { + AuthRecipeUserInfo primaryUser = ((AuthRecipeStorage) StorageLayer.getStorage( + process.getProcess())).getPrimaryUserById( new AppIdentifier(null, null), userId); assertEquals(user3.getSupertokensUserId(), primaryUser.getSupertokensUserId()); assertEquals(4, primaryUser.loginMethods.length); diff --git a/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java b/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java index b551c44..a1a2e0c 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java @@ -42,7 +42,6 @@ import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.*; -import static org.junit.Assert.assertNotNull; public class SuperTokensSaaSSecretTest { @Rule @@ -102,10 +101,11 @@ public void testThatTenantCannotSetProtectedConfigIfSuperTokensSaaSSecretIsSet() try { JsonObject j = new JsonObject(); j.addProperty(PROTECTED_CORE_CONFIG[i], ""); - Multitenancy.addNewOrUpdateAppOrTenant(process.main, new TenantConfig(new TenantIdentifier(null, null, "t1"), new EmailPasswordConfig(false), - new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), - new PasswordlessConfig(false), - null, null, j), true); + Multitenancy.addNewOrUpdateAppOrTenant(process.main, + new TenantConfig(new TenantIdentifier(null, null, "t1"), new EmailPasswordConfig(false), + new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), + new PasswordlessConfig(false), + null, null, j), true); fail(); } catch (BadPermissionException e) { assertEquals(e.getMessage(), "Not allowed to modify DB related configs."); @@ -195,7 +195,8 @@ public void testThatTenantCannotGetProtectedConfigIfSuperTokensSaaSSecretIsSet() { JsonObject response = HttpRequestForTesting.sendJsonRequest(process.getProcess(), "", - HttpRequestForTesting.getMultitenantUrl(TenantIdentifier.BASE_TENANT, "/recipe/multitenancy/tenant/list"), + HttpRequestForTesting.getMultitenantUrl(TenantIdentifier.BASE_TENANT, + "/recipe/multitenancy/tenant/list"), null, 1000, 1000, null, SemVer.v3_0.get(), "GET", apiKey, "multitenancy"); @@ -216,7 +217,8 @@ public void testThatTenantCannotGetProtectedConfigIfSuperTokensSaaSSecretIsSet() { JsonObject response = HttpRequestForTesting.sendJsonRequest(process.getProcess(), "", - HttpRequestForTesting.getMultitenantUrl(TenantIdentifier.BASE_TENANT, "/recipe/multitenancy/tenant/list"), + HttpRequestForTesting.getMultitenantUrl(TenantIdentifier.BASE_TENANT, + "/recipe/multitenancy/tenant/list"), null, 1000, 1000, null, SemVer.v3_0.get(), "GET", saasSecret, "multitenancy"); diff --git a/src/test/java/io/supertokens/storage/mysql/test/TableCreationTest.java b/src/test/java/io/supertokens/storage/mysql/test/TableCreationTest.java index ac57459..3d9399e 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/TableCreationTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/TableCreationTest.java @@ -45,7 +45,7 @@ public void beforeEach() { @Test public void checkingCreationOfNewTable() throws InterruptedException { - String[] args = { "../" }; + String[] args = {"../"}; TestingProcessManager.TestingProcess process = TestingProcessManager.start(args); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); diff --git a/src/test/java/io/supertokens/storage/mysql/test/TestMainThread.java b/src/test/java/io/supertokens/storage/mysql/test/TestMainThread.java index 02607bc..afa7aec 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/TestMainThread.java +++ b/src/test/java/io/supertokens/storage/mysql/test/TestMainThread.java @@ -75,8 +75,9 @@ public void testThatMainThreadIsSameThroughout() throws Exception { JsonObject requestBody = new JsonObject(); requestBody.addProperty("appId", "a1"); requestBody.add("coreConfig", config); - HttpRequestForTesting.sendJsonPUTRequest(process.getProcess(), "", "http://localhost:3567/recipe/multitenancy/app", - requestBody, 1000, 2500, null, "3.0", "multitenancy"); + HttpRequestForTesting.sendJsonPUTRequest(process.getProcess(), "", + "http://localhost:3567/recipe/multitenancy/app", + requestBody, 1000, 2500, null, "3.0", "multitenancy"); Storage storage2 = StorageLayer.getStorage(new TenantIdentifier(null, "a1", null), process.getProcess()); diff --git a/src/test/java/io/supertokens/storage/mysql/test/TestingProcessManager.java b/src/test/java/io/supertokens/storage/mysql/test/TestingProcessManager.java index 2fb5d9a..a9776f9 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/TestingProcessManager.java +++ b/src/test/java/io/supertokens/storage/mysql/test/TestingProcessManager.java @@ -32,7 +32,7 @@ public class TestingProcessManager { static void deleteAllInformation() throws Exception { System.out.println("----------DELETE ALL INFORMATION----------"); - String[] args = { "../" }; + String[] args = {"../"}; TestingProcess process = TestingProcessManager.start(args); process.checkOrWaitForEvent(PROCESS_STATE.STARTED); process.main.deleteAllInformationForTesting(); @@ -148,7 +148,8 @@ public EventAndException checkOrWaitForEvent(PROCESS_STATE state) throws Interru return checkOrWaitForEvent(state, 15000); } - public EventAndException checkOrWaitForEvent(PROCESS_STATE state, long timeToWaitMS) throws InterruptedException { + public EventAndException checkOrWaitForEvent(PROCESS_STATE state, long timeToWaitMS) + throws InterruptedException { EventAndException e = ProcessState.getInstance(main).getLastEventByName(state); if (e == null) { // we shall now wait until some time as passed. diff --git a/src/test/java/io/supertokens/storage/mysql/test/httpRequest/HttpRequestForTesting.java b/src/test/java/io/supertokens/storage/mysql/test/httpRequest/HttpRequestForTesting.java index 1ad2a9e..1a119fa 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/httpRequest/HttpRequestForTesting.java +++ b/src/test/java/io/supertokens/storage/mysql/test/httpRequest/HttpRequestForTesting.java @@ -62,7 +62,8 @@ private static boolean isJsonValid(String jsonInString) { @SuppressWarnings("unchecked") public static T sendGETRequest(Main main, String requestID, String url, Map params, - int connectionTimeoutMS, int readTimeoutMS, Integer version, String cdiVersion, String rid) + int connectionTimeoutMS, int readTimeoutMS, Integer version, String cdiVersion, + String rid) throws IOException, HttpResponseException { StringBuilder paramBuilder = new StringBuilder(); @@ -198,101 +199,107 @@ public static T sendJsonRequest(Main main, String requestID, String url, Jso } public static T sendJsonPOSTRequest(Main main, String requestID, String url, JsonElement requestBody, - int connectionTimeoutMS, int readTimeoutMS, Integer version, String cdiVersion, String rid) + int connectionTimeoutMS, int readTimeoutMS, Integer version, + String cdiVersion, String rid) throws IOException, HttpResponseException { return sendJsonRequest(main, requestID, url, requestBody, connectionTimeoutMS, readTimeoutMS, version, cdiVersion, "POST", null, rid); } public static T sendJsonPOSTRequest(Main main, String requestID, String url, JsonElement requestBody, - int connectionTimeoutMS, int readTimeoutMS, Integer version, String cdiVersion, String apiKey, String rid) + int connectionTimeoutMS, int readTimeoutMS, Integer version, + String cdiVersion, String apiKey, String rid) throws IOException, HttpResponseException { return sendJsonRequest(main, requestID, url, requestBody, connectionTimeoutMS, readTimeoutMS, version, cdiVersion, "POST", apiKey, rid); } public static T sendJsonPUTRequest(Main main, String requestID, String url, JsonElement requestBody, - int connectionTimeoutMS, int readTimeoutMS, Integer version, String cdiVersion, String rid) + int connectionTimeoutMS, int readTimeoutMS, Integer version, + String cdiVersion, String rid) throws IOException, HttpResponseException { return sendJsonRequest(main, requestID, url, requestBody, connectionTimeoutMS, readTimeoutMS, version, cdiVersion, "PUT", null, rid); } public static T sendJsonDELETERequest(Main main, String requestID, String url, JsonElement requestBody, - int connectionTimeoutMS, int readTimeoutMS, Integer version, String cdiVersion, String rid) + int connectionTimeoutMS, int readTimeoutMS, Integer version, + String cdiVersion, String rid) throws IOException, HttpResponseException { return sendJsonRequest(main, requestID, url, requestBody, connectionTimeoutMS, readTimeoutMS, version, cdiVersion, "DELETE", null, rid); } @SuppressWarnings("unchecked") - public static T sendJsonDELETERequestWithQueryParams(Main main, String requestID, String url, Map params, - int connectionTimeoutMS, int readTimeoutMS, Integer version, String cdiVersion, String rid) + public static T sendJsonDELETERequestWithQueryParams(Main main, String requestID, String url, + Map params, + int connectionTimeoutMS, int readTimeoutMS, + Integer version, String cdiVersion, String rid) throws IOException, HttpResponseException { - StringBuilder paramBuilder = new StringBuilder(); + StringBuilder paramBuilder = new StringBuilder(); - if (params != null) { - for (Map.Entry entry : params.entrySet()) { - paramBuilder.append(entry.getKey()).append("=") - .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)).append("&"); - } - } - String paramsStr = paramBuilder.toString(); - if (!paramsStr.equals("")) { - paramsStr = paramsStr.substring(0, paramsStr.length() - 1); - url = url + "?" + paramsStr; + if (params != null) { + for (Map.Entry entry : params.entrySet()) { + paramBuilder.append(entry.getKey()).append("=") + .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)).append("&"); + } + } + String paramsStr = paramBuilder.toString(); + if (!paramsStr.equals("")) { + paramsStr = paramsStr.substring(0, paramsStr.length() - 1); + url = url + "?" + paramsStr; + } + URL obj = getURL(main, requestID, url); + InputStream inputStream = null; + HttpURLConnection con = null; + + try { + con = (HttpURLConnection) obj.openConnection(); + con.setRequestMethod("DELETE"); + con.setConnectTimeout(connectionTimeoutMS); + con.setReadTimeout(readTimeoutMS + 1000); + if (version != null) { + con.setRequestProperty("api-version", version + ""); + } + if (cdiVersion != null) { + con.setRequestProperty("cdi-version", cdiVersion); + } + if (rid != null) { + con.setRequestProperty("rId", rid); + } + + int responseCode = con.getResponseCode(); + + if (responseCode < STATUS_CODE_ERROR_THRESHOLD) { + inputStream = con.getInputStream(); + } else { + inputStream = con.getErrorStream(); + } + + StringBuilder response = new StringBuilder(); + try (BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String inputLine; + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); } - URL obj = getURL(main, requestID, url); - InputStream inputStream = null; - HttpURLConnection con = null; - - try { - con = (HttpURLConnection) obj.openConnection(); - con.setRequestMethod("DELETE"); - con.setConnectTimeout(connectionTimeoutMS); - con.setReadTimeout(readTimeoutMS + 1000); - if (version != null) { - con.setRequestProperty("api-version", version + ""); - } - if (cdiVersion != null) { - con.setRequestProperty("cdi-version", cdiVersion); - } - if (rid != null) { - con.setRequestProperty("rId", rid); - } - - int responseCode = con.getResponseCode(); - - if (responseCode < STATUS_CODE_ERROR_THRESHOLD) { - inputStream = con.getInputStream(); - } else { - inputStream = con.getErrorStream(); - } - - StringBuilder response = new StringBuilder(); - try (BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { - String inputLine; - while ((inputLine = in.readLine()) != null) { - response.append(inputLine); - } - } - if (responseCode < STATUS_CODE_ERROR_THRESHOLD) { - if (!isJsonValid(response.toString())) { - return (T) response.toString(); - } - return (T) (new JsonParser().parse(response.toString())); - } - throw new HttpResponseException(responseCode, response.toString()); - } finally { - if (inputStream != null) { - inputStream.close(); - } - - if (con != null) { - con.disconnect(); - } + } + if (responseCode < STATUS_CODE_ERROR_THRESHOLD) { + if (!isJsonValid(response.toString())) { + return (T) response.toString(); } + return (T) (new JsonParser().parse(response.toString())); + } + throw new HttpResponseException(responseCode, response.toString()); + } finally { + if (inputStream != null) { + inputStream.close(); + } + + if (con != null) { + con.disconnect(); + } } + } public static String getMultitenantUrl(TenantIdentifier tenantIdentifier, String path) { StringBuilder sb = new StringBuilder(); diff --git a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java index a01b71b..3934d4f 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java @@ -745,7 +745,8 @@ public void testTenantCreationAndThenDbDownDbThrowsErrorInRecipesAndDoesntAffect tenantConfigJson); StorageLayer.getMultitenancyStorage(process.getProcess()).createTenant(tenantConfig); - MultitenancyHelper.getInstance(process.getProcess()).refreshTenantsInCoreBasedOnChangesInCoreConfigOrIfTenantListChanged(true); + MultitenancyHelper.getInstance(process.getProcess()) + .refreshTenantsInCoreBasedOnChangesInCoreConfigOrIfTenantListChanged(true); try { EmailPassword.signIn(tid, (StorageLayer.getStorage(tid, process.getProcess())), diff --git a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestForNoCrashDuringStartup.java b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestForNoCrashDuringStartup.java index b2ee097..5828e42 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestForNoCrashDuringStartup.java +++ b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestForNoCrashDuringStartup.java @@ -48,8 +48,8 @@ import java.io.IOException; -import static org.junit.Assert.*; import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; +import static org.junit.Assert.*; public class TestForNoCrashDuringStartup { TestingProcessManager.TestingProcess process; @@ -107,7 +107,8 @@ public void testThatCUDRecoversWhenItFailsToAddEntryDuringCreation() throws Exce assertEquals(2, allTenants.length); // should have the new CUD try { - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); fail(); } catch (HttpResponseException e) { // ignore @@ -117,14 +118,16 @@ public void testThatCUDRecoversWhenItFailsToAddEntryDuringCreation() throws Exce MultitenancyQueries.simulateErrorInAddingTenantIdInTargetStorage_forTesting = false; // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); } @Test public void testThatCUDRecoversWhenTheDbIsDownDuringCreationButDbComesUpLater() throws Exception { Start start = ((Start) StorageLayer.getBaseStorage(process.getProcess())); try { - update(start, "DROP DATABASE st5000;", pst -> {}); + update(start, "DROP DATABASE st5000;", pst -> { + }); } catch (Exception e) { // ignore } @@ -154,17 +157,20 @@ public void testThatCUDRecoversWhenTheDbIsDownDuringCreationButDbComesUpLater() assertEquals(2, allTenants.length); // should have the new CUD try { - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); fail(); } catch (HttpResponseException e) { // ignore assertTrue(e.getMessage().contains("Internal Error")); // db is still down } - update(start, "CREATE DATABASE st5000;", pst -> {}); + update(start, "CREATE DATABASE st5000;", pst -> { + }); // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); } @Test @@ -260,7 +266,8 @@ public void testThatCoreDoesNotCrashDuringStartupWhenCUDCreationFailedToAddEntry MultitenancyQueries.simulateErrorInAddingTenantIdInTargetStorage_forTesting = false; // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); } @Test @@ -291,7 +298,8 @@ public void testThatCoreDoesNotCrashDuringStartupWhenTenantEntryIsInconsistentIn assertEquals(2, allTenants.length); // should have the new CUD Start start = (Start) StorageLayer.getBaseStorage(process.getProcess()); - update(start, "DELETE FROM apps;", pst -> {}); + update(start, "DELETE FROM apps;", pst -> { + }); process.kill(false); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); @@ -306,13 +314,15 @@ public void testThatCoreDoesNotCrashDuringStartupWhenTenantEntryIsInconsistentIn MultitenancyQueries.simulateErrorInAddingTenantIdInTargetStorage_forTesting = false; // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); Session.createNewSession(process.getProcess(), "userid", new JsonObject(), new JsonObject()); } @Test - public void testThatCoreDoesNotCrashDuringStartupWhenAppCreationFailedToAddEntryInTheBaseTenantStorage() throws Exception { + public void testThatCoreDoesNotCrashDuringStartupWhenAppCreationFailedToAddEntryInTheBaseTenantStorage() + throws Exception { JsonObject coreConfig = new JsonObject(); TenantIdentifier tenantIdentifier = new TenantIdentifier(null, "a1", null); @@ -354,7 +364,8 @@ public void testThatCoreDoesNotCrashDuringStartupWhenAppCreationFailedToAddEntry assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); Session.createNewSession( new TenantIdentifier(null, "a1", null), @@ -364,7 +375,8 @@ public void testThatCoreDoesNotCrashDuringStartupWhenAppCreationFailedToAddEntry } @Test - public void testThatCoreDoesNotCrashDuringStartupWhenCUDCreationFailedToAddTenantEntryInTargetStorageWithLoadOnlyCUDConfig() throws Exception { + public void testThatCoreDoesNotCrashDuringStartupWhenCUDCreationFailedToAddTenantEntryInTargetStorageWithLoadOnlyCUDConfig() + throws Exception { JsonObject coreConfig = new JsonObject(); TenantIdentifier tenantIdentifier = new TenantIdentifier("127.0.0.1", null, null); @@ -442,10 +454,12 @@ public void testThatCoreDoesNotCrashDuringStartupWhenCUDCreationFailedToAddTenan assertEquals(2, allTenants.length); // should have the new CUD // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); try { - tpSignInUpAndGetResponse(new TenantIdentifier("localhost", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("localhost", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); fail(); } catch (HttpResponseException e) { // ignore @@ -465,9 +479,11 @@ public void testThatCoreDoesNotCrashDuringStartupWhenCUDCreationFailedToAddTenan assertEquals(2, allTenants.length); // should have the new CUD // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("localhost", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("localhost", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); try { - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); fail(); } catch (HttpResponseException e) { // ignore @@ -488,7 +504,8 @@ public void testThatCoreDoesNotCrashDuringStartupWhenCUDCreationFailedToAddTenan public void testThatTenantComesToLifeOnceTheTargetDbIsUpAfterCoreRestart() throws Exception { Start start = ((Start) StorageLayer.getBaseStorage(process.getProcess())); try { - update(start, "DROP DATABASE st5000;", pst -> {}); + update(start, "DROP DATABASE st5000;", pst -> { + }); } catch (Exception e) { // ignore } @@ -518,7 +535,8 @@ public void testThatTenantComesToLifeOnceTheTargetDbIsUpAfterCoreRestart() throw assertEquals(2, allTenants.length); // should have the new CUD try { - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); fail(); } catch (HttpResponseException e) { // ignore @@ -537,13 +555,16 @@ public void testThatTenantComesToLifeOnceTheTargetDbIsUpAfterCoreRestart() throw // the process should start successfully even though the db is down start = ((Start) StorageLayer.getBaseStorage(process.getProcess())); - update(start, "CREATE DATABASE st5000;", pst -> {}); + update(start, "CREATE DATABASE st5000;", pst -> { + }); // this should succeed now - tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", "test@example.com", process.getProcess(), SemVer.v5_0); + tpSignInUpAndGetResponse(new TenantIdentifier("127.0.0.1", null, null), "google", "googleid1", + "test@example.com", process.getProcess(), SemVer.v5_0); } - public static JsonObject tpSignInUpAndGetResponse(TenantIdentifier tenantIdentifier, String thirdPartyId, String thirdPartyUserId, String email, Main main, SemVer version) + public static JsonObject tpSignInUpAndGetResponse(TenantIdentifier tenantIdentifier, String thirdPartyId, + String thirdPartyUserId, String email, Main main, SemVer version) throws HttpResponseException, IOException { JsonObject emailObject = new JsonObject(); emailObject.addProperty("id", email); diff --git a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java index 77d1ad3..8151051 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java +++ b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java @@ -15,6 +15,7 @@ */ package io.supertokens.storage.mysql.test.multitenancy; + import com.google.gson.JsonObject; import io.supertokens.ProcessState; import io.supertokens.emailpassword.EmailPassword; @@ -110,7 +111,8 @@ public void testUsersWorkAfterUserPoolIdChanges() throws Exception { String userPoolId2 = storage.getUserPoolId(); assertNotEquals(userPoolId, userPoolId2); - AuthRecipeUserInfo user2 = EmailPassword.signIn(tenantIdentifier, storage, process.getProcess(), "user@example.com", "password"); + AuthRecipeUserInfo user2 = EmailPassword.signIn(tenantIdentifier, storage, process.getProcess(), + "user@example.com", "password"); assertEquals(userInfo, user2); } @@ -160,7 +162,8 @@ public void testUsersWorkAfterUserPoolIdChangesAndServerRestart() throws Excepti String userPoolId2 = storage.getUserPoolId(); assertNotEquals(userPoolId, userPoolId2); - AuthRecipeUserInfo user2 = EmailPassword.signIn(tenantIdentifier, storage, process.getProcess(), "user@example.com", "password"); + AuthRecipeUserInfo user2 = EmailPassword.signIn(tenantIdentifier, storage, process.getProcess(), + "user@example.com", "password"); assertEquals(userInfo, user2); }