Compare commits

...
Author SHA1 Message Date
copilot-swe-agent[bot]andMeldiron d9773f44b1 Change GitHub alert from NOTE to TIP in VCS comments
Co-authored-by: Meldiron <19310830+Meldiron@users.noreply.github.com>
2025-10-20 12:32:38 +00:00
copilot-swe-agent[bot] 46dd8fdc68 Initial plan 2025-10-20 12:28:04 +00:00
Damodar LohaniandGitHub 254f026458 Merge pull request #10667 from appwrite/fix-auth-refactor
Fix: reset argon 2 options to previous default
2025-10-19 14:00:25 +05:45
Damodar Lohani 248d3aea7a Fix: reset argon 2 options to previous default 2025-10-19 05:44:44 +00:00
Luke B. SilverandGitHub 07d55d17a3 Merge pull request #10658 from appwrite/update-domains-0.8.3
update domain lib to 0.8.4
2025-10-17 13:09:36 +01:00
Chirag Aggarwal abfab60eec update to 0.8.4 2025-10-17 17:05:47 +05:30
Chirag Aggarwal fc3ac122dd Merge branch '1.8.x' into update-domains-0.8.3 2025-10-17 17:05:24 +05:30
Jake BarnbyandGitHub 3963b632d8 Merge pull request #10663 from appwrite/update-apple-swift
chore: update apple and swift sdks to 13.2.2
2025-10-17 07:01:25 +00:00
Chirag Aggarwal 1936a01464 chore: update apple and swift sdks to 13.2.2 2025-10-17 12:28:31 +05:30
Luke B. SilverandGitHub 2cbfa6930f Merge pull request #10655 from appwrite/fix-test-dependencies-projects
Refactor ProjectsConsoleClientTest to remove test dependencies
2025-10-16 11:30:50 +01:00
Chirag Aggarwal 33a856af41 update domain lib to 0.8.3 2025-10-16 15:54:43 +05:30
Chirag Aggarwal 5d1d937fde remove changes 2025-10-16 15:29:59 +05:30
Chirag Aggarwal 83ec855f4b skip harder ones 2025-10-16 15:18:21 +05:30
Luke B. SilverandGitHub 5ce9b8eaeb Merge pull request #10656 from appwrite/feat-replace-sleep-in-webhooks-service
Replace sleep in webhook tests with assertEventually
2025-10-16 10:45:32 +01:00
Khushboo Verma be983eb68a Remove race condition 2025-10-16 14:40:47 +05:30
Chirag Aggarwal c6f144313d more tests 2025-10-16 14:29:57 +05:30
Chirag Aggarwal ae8ec1c736 formatting 2025-10-16 14:26:39 +05:30
Chirag Aggarwal 19d7f02371 more tests 2025-10-16 14:25:12 +05:30
Khushboo Verma f0660f3fda Replace sleep in webhook tests with assertEventually 2025-10-16 14:23:35 +05:30
Chirag Aggarwal 9ded176cf2 Refactor ProjectsConsoleClientTest to remove test dependencies
- Remove @depends annotations to make tests independent
- Each test now creates its own team and project instead of relying on shared state
- Replace sleep() calls with assertEventually() for more reliable async testing
- Change test methods to return void instead of passing data between tests
- Remove unnecessary sleep() call that was causing test flakiness
2025-10-16 14:21:30 +05:30
Damodar LohaniandGitHub 2e10cd0009 Merge pull request #10654 from appwrite/fix-undefined-var
Fix: undefined variable warning
2025-10-16 13:40:04 +05:45
Damodar Lohani 7ff664e62b Fix: undefined $user 2025-10-16 07:38:13 +00:00
Damodar LohaniandGitHub 9dd1939d1f Merge pull request #10468 from appwrite/feat-apps-module-dl
Feat apps module dl
2025-10-16 11:40:27 +05:45
Damodar LohaniandGitHub 8dfdfcb522 Merge pull request #10652 from appwrite/fix-undefined-sequence
Fix undefined sequence
2025-10-16 10:34:37 +05:45
Damodar LohaniandGitHub b63c2804f1 Fix: undefined $sequence 2025-10-16 10:26:49 +05:45
Damodar Lohani ced2270571 remove unused injection 2025-10-16 03:39:39 +00:00
Damodar Lohani d3436077a1 remove unused hash 2025-10-16 03:39:18 +00:00
Damodar Lohani e06349e803 update argon2 instances 2025-10-16 03:34:45 +00:00
Damodar Lohani 9849b9d678 Fix empty check 2025-10-16 02:41:53 +00:00
Damodar Lohani 22136867ed add additional check 2025-10-16 02:29:30 +00:00
Damodar Lohani 2df621f9c5 Fix: update comment, typings 2025-10-16 02:23:41 +00:00
Damodar Lohani 9a599e2015 update recommended param for argon2 2025-10-16 02:20:28 +00:00
Damodar Lohani 431dd96b98 chaining 2025-10-16 02:17:59 +00:00
Damodar Lohani 4d8f950955 fix roles filtering 2025-10-16 02:17:52 +00:00
Damodar Lohani 08e559180d fix missing injection 2025-10-16 02:08:07 +00:00
Damodar Lohani 4cb63068de improve install loop 2025-10-16 02:07:17 +00:00
Damodar Lohani f062b39cfa Fix encoding 2025-10-16 02:06:01 +00:00
Damodar Lohani 06ee421965 update composer 2025-10-15 07:11:27 +00:00
Damodar Lohani c3c69cc43b Merge remote-tracking branch 'origin/1.8.x' into feat-apps-module-dl 2025-10-15 07:05:23 +00:00
Damodar Lohani e47d53ddcc Merge remote-tracking branch 'origin/main' into feat-apps-module-dl 2025-10-15 07:04:38 +00:00
Jake BarnbyandGitHub 290a7b27db Merge branch 'main' into 1.8.x 2025-10-15 18:45:38 +13:00
Luke B. SilverandGitHub 3e078027a7 Merge pull request #10644 from appwrite/bcc-only-emails
chore: use bcc only emails for smtp
2025-10-14 13:18:36 +01:00
Chirag Aggarwal 97f448f984 comma 2025-10-14 17:19:08 +05:30
Chirag Aggarwal 07727298f7 remove default recepient 2025-10-14 17:18:44 +05:30
Chirag Aggarwal 752520470d fix: param 2025-10-14 09:27:50 +05:30
Chirag Aggarwal 128cd68ec8 chore: use bcc only emails for smtp 2025-10-14 09:23:31 +05:30
Damodar LohaniandGitHub a832343348 Merge pull request #10617 from appwrite/fix-make-stats-usage-extendable
Fix: make methods protected for extending
2025-10-14 06:40:25 +05:45
Luke B. SilverandGitHub 3e47f9442f Merge pull request #10641 from appwrite/update-dotnet-sdk-0.21.2
Update .NET SDK to 0.21.2 and improve release detection
2025-10-13 12:53:28 +01:00
Luke B. SilverandGitHub 08d661d8c3 Merge pull request #10620 from appwrite/fix-block-schedules
Fix block schedules
2025-10-13 12:51:38 +01:00
loks0n 3544649903 fix: block schedules 2025-10-13 12:29:32 +01:00
Chirag Aggarwal 6f5ac232c5 lint 2025-10-13 16:01:55 +05:30
Chirag Aggarwal 3b82141de2 Update .NET SDK to 0.21.2 and improve release detection
- Update .NET SDK version to 0.21.2 with Object[] deserialization fix
- Update sdk-generator dependency from 1.4.3 to 1.4.4
- Improve SDK release detection to check actual commit SHA of latest release tag instead of just checking releases targeting the branch
2025-10-13 15:25:51 +05:30
Jake BarnbyandGitHub e303501d4a Merge pull request #10640 from appwrite/feat-txn
Fix txn API scope backwards compat
2025-10-13 16:30:46 +13:00
Jake Barnby 935011b9e9 Fix backwards compat API scopes 2025-10-13 15:59:26 +13:00
Jake BarnbyandGitHub de7dd6079e Merge pull request #10618 from appwrite/ser-417
Throw duplicate error when function id already exists
2025-10-13 14:56:43 +13:00
Damodar Lohani 5e5b22d649 fix jwt 2025-10-12 04:38:14 +00:00
Damodar LohaniandGitHub 53212dc654 Merge branch '1.8.x' into fix-make-stats-usage-extendable 2025-10-12 10:17:33 +05:45
Damodar Lohani 1b17c32405 update block 2025-10-12 03:51:37 +00:00
Damodar Lohani d56dff954f Merge remote-tracking branch 'origin/1.8.x' into feat-apps-module-dl 2025-10-12 00:34:07 +00:00
Matej BačoandGitHub 95268c49ce Merge pull request #10631 from appwrite/fix-zero-errors-on-realtime
Fix: code 0 from databases on realtime
2025-10-10 15:45:09 +02:00
Darshan 1c6b56385c fix: code 0 from databases. 2025-10-10 18:26:00 +05:30
Luke B. SilverandGitHub 9819ee518d Merge pull request #10629 from appwrite/update-domains-0.8.2
update domains lib to 0.8.2
2025-10-10 12:29:19 +01:00
Chirag Aggarwal 751d51ea2e update domains lib to 0.8.2 2025-10-10 15:37:29 +05:30
Hemachandar 1f322a2700 add test 2025-10-10 15:30:56 +05:30
Jake BarnbyandGitHub d89173ad57 Merge pull request #10627 from appwrite/fix-releases-sdks
fix: prevent empty releases in sdk release script
2025-10-10 21:43:35 +13:00
Chirag Aggarwal d6fc2806dc fix: prevent empty releases in sdk release script 2025-10-10 13:26:55 +05:30
Jake Barnby a8b9d75b2a Merge remote-tracking branch 'origin/feat-txn' into 1.8.x 2025-10-10 19:21:48 +13:00
Jake Barnby ab5556919e Update specs 2025-10-10 19:21:33 +13:00
Jake Barnby f9e0bc4cd7 Merge branch 'feat-txn' into 1.8.x 2025-10-10 18:46:42 +13:00
Jake Barnby 12a1653ae0 Update doc desc 2025-10-10 18:44:48 +13:00
Jake BarnbyandGitHub 821b3b86e4 Merge pull request #10626 from appwrite/feat-txn
Fix cross API compatibility
2025-10-10 18:38:42 +13:00
Jake Barnby 2830ab55f0 Lint 2025-10-10 17:42:42 +13:00
Jake Barnby f95e8a965a Only set sequence on not empty 2025-10-10 17:27:57 +13:00
Jake Barnby 7512a0db6b Fix cross-API compat 2025-10-10 17:27:09 +13:00
Jake Barnby cdac840071 Use return value for write ops count 2025-10-10 15:51:26 +13:00
Jake BarnbyandGitHub aa43902d32 Merge pull request #10624 from appwrite/feat-txn
Feat txn
2025-10-10 02:38:21 +13:00
Jake Barnby 276b135799 Trigger CI 2025-10-10 02:17:42 +13:00
Jake Barnby bf589f7485 Fix client side 2025-10-10 02:16:58 +13:00
Jake BarnbyandGitHub 852f06cc28 Merge pull request #10623 from Veera-mulge/change-desc
Update README.md
2025-10-10 02:09:26 +13:00
VeereshandGitHub d82171b4de Update README.md 2025-10-09 18:36:30 +05:30
Jake BarnbyandGitHub 1dbcfcc154 Merge pull request #10621 from appwrite/feat-txn
Feat txn sdks
2025-10-10 00:34:27 +13:00
Jake Barnby 32d6eaa21c Check expiry on stage 2025-10-09 23:37:44 +13:00
Jake Barnby a3103bf4d4 Fix release 2025-10-09 23:37:28 +13:00
Hemachandar 9cd284f5cd Throw duplicate error when function id already exists 2025-10-09 15:01:00 +05:30
Jake Barnby 0877aa2964 Generate SDKs 2025-10-09 21:04:50 +13:00
Jake Barnby 3b225b8ec3 Update specs 2025-10-09 16:52:40 +13:00
Jake BarnbyandGitHub 5727b0fb45 Merge pull request #10023 from appwrite/feat-txn
Feat txn
2025-10-09 16:47:45 +13:00
Jake Barnby 8193f0fcac Ensure create/upsert stores in state by generated ID not unique string 2025-10-09 16:24:25 +13:00
Jake Barnby 3d3f50064d Force set state on increment 2025-10-09 15:50:18 +13:00
Damodar LohaniandGitHub 432faaf209 Fix: make methods protected for extending 2025-10-09 08:24:39 +05:45
Jake Barnby 10b1f1f145 Merge remote-tracking branch 'origin/1.8.x' into feat-txn 2025-10-09 13:45:29 +13:00
Jake Barnby dcad82c46b Update db 2025-10-09 13:45:19 +13:00
Jake BarnbyandGitHub 07ce00d36d Merge pull request #10615 from appwrite/deprecate-create-verification-add-patch-releases
add automatic releases
2025-10-08 20:55:37 +13:00
Chirag Aggarwal 8d2df2b744 add go changes 2025-10-08 13:25:28 +05:30
Chirag Aggarwal adf9ec3e75 add automatic releases 2025-10-08 13:05:46 +05:30
Jake BarnbyandGitHub 1c691cf3e8 Merge pull request #10614 from appwrite/deprecate-create-verification-add-patch-releases
Add minor releases for all SDKs - deprecate createVerification, add createEmailVerification
2025-10-08 19:40:11 +13:00
Chirag Aggarwal e935fc2510 Add minor releases for all SDKs - deprecate createVerification, add createEmailVerification
This commit adds minor version releases for all client and server SDKs to deprecate the
`createVerification` method in the Account service and introduce the new `createEmailVerification`
method as its replacement.

Updated SDKs:

Client SDKs:
- Android: 11.0.0 → 11.1.0
- Web: 21.0.0 → 21.1.0
- Flutter: 20.0.0 → 20.1.0
- Apple: 13.0.0 → 13.1.0
- React Native: 0.15.0 → 0.16.0

Server SDKs:
- Node.js: 20.0.0 → 20.1.0
- PHP: 17.2.0 → 17.3.0
- Python: 13.2.0 → 13.3.0
- Ruby: 19.0.0 → 19.1.0
- Go: 0.13.0 → 0.14.0
- .NET: 0.19.0 → 0.20.0
- Dart: 19.0.0 → 19.1.0
- Kotlin: 12.0.0 → 12.1.0
- Swift: 13.0.0 → 13.1.0

Console SDK:
- CLI: 10.0.1 → 10.1.0
2025-10-08 10:20:23 +05:30
Matej BačoandGitHub ca24ff808d Merge pull request #10533 from appwrite/ser-378-fix-null-recipient-in-email
Throw error when email is not available for account verification
2025-10-07 14:49:01 +02:00
Matej BačoandGitHub e3b1146dbb Merge pull request #10501 from appwrite/ser-375-update-email-verification-with-branded-design
Branded email for Console auth flows
2025-10-07 13:20:53 +02:00
Hemachandar 7f62b19240 Merge branch '1.8.x' into ser-375-update-email-verification-with-branded-design 2025-10-07 16:11:54 +05:30
Hemachandar 6e0d376746 use filevalidator 2025-10-07 16:07:47 +05:30
Jake Barnby 066e0bc236 Validate inc/dec operation value is numeric 2025-10-07 23:33:19 +13:00
Jake Barnby eb7306a4fa Add missing state handlers 2025-10-07 22:17:59 +13:00
Matej BačoandGitHub f653348f93 Merge pull request #10609 from appwrite/ser-439
Add project name in email subject
2025-10-07 09:53:04 +02:00
Jake Barnby 9e3c439c51 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-10-07 18:57:46 +13:00
Jake Barnby 61b073a6a2 Clean up 2025-10-07 18:53:38 +13:00
Jake BarnbyandGitHub 92ecd08a18 Merge pull request #10606 from appwrite/feat-rename-verification-methods
Rename verification SDK methods to be more specific
2025-10-07 18:17:45 +13:00
Chirag AggarwalandGitHub 8baf4d429e Merge branch '1.8.x' into feat-rename-verification-methods 2025-10-07 11:47:43 +07:00
Jake BarnbyandGitHub aa48c6e63e Merge pull request #10611 from appwrite/chore-bump-db
Chore bump db
2025-10-07 17:34:31 +13:00
Chirag Aggarwal 024d13c1b2 update naming 2025-10-07 09:58:39 +05:30
Jake Barnby 52ac68b511 Trigger CI 2025-10-07 16:12:20 +13:00
Jake Barnby 99c0ccacf1 Update database 2025-10-07 16:11:18 +13:00
Jake BarnbyandGitHub 5d09189737 Merge pull request #10608 from appwrite/realtime-fix
added both collection and table id in the realtime
2025-10-07 14:17:19 +13:00
Luke B. SilverandGitHub af68c46702 Merge pull request #10592 from Priyanshuthapliyal2005/fix/tableDbBrokenLink
fix(docs): update broken create table links in TablesDB docs
2025-10-06 21:24:42 +01:00
Luke B. SilverandGitHub 7b207ccfd2 Merge pull request #10581 from Priyanshuthapliyal2005/fix/listTemplates
fix(listTemplates): correct invalid template links in Create temporary deployment endpoint
2025-10-06 21:18:42 +01:00
HemachandarandGitHub a60ae0a9ed Merge branch '1.8.x' into ser-439 2025-10-06 23:51:06 +05:30
Hemachandar cb70a6e2c8 Add project name in email subject 2025-10-06 22:14:29 +05:30
Hemachandar caf18372ce feedback 2025-10-06 21:52:18 +05:30
ArnabChatterjee20k eeebea1dbb added both collection and table id in the realtime 2025-10-06 20:13:36 +05:30
Hemachandar 29dbe99840 simplify config & templates 2025-10-06 19:58:01 +05:30
Chirag Aggarwal 56076ad649 update path and add alias 2025-10-06 19:13:06 +05:30
Chirag Aggarwal c618144d78 update examples 2025-10-06 16:46:56 +05:30
Chirag AggarwalandClaude 4348a176d5 Rename verification SDK methods to be more specific
This commit renames the verification SDK methods to better reflect their purpose:
- `createVerification` → `createEmailVerification`
- `updateVerification` → `updateEmailVerification`

The old method names are maintained for backwards compatibility and marked as deprecated (since 1.8.0) with references to the new method names.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 16:44:31 +05:30
Jake BarnbyandGitHub 3190d0437e Merge pull request #10596 from appwrite/feat-update-relationships
Update database
2025-10-06 18:29:45 +13:00
Jake BarnbyandGitHub 06a6240877 Merge pull request #10598 from appwrite/fix-dat-761
Sanitize 5xx errors on realtime
2025-10-06 17:48:37 +13:00
Jake Barnby 1311c73d1a Merge branch 'feat-update-relationships' of github.com:appwrite/appwrite into feat-update-relationships 2025-10-06 17:32:49 +13:00
Jake Barnby b7f7fb00af Update database 2025-10-06 17:32:35 +13:00
DarshanandGitHub fa4044d922 Merge branch '1.8.x' into fix-dat-761 2025-10-06 09:58:17 +05:30
Darshan 875c8f8d1d Merge remote-tracking branch 'origin/fix-dat-761' into fix-dat-761 2025-10-06 09:58:05 +05:30
Darshan 02b982f3a1 update: code fallback! 2025-10-06 09:57:54 +05:30
Jake BarnbyandGitHub d7edaef34f Merge branch '1.8.x' into feat-update-relationships 2025-10-06 17:09:50 +13:00
Jake Barnby 1da034d00c Update database 2025-10-06 17:08:19 +13:00
Jake BarnbyandGitHub a06d96699b Merge branch '1.8.x' into feat-txn 2025-10-06 17:02:11 +13:00
Jake BarnbyandGitHub ee7917999d Merge pull request #10554 from appwrite/update-sdks-add-response-models
chore: update sdks add response models
2025-10-06 16:19:33 +13:00
Jake Barnby 2566f4d98e Add tostring 2025-10-06 14:16:01 +13:00
Jake Barnby 24f6da5610 Add assertions on tables DB 2025-10-06 13:47:21 +13:00
DarshanandGitHub 68124d1d14 Merge branch '1.8.x' into fix-dat-761 2025-10-05 15:28:45 +05:30
Luke B. SilverandGitHub 04ae6a582a Merge pull request #10601 from appwrite/chore-update-composer-deps
chore: update composer dependencies
2025-10-04 21:56:11 +01:00
Chirag Aggarwal 0314547c95 fix: permission issues 2025-10-05 00:39:54 +05:30
Chirag AggarwalandGitHub 5aa94036d1 Merge branch '1.8.x' into update-sdks-add-response-models 2025-10-05 02:01:33 +07:00
Chirag AggarwalandClaude 81bd4cbe50 chore: update composer dependencies
- Updated open-telemetry/api from 1.6.0 to 1.7.0
- Updated open-telemetry/sdk from 1.8.0 to 1.9.0
- Updated utopia-php/domains from 0.8.0 to 0.8.1
- Updated appwrite/sdk-generator from 1.4.2 to 1.4.3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-05 00:26:37 +05:30
Chirag Aggarwal f5af1ee7bb update more 2025-10-04 21:09:19 +05:30
Darshan 236585c20b fix: sanitize 5xx errors on realtime when running in production. 2025-10-04 18:38:35 +05:30
Jake Barnby ce52dba419 Update to release 2025-10-05 00:09:26 +13:00
Jake Barnby 5be2489e55 Check query result 2025-10-05 00:06:56 +13:00
Jake Barnby 12f6b07fbf Update database 2025-10-04 23:20:08 +13:00
Jake Barnby 6881df6ae5 Fix expectations 2025-10-04 22:55:07 +13:00
Jake Barnby 52892ee46e Upgrade for breaking changes 2025-10-04 22:32:01 +13:00
Jake Barnby 57e3e8f5f4 Fix test scope 2025-10-04 21:10:50 +13:00
Jake Barnby 3e77810e13 Fix existence check for tracked + staged ops 2025-10-04 19:26:22 +13:00
Jake Barnby 01ef058adb Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	tests/e2e/Services/Realtime/RealtimeCustomClientTest.php
2025-10-04 17:03:52 +13:00
Jake Barnby 17a5019606 Merge branch 'feat-txn' of github.com:appwrite/appwrite into feat-txn 2025-10-04 16:49:27 +13:00
Jake Barnby 9edc0c16d8 Realtime txn tests 2025-10-04 16:48:44 +13:00
Jake Barnby 2c7cf7826b Fix operation perm checks 2025-10-04 16:43:39 +13:00
Aditya OberaiandGitHub 3fd5e0337b Merge branch '1.8.x' into fix/listTemplates 2025-10-04 01:16:19 +05:30
Jake Barnby 742ddc517b Update database 2025-10-04 01:38:06 +13:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
e93e03c248 Update src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-04 01:15:53 +13:00
Jake Barnby 89a47953d8 Fix tests 2025-10-04 00:46:13 +13:00
Hemachandar b145c609bd change error codes 2025-10-03 16:29:39 +05:30
Priyanshu ThapliyalandGitHub be67da9d64 Merge branch '1.8.x' into fix/tableDbBrokenLink 2025-10-03 15:49:21 +05:30
Matej BačoandGitHub 59d5c49818 Merge pull request #10589 from appwrite/ser-377
Handle OIDC well-known endpoint errors
2025-10-03 10:44:38 +02:00
Priyanshu ThapliyalandGitHub 9d4592d90e Merge branch '1.8.x' into fix/tableDbBrokenLink 2025-10-03 14:01:05 +05:30
Priyanshu Thapliyal ce86758cdc fix typo issues raise by bot 2025-10-03 08:30:06 +00:00
Matej BačoandGitHub b811fc6252 Merge pull request #10503 from appwrite/ser-10-oauth-auto-allow-site-domains
Auto-allow sites domain for OAuth
2025-10-03 10:15:05 +02:00
Jake Barnby deb3d75375 Explicit order asc 2025-10-03 20:00:32 +13:00
Jake BarnbyandGitHub 60433ef22d Merge pull request #10590 from appwrite/dat-753
Bug fix -> related data in realtime payload
2025-10-03 19:31:48 +13:00
Jake Barnby 2bc90db1f6 Fix tests 2025-10-03 18:56:05 +13:00
Jake Barnby 59ae403391 Add more validation tests 2025-10-03 17:34:34 +13:00
Jake Barnby 71b2164154 Clean up state helper 2025-10-03 16:58:23 +13:00
Chirag Aggarwal 848b932ea1 fix flutter version 2025-10-03 08:46:25 +05:30
Chirag Aggarwal a61385e534 update versions 2025-10-03 08:43:54 +05:30
Chirag AggarwalandGitHub a3dff6a640 Merge branch '1.8.x' into update-sdks-add-response-models 2025-10-02 22:54:44 +07:00
Priyanshu Thapliyal 770c58d33c fix(docs): replace broken table creation links with correct references 2025-10-02 14:28:35 +00:00
ArnabChatterjee20k 76d3dc3d5a * added senstive var copying in from method
* added tests
2025-10-02 18:27:20 +05:30
Jake Barnby 522a4d2a62 Format 2025-10-03 00:39:14 +13:00
Jake Barnby 44e7068a9a Fix syntax 2025-10-03 00:26:39 +13:00
Jake Barnby 0aaa276f03 Merge branch 'feat-txn' of github.com:appwrite/appwrite into feat-txn 2025-10-03 00:12:30 +13:00
Jake Barnby d54058b59a Fix multi API event 2025-10-03 00:12:19 +13:00
Jake Barnby 5da2ca292a Add missing injection 2025-10-03 00:03:54 +13:00
Jake Barnby f4830b1672 Catch query exception 2025-10-03 00:03:46 +13:00
Jake Barnby 7fd2502dd5 Block client bulk upsert txn 2025-10-03 00:03:34 +13:00
Jake Barnby 36a8365ebb Count from state 2025-10-03 00:03:20 +13:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
45da32d5d9 Update src/Appwrite/Utopia/Database/Validator/Operation.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-02 23:57:30 +13:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
a9a97b2fe0 Update src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-02 23:20:22 +13:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
6581d68e6d Update src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-02 23:20:02 +13:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
51d5ddb463 Update src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-02 23:17:17 +13:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
9813b98133 Update src/Appwrite/Databases/TransactionState.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-02 23:05:43 +13:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
93d8f1cfe7 Update src/Appwrite/Databases/TransactionState.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-02 23:03:52 +13:00
HemachandarandGitHub 3d287207d2 Merge branch '1.8.x' into ser-377 2025-10-02 14:59:50 +05:30
Hemachandar ca1c069e65 Handle OIDC well-known endpoint errors 2025-10-02 14:58:55 +05:30
Jake Barnby 473be9284d Check convert 2025-10-02 22:24:54 +13:00
Jake Barnby f667149556 Trigger CI 2025-10-02 22:12:02 +13:00
Jake Barnby 490341af09 Fix log limit 2025-10-02 21:46:28 +13:00
Jake Barnby ae661e9961 Fix missing bulk map 2025-10-02 21:37:54 +13:00
Jake Barnby 26ae33522d Fix txn read scope 2025-10-02 21:36:33 +13:00
Jake Barnby 070d5f59d1 Merge remote-tracking branch 'origin/1.8.x' into feat-txn 2025-10-02 19:25:46 +13:00
Jake BarnbyandGitHub eff3e4bda2 Merge pull request #10585 from appwrite/fix-logs-truncation-tests
fix: logs truncation tests
2025-10-02 19:22:21 +13:00
Matej BačoandGitHub e40cb8e327 Merge pull request #10586 from appwrite/fix-activities
Fix activities
2025-10-01 15:41:27 +02:00
Darshan 813bc0d9b3 fix: wrong audit resource. 2025-10-01 18:25:32 +05:30
Chirag Aggarwal 11bbe3c6dd fix: test file 2025-10-01 18:17:35 +05:30
Chirag AggarwalandGitHub 2841c1b792 Merge branch '1.8.x' into update-sdks-add-response-models 2025-10-01 19:13:32 +07:00
Priyanshu Thapliyal 558904e103 fix(listTemplates): fix invalid template links in Create temporary deployment endpoint 2025-10-01 08:58:22 +00:00
Khushboo VermaandGitHub f7e594a51a Merge branch '1.8.x' into ser-378-fix-null-recipient-in-email 2025-10-01 08:38:17 +01:00
Jake Barnby 9a468e8297 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-10-01 20:15:43 +13:00
Chirag Aggarwal b4dd1df0c7 update composer 2025-10-01 11:56:48 +05:30
Jake BarnbyandGitHub 8752feef4d Merge pull request #10577 from appwrite/chore-bump-db
Update database for nested selection fix
2025-10-01 19:03:15 +13:00
Jake Barnby b1757250d1 Fix update 2025-10-01 17:47:42 +13:00
Chirag Aggarwal 3d43f85145 add temp hack 2025-10-01 10:06:55 +05:30
Chirag Aggarwal 397c41e68b update cli 2025-10-01 09:46:20 +05:30
Jake Barnby 3dd099bd94 Update database for nested selection fix 2025-10-01 17:05:12 +13:00
Torsten DittmannandGitHub 054bee773c Merge pull request #10572 from appwrite/fix-builds-worker-output-directory 2025-09-30 20:31:03 +04:00
Torsten Dittmann b7604a5742 Fix buildOutput attribute name in deployment check 2025-09-30 19:51:17 +04:00
Luke B. SilverandGitHub e244cb2f02 Merge pull request #10571 from appwrite/fix-builds-worker-output-directory
fix(builds-worker): Use outputDirectory attribute from deployment
2025-09-30 15:58:13 +01:00
Torsten Dittmann debdfeedf1 Fix variable reference in function build command 2025-09-30 18:33:22 +04:00
Torsten Dittmann 4b98544112 Move outputDirectory initialization before conditional flow 2025-09-30 18:31:37 +04:00
Torsten Dittmann 04d6693803 Fix output directory path validation and position 2025-09-30 18:10:53 +04:00
Torsten Dittmann b614045d97 fix(builds-worker): Use outputDirectory attribute from deployment or
resource
2025-09-30 18:08:49 +04:00
Jake BarnbyandGitHub f0b3f40a63 Merge pull request #10561 from appwrite/update-enums
chore: add enums for database type and column status
2025-09-29 19:51:44 +13:00
Chirag Aggarwal 5245ff7167 update enum name 2025-09-29 11:29:40 +05:30
Chirag Aggarwal d5e1f9952a chore: add enums for database type and column status 2025-09-29 11:26:00 +05:30
Chirag Aggarwal a0e8711d9b chore: update sdks add response models 2025-09-26 15:33:37 +05:30
Jake BarnbyandGitHub cf92c259ed Merge pull request #10553 from appwrite/update-platform-type
fix: enum typing for platform in specs
2025-09-26 20:06:53 +12:00
Chirag Aggarwal a0f0449c21 fix: enum typing for platform in specs 2025-09-26 12:33:10 +05:30
Jake Barnby 372a50f9a5 Update lock 2025-09-26 14:45:09 +12:00
Jake Barnby ce1f7d4da3 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-09-26 14:43:10 +12:00
Jake Barnby ef147cde21 Format 2025-09-26 14:28:11 +12:00
Jake Barnby 4e91904608 Update database 2025-09-26 14:25:02 +12:00
Luke B. SilverandGitHub cdd5e5e728 Merge pull request #10551 from appwrite/update-composer-frameowkr
chore: update framework lib to 0.33.28
2025-09-25 15:59:39 +01:00
Chirag Aggarwal 14c64e405b chore: update framework lib 2025-09-25 19:45:32 +05:30
Jake Barnby e06c358db4 Don't require data for delete operation 2025-09-26 00:50:25 +12:00
Jake Barnby 7a03084e83 Bump SDK version 2025-09-25 19:21:21 +12:00
Jake Barnby 97f76899bf Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	app/config/platforms.php
2025-09-25 18:00:07 +12:00
Jake Barnby 4a3cbdafca Move to row-level scope for txn 2025-09-25 17:59:39 +12:00
Luke B. SilverandGitHub f28bb9345b Merge pull request #9874 from appwrite/fix-zindex
Update: `z-index` to be the highest
2025-09-24 16:59:20 +01:00
Darshan c00eec948a remove: unnecessary changes. 2025-09-24 18:01:43 +05:30
Darshan b067d26e3e Merge remote-tracking branch 'origin/fix-zindex' into fix-zindex 2025-09-24 17:57:50 +05:30
Darshan e6c9a30e98 Merge branch '1.8.x' into fix-zindex 2025-09-24 17:57:36 +05:30
DarshanandGitHub d5011c0f09 Merge branch '1.8.x' into fix-zindex 2025-09-24 17:56:41 +05:30
DarshanandGitHub 4808fd827a Merge branch 'main' into fix-zindex 2025-09-24 17:52:56 +05:30
Luke B. SilverandGitHub 04fdab0920 Merge pull request #10545 from appwrite/update-afterbuild-with-adapter
chore: update afterbuild to also pass adapter
2025-09-24 09:52:12 +01:00
Hemachandar 752368327f feedback 2025-09-24 13:06:20 +05:30
Chirag Aggarwal 85da691aec allow null adapter 2025-09-24 13:05:37 +05:30
Chirag Aggarwal 9d99f5cec2 chore: update afterbuild pass adapter 2025-09-24 11:47:13 +05:30
Jake BarnbyandGitHub aa4a58c8aa Merge pull request #10541 from appwrite/update-after-build
chore: update afterbuild fn
2025-09-24 17:23:08 +12:00
Chirag Aggarwal 5749b41753 updated to use if throw checks 2025-09-24 10:00:55 +05:30
Jake BarnbyandGitHub 7a31e1cf15 Merge pull request #10540 from appwrite/fix-healthstatus-enum
Fix healthstatus enum
2025-09-24 14:09:28 +12:00
Chirag Aggarwal 7ea01733ef chore: update afterbuild fn 2025-09-23 18:28:29 +05:30
Chirag Aggarwal 9ede8cfb91 fix: healthstatus enum override due to conflict 2025-09-23 16:52:35 +05:30
Jake BarnbyandGitHub 5448c79028 Merge pull request #10539 from appwrite/chore-sdk-release
SDK releases
2025-09-23 19:41:17 +12:00
Jake Barnby 0995bd6a6e SDK releases 2025-09-23 19:17:06 +12:00
Jake BarnbyandGitHub dce014993f Merge pull request #10538 from appwrite/respone-models-enum-names
chore: include response model enum names
2025-09-23 18:23:46 +12:00
Chirag Aggarwal 5d8ac0a5b0 add message status 2025-09-23 11:31:29 +05:30
Chirag Aggarwal 17f1cb214f override healthstatus 2025-09-23 10:57:35 +05:30
Chirag Aggarwal 84a4ef0baf chore: include response model enum names 2025-09-23 10:47:39 +05:30
Jake BarnbyandGitHub dece9c8d53 Merge pull request #10522 from appwrite/refactor-schedules
refactor: improve code readability for schedules
2025-09-23 15:08:49 +12:00
Chirag AggarwalandGitHub 3616337646 Merge branch '1.8.x' into refactor-schedules 2025-09-23 09:20:20 +07:00
Chirag Aggarwal 421ec6f3f8 fix: use correct constant 2025-09-23 07:49:55 +05:30
Chirag Aggarwal 734d2ce512 fix: use correct constant 2025-09-23 07:49:07 +05:30
Chirag Aggarwal 232b22b71e use constants 2025-09-23 07:35:17 +05:30
Chirag Aggarwal c52081dbed fix: to use correct pattern 2025-09-22 19:58:18 +05:30
Luke B. SilverandGitHub ab7d3d3415 Merge pull request #10496 from appwrite/cursor/add-type-enum-support-and-update-docs-3769
Add type_enum support and update docs
2025-09-22 14:47:54 +01:00
Chirag AggarwalandGitHub 2043d0e322 Merge branch '1.8.x' into refactor-schedules 2025-09-22 16:11:46 +07:00
Hemachandar 0228c74f71 Throw error when email is not available for account verification 2025-09-22 14:26:23 +05:30
Luke B. SilverandGitHub 6ff683909d Merge pull request #10511 from appwrite/update-cli-10.0.0
update cli to 10.0.0
2025-09-22 09:54:52 +01:00
Chirag AggarwalandGitHub d5d6f9a748 Merge branch '1.8.x' into cursor/add-type-enum-support-and-update-docs-3769 2025-09-22 15:52:43 +07:00
Chirag Aggarwal f09d5258ec use constants 2025-09-22 14:20:58 +05:30
Hemachandar 2f1046db2b fix tests 2025-09-22 12:10:55 +05:30
Hemachandar 2f768aa30d Merge branch '1.8.x' into ser-10-oauth-auto-allow-site-domains 2025-09-22 11:21:32 +05:30
Jake Barnby 9fde875904 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
#	src/Appwrite/Platform/Workers/StatsResources.php
#	src/Appwrite/Platform/Workers/StatsUsage.php
2025-09-22 16:12:45 +12:00
Chirag Aggarwal 3e8211d6bd refactor: improve code readability for schedules 2025-09-20 19:45:44 +05:30
Jake BarnbyandGitHub 0b5fc8f0fd Merge pull request #10517 from appwrite/fix-miss-catch
Catch query exception on bulk update/delete
2025-09-19 18:16:31 +12:00
Jake Barnby f944ad350e Catch query exception on bulk update/delete 2025-09-19 17:32:34 +12:00
Jake BarnbyandGitHub df276692e8 Merge pull request #10516 from appwrite/fix-internal-removal
Don't remove required attributes
2025-09-19 15:52:08 +12:00
Jake Barnby c1782f6f58 Don't remove required attributes 2025-09-19 15:28:41 +12:00
Luke B. SilverandGitHub 40bdfb0a14 Merge pull request #10515 from appwrite/bump-database-1-5
bump database 1.5.0
2025-09-18 16:25:20 +01:00
fogelito d9b657796b bump database 1.5.0 2025-09-18 17:49:38 +03:00
Jake BarnbyandGitHub e2f4d380f6 Merge pull request #10514 from Veera-mulge/change-desc
Update README.md
2025-09-19 01:08:50 +12:00
VeereshandGitHub 4b90998d1e Update README.md 2025-09-18 18:04:27 +05:30
Hemachandar 5fd2dfafb7 remove var_dump 2025-09-18 14:10:56 +05:30
Hemachandar 0812ac97a9 tests 2025-09-18 14:09:42 +05:30
Jake BarnbyandGitHub 9a0ab6c5a0 Merge pull request #10513 from appwrite/sub-query-variables-order-by
Sub query variables order by
2025-09-18 20:25:05 +12:00
fogelito 4da7f04a5c Add order by 2025-09-18 10:58:27 +03:00
fogelito a7e9e58312 Add order by 2025-09-18 10:57:47 +03:00
Hemachandar dedc7a35c9 remove debug output 2025-09-18 12:38:18 +05:30
Hemachandar 2021396f39 email otp branded 2025-09-18 12:36:00 +05:30
Chirag Aggarwal 427c891e0f update cli to 10.0.0 2025-09-18 10:13:23 +05:30
Jake BarnbyandGitHub 34f3501cdc Merge pull request #10509 from appwrite/fix-spatials-type-required-col
Add spatial column validation during required mode and tests for exis…
2025-09-18 15:29:50 +12:00
Jake BarnbyandGitHub 30003caeb3 Merge pull request #10472 from appwrite/stats-resources-try-catch
Stats resources and usage sorting by unique field
2025-09-18 15:20:19 +12:00
Jake Barnby 0e2c5d93f5 Update check 2025-09-18 14:54:07 +12:00
Damodar Lohani 4540362f42 Fix: token hash magic url session 2025-09-18 01:37:19 +00:00
Damodar Lohani 3065f53d83 Fix token hash 2025-09-18 01:14:14 +00:00
ArnabChatterjee20k 52ceddcd5a linting 2025-09-17 20:02:36 +05:30
ArnabChatterjee20k c5e9ec3969 added cases for checking default added or not 2025-09-17 20:00:10 +05:30
ArnabChatterjee20k 5b09ebe54b added cases for with default values 2025-09-17 19:46:06 +05:30
ArnabChatterjee20k 4815780476 Add spatial column validation during required mode and tests for existing data in databases 2025-09-17 18:01:29 +05:30
Damodar Lohani 74f181d7a8 fix token length 2025-09-17 10:18:49 +00:00
Damodar LohaniandGitHub 337eda8538 Merge branch '1.8.x' into feat-apps-module-dl 2025-09-17 14:49:22 +05:45
fogelito 7d1a1d3ef4 use $tenant 2025-09-17 08:45:23 +03:00
fogelito 88c6e783c4 Merge branch '1.8.x' of https://github.com/appwrite/appwrite into stats-resources-try-catch 2025-09-17 08:42:27 +03:00
Jake Barnby ddb852c150 Merge branch 'feat-txn' of github.com:appwrite/appwrite into feat-txn 2025-09-17 14:58:36 +12:00
Jake Barnby 63aee11312 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-09-17 14:58:17 +12:00
Jake BarnbyandGitHub 14062fc7c2 Merge pull request #10506 from appwrite/feat-reconnects
Update database
2025-09-17 13:08:41 +12:00
Jake Barnby f03a62d43d Update database 2025-09-17 01:33:36 +12:00
Jake BarnbyandGitHub d7e90560c9 Merge pull request #10505 from appwrite/fix-bucket-query
Catch query exception on bucket/file list
2025-09-17 00:15:12 +12:00
Jake Barnby 832687dd09 Catch query exception on bucket/file list 2025-09-16 23:42:07 +12:00
Jake Barnby b38b2bba0c Remove state order on created, rely on sequence order 2025-09-16 21:13:41 +12:00
Hemachandar 21f25b4ce4 Auto-allow sites domain for OAuth 2025-09-16 14:16:02 +05:30
fogelito 614285f1ae Add Scope for tests 2025-09-16 11:29:13 +03:00
Jake BarnbyandGitHub 76f59e2404 Merge pull request #10502 from appwrite/fix-filter-exceptions
Throw appropriate 400s from request filters
2025-09-16 19:19:03 +12:00
Jake Barnby c9b39a3f28 Lint 2025-09-16 18:37:52 +12:00
Hemachandar e6be9bac07 cleanup 2025-09-16 11:55:43 +05:30
Hemachandar f8ab95b3e1 tests & lint 2025-09-16 11:54:01 +05:30
Jake Barnby 081e2aeb6e Throw appropriate 400s from request filters 2025-09-16 17:51:22 +12:00
Damodar LohaniandGitHub 20c3641ac1 Merge branch '1.8.x' into feat-apps-module-dl 2025-09-16 10:25:30 +05:45
Damodar Lohani 33f7056e7a reest callback 2025-09-16 04:38:52 +00:00
Damodar Lohani 73e7c98131 Fix token length update 2025-09-16 04:36:30 +00:00
Damodar Lohani 1157d6fd10 Fix re-hashing 2025-09-16 04:27:00 +00:00
Chirag Aggarwal 31ed726409 keep graphql backwards 2025-09-16 09:48:17 +05:30
Jake Barnby fb65d7a965 Add scoped tests 2025-09-16 13:25:15 +12:00
Jake Barnby 42d981c0ef Add scopes to roles 2025-09-16 13:15:08 +12:00
Jake Barnby a7cff1b53d Merge remote-tracking branch 'origin/1.8.x' into feat-txn 2025-09-16 12:58:09 +12:00
Steven NguyenandGitHub 64bb1efc44 Merge pull request #10483 from appwrite/SUC-1668-fix-database-usage-stats
SUC-1668 fix:database usage metrics
2025-09-15 16:28:58 -07:00
Hemachandar 0b9e43c9f8 Branded email for Console auth flows 2025-09-16 00:58:23 +05:30
Damodar Lohani cfd82d9709 use newer syntax 2025-09-15 10:57:31 +00:00
Damodar Lohani 21245836c7 Merge remote-tracking branch 'origin/1.8.x' into feat-apps-module-dl 2025-09-15 10:44:43 +00:00
Damodar Lohani b5ca4c1166 update suggestion 2025-09-15 10:43:40 +00:00
Damodar Lohani 780799f87a update to initialize first 2025-09-15 10:41:29 +00:00
Damodar Lohani 4579e41ace update check 2025-09-15 10:33:21 +00:00
Damodar Lohani 19cf94bd7e Fix oauth2 changes 2025-09-15 10:22:45 +00:00
Chirag Aggarwal 1f9bc650de work in progress 2025-09-15 12:13:48 +05:30
Chirag Aggarwal ef69520f95 fix: nitpick comments 2025-09-15 11:51:47 +05:30
Chirag Aggarwal 579f6691f9 fix: default to be created 2025-09-15 11:42:23 +05:30
Chirag Aggarwal 40eaf39d91 fix: graphql 2025-09-15 11:39:00 +05:30
Chirag Aggarwal 0f5cb2611d fix: grammer 2025-09-15 10:32:06 +05:30
Chirag Aggarwal f9ac0b48c8 fix: use 1.8.x 2025-09-15 10:28:34 +05:30
Damodar Lohani 13b98409ae reset length 2025-09-14 05:56:56 +00:00
Damodar Lohani 518389d32c fix length 2025-09-14 05:37:06 +00:00
Damodar Lohani 800db0b99d Fix magic URL token length 2025-09-14 05:23:30 +00:00
Damodar Lohani cfa4530797 composer update 2025-09-14 05:03:20 +00:00
Damodar Lohani d42841d80a fix: remove hardcode, reuse hasher 2025-09-14 05:02:50 +00:00
3b668f7806 Update composer.json
Co-authored-by: Matej Bačo <matejbacocom@gmail.com>
2025-09-14 10:45:53 +05:45
32b290a231 Update src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php
Co-authored-by: Matej Bačo <matejbacocom@gmail.com>
2025-09-14 10:44:46 +05:45
Damodar Lohani 365aaca56d fix: remove legacy token generator use 2025-09-14 04:58:34 +00:00
Damodar Lohani 1c726d0466 fix: encoded not defined 2025-09-14 04:53:49 +00:00
Damodar Lohani c903caabcc remove dump 2025-09-14 04:50:13 +00:00
Damodar Lohani 53a117bd0f Merge remote-tracking branch 'origin/1.8.x' into feat-apps-module-dl 2025-09-14 04:49:34 +00:00
Jake Barnby 0f9c2001f7 Demo SDK 2025-09-13 02:42:42 +12:00
Divyansha Dubey ef3d38c5a6 fixed db stats env var 2025-09-12 17:48:15 +04:00
Jake Barnby 5c09e8ae00 Lint 2025-09-13 00:35:03 +12:00
Jake Barnby e5a95ed990 Update DB 2025-09-13 00:31:35 +12:00
Jake Barnby edc637b762 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-09-13 00:29:19 +12:00
Jake Barnby 304ebf12b9 Add more tests 2025-09-13 00:04:49 +12:00
Jake Barnby 4f916fae22 Handle limit exception 2025-09-13 00:04:37 +12:00
Jake Barnby 7120bce761 Handle structure exception 2025-09-12 21:47:40 +12:00
Jake Barnby 38dc92bfa7 Delete with worker 2025-09-12 02:05:19 +12:00
Jake Barnby 1403868d05 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-09-12 01:45:41 +12:00
Jake Barnby 65ad2c9ff5 Handle usage + realtime 2025-09-12 01:45:16 +12:00
Jake Barnby 09753cd6dc Optimise schema 2025-09-12 01:16:23 +12:00
Jake Barnby ef685c5bc1 Fix tests 2025-09-12 00:19:39 +12:00
Jake Barnby fd6ddf6926 Fix operation spec gen 2025-09-11 23:31:53 +12:00
Jake Barnby 67b05a3f1a Fix test workflow 2025-09-11 23:08:23 +12:00
Jake Barnby b74e5ce5cd Block bulk ops through txn create multi ops 2025-09-11 22:22:46 +12:00
Jake Barnby 6652e27dd5 Update TablesDB auth 2025-09-11 22:21:53 +12:00
Jake Barnby c7dba3690a Update auth types 2025-09-11 22:17:00 +12:00
Jake Barnby dd64afa970 Add missing references 2025-09-11 22:16:44 +12:00
Jake Barnby be81c73c40 Update DB 2025-09-11 21:30:07 +12:00
Damodar Lohani 72f5793928 revert date format 2025-09-11 09:18:23 +00:00
Jake Barnby e6c83f364c Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-09-11 21:17:50 +12:00
Jake Barnby 8706828c22 Fix tests 2025-09-11 21:13:41 +12:00
Damodar LohaniandGitHub b8e3a19586 Merge branch '1.8.x' into feat-apps-module-dl 2025-09-11 14:47:14 +05:45
Damodar Lohani e36de6b72b revert date format 2025-09-11 08:59:27 +00:00
Damodar Lohani bcec5c0922 revert date format 2025-09-11 08:57:27 +00:00
Damodar Lohani 72186f1882 reset det change 2025-09-11 08:46:38 +00:00
Damodar Lohani e4d70a4d4f Fix: default options 2025-09-11 07:55:52 +00:00
fogelito e673d405d6 formatting? 2025-09-11 10:14:16 +03:00
fogelito 84aaaf810f Question 2025-09-11 10:07:45 +03:00
fogelito 5740eb8901 Add sorting 2025-09-11 10:04:42 +03:00
Damodar Lohani 6d19d76bac Fix scope check 2025-09-11 06:51:01 +00:00
fogelito a31190422a formatting 2025-09-11 09:41:17 +03:00
Damodar Lohani 55bebd92f3 Fix date format 2025-09-11 06:27:58 +00:00
Damodar LohaniandGitHub 0d4df67958 Merge branch '1.8.x' into feat-apps-module-dl 2025-09-11 11:59:31 +05:45
Jake Barnby 498484ca4e Legacy DB support 2025-09-11 17:54:55 +12:00
Jake Barnby f9b92ddead Fix namespace 2025-09-11 16:37:43 +12:00
Jake Barnby 461c8681af Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
#	src/Appwrite/Platform/Workers/StatsResources.php
2025-09-11 16:36:49 +12:00
Jake Barnby 28a2b577e7 Update lock 2025-09-11 16:36:09 +12:00
fogelito 6ed4590e0f Respect time nulls 2025-09-10 18:04:35 +03:00
fogelito b44051e0a2 Respect time nulls 2025-09-10 17:48:58 +03:00
fogelito 494fe274b0 sort as strings 2025-09-10 17:43:37 +03:00
fogelito 5820bae097 Merge branch '1.8.x' of https://github.com/appwrite/appwrite into stats-resources-try-catch 2025-09-10 17:24:49 +03:00
fogelito de9e177bc8 sort and hardcode bachSize 2025-09-10 17:23:33 +03:00
fogelito 95f49559d0 add finally 2025-09-10 12:43:37 +03:00
Damodar Lohani 356fbed325 fix password update 2025-09-10 09:09:12 +00:00
Damodar Lohani 4578819a58 revert test update 2025-09-10 07:59:00 +00:00
Damodar Lohani 6099313cb4 Fxi teams tests 2025-09-10 07:57:45 +00:00
Damodar Lohani 487663f892 fixed attribute 2025-09-10 07:30:22 +00:00
Damodar LohaniandGitHub d8e769ef1f Merge branch '1.8.x' into feat-apps-module-dl 2025-09-10 12:48:44 +05:45
Damodar Lohani 41dbe1a384 Fix internal ID refactor 2025-09-10 07:03:11 +00:00
Damodar Lohani 631c00023e update lock 2025-09-10 04:38:14 +00:00
Damodar Lohani 4478edc211 fix linter 2025-09-10 04:25:21 +00:00
Damodar Lohani 2be8895dfd Merge remote-tracking branch 'origin/1.8.x' into feat-apps-module-dl 2025-09-10 03:56:34 +00:00
Jake Barnby 78ffab5116 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
#	src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php
2025-09-09 00:52:39 +12:00
Jake Barnby 495eeeb929 Support legacy 2025-09-09 00:50:48 +12:00
Jake Barnby 7c3ba74710 Rename 2025-09-08 19:21:59 +12:00
Jake Barnby abf6c0a0b8 Add more bulk tests 2025-09-08 19:20:26 +12:00
Jake Barnby 812a09f556 Add read-your-write support 2025-09-06 04:26:49 +12:00
Jake Barnby 098b0cd028 Fix array as doc 2025-09-06 02:37:52 +12:00
Jake Barnby 391942ba72 Fix bulk logged queries 2025-09-06 02:37:17 +12:00
Jake Barnby f4bf1756c9 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-09-05 21:40:21 +12:00
Matej BačoandGitHub a703fcc8e9 Merge pull request #10440 from Veera-mulge/change-desc
Update README.md
2025-09-04 17:21:24 +02:00
VeereshandGitHub 01586653a1 Update README.md 2025-09-04 20:36:03 +05:30
Jake Barnby 3d5caaa0bb Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-09-05 01:05:44 +12:00
Jake Barnby c2916c7a2d Lint 2025-09-05 01:04:48 +12:00
Jake Barnby d28643bd2b Update DB 2025-09-05 01:02:30 +12:00
Eldad A. FuxandGitHub c02574b057 Merge pull request #10430 from appwrite/chore-github-issue-auto-label
chore: create workflow to auto add labels to issues
2025-09-04 11:43:02 +01:00
Jake Barnby 7eba6582c6 Fix bulk payloads 2025-09-04 20:32:37 +12:00
Steven NguyenandGitHub ba97cfb440 chore: create workflow to auto add labels to issues 2025-09-03 23:14:37 +00:00
Jake Barnby 5702def9d2 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
#	src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php
#	tests/e2e/Services/Databases/Legacy/DatabasesBase.php
2025-09-04 04:00:57 +12:00
Jake Barnby de5df4b72e Add extra tests 2025-09-04 03:57:03 +12:00
Matej BačoandGitHub 1d0fc635c1 Merge pull request #10424 from Veera-mulge/change-desc
Update README.md
2025-09-03 17:31:09 +02:00
VeereshandGitHub 5eb7c3a7c8 Update README.md 2025-09-03 19:18:25 +05:30
Jake Barnby 903e9b52c2 Fix size limit exception 2025-09-03 23:54:21 +12:00
Jake Barnby 00f91c444c Fix tests 2025-09-03 04:55:31 +12:00
Jake Barnby c34efeff1e Add to the other workflow 2025-09-03 04:37:48 +12:00
Jake Barnby 76287beca0 Format 2025-09-03 04:36:34 +12:00
Jake Barnby 1d8d757960 Add txn to workflow 2025-09-03 04:32:59 +12:00
Jake Barnby 2202dc9747 Handle intra-transactional ops with state tracking 2025-09-03 04:29:42 +12:00
Jake Barnby 5528e9964b Updates tests 2025-09-03 03:53:08 +12:00
Jake Barnby 04a9ff9c23 Ensure ID on create doc op 2025-09-03 03:42:56 +12:00
Jake Barnby 7861ee8cbd Add transaction scopes to test keys 2025-09-03 03:42:44 +12:00
Jake Barnby 70ef7059c3 Add increment validation 2025-09-03 03:42:19 +12:00
Jake Barnby 3f0ad7f6c7 Update registry 2025-09-03 03:41:53 +12:00
Jake Barnby c9cf38d630 Add expired log deletion 2025-09-03 01:31:53 +12:00
Jake Barnby f836fbeba5 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php
#	src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php
#	src/Appwrite/Utopia/Response.php
2025-09-02 23:31:47 +12:00
Jake Barnby 14002dc20d Remove invalid return 2025-08-18 17:37:16 +12:00
Jake Barnby 8579a01cfc Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.lock
2025-08-16 00:07:42 +12:00
Jake Barnby 237263a194 Lint 2025-08-15 02:01:44 +12:00
Jake Barnby ef8d1b525d Fix missing grids injections 2025-08-15 01:54:45 +12:00
Jake Barnby 4b4969e79b Sync response 2025-08-15 01:40:08 +12:00
Jake Barnby 44daaae981 Update deps 2025-08-15 01:33:44 +12:00
Jake Barnby d444bb66b8 Truemaps for fast lookup 2025-08-15 01:33:35 +12:00
Jake Barnby 2b3795224d Check for documentId on ops that require it 2025-08-15 01:33:22 +12:00
Jake Barnby 46f8d76d7a Fix defualts for bulk op add 2025-08-15 01:32:21 +12:00
Jake Barnby ad8cebc6e3 Ensure updated txn is returned from bulk op add 2025-08-15 01:32:09 +12:00
Jake Barnby bed46be720 Add grids params 2025-08-15 01:05:03 +12:00
Jake Barnby 0533568f9e Fix test 2025-08-15 01:03:46 +12:00
Jake Barnby 56d7716ddb Require data param for ops 2025-08-15 01:03:36 +12:00
Jake Barnby e9c730e0c1 Add txn id to create multi-method params 2025-08-15 01:03:18 +12:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
875338d133 Update src/Appwrite/Utopia/Database/Validator/Queries/Transactions.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-08-15 00:48:56 +12:00
Jake BarnbyGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2a5ab1f8aa Update src/Appwrite/Utopia/Database/Validator/Queries/Transactions.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-08-15 00:48:37 +12:00
Jake Barnby 6e6364638d Add missing validator ops 2025-08-15 00:37:39 +12:00
Jake Barnby dfeadfd50f Update naming 2025-08-15 00:37:29 +12:00
Jake Barnby 9838571184 Catch explicit txn exception 2025-08-15 00:37:18 +12:00
Jake Barnby 5cd99de6e4 Remove redundant read 2025-08-15 00:36:59 +12:00
Jake Barnby fb31fbea9b Ensure parsed queries 2025-08-15 00:36:42 +12:00
Jake Barnby d6544f412d Add missing bulk cases on commit 2025-08-15 00:36:26 +12:00
Jake Barnby 3a7d8d2296 Remove redundant order 2025-08-15 00:35:41 +12:00
Jake Barnby 84bf2641aa Fix scope 2025-08-15 00:35:20 +12:00
Jake Barnby ede88a533e Handle create single/bulk split 2025-08-15 00:35:06 +12:00
Jake Barnby 3d1ae4feda Process permissions before txn logging 2025-08-15 00:34:20 +12:00
Jake Barnby 2235848262 Clear txn logs on worker 2025-08-15 00:32:03 +12:00
Jake Barnby 76034f801b Add failed error 2025-08-15 00:31:27 +12:00
Jake BarnbyandGitHub 2dd8dd8edc Merge pull request #10319 from appwrite/cursor/enforce-operations-cap-per-transaction-6dd5
Enforce operations cap per transaction
2025-08-14 22:23:56 +12:00
Jake Barnby c8afcbccee Fix create inject 2025-08-14 22:22:12 +12:00
Jake Barnby ef63d421b3 Merge branch 'feat-txn' into cursor/enforce-operations-cap-per-transaction-6dd5 2025-08-14 22:21:06 +12:00
Jake Barnby ba25f9f8d5 Merge branch 'feat-txn' of github.com:appwrite/appwrite into feat-txn 2025-08-14 22:20:57 +12:00
Jake Barnby 31a7df7214 Import fixes 2025-08-14 22:20:30 +12:00
Cursor Agentandjakeb994 335052bc84 Remove unused function and webhook event queue injections in database actions
Co-authored-by: jakeb994 <jakeb994@gmail.com>
2025-08-14 10:17:54 +00:00
Cursor Agentandjakeb994 dffe030d16 Replace databasesBatchSize with databasesTransactionSize in database operations
Co-authored-by: jakeb994 <jakeb994@gmail.com>
2025-08-14 10:06:43 +00:00
Cursor Agentandjakeb994 6d477688d7 Enforce max operations per transaction in database operations
Co-authored-by: jakeb994 <jakeb994@gmail.com>
2025-08-14 09:50:45 +00:00
Jake Barnby 1da2812864 Merge remote-tracking branch 'origin/1.8.x' into feat-txn 2025-08-14 21:44:05 +12:00
Jake BarnbyandGitHub 7ca9754ebf Merge pull request #10305 from appwrite/cursor/replay-database-transaction-logs-sequentially-d222
Replay database transaction logs sequentially
2025-08-13 01:37:20 +12:00
Cursor Agentandjakeb994 a71333ac60 Refactor transaction replay to preserve exact order and timestamps
Co-authored-by: jakeb994 <jakeb994@gmail.com>
2025-08-12 12:00:28 +00:00
Jake Barnby 5cec34b802 Fix merge 2025-08-12 00:45:30 +12:00
Jake BarnbyandGitHub 8d648a43c2 Merge pull request #10295 from appwrite/cursor/restore-database-transaction-functionality-439c
Restore database transaction functionality
2025-08-12 00:39:25 +12:00
Cursor Agentandjakeb994 5886c53ce3 Add transaction staging support for document operations
Co-authored-by: jakeb994 <jakeb994@gmail.com>
2025-08-11 08:43:30 +00:00
Cursor Agentandjakeb994 480f8c97ca Add transaction support for databases with staging and commit/rollback
Co-authored-by: jakeb994 <jakeb994@gmail.com>
2025-08-11 08:25:58 +00:00
Jake Barnby cbf210b9e6 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	composer.json
#	composer.lock
#	tests/e2e/Services/Databases/Legacy/DatabasesBase.php
2025-08-11 20:06:40 +12:00
Jake Barnby 93cc4e1df8 Merge remote-tracking branch 'origin/1.8.x' into feat-txn
# Conflicts:
#	app/config/errors.php
#	app/config/roles.php
#	app/controllers/api/databases.php
#	composer.json
#	composer.lock
#	src/Appwrite/Extend/Exception.php
#	src/Appwrite/Utopia/Response.php
#	tests/e2e/Services/Databases/Legacy/DatabasesBase.php
2025-07-29 22:16:56 +12:00
Jake Barnby 07cce5ad3c Optional param 2025-07-29 21:30:02 +12:00
Christy Jacob b5c5f76acc Merge branch '1.7.x' of github.com:appwrite/appwrite into feat-apps-module 2025-06-20 17:39:28 +04:00
Jake Barnby 2745d8dce7 Add single op counting 2025-06-18 19:51:37 -04:00
Jake Barnby ac32947908 Update db 2025-06-18 19:17:47 -04:00
Jake Barnby b471bd0f58 Add operations to response model 2025-06-18 16:53:47 -04:00
Jake Barnby 910f27016b Add operation to txn meta 2025-06-17 22:08:08 -04:00
Jake Barnby 75469eed7d Fix staged values 2025-06-17 21:55:38 -04:00
Jake Barnby 5d5a6fbc5d Add delete transaction 2025-06-17 21:55:08 -04:00
Jake Barnby aba75abc93 Update params 2025-06-17 21:54:40 -04:00
Jake Barnby 1e82c7f0ef Add listTransactions 2025-06-17 21:54:30 -04:00
Jake Barnby 0b00ce28e0 Remove redundant attributes 2025-06-17 19:37:53 -04:00
Jake Barnby 145cb54bc0 Separate bulk 2025-06-17 16:58:25 -04:00
Jake Barnby bd9d827a16 Add tests 2025-06-17 16:54:32 -04:00
Jake Barnby 4da95f765b Don't require data 2025-06-17 16:45:14 -04:00
Jake Barnby d13081b4f2 Use const 2025-06-17 16:45:07 -04:00
Jake Barnby b71688a587 Format 2025-06-17 16:07:14 -04:00
Jake Barnby 14c0d27019 Merge remote-tracking branch 'origin/1.8.x' into feat-txn 2025-06-17 16:04:05 -04:00
Jake Barnby 705e5dd45b Add txn support to existing routes 2025-06-17 16:03:58 -04:00
Jake Barnby 4e2727292e Add txn routes 2025-06-17 16:03:33 -04:00
Jake Barnby cfc6d5fe2b Add txn collections 2025-06-17 16:02:32 -04:00
Jake Barnby c11fd38f0f Add txn models 2025-06-17 16:02:17 -04:00
Jake Barnby 11ce394181 Add txn errors 2025-06-17 16:01:56 -04:00
Jake Barnby fc4b82d017 Add txn scopes 2025-06-17 16:01:45 -04:00
Jake Barnby b556846be3 Add txn roles 2025-06-17 16:01:39 -04:00
DarshanandGitHub 598165c0e7 Merge branch 'main' into fix-zindex 2025-05-23 22:20:57 +05:30
DarshanandGitHub d08e406e9e Merge branch 'main' into fix-zindex 2025-05-23 19:25:51 +05:30
Darshan fc8326417b update: z-index to be the highest! 2025-05-23 19:20:26 +05:30
Eldad Fux 6f861a91ee Updated auth lib 2025-04-29 21:33:59 +02:00
Eldad Fux 0483c7efb5 Merge fixes 2025-04-29 20:44:05 +02:00
Eldad Fux fb29fe7b3c Merge remote-tracking branch 'origin/1.7.x' into feat-apps-module 2025-04-29 20:12:31 +02:00
Eldad Fux 1bf1766822 Merge remote-tracking branch 'origin/feat-sites' into feat-apps-module 2025-03-28 08:20:24 +01:00
Eldad Fux 57edb4a385 Removed leftovers 2025-03-28 08:17:47 +01:00
Eldad Fux 17c555ab6c Expanded the identities collection 2025-03-28 02:13:17 +01:00
Eldad Fux d6bd72cfd3 formatting 2025-03-19 14:10:56 +01:00
Eldad Fux 8c9123beaa Fixed tests 2025-03-19 13:54:32 +01:00
Eldad Fux 3d967e695f Updated auth lib 2025-03-19 07:57:28 +01:00
Eldad Fux a7d7e39dfd Fixed tests 2025-03-18 22:47:17 +01:00
Eldad Fux 38cb95e940 Fixed tests 2025-03-18 22:28:19 +01:00
Eldad Fux b2b20c48b3 Fixed tests 2025-03-18 22:12:03 +01:00
Eldad Fux fed6579491 Update teams tests 2025-03-18 21:52:41 +01:00
Eldad Fux 8cb85cafbd Fixes realtime tests 2025-03-18 20:24:38 +01:00
Eldad Fux 55e560bb41 Fixed unit tests 2025-03-18 19:08:58 +01:00
Eldad Fux dd9a40221e Merge remote-tracking branch 'origin/feat-sites' into feat-apps-module 2025-03-18 17:38:32 +01:00
Eldad Fux 24300cd3bd tests 2025-03-18 17:22:58 +01:00
Eldad Fux 4d5961c3ab Fixed test 2025-03-18 16:20:37 +01:00
Eldad Fux afb40218d7 Fixed tests 2025-03-18 16:12:13 +01:00
Eldad Fux 3daa3821ef Fixed syntax error 2025-03-18 10:24:42 +01:00
Eldad Fux 84cec0e32c format 2025-03-18 10:18:29 +01:00
Eldad Fux 7bae15d4fe Merge remote-tracking branch 'origin/feat-sites' into feat-apps-module 2025-03-18 10:15:06 +01:00
Eldad Fux 0180f72067 Removed unsed methods and tests 2025-03-18 00:30:31 +01:00
Eldad Fux f537091eb2 Fixed tests 2025-03-17 23:57:44 +01:00
Eldad Fux c99c83a006 Merge remote-tracking branch 'origin/feat-sites' into feat-apps-module 2025-03-17 23:15:57 +01:00
Eldad Fux 113828cd00 Improved errors 2025-03-17 22:51:22 +01:00
Eldad Fux 477add3022 Formatting 2025-03-17 21:49:10 +01:00
Eldad Fux 8aa5714173 cleanups 2025-03-17 21:44:31 +01:00
Eldad Fux fdb83c51f7 formatting 2025-03-17 12:46:07 +01:00
Eldad Fux c15739bba7 Merge remote-tracking branch 'origin/feat-sites' into feat-apps-module 2025-03-17 12:44:49 +01:00
Eldad Fux 1ce84f1650 WIP 2025-03-17 12:39:35 +01:00
Eldad Fux f618a8b563 Fixed account test 2025-03-16 22:16:02 +01:00
Eldad Fux 9346efc24a Fixed some tests 2025-03-16 19:35:42 +01:00
Eldad Fux a5e57a9a67 Work in progress, moving to instance based auth 2025-03-16 18:54:55 +01:00
Eldad Fux cc724218b0 fixed formatting 2025-03-16 18:32:46 +01:00
Eldad Fux 706ce4b3b6 WIP - cleaning up auth managment 2025-03-16 18:30:48 +01:00
Eldad Fux c08355df8d Updated composer 2025-03-16 10:34:45 +01:00
Eldad Fux 2d5904e3d0 Merge remote-tracking branch 'origin/feat-sites' into feat-apps-module 2025-03-16 10:26:55 +01:00
Eldad Fux d1318cf016 Updated dependencies 2025-03-10 02:19:57 +01:00
Eldad Fux 91921859a2 Merge remote-tracking branch 'origin/1.6.x' into feat-apps-module 2025-03-10 02:14:35 +01:00
Eldad Fux a058925252 Code formatting 2025-03-10 00:23:22 +01:00
Eldad Fux fadb24f295 revert change to build 2025-03-10 00:21:49 +01:00
Eldad Fux 748119334d Merge remote-tracking branch 'origin/feat-sites' into feat-apps-module 2025-03-10 00:18:23 +01:00
Eldad Fux cb05b87dda Upgraded users to use utopia/auth 2025-03-10 00:08:04 +01:00
Eldad Fux aa36d944db Add teamId to project array in e2e test 2025-03-01 22:00:37 +01:00
1079 changed files with 44940 additions and 5212 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
> We just announced Timestamp Overrides for Appwrite Databases - [Learn more](https://appwrite.io/blog/post/announcing-timestamp-overrides)
> We just announced Transactions API for Appwrite Databases - [Learn more](https://appwrite.io/blog/post/announcing-transactions-api)
> Appwrite Cloud is now Generally Available - [Learn more](https://appwrite.io/cloud-ga)
+5
View File
@@ -103,6 +103,11 @@ CLI::setResource('console', function () {
return new Document(Config::getParam('console'));
}, []);
CLI::setResource(
'isResourceBlocked',
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
);
CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) {
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
+3 -4
View File
@@ -1,6 +1,5 @@
<?php
use Appwrite\Auth\Auth;
use Utopia\Database\Database;
use Utopia\Database\Helpers\ID;
@@ -173,7 +172,7 @@ return [
'size' => 256,
'signed' => true,
'required' => false,
'default' => Auth::DEFAULT_ALGO,
'default' => 'argon2',
'array' => false,
'filters' => [],
],
@@ -184,7 +183,7 @@ return [
'size' => 65535,
'signed' => true,
'required' => false,
'default' => Auth::DEFAULT_ALGO_OPTIONS,
'default' => ['type' => 'argon2', 'memoryCost' => 2048, 'timeCost' => 4, 'threads' => 3],
'array' => false,
'filters' => ['json'],
],
@@ -1115,9 +1114,9 @@ return [
[
'$id' => ID::custom('expire'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'required' => false,
'format' => '',
'signed' => false,
'default' => null,
'array' => false,
+124
View File
@@ -2521,4 +2521,128 @@ return [
],
],
],
'transactions' => [
'$collection' => ID::custom(Database::METADATA),
'$id' => ID::custom('transactions'),
'name' => 'Transactions',
'attributes' => [
[
'$id' => ID::custom('status'),
'type' => Database::VAR_STRING,
'size' => 16, // pending | committing | committed | failed
'signed' => true,
'required' => false,
'default' => 'pending',
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('operations'),
'type' => Database::VAR_INTEGER,
'size' => 0,
'signed' => false,
'required' => true,
'default' => 0,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('expiresAt'),
'type' => Database::VAR_DATETIME,
'size' => 0,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
],
'indexes' => [
[
'$id' => ID::custom('_key_expiresAt'),
'type' => Database::INDEX_KEY,
'attributes' => ['expiresAt'],
'lengths' => [],
'orders' => [Database::ORDER_DESC],
],
],
],
'transactionLogs' => [
'$collection' => ID::custom(Database::METADATA),
'$id' => ID::custom('transactionLogs'),
'name' => 'Transaction Logs',
'attributes' => [
[
'$id' => ID::custom('transactionInternalId'),
'type' => Database::VAR_STRING,
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('databaseInternalId'),
'type' => Database::VAR_STRING,
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('collectionInternalId'),
'type' => Database::VAR_STRING,
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('documentId'),
'type' => Database::VAR_STRING,
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('action'),
'type' => Database::VAR_STRING,
'size' => 32, // create | update | upsert | increment | decrement | delete | bulkCreate | bulkUpdate | bulkUpsert | bulkDelete
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('data'),
'type' => Database::VAR_STRING,
'size' => 5_000_000, // Allow large payloads for bulk operations
'signed' => false,
'required' => true,
'default' => null,
'array' => false,
'filters' => ['json'],
],
],
'indexes' => [
[
'$id' => ID::custom('_key_transaction'),
'type' => Database::INDEX_KEY,
'attributes' => ['transactionInternalId'],
'lengths' => [],
'orders' => [],
],
],
],
];
+2 -2
View File
@@ -4,7 +4,6 @@
* Initializes console project document.
*/
use Appwrite\Auth\Auth;
use Appwrite\Network\Platform;
use Utopia\Database\Helpers\ID;
use Utopia\System\System;
@@ -38,7 +37,7 @@ $console = [
'mockNumbers' => [],
'invites' => System::getEnv('_APP_CONSOLE_INVITES', 'enabled') === 'enabled',
'limit' => (System::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user
'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, // 1 Year in seconds
'duration' => TOKEN_EXPIRATION_LOGIN_LONG, // 1 Year in seconds
'sessionAlerts' => System::getEnv('_APP_CONSOLE_SESSION_ALERTS', 'disabled') === 'enabled',
'invalidateSessions' => true
],
@@ -49,6 +48,7 @@ $console = [
'githubSecret' => System::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''),
'githubAppid' => System::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '')
],
'smtpBaseTemplate' => APP_BRANDED_EMAIL_BASE_TEMPLATE,
];
return $console;
+62
View File
@@ -211,6 +211,11 @@ return [
'description' => 'User with the requested ID could not be found.',
'code' => 404,
],
Exception::USER_EMAIL_NOT_FOUND => [
'name' => Exception::USER_EMAIL_NOT_FOUND,
'description' => 'User email could not be found.',
'code' => 400,
],
Exception::USER_EMAIL_ALREADY_EXISTS => [
'name' => Exception::USER_EMAIL_ALREADY_EXISTS,
'description' => 'A user with the same email already exists in the current project.',
@@ -312,11 +317,21 @@ return [
'description' => 'OAuth2 provider returned some error.',
'code' => 424,
],
Exception::USER_EMAIL_NOT_VERIFIED => [
'name' => Exception::USER_EMAIL_NOT_VERIFIED,
'description' => 'User email is not verified',
'code' => 400,
],
Exception::USER_EMAIL_ALREADY_VERIFIED => [
'name' => Exception::USER_EMAIL_ALREADY_VERIFIED,
'description' => 'User email is already verified',
'code' => 409,
],
Exception::USER_PHONE_NOT_VERIFIED => [
'name' => Exception::USER_PHONE_NOT_VERIFIED,
'description' => 'User phone is not verified',
'code' => 400,
],
Exception::USER_PHONE_ALREADY_VERIFIED => [
'name' => Exception::USER_PHONE_ALREADY_VERIFIED,
'description' => 'User phone is already verified',
@@ -563,6 +578,11 @@ return [
'description' => 'The requested runtime is either inactive or unsupported. Please check the value of the _APP_FUNCTIONS_RUNTIMES environment variable.',
'code' => 404,
],
Exception::FUNCTION_ALREADY_EXISTS => [
'name' => Exception::FUNCTION_ALREADY_EXISTS,
'description' => 'Function with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.',
'code' => 409,
],
Exception::FUNCTION_ENTRYPOINT_MISSING => [
'name' => Exception::FUNCTION_ENTRYPOINT_MISSING,
'description' => 'Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function\'s "Settings" > "Configuration" > "Entrypoint".',
@@ -966,6 +986,48 @@ return [
'code' => 409,
],
/** Transactions */
Exception::TRANSACTION_NOT_FOUND => [
'name' => Exception::TRANSACTION_NOT_FOUND,
'description' => 'Transaction with the requested ID could not be found.',
'code' => 404,
],
Exception::TRANSACTION_ALREADY_EXISTS => [
'name' => Exception::TRANSACTION_ALREADY_EXISTS,
'description' => 'Transaction with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.',
'code' => 409,
],
Exception::TRANSACTION_INVALID => [
'name' => Exception::TRANSACTION_INVALID,
'description' => 'The transaction is invalid. Please check the transaction state and try again.',
'code' => 400,
],
Exception::TRANSACTION_FAILED => [
'name' => Exception::TRANSACTION_FAILED,
'description' => 'The transaction has errored. Please check the transaction data and try again.',
'code' => 400,
],
Exception::TRANSACTION_EXPIRED => [
'name' => Exception::TRANSACTION_EXPIRED,
'description' => 'The transaction has expired. Please create a new transaction and try again.',
'code' => 410,
],
Exception::TRANSACTION_CONFLICT => [
'name' => Exception::TRANSACTION_CONFLICT,
'description' => 'The transaction has a conflict. Please resolve the conflict and try again.',
'code' => 409,
],
Exception::TRANSACTION_LIMIT_EXCEEDED => [
'name' => Exception::TRANSACTION_LIMIT_EXCEEDED,
'description' => 'The maximum number of operations per transaction has been exceeded.',
'code' => 400,
],
Exception::TRANSACTION_NOT_READY => [
'name' => Exception::TRANSACTION_NOT_READY,
'description' => 'The transaction is not ready yet. Please try again later.',
'code' => 400,
],
/** Project Errors */
Exception::PROJECT_NOT_FOUND => [
'name' => Exception::PROJECT_NOT_FOUND,
@@ -131,6 +131,14 @@
.social-icon > img {
margin: auto;
}
p.security-phrase:not(:empty) {
opacity: 0.7;
margin: 0;
padding: 0;
margin-top: 32px;
padding-top: 32px;
border-top: 1px solid #e8e9f0;
}
</style>
</head>
@@ -147,6 +155,7 @@
<img
height="32px"
src="{{logoUrl}}"
alt="Appwrite logo"
/>
</td>
</tr>
@@ -155,12 +164,12 @@
<table style="margin-top: 32px">
<tr>
<td>
<h1>{{subject}}</h1>
<h1>{{heading}}</h1>
</td>
</tr>
</table>
<table style="margin-top: 32px">
<table style="margin-top: 16px">
<tr>
<td>
{{body}}
+21 -1
View File
@@ -44,6 +44,21 @@
color: currentColor;
word-break: break-all;
}
a.button {
box-sizing: border-box;
display: inline-block;
text-align: center;
text-decoration: none;
padding: 9px 14px;
color: #ffffff;
background-color: #2D2D31;
border: 1px solid #414146;
border-radius: 8px;
}
a.button:hover,
a.button:focus {
opacity: 0.8;
}
table {
width: 100%;
border-spacing: 0 !important;
@@ -94,10 +109,15 @@
h* {
font-family: 'Poppins', sans-serif;
}
p {
margin-bottom: 10px;
}
p.security-phrase:not(:empty) {
opacity: 0.7;
margin-top: 32px;
padding-top: 32px;
border-top: 1px solid #e8e9f0;
}
</style>
</head>
@@ -1,6 +1,6 @@
<p>{{hello}}</p>
<p>{{body}}</p>
<p><a href="{{redirect}}" target="_blank" style="font-size: 14px; font-family: Inter, sans-serif; color: #ffffff; text-decoration: none; background-color: #2D2D31; border-radius: 8px; padding: 9px 14px; border: 1px solid #414146; display: inline-block; text-align:center; box-sizing: border-box;">{{buttonText}}</a></p>
<p><a href="{{redirect}}" target="_blank" class="button">{{buttonText}}</a></p>
<p>{{footer}}</p>
<p style="margin-bottom: 32px">
{{thanks}}
@@ -5,7 +5,7 @@
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; display: inline-block;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #19191D;">
<a rel="noopener" target="_blank" href="{{redirect}}" style="font-size: 14px; font-family: Inter; color: #ffffff; text-decoration: none; border-radius: 8px; padding: 9px 14px; border: 1px solid #19191D; display: inline-block;">{{buttonText}}</a>
<a rel="noopener" target="_blank" href="{{redirect}}" class="button">{{buttonText}}</a>
</td>
</tr>
</table>
@@ -5,7 +5,7 @@
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; display: inline-block;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #ffffff;">
<p style="font-size: 24px; text-indent: 18px; letter-spacing: 18px; font-family: 'Inter', sans-serif; color: #414146; text-decoration: none; border-radius: 8px; padding: 24px 12px; border: 1px solid #EDEDF0; display: inline-block; font-weight: bold; ">{{otp}}</p>
<p style="font-size: 24px; text-indent: 18px; letter-spacing: 18px; font-family: 'Inter', sans-serif; color: #414146; text-decoration: none; border-radius: 8px; margin-top: 0px; margin-bottom: 0px; padding: 24px 12px; border: 1px solid #EDEDF0; display: inline-block; font-weight: bold;">{{otp}}</p>
</td>
</tr>
</table>
+2 -4
View File
@@ -5,7 +5,7 @@
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; display: inline-block;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #ffffff;">
<p style="font-size: 24px; text-indent: 18px; letter-spacing: 18px; font-family: Inter; color: #414146; text-decoration: none; border-radius: 8px; padding: 24px 12px; border: 1px solid #EDEDF0; display: inline-block; font-weight: bold; ">{{otp}}</p>
<p style="font-size: 24px; text-indent: 18px; letter-spacing: 18px; font-family: 'Inter', sans-serif; color: #414146; text-decoration: none; border-radius: 8px; margin-top: 0px; margin-bottom: 0px; padding: 24px 12px; border: 1px solid #EDEDF0; display: inline-block; font-weight: bold; ">{{otp}}</p>
</td>
</tr>
</table>
@@ -15,6 +15,4 @@
<p style="margin-bottom: 0px;">{{thanks}}</p>
<p style="margin-top: 0px;">{{signature}}</p>
<hr style="margin-block-start: 1rem; margin-block-end: 1rem;">
<p style="opacity: 0.7;">{{securityPhrase}}</p>
<p class="security-phrase">{{securityPhrase}}</p>
+5 -2
View File
@@ -3,8 +3,9 @@
"settings.locale": "en",
"settings.direction": "ltr",
"emails.sender": "{{project}} Team",
"emails.verification.subject": "Account Verification",
"emails.verification.subject": "Account Verification for {{project}}",
"emails.verification.preview": "Verify your email to activate your {{project}} account.",
"emails.verification.heading": "Verify your email to start using {{project}}",
"emails.verification.hello": "Hello {{user}},",
"emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.",
"emails.verification.footer": "If you didnt ask to verify this address, you can ignore this message.",
@@ -33,6 +34,7 @@
"emails.sessionAlert.signature": "{{project}} team",
"emails.otpSession.subject": "OTP for {{project}} Login",
"emails.otpSession.preview": "Use OTP {{otp}} to sign in to {{project}}. Expires in 15 minutes.",
"emails.otpSession.heading": "Login with OTP to use {{project}}",
"emails.otpSession.hello": "Hello {{user}},",
"emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.",
"emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.",
@@ -41,12 +43,13 @@
"emails.otpSession.signature": "{{project}} team",
"emails.mfaChallenge.subject": "Verification Code for {{project}}",
"emails.mfaChallenge.preview": "Use code {{otp}} for two-step verification in {{project}}. Expires in 15 minutes.",
"emails.mfaChallenge.heading": "Complete two-step verification to use {{project}}",
"emails.mfaChallenge.hello": "Hello {{user}},",
"emails.mfaChallenge.description": "Enter the following code to confirm your two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.",
"emails.mfaChallenge.clientInfo": "This verification code was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the verification code, you can safely ignore this email.",
"emails.mfaChallenge.thanks": "Thanks,",
"emails.mfaChallenge.signature": "{{project}} team",
"emails.recovery.subject": "Password Reset",
"emails.recovery.subject": "Password Reset for {{project}}",
"emails.recovery.preview": "Reset your {{project}} password using the link.",
"emails.recovery.hello": "Hello {{user}},",
"emails.recovery.body": "Follow this link to reset your {{b}}{{project}}{{/b}} password.",
+16 -16
View File
@@ -11,7 +11,7 @@ return [
[
'key' => 'web',
'name' => 'Web',
'version' => '20.0.0',
'version' => '21.2.1',
'url' => 'https://github.com/appwrite/sdk-for-web',
'package' => 'https://www.npmjs.com/package/appwrite',
'enabled' => true,
@@ -60,7 +60,7 @@ return [
[
'key' => 'flutter',
'name' => 'Flutter',
'version' => '19.0.0',
'version' => '20.2.1',
'url' => 'https://github.com/appwrite/sdk-for-flutter',
'package' => 'https://pub.dev/packages/appwrite',
'enabled' => true,
@@ -79,7 +79,7 @@ return [
[
'key' => 'apple',
'name' => 'Apple',
'version' => '12.0.0',
'version' => '13.2.2',
'url' => 'https://github.com/appwrite/sdk-for-apple',
'package' => 'https://github.com/appwrite/sdk-for-apple',
'enabled' => true,
@@ -116,7 +116,7 @@ return [
[
'key' => 'android',
'name' => 'Android',
'version' => '10.0.0',
'version' => '11.2.1',
'url' => 'https://github.com/appwrite/sdk-for-android',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
'enabled' => true,
@@ -139,7 +139,7 @@ return [
[
'key' => 'react-native',
'name' => 'React Native',
'version' => '0.13.0',
'version' => '0.17.1',
'url' => 'https://github.com/appwrite/sdk-for-react-native',
'package' => 'https://npmjs.com/package/react-native-appwrite',
'enabled' => true,
@@ -207,7 +207,7 @@ return [
[
'key' => 'web',
'name' => 'Console',
'version' => '0.1.0',
'version' => '0.1.1',
'url' => '',
'package' => '',
'enabled' => true,
@@ -226,7 +226,7 @@ return [
[
'key' => 'cli',
'name' => 'Command Line',
'version' => '9.1.0',
'version' => '10.2.1',
'url' => 'https://github.com/appwrite/sdk-for-cli',
'package' => 'https://www.npmjs.com/package/appwrite-cli',
'enabled' => true,
@@ -262,7 +262,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '19.0.0',
'version' => '20.2.1',
'url' => 'https://github.com/appwrite/sdk-for-node',
'package' => 'https://www.npmjs.com/package/node-appwrite',
'enabled' => true,
@@ -281,7 +281,7 @@ return [
[
'key' => 'php',
'name' => 'PHP',
'version' => '17.0.0',
'version' => '17.4.1',
'url' => 'https://github.com/appwrite/sdk-for-php',
'package' => 'https://packagist.org/packages/appwrite/appwrite',
'enabled' => true,
@@ -300,7 +300,7 @@ return [
[
'key' => 'python',
'name' => 'Python',
'version' => '13.0.0',
'version' => '13.4.1',
'url' => 'https://github.com/appwrite/sdk-for-python',
'package' => 'https://pypi.org/project/appwrite/',
'enabled' => true,
@@ -319,7 +319,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '18.0.0',
'version' => '19.2.1',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'package' => 'https://rubygems.org/gems/appwrite',
'enabled' => true,
@@ -338,7 +338,7 @@ return [
[
'key' => 'go',
'name' => 'Go',
'version' => '0.11.0',
'version' => 'v0.13.1',
'url' => 'https://github.com/appwrite/sdk-for-go',
'package' => 'https://github.com/appwrite/sdk-for-go',
'enabled' => true,
@@ -357,7 +357,7 @@ return [
[
'key' => 'dotnet',
'name' => '.NET',
'version' => '0.17.0',
'version' => '0.21.2',
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
'package' => 'https://www.nuget.org/packages/Appwrite',
'enabled' => true,
@@ -376,7 +376,7 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '18.0.0',
'version' => '19.2.1',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'package' => 'https://pub.dev/packages/dart_appwrite',
'enabled' => true,
@@ -395,7 +395,7 @@ return [
[
'key' => 'kotlin',
'name' => 'Kotlin',
'version' => '11.0.0',
'version' => '12.2.1',
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
'enabled' => true,
@@ -418,7 +418,7 @@ return [
[
'key' => 'swift',
'name' => 'Swift',
'version' => '12.0.0',
'version' => '13.2.2',
'url' => 'https://github.com/appwrite/sdk-for-swift',
'package' => 'https://github.com/appwrite/sdk-for-swift',
'enabled' => true,
+7 -8
View File
@@ -1,6 +1,5 @@
<?php
use Appwrite\Auth\Auth;
$member = [
'global',
@@ -28,7 +27,7 @@ $member = [
'subscribers.write',
'subscribers.read',
'assistant.read',
'rules.read'
'rules.read',
];
$admins = [
@@ -92,7 +91,7 @@ $admins = [
];
return [
Auth::USER_ROLE_GUESTS => [
USER_ROLE_GUESTS => [
'label' => 'Guests',
'scopes' => [
'global',
@@ -112,23 +111,23 @@ return [
'execution.write',
],
],
Auth::USER_ROLE_USERS => [
USER_ROLE_USERS => [
'label' => 'Users',
'scopes' => \array_merge($member),
],
Auth::USER_ROLE_ADMIN => [
USER_ROLE_ADMIN => [
'label' => 'Admin',
'scopes' => \array_merge($admins),
],
Auth::USER_ROLE_DEVELOPER => [
USER_ROLE_DEVELOPER => [
'label' => 'Developer',
'scopes' => \array_merge($admins),
],
Auth::USER_ROLE_OWNER => [
USER_ROLE_OWNER => [
'label' => 'Owner',
'scopes' => \array_merge($member, $admins),
],
Auth::USER_ROLE_APPS => [
USER_ROLE_APPS => [
'label' => 'Applications',
'scopes' => ['global', 'health.read', 'graphql'],
],
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -3102,7 +3102,7 @@ App::post('/v1/messaging/messages/email')
case MessageStatus::SCHEDULED:
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceType' => SCHEDULE_RESOURCE_TYPE_MESSAGE,
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
@@ -3244,7 +3244,7 @@ App::post('/v1/messaging/messages/sms')
case MessageStatus::SCHEDULED:
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceType' => SCHEDULE_RESOURCE_TYPE_MESSAGE,
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
@@ -3462,7 +3462,7 @@ App::post('/v1/messaging/messages/push')
case MessageStatus::SCHEDULED:
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceType' => SCHEDULE_RESOURCE_TYPE_MESSAGE,
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
@@ -3863,7 +3863,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceType' => SCHEDULE_RESOURCE_TYPE_MESSAGE,
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
@@ -4084,7 +4084,7 @@ App::patch('/v1/messaging/messages/sms/:messageId')
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceType' => SCHEDULE_RESOURCE_TYPE_MESSAGE,
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
@@ -4258,7 +4258,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
$schedule = $dbForPlatform->createDocument('schedules', new Document([
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceType' => SCHEDULE_RESOURCE_TYPE_MESSAGE,
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
+23 -3
View File
@@ -1,7 +1,6 @@
<?php
use Ahc\Jwt\JWT;
use Appwrite\Auth\Auth;
use Appwrite\Auth\Validator\MockNumber;
use Appwrite\Event\Delete;
use Appwrite\Event\Mail;
@@ -118,7 +117,7 @@ App::post('/v1/projects')
'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT,
'passwordHistory' => 0,
'passwordDictionary' => false,
'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG,
'duration' => TOKEN_EXPIRATION_LOGIN_LONG,
'personalDataCheck' => false,
'mockNumbers' => [],
'sessionAlerts' => false,
@@ -1756,7 +1755,28 @@ App::post('/v1/projects/:projectId/platforms')
]
))
->param('projectId', '', new UID(), 'Project unique ID.')
->param('type', null, new WhiteList([Platform::TYPE_WEB, Platform::TYPE_FLUTTER_WEB, Platform::TYPE_FLUTTER_IOS, Platform::TYPE_FLUTTER_ANDROID, Platform::TYPE_FLUTTER_LINUX, Platform::TYPE_FLUTTER_MACOS, Platform::TYPE_FLUTTER_WINDOWS, Platform::TYPE_APPLE_IOS, Platform::TYPE_APPLE_MACOS, Platform::TYPE_APPLE_WATCHOS, Platform::TYPE_APPLE_TVOS, Platform::TYPE_ANDROID, Platform::TYPE_UNITY, Platform::TYPE_REACT_NATIVE_IOS, Platform::TYPE_REACT_NATIVE_ANDROID], true), 'Platform type.')
->param(
'type',
null,
new WhiteList([
Platform::TYPE_WEB,
Platform::TYPE_FLUTTER_WEB,
Platform::TYPE_FLUTTER_IOS,
Platform::TYPE_FLUTTER_ANDROID,
Platform::TYPE_FLUTTER_LINUX,
Platform::TYPE_FLUTTER_MACOS,
Platform::TYPE_FLUTTER_WINDOWS,
Platform::TYPE_APPLE_IOS,
Platform::TYPE_APPLE_MACOS,
Platform::TYPE_APPLE_WATCHOS,
Platform::TYPE_APPLE_TVOS,
Platform::TYPE_ANDROID,
Platform::TYPE_UNITY,
Platform::TYPE_REACT_NATIVE_IOS,
Platform::TYPE_REACT_NATIVE_ANDROID,
], true),
'Platform type. Possible values are: web, flutter-web, flutter-ios, flutter-android, flutter-linux, flutter-macos, flutter-windows, apple-ios, apple-macos, apple-watchos, apple-tvos, android, unity, react-native-ios, react-native-android.'
)
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
->param('key', '', new Text(256), 'Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.', true)
->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true)
+4
View File
@@ -225,6 +225,8 @@ App::get('/v1/storage/buckets')
$total = $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
$response->dynamic(new Document([
'buckets' => $buckets,
@@ -853,6 +855,8 @@ App::get('/v1/storage/buckets/:bucketId/files')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
} catch (OrderException $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
$response->dynamic(new Document([
+34 -22
View File
@@ -28,6 +28,9 @@ use MaxMind\Db\Reader;
use Utopia\Abuse\Abuse;
use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Auth\Proofs\Password;
use Utopia\Auth\Proofs\Token;
use Utopia\Auth\Store;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
@@ -471,10 +474,9 @@ App::post('/v1/teams/:teamId/memberships')
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('roles', [], function (Document $project) {
if ($project->getId() === 'console') {
;
$roles = array_keys(Config::getParam('roles', []));
array_filter($roles, function ($role) {
return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]);
$roles = array_filter($roles, function ($role) {
return !in_array($role, [USER_ROLE_APPS, USER_ROLE_GUESTS, USER_ROLE_USERS]);
});
return new ArrayList(new WhiteList($roles), APP_LIMIT_ARRAY_PARAMS_SIZE);
}
@@ -493,7 +495,9 @@ App::post('/v1/teams/:teamId/memberships')
->inject('timelimit')
->inject('queueForStatsUsage')
->inject('plan')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) {
->inject('proofForPassword')
->inject('proofForToken')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Password $proofForPassword, Token $proofForToken) {
$isAppUser = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
@@ -566,6 +570,7 @@ App::post('/v1/teams/:teamId/memberships')
try {
$userId = ID::unique();
$hash = $proofForPassword->hash($proofForPassword->generate());
$invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([
'$id' => $userId,
'$permissions' => [
@@ -579,9 +584,9 @@ App::post('/v1/teams/:teamId/memberships')
'emailVerification' => false,
'status' => true,
// TODO: Set password empty?
'password' => Auth::passwordHash(Auth::passwordGenerator(), Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS),
'hash' => Auth::DEFAULT_ALGO,
'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS,
'password' => $hash,
'hash' => $proofForPassword->getHash()->getName(),
'hashOptions' => $proofForPassword->getHash()->getOptions(),
/**
* Set the password update time to 0 for users created using
* team invite and OAuth to allow password updates without an
@@ -613,7 +618,7 @@ App::post('/v1/teams/:teamId/memberships')
Query::equal('teamInternalId', [$team->getSequence()]),
]);
$secret = Auth::tokenGenerator();
$secret = $proofForToken->generate();
if ($membership->isEmpty()) {
$membershipId = ID::unique();
$membership = new Document([
@@ -633,7 +638,7 @@ App::post('/v1/teams/:teamId/memberships')
'invited' => DateTime::now(),
'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null,
'confirm' => ($isPrivilegedUser || $isAppUser),
'secret' => Auth::hash($secret),
'secret' => $proofForToken->hash($secret),
'search' => implode(' ', [$membershipId, $invitee->getId()])
]);
@@ -646,7 +651,7 @@ App::post('/v1/teams/:teamId/memberships')
}
} elseif ($membership->getAttribute('confirm') === false) {
$membership->setAttribute('secret', Auth::hash($secret));
$membership->setAttribute('secret', $proofForToken->hash($secret));
$membership->setAttribute('invited', DateTime::now());
if ($isPrivilegedUser || $isAppUser) {
@@ -1070,7 +1075,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
if ($project->getId() === 'console') {
$roles = array_keys(Config::getParam('roles', []));
array_filter($roles, function ($role) {
return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]);
return !in_array($role, [USER_ROLE_APPS, USER_ROLE_GUESTS, USER_ROLE_USERS]);
});
return new ArrayList(new WhiteList($roles), APP_LIMIT_ARRAY_PARAMS_SIZE);
}
@@ -1185,7 +1190,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->inject('project')
->inject('geodb')
->inject('queueForEvents')
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents) {
->inject('store')
->inject('proofForToken')
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) {
$protocol = $request->getProtocol();
$membership = $dbForProject->getDocument('memberships', $membershipId);
@@ -1204,7 +1211,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
}
if (Auth::hash($secret) !== $membership->getAttribute('secret')) {
if (!$proofForToken->verify($secret, $membership->getAttribute('secret'))) {
throw new Exception(Exception::TEAM_INVALID_SECRET);
}
@@ -1238,9 +1245,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
$detector = new Detector($request->getUserAgent('UNKNOWN'));
$record = $geodb->get($request->getIP());
$authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
$authDuration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG;
$expire = DateTime::addSeconds(new \DateTime(), $authDuration);
$secret = Auth::tokenGenerator();
$secret = $proofForToken->generate();
$session = new Document(array_merge([
'$id' => ID::unique(),
'$permissions' => [
@@ -1250,9 +1257,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
],
'userId' => $user->getId(),
'userInternalId' => $user->getSequence(),
'provider' => Auth::SESSION_PROVIDER_EMAIL,
'provider' => SESSION_PROVIDER_EMAIL,
'providerUid' => $user->getAttribute('email'),
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'secret' => $proofForToken->hash($secret), // One way hash encryption to protect DB leak
'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(),
'factors' => ['email'],
@@ -1264,14 +1271,19 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
Authorization::setRole(Role::user($userId)->toString());
$encoded = $store
->setProperty('id', $user->getId())
->setProperty('secret', $secret)
->encode();
if (!Config::getParam('domainVerification')) {
$response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)]));
$response->addHeader('X-Fallback-Cookies', \json_encode([$store->getKey() => $encoded]));
}
$response
->addCookie(
name: Auth::$cookieName . '_legacy',
value: Auth::encodeSession($user->getId(), $secret),
name: $store->getKey() . '_legacy',
value: $encoded,
expire: (new \DateTime($expire))->getTimestamp(),
path: '/',
domain: Config::getParam('cookieDomain'),
@@ -1279,8 +1291,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
httponly: true
)
->addCookie(
name: Auth::$cookieName,
value: Auth::encodeSession($user->getId(), $secret),
name: $store->getKey(),
value: $encoded,
expire: (new \DateTime($expire))->getTimestamp(),
path: '/',
domain: Config::getParam('cookieDomain'),
+101 -43
View File
@@ -1,7 +1,6 @@
<?php
use Ahc\Jwt\JWT;
use Appwrite\Auth\Auth;
use Appwrite\Auth\MFA\Type;
use Appwrite\Auth\MFA\Type\TOTP;
use Appwrite\Auth\Validator\Password;
@@ -32,6 +31,18 @@ use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Auth\Hash;
use Utopia\Auth\Hashes\Argon2;
use Utopia\Auth\Hashes\Bcrypt;
use Utopia\Auth\Hashes\MD5;
use Utopia\Auth\Hashes\PHPass;
use Utopia\Auth\Hashes\Plaintext;
use Utopia\Auth\Hashes\Scrypt;
use Utopia\Auth\Hashes\ScryptModified;
use Utopia\Auth\Hashes\Sha;
use Utopia\Auth\Proofs\Password as ProofsPassword;
use Utopia\Auth\Proofs\Token;
use Utopia\Auth\Store;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
@@ -60,10 +71,9 @@ use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
/** TODO: Remove function when we move to using utopia/platform */
function createUser(string $hash, mixed $hashOptions, string $userId, ?string $email, ?string $password, ?string $phone, string $name, Document $project, Database $dbForProject, Hooks $hooks): Document
function createUser(Hash $hash, string $userId, ?string $email, ?string $password, ?string $phone, string $name, Document $project, Database $dbForProject, Hooks $hooks): Document
{
$plaintextPassword = $password;
$hashOptionsObject = (\is_string($hashOptions)) ? \json_decode($hashOptions, true) : $hashOptions; // Cast to JSON array
$passwordHistory = $project->getAttribute('auths', [])['passwordHistory'] ?? 0;
if (!empty($email)) {
@@ -97,7 +107,18 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
}
}
$password = (!empty($password)) ? ($hash === 'plaintext' ? Auth::passwordHash($password, $hash, $hashOptionsObject) : $password) : null;
$hashedPassword = null;
if (!empty($password)) {
if ($hash instanceof Plaintext) { // Password was never hashed, hash it with the default hash
$defaultHash = new ProofsPassword();
$hashedPassword = $defaultHash->hash($password);
$hash = $defaultHash->getHash();
} else {
$hashedPassword = $password;
}
}
$user = new Document([
'$id' => $userId,
'$permissions' => [
@@ -111,11 +132,11 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
'phoneVerification' => false,
'status' => true,
'labels' => [],
'password' => $password,
'passwordHistory' => is_null($password) || $passwordHistory === 0 ? [] : [$password],
'passwordUpdate' => (!empty($password)) ? DateTime::now() : null,
'hash' => $hash === 'plaintext' ? Auth::DEFAULT_ALGO : $hash,
'hashOptions' => $hash === 'plaintext' ? Auth::DEFAULT_ALGO_OPTIONS : $hashOptionsObject + ['type' => $hash],
'password' => $hashedPassword,
'passwordHistory' => is_null($hashedPassword) || $passwordHistory === 0 ? [] : [$hashedPassword],
'passwordUpdate' => (!empty($hashedPassword)) ? DateTime::now() : null,
'hash' => $hash->getName(),
'hashOptions' => $hash->getOptions(),
'registration' => DateTime::now(),
'reset' => false,
'name' => $name,
@@ -126,7 +147,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
'search' => implode(' ', [$userId, $email, $phone, $name]),
]);
if ($hash === 'plaintext') {
if ($hash instanceof Plaintext) {
$hooks->trigger('passwordValidator', [$dbForProject, $project, $plaintextPassword, &$user, true]);
}
@@ -217,7 +238,9 @@ App::post('/v1/users')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, ?string $email, ?string $phone, ?string $password, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$user = createUser('plaintext', '{}', $userId, $email, $password, $phone, $name, $project, $dbForProject, $hooks);
$plaintext = new Plaintext();
$user = createUser($plaintext, $userId, $email, $password, $phone, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($user, Response::MODEL_USER);
@@ -251,7 +274,10 @@ App::post('/v1/users/bcrypt')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$user = createUser('bcrypt', '{}', $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$bcrypt = new Bcrypt();
$bcrypt->setCost(8); // Default cost
$user = createUser($bcrypt, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -286,7 +312,9 @@ App::post('/v1/users/md5')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$user = createUser('md5', '{}', $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$md5 = new MD5();
$user = createUser($md5, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -321,7 +349,13 @@ App::post('/v1/users/argon2')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$user = createUser('argon2', '{}', $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$argon2 = new Argon2();
$argon2
->setMemoryCost(2048)
->setTimeCost(4)
->setThreads(3);
$user = createUser($argon2, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -357,13 +391,12 @@ App::post('/v1/users/sha')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $passwordVersion, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$options = '{}';
$sha = new Sha();
if (!empty($passwordVersion)) {
$options = '{"version":"' . $passwordVersion . '"}';
$sha->setVersion($passwordVersion);
}
$user = createUser('sha', $options, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$user = createUser($sha, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -398,7 +431,9 @@ App::post('/v1/users/phpass')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$user = createUser('phpass', '{}', $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$phpass = new PHPass();
$user = createUser($phpass, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -438,15 +473,15 @@ App::post('/v1/users/scrypt')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $passwordSalt, int $passwordCpu, int $passwordMemory, int $passwordParallel, int $passwordLength, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$options = [
'salt' => $passwordSalt,
'costCpu' => $passwordCpu,
'costMemory' => $passwordMemory,
'costParallel' => $passwordParallel,
'length' => $passwordLength
];
$scrypt = new Scrypt();
$scrypt
->setSalt($passwordSalt)
->setCpuCost($passwordCpu)
->setMemoryCost($passwordMemory)
->setParallelCost($passwordParallel)
->setLength($passwordLength);
$user = createUser('scrypt', \json_encode($options), $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$user = createUser($scrypt, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -484,7 +519,13 @@ App::post('/v1/users/scrypt-modified')
->inject('dbForProject')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $passwordSalt, string $passwordSaltSeparator, string $passwordSignerKey, string $name, Response $response, Document $project, Database $dbForProject, Hooks $hooks) {
$user = createUser('scryptMod', '{"signerKey":"' . $passwordSignerKey . '","saltSeparator":"' . $passwordSaltSeparator . '","salt":"' . $passwordSalt . '"}', $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$scryptModified = new ScryptModified();
$scryptModified
->setSalt($passwordSalt)
->setSaltSeparator($passwordSaltSeparator)
->setSignerKey($passwordSignerKey);
$user = createUser($scryptModified, $userId, $email, $password, null, $name, $project, $dbForProject, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -1069,7 +1110,6 @@ App::get('/v1/users/identities')
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
if (!empty($search)) {
$queries[] = Query::search('search', $search);
}
@@ -1336,12 +1376,21 @@ App::patch('/v1/users/:userId/password')
$hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, true]);
$newPassword = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS);
// Create Argon2 hasher with default settings
$hasher = new Argon2();
$hasher
->setMemoryCost(2048)
->setTimeCost(4)
->setThreads(3);
$newPassword = $hasher->hash($password);
$hash = ProofsPassword::createHash($user->getAttribute('hash'), $user->getAttribute('hashOptions'));
$historyLimit = $project->getAttribute('auths', [])['passwordHistory'] ?? 0;
$history = $user->getAttribute('passwordHistory', []);
if ($historyLimit > 0) {
$validator = new PasswordHistory($history, $user->getAttribute('hash'), $user->getAttribute('hashOptions'));
$validator = new PasswordHistory($history, $hash);
if (!$validator->isValid($password)) {
throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED);
}
@@ -1354,8 +1403,8 @@ App::patch('/v1/users/:userId/password')
->setAttribute('password', $newPassword)
->setAttribute('passwordHistory', $history)
->setAttribute('passwordUpdate', DateTime::now())
->setAttribute('hash', Auth::DEFAULT_ALGO)
->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS);
->setAttribute('hash', $hasher->getName())
->setAttribute('hashOptions', $hasher->getOptions());
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
@@ -2168,17 +2217,19 @@ App::post('/v1/users/:userId/sessions')
->inject('locale')
->inject('geodb')
->inject('queueForEvents')
->action(function (string $userId, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents) {
->inject('store')
->inject('proofForToken')
->action(function (string $userId, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Store $store, Token $proofForToken) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
throw new Exception(Exception::USER_NOT_FOUND);
}
$secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION);
$secret = $proofForToken->generate();
$detector = new Detector($request->getUserAgent('UNKNOWN'));
$record = $geodb->get($request->getIP());
$duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
$duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG;
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration));
$session = new Document(array_merge(
@@ -2186,8 +2237,8 @@ App::post('/v1/users/:userId/sessions')
'$id' => ID::unique(),
'userId' => $user->getId(),
'userInternalId' => $user->getSequence(),
'provider' => Auth::SESSION_PROVIDER_SERVER,
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'provider' => SESSION_PROVIDER_SERVER,
'secret' => $proofForToken->hash($secret), // One way hash encryption to protect DB leak
'userAgent' => $request->getUserAgent('UNKNOWN'),
'factors' => ['server'],
'ip' => $request->getIP(),
@@ -2211,8 +2262,13 @@ App::post('/v1/users/:userId/sessions')
$dbForProject->purgeCachedDocument('users', $user->getId());
$encoded = $store
->setProperty('id', $user->getId())
->setProperty('secret', $secret)
->encode();
$session
->setAttribute('secret', Auth::encodeSession($user->getId(), $secret))
->setAttribute('secret', $encoded)
->setAttribute('countryName', $countryName);
$queueForEvents
@@ -2247,7 +2303,7 @@ App::post('/v1/users/:userId/tokens')
))
->param('userId', '', new UID(), 'User ID.')
->param('length', 6, new Range(4, 128), 'Token length in characters. The default length is 6 characters', true)
->param('expire', Auth::TOKEN_EXPIRATION_GENERIC, new Range(60, Auth::TOKEN_EXPIRATION_LOGIN_LONG), 'Token expiration period in seconds. The default expiration is 15 minutes.', true)
->param('expire', TOKEN_EXPIRATION_GENERIC, new Range(60, TOKEN_EXPIRATION_LOGIN_LONG), 'Token expiration period in seconds. The default expiration is 15 minutes.', true)
->inject('request')
->inject('response')
->inject('dbForProject')
@@ -2259,15 +2315,17 @@ App::post('/v1/users/:userId/tokens')
throw new Exception(Exception::USER_NOT_FOUND);
}
$secret = Auth::tokenGenerator($length);
$proofForToken = new Token($length);
$proofForToken->setHash(new Sha());
$secret = $proofForToken->generate();
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $expire));
$token = new Document([
'$id' => ID::unique(),
'userId' => $user->getId(),
'userInternalId' => $user->getSequence(),
'type' => Auth::TOKEN_TYPE_GENERIC,
'secret' => Auth::hash($secret),
'type' => TOKEN_TYPE_GENERIC,
'secret' => $proofForToken->hash($secret),
'expire' => $expire,
'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP()
+22 -9
View File
@@ -1185,17 +1185,29 @@ App::error()
$trace = $error->getTrace();
if (php_sapi_name() === 'cli') {
Console::error('[Error] Timestamp: ' . date('c', time()));
$logLevel = $code >= 500 || $code == 0 ? 'error' : 'warning';
$logPrefix = $code >= 500 || $code == 0 ? '[Error]' : '[Warning]';
Console::{$logLevel}($logPrefix . ' Timestamp: ' . date('c', time()));
if ($route) {
Console::error('[Error] Method: ' . $route->getMethod());
Console::error('[Error] URL: ' . $route->getPath());
Console::{$logLevel}($logPrefix . ' Status Code: ' . $code);
Console::{$logLevel}($logPrefix . ' URL: ' . $route->getMethod() . ' ' . $route->getPath());
}
Console::error('[Error] Type: ' . get_class($error));
Console::error('[Error] Message: ' . $message);
Console::error('[Error] File: ' . $file);
Console::error('[Error] Line: ' . $line);
Console::{$logLevel}($logPrefix . ' Type: ' . get_class($error));
Console::{$logLevel}($logPrefix . ' Message: ' . $message);
Console::{$logLevel}($logPrefix . ' File: ' . $file);
Console::{$logLevel}($logPrefix . ' Line: ' . $line);
Console::{$logLevel}($logPrefix . ' Trace:');
foreach ($trace as $index => $entry) {
$traceFile = $entry['file'] ?? 'unknown';
$traceLine = $entry['line'] ?? 0;
$traceFunction = $entry['function'] ?? 'unknown';
$traceClass = $entry['class'] ?? '';
$traceType = $entry['type'] ?? '';
Console::{$logLevel}(" #{$index} {$traceFile}({$traceLine}): {$traceClass}{$traceType}{$traceFunction}()");
}
Console::{$logLevel}('');
}
switch ($class) {
@@ -1253,7 +1265,7 @@ App::error()
}
/**
* If its not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php
* If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php
*/
if (!$publish && $project->getId() !== 'console') {
if (!Auth::isPrivilegedUser(Authorization::getRoles())) {
@@ -1355,6 +1367,7 @@ App::error()
case 409: // Error allowed publicly
case 412: // Error allowed publicly
case 416: // Error allowed publicly
case 422: // Error allowed publicly
case 429: // Error allowed publicly
case 451: // Error allowed publicly
case 501: // Error allowed publicly
+69 -10
View File
@@ -222,39 +222,94 @@ App::init()
->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) {
$route = $utopia->getRoute();
/**
* Handle user authentication and session validation.
*
* This function follows a series of steps to determine the appropriate user session
* based on cookies, headers, and JWT tokens.
*
* Process:
*
* Project & Role Validation:
* 1. Check if the project is empty. If so, throw an exception.
* 2. Get the roles configuration.
* 3. Determine the role for the user based on the user document.
* 4. Get the scopes for the role.
*
* API Key Authentication:
* 5. If there is an API key:
* - Verify no user session exists simultaneously
* - Check if key is expired
* - Set role and scopes from API key
* - Handle special app role case
* - For standard keys, update last accessed time
*
* User Activity:
* 6. If the project is not the console and user is not admin:
* - Update user's last activity timestamp
*
* Access Control:
* 7. Get the method from the route
* 8. Validate namespace permissions
* 9. Validate scope permissions
* 10. Check if user is blocked
*
* Security Checks:
* 11. Verify password status (check if reset required)
* 12. Validate MFA requirements:
* - Check if MFA is enabled
* - Verify email status
* - Verify phone status
* - Verify authenticator status
* 13. Handle Multi-Factor Authentication:
* - Check remaining required factors
* - Validate factor completion
* - Throw exception if factors incomplete
*/
// Step 1: Check if project is empty
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
// Step 2: Get roles configuration
$roles = Config::getParam('roles', []);
// Step 3: Determine role for user
// TODO get scopes from the identity instead of the user roles config. The identity will containn the scopes the user authorized for the access token.
$role = $user->isEmpty()
? Role::guests()->toString()
: Role::users()->toString();
// Step 4: Get scopes for the role
$scopes = $roles[$role]['scopes'];
// API Key authentication
// Step 5: API Key Authentication
if (!empty($apiKey)) {
// Verify no user session exists simultaneously
if (!$user->isEmpty()) {
throw new Exception(Exception::USER_API_KEY_AND_SESSION_SET);
}
// Check if key is expired
if ($apiKey->isExpired()) {
throw new Exception(Exception::PROJECT_KEY_EXPIRED);
}
// Set role and scopes from API key
$role = $apiKey->getRole();
$scopes = $apiKey->getScopes();
if ($apiKey->getRole() === Auth::USER_ROLE_APPS) {
// Handle special app role case
if ($apiKey->getRole() === USER_ROLE_APPS) {
// Disable authorization checks for API keys
Authorization::setDefaultStatus(false);
$user = new Document([
'$id' => '',
'status' => true,
'type' => Auth::ACTIVITY_TYPE_APP,
'type' => ACTIVITY_TYPE_APP,
'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(),
'password' => '',
'name' => $apiKey->getName(),
@@ -263,6 +318,7 @@ App::init()
$queueForAudits->setUser($user);
}
// For standard keys, update last accessed time
if ($apiKey->getType() === API_KEY_STANDARD) {
$dbKey = $project->find(
key: 'secret',
@@ -332,7 +388,7 @@ App::init()
Authorization::setRole($authRole);
}
// Update project last activity
// Step 6: Update project and user last activity
if (!$project->isEmpty() && $project->getId() !== 'console') {
$accessedAt = $project->getAttribute('accessedAt', 0);
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) {
@@ -341,7 +397,6 @@ App::init()
}
}
// Update user last activity
if (!empty($user->getId())) {
$accessedAt = $user->getAttribute('accessedAt', 0);
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) {
@@ -355,6 +410,7 @@ App::init()
}
}
// Steps 7-9: Access Control - Method, Namespace and Scope Validation
/**
* @var ?Method $method
*/
@@ -378,21 +434,23 @@ App::init()
}
}
// Do now allow access if scope is not allowed
// Step 9: Validate scope permissions
$allowed = (array)$route->getLabel('scope', 'none');
if (empty(\array_intersect($allowed, $scopes))) {
throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scopes (' . \json_encode($allowed) . ')');
}
// Do not allow access to blocked accounts
// Step 10: Check if user is blocked
if (false === $user->getAttribute('status')) { // Account is blocked
throw new Exception(Exception::USER_BLOCKED);
}
// Step 11: Verify password status
if ($user->getAttribute('reset')) {
throw new Exception(Exception::USER_PASSWORD_RESET_REQUIRED);
}
// Step 12: Validate MFA requirements
$mfaEnabled = $user->getAttribute('mfa', false);
$hasVerifiedEmail = $user->getAttribute('emailVerification', false);
$hasVerifiedPhone = $user->getAttribute('phoneVerification', false);
@@ -400,6 +458,7 @@ App::init()
$hasMoreFactors = $hasVerifiedEmail || $hasVerifiedPhone || $hasVerifiedAuthenticator;
$minimumFactors = ($mfaEnabled && $hasMoreFactors) ? 2 : 1;
// Step 13: Handle Multi-Factor Authentication
if (!in_array('mfa', $route->getGroups())) {
if ($session && \count($session->getAttribute('factors', [])) < $minimumFactors) {
throw new Exception(Exception::USER_MORE_FACTORS_REQUIRED);
@@ -526,7 +585,7 @@ App::init()
if (!$user->isEmpty()) {
$userClone = clone $user;
// $user doesn't support `type` and can cause unintended effects.
$userClone->setAttribute('type', Auth::ACTIVITY_TYPE_USER);
$userClone->setAttribute('type', ACTIVITY_TYPE_USER);
$queueForAudits->setUser($userClone);
}
@@ -766,7 +825,7 @@ App::shutdown()
if (!$user->isEmpty()) {
$userClone = clone $user;
// $user doesn't support `type` and can cause unintended effects.
$userClone->setAttribute('type', Auth::ACTIVITY_TYPE_USER);
$userClone->setAttribute('type', ACTIVITY_TYPE_USER);
$queueForAudits->setUser($userClone);
} elseif ($queueForAudits->getUser() === null || $queueForAudits->getUser()->isEmpty()) {
/**
@@ -780,7 +839,7 @@ App::shutdown()
$user = new Document([
'$id' => '',
'status' => true,
'type' => Auth::ACTIVITY_TYPE_GUEST,
'type' => ACTIVITY_TYPE_GUEST,
'email' => 'guest.' . $project->getId() . '@service.' . $request->getHostname(),
'password' => '',
'name' => 'Guest',
+1 -1
View File
@@ -20,7 +20,7 @@ App::init()
$lastUpdate = $session->getAttribute('mfaUpdatedAt');
if (!empty($lastUpdate)) {
$now = DateTime::now();
$maxAllowedDate = DateTime::addSeconds(new \DateTime($lastUpdate), Auth::MFA_RECENT_DURATION); // Maximum date until session is considered safe before asking for another challenge
$maxAllowedDate = DateTime::addSeconds(new \DateTime($lastUpdate), MFA_RECENT_DURATION); // Maximum date until session is considered safe before asking for another challenge
$isSessionFresh = DateTime::formatTz($maxAllowedDate) >= DateTime::formatTz($now);
}
+81 -2
View File
@@ -31,6 +31,7 @@ const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate
const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate period in seconds
const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return in list API calls
const APP_LIMIT_DATABASE_BATCH = 100; // Default maximum batch size for database operations
const APP_LIMIT_DATABASE_TRANSACTION = 100; // Default maximum operations per transaction
const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours
const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours
const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours
@@ -55,6 +56,10 @@ const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes
const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes
const APP_DATABASE_QUERY_MAX_VALUES = 500;
const APP_DATABASE_ENCRYPT_SIZE_MIN = 150;
const APP_DATABASE_TXN_TTL_MIN = 60; // 1 minute
const APP_DATABASE_TXN_TTL_MAX = 3600; // 1 hour
const APP_DATABASE_TXN_TTL_DEFAULT = 300; // 5 minutes
const APP_DATABASE_TXN_MAX_OPERATIONS = 100; // Maximum operations per transaction
const APP_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_SITES = '/storage/sites';
const APP_STORAGE_FUNCTIONS = '/storage/functions';
@@ -85,6 +90,73 @@ const APP_PLATFORM_CLIENT = 'client';
const APP_PLATFORM_CONSOLE = 'console';
const APP_VCS_GITHUB_USERNAME = 'Appwrite';
const APP_VCS_GITHUB_EMAIL = 'team@appwrite.io';
const APP_BRANDED_EMAIL_BASE_TEMPLATE = 'email-base-styled';
// User Roles
const USER_ROLE_ANY = 'any';
const USER_ROLE_GUESTS = 'guests';
const USER_ROLE_USERS = 'users';
const USER_ROLE_ADMIN = 'admin';
const USER_ROLE_DEVELOPER = 'developer';
const USER_ROLE_OWNER = 'owner';
const USER_ROLE_APPS = 'apps';
const USER_ROLE_SYSTEM = 'system';
/**
* Token Expiration times.
*/
const TOKEN_EXPIRATION_LOGIN_LONG = 31536000; /* 1 year */
const TOKEN_EXPIRATION_LOGIN_SHORT = 3600; /* 1 hour */
const TOKEN_EXPIRATION_RECOVERY = 3600; /* 1 hour */
const TOKEN_EXPIRATION_CONFIRM = 3600 * 1; /* 1 hour */
const TOKEN_EXPIRATION_OTP = 60 * 15; /* 15 minutes */
const TOKEN_EXPIRATION_GENERIC = 60 * 15; /* 15 minutes */
/**
* Token Lengths.
*/
const TOKEN_LENGTH_MAGIC_URL = 64;
const TOKEN_LENGTH_VERIFICATION = 256;
const TOKEN_LENGTH_RECOVERY = 256;
const TOKEN_LENGTH_OAUTH2 = 64;
const TOKEN_LENGTH_SESSION = 256;
/**
* Token Types.
*/
const TOKEN_TYPE_LOGIN = 1; // Deprecated
const TOKEN_TYPE_VERIFICATION = 2;
const TOKEN_TYPE_RECOVERY = 3;
const TOKEN_TYPE_INVITE = 4;
const TOKEN_TYPE_MAGIC_URL = 5;
const TOKEN_TYPE_PHONE = 6;
const TOKEN_TYPE_OAUTH2 = 7;
const TOKEN_TYPE_GENERIC = 8;
const TOKEN_TYPE_EMAIL = 9; // OTP
/**
* Session Providers.
*/
const SESSION_PROVIDER_EMAIL = 'email';
const SESSION_PROVIDER_ANONYMOUS = 'anonymous';
const SESSION_PROVIDER_MAGIC_URL = 'magic-url';
const SESSION_PROVIDER_PHONE = 'phone';
const SESSION_PROVIDER_OAUTH2 = 'oauth2';
const SESSION_PROVIDER_TOKEN = 'token';
const SESSION_PROVIDER_SERVER = 'server';
/**
* Activity associated with user or the app.
*/
const ACTIVITY_TYPE_APP = 'app';
const ACTIVITY_TYPE_USER = 'user';
const ACTIVITY_TYPE_GUEST = 'guest';
/**
* MFA
*/
const MFA_RECENT_DURATION = 1800; // 30 mins
// Database Reconnect
const DATABASE_RECONNECT_SLEEP = 2;
@@ -104,8 +176,11 @@ const BUILD_TYPE_RETRY = 'retry';
// Deletion Types
const DELETE_TYPE_DATABASES = 'databases';
const DELETE_TYPE_DOCUMENT = 'document';
const DELETE_TYPE_COLLECTIONS = 'collections';
const DELETE_TYPE_TRANSACTION = 'transaction';
const DELETE_TYPE_EXPIRED_TRANSACTIONS = 'expired_transactions';
const DELETE_TYPE_PROJECTS = 'projects';
const DELETE_TYPE_SITES = 'sites';
const DELETE_TYPE_FUNCTIONS = 'functions';
@@ -262,7 +337,6 @@ const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound';
const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound';
// Resource types
const RESOURCE_TYPE_PROJECTS = 'projects';
const RESOURCE_TYPE_FUNCTIONS = 'functions';
const RESOURCE_TYPE_SITES = 'sites';
@@ -272,10 +346,15 @@ const RESOURCE_TYPE_PROVIDERS = 'providers';
const RESOURCE_TYPE_TOPICS = 'topics';
const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers';
const RESOURCE_TYPE_MESSAGES = 'messages';
const RESOURCE_TYPE_EXECUTIONS = 'executions';
// Resource types for Tokens
const TOKENS_RESOURCE_TYPE_FILES = 'files';
const TOKENS_RESOURCE_TYPE_SITES = 'sites';
const TOKENS_RESOURCE_TYPE_FUNCTIONS = 'functions';
const TOKENS_RESOURCE_TYPE_DATABASES = 'databases';
// Resource types for Schedules
const SCHEDULE_RESOURCE_TYPE_EXECUTION = 'execution';
const SCHEDULE_RESOURCE_TYPE_FUNCTION = 'function';
const SCHEDULE_RESOURCE_TYPE_MESSAGE = 'message';
+2
View File
@@ -255,6 +255,8 @@ Database::addFilter(
->find('variables', [
Query::equal('resourceInternalId', [$document->getSequence()]),
Query::equal('resourceType', $resourceType),
Query::orderAsc('resourceType'),
Query::orderAsc(),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
+129 -54
View File
@@ -4,6 +4,7 @@ use Ahc\Jwt\JWT;
use Ahc\Jwt\JWTException;
use Appwrite\Auth\Auth;
use Appwrite\Auth\Key;
use Appwrite\Databases\TransactionState;
use Appwrite\Event\Audit;
use Appwrite\Event\Build;
use Appwrite\Event\Certificate;
@@ -23,9 +24,16 @@ use Appwrite\GraphQL\Schema;
use Appwrite\Network\Platform;
use Appwrite\Network\Validator\Origin;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Executor\Executor;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\App;
use Utopia\Auth\Hashes\Argon2;
use Utopia\Auth\Hashes\Sha;
use Utopia\Auth\Proofs\Code;
use Utopia\Auth\Proofs\Password;
use Utopia\Auth\Proofs\Token;
use Utopia\Auth\Store;
use Utopia\Cache\Adapter\Pool as CachePool;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
@@ -151,7 +159,7 @@ App::setResource('queueForMigrations', function (Publisher $publisher) {
App::setResource('queueForStatsResources', function (Publisher $publisher) {
return new StatsResources($publisher);
}, ['publisher']);
App::setResource('platforms', function (Request $request, Document $console, Document $project) {
App::setResource('platforms', function (Request $request, Document $console, Document $project, Database $dbForPlatform) {
$console->setAttribute('platforms', [ // Always allow current host
'$collection' => ID::custom('platforms'),
'name' => 'Current Host',
@@ -190,78 +198,128 @@ App::setResource('platforms', function (Request $request, Document $console, Doc
], Document::SET_TYPE_APPEND);
}
$origin = \parse_url($request->getOrigin(), PHP_URL_HOST);
if (empty($origin)) {
$origin = \parse_url($request->getReferer(), PHP_URL_HOST);
}
// Safe if rule with same project ID exists
if (!empty($origin)) {
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
$rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? '')));
} else {
$rule = Authorization::skip(
fn () => $dbForPlatform->find('rules', [
Query::equal('domain', [$origin]),
Query::limit(1)
])
)[0] ?? new Document();
}
if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) {
$project->setAttribute('platforms', [
'$collection' => ID::custom('platforms'),
'type' => Platform::TYPE_WEB,
'name' => $origin,
'hostname' => $origin,
], Document::SET_TYPE_APPEND);
}
}
return [
...$console->getAttribute('platforms', []),
...$project->getAttribute('platforms', []),
];
}, ['request', 'console', 'project']);
}, ['request', 'console', 'project', 'dbForPlatform']);
App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform) {
App::setResource('user', function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Store $store, Token $proofForToken) {
/** @var Appwrite\Utopia\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Database $dbForPlatform */
/** @var string $mode */
/** @var Utopia\Auth\Store $store */
/**
* Handles user authentication and session validation.
*
* This function follows a series of steps to determine the appropriate user session
* based on cookies, headers, and JWT tokens.
*
* Process:
* 1. Checks the cookie based on mode:
* - If in admin mode, uses console project id for key.
* - Otherwise, sets the key using the project ID
* 2. If no cookie is found, attempts to retrieve the fallback header `x-fallback-cookies`.
* - If this method is used, returns the header: `X-Debug-Fallback: true`.
* 3. Fetches the user document from the appropriate database based on the mode.
* 4. If the user document is empty or the session key cannot be verified, sets an empty user document.
* 5. Regardless of the results from steps 1-4, attempts to fetch the JWT token.
* 6. If the JWT user has a valid session ID, updates the user variable with the user from `projectDB`,
* overwriting the previous value.
*/
Authorization::setDefaultStatus(true);
Auth::setCookieName('a_session_' . $project->getId());
$store->setKey('a_session_' . $project->getId());
if (APP_MODE_ADMIN === $mode) {
Auth::setCookieName('a_session_' . $console->getId());
$store->setKey('a_session_' . $console->getId());
}
$session = Auth::decodeSession(
$store->decode(
$request->getCookie(
Auth::$cookieName, // Get sessions
$request->getCookie(Auth::$cookieName . '_legacy', '')
$store->getKey(), // Get sessions
$request->getCookie($store->getKey() . '_legacy', '')
)
);
// Get session from header for SSR clients
if (empty($session['id']) && empty($session['secret'])) {
if (empty($store->getProperty('id', '')) && empty($store->getProperty('secret', ''))) {
$sessionHeader = $request->getHeader('x-appwrite-session', '');
if (!empty($sessionHeader)) {
$session = Auth::decodeSession($sessionHeader);
$store->decode($sessionHeader);
}
}
// Get fallback session from old clients (no SameSite support) or clients who block 3rd-party cookies
if ($response) {
if ($response) { // if in http context - add debug header
$response->addHeader('X-Debug-Fallback', 'false');
}
if (empty($session['id']) && empty($session['secret'])) {
if (empty($store->getProperty('id', '')) && empty($store->getProperty('secret', ''))) {
if ($response) {
$response->addHeader('X-Debug-Fallback', 'true');
}
$fallback = $request->getHeader('x-fallback-cookies', '');
$fallback = \json_decode($fallback, true);
$session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : ''));
$store->decode(((is_array($fallback) && isset($fallback[$store->getKey()])) ? $fallback[$store->getKey()] : ''));
}
Auth::$unique = $session['id'] ?? '';
Auth::$secret = $session['secret'] ?? '';
$user = new Document([]);
if (!empty(Auth::$unique)) {
if ($mode === APP_MODE_ADMIN) {
$user = $dbForPlatform->getDocument('users', Auth::$unique);
} elseif (!$project->isEmpty()) {
if ($project->getId() === 'console') {
$user = $dbForPlatform->getDocument('users', Auth::$unique);
} else {
$user = $dbForProject->getDocument('users', Auth::$unique);
if (APP_MODE_ADMIN === $mode) {
$user = $dbForPlatform->getDocument('users', $store->getProperty('id', ''));
} else {
if ($project->isEmpty()) {
$user = new Document([]);
} else {
if (!empty($store->getProperty('id', ''))) {
if ($project->getId() === 'console') {
$user = $dbForPlatform->getDocument('users', $store->getProperty('id', ''));
} else {
$user = $dbForProject->getDocument('users', $store->getProperty('id', ''));
}
}
}
}
if (
$user->isEmpty() // Check a document has been found in the DB
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret)
|| !Auth::sessionVerify($user->getAttribute('sessions', []), $store->getProperty('secret', ''), $proofForToken)
) { // Validate user has valid login token
$user = new Document([]);
}
@@ -306,7 +364,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons
$dbForPlatform->setMetadata('user', $user->getId());
return $user;
}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform']);
}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'store', 'proofForToken']);
App::setResource('project', function ($dbForPlatform, $request, $console) {
/** @var Appwrite\Utopia\Request $request */
@@ -324,13 +382,13 @@ App::setResource('project', function ($dbForPlatform, $request, $console) {
return $project;
}, ['dbForPlatform', 'request', 'console']);
App::setResource('session', function (Document $user) {
App::setResource('session', function (Document $user, Store $store, Token $proofForToken) {
if ($user->isEmpty()) {
return;
}
$sessions = $user->getAttribute('sessions', []);
$sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret);
$sessionId = Auth::sessionVerify($user->getAttribute('sessions'), $store->getProperty('secret', ''), $proofForToken);
if (!$sessionId) {
return;
@@ -343,7 +401,7 @@ App::setResource('session', function (Document $user) {
}
return;
}, ['user']);
}, ['user', 'store', 'proofForToken']);
App::setResource('console', function () {
return new Document(Config::getParam('console'));
@@ -375,7 +433,7 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant((int)$project->getSequence())
->setTenant((int) $project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
@@ -428,7 +486,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant((int)$project->getSequence())
->setTenant((int) $project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
@@ -458,7 +516,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
return function (?Document $project = null) use ($pools, $cache, &$database) {
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant((int)$project->getSequence());
$database->setTenant((int) $project->getSequence());
return $database;
}
@@ -473,7 +531,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
// set tenant
if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant((int)$project->getSequence());
$database->setTenant((int) $project->getSequence());
}
return $database;
@@ -501,7 +559,7 @@ App::setResource('redis', function () {
$pass = System::getEnv('_APP_REDIS_PASS', '');
$redis = new \Redis();
@$redis->pconnect($host, (int)$port);
@$redis->pconnect($host, (int) $port);
if ($pass) {
$redis->auth($pass);
}
@@ -714,7 +772,7 @@ App::setResource('schema', function ($utopia, $dbForProject) {
// NOTE: `params` and `urls` are not used internally in the `Schema::build` function below!
$params = [
'list' => function (string $databaseId, string $collectionId, array $args) {
return [ 'queries' => $args['queries']];
return ['queries' => $args['queries']];
},
'create' => function (string $databaseId, string $collectionId, array $args) {
$id = $args['id'] ?? 'unique()';
@@ -917,6 +975,37 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key
return Key::decode($project, $key);
}, ['request', 'project']);
App::setResource('store', function (): Store {
return new Store();
});
App::setResource('proofForPassword', function (): Password {
$hash = new Argon2();
$hash
->setMemoryCost(2048)
->setTimeCost(4)
->setThreads(3);
$password = new Password();
$password
->setHash($hash);
return $password;
});
App::setResource('proofForToken', function (): Token {
$token = new Token();
$token->setHash(new Sha());
return $token;
});
App::setResource('proofForCode', function (): Code {
$code = new Code();
$code->setHash(new Sha());
return $code;
});
App::setResource('executor', fn () => new Executor());
App::setResource('resourceToken', function ($project, $dbForProject, $request) {
@@ -963,7 +1052,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) {
}
$accessedAt = $token->getAttribute('accessedAt', 0);
if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), - APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) {
if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) {
$token->setAttribute('accessedAt', DatabaseDateTime::now());
Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token));
}
@@ -1005,24 +1094,6 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef
return $referrer;
}
// Safe if rule with same project ID exists
if (!empty($origin)) {
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
$rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? '')));
} else {
$rule = Authorization::skip(
fn () => $dbForPlatform->find('rules', [
Query::equal('domain', [$origin]),
Query::limit(1)
])
)[0] ?? new Document();
}
if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) {
return $referrer;
}
}
// Unsafe; Localhost is always safe for ease of local development
$origin = 'localhost';
$protocol = \parse_url($request->getOrigin($httpReferrer), PHP_URL_SCHEME);
@@ -1030,3 +1101,7 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef
$referrer = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : '');
return $referrer;
}, ['request', 'httpReferrer', 'platforms', 'dbForPlatform', 'project', 'utopia']);
App::setResource('transactionState', function (Database $dbForProject) {
return new TransactionState($dbForProject);
}, ['dbForProject']);
+39 -8
View File
@@ -16,6 +16,9 @@ use Swoole\Timer;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\App;
use Utopia\Auth\Hashes\Sha;
use Utopia\Auth\Proofs\Token;
use Utopia\Auth\Store;
use Utopia\Cache\Adapter\Pool as CachePool;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
@@ -604,11 +607,18 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
$code = 500;
}
$message = $th->getMessage();
// sanitize 0 && 5xx errors
if (($code === 0 || $code >= 500) && !App::isDevelopment()) {
$message = 'Error: Server Error';
}
$response = [
'type' => 'error',
'data' => [
'code' => $code,
'message' => $th->getMessage()
'message' => $message
]
];
@@ -671,15 +681,24 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Payload is not valid.');
}
$session = Auth::decodeSession($message['data']['session']);
Auth::$unique = $session['id'] ?? '';
Auth::$secret = $session['secret'] ?? '';
$store = new Store();
$user = $database->getDocument('users', Auth::$unique);
$store->decode($message['data']['session']);
$user = $database->getDocument('users', $store->getProperty('id', ''));
/**
* TODO:
* Moving forward, we should try to use our dependency injection container
* to inject the proof for token.
* This way we will have one source of truth for the proof for token.
*/
$proofForToken = new Token();
$proofForToken->setHash(new Sha());
if (
empty($user->getId()) // Check a document has been found in the DB
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret) // Validate user has valid login token
|| !Auth::sessionVerify($user->getAttribute('sessions', []), $store->getProperty('secret', ''), $proofForToken) // Validate user has valid login token
) {
// cookie not valid
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.');
@@ -705,11 +724,23 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Message type is not valid.');
}
} catch (Throwable $th) {
$code = $th->getCode();
if (!is_int($code)) {
$code = 500;
}
$message = $th->getMessage();
// sanitize 0 && 5xx errors
if (($code === 0 || $code >= 500) && !App::isDevelopment()) {
$message = 'Error: Server Error';
}
$response = [
'type' => 'error',
'data' => [
'code' => $th->getCode(),
'message' => $th->getMessage()
'code' => $code,
'message' => $message
]
];
+3 -2
View File
@@ -46,13 +46,14 @@
"ext-sockets": "*",
"appwrite/php-runtimes": "0.19.*",
"appwrite/php-clamav": "2.0.*",
"utopia-php/auth": "0.4.*",
"utopia-php/abuse": "1.*",
"utopia-php/analytics": "0.10.*",
"utopia-php/audit": "1.*",
"utopia-php/cache": "0.13.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "1.*",
"utopia-php/database": "2.*",
"utopia-php/detector": "0.1.*",
"utopia-php/domains": "0.8.*",
"utopia-php/dns": "0.3.*",
@@ -62,7 +63,7 @@
"utopia-php/image": "0.8.*",
"utopia-php/locale": "0.8.*",
"utopia-php/logger": "0.6.*",
"utopia-php/messaging": "0.18.*",
"utopia-php/messaging": "0.19.*",
"utopia-php/migration": "1.*",
"utopia-php/orchestration": "0.9.*",
"utopia-php/platform": "0.7.*",
Generated
+213 -152
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7553e976312b0423cc31544abb91caec",
"content-hash": "9658991ad6520dad5807d7e1ed1e9bd4",
"packages": [
{
"name": "adhocore/jwt",
@@ -756,24 +756,21 @@
},
{
"name": "google/protobuf",
"version": "v4.32.0",
"version": "v4.33.0",
"source": {
"type": "git",
"url": "https://github.com/protocolbuffers/protobuf-php.git",
"reference": "9a9a92ecbe9c671dc1863f6d4a91ea3ea12c8646"
"reference": "b50269e23204e5ae859a326ec3d90f09efe3047d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/9a9a92ecbe9c671dc1863f6d4a91ea3ea12c8646",
"reference": "9a9a92ecbe9c671dc1863f6d4a91ea3ea12c8646",
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/b50269e23204e5ae859a326ec3d90f09efe3047d",
"reference": "b50269e23204e5ae859a326ec3d90f09efe3047d",
"shasum": ""
},
"require": {
"php": ">=8.1.0"
},
"provide": {
"ext-protobuf": "*"
},
"require-dev": {
"phpunit/phpunit": ">=5.0.0 <8.5.27"
},
@@ -797,9 +794,9 @@
"proto"
],
"support": {
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.32.0"
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.0"
},
"time": "2025-08-14T20:00:33+00:00"
"time": "2025-10-15T20:10:28+00:00"
},
{
"name": "league/csv",
@@ -1162,20 +1159,20 @@
},
{
"name": "open-telemetry/api",
"version": "1.5.0",
"version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/api.git",
"reference": "7692075f486c14d8cfd37fba98a08a5667f089e5"
"reference": "610b79ad9d6d97e8368bcb6c4d42394fbb87b522"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/api/zipball/7692075f486c14d8cfd37fba98a08a5667f089e5",
"reference": "7692075f486c14d8cfd37fba98a08a5667f089e5",
"url": "https://api.github.com/repos/opentelemetry-php/api/zipball/610b79ad9d6d97e8368bcb6c4d42394fbb87b522",
"reference": "610b79ad9d6d97e8368bcb6c4d42394fbb87b522",
"shasum": ""
},
"require": {
"open-telemetry/context": "^1.0",
"open-telemetry/context": "^1.4",
"php": "^8.1",
"psr/log": "^1.1|^2.0|^3.0",
"symfony/polyfill-php82": "^1.26"
@@ -1191,7 +1188,7 @@
]
},
"branch-alias": {
"dev-main": "1.4.x-dev"
"dev-main": "1.7.x-dev"
}
},
"autoload": {
@@ -1228,20 +1225,20 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-08-07T23:07:38+00:00"
"time": "2025-10-02T23:44:28+00:00"
},
{
"name": "open-telemetry/context",
"version": "1.3.1",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/context.git",
"reference": "438f71812242db3f196fb4c717c6f92cbc819be6"
"reference": "d4c4470b541ce72000d18c339cfee633e4c8e0cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/438f71812242db3f196fb4c717c6f92cbc819be6",
"reference": "438f71812242db3f196fb4c717c6f92cbc819be6",
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/d4c4470b541ce72000d18c339cfee633e4c8e0cf",
"reference": "d4c4470b541ce72000d18c339cfee633e4c8e0cf",
"shasum": ""
},
"require": {
@@ -1287,7 +1284,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-08-13T01:12:00+00:00"
"time": "2025-09-19T00:05:49+00:00"
},
{
"name": "open-telemetry/exporter-otlp",
@@ -1355,16 +1352,16 @@
},
{
"name": "open-telemetry/gen-otlp-protobuf",
"version": "1.5.0",
"version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git",
"reference": "585bafddd4ae6565de154610b10a787a455c9ba0"
"reference": "673af5b06545b513466081884b47ef15a536edde"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0",
"reference": "585bafddd4ae6565de154610b10a787a455c9ba0",
"url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/673af5b06545b513466081884b47ef15a536edde",
"reference": "673af5b06545b513466081884b47ef15a536edde",
"shasum": ""
},
"require": {
@@ -1414,27 +1411,27 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-01-15T23:07:07+00:00"
"time": "2025-09-17T23:10:12+00:00"
},
{
"name": "open-telemetry/sdk",
"version": "1.7.1",
"version": "1.9.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/sdk.git",
"reference": "52690d4b37ae4f091af773eef3c238ed2bc0aa06"
"reference": "8986bcbcbea79cb1ba9e91c1d621541ad63d6b3e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/52690d4b37ae4f091af773eef3c238ed2bc0aa06",
"reference": "52690d4b37ae4f091af773eef3c238ed2bc0aa06",
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/8986bcbcbea79cb1ba9e91c1d621541ad63d6b3e",
"reference": "8986bcbcbea79cb1ba9e91c1d621541ad63d6b3e",
"shasum": ""
},
"require": {
"ext-json": "*",
"nyholm/psr7-server": "^1.1",
"open-telemetry/api": "^1.4",
"open-telemetry/context": "^1.0",
"open-telemetry/api": "^1.7",
"open-telemetry/context": "^1.4",
"open-telemetry/sem-conv": "^1.0",
"php": "^8.1",
"php-http/discovery": "^1.14",
@@ -1468,7 +1465,7 @@
]
},
"branch-alias": {
"dev-main": "1.0.x-dev"
"dev-main": "1.9.x-dev"
}
},
"autoload": {
@@ -1511,7 +1508,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-09-05T07:17:06+00:00"
"time": "2025-10-02T23:44:28+00:00"
},
{
"name": "open-telemetry/sem-conv",
@@ -1572,16 +1569,16 @@
},
{
"name": "paragonie/constant_time_encoding",
"version": "v2.7.0",
"version": "v2.8.2",
"source": {
"type": "git",
"url": "https://github.com/paragonie/constant_time_encoding.git",
"reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105"
"reference": "e30811f7bc69e4b5b6d5783e712c06c8eabf0226"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/52a0d99e69f56b9ec27ace92ba56897fe6993105",
"reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/e30811f7bc69e4b5b6d5783e712c06c8eabf0226",
"reference": "e30811f7bc69e4b5b6d5783e712c06c8eabf0226",
"shasum": ""
},
"require": {
@@ -1635,7 +1632,7 @@
"issues": "https://github.com/paragonie/constant_time_encoding/issues",
"source": "https://github.com/paragonie/constant_time_encoding"
},
"time": "2024-05-08T12:18:48+00:00"
"time": "2025-09-24T15:12:37+00:00"
},
{
"name": "paragonie/random_compat",
@@ -1930,16 +1927,16 @@
},
{
"name": "phpseclib/phpseclib",
"version": "3.0.46",
"version": "3.0.47",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6"
"reference": "9d6ca36a6c2dd434765b1071b2644a1c683b385d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6",
"reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/9d6ca36a6c2dd434765b1071b2644a1c683b385d",
"reference": "9d6ca36a6c2dd434765b1071b2644a1c683b385d",
"shasum": ""
},
"require": {
@@ -2020,7 +2017,7 @@
],
"support": {
"issues": "https://github.com/phpseclib/phpseclib/issues",
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.46"
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.47"
},
"funding": [
{
@@ -2036,7 +2033,7 @@
"type": "tidelift"
}
],
"time": "2025-06-26T16:29:55+00:00"
"time": "2025-10-06T01:07:24+00:00"
},
{
"name": "psr/container",
@@ -2599,16 +2596,16 @@
},
{
"name": "symfony/http-client",
"version": "v7.3.3",
"version": "v7.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
"reference": "333b9bd7639cbdaecd25a3a48a9d2dcfaa86e019"
"reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/333b9bd7639cbdaecd25a3a48a9d2dcfaa86e019",
"reference": "333b9bd7639cbdaecd25a3a48a9d2dcfaa86e019",
"url": "https://api.github.com/repos/symfony/http-client/zipball/4b62871a01c49457cf2a8e560af7ee8a94b87a62",
"reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62",
"shasum": ""
},
"require": {
@@ -2675,7 +2672,7 @@
"http"
],
"support": {
"source": "https://github.com/symfony/http-client/tree/v7.3.3"
"source": "https://github.com/symfony/http-client/tree/v7.3.4"
},
"funding": [
{
@@ -2695,7 +2692,7 @@
"type": "tidelift"
}
],
"time": "2025-08-27T07:45:05+00:00"
"time": "2025-09-11T10:12:26+00:00"
},
{
"name": "symfony/http-client-contracts",
@@ -3296,16 +3293,16 @@
},
{
"name": "utopia-php/abuse",
"version": "1.0.0",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "c5e2232033b507a07f72180dc56d37e1872ee7be"
"reference": "cd591568791556d246d901d6aaf9935ab02c3f9a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/c5e2232033b507a07f72180dc56d37e1872ee7be",
"reference": "c5e2232033b507a07f72180dc56d37e1872ee7be",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/cd591568791556d246d901d6aaf9935ab02c3f9a",
"reference": "cd591568791556d246d901d6aaf9935ab02c3f9a",
"shasum": ""
},
"require": {
@@ -3313,7 +3310,7 @@
"ext-pdo": "*",
"ext-redis": "*",
"php": ">=8.0",
"utopia-php/database": "1.*"
"utopia-php/database": "2.*"
},
"require-dev": {
"laravel/pint": "1.*",
@@ -3341,9 +3338,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/1.0.0"
"source": "https://github.com/utopia-php/abuse/tree/1.0.1"
},
"time": "2025-08-13T09:12:54+00:00"
"time": "2025-09-04T12:46:54+00:00"
},
{
"name": "utopia-php/analytics",
@@ -3393,21 +3390,21 @@
},
{
"name": "utopia-php/audit",
"version": "1.0.0",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "c0ed75f4d068f1f6c2e7149a909490d4214e72bb"
"reference": "5ef26d6a2ab2db7bb86288a1a6ef970307b46f22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/c0ed75f4d068f1f6c2e7149a909490d4214e72bb",
"reference": "c0ed75f4d068f1f6c2e7149a909490d4214e72bb",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/5ef26d6a2ab2db7bb86288a1a6ef970307b46f22",
"reference": "5ef26d6a2ab2db7bb86288a1a6ef970307b46f22",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/database": "1.*"
"utopia-php/database": "2.*"
},
"require-dev": {
"laravel/pint": "1.*",
@@ -3434,9 +3431,64 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/1.0.0"
"source": "https://github.com/utopia-php/audit/tree/1.0.1"
},
"time": "2025-08-13T09:09:00+00:00"
"time": "2025-09-04T12:46:43+00:00"
},
{
"name": "utopia-php/auth",
"version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/auth.git",
"reference": "02415e1a89cdbc14e3e16a7856ecf7f868869449"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/auth/zipball/02415e1a89cdbc14e3e16a7856ecf7f868869449",
"reference": "02415e1a89cdbc14e3e16a7856ecf7f868869449",
"shasum": ""
},
"require": {
"ext-hash": "*",
"ext-scrypt": "*",
"ext-sodium": "*",
"php": ">=8.0"
},
"require-dev": {
"laravel/pint": "1.2.*",
"phpstan/phpstan": "1.9.x-dev",
"phpunit/phpunit": "^9.3",
"vimeo/psalm": "4.0.1"
},
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\Auth\\": "src/Auth"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Utopia PHP",
"email": "team@appwrite.io"
}
],
"description": "A simple PHP authentication library",
"keywords": [
"Authentication",
"auth",
"php",
"security"
],
"support": {
"issues": "https://github.com/utopia-php/auth/issues",
"source": "https://github.com/utopia-php/auth/tree/0.4.0"
},
"time": "2025-04-29T19:29:28+00:00"
},
{
"name": "utopia-php/cache",
@@ -3638,16 +3690,16 @@
},
{
"name": "utopia-php/database",
"version": "1.4.8",
"version": "2.3.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "dbecdf89fde33a5f81ec19f4f97fe0c3715dc83a"
"reference": "35c978ddd20b649d119296094686d3cc9fcf161f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/dbecdf89fde33a5f81ec19f4f97fe0c3715dc83a",
"reference": "dbecdf89fde33a5f81ec19f4f97fe0c3715dc83a",
"url": "https://api.github.com/repos/utopia-php/database/zipball/35c978ddd20b649d119296094686d3cc9fcf161f",
"reference": "35c978ddd20b649d119296094686d3cc9fcf161f",
"shasum": ""
},
"require": {
@@ -3688,9 +3740,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/1.4.8"
"source": "https://github.com/utopia-php/database/tree/2.3.2"
},
"time": "2025-09-12T03:35:59+00:00"
"time": "2025-10-07T03:09:32+00:00"
},
{
"name": "utopia-php/detector",
@@ -3795,16 +3847,16 @@
},
{
"name": "utopia-php/domains",
"version": "0.8.0",
"version": "0.8.4",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/domains.git",
"reference": "650463d2a1525273eb03223c48da9fb1a768bbf7"
"reference": "316a76b0fcbc7f82e40be466c22c19acb243ee22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/650463d2a1525273eb03223c48da9fb1a768bbf7",
"reference": "650463d2a1525273eb03223c48da9fb1a768bbf7",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/316a76b0fcbc7f82e40be466c22c19acb243ee22",
"reference": "316a76b0fcbc7f82e40be466c22c19acb243ee22",
"shasum": ""
},
"require": {
@@ -3850,9 +3902,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/domains/issues",
"source": "https://github.com/utopia-php/domains/tree/0.8.0"
"source": "https://github.com/utopia-php/domains/tree/0.8.4"
},
"time": "2025-05-16T10:03:59+00:00"
"time": "2025-10-17T11:31:56+00:00"
},
{
"name": "utopia-php/dsn",
@@ -3942,16 +3994,16 @@
},
{
"name": "utopia-php/framework",
"version": "0.33.27",
"version": "0.33.28",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/http.git",
"reference": "d9d10a895e85c8c7675220347cc6109db9d3bd37"
"reference": "5aaa94d406577b0059ad28c78022606890dc6de0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/http/zipball/d9d10a895e85c8c7675220347cc6109db9d3bd37",
"reference": "d9d10a895e85c8c7675220347cc6109db9d3bd37",
"url": "https://api.github.com/repos/utopia-php/http/zipball/5aaa94d406577b0059ad28c78022606890dc6de0",
"reference": "5aaa94d406577b0059ad28c78022606890dc6de0",
"shasum": ""
},
"require": {
@@ -3983,9 +4035,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/http/issues",
"source": "https://github.com/utopia-php/http/tree/0.33.27"
"source": "https://github.com/utopia-php/http/tree/0.33.28"
},
"time": "2025-09-07T18:40:53+00:00"
"time": "2025-09-25T10:44:24+00:00"
},
{
"name": "utopia-php/image",
@@ -4139,16 +4191,16 @@
},
{
"name": "utopia-php/messaging",
"version": "0.18.2",
"version": "0.19.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/messaging.git",
"reference": "0d364edacf4d4867964c7e17f653031dd39394bf"
"reference": "0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/0d364edacf4d4867964c7e17f653031dd39394bf",
"reference": "0d364edacf4d4867964c7e17f653031dd39394bf",
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8",
"reference": "0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8",
"shasum": ""
},
"require": {
@@ -4184,22 +4236,22 @@
],
"support": {
"issues": "https://github.com/utopia-php/messaging/issues",
"source": "https://github.com/utopia-php/messaging/tree/0.18.2"
"source": "https://github.com/utopia-php/messaging/tree/0.19.0"
},
"time": "2025-07-21T18:27:03+00:00"
"time": "2025-10-14T11:46:49+00:00"
},
{
"name": "utopia-php/migration",
"version": "1.1.1",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "c42935a6a4ee3701c68d24244e82ecb39e945ec4"
"reference": "6fb6f8f032cd34c3c65728a55d494adeac2ff038"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/c42935a6a4ee3701c68d24244e82ecb39e945ec4",
"reference": "c42935a6a4ee3701c68d24244e82ecb39e945ec4",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/6fb6f8f032cd34c3c65728a55d494adeac2ff038",
"reference": "6fb6f8f032cd34c3c65728a55d494adeac2ff038",
"shasum": ""
},
"require": {
@@ -4207,7 +4259,7 @@
"ext-curl": "*",
"ext-openssl": "*",
"php": ">=8.1",
"utopia-php/database": "1.*",
"utopia-php/database": "2.*",
"utopia-php/dsn": "0.2.*",
"utopia-php/framework": "0.33.*",
"utopia-php/storage": "0.18.*"
@@ -4240,9 +4292,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/1.1.1"
"source": "https://github.com/utopia-php/migration/tree/1.1.0"
},
"time": "2025-09-10T06:17:20+00:00"
"time": "2025-09-10T05:45:30+00:00"
},
{
"name": "utopia-php/orchestration",
@@ -4569,16 +4621,16 @@
},
{
"name": "utopia-php/storage",
"version": "0.18.13",
"version": "0.18.14",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/storage.git",
"reference": "3d8ce53ae042173bf230445e996056c5f65ded22"
"reference": "4f14ec952c6f4006dd0613e55bbf7631814fbc00"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/3d8ce53ae042173bf230445e996056c5f65ded22",
"reference": "3d8ce53ae042173bf230445e996056c5f65ded22",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/4f14ec952c6f4006dd0613e55bbf7631814fbc00",
"reference": "4f14ec952c6f4006dd0613e55bbf7631814fbc00",
"shasum": ""
},
"require": {
@@ -4621,9 +4673,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/storage/issues",
"source": "https://github.com/utopia-php/storage/tree/0.18.13"
"source": "https://github.com/utopia-php/storage/tree/0.18.14"
},
"time": "2025-05-26T13:10:35+00:00"
"time": "2025-10-07T10:21:47+00:00"
},
{
"name": "utopia-php/swoole",
@@ -5007,16 +5059,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "1.3.4",
"version": "1.4.4",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "d3b420dced42f1eec1f6d0aa98b7bbf8de4042ac"
"reference": "a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/d3b420dced42f1eec1f6d0aa98b7bbf8de4042ac",
"reference": "d3b420dced42f1eec1f6d0aa98b7bbf8de4042ac",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49",
"reference": "a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49",
"shasum": ""
},
"require": {
@@ -5052,9 +5104,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/1.3.4"
"source": "https://github.com/appwrite/sdk-generator/tree/1.4.4"
},
"time": "2025-09-08T11:56:04+00:00"
"time": "2025-10-13T09:20:49+00:00"
},
{
"name": "doctrine/annotations",
@@ -5130,6 +5182,7 @@
"issues": "https://github.com/doctrine/annotations/issues",
"source": "https://github.com/doctrine/annotations/tree/2.0.2"
},
"abandoned": true,
"time": "2024-09-05T10:17:24+00:00"
},
{
@@ -5281,16 +5334,16 @@
},
{
"name": "laravel/pint",
"version": "v1.24.0",
"version": "v1.25.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a"
"reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a",
"reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a",
"url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9",
"reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9",
"shasum": ""
},
"require": {
@@ -5301,9 +5354,9 @@
"php": "^8.2.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.82.2",
"illuminate/view": "^11.45.1",
"larastan/larastan": "^3.5.0",
"friendsofphp/php-cs-fixer": "^3.87.2",
"illuminate/view": "^11.46.0",
"larastan/larastan": "^3.7.1",
"laravel-zero/framework": "^11.45.0",
"mockery/mockery": "^1.6.12",
"nunomaduro/termwind": "^2.3.1",
@@ -5314,9 +5367,6 @@
],
"type": "project",
"autoload": {
"files": [
"overrides/Runner/Parallel/ProcessFactory.php"
],
"psr-4": {
"App\\": "app/",
"Database\\Seeders\\": "database/seeders/",
@@ -5346,7 +5396,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2025-07-10T18:09:32+00:00"
"time": "2025-09-19T02:57:12+00:00"
},
{
"name": "matthiasmullie/minify",
@@ -6236,16 +6286,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.6.26",
"version": "9.6.29",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "a0139ea157533454f611038326f3020b3051f129"
"reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a0139ea157533454f611038326f3020b3051f129",
"reference": "a0139ea157533454f611038326f3020b3051f129",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9ecfec57835a5581bc888ea7e13b51eb55ab9dd3",
"reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3",
"shasum": ""
},
"require": {
@@ -6270,7 +6320,7 @@
"sebastian/comparator": "^4.0.9",
"sebastian/diff": "^4.0.6",
"sebastian/environment": "^5.1.5",
"sebastian/exporter": "^4.0.6",
"sebastian/exporter": "^4.0.8",
"sebastian/global-state": "^5.0.8",
"sebastian/object-enumerator": "^4.0.4",
"sebastian/resource-operations": "^3.0.4",
@@ -6319,7 +6369,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.26"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.29"
},
"funding": [
{
@@ -6343,7 +6393,7 @@
"type": "tidelift"
}
],
"time": "2025-09-11T06:17:45+00:00"
"time": "2025-09-24T06:29:11+00:00"
},
{
"name": "psr/cache",
@@ -6835,16 +6885,16 @@
},
{
"name": "sebastian/exporter",
"version": "4.0.6",
"version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72"
"reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72",
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c",
"reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c",
"shasum": ""
},
"require": {
@@ -6900,15 +6950,27 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6"
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
"type": "tidelift"
}
],
"time": "2024-03-02T06:33:00+00:00"
"time": "2025-09-24T06:03:27+00:00"
},
{
"name": "sebastian/global-state",
@@ -7491,16 +7553,16 @@
},
{
"name": "symfony/console",
"version": "v7.3.3",
"version": "v7.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7"
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7",
"reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7",
"url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"shasum": ""
},
"require": {
@@ -7565,7 +7627,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.3.3"
"source": "https://github.com/symfony/console/tree/v7.3.4"
},
"funding": [
{
@@ -7585,7 +7647,7 @@
"type": "tidelift"
}
],
"time": "2025-08-25T06:35:40+00:00"
"time": "2025-09-22T15:31:00+00:00"
},
{
"name": "symfony/filesystem",
@@ -8128,16 +8190,16 @@
},
{
"name": "symfony/process",
"version": "v7.3.3",
"version": "v7.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "32241012d521e2e8a9d713adb0812bb773b907f1"
"reference": "f24f8f316367b30810810d4eb30c543d7003ff3b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1",
"reference": "32241012d521e2e8a9d713adb0812bb773b907f1",
"url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b",
"reference": "f24f8f316367b30810810d4eb30c543d7003ff3b",
"shasum": ""
},
"require": {
@@ -8169,7 +8231,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v7.3.3"
"source": "https://github.com/symfony/process/tree/v7.3.4"
},
"funding": [
{
@@ -8189,20 +8251,20 @@
"type": "tidelift"
}
],
"time": "2025-08-18T09:42:54+00:00"
"time": "2025-09-11T10:12:26+00:00"
},
{
"name": "symfony/string",
"version": "v7.3.3",
"version": "v7.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c"
"reference": "f96476035142921000338bad71e5247fbc138872"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
"reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
"url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872",
"reference": "f96476035142921000338bad71e5247fbc138872",
"shasum": ""
},
"require": {
@@ -8217,7 +8279,6 @@
},
"require-dev": {
"symfony/emoji": "^7.1",
"symfony/error-handler": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/intl": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
@@ -8260,7 +8321,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v7.3.3"
"source": "https://github.com/symfony/string/tree/v7.3.4"
},
"funding": [
{
@@ -8280,7 +8341,7 @@
"type": "tidelift"
}
],
"time": "2025-08-25T06:35:40+00:00"
"time": "2025-09-11T14:36:48+00:00"
},
{
"name": "textalk/websocket",
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Account;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Account account = new Account(client);
account.createEmailVerification(
"https://example.com", // url
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -0,0 +1,23 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Account;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Account account = new Account(client);
account.updateEmailVerification(
"<USER_ID>", // userId
"<SECRET>", // secret
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -20,6 +20,7 @@ databases.createDocument(
"isAdmin" to false
), // data
listOf("read("any")"), // permissions (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,33 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.createOperations(
"<TRANSACTION_ID>", // transactionId
listOf(
{
"action": "create",
"databaseId": "<DATABASE_ID>",
"collectionId": "<COLLECTION_ID>",
"documentId": "<DOCUMENT_ID>",
"data": {
"name": "Walter O'Brien"
}
}
), // operations (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.createTransaction(
60, // ttl (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -15,6 +15,7 @@ databases.decrementDocumentAttribute(
"", // attribute
0, // value (optional)
0, // min (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -12,6 +12,7 @@ databases.deleteDocument(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
"<DOCUMENT_ID>", // documentId
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.deleteTransaction(
"<TRANSACTION_ID>", // transactionId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -13,6 +13,7 @@ databases.getDocument(
"<COLLECTION_ID>", // collectionId
"<DOCUMENT_ID>", // documentId
listOf(), // queries (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.getTransaction(
"<TRANSACTION_ID>", // transactionId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -15,6 +15,7 @@ databases.incrementDocumentAttribute(
"", // attribute
0, // value (optional)
0, // max (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -12,6 +12,7 @@ databases.listDocuments(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
listOf(), // queries (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.listTransactions(
listOf(), // queries (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -14,6 +14,7 @@ databases.updateDocument(
"<DOCUMENT_ID>", // documentId
mapOf( "a" to "b" ), // data (optional)
listOf("read("any")"), // permissions (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,24 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.updateTransaction(
"<TRANSACTION_ID>", // transactionId
false, // commit (optional)
false, // rollback (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -14,6 +14,7 @@ databases.upsertDocument(
"<DOCUMENT_ID>", // documentId
mapOf( "a" to "b" ), // data
listOf("read("any")"), // permissions (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,33 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.TablesDB;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
TablesDB tablesDB = new TablesDB(client);
tablesDB.createOperations(
"<TRANSACTION_ID>", // transactionId
listOf(
{
"action": "create",
"databaseId": "<DATABASE_ID>",
"tableId": "<TABLE_ID>",
"rowId": "<ROW_ID>",
"data": {
"name": "Walter O'Brien"
}
}
), // operations (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -20,6 +20,7 @@ tablesDB.createRow(
"isAdmin" to false
), // data
listOf("read("any")"), // permissions (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.TablesDB;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
TablesDB tablesDB = new TablesDB(client);
tablesDB.createTransaction(
60, // ttl (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -15,6 +15,7 @@ tablesDB.decrementRowColumn(
"", // column
0, // value (optional)
0, // min (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -12,6 +12,7 @@ tablesDB.deleteRow(
"<DATABASE_ID>", // databaseId
"<TABLE_ID>", // tableId
"<ROW_ID>", // rowId
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.TablesDB;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
TablesDB tablesDB = new TablesDB(client);
tablesDB.deleteTransaction(
"<TRANSACTION_ID>", // transactionId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -13,6 +13,7 @@ tablesDB.getRow(
"<TABLE_ID>", // tableId
"<ROW_ID>", // rowId
listOf(), // queries (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.TablesDB;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
TablesDB tablesDB = new TablesDB(client);
tablesDB.getTransaction(
"<TRANSACTION_ID>", // transactionId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -15,6 +15,7 @@ tablesDB.incrementRowColumn(
"", // column
0, // value (optional)
0, // max (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -12,6 +12,7 @@ tablesDB.listRows(
"<DATABASE_ID>", // databaseId
"<TABLE_ID>", // tableId
listOf(), // queries (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,22 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.TablesDB;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
TablesDB tablesDB = new TablesDB(client);
tablesDB.listTransactions(
listOf(), // queries (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -14,6 +14,7 @@ tablesDB.updateRow(
"<ROW_ID>", // rowId
mapOf( "a" to "b" ), // data (optional)
listOf("read("any")"), // permissions (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,24 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.TablesDB;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
TablesDB tablesDB = new TablesDB(client);
tablesDB.updateTransaction(
"<TRANSACTION_ID>", // transactionId
false, // commit (optional)
false, // rollback (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -14,6 +14,7 @@ tablesDB.upsertRow(
"<ROW_ID>", // rowId
mapOf( "a" to "b" ), // data (optional)
listOf("read("any")"), // permissions (optional)
"<TRANSACTION_ID>", // transactionId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val account = Account(client)
val result = account.createEmailVerification(
url = "https://example.com",
)
@@ -0,0 +1,14 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val account = Account(client)
val result = account.updateEmailVerification(
userId = "<USER_ID>",
secret = "<SECRET>",
)
@@ -20,4 +20,5 @@ val result = databases.createDocument(
"isAdmin" to false
),
permissions = listOf("read("any")"), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,24 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.createOperations(
transactionId = "<TRANSACTION_ID>",
operations = listOf(
{
"action": "create",
"databaseId": "<DATABASE_ID>",
"collectionId": "<COLLECTION_ID>",
"documentId": "<DOCUMENT_ID>",
"data": {
"name": "Walter O'Brien"
}
}
), // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.createTransaction(
ttl = 60, // (optional)
)
@@ -15,4 +15,5 @@ val result = databases.decrementDocumentAttribute(
attribute = "",
value = 0, // (optional)
min = 0, // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -12,4 +12,5 @@ val result = databases.deleteDocument(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = "<DOCUMENT_ID>",
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.deleteTransaction(
transactionId = "<TRANSACTION_ID>",
)
@@ -13,4 +13,5 @@ val result = databases.getDocument(
collectionId = "<COLLECTION_ID>",
documentId = "<DOCUMENT_ID>",
queries = listOf(), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.getTransaction(
transactionId = "<TRANSACTION_ID>",
)
@@ -15,4 +15,5 @@ val result = databases.incrementDocumentAttribute(
attribute = "",
value = 0, // (optional)
max = 0, // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -12,4 +12,5 @@ val result = databases.listDocuments(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = listOf(), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.listTransactions(
queries = listOf(), // (optional)
)
@@ -14,4 +14,5 @@ val result = databases.updateDocument(
documentId = "<DOCUMENT_ID>",
data = mapOf( "a" to "b" ), // (optional)
permissions = listOf("read("any")"), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,15 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.updateTransaction(
transactionId = "<TRANSACTION_ID>",
commit = false, // (optional)
rollback = false, // (optional)
)
@@ -14,4 +14,5 @@ val result = databases.upsertDocument(
documentId = "<DOCUMENT_ID>",
data = mapOf( "a" to "b" ),
permissions = listOf("read("any")"), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,24 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.TablesDB
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val tablesDB = TablesDB(client)
val result = tablesDB.createOperations(
transactionId = "<TRANSACTION_ID>",
operations = listOf(
{
"action": "create",
"databaseId": "<DATABASE_ID>",
"tableId": "<TABLE_ID>",
"rowId": "<ROW_ID>",
"data": {
"name": "Walter O'Brien"
}
}
), // (optional)
)
@@ -20,4 +20,5 @@ val result = tablesDB.createRow(
"isAdmin" to false
),
permissions = listOf("read("any")"), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.TablesDB
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val tablesDB = TablesDB(client)
val result = tablesDB.createTransaction(
ttl = 60, // (optional)
)
@@ -15,4 +15,5 @@ val result = tablesDB.decrementRowColumn(
column = "",
value = 0, // (optional)
min = 0, // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -12,4 +12,5 @@ val result = tablesDB.deleteRow(
databaseId = "<DATABASE_ID>",
tableId = "<TABLE_ID>",
rowId = "<ROW_ID>",
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.TablesDB
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val tablesDB = TablesDB(client)
val result = tablesDB.deleteTransaction(
transactionId = "<TRANSACTION_ID>",
)
@@ -13,4 +13,5 @@ val result = tablesDB.getRow(
tableId = "<TABLE_ID>",
rowId = "<ROW_ID>",
queries = listOf(), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.TablesDB
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val tablesDB = TablesDB(client)
val result = tablesDB.getTransaction(
transactionId = "<TRANSACTION_ID>",
)
@@ -15,4 +15,5 @@ val result = tablesDB.incrementRowColumn(
column = "",
value = 0, // (optional)
max = 0, // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -12,4 +12,5 @@ val result = tablesDB.listRows(
databaseId = "<DATABASE_ID>",
tableId = "<TABLE_ID>",
queries = listOf(), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)
@@ -0,0 +1,13 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.TablesDB
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val tablesDB = TablesDB(client)
val result = tablesDB.listTransactions(
queries = listOf(), // (optional)
)
@@ -14,4 +14,5 @@ val result = tablesDB.updateRow(
rowId = "<ROW_ID>",
data = mapOf( "a" to "b" ), // (optional)
permissions = listOf("read("any")"), // (optional)
transactionId = "<TRANSACTION_ID>", // (optional)
)

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