Compare commits

...
1246 Commits
Author SHA1 Message Date
Jake Barnby bfd862cb99 Revert "Merge pull request #9879 from appwrite/revert-9865-feat-sequence"
This reverts commit d8904af909, reversing
changes made to a366feba80.

# Conflicts:
#	composer.lock
2025-05-26 17:07:35 +12:00
Jake Barnby 3571f35d0d Merge branch 'feat-sync' of github.com:appwrite/appwrite into feat-sync
# Conflicts:
#	app/controllers/api/databases.php
#	composer.lock
2025-05-26 17:05:37 +12:00
Jake Barnby a01e7b8619 Merge remote-tracking branch 'origin/1.7.x' into feat-sync 2025-05-26 17:00:55 +12:00
Steven NguyenandGitHub 568f6fd274 Merge pull request #9891 from appwrite/chore-update-console-6-0-13
Update console image to version 6.0.13
2025-05-25 11:15:06 -07:00
Torsten DittmannandGitHub 43d84c680e Merge pull request #9893 from appwrite/chore-upgrade-to-1-7-4
Update version from 1.7.3 to 1.7.4
2025-05-25 19:45:23 +02:00
Torsten Dittmann 7531c64b31 Update version from 1.7.3 to 1.7.4 2025-05-25 19:44:51 +02:00
Torsten Dittmann ddf5b8e156 Update console image to version 6.0.13 2025-05-25 19:39:06 +02:00
Matej BačoandGitHub 3bb5e9085e Merge pull request #9886 from appwrite/fix-console-sdk-file-upload
Chore: Upgrade to fix createDeployment chunk upload
2025-05-25 01:06:41 +02:00
Matej Bačo d3533840c8 Chore: Use release, not branch 2025-05-25 00:50:51 +02:00
Matej Bačo aa9f554853 Fix chunk uploaded manual deployment 2025-05-25 00:05:30 +02:00
Matej Bačo eb8da87eed Fix bug; trigger sdk generation 2025-05-24 23:47:27 +02:00
Matej Bačo 17eab0ecb5 Upgrade to fix createDeployment chunk upload 2025-05-24 23:42:19 +02:00
Steven NguyenandGitHub 4c5094d3dc Merge pull request #9883 from appwrite/fix-migration-default-region
fix(migration): _APP_DEFAULT_REGION is not a valid env var
2025-05-23 20:09:09 -07:00
Steven Nguyen 295e2773f3 fix(migration): _APP_DEFAULT_REGION is not a valid env var
Across the rest of the codebase, we use _APP_REGION with 'default' as
the fallback value. This commit updates the migration to do the same.
2025-05-23 17:46:07 -07:00
Steven NguyenandGitHub 341bcb5222 Merge pull request #9882 from appwrite/feat-1.7.3-release-prep
Prepare 1.7.3 release
2025-05-23 17:45:42 -07:00
Steven Nguyen b932db34f3 Bump appwrite version to 1.7.3 2025-05-23 16:01:00 -07:00
Steven NguyenandGitHub 7208729805 Merge pull request #9881 from appwrite/chore-bump-console-6.0.11
Bump console to version 6.0.11
2025-05-23 16:00:38 -07:00
Steven NguyenandGitHub f9a74868ff Merge pull request #9856 from appwrite/fix-migration-rule-owner
fix(migration): set owner and region while migrating rules
2025-05-23 15:24:33 -07:00
Steven Nguyen 0ec7dcf08d Bump console to version 6.0.11 2025-05-23 15:07:45 -07:00
Steven Nguyen 8ce46c791f fix(migration): set owner and region while migrating rules
These attributes were added to the rules collection in 1.6.2, but the
migration script was not updated to set them. Because they're empty, the
1.7 migration fails while updating rules documents because region is
required.
2025-05-23 15:06:19 -07:00
Eldad A. FuxandGitHub d8904af909 Merge pull request #9879 from appwrite/revert-9865-feat-sequence
Revert "Feat sequence"
2025-05-23 21:41:15 +01:00
Christy JacobandGitHub 28d2ed1baa Revert "Feat sequence" 2025-05-23 21:39:56 +04:00
Jake BarnbyandGitHub a366feba80 Merge pull request #9878 from ArnabChatterjee20k/dat-532
updated errro for the string encryption
2025-05-23 15:27:35 +00:00
Christy JacobandGitHub 484988fcd7 Merge pull request #9875 from appwrite/fix-add-region-to-github-related-urls
Fix URL for view logs in github comment
2025-05-23 19:19:33 +04:00
ArnabChatterjee20k 49f8369fdd updated the message 2025-05-23 20:45:36 +05:30
ArnabChatterjee20k 6af9d1206d added a constant 2025-05-23 20:41:08 +05:30
ArnabChatterjee20k 14fe7a3293 updated errro for the string encryption 2025-05-23 20:35:59 +05:30
Khushboo Verma 1434e69b94 Merge branch 'main' into fix-add-region-to-github-related-urls 2025-05-23 20:12:53 +05:30
Khushboo Verma 65a220b702 Fix URL for view logs in github comment 2025-05-23 20:11:27 +05:30
Christy JacobandGitHub ec77137768 Merge pull request #9873 from appwrite/feat-add-builds-worker-group-main
feat: add builds worker group
2025-05-23 17:51:55 +04:00
loks0n 18335ebf89 feat: add builds worker group 2025-05-23 14:29:31 +01:00
Jake Barnby d27dba05d2 Merge pull request #9841 from ArnabChatterjee20k/dat-532
added checking for encrypt and plan allowing encryption of string att…
2025-05-23 23:54:18 +12:00
Jake Barnby 1a2a725cb0 Merge pull request #9868 from ArnabChatterjee20k/dat-532
added encrypt property in the attribute string response model
2025-05-23 23:53:23 +12:00
Jake BarnbyandGitHub 39d45bdca9 Merge pull request #9865 from appwrite/feat-sequence
Feat sequence
2025-05-23 10:14:15 +00:00
DarshanandGitHub a413a613f5 Merge branch 'main' into feat-sequence 2025-05-23 15:35:39 +05:30
Jake BarnbyandGitHub 5eab81cf03 Merge pull request #9868 from ArnabChatterjee20k/dat-532
added encrypt property in the attribute string response model
2025-05-23 09:03:42 +00:00
ArnabChatterjee20k b8cb6f281d linting 2025-05-23 14:19:00 +05:30
ArnabChatterjee20k 7c760e4b07 linting 2025-05-23 14:16:35 +05:30
ArnabChatterjee20k e586afceb7 updates 2025-05-23 14:11:57 +05:30
ArnabChatterjee20k 6ea3593921 updated collection filter 2025-05-23 13:40:56 +05:30
ArnabChatterjee20k 73764941b6 updated tests and collection method 2025-05-23 13:23:33 +05:30
Jake Barnby 14274d96aa Update libs 2025-05-23 19:42:43 +12:00
Jake Barnby 587b84d04a Merge remote-tracking branch 'origin/1.7.x' into feat-sequence 2025-05-23 19:40:57 +12:00
Jake Barnby fec814e0ec Merge remote-tracking branch 'origin/main' into feat-sequence 2025-05-23 19:40:48 +12:00
ArnabChatterjee20k 02426df1ca linting 2025-05-23 12:53:10 +05:30
ArnabChatterjee20k 1d0577b07d added encrypt to the get and list atttributes 2025-05-23 12:51:59 +05:30
ArnabChatterjee20k 1a4a10400b added test for the encrypted string in the server 2025-05-23 12:12:23 +05:30
ArnabChatterjee20k 0cccb75273 added encrypt property in the attribute string response model 2025-05-23 12:05:42 +05:30
Steven NguyenandGitHub 6526e8d956 Merge pull request #9842 from appwrite/pla-2914
chore: use unique filename for health check
2025-05-22 17:30:32 -07:00
Steven NguyenandGitHub 1e220766b2 Merge pull request #9858 from appwrite/update-flutter-docs
chore: update flutter_web_auth_2 docs to match 4.x
2025-05-22 15:14:25 -07:00
Matej BačoandGitHub 57ee69ad9a Merge pull request #9866 from appwrite/fix-unlimited-deployment-size
Fix: unlimited deployment size
2025-05-22 17:34:54 +02:00
Jake Barnby 04a9b0be34 Fix replace 2025-05-23 03:29:44 +12:00
Matej Bačo b4f5af8461 Fix: unlimited deployment size 2025-05-22 17:25:47 +02:00
Jake Barnby f6bf779119 Update database 2025-05-23 02:57:11 +12:00
Jake Barnby 71e3446498 Change internal ID to sequence 2025-05-23 02:55:29 +12:00
Matej BačoandGitHub 4adea70684 Merge pull request #9863 from appwrite/feat-add-configurable-resource-size
Add configurable deployment and build size
2025-05-22 15:28:40 +02:00
Matej BačoandGitHub 9321f585f5 Update app/worker.php 2025-05-22 15:22:40 +02:00
Jake BarnbyandGitHub 91d729cc55 Merge pull request #9864 from appwrite/fix-generic-s3
Fix bucket not included in path
2025-05-22 13:09:53 +00:00
Jake Barnby bd01d12db5 Format 2025-05-23 00:51:31 +12:00
Jake Barnby d2d9032ede Fix bucket not included in path 2025-05-23 00:49:26 +12:00
Khushboo Verma b727b8c100 Add configurable deployment and build size 2025-05-22 18:01:34 +05:30
Christy JacobandGitHub 9df0045024 Merge pull request #9861 from appwrite/fix-cname-validation
Fix: CNAME validation
2025-05-22 14:15:27 +04:00
Christy JacobandGitHub 3c74818591 Merge pull request #9859 from appwrite/sites-certificates
fix: send deploymentResourceType in rules verification
2025-05-22 13:30:18 +04:00
Matej BačoandGitHub a734ae163a Merge pull request #9860 from appwrite/fix-error-page-for-development
Only load error page for development mode
2025-05-22 10:31:46 +02:00
Matej Bačo 67a5192705 Fix CNAME validation 2025-05-22 10:13:12 +02:00
Fabian Gruber 128dc1d946 fix: send deploymentResourceType in rules verification 2025-05-22 10:05:45 +02:00
Khushboo Verma d283c820da Only load error page for development mode 2025-05-22 13:34:25 +05:30
Chirag Aggarwal 86526fa1df chore: update changelog 2025-05-22 06:11:28 +00:00
Chirag Aggarwal c5f7a72409 chore: update flutter_web_auth_2 docs to match 4.x 2025-05-22 06:03:35 +00:00
Matej BačoandGitHub 6b7071ca94 Merge pull request #9852 from appwrite/fix-double-logs
Fix: double logs on failure
2025-05-21 16:59:24 +02:00
Matej Bačo 83e62dc6e1 Fix double logs on failure 2025-05-21 16:44:04 +02:00
Christy JacobandGitHub 02de47f1dc Merge pull request #9850 from appwrite/task-coroutine-hooks-1.6
fix: task coroutine hooks
2025-05-21 18:31:57 +04:00
Fabian Gruber 241a0c88e1 fix: task coroutine hooks 2025-05-21 16:21:11 +02:00
Jake BarnbyandGitHub 341775de2e Merge pull request #9848 from appwrite/cors-allow-dev-key
fix: allow devkeys header to pass CORS
2025-05-21 11:42:21 +00:00
Chirag Aggarwal eda1bf3207 chore: update test 2025-05-21 11:05:25 +00:00
Luke B. SilverandGitHub 30915b4803 Merge branch 'main' into cors-allow-dev-key 2025-05-21 11:53:09 +01:00
Chirag Aggarwal d9bd867b38 fix: allow devkeys header to pass CORS 2025-05-21 10:32:56 +00:00
Jake BarnbyandGitHub 86b64fdee8 Merge pull request #9845 from appwrite/feat-sync-1.6.x
Sync 1.6.x
2025-05-21 09:59:56 +00:00
Jake BarnbyandGitHub 8fec677579 Merge pull request #9846 from appwrite/feat-sync-1.7.x
Sync 1.7.x
2025-05-21 09:59:45 +00:00
Christy JacobandGitHub 27fae92b89 Merge pull request #9847 from appwrite/PLA-2928
fix(storage): do not allow full range
2025-05-21 13:16:24 +04:00
Fabian Gruber ba3f907028 fix(storage): do not allow full range
This prevents requests with `Range: 0-<file length>` and limits it to APP_STORAGE_READ_BUFFER
2025-05-21 10:57:58 +02:00
Jake BarnbyandGitHub eab446a828 Merge pull request #9841 from ArnabChatterjee20k/dat-532
added checking for encrypt and plan allowing encryption of string att…
2025-05-21 08:51:31 +00:00
Christy JacobandGitHub d25800973c Merge pull request #9826 from appwrite/feat-1.7.2-release-prep
Prepare 1.7.2 release
2025-05-21 12:40:36 +04:00
Jake Barnby 0024926e11 Merge remote-tracking branch 'origin/1.7.x' into feat-sync-1.7.x 2025-05-21 20:15:41 +12:00
Matej BačoandGitHub 8734aeb314 Merge pull request #9844 from appwrite/1.7.x
Append build error to build logs
2025-05-21 10:15:20 +02:00
Jake Barnby 3ec0f08db1 Merge remote-tracking branch 'origin/1.6.x' into feat-sync-1.6.x
# Conflicts:
#	composer.lock
#	src/Appwrite/Messaging/Adapter/Realtime.php
#	src/Appwrite/Platform/Workers/Deletes.php
2025-05-21 20:15:08 +12:00
ArnabChatterjee20k c4df1c8c4b updated exception type 2025-05-21 13:34:08 +05:30
Matej BačoandGitHub 61b20160f4 Merge pull request #9836 from appwrite/fix-show-build-logs-on-failure
Append build error to build logs
2025-05-21 10:02:57 +02:00
Jake BarnbyandGitHub b8a744d088 Merge pull request #9837 from appwrite/feat-dev-key-to-clients
feat: add dev key to clients
2025-05-21 08:00:22 +00:00
ArnabChatterjee20k 82fd8553bf updated the condition 2025-05-21 13:29:24 +05:30
ArnabChatterjee20k 8796670c66 reverted test 2025-05-21 13:19:07 +05:30
Jake BarnbyandGitHub c96232f764 Merge pull request #9843 from appwrite/feat-sync-upsert
Merge pull request #9811 from ArnabChatterjee20k/upsert-single-docume…
2025-05-21 07:44:39 +00:00
ArnabChatterjee20k 9fa6deae61 reverted the tests and updated the plan checking condition 2025-05-21 13:14:22 +05:30
Jake Barnby 20f2cbffda Merge pull request #9811 from ArnabChatterjee20k/upsert-single-document-route
Upsert single document route
2025-05-21 19:29:31 +12:00
Chirag Aggarwal fe5419401a chore: use unique filename for health check 2025-05-21 07:28:25 +00:00
Chirag Aggarwal cca95d5bd2 chore: update to minor versions 2025-05-21 06:36:09 +00:00
ArnabChatterjee20k 43aae24132 updated tests for the custom server test 2025-05-21 11:38:34 +05:30
ArnabChatterjee20k f534b9e460 added checking for encrypt and plan allowing encryption of string attribute 2025-05-21 11:00:01 +05:30
Chirag Aggarwal d302718757 chore: update sdks 2025-05-21 05:19:31 +00:00
Steven NguyenandGitHub e5ad27c33a Merge pull request #9840 from appwrite/1.7.x
Merge 1.7.x into main
2025-05-20 20:49:20 -07:00
Chirag AggarwalandGitHub 58c3232578 Merge branch 'main' into feat-dev-key-to-clients 2025-05-21 09:17:17 +05:30
Steven Nguyen ac8105dea2 Bump appwrite version to 1.7.2 2025-05-20 17:29:32 -07:00
Jake BarnbyandGitHub cbba893f53 Merge pull request #9829 from appwrite/fix-empty-function-migration
Fix migrating functions with no deployments
2025-05-21 00:24:34 +00:00
loks0n dde0dd2218 feat: add dev key to clients 2025-05-20 23:05:48 +01:00
Khushboo Verma 3335f56cf6 Append build error to build logs 2025-05-20 21:15:05 +05:30
Jake BarnbyandGitHub 815849aa64 Merge pull request #9811 from ArnabChatterjee20k/upsert-single-document-route
Upsert single document route
2025-05-20 14:37:10 +00:00
Jake BarnbyandGitHub 727bac5f3d Merge pull request #9834 from appwrite/fix-missing-catch
Catch query exception on get document for selects
2025-05-20 14:32:20 +00:00
Jake BarnbyandGitHub 9f14f1152a Update app/controllers/api/databases.php 2025-05-21 02:22:51 +12:00
Jake Barnby bc34f95646 Update lock 2025-05-21 01:13:08 +12:00
Matej BačoandGitHub dbc66d2221 Merge pull request #9835 from appwrite/feat-lynx-gallery
Feat: Add lynx gallery
2025-05-20 15:10:59 +02:00
Matej Bačo e8661e6d31 Fix starter template for flutter 2025-05-20 15:10:37 +02:00
Matej Bačo 2ad4390958 Add lynx gallery 2025-05-20 15:03:45 +02:00
Jake Barnby fe763093df Catch query exception on get document for selects 2025-05-21 00:58:32 +12:00
ArnabChatterjee20k c5a08b69b0 changed custom id to uid 2025-05-20 18:14:51 +05:30
Matej BačoandGitHub 00e3397b56 Merge pull request #9833 from appwrite/chore-upgrade-console
Chore: Upgrade console
2025-05-20 14:17:18 +02:00
Matej Bačo 69adb689f8 Upgrade console 2025-05-20 14:16:04 +02:00
Matej BačoandGitHub 0379086c48 Merge pull request #9820 from appwrite/update-desc
Update: token desc
2025-05-20 13:35:25 +02:00
Jake BarnbyandGitHub bc5343b559 Apply suggestions from code review 2025-05-20 23:27:31 +12:00
Jake BarnbyandGitHub eb05e8c35c Merge branch 'main' into upsert-single-document-route 2025-05-20 11:12:14 +00:00
Christy JacobandGitHub 5e10670d22 Merge pull request #9831 from appwrite/fix-download-endpoint
fix: download endpoint
2025-05-20 14:21:55 +04:00
loks0n 455554a6a2 fix: download endpoint 2025-05-20 11:14:16 +01:00
Matej Bačo cb97679553 Specs, SDKs and Docs fixes (deprecated params) 2025-05-20 11:50:36 +02:00
ArnabChatterjee20k 80e842444b updated test for upsertion 2025-05-20 14:28:16 +05:30
Matej BačoandGitHub 6400e94d8b Merge pull request #9830 from appwrite/fix-flutter-starter
Fix: flutter starter
2025-05-20 10:49:11 +02:00
Matej Bačo d710b48ef5 Fix: flutter starter 2025-05-20 10:40:21 +02:00
Jake BarnbyandGitHub 2f6a82f4d5 Merge pull request #9757 from appwrite/feat-pool-adapter
Feat pool adapter
2025-05-20 08:25:34 +00:00
Matej BačoandGitHub 1a7982f855 Merge pull request #9828 from appwrite/sites-certificates
certificates: add domainType to certificate worker
2025-05-20 10:16:14 +02:00
Jake Barnby 149dfb9651 Update lock 2025-05-20 20:07:11 +12:00
Fabian Gruber 14873824ce certificates: add domainType to certificate worker 2025-05-20 09:56:46 +02:00
Jake Barnby 2a99bd4bda Fix migrating functions with no deployments 2025-05-20 19:26:26 +12:00
Jake BarnbyandGitHub 534096cac6 Merge branch '1.6.x' into feat-pool-adapter 2025-05-20 07:07:58 +00:00
ArnabChatterjee20kandGitHub 9f50f0c04a Merge branch 'main' into upsert-single-document-route 2025-05-20 12:14:42 +05:30
ArnabChatterjee20k b5d31d1b76 updated the upsert test for the relationship 2025-05-20 12:11:41 +05:30
ArnabChatterjee20k 53e790d886 changed uid to custom id to allow unique values as well 2025-05-20 10:54:09 +05:30
Steven NguyenandGitHub e9d0462548 Merge pull request #9825 from appwrite/fix-app-domain-sites-env-var
fix: add _APP_DOMAIN_SITES variables.php so the env is initialized
2025-05-19 17:05:02 -07:00
Steven Nguyen d2b0048a7f fix: add _APP_DOMAIN_SITES variables.php so the env is initialized
Without this, API calls to Appwrite can result in rule_not_found errors.
2025-05-19 16:04:04 -07:00
Aditya Oberai 4aeca149b0 update specs 2025-05-19 18:44:07 +00:00
12bb74a58d Update src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php
Co-authored-by: Matej Bačo <matejbacocom@gmail.com>
2025-05-20 00:11:03 +05:30
Aditya Oberai b2451c37c3 update 1.7.x and latest specs 2025-05-19 14:50:57 +00:00
Darshan 14fe7a7217 update: token desc. 2025-05-19 19:54:34 +05:30
Christy JacobandGitHub f59377e1bb Merge pull request #9815 from appwrite/task-coroutine-hooks-1.6
fix: task coroutine hooks
2025-05-19 16:59:19 +04:00
Christy JacobandGitHub 24312e69f4 Merge pull request #9814 from appwrite/task-coroutine-hooks
fix: task coroutine hooks
2025-05-19 16:59:16 +04:00
Fabian Gruber 1177178885 fix: task coroutine hooks 2025-05-19 14:03:58 +02:00
Fabian Gruber 3274a38c9b fix: task coroutine hooks 2025-05-19 14:02:47 +02:00
Matej BačoandGitHub eb3b09cf0d Merge pull request #9816 from appwrite/chore-upgrade-libs
Chore: upgrade detection, executor and console
2025-05-19 13:16:24 +02:00
Matej Bačo e203ae7327 upgrade detection, executor and console 2025-05-19 13:02:04 +02:00
ArnabChatterjee20k 559b6024bc linting 2025-05-19 16:00:38 +05:30
ArnabChatterjee20k 256aa684a2 updated tests 2025-05-19 15:59:38 +05:30
Matej BačoandGitHub 0ec7ff2cee Merge pull request #9812 from appwrite/fix-remove-search
Remove: `search` to maintain document structure
2025-05-19 11:59:04 +02:00
Darshan fc279cb30c remove: search from deployments. 2025-05-19 15:12:50 +05:30
Darshan abd2cead73 remove: search. 2025-05-19 15:03:59 +05:30
ArnabChatterjee20k 1de778443f resolved comments for the api 2025-05-19 14:30:29 +05:30
ArnabChatterjee20k 08478b8d39 removed document existence check for the document id
updated labels
added tests for upserts
2025-05-19 13:56:11 +05:30
ArnabChatterjee20k 330c298c58 add upsert route for a single document 2025-05-19 12:10:42 +05:30
Eldad A. FuxandGitHub e7c9b3d900 Merge pull request #9810 from appwrite/fix-chunk-reading-realtime
Fix logic of chunk reading
2025-05-19 03:39:16 +01:00
Matej Bačo 6090ca50fc Fix logic of chunk reading 2025-05-19 04:35:44 +02:00
Christy JacobandGitHub 3ba0565e44 Merge pull request #9808 from appwrite/chore-update-domains
chore: update domains
2025-05-19 03:45:43 +02:00
Eldad A. FuxandGitHub 6dbb14bf7b Merge pull request #9809 from appwrite/1.7.x
1.7.x
2025-05-19 02:42:37 +01:00
Christy Jacob b8b0db7a2f chore: update domains 2025-05-19 05:34:38 +04:00
Eldad A. FuxandGitHub 728b758db5 Merge pull request #9806 from appwrite/feat-x-edge-bypass-gateway
feat: bypass gateway
2025-05-18 23:36:37 +01:00
loks0n 33dc7ea97c feat: bypass gateway 2025-05-18 23:23:06 +01:00
Matej BačoandGitHub da811de615 Merge pull request #9805 from appwrite/fix-site-env-vars
Fix: site env vars at runtime
2025-05-19 00:13:36 +02:00
Matej Bačo c1315019cb Litner fix 2025-05-18 23:53:56 +02:00
Matej Bačo 1eb642aff0 Fix site env vars at runtime 2025-05-18 23:53:43 +02:00
Matej BačoandGitHub 908d80e8d9 Merge pull request #9804 from appwrite/fix-function-create-compatibility
Fix: backwards compatibility for function creation
2025-05-18 23:15:59 +02:00
Matej Bačo 02b7e0df4d queries backwards compatibilit 2025-05-18 22:51:17 +02:00
Matej Bačo e84ad1e83c Upgrade libs 2025-05-18 22:37:30 +02:00
Matej Bačo 0e90f64ea6 Fix backwards compatibility for function reation 2025-05-18 22:07:52 +02:00
Matej BačoandGitHub 08e93997b5 Merge pull request #9802 from appwrite/1.7.x
Fix: domain validaiton
2025-05-18 21:45:35 +02:00
Matej BačoandGitHub aaee95a761 Merge branch 'main' into 1.7.x 2025-05-18 21:39:53 +02:00
Matej BačoandGitHub 637b842e16 Merge pull request #9801 from appwrite/fix-request-response-1.7.x
fix: request response formats for 1.7.x
2025-05-18 21:32:36 +02:00
Matej Bačo 1e24d14dd1 Fix DNS lookup speed 2025-05-18 21:32:26 +02:00
Chirag AggarwalandGitHub 2fe80462f1 Merge branch '1.7.x' into fix-request-response-1.7.x 2025-05-19 00:35:40 +05:30
Chirag Aggarwal 2ba4ae8e60 fix: request response formats for 1.7.x 2025-05-18 18:54:29 +00:00
Matej Bačo 8170661012 Fix domain validaiton 2025-05-18 20:51:52 +02:00
Jake BarnbyandGitHub 9873daa3ad Merge pull request #9649 from appwrite/1.7.x
1.7.x
2025-05-18 15:15:37 +00:00
Jake BarnbyandGitHub 33ac93338d Merge pull request #9798 from appwrite/chore-bump-console
Update console
2025-05-18 14:32:15 +00:00
Jake Barnby 3e2afc468a Update console 2025-05-19 02:31:02 +12:00
Jake BarnbyandGitHub cb9f45a546 Merge pull request #9797 from appwrite/chore-review-fixes
Chore review fixes
2025-05-18 14:08:18 +00:00
Jake Barnby bb7055fb47 Lint 2025-05-19 01:59:02 +12:00
Jake Barnby 4307bb8b33 Fix deprecated method usage 2025-05-19 01:56:25 +12:00
Jake Barnby dd4ffa41af Fix header check mismatch 2025-05-19 01:56:08 +12:00
Jake Barnby 5a6e891099 Fix invalid matrix read 2025-05-19 01:56:00 +12:00
Jake BarnbyandGitHub abba19a22f Merge branch 'main' into 1.7.x 2025-05-18 13:27:53 +00:00
Christy JacobandGitHub 2db4086ec3 Merge pull request #9796 from appwrite/sync-1.6.x
Sync 1.6.x
2025-05-18 15:24:32 +02:00
Matej BačoandGitHub 0d58bb8ede Merge pull request #9788 from appwrite/fix-remove-builds
fix: remove builds
2025-05-18 14:47:08 +02:00
Jake BarnbyandGitHub b06e4501c5 Merge branch 'main' into 1.7.x 2025-05-18 12:46:06 +00:00
Jake Barnby 7c6c9d7cb2 Merge remote-tracking branch 'origin/1.6.x' into sync-1.6.x 2025-05-19 00:44:50 +12:00
Jake BarnbyandGitHub 5b9bfd7673 Merge pull request #9795 from appwrite/fix-version
Update version
2025-05-18 12:43:29 +00:00
Jake Barnby 41668d4cd0 Update version 2025-05-19 00:41:37 +12:00
Jake BarnbyandGitHub d0bb88f69f Merge pull request #9793 from appwrite/fix-migration-version
Fix class name
2025-05-18 11:56:17 +00:00
Jake Barnby 502c0ad542 Fix class name 2025-05-18 23:53:54 +12:00
Jake BarnbyandGitHub e4cf79cc47 Merge pull request #9792 from appwrite/chore-bump-console
Update console
2025-05-18 11:38:42 +00:00
Jake Barnby b3170df23e Update console 2025-05-18 23:23:29 +12:00
Matej BačoandGitHub 413bfebd5d Merge branch '1.7.x' into fix-remove-builds 2025-05-18 13:13:35 +02:00
Matej Bačo 2bee98afcf Fix remaining tests 2025-05-18 12:51:07 +02:00
Matej Bačo b228bdd9c7 Fix failing tests 2025-05-18 12:02:32 +02:00
Jake BarnbyandGitHub 58d0862679 Merge pull request #9791 from appwrite/sync-telemetry
Remove telemetry
2025-05-18 09:57:09 +00:00
Matej Bačo 0e69929054 Fix separation strategy 2025-05-18 11:39:30 +02:00
Jake Barnby 9abc4d5d27 Lint 2025-05-18 21:20:15 +12:00
Jake Barnby 5bcb305338 Add back no telemetry injection 2025-05-18 21:20:08 +12:00
Jake Barnby 6906a97c22 Remove telemetry 2025-05-18 21:18:41 +12:00
Jake BarnbyandGitHub 7efcb966c6 Merge pull request #9787 from appwrite/chore-sync-1.6.x
Chore sync 1.6.x
2025-05-18 09:11:23 +00:00
Matej Bačo 2ae33a7351 Merge branch 'fix-remove-builds' of github.com:appwrite/appwrite into fix-remove-builds 2025-05-18 11:08:26 +02:00
Matej Bačo 9b4f787d40 Fix edge case with no commands 2025-05-18 11:08:14 +02:00
Matej BačoandGitHub 26c69604d7 Merge branch '1.7.x' into fix-remove-builds 2025-05-18 10:49:37 +02:00
Jake BarnbyandGitHub de1eda4c39 Merge pull request #9790 from appwrite/update-changelog-and-sdks
chore: update sdk versions and changelog
2025-05-18 08:42:04 +00:00
Chirag Aggarwal d340e3ec39 chore: add changelog for dart 2025-05-18 08:36:23 +00:00
Matej Bačo 03f01e322e SSR detection without createCommand and remove=false 2025-05-18 10:30:27 +02:00
Chirag Aggarwal c8140ee2d2 chore: add changelog for android, deno and react native 2025-05-18 08:20:20 +00:00
Chirag Aggarwal c58ae51895 chore: update sdk versions and changelog 2025-05-18 08:10:07 +00:00
loks0n 27a5bd70bc fix: remove builds 2025-05-18 00:56:11 +01:00
Steven NguyenandGitHub 90ab94fe5e Merge pull request #9786 from appwrite/fix-task-stats-resource-crashing
fix: prevent appwrite-task-stats-resources from crashing
2025-05-17 15:39:18 -07:00
Steven Nguyen 5db1cff69f Merge branch '1.6.x' into chore-sync-1.6.x 2025-05-17 14:22:13 -07:00
Steven Nguyen 516702e901 fix: prevent appwrite-task-stats-resources from crashing
Remove the volume mounts meant for local development from the prod
docker-compose file.

Also, ensure the container restarts automatically if it crashes just
like all the other containers.
2025-05-17 13:27:31 -07:00
Eldad A. FuxandGitHub 5fe5c82801 Merge pull request #9784 from appwrite/release-1.6.2
Release 1.6.2
2025-05-17 21:41:13 +02:00
Jake BarnbyandGitHub 0327705477 Merge pull request #9783 from appwrite/fix-version
Fix length
2025-05-17 15:28:31 +00:00
Jake Barnby c0c9b64ce6 Fix length 2025-05-18 03:27:47 +12:00
Jake BarnbyandGitHub 18ed2ecce6 Merge pull request #9782 from appwrite/fix-version
Add RC version to migration
2025-05-17 15:21:50 +00:00
Jake Barnby 32d2001aa2 Add RC version to migration 2025-05-18 03:20:46 +12:00
Jake BarnbyandGitHub 292a5f01da Merge pull request #9781 from appwrite/fix-version
Set version to RC1
2025-05-17 15:14:27 +00:00
Jake Barnby 617fc6a04a Set version to RC1 2025-05-18 03:13:36 +12:00
Jake BarnbyandGitHub 0d67e8297b Merge pull request #9780 from appwrite/feat-1.7-sdks
Feat 1.7 SDKs
2025-05-17 14:45:54 +00:00
Jake Barnby 173486bdef Sync to install compose 2025-05-18 02:43:32 +12:00
Jake Barnby 41451b775e Add server docs 2025-05-18 02:28:12 +12:00
Jake Barnby 7687c99480 Add docs 2025-05-18 02:25:38 +12:00
Jake BarnbyandGitHub d9a863c444 Merge pull request #9770 from appwrite/update-request-response-filters
chore: update request response filters for 1.7.x
2025-05-17 14:16:52 +00:00
Jake Barnby 42901bbd69 Fix client specs 2025-05-18 02:01:43 +12:00
Jake Barnby 99278f13af Bump versions 2025-05-17 23:56:57 +12:00
Jake Barnby 2cb0ce0350 Update specs 2025-05-17 23:55:14 +12:00
Jake BarnbyandGitHub 1888606eec Merge pull request #9778 from appwrite/feat-sync-1.6.x
Sync 1.6.x
2025-05-17 11:43:14 +00:00
Jake Barnby a4845661b9 Fix merge 2025-05-17 22:50:30 +12:00
Jake Barnby a96f770e84 Fix merge 2025-05-17 22:43:32 +12:00
Jake Barnby 678578ad64 Fix merge 2025-05-17 20:33:32 +12:00
Jake Barnby b41dfb49b4 Fix merge 2025-05-17 20:27:45 +12:00
Jake Barnby d577fd1294 Sync 1.6.x 2025-05-17 20:23:46 +12:00
Jake BarnbyandGitHub d3ba4dab46 Merge pull request #9738 from appwrite/feat-ce-migration
1.7.x ce migration
2025-05-17 08:18:00 +00:00
Jake BarnbyandGitHub 75f2619ab3 Merge pull request #9774 from appwrite/fix-multi-method-auth
Fix specs
2025-05-17 08:06:22 +00:00
Eldad A. FuxandGitHub 3ff15accfd Merge pull request #9777 from appwrite/fix-gif-preview
fix(storage): do not preview gif input/output
2025-05-17 00:13:14 +02:00
Steven Nguyen 5d25265e5c fix(storage): do not preview gif input/output
Processing a gif file can consume large amounts of memory causing the
container to crash.

As a safety precaution, don't output to gif either. Any attempt to
output to gif will fallback to jpg.
2025-05-16 14:46:24 -07:00
Chirag Aggarwal 5d4a9e8c56 chore: add request filter v19 tests 2025-05-16 18:31:36 +00:00
Chirag Aggarwal 608eacc773 chore: removed values from response filters 2025-05-16 18:26:21 +00:00
Christy JacobandGitHub 61ac661851 chore: update storage library (#9776)
* chore: update storage library

* chore: update storage library

* chore: revert f802fb9 and 651cec6

* chore: revert composer

* chore: revert lockfile
2025-05-16 19:18:08 +02:00
Torsten DittmannandGitHub ac77c15a59 Merge pull request #9771 from appwrite/LauraDuRy-patch-2
Update README.md
2025-05-16 18:17:19 +02:00
Jake Barnby 5a0e94ae18 Format 2025-05-17 03:44:26 +12:00
Jake Barnby ea0a7ce485 Fix specs 2025-05-17 03:40:51 +12:00
Jake Barnby 91f8570801 Format 2025-05-17 01:57:57 +12:00
Jake Barnby a3722f53a5 Fix getting function for rule 2025-05-17 01:39:25 +12:00
Jake Barnby 04009699eb Fix type + resourceType fallbacks 2025-05-17 01:37:20 +12:00
Jake Barnby e22ef82116 Safe multi-run by self-fallback 2025-05-17 00:49:59 +12:00
Jake Barnby c56dba6b20 Add console 2025-05-17 00:19:12 +12:00
Jake Barnby be400681e7 Fix collection exists fallbacks 2025-05-17 00:18:57 +12:00
Jake Barnby 43493f71aa Remove invalid collections 2025-05-16 22:10:13 +12:00
Jake Barnby ac38418812 Update logs 2025-05-16 22:07:43 +12:00
Jake Barnby 8ff4bc0f7b Fix count 2025-05-16 22:07:34 +12:00
Jake Barnby 19d040d43d Remove redundant method 2025-05-16 22:07:17 +12:00
Jake Barnby d6fd05866a Ignore duplicate on create collection 2025-05-16 22:06:59 +12:00
Jake Barnby fa3894ef1c Fix extra collection keys 2025-05-16 22:06:37 +12:00
Chirag Aggarwal 14f436c604 chore: update env 2025-05-16 09:56:35 +00:00
Chirag Aggarwal 1980df1156 chore: temporary to check tests 2025-05-16 09:22:03 +00:00
Jake Barnby 15c13aa032 Remove duplicate attribute 2025-05-16 21:13:09 +12:00
Fabian GruberandGitHub 5fe6359fe6 Create unique stable cache identifier (#9769) 2025-05-16 10:56:12 +02:00
Jake Barnby 697d23e9a4 Update database 2025-05-16 20:49:52 +12:00
Jake Barnby 1b244f4095 Merge remote-tracking branch 'origin/1.7.x' into feat-ce-migration 2025-05-16 20:46:33 +12:00
Jake Barnby 379ffd8eeb Disable coroutines 2025-05-16 20:30:29 +12:00
Jake Barnby 4ce6587634 Fix key matching 2025-05-16 20:30:16 +12:00
Jake Barnby 768d005f08 Use create bulk attributes 2025-05-16 20:30:04 +12:00
Jake Barnby 4d4cfef1ad Skip empty ID 2025-05-16 20:29:52 +12:00
Chirag AggarwalandGitHub 4f122d8982 Merge branch '1.7.x' into update-request-response-filters 2025-05-16 13:48:53 +05:30
Laura Du RyandGitHub 4417306295 Update README.md 2025-05-16 09:41:09 +02:00
Eldad A. FuxandGitHub 88bb95ec5c Merge pull request #9768 from appwrite/fix-scopes
Fix scopes
2025-05-16 09:04:48 +02:00
Chirag Aggarwal c657e368cc chore: update request response filters for 1.7.x 2025-05-16 06:18:59 +00:00
Jake Barnby 2d6d79de7b Fix names 2025-05-16 17:36:29 +12:00
Jake Barnby 59ef8077da Skip devKeys subquery 2025-05-16 17:36:19 +12:00
Jake Barnby 43fce76c9b Remove redundant namespace set 2025-05-16 17:35:36 +12:00
DarshanandGitHub 0dfda7ca7c Merge branch '1.7.x' into fix-scopes 2025-05-16 11:05:19 +05:30
Darshan baa9b7bf6f update: specs for sdk gen. 2025-05-16 11:05:05 +05:30
Jake Barnby 907d968a5f Remove redundant doc migration 2025-05-16 17:25:06 +12:00
Jake Barnby 7344733165 Use db loop methods, update names 2025-05-16 17:24:11 +12:00
Jake Barnby 56fda6a34b Add migration options 2025-05-16 17:23:17 +12:00
Jake Barnby a23548fba5 Add domains + dnsRecords to platform 2025-05-16 14:57:18 +12:00
Jake Barnby ae2bc1f740 Fix expire required 2025-05-16 14:56:52 +12:00
Jake Barnby f12e84abc5 Merge remote-tracking branch 'origin/1.7.x' into feat-ce-migration 2025-05-16 13:46:17 +12:00
Jake BarnbyandGitHub 38a2ec0a2f Merge pull request #9767 from appwrite/fix-db-exceptions
Only rethrow auth and timeout in general handler
2025-05-16 01:10:24 +00:00
Jake BarnbyandGitHub 70c2079f75 Merge pull request #9726 from appwrite/fix-delete-project-loop
Fix infinie loop in delete project
2025-05-16 01:04:37 +00:00
Matej BačoandGitHub c5d4173923 Merge branch '1.6.x' into 1.7.x 2025-05-15 18:27:56 +02:00
Matej Bačo 2db7ec3290 Post-merge fixes 2025-05-15 18:10:11 +02:00
Matej Bačo ac6450c726 Merge branch '1.6.x' into 1.7.x 2025-05-15 18:03:15 +02:00
Steven NguyenandGitHub 8de9b7ffb2 Merge pull request #9765 from appwrite/fix-owner-downgrade
Fix owner role downgrade
2025-05-15 08:30:18 -07:00
Steven NguyenandGitHub fa2a3bad53 Merge pull request #9747 from appwrite/generate-server-sdk
feat: add ability to generate client and server sdks
2025-05-15 08:28:32 -07:00
Matej Bačo 8a555fd294 Add react native 2025-05-15 16:21:36 +02:00
Darshan f0a835b3b2 update: token scopes tests for console client. 2025-05-15 19:37:07 +05:30
Darshan bebd103611 update: token scopes tests for console client. 2025-05-15 19:22:53 +05:30
Darshan 1ab724ff04 update: token scopes tests. 2025-05-15 19:13:51 +05:30
Darshan de57c8f35e update: token scopes. 2025-05-15 19:04:11 +05:30
Fabian GruberandGitHub d28831632e Swap default image quality to -1, keeping source image quality. (#9766) 2025-05-15 14:45:24 +02:00
Jake Barnby 6e40070b98 Lint 2025-05-16 00:35:21 +12:00
Jake Barnby 738e256692 Remove redundant catches 2025-05-16 00:25:23 +12:00
Jake Barnby 4f2142a470 Lint 2025-05-16 00:22:52 +12:00
Eldad A. FuxandGitHub 23d73e1f3e Merge pull request #9750 from appwrite/update-tokens
Update tokens without JWT
2025-05-15 14:19:41 +02:00
Jake Barnby 11e4e9432e Fix tests 2025-05-16 00:14:09 +12:00
Jake Barnby b1829bacfe Only rethrow auth and timeout in general handler 2025-05-15 23:33:00 +12:00
Matej Bačo ee5f8df72b Fix Flutter default commands 2025-05-15 11:50:09 +02:00
DarshanandGitHub de30b49515 Merge branch '1.6.x' into fix-owner-downgrade 2025-05-15 15:02:07 +05:30
Darshan 15992da369 update: tests. 2025-05-15 15:01:23 +05:30
Eldad A. FuxandGitHub 919c427d36 Merge pull request #9745 from appwrite/feat-logo-url
feat: plan based email logoUrl
2025-05-15 11:06:07 +02:00
Darshan ad3adbda21 fix: owner downgrade. 2025-05-15 14:08:54 +05:30
Fabian GruberandGitHub 651cec65da feat: telemetry for storage devices (#9761) 2025-05-15 10:21:38 +02:00
Chirag Aggarwal fe767e9655 chore: accent color 2025-05-15 07:44:14 +00:00
Chirag Aggarwal f818607680 chore: keep console sdk preview automatic 2025-05-15 05:27:43 +00:00
Chirag Aggarwal e1e6b82ca3 chore: remove on pull request 2025-05-15 05:22:48 +00:00
Chirag Aggarwal 403a2e9db3 chore: whitespace 2025-05-15 05:17:57 +00:00
Chirag Aggarwal 1c5f7ccd37 chore: update sdk preview workflow to be generic 2025-05-15 05:14:39 +00:00
Steven NguyenandGitHub aa411e4ac8 Merge pull request #9755 from appwrite/release-1.6.2
Sync 1.6.2 into main
2025-05-14 17:10:19 -07:00
Steven NguyenandGitHub fdbc01aa3d Merge pull request #9733 from appwrite/pla-1849
chore: improve route not found error message
2025-05-14 07:06:22 -07:00
Shimon NewmanandGitHub e08133976b fix metrics name in databases usage api (#9760) 2025-05-14 14:57:41 +02:00
Chirag AggarwalandGitHub 52fdeccd11 Merge branch '1.6.x' into pla-1849 2025-05-14 18:02:05 +05:30
Chirag AggarwalandGitHub f62979cfa8 feat: inforu adapter (#9620)
* chore: update utopia messaging library

* chore: init inforu adapter

* chore: use dev message

* chore: update composer

* chore: fix ordering

* chore: use user for senderId
2025-05-14 12:11:21 +02:00
Jake Barnby 55236524e3 Fix merge 2025-05-14 21:42:39 +12:00
Jake Barnby 4e9385f70b Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter 2025-05-14 21:29:10 +12:00
Jake Barnby 33fbab7e3d Fix missing capture 2025-05-14 21:28:59 +12:00
Fabian GruberandGitHub c0b7c47615 fix(schedules): disable coroutine until we have proper pool support (#9759) 2025-05-14 10:40:56 +02:00
Jake Barnby 09152a08e1 Fix merge 2025-05-14 18:27:51 +12:00
Jake Barnby af3388a51f Format 2025-05-14 18:16:54 +12:00
Jake Barnby 16b2449787 Revert "Merge pull request #9703 from appwrite/revert-9659-feat-pool-adapter"
This reverts commit bf9deb09f5, reversing
changes made to d312fe22ff.

# Conflicts:
#	app/cli.php
#	app/init/registers.php
#	composer.lock
#	src/Appwrite/Messaging/Adapter/Realtime.php
#	src/Appwrite/Platform/Tasks/ScheduleBase.php
#	src/Appwrite/Platform/Tasks/ScheduleExecutions.php
#	src/Appwrite/Platform/Tasks/ScheduleFunctions.php
#	src/Appwrite/Platform/Tasks/ScheduleMessages.php
2025-05-14 18:14:07 +12:00
Darshan c2f54c653c generate: specs. 2025-05-14 10:47:40 +05:30
Darshan af4d1a8264 update: comment. 2025-05-14 10:47:32 +05:30
Jake Barnby d8cc770ba5 Merge branch 'feat-pool-adapter' of github.com:appwrite/appwrite into feat-pool-adapter 2025-05-14 16:43:03 +12:00
Jake Barnby 3e914a4f1b Revert name merge issue 2025-05-14 16:42:36 +12:00
Jake Barnby 406630cb61 Update deps 2025-05-14 16:40:47 +12:00
Chirag Aggarwal 3559ecbf80 chore: initialize plan in worker 2025-05-14 03:38:51 +00:00
Chirag Aggarwal a2686b4a8d Merge branch '1.7.x' into feat-logo-url 2025-05-14 03:21:45 +00:00
Jake BarnbyandGitHub 98c634c3c9 Merge pull request #9748 from ArnabChatterjee20k/feat/index-length
Feat/index length
2025-05-14 01:24:19 +00:00
DarshanandGitHub 28f404147b Merge branch '1.7.x' into update-tokens 2025-05-13 21:21:22 +05:30
Matej BačoandGitHub 39e083188c Merge pull request #9752 from appwrite/fix-indexes
Fix indexes for `1.7.x`
2025-05-13 17:49:52 +02:00
Darshan 6ea10dbeb9 remove: data additions to search attribute. 2025-05-13 19:08:12 +05:30
Darshan 9d4a7fadb9 fix: tests due to no search attribute. 2025-05-13 18:59:16 +05:30
ArnabChatterjee20k 4208c52c7f reverted overriding index size for index attribute 2025-05-13 18:21:58 +05:30
ArnabChatterjee20k 9055645d06 updated test for the array attribute index overriding 2025-05-13 18:21:34 +05:30
Jake Barnby a4239fc5dc Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter 2025-05-14 00:36:45 +12:00
ArnabChatterjee20kandGitHub 9731953c09 Merge branch '1.6.x' into feat/index-length 2025-05-13 17:42:20 +05:30
ArnabChatterjee20k f8fdecaa2d made the code a bit simpler 2025-05-13 17:40:04 +05:30
ArnabChatterjee20k 41d7114e97 updated composer and index api 2025-05-13 17:37:15 +05:30
Fabian GruberandGitHub 4853e0803c fix(schedules): better error handling (#9751) 2025-05-13 14:05:13 +02:00
Darshan 89af35cb5b bump: composer because linter bothers me on CI. 2025-05-13 17:33:33 +05:30
Darshan 7fd88315ba bump: composer because linter bothers me on CI. 2025-05-13 17:30:05 +05:30
Darshan e4ea29ddf6 Merge branch '1.7.x' into update-tokens 2025-05-13 17:27:56 +05:30
Darshan d50b3f1519 fix: indexes on changed attributes. 2025-05-13 17:25:01 +05:30
Darshan 1d38291826 updates: remove permissions, allow tokens management only on console. 2025-05-13 16:53:30 +05:30
Fabian GruberandGitHub 40642b2aad fix(schedules): enqueue delay telemetry in wrong format (#9749) 2025-05-13 13:03:09 +02:00
Darshan 942b81053d address comments. 2025-05-13 16:23:29 +05:30
DarshanandGitHub f01bfc842b Merge branch '1.7.x' into update-tokens 2025-05-13 16:16:46 +05:30
Darshan 6f15a43b02 update: constant and error desc. 2025-05-13 16:16:33 +05:30
Darshan 52a128cfaa fix: tests; add: params for sdks. 2025-05-13 16:14:29 +05:30
Darshan 4e9f137e55 remove: jwt logic. serve the jwt directly from the model itself. 2025-05-13 15:41:26 +05:30
Khushboo Verma 25a13d3666 Sync with cloud 2025-05-13 15:40:21 +05:30
arnab cd806e80d7 updated tests and validations 2025-05-13 15:39:13 +05:30
Khushboo Verma a3cb7c81a2 Add V23 migration and remove coroutines 2025-05-13 15:22:09 +05:30
Jake Barnby 0f313afcb5 Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter
# Conflicts:
#	src/Appwrite/Messaging/Adapter/Realtime.php
2025-05-13 21:10:57 +12:00
Matej Bačo 33d4650827 Post-merge fixes 2025-05-13 10:18:57 +02:00
Matej Bačo af0c872999 Merge branch '1.6.x' into 1.7.x 2025-05-13 10:11:39 +02:00
Khushboo Verma bebf6a4ef6 Merge branch '1.7.x' into feat-ce-migration 2025-05-13 12:42:29 +05:30
arnab a970512e3c added length param, response model, e2e test 2025-05-13 10:35:04 +05:30
Fabian GruberandGitHub 7c229ad878 feat(scheduling): add telemetry for scheduler tasks (#9721) 2025-05-12 18:05:32 +02:00
Matej Bačo 06bf26682e Fix index 2025-05-12 17:33:21 +02:00
Matej Bačo 3b38b6bb57 Migration review fixes 2025-05-12 16:52:13 +02:00
Khushboo Verma 9f4e0f5eb9 Merge branch '1.7.x' into feat-ce-migration 2025-05-12 20:06:01 +05:30
Chirag Aggarwal 980afc2eaf chore: update social links 2025-05-12 13:20:59 +00:00
Chirag Aggarwal a802a78b0b feat: plan based email logoUrl 2025-05-12 13:10:58 +00:00
Matej BačoandGitHub 1276e74e79 Merge pull request #9743 from appwrite/fix-filters
Fix request filters with multi-method routes
2025-05-12 10:22:26 +02:00
Jake Barnby 800dd8bdac Remove redundant filter, action checks which parameter sets are allowed 2025-05-12 19:26:35 +12:00
Jake Barnby 0099eef8c8 Faster short-path for single method routes 2025-05-12 19:25:52 +12:00
Jake Barnby d04e43c615 Improve matched case 2025-05-12 17:50:14 +12:00
Jake Barnby 3203ea5d43 Fix request filters with multi-method routes 2025-05-12 17:41:03 +12:00
Chirag Aggarwal b0e95171f8 chore: update react native and generate sdk 2025-05-10 14:29:11 +00:00
Chirag Aggarwal 28fe6f34de Merge branch '1.6.x' into pla-1849 2025-05-10 08:30:50 +00:00
Jake Barnby de7c8b8c27 Update deps 2025-05-10 18:27:20 +12:00
Khushboo Verma b249584b92 1.7.x ce migration 2025-05-09 17:46:29 +05:30
Eldad A. FuxandGitHub 7f8fe139e9 Merge pull request #9737 from appwrite/1.7.x-introduce-oauth-class
chore: introduce class attribute to oauth2 config
2025-05-09 13:10:00 +02:00
Chirag Aggarwal 21273c8336 fix: undefined classname 2025-05-09 10:57:45 +00:00
Chirag Aggarwal f91ec238b9 chore: introduce class attribute to oauth2 config 2025-05-09 10:09:16 +00:00
fogelito a725b1c952 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into fix-delete-project-loop 2025-05-08 18:58:52 +03:00
Jake BarnbyandGitHub 932ed94b8c Merge pull request #9065 from appwrite/feat-bulk-operations
Feat bulk operations
2025-05-08 14:26:52 +00:00
Christy JacobandGitHub 3fea5ec914 Merge pull request #9734 from appwrite/pla-2876
refactor: maintenance task to run at a specific time
2025-05-08 18:00:38 +04:00
Chirag Aggarwal 2c8e1e1731 chore: deprecate delay 2025-05-08 13:44:58 +00:00
Jake Barnby 6f39c9d147 Update database 2025-05-09 00:11:54 +12:00
Jake Barnby ac760d9ddc Generate SDKs 2025-05-08 22:09:12 +12:00
Jake Barnby 077698a0ee Update db to release 2025-05-08 22:02:06 +12:00
Jake Barnby 1a32ce60bd Add on listener 2025-05-08 21:57:20 +12:00
Jake Barnby eb52ccfeae Update database 2025-05-08 21:17:54 +12:00
Jake Barnby 9c50d60350 Handle upsert usage 2025-05-08 21:08:23 +12:00
Chirag Aggarwal fea58c2bc9 refactor: maintenance task to run at a specific time 2025-05-08 07:49:27 +00:00
fogelito e5a1af3183 Remove DBG 2025-05-08 10:43:28 +03:00
fogelito 9b9ed93db2 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into fix-delete-project-loop 2025-05-08 10:40:02 +03:00
Chirag Aggarwal 6684364b98 chore: improve route not found error message 2025-05-08 07:25:29 +00:00
Jake Barnby 540102ff97 Explicitly catch exceptions 2025-05-08 18:10:26 +12:00
Jake Barnby c3f0bec1ff Validate nested internals 2025-05-08 18:09:37 +12:00
Jake Barnby eaa105477a Fix tests for permissions/relationships updates 2025-05-08 17:17:02 +12:00
Jake Barnby 1e19e7d0b4 Remove permissions + relationships logic from bulk update/delete 2025-05-08 02:59:04 +12:00
Jake Barnby be7ea1f798 Add bulk upsert route 2025-05-08 02:49:02 +12:00
Jake Barnby 639ce4d026 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations
# Conflicts:
#	composer.lock
2025-05-08 01:24:39 +12:00
Jake BarnbyandGitHub a35c955e54 Merge pull request #9729 from appwrite/update-database-lib
chore: update utopia database to 0.67.x
2025-05-07 13:16:53 +00:00
Jake Barnby b44682b6ff Doc updates 2025-05-07 21:23:16 +12:00
Jake Barnby fdc98389b1 Return total as modified count 2025-05-07 16:22:15 +12:00
Jake Barnby 05821c2993 Fix conditional 2025-05-07 15:46:17 +12:00
Jake Barnby 5f19398a9b Accumulate up to limit 2025-05-07 15:45:58 +12:00
Jake Barnby 41ecccda1e Revert "Fix tests for model changes"
This reverts commit f5d243e229.

# Conflicts:
#	app/controllers/api/databases.php
2025-05-07 15:45:46 +12:00
Jake Barnby 572c49cc90 Revert "Don't accumulate docs on update/delete"
This reverts commit 8c1b9044b3.

# Conflicts:
#	app/controllers/api/databases.php
2025-05-07 15:44:58 +12:00
Jake Barnby f7d7b8d3dd Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations 2025-05-07 15:14:13 +12:00
Jake Barnby f5d243e229 Fix tests for model changes 2025-05-07 15:14:05 +12:00
Steven NguyenandGitHub 51f44b02b9 Merge pull request #9724 from appwrite/pla-2856
chore: add harden create email token endpoint
2025-05-06 14:17:41 -07:00
Jake Barnby 8c1b9044b3 Don't accumulate docs on update/delete 2025-05-07 03:10:13 +12:00
Matej BačoandGitHub 06ff33cf7e Merge pull request #9678 from appwrite/fix-missing-filter
Fix: FileTokens
2025-05-06 16:08:23 +02:00
Chirag Aggarwal da05398389 chore: update utopia database to 0.67.x 2025-05-06 13:08:56 +00:00
fogelito c5086d8fba Different color 2025-05-06 15:18:51 +03:00
DarshanandGitHub 01f5896ac1 Merge branch '1.7.x' into fix-missing-filter 2025-05-06 17:05:08 +05:30
fogelito 6f34592efe Add messages 2025-05-06 14:18:26 +03:00
Christy JacobandGitHub f841979de8 Merge pull request #9727 from appwrite/PLA-2826-1
tasks: clean all Timers on error & shutdown
2025-05-06 14:30:24 +04:00
Fabian Gruber 8d93a8aa09 tasks: clean all Timers on error & shutdown 2025-05-06 12:20:04 +02:00
Matej BačoandGitHub 391d5aca58 Merge pull request #9699 from appwrite/fix-add-type-to-create-duplicate-deployment
Set type in createDuplicateDeployment
2025-05-06 12:16:43 +02:00
Jake Barnby af09f17e02 Max 1 operation 2025-05-06 22:05:59 +12:00
Khushboo Verma 9248f06e60 Add test for manual type 2025-05-06 15:31:22 +05:30
Khushboo Verma dc569317d3 Merge branch '1.7.x' into fix-add-type-to-create-duplicate-deployment 2025-05-06 15:24:41 +05:30
fogelito abc2795daa Delete using Cursor 2025-05-06 12:25:56 +03:00
fogelito 6264e616d3 Delete using Cursor 2025-05-06 12:18:29 +03:00
fogelito 56a8e38890 listCollections with big limit 2025-05-06 10:50:56 +03:00
Chirag Aggarwal f905c10acc chore: add harden create email token endpoint 2025-05-06 07:18:23 +00:00
Jake Barnby a6d23298ac Use constant 2025-05-06 13:50:38 +12:00
Jake Barnby af51e31197 Remove debug headers 2025-05-06 13:45:18 +12:00
Jake Barnby cc4c147b15 First class callable syntax 2025-05-06 13:36:45 +12:00
Jake Barnby 66a40eb175 AI review fixes 2025-05-06 02:21:45 +12:00
Jake Barnby 9b6408e53a Fluent setter for parameter 2025-05-06 01:47:35 +12:00
Jake Barnby 4b1dba692c Min 1 operation 2025-05-06 01:02:07 +12:00
Jake Barnby 4da44cf13c Lint 2025-05-05 23:36:36 +12:00
Jake Barnby 24229c63ea Fix multi-method graphql parameter mapping 2025-05-05 23:26:59 +12:00
Jake Barnby 21d9f182d6 Remove dump 2025-05-05 22:30:20 +12:00
Jake Barnby 2f091a1fab Fix permissions set 2025-05-05 21:45:30 +12:00
Jake Barnby 808f338c7c Fix all bulk/relationship tests 2025-05-05 17:20:24 +12:00
Jake Barnby 1f08344c8d Fix update test 2025-05-05 17:01:05 +12:00
Jake Barnby 384e606503 Fix bulk update relationship test 2025-05-05 16:52:06 +12:00
Jake BarnbyandGitHub cdd61feec8 Merge branch '1.6.x' into feat-bulk-operations 2025-05-05 04:29:49 +00:00
Jake BarnbyandGitHub e9edf013b0 Merge pull request #9618 from appwrite/update-collections-indexes
Update console indexes
2025-05-05 03:12:20 +00:00
Jake Barnby f52f864085 Get limit directly from plan 2025-05-05 15:04:32 +12:00
DarshanandGitHub 487247c289 Merge branch '1.7.x' into fix-missing-filter 2025-05-03 09:40:04 +05:30
Jake Barnby df5fb87925 Update DB 2025-05-03 01:55:17 +12:00
Jake Barnby bae0676a62 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations 2025-05-03 01:45:14 +12:00
Eldad A. FuxandGitHub 158a76545e Merge pull request #9702 from appwrite/fix-module-name
fix: tokens module
2025-05-02 15:03:41 +02:00
Matej Bačo f76aff1916 Migration preparations 2025-05-02 11:17:51 +02:00
Christy JacobandGitHub da4a1b4806 Merge pull request #9704 from appwrite/feat-1.6.2-release-prep
Add 1.6.2 to CHANGES.md
2025-05-02 00:03:49 +04:00
Darshan 6dbeff0111 update: specs for console sdk. 2025-05-01 13:20:29 +05:30
DarshanandGitHub d2aee75cf9 Merge branch '1.7.x' into fix-missing-filter 2025-05-01 12:58:45 +05:30
Darshan 972cb9c6a5 add: $permissions to the resourceToken response modal. 2025-05-01 12:58:20 +05:30
Jake BarnbyandGitHub 6794ef77fd Merge pull request #9710 from appwrite/expose-var
Expose var
2025-05-01 06:52:04 +00:00
Darshan dcf11df193 remove: method and expose the variable itself. 2025-05-01 12:16:07 +05:30
Jake BarnbyandGitHub b922858428 Merge pull request #9709 from appwrite/source-report
Add: Source report method
2025-05-01 06:23:57 +00:00
Darshan 8c7ccfcc12 address comments. 2025-05-01 11:37:58 +05:30
Darshan 606fea5871 address comments. 2025-05-01 11:31:51 +05:30
Darshan d137b41c0b add: expose source report for cloud. 2025-05-01 11:22:19 +05:30
Steven Nguyen 977a920959 chore: add 1.6.2 to CHANGES.md 2025-04-30 17:23:50 -07:00
Khushboo Verma f2bcae75b2 Add tests for type 2025-04-30 19:05:08 +05:30
Khushboo Verma 5e0eb59718 Merge branch '1.7.x' into fix-add-type-to-create-duplicate-deployment 2025-04-30 18:51:01 +05:30
Jake BarnbyandGitHub bf9deb09f5 Merge pull request #9703 from appwrite/revert-9659-feat-pool-adapter
Revert "Feat pool adapter"
2025-04-30 12:14:55 +00:00
Jake BarnbyandGitHub c759f9ec11 Revert "Feat pool adapter" 2025-04-30 23:24:54 +12:00
Jake Barnby ea42b823d8 Revert name merge issue 2025-04-30 22:47:41 +12:00
Matej Bačo 279ff8f5ae Migration preps, table width issues 2025-04-30 12:38:32 +02:00
Matej Bačo e1dbf2170e Migration preparations 2025-04-30 12:10:51 +02:00
Jake BarnbyandGitHub d312fe22ff Merge pull request #9659 from appwrite/feat-pool-adapter
Feat pool adapter
2025-04-30 10:05:47 +00:00
Chirag Aggarwal 8d9e840b23 fix: appwrite.php file 2025-04-30 10:02:25 +00:00
Chirag Aggarwal 093feb58ca fix: tokens module 2025-04-30 10:00:58 +00:00
Jake Barnby 6e59859f5c AI review fixes 2025-04-30 21:18:24 +12:00
Matej Bačo bd50baff85 Upgrade db lib for migration fix 2025-04-30 09:31:17 +02:00
Jake Barnby 7b88792b6a Accumulate documents 2025-04-30 17:40:54 +12:00
Jake Barnby 27ac5cbb2a Remove redundant withTimestamp 2025-04-30 17:40:47 +12:00
Darshan 64a24b2211 update: tests for getFileDownload with resourceToken and misc changes. 2025-04-30 10:10:35 +05:30
Darshan 1170fd0ee9 update: tests for getFileDownload with resourceToken. 2025-04-30 09:52:27 +05:30
Darshan 61d583c32e update: add resourceToken usage to getFileDownload as well. 2025-04-30 09:45:43 +05:30
Jake Barnby f2270b9ef8 Add read/write counts for bulk operations 2025-04-30 14:22:48 +12:00
Jake Barnby 58c536e232 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations
# Conflicts:
#	src/Appwrite/Platform/Tasks/Specs.php
#	src/Appwrite/SDK/Specification/Format/OpenAPI3.php
#	src/Appwrite/SDK/Specification/Format/Swagger2.php
2025-04-30 13:18:06 +12:00
Jake Barnby 6400b0dc48 Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter 2025-04-30 13:16:56 +12:00
Jake BarnbyandGitHub 44abf276d7 Merge pull request #9478 from appwrite/chore-merge-namespace
Move specification into SDK namespace
2025-04-30 01:15:13 +00:00
Jake Barnby ed0929416b Format 2025-04-30 13:13:14 +12:00
Jake Barnby 2e2af32be3 Fix missing trigger 2025-04-30 13:06:51 +12:00
Jake Barnby ea38a7f869 Coroutine sleep 2025-04-30 13:05:31 +12:00
Jake Barnby 43fb92ca83 Set publisher on base 2025-04-30 13:04:19 +12:00
Jake Barnby 38f5d88b03 Remove unused param 2025-04-30 12:44:15 +12:00
Jake Barnby f7296d80b2 Fix function schedule sleep 2025-04-30 12:27:18 +12:00
Jake Barnby 453bb8ab70 Update tests for changes 2025-04-30 12:09:13 +12:00
Jake Barnby a98520302d Reduce max batch 2025-04-30 12:09:02 +12:00
Jake Barnby 6af3912eff Remove unused value 2025-04-30 12:08:53 +12:00
Jake Barnby f82726c2b4 Remove redundant batch size passing 2025-04-30 12:08:38 +12:00
Jake Barnby 0ab1ebd8c4 Validate create batch size inline 2025-04-30 12:07:56 +12:00
Jake Barnby 706e5f2453 Merge remote-tracking branch 'origin/1.6.x' into chore-merge-namespace 2025-04-30 10:46:54 +12:00
Jake Barnby 2238f6d822 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations
# Conflicts:
#	app/config/specs/open-api3-1.6.x-client.json
#	app/config/specs/open-api3-1.6.x-console.json
#	app/config/specs/open-api3-1.6.x-server.json
#	app/config/specs/open-api3-latest-client.json
#	app/config/specs/open-api3-latest-console.json
#	app/config/specs/open-api3-latest-server.json
#	app/config/specs/swagger2-1.6.x-client.json
#	app/config/specs/swagger2-1.6.x-console.json
#	app/config/specs/swagger2-1.6.x-server.json
#	app/config/specs/swagger2-latest-client.json
#	app/config/specs/swagger2-latest-console.json
#	app/config/specs/swagger2-latest-server.json
#	composer.lock
#	src/Appwrite/Specification/Format/Swagger2.php
2025-04-30 10:45:18 +12:00
Jake Barnby 5fc2c1ceb8 Fix registry ref 2025-04-30 10:34:24 +12:00
Khushboo Verma 2610a0cbcd Set type in createDuplicateDeployment 2025-04-30 02:26:30 +05:30
DarshanandGitHub d0a28f8062 Merge branch '1.7.x' into fix-missing-filter 2025-04-29 19:53:38 +05:30
Darshan eee9adc325 update: use constant. 2025-04-29 19:52:40 +05:30
Darshan 9ae22ae3fe add: resourceId check. 2025-04-29 19:52:14 +05:30
Darshan f8ddbe5c7a remove: resources' internal ids. 2025-04-29 19:51:36 +05:30
Darshan 5208e69543 add: infinite expiry test. 2025-04-29 19:46:35 +05:30
Darshan 645b04cf32 fix: tests. 2025-04-29 19:37:39 +05:30
Matej Bačo 0148c3ed77 Fix migration row length issue 2025-04-29 16:00:09 +02:00
Darshan d9a065713b Merge remote-tracking branch 'origin/fix-missing-filter' into fix-missing-filter 2025-04-29 18:40:06 +05:30
Darshan 8887da9e0b add: tokens e2e to ci. 2025-04-29 18:39:58 +05:30
DarshanandGitHub 74dca5b60c Merge branch '1.7.x' into fix-missing-filter 2025-04-29 18:31:48 +05:30
Darshan 6c86faa5d4 add: file tokens tests. 2025-04-29 18:25:39 +05:30
Matej BačoandGitHub 9ea5d98fc7 Merge pull request #9698 from appwrite/chore-db-migration-preps
Chore: Database migration preparations
2025-04-29 13:22:05 +02:00
Darshan 4a8f400f7e add: token usage on view endpoint as well. 2025-04-29 16:23:48 +05:30
Matej Bačo 7ece755abf Improve code quality 2025-04-29 11:56:51 +02:00
Jake Barnby e643e7a406 Lint 2025-04-29 21:33:51 +12:00
Matej Bačo 841d260b5f PlatformDB migration preparations 2025-04-29 11:31:06 +02:00
Jake Barnby 02b1c82226 Remove all remaining pool usages 2025-04-29 21:28:53 +12:00
Jake Barnby 4d92af5ba6 Realtime pool adapters 2025-04-29 21:28:40 +12:00
Jake Barnby acec1ab699 Use pool adapters in health api 2025-04-29 21:28:25 +12:00
Jake Barnby 1d82c67d1f Add pubsub pool adapter 2025-04-29 21:28:13 +12:00
Jake Barnby eabf3993a0 Use pool adapter on project create 2025-04-29 18:13:30 +12:00
Jake Barnby 47c5c55267 Remove redundant reclaims 2025-04-29 14:58:54 +12:00
Jake Barnby 43ae7c4b14 Format 2025-04-29 14:57:18 +12:00
Jake Barnby 38aae9e2c1 Fix sync 2025-04-29 14:07:48 +12:00
Steven NguyenandGitHub e74502a259 Merge pull request #9692 from appwrite/fix-vcs-migrations
Fix vcs migrations
2025-04-28 09:34:52 -07:00
Steven Nguyen 101283f345 fix: prevent update migration from clearing scopes and resetting specs 2025-04-28 09:02:06 -07:00
Steven Nguyen 8d9abd2f31 fix(vcs): add missing attributes to 1.6.x migration 2025-04-28 09:02:06 -07:00
Darshan 53e829408f update: use constants. 2025-04-28 20:01:42 +05:30
Darshan 948df2b774 fix: that permissions issue, pheww! 2025-04-28 19:49:32 +05:30
Jake BarnbyandGitHub 4d2a08e7fd Merge branch '1.6.x' into feat-pool-adapter 2025-04-28 10:02:55 +00:00
Jake Barnby a9e953d840 Lint 2025-04-28 22:02:31 +12:00
Jake Barnby 6caa347b26 Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter
# Conflicts:
#	composer.lock
#	src/Appwrite/Messaging/Adapter/Realtime.php
2025-04-28 21:56:45 +12:00
Christy JacobandGitHub 5578e199e4 Merge pull request #9689 from appwrite/PLA-2808
feat(users): synchronously delete identities and targets in controller
2025-04-28 12:56:31 +04:00
Matej Bačo 08806afb38 Fix CSV import bug 2025-04-28 08:39:33 +02:00
Matej Bačo 13c9f79b3d Update console 2025-04-28 08:38:49 +02:00
Jake BarnbyandGitHub 8623767926 Merge pull request #9677 from ArnabChatterjee20k/chore--utopia-migration
Chore: updated utopia migration version
2025-04-28 03:51:57 +00:00
Jake BarnbyandGitHub d39fce55c1 Merge branch '1.6.x' into chore--utopia-migration 2025-04-28 03:38:30 +00:00
Steven NguyenandGitHub 70f31bb48c Merge pull request #9691 from appwrite/update-flutter-sdk
chore: update flutter sdk
2025-04-25 12:48:50 -07:00
Chirag Aggarwal b65c375655 chore: update flutter sdk 2025-04-25 19:24:12 +00:00
Fabian Gruber 270250a563 review feedback 2025-04-25 16:25:26 +02:00
Fabian Gruber 9601860247 feat(users): synchronously delete identities and targets in controller 2025-04-25 15:55:10 +02:00
Christy JacobandGitHub 09ca143231 Merge pull request #9687 from appwrite/PLA-2807
feat(dispatch): add contextual dispatch logic
2025-04-25 17:52:43 +04:00
Matej Bačo edf552fa9a Fix more tests 2025-04-25 15:10:20 +02:00
Matej Bačo 8e036b2dd4 Merge branch '1.7.x' of github.com:appwrite/appwrite into 1.7.x 2025-04-25 14:13:45 +02:00
Matej Bačo 7ae2c1bb2e Fix more tests 2025-04-25 14:13:22 +02:00
Matej BačoandGitHub bbfb93c91b Merge pull request #9676 from appwrite/feat-playground-templates
Feat: Add playground templates
2025-04-25 14:13:07 +02:00
Matej Bačo 8645ca05ba Fix tests 2025-04-25 12:06:09 +00:00
Matej Bačo 8ce3bdb6d7 Fix another bug 2025-04-25 13:17:02 +02:00
Matej Bačo 65bb7c6dfd Linter fix 2025-04-25 12:57:55 +02:00
Matej Bačo 23c4fa27be Fix tests, linter 2025-04-25 12:57:45 +02:00
Christy JacobandGitHub 2afbfea0d0 Merge pull request #9638 from appwrite/fix-zero-specifications
fix(functions): treat 0 as unlimited for CPUs and memory
2025-04-25 14:49:04 +04:00
Matej Bačo 0787034bab Fixes post-1.6.x-merge 2025-04-25 12:26:10 +02:00
Matej Bačo d8103cb57e Merge branch '1.7.x' into 1.6.x 2025-04-25 12:18:04 +02:00
Matej Bačo e1dc20b71a Fix screenshots 2025-04-25 10:43:57 +02:00
Steven Nguyen 928f535800 chore(functions): update desc for CPU and mem env vars
Clarify that 0 for _APP_FUNCTIONS_CPUS and _APP_FUNCTIONS_MEMORY means
unlimited.
2025-04-24 17:30:03 -07:00
Fabian Gruber 391e045775 feat(dispatch): add contextual dispatch logic 2025-04-24 23:15:00 +02:00
Christy JacobandGitHub 8b23d4bab1 Merge pull request #9666 from appwrite/fix-headers
fix: remove content-type header from get request specs
2025-04-24 19:14:19 +04:00
Chirag Aggarwal 187ba0a575 chore: update all examples to new endpoint 2025-04-24 14:46:03 +00:00
Chirag Aggarwal 68c85a52fb Merge branch '1.6.x' into fix-headers 2025-04-24 14:42:45 +00:00
Christy JacobandGitHub 8cb4d2894b Merge pull request #9685 from appwrite/chore-docs-endpoint
core: introduce endpoint.docs in specs
2025-04-24 18:14:01 +04:00
Chirag Aggarwal 75efa28125 core: introduce endpoint.docs in specs 2025-04-24 11:15:23 +00:00
Matej Bačo 85d48f6ff0 Upgrade browser 2025-04-24 08:57:24 +02:00
Darshan 9a7c7dee56 add: last accessed var, remove secret from model. 2025-04-24 11:08:56 +05:30
Darshan 7b88c80350 fix: internal query. 2025-04-24 09:55:56 +05:30
Darshan 479577f00b add: secret to the response model. 2025-04-24 09:55:46 +05:30
Christy JacobandGitHub 7952eafdf0 Merge pull request #9681 from appwrite/revert-9648-feat-add-configurable-function-size
Revert "Add configurable function and build size"
2025-04-23 19:49:43 +04:00
Christy JacobandGitHub de9b0e6eee Revert "Add configurable function and build size" 2025-04-23 21:18:04 +05:30
Christy JacobandGitHub aeffeb8cc8 Merge pull request #9679 from appwrite/fix-oauth-redirects
fix: ensure all 4xx errors in OAuth redirect lead to the failure URL
2025-04-23 19:23:23 +04:00
Christy JacobandGitHub a11cbc3799 Merge pull request #9680 from appwrite/non-critical-events
feat: allow non-critical events to ignore exceptions when enqueuing the event
2025-04-23 19:18:19 +04:00
Fabian Gruber b0eb6434b8 fix: nullable group field in SDK\Method 2025-04-23 17:14:19 +02:00
Fabian Gruber fe28af292b feat: allow non-critical events to ignore exceptions when enqueuing the message 2025-04-23 16:48:09 +02:00
Christy Jacob 6b4ecbcd23 fix: ensure all 4xx errors in OAuth redirect lead to the failure URL 2025-04-23 18:39:55 +04:00
Darshan 26a2180a44 fix: datetime filter to file-tokens expiry. 2025-04-23 18:55:36 +05:30
Chirag Aggarwal dab6701f79 chore: update sdk generator 2025-04-23 13:22:47 +00:00
ArnabChatterjee20k 26edc75455 updated utopia migration version 2025-04-23 15:09:44 +05:30
Matej Bačo 73a6fc2df3 Merge branch '1.7.x' into feat-playground-templates 2025-04-23 10:53:04 +02:00
Matej Bačo 05feea5f6d Fix leftover 2025-04-22 17:20:21 +02:00
Matej Bačo 62282e9515 Add playgrounds, sync screenshots 2025-04-22 17:06:01 +02:00
Chirag Aggarwal 51763a6e84 chore: update platforms 2025-04-22 13:37:02 +00:00
Chirag Aggarwal 60c336bfa1 Merge branch '1.6.x' into fix-headers 2025-04-22 13:30:46 +00:00
Christy JacobandGitHub f58c8c5370 Merge pull request #9655 from appwrite/update-sdks
chore: update sdks
2025-04-22 17:18:41 +04:00
Christy JacobandGitHub 4228bc9b63 Merge pull request #9574 from appwrite/chore-sensitive-check
chore: abstract token secret hiding to response model
2025-04-22 17:18:11 +04:00
Christy JacobandGitHub ed8c39f649 Merge pull request #8933 from appwrite/feat-multi-region-docs
feat: update API endpoint in the code examples
2025-04-22 17:16:51 +04:00
Christy Jacob c0bd4401c5 feat: regenerate specs 2025-04-22 17:02:33 +04:00
Christy Jacob cd647e0c18 Merge branch '1.6.x' of github.com:appwrite/appwrite into feat-multi-region-docs 2025-04-22 14:02:20 +04:00
Matej BačoandGitHub 8906d94e8f Merge pull request #9648 from appwrite/feat-add-configurable-function-size
Add configurable function and build size
2025-04-22 10:51:29 +02:00
fogelito e1e195cec6 update projects indexes 2025-04-20 10:25:13 +03:00
fogelito 1be83d15dd Merge branch '1.6.x' of https://github.com/appwrite/appwrite into update-collections-indexes 2025-04-20 09:57:18 +03:00
loks0n c9a7902e52 chore: update platforms 2025-04-17 19:45:32 +01:00
Chirag Aggarwal 73a10a1dca chore: include head requests 2025-04-17 17:55:33 +00:00
Chirag Aggarwal 7bd3c334ed fix: remove content-type header from get request specs 2025-04-17 17:43:13 +00:00
Christy JacobandGitHub 68e0083566 Merge pull request #9596 from appwrite/feat-group
feat: sdk group attribute
2025-04-17 18:26:01 +04:00
Christy JacobandGitHub f4e8d72593 Merge branch '1.6.x' into feat-group 2025-04-17 18:25:47 +04:00
Jake Barnby d9d15b0fbe Update queue version 2025-04-18 00:21:53 +12:00
Jake Barnby 59c4536208 Format 2025-04-18 00:10:20 +12:00
Jake Barnby cc20484131 Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter
# Conflicts:
#	composer.lock
2025-04-18 00:00:55 +12:00
Jake Barnby ec65071ae3 Revert "Add publisher consumer pool adapter"
This reverts commit fe26dcb50a.
2025-04-17 23:59:43 +12:00
Jake Barnby fe26dcb50a Add publisher consumer pool adapter 2025-04-17 22:27:20 +12:00
Jake Barnby 25a3266301 Remove dump 2025-04-17 22:25:36 +12:00
Jake BarnbyandGitHub dd3f92856a Merge pull request #9657 from ArnabChatterjee20k/fix/error-order-attr-null
Fix/throwing 400 for null order attributes
2025-04-17 09:49:44 +00:00
Jake Barnby bef10d7c84 Update specs 2025-04-17 21:36:08 +12:00
arnab e6e28f32ff added comments for test case 2025-04-17 14:59:37 +05:30
Jake Barnby 382ffceed9 Lint 2025-04-17 21:19:12 +12:00
arnab fb6ec704a1 test case added 2025-04-17 14:44:59 +05:30
Chirag Aggarwal 0f8e1db044 chore: update specs 2025-04-17 07:04:41 +00:00
Jake Barnby cd72d70432 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations 2025-04-17 17:09:51 +12:00
Jake Barnby 61cf767232 Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter 2025-04-17 17:09:13 +12:00
Jake Barnby 70364d7a07 Format 2025-04-17 17:09:08 +12:00
ArnabChatterjee20kandGitHub 772ca7d36c Merge branch '1.6.x' into fix/error-order-attr-null 2025-04-17 10:25:00 +05:30
Jake BarnbyandGitHub 189f2e05e0 Merge pull request #9651 from appwrite/pla-2776
chore: fix error logging for CLI tasks
2025-04-17 04:53:49 +00:00
Jake Barnby 100870557b Use cache pool adapter 2025-04-17 16:50:13 +12:00
Jake Barnby 03cae4c5ee Pool use project create 2025-04-17 16:49:12 +12:00
ArnabChatterjee20k b2f7ed48dd Simplify constructor usage by inlining message; limit try/catch to DB operations 2025-04-17 10:16:26 +05:30
Jake Barnby 28addd6702 Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter
# Conflicts:
#	app/controllers/api/health.php
2025-04-17 13:34:30 +12:00
Jake Barnby 4b8c68e5ed Update db 2025-04-17 13:34:08 +12:00
arnab ecd77cb2e3 added order exception in projects and vcs 2025-04-16 17:53:39 +05:30
arnab 8d3070416a added order exception in rest of the controllers 2025-04-16 17:29:36 +05:30
arnab 6e422ebe3c added teams and users order exception 2025-04-16 17:16:39 +05:30
arnab 3c602e84e6 added order exception in teams 2025-04-16 17:09:53 +05:30
arnab 1cacb87c65 added order query exception handling in the storage 2025-04-16 17:09:13 +05:30
arnab 8e4bd363d2 added catching of order exception in database controllers 2025-04-16 17:03:14 +05:30
arnab b7c2220648 added exception and errors 2025-04-16 17:02:43 +05:30
ArnabChatterjee20k 85de3d27d8 updated database version 2025-04-16 15:22:38 +05:30
Chirag AggarwalandGitHub c7ab1dda9f Merge branch '1.6.x' into pla-2776 2025-04-16 12:58:13 +05:30
Chirag Aggarwal c1f62ce0bd Merge branch '1.6.x' into feat-group 2025-04-16 04:49:07 +00:00
Jake BarnbyandGitHub 74d946e42a Merge pull request #9583 from appwrite/feat-usage-dump-multi-tenant-batch
Feat: multi tenant dual writing
2025-04-16 04:14:09 +00:00
Damodar LohaniandGitHub 523a8b6ff6 Merge branch '1.6.x' into feat-usage-dump-multi-tenant-batch 2025-04-16 08:49:17 +05:45
Jake Barnby d10757e69f Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter 2025-04-16 13:55:55 +12:00
Jake BarnbyandGitHub 06c87a28c9 Merge pull request #9656 from appwrite/fix-keys
Fix keys
2025-04-16 01:26:40 +00:00
Jake Barnby b9e8c1d8bc Skip server console test 2025-04-16 13:07:11 +12:00
Jake Barnby 53660f3100 Add more cases 2025-04-16 12:30:22 +12:00
Jake Barnby bea723ff2e Add test 2025-04-16 12:04:19 +12:00
Jake Barnby ba58a372d1 Throw on key not found 2025-04-16 10:50:53 +12:00
Chirag Aggarwal 59e43b1035 chore: update sdks 2025-04-15 20:55:11 +00:00
Christy Jacob 304f67c88f fix: usage test assertion 2025-04-15 18:18:40 +04:00
Christy JacobandGitHub 8e2571539c Merge pull request #9653 from appwrite/update-usage-test
fix: usage test assertion
2025-04-15 17:46:46 +04:00
Christy JacobandGitHub 3e0323dae8 Merge branch '1.6.x' into update-usage-test 2025-04-15 17:43:10 +04:00
Christy Jacob d0181787b9 fix: usage test assertion 2025-04-15 17:38:34 +04:00
Chirag Aggarwal f08ea92df4 chore: update cli 2025-04-15 11:08:54 +00:00
Jake Barnby 49ea2f6fd9 Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter
# Conflicts:
#	app/controllers/api/projects.php
#	composer.json
#	composer.lock
#	src/Appwrite/Platform/Workers/Deletes.php
2025-04-15 22:21:01 +12:00
Jake Barnby b972e7a1d4 Stash 2025-04-15 22:18:48 +12:00
c3120f4aaa chore: add error tag
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2025-04-15 10:30:29 +05:30
Damodar LohaniandGitHub 969c58fda9 Merge branch '1.6.x' into feat-usage-dump-multi-tenant-batch 2025-04-15 10:44:47 +05:45
Damodar Lohani 49814c2a7e bring back stats usage dump 2025-04-15 04:58:16 +00:00
Damodar Lohani f9141ca564 fix param types 2025-04-15 04:48:19 +00:00
Damodar Lohani 4edec1494a fix remove comments 2025-04-15 04:45:56 +00:00
Jake BarnbyandGitHub 0b60898ad5 Merge pull request #9643 from appwrite/feat-bulk-callbacks
Update database
2025-04-15 04:28:18 +00:00
Damodar LohaniandGitHub 82ce35029a Merge pull request #9585 from appwrite/fix-merge-stats-usage-and-dump
Fix: merge the working of StatsUsage and StatsUsageDump
2025-04-15 09:50:43 +05:45
Damodar Lohani 93f86e57ea use clone 2025-04-15 03:15:24 +00:00
a46c5d1029 Update src/Appwrite/Platform/Workers/StatsUsage.php
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2025-04-15 08:54:04 +05:45
Chirag Aggarwal 88b229b13e chore: fix error logging for CLI tasks 2025-04-14 21:35:26 +00:00
Chirag Aggarwal 3ed87a8ab9 chore: update endpoint descriptions to follow CRUD naming 2025-04-14 18:40:48 +00:00
Khushboo Verma 6e86527eb6 Keep build size in MBs 2025-04-14 14:33:46 +00:00
5d9bdd4cc7 Update app/controllers/api/functions.php
Co-authored-by: Matej Bačo <matejbacocom@gmail.com>
2025-04-14 19:53:39 +05:30
Khushboo Verma 6852ee1f0f Read buildSize from plan 2025-04-14 14:07:23 +00:00
Khushboo Verma 81c3d96629 Consistent naming 2025-04-14 14:00:44 +00:00
Khushboo Verma 1acbff316e Use 1000 instead of 1024 2025-04-14 13:46:52 +00:00
Khushboo Verma f02707627f Refactor 2025-04-14 12:16:50 +00:00
Khushboo Verma 0df1396d52 Add plan to worker.php 2025-04-14 11:54:40 +00:00
Khushboo Verma c4509f5ce7 Add plan to builds worker 2025-04-14 10:31:08 +00:00
Khushboo Verma 3f0857b36d Add plan to create deployment 2025-04-14 10:28:29 +00:00
Jake BarnbyandGitHub e3f64c3234 Merge pull request #9646 from ArnabChatterjee20k/update-migrations-version
chore: updated the migration version to 8.6
2025-04-14 10:14:18 +00:00
ArnabChatterjee20kandGitHub 2c36fab1c6 Merge branch '1.6.x' into update-migrations-version 2025-04-14 15:21:30 +05:30
ArnabChatterjee20k f8d92c04ad updated the migration version to 8.6 2025-04-14 15:09:40 +05:30
Jake Barnby 950cc420a2 Update database 2025-04-14 19:40:51 +12:00
Jake Barnby cbb943cc88 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-callbacks 2025-04-14 19:40:13 +12:00
Jake Barnby 862664dd62 Format 2025-04-14 19:05:42 +12:00
Jake Barnby 498f9e40c8 Update worker bulk method usage 2025-04-14 18:50:33 +12:00
Jake BarnbyandGitHub dc40fd7ddc Merge pull request #9644 from appwrite/fix-tasks
Fix tasks
2025-04-14 06:49:22 +00:00
Jake Barnby a6281992b1 Fix maintenance 2025-04-14 18:26:13 +12:00
Jake Barnby 3be50d2ab5 Fix syntax 2025-04-14 18:26:07 +12:00
Jake Barnby 2a2bf7f154 Fix maintenance 2025-04-14 18:23:35 +12:00
Jake Barnby 9a8ba13dbf Fix syntax 2025-04-14 18:18:10 +12:00
Jake Barnby ecdea8b487 Update database 2025-04-14 18:07:12 +12:00
Damodar LohaniandGitHub 5f6e65c1aa Merge branch 'feat-usage-dump-multi-tenant-batch' into fix-merge-stats-usage-and-dump 2025-04-13 09:47:45 +05:45
Damodar LohaniandGitHub 932f34df92 Merge branch '1.6.x' into feat-usage-dump-multi-tenant-batch 2025-04-13 09:47:30 +05:45
Damodar Lohani fd5a900758 update database 2025-04-13 03:46:59 +00:00
Damodar LohaniandGitHub fb7223bd1b Merge branch 'feat-usage-dump-multi-tenant-batch' into fix-merge-stats-usage-and-dump 2025-04-13 09:30:51 +05:45
Chirag Aggarwal b1685a5ca1 chore: update users auth group to sessions 2025-04-12 13:38:00 +00:00
Chirag Aggarwal c3656fd4e7 Merge branch '1.6.x' into feat-group 2025-04-12 06:50:20 +00:00
Chirag Aggarwal b3c9e6181f chore: update groups 2025-04-12 06:50:02 +00:00
Chirag Aggarwal 04733e25c8 chore: make group nullable and remove it from endpoints where its not required 2025-04-12 06:41:57 +00:00
Steven NguyenandGitHub 67084374fb Merge pull request #9637 from appwrite/update-console
chore: update console
2025-04-11 20:22:47 -07:00
Steven Nguyen b431eb4a51 fix(functions): treat 0 as unlimited for CPUs and memory
Prior versions of Appwrite treated 0 as unlimited for
_APP_FUNCTIONS_CPUS and _APP_FUNCTIONS_MEMORY. As such, this PR updates
the specification validator and the list specifications endpoint to also
treat the default 0 value as unlimited, allowing any specification.
2025-04-11 12:13:06 -07:00
Steven NguyenandGitHub 4d9521edc6 Merge pull request #9633 from appwrite/fix-migrations-destination
Fix migrations
2025-04-11 11:18:52 -07:00
Chirag Aggarwal 1dd0b419c5 chore: update console 2025-04-11 15:32:03 +00:00
Christy JacobandGitHub 636b0775fd Merge pull request #9636 from appwrite/revert-9632-revert-8667-multi-region-support
Revert "Revert "Multi region support""
2025-04-11 19:19:37 +04:00
Shimon NewmanandGitHub c4a506445d Revert "Revert "Multi region support"" 2025-04-11 17:52:19 +03:00
Steven Nguyen 8d046f021c fix: update upgrade migration to create missing attributes
Between version 1.6.0 and 1.6.1, the migrations collection was updated
to include a destination attribute and the databases collection was
updated to include an originalId attribute. However, the upgrade
migration was not updated to create these attributes.

This PR updates the migration to create the missing attributes.
2025-04-10 16:21:12 -07:00
Christy JacobandGitHub 2d0885ed70 Merge pull request #9632 from appwrite/revert-8667-multi-region-support
Revert "Multi region support"
2025-04-10 20:55:05 +04:00
Christy JacobandGitHub ffe153630d Revert "Multi region support" 2025-04-10 22:19:23 +05:30
Christy JacobandGitHub 6cd9fc72d9 Merge pull request #8667 from appwrite/multi-region-support
Multi region support
2025-04-10 20:05:21 +04:00
shimon 312d1029c0 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-04-10 18:36:05 +03:00
shimon fb802c7fe4 addressing comments 2025-04-10 18:35:45 +03:00
Christy JacobandGitHub 942775c352 Merge pull request #9631 from appwrite/chore-bump-console-5.2.56
Bump console to version 5.2.56
2025-04-10 19:01:06 +04:00
shimon f5852a52e2 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-04-10 17:20:23 +03:00
shimon ff89da513f addressing comments 2025-04-10 17:20:05 +03:00
Jake Barnby 31cf1266e1 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations 2025-04-10 18:22:21 +12:00
Steven Nguyen 49ab765ee8 Bump console to version 5.2.56 2025-04-09 17:02:24 -07:00
Christy JacobandGitHub 2495101dfd Merge pull request #9624 from appwrite/feat-cache-telemetry
feat: cache telemetry
2025-04-10 00:31:06 +04:00
shimon 07cdd66296 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-04-09 10:02:40 +03:00
Jake BarnbyandGitHub e1b4917acf Merge pull request #9628 from appwrite/chore-update-migrations
Update migrations lib
2025-04-09 05:45:43 +00:00
Jake Barnby 796a1b5bd2 Update migrations lib 2025-04-09 17:26:41 +12:00
Jake Barnby cfab30b43f Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations
# Conflicts:
#	app/init/resources.php
2025-04-09 16:31:52 +12:00
Christy JacobandGitHub 881525f349 Merge pull request #9623 from appwrite/feat-figma-oauth
feat: add figma oauth provider
2025-04-08 16:57:37 +04:00
Christy JacobandGitHub 8086d6eef0 Merge pull request #9625 from appwrite/update-composer
chore: update dependencies
2025-04-08 16:28:51 +04:00
Chirag Aggarwal badbcaf1a8 chore: update dependencies 2025-04-08 11:33:38 +00:00
loks0n e6d9c5c5fd chore: fmt 2025-04-08 12:24:05 +01:00
loks0n 86c26f2dc7 feat: cache telemetry 2025-04-08 12:12:28 +01:00
Chirag Aggarwal 2c453d5fd9 fix: request issues and permissions 2025-04-08 08:51:04 +00:00
Chirag Aggarwal 3bd8405deb feat: add figma oauth provider 2025-04-08 07:56:35 +00:00
shimon fed98ffdfe Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	docker-compose.yml
2025-04-07 13:06:54 +03:00
fogelito 4396c5f0fc Update indexes console 2025-04-07 08:48:53 +03:00
Damodar LohaniandGitHub 57bc76edc7 Merge branch '1.6.x' into feat-usage-dump-multi-tenant-batch 2025-04-07 09:21:32 +05:45
shimon 31c326fe87 sync with 1.6.x 2025-04-03 11:31:45 +03:00
shimon 0dc319d244 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-04-03 11:30:14 +03:00
Jake Barnby 608bda0b48 Update lock 2025-04-02 13:47:12 +13:00
Jake Barnby 91d4b1b99f Merge remote-tracking branch 'origin/1.6.x' into feat-pool-adapter
# Conflicts:
#	composer.lock
2025-04-02 13:40:27 +13:00
Damodar Lohani ae0cdaff63 Merge remote-tracking branch 'origin/feat-usage-dump-multi-tenant-batch' into fix-merge-stats-usage-and-dump 2025-04-01 04:38:40 +00:00
Chirag Aggarwal 2a7038bb8e chore: remove logging 2025-03-31 09:33:37 +00:00
Chirag Aggarwal 2c434924de chore: update openapi specs 2025-03-31 09:32:47 +00:00
Chirag Aggarwal d9b7a018ea chore: update specs 2025-03-31 06:23:31 +00:00
Chirag Aggarwal abcaf6cd73 feat: sdk group attribute 2025-03-31 05:48:17 +00:00
Damodar Lohani 81ee68e219 Merge remote-tracking branch 'origin/1.6.x' into feat-usage-dump-multi-tenant-batch 2025-03-31 04:07:10 +00:00
Damodar Lohani e14ae7ea4a fix 2025-03-31 03:59:37 +00:00
Damodar Lohani ec21effd2c Fix type error 2025-03-31 03:55:06 +00:00
Damodar Lohani 7399362c20 Merge remote-tracking branch 'origin/1.6.x' into fix-merge-stats-usage-and-dump 2025-03-31 03:45:46 +00:00
Damodar Lohani d5ad714f5a fix missing queue name 2025-03-30 06:09:03 +00:00
Damodar Lohani 1389bab3d1 remove db storage check 2025-03-30 05:56:14 +00:00
Damodar Lohani 100189c0fb Merge remote-tracking branch 'origin/feat-usage-dump-multi-tenant-batch' into fix-merge-stats-usage-and-dump 2025-03-30 05:55:28 +00:00
Damodar Lohani d36a09eec6 remove database storage triggers 2025-03-30 05:54:48 +00:00
Jake Barnby a9152c0c20 Doctor pool use 2025-03-28 16:51:47 +13:00
Jake Barnby 906f774a90 Worker scope pool use 2025-03-28 16:50:34 +13:00
Jake Barnby ec2f3b69cc API scope pool use 2025-03-28 16:50:13 +13:00
Jake Barnby 5b843015b0 Realtime scope pool use 2025-03-28 16:43:17 +13:00
Jake Barnby 3a2ff9790c CLI scope pool use 2025-03-28 16:42:26 +13:00
Jake Barnby 08bc6379bd Remove redundant DSN parse 2025-03-28 14:43:34 +13:00
Jake Barnby 10c6315589 Add doc comments 2025-03-27 23:00:28 +13:00
Jake Barnby 536b6162ce Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations 2025-03-27 21:39:36 +13:00
Damodar Lohani f4d01f4c37 fix: remove stats usage dump worker from docker 2025-03-27 08:36:52 +00:00
Jake Barnby 6608023b9f Regen specs 2025-03-27 21:30:10 +13:00
Damodar Lohani cfb1f4fcdb fix: remove stats usage dump 2025-03-27 08:29:12 +00:00
Damodar Lohani 05067302d2 Fix: merge the working of StatsUsage and StatsUsageDump 2025-03-27 08:25:48 +00:00
Jake Barnby 7c3d2c8435 Spread validator args 2025-03-27 21:06:04 +13:00
Jake Barnby aa0111550b Handle parameter class for spec generation 2025-03-27 21:04:14 +13:00
Jake Barnby 04c3182f7c Use parameter class instead of inline array 2025-03-27 21:03:56 +13:00
Jake Barnby 5aca1fcfa9 Fix content type usage 2025-03-27 21:03:28 +13:00
Jake Barnby 254c12b084 Use parameter class in method class 2025-03-27 21:03:10 +13:00
Jake Barnby 6615c1a382 Add SDK parameter class 2025-03-27 21:02:25 +13:00
Jake Barnby 7ca4009457 Remove leftover 2025-03-27 21:01:59 +13:00
Damodar Lohani 1a54bd58a6 check empty project id 2025-03-27 07:01:44 +00:00
Damodar Lohani c443a2f999 Fix dual writing 2025-03-27 05:50:01 +00:00
Jake Barnby ee9efe530d Add max batch size resource for plan override 2025-03-27 18:28:55 +13:00
Jake Barnby 985476ac50 Bulk operations for server/console only 2025-03-27 18:16:25 +13:00
Jake Barnby 7e6799d6dd Block bulk operations on collections with relationships 2025-03-27 18:13:10 +13:00
Jake Barnby 2e12ae4390 Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations
# Conflicts:
#	composer.lock
2025-03-27 18:11:03 +13:00
Damodar Lohani 9f537a5bee Feat: multi tenant dual writing 2025-03-27 04:59:34 +00:00
Chirag Aggarwal 8b1e97bae4 chore: remove console import 2025-03-26 14:38:31 +00:00
Chirag Aggarwal 7b8f25696c chore: added showSensitve wrapper instead of param 2025-03-26 14:37:35 +00:00
shimon 35cd2b5295 adding custom domain validation against _APP_CUSTOM_DOMAIN_DENY_LIST 2025-03-26 09:39:53 +02:00
shimon 989fa2b8a0 adding custom domain validation against _APP_CUSTOM_DOMAIN_DENY_LIST 2025-03-26 09:25:49 +02:00
shimon cb2d0dc592 adding custom domain validation against _APP_CUSTOM_DOMAIN_DENY_LIST 2025-03-26 09:07:38 +02:00
shimon a9d1f6668f adding custom domain validation against _APP_CUSTOM_DOMAIN_DENY_LIST 2025-03-26 09:05:36 +02:00
shimon 8447732614 adding region query to deleteProjectsByTeam 2025-03-25 21:11:41 +02:00
shimon 9f446da0a5 adding region query to deleteProjectsByTeam 2025-03-25 20:28:29 +02:00
shimon 62effa7bc4 adding region query to deleteProjectsByTeam 2025-03-25 20:23:08 +02:00
shimon dedcdc2e0e adding region query to deleteProjectsByTeam 2025-03-25 19:13:11 +02:00
shimon 854256e8a6 debug 2025-03-25 10:47:05 +02:00
shimon d72f69f792 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.lock
2025-03-25 10:46:41 +02:00
Chirag AggarwalandGitHub 7fdde1a518 Update Response.php 2025-03-25 14:09:47 +05:30
shimon 16aca35bd4 debug 2025-03-24 20:33:51 +02:00
Chirag Aggarwal e93010c5fe chore: add showSensitive attribute 2025-03-24 14:26:56 +00:00
Chirag Aggarwal d677b8ed88 fix: webhook tests 2025-03-24 14:06:36 +00:00
Chirag Aggarwal 3399308ee3 Merge branch '1.6.x' into chore-sensitive-check 2025-03-24 12:28:54 +00:00
shimon 56d78b1712 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	app/worker.php
2025-03-24 10:56:47 +02:00
shimon e4c4ffdb3c pull resources changes 2025-03-24 10:54:18 +02:00
shimon ab1683070b debug 2025-03-23 19:59:51 +02:00
shimon 9f3d15bd1c Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-03-23 19:58:34 +02:00
shimon a7199ff980 debug 2025-03-23 10:44:00 +02:00
shimon 434fcdc508 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-03-21 19:08:53 +02:00
shimon ed7c2fa451 debug 2025-03-21 19:08:37 +02:00
shimon 69bdf50c85 debug 2025-03-20 18:27:23 +02:00
shimon ea02639767 debug 2025-03-20 18:15:51 +02:00
shimon bd19da2e7a debug 2025-03-20 17:12:59 +02:00
shimon 6c0ce5cc41 debug 2025-03-20 15:05:48 +02:00
shimon 403e5773a2 cleanup 2025-03-20 14:26:11 +02:00
shimon 68e8b7ca2b Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-03-20 10:47:07 +02:00
shimon 438d5185a9 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-03-19 19:47:44 +02:00
shimon d3cabcd5ac composer 2025-03-19 11:15:25 +02:00
shimon 84133ef631 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.lock
2025-03-19 11:13:58 +02:00
shimon 2be59a94da update 2025-03-19 11:13:30 +02:00
shimon fca2e95fdd debug 2025-03-18 19:29:40 +02:00
shimon 5683c310db debug 2025-03-18 18:36:46 +02:00
Jake Barnby bc866dc717 Sync with 1.6.x 2025-03-17 21:10:30 +13:00
Jake Barnby 94f9d0140b Merge branch '1.6.x' into feat-bulk-operations
# Conflicts:
#	app/config/specs/open-api3-1.6.x-client.json
#	app/config/specs/open-api3-1.6.x-console.json
#	app/config/specs/open-api3-1.6.x-server.json
#	app/config/specs/swagger2-1.6.x-client.json
#	app/config/specs/swagger2-1.6.x-console.json
#	app/config/specs/swagger2-1.6.x-server.json
#	app/init.php
#	composer.json
#	composer.lock
2025-03-17 20:44:08 +13:00
shimon ab790f6c02 debug 2025-03-16 15:24:29 +02:00
shimon ff618a0565 debug 2025-03-16 14:42:22 +02:00
shimon b3db296f13 sync with main 2025-03-16 14:05:03 +02:00
shimon e019e426f1 debug 2025-03-16 13:47:54 +02:00
shimon adacec4ad1 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	app/init.php
#	composer.lock
2025-03-16 10:55:24 +02:00
shimon a60d916c51 debug 2025-03-11 19:18:05 +02:00
shimon d522b1a04c debug 2025-03-11 18:56:24 +02:00
shimon 4b740dce86 sync with 1.6.x 2025-03-11 18:23:35 +02:00
shimon 6a05bd4e0d Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	app/init.php
2025-03-11 18:19:44 +02:00
shimon 0570567b2e sync with 1.6.x 2025-03-09 21:24:24 +02:00
shimon 3a29bcb41b Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.lock
2025-03-09 21:23:33 +02:00
shimon 1b3fe3046d sync with 1.6.x 2025-03-06 13:12:03 +02:00
shimon 7c91157dc8 sync with 1.6.x 2025-03-06 12:10:10 +02:00
shimon 584e4c0d75 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-03-06 12:03:10 +02:00
shimon f0477f8940 sync with 1.6.x 2025-03-05 17:30:59 +02:00
shimon 3bc81c82ec Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	src/Appwrite/Platform/Workers/Usage.php
2025-03-05 17:29:57 +02:00
Jake Barnby 2f43a3566d Remove bulk update permissions param 2025-03-05 16:42:09 +13:00
Jake Barnby 0f0ea5e96c Update deps 2025-03-05 15:18:14 +13:00
Jake Barnby 99377e26ee Reset fixes 2025-03-05 15:09:06 +13:00
Jake Barnby d809ab1ff3 Merge branch 'feat-bulk-operations' of github.com:appwrite/appwrite into feat-bulk-operations
# Conflicts:
#	app/controllers/api/databases.php
#	app/controllers/shared/api.php
#	composer.json
#	composer.lock
2025-03-05 12:47:47 +13:00
Jake Barnby a5c4fe0a2d Merge remote-tracking branch 'origin/1.6.x' into feat-bulk-operations
# Conflicts:
#	app/config/specs/open-api3-latest-client.json
#	app/config/specs/open-api3-latest-console.json
#	app/config/specs/open-api3-latest-server.json
#	app/config/specs/swagger2-latest-client.json
#	app/config/specs/swagger2-latest-console.json
#	app/config/specs/swagger2-latest-server.json
#	app/controllers/api/databases.php
#	app/controllers/shared/api.php
#	composer.json
#	composer.lock
#	docs/references/databases/create-document.md
2025-03-05 12:44:39 +13:00
shimon 12eb3b4eea debug 2025-03-03 10:47:28 +02:00
shimon adb451234b debug 2025-03-02 22:27:13 +02:00
shimon 52a73856bc debug 2025-03-02 21:19:45 +02:00
shimon 921b9154eb debug 2025-03-02 20:56:28 +02:00
shimon 5ed1ca617f cleanup 2025-02-27 11:02:27 +02:00
shimon 12f274223f sync against 1.6.x 2025-02-27 10:31:47 +02:00
shimon 368b61493f Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.lock
2025-02-27 10:29:06 +02:00
shimon 458df23797 debug cert 2025-02-26 17:41:44 +02:00
shimon 369caae87d debug cert 2025-02-26 17:40:06 +02:00
shimon f48791fba6 debug cert 2025-02-26 15:53:04 +02:00
shimon e2b9c64f91 debug cert 2025-02-25 18:01:30 +02:00
shimon 69e9a1bd8c debug cert 2025-02-25 17:42:36 +02:00
shimon 1f606a591d debug cert 2025-02-24 14:13:18 +02:00
shimon e972ccedd6 debug 2025-02-20 10:26:39 +02:00
shimon e4369e5e85 debug 2025-02-20 09:48:17 +02:00
shimon 45b2d58aa5 debug 2025-02-19 23:28:09 +02:00
shimon be1c12147f debug 2025-02-19 22:59:04 +02:00
shimon 4157e89ab7 debug 2025-02-19 22:33:13 +02:00
shimon c151d2aaca debug 2025-02-19 18:18:39 +02:00
shimon baa40e4007 debug 2025-02-19 18:15:26 +02:00
shimon 197e32f128 debug 2025-02-19 13:52:14 +02:00
shimon 39e5c5e734 debug 2025-02-19 10:11:47 +02:00
shimon a8a8df602f sync against 1.6.x 2025-02-17 10:30:53 +02:00
shimon d641177618 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-02-16 20:13:11 +02:00
shimon 463bc4aac3 sync against 1.6.x 2025-02-15 06:28:19 +02:00
shimon e597ee4493 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	app/http.php
2025-02-15 06:24:48 +02:00
shimon 00478e8533 _APP_DOMAIN_FUNCTIONS_FALLBACK 2025-02-14 11:08:43 +02:00
Chirag AggarwalandGitHub 9aad6721cd Merge branch '1.6.x' into chore-sensitive-check 2025-02-14 09:04:56 +05:30
Bradley Schofield c560524a42 Add more benchmarks, update DB Lib 2025-02-13 16:52:53 +09:00
Chirag Aggarwal ec5fd1d798 chore: remove showsensitive 2025-02-11 09:06:11 +00:00
Chirag Aggarwal f723948907 Merge branch '1.6.x' into chore-sensitive-check 2025-02-11 08:29:06 +00:00
Bradley Schofield 0ccaf9adff Add more benchmarks 2025-02-11 15:57:27 +09:00
d490879615 Update app/controllers/api/databases.php
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2025-02-11 09:24:35 +09:00
709f616f7f Update app/controllers/api/databases.php
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2025-02-11 09:24:26 +09:00
a8a5b4d00c Update docs/references/databases/update-documents.md
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2025-02-11 09:24:18 +09:00
Bradley Schofield a27ba015e9 Merge branch '1.6.x' into feat-bulk-operations
# Conflicts:
#	app/controllers/api/databases.php
#	app/controllers/shared/api.php
#	composer.json
#	composer.lock
2025-02-11 09:23:49 +09:00
shimon 2106022507 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.json
#	composer.lock
2025-02-09 10:06:56 +02:00
Matej Bačo e992ed11c1 Fix unwanted redirects in functions 2025-02-06 11:08:28 +01:00
shimon 50400c4b43 _APP_DOMAIN_FUNCTIONS_FALLBACK 2025-02-05 13:14:03 +02:00
shimon 3cfb013f1e _APP_DOMAIN_FUNCTIONS_FALLBACK 2025-02-05 12:49:04 +02:00
shimon be27912a6e _APP_DOMAIN_FUNCTIONS_FALLBACK 2025-02-05 11:35:19 +02:00
shimon b73b450a2e updated against 1.6.x 2025-02-04 21:36:06 +02:00
shimon 4dc7206e04 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.json
#	composer.lock
2025-02-04 21:12:11 +02:00
Jake Barnby 386c6076b2 Merge branch '1.6.x' into feat-bulk-operations
# Conflicts:
#	composer.json
#	composer.lock
2025-02-05 01:52:35 +13:00
Jake Barnby 5be62c22e0 Move specification into SDK namespace 2025-02-05 00:08:56 +13:00
Bradley Schofield bd20ea0300 Fix additional methods with multiple responses 2025-01-30 14:19:20 +09:00
Bradley Schofield 40f8a4cb02 Merge branch '1.6.x' into feat-bulk-operations 2025-01-27 09:36:15 +09:00
shimon b18d3bc678 payload debug 2025-01-24 18:36:32 +02:00
shimon 0cc5088e8e payload debug 2025-01-24 18:03:24 +02:00
shimon 2c4f5d3daa payload debug 2025-01-24 17:52:07 +02:00
shimon 1675683e76 payload debug 2025-01-24 17:38:29 +02:00
shimon 78dcfd2770 payload debug 2025-01-24 17:25:57 +02:00
shimon 87de071f53 payload debug 2025-01-24 16:53:26 +02:00
shimon 39585d0438 payload debug 2025-01-24 16:46:02 +02:00
shimon 270dfd685d payload debug 2025-01-24 16:39:16 +02:00
shimon de29879793 payload debug 2025-01-24 16:22:11 +02:00
shimon a70e323a15 payload debug 2025-01-24 09:41:53 +02:00
Bradley Schofield 5dadd8caea Fix required/whitelist system and descriptions 2025-01-24 16:19:43 +09:00
shimon ff1bfb61f1 payload debug 2025-01-24 09:06:10 +02:00
Bradley Schofield a6f459ecca Cleanup a few leftover from development 2025-01-24 14:26:17 +09:00
shimon 54c8a890d3 removed comments 2025-01-23 09:23:19 +02:00
shimon 74b06cdd96 debug platforms 2025-01-23 08:51:13 +02:00
shimon 5113c9e50a debug platforms 2025-01-23 07:53:03 +02:00
shimon 0052487d49 debug platforms 2025-01-23 07:47:23 +02:00
shimon 9841f6ae87 debug platforms 2025-01-23 07:40:44 +02:00
shimon 9b58ae7ff5 debug platforms 2025-01-23 07:23:35 +02:00
Bradley Schofield 2647379557 Fix missing dependency 2025-01-23 13:24:56 +09:00
Bradley Schofield 8fb7a2db32 Merge branch '1.6.x' into feat-bulk-operations
# Conflicts:
#	app/config/specs/open-api3-latest-client.json
#	app/config/specs/open-api3-latest-console.json
#	app/config/specs/open-api3-latest-server.json
#	app/config/specs/swagger2-latest-client.json
#	app/config/specs/swagger2-latest-console.json
#	app/config/specs/swagger2-latest-server.json
#	app/controllers/api/databases.php
#	app/controllers/api/functions.php
#	app/controllers/api/migrations.php
#	app/controllers/api/projects.php
#	app/controllers/api/proxy.php
#	app/controllers/api/storage.php
#	app/controllers/api/users.php
#	app/controllers/api/vcs.php
#	composer.json
#	composer.lock
#	docs/references/account/create-push-target.md
#	docs/references/account/delete-push-target.md
#	docs/references/account/update-push-target.md
#	src/Appwrite/SDK/Method.php
#	src/Appwrite/Specification/Format/OpenAPI3.php
#	src/Appwrite/Specification/Format/Swagger2.php
2025-01-23 11:19:20 +09:00
shimon 59c41478ca debug platforms 2025-01-22 21:14:41 +02:00
shimon 37087c37ca debug platforms 2025-01-22 20:44:18 +02:00
shimon 066008293d debug 2025-01-22 18:49:57 +02:00
shimon b9acae5a25 debug 2025-01-21 09:43:34 +02:00
shimon d0452e5d3b debug 2025-01-20 19:26:14 +02:00
shimon f94f6642ea debug 2025-01-20 17:45:42 +02:00
shimon 01dc8fa396 debug 2025-01-20 16:16:38 +02:00
shimon 430c883a88 debug 2025-01-20 15:29:33 +02:00
shimon dbec8c01a9 debug 2025-01-20 11:47:47 +02:00
shimon 0c37530974 debug 2025-01-20 11:34:25 +02:00
shimon 5fa4a1232f debug 2025-01-20 11:32:54 +02:00
shimon 645fbd4f1c debug 2025-01-20 10:33:06 +02:00
shimon b2f920d983 debug 2025-01-20 10:03:54 +02:00
shimon 3c152b8349 debug 2025-01-20 09:25:15 +02:00
shimon bad427071e debug 2025-01-19 22:41:00 +02:00
shimon 419d18bb1c debug 2025-01-19 22:25:03 +02:00
shimon 6e1675c574 debug 2025-01-19 22:10:52 +02:00
shimon 561af1d386 debug 2025-01-19 21:03:48 +02:00
shimon 286f7e6b86 added attr installations collection 2025-01-19 11:22:22 +02:00
shimon fe18afcfca Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2025-01-19 10:33:47 +02:00
shimon 348199712a composer.lock 2025-01-16 15:10:07 +02:00
shimon 1ae7d730ba Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support 2025-01-16 15:04:52 +02:00
Jake BarnbyandGitHub 39c70b3539 Merge pull request #9108 from appwrite/feat-new-sdk-label
Feat new sdk label
2025-01-16 23:19:29 +13:00
Bradley Schofield e0101def27 Fix tests 2025-01-16 17:47:36 +09:00
Bradley Schofield 469732f482 Address Comments 2025-01-16 14:34:53 +09:00
Bradley Schofield 4c22088146 Address GraphQL 2025-01-16 11:30:50 +09:00
Bradley Schofield 9d04c61cbe Attempt to fix tests 2025-01-16 11:07:09 +09:00
Bradley Schofield 48bf8001ae Address Comments 2025-01-15 16:17:35 +09:00
Bradley Schofield 1691910023 Run Linter 2025-01-15 12:56:46 +09:00
Bradley Schofield d6474a85e2 Address Comments 2025-01-15 12:54:49 +09:00
Bradley Schofield 8d7712a669 Remove debug flag 2025-01-15 09:59:16 +09:00
Bradley Schofield 396602d887 Address Comments 2025-01-15 09:58:57 +09:00
Bradley Schofield bc85d04bbc Run Linter 2025-01-14 18:10:27 +09:00
Bradley Schofield ec44b1f272 Make all delete routes return none 2025-01-14 18:09:37 +09:00
Bradley Schofield efd8dc16b3 Address Comments 2025-01-14 17:52:31 +09:00
shimon 246c334127 debug region validation 2025-01-13 21:05:19 +02:00
ChiragAgg5k 11867bef50 chore: fix webhooks 2025-01-13 21:46:42 +05:30
Chirag Aggarwal 8b0465f129 fix: webhooks 2025-01-13 15:04:33 +00:00
Bradley Schofield d54d0ea7b3 Address error validation comment 2025-01-13 09:35:05 +09:00
Chirag Aggarwal 99f736aa52 chore: add sensitive to fn logs n errors 2025-01-11 13:46:44 +00:00
Chirag AggarwalandGitHub 48fd3b371e Merge branch '1.6.x' into chore-sensitive-check 2025-01-10 23:51:26 +05:30
Chirag Aggarwal acea8812da chore: add senstive attribute to session 2025-01-10 18:21:04 +00:00
Chirag Aggarwal 13597d7c54 chore: abstract token secret hiding to response model 2025-01-10 13:47:38 +00:00
Bradley Schofield 8f2cca5b0f Fix Response Models 2025-01-10 16:53:09 +09:00
Bradley Schofield a1c70a6956 Run Formatter, Fix GraphQL 2025-01-10 14:23:04 +09:00
Bradley Schofield 87de19b610 Address Comments 2025-01-10 02:07:56 +09:00
shimon f4d2583865 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support 2025-01-08 15:54:46 +02:00
shimon 18f17ff9fb remove abuse from deletes worker 2025-01-08 15:54:31 +02:00
Bradley Schofield 0d6095ba18 Add improved error handling for SDK Class 2025-01-03 14:16:26 +00:00
Bradley Schofield 6a782ce373 Implement SDKResponse class 2024-12-30 11:32:40 +00:00
shimon 33a8da45bd rollback project usage changes 2024-12-25 12:34:02 +02:00
shimon a7d09118e4 composer 2024-12-24 18:53:28 +02:00
shimon 0e0009dd27 composer 2024-12-24 18:52:33 +02:00
shimon 3159e5de0c project usage updates 2024-12-24 18:22:17 +02:00
shimon e4bdbdd9ba Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.lock
2024-12-24 18:18:44 +02:00
Bradley Schofield 624c91816b Begin work on SDKResponse refactor 2024-12-20 12:06:09 +09:00
Bradley Schofield 64a957859e Run Linter 2024-12-17 10:39:06 +09:00
Bradley Schofield fa053e493a Update specs 2024-12-17 10:33:08 +09:00
Bradley Schofield 1361dbdec5 Remove get version API from SDKs 2024-12-17 10:33:02 +09:00
Bradley Schofield 8ae462c317 Fix JSON Encode for multiplex objects 2024-12-17 10:31:26 +09:00
Bradley Schofield 2997a11274 Add SDK Multiplexing 2024-12-17 10:27:00 +09:00
Bradley Schofield 67a72edebf Run Linter 2024-12-16 15:03:57 +09:00
Bradley Schofield b4c77fbd5f Get Initial Draft Working 2024-12-16 14:59:01 +09:00
shimon e154407fc6 Merge remote-tracking branch 'origin/multi-region-support' into multi-region-support 2024-12-14 20:23:32 +02:00
shimon 06b69360f4 sync with 1.6.x 2024-12-14 20:23:07 +02:00
shimon aa2a45f142 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	app/controllers/api/functions.php
#	app/controllers/api/messaging.php
#	docker-compose.yml
2024-12-14 20:18:06 +02:00
Jake Barnby 54d1ef257d Remove logs 2024-12-12 21:01:26 +13:00
Jake Barnby 39e4a04625 Fix default region 2024-12-12 20:31:50 +13:00
Jake Barnby 9a89cc1332 Remove logs 2024-12-12 19:06:35 +13:00
Jake Barnby f4637e1b7d Create audit/abuse for V2 2024-12-12 18:55:25 +13:00
Jake Barnby 8f390a70c7 Fix self-hosted region check default 2024-12-12 18:54:58 +13:00
Bradley Schofield f7e69624c6 Address comments 2024-12-11 10:19:10 +09:00
Bradley Schofield e9c2ebbcf5 Implement SDK Multiplexing for Create Document/s 2024-12-10 12:31:26 +09:00
Bradley Schofield 879ddb3074 Implement SDK Method Multiplexing 2024-12-09 14:21:56 +09:00
Jake Barnby c9e6bfbdb3 Update database 2024-12-09 16:48:41 +13:00
shimon 8e0bd8d18d composer 2024-12-08 15:47:29 +02:00
shimon d0be46be74 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.json
#	composer.lock
2024-12-08 15:46:49 +02:00
Jake Barnby dd6cde6ae5 Log trace 2024-12-05 21:30:26 +13:00
Jake Barnby 714c2f30d7 Update database 2024-12-05 17:50:24 +13:00
Jake BarnbyandGitHub 8c1f6aabb7 Merge pull request #8968 from appwrite/feat-bulk-create
Feat: Bulk Create Documents
2024-12-04 19:03:31 +13:00
Bradley Schofield f707be6ed3 Add extra tests 2024-12-04 09:13:08 +09:00
shimon 316b739a27 composer 2024-12-03 19:43:39 +02:00
shimon b04a85491b debug 2024-12-03 17:36:19 +02:00
shimon 635dbdb5cb debug 2024-12-03 16:38:44 +02:00
shimon d06e41f81e debug 2024-12-03 15:00:45 +02:00
Bradley Schofield bcb4ffa404 Fix Tests 2024-12-03 17:39:25 +09:00
Bradley Schofield c0d4b58eea Merge branch 'feat-bulk-operations' into feat-bulk-create
# Conflicts:
#	tests/e2e/Services/Databases/DatabasesCustomClientTest.php
2024-12-03 17:06:35 +09:00
Bradley Schofield e2ab6a05ab Fix permissions and accompanying tests 2024-12-03 16:40:03 +09:00
Jake BarnbyandGitHub 6bbb522a87 Merge pull request #8955 from appwrite/feat-bulk-updates
Feat bulk updates
2024-12-03 19:35:45 +13:00
Bradley Schofield 7f2d3beb31 Run Linter 2024-12-03 15:19:58 +09:00
Bradley Schofield 3d4917727b Address Comments 2024-12-03 15:14:07 +09:00
Bradley SchofieldandGitHub 41ead533b8 Linter 2024-12-03 05:03:51 +00:00
Bradley SchofieldandGitHub c47f65d27c Merge remote-tracking branch 'origin/feat-bulk-operations' into feat-bulk-updates 2024-12-03 05:03:02 +00:00
Bradley SchofieldandGitHub 116ba6bc7b Fix Problems with tests and params 2024-12-03 04:38:59 +00:00
Jake BarnbyandGitHub adc94cf1b4 Merge pull request #8942 from appwrite/feat-bulk-deletes
Feat bulk deletes
2024-12-03 17:36:06 +13:00
Jake BarnbyandGitHub 257733aec0 Update app/controllers/api/databases.php 2024-12-03 17:35:46 +13:00
Bradley Schofield fbbf846eb9 Run Linter 2024-12-02 19:59:48 +09:00
Bradley Schofield fbf985ea90 Add event 2024-12-02 19:57:21 +09:00
Bradley Schofield f061f724e0 Fix params 2024-12-02 19:06:34 +09:00
Bradley Schofield 125585831b Remove bulk deletes realtime test 2024-12-02 18:16:04 +09:00
Bradley Schofield 3c418c1607 Address params and events 2024-12-02 18:08:10 +09:00
Bradley Schofield 8f8c008e8b Fix params and usage 2024-12-02 18:06:04 +09:00
shimon 1a6f23c3a1 debug 2024-12-02 10:13:10 +02:00
Bradley Schofield 84ba7febe7 Run Linter 2024-12-02 16:45:03 +09:00
Bradley Schofield 7b79642f4b Run Linter 2024-12-02 16:44:15 +09:00
Bradley Schofield 949347764a Add new database events 2024-12-02 16:43:19 +09:00
Bradley Schofield 32c4debffc Remove realtime/events from bulk operations and get usage events working 2024-12-02 16:40:19 +09:00
Bradley Schofield 2850879428 Remove Events for bulk updates 2024-12-02 16:07:32 +09:00
Bradley Schofield 1c0c8f0eb6 Run Formatter 2024-12-02 13:15:41 +09:00
shimon ba510a5641 debug 2024-12-01 20:07:40 +02:00
shimon cb93b9e1e7 debug 2024-12-01 19:25:43 +02:00
shimon 61d030b2c6 sync with 1.6.x 2024-11-29 15:24:52 +02:00
shimon 1d49d8284c Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support 2024-11-29 15:02:56 +02:00
shimon 65474df642 debug 2024-11-29 13:30:04 +02:00
shimon ac27c77426 debug 2024-11-29 13:14:20 +02:00
Bradley Schofield 00e3fe12f4 Revert "Fix wrong params on feedback, disable debugging in compose file"
This reverts commit 5c895579ed.
2024-11-28 17:25:38 +09:00
Bradley Schofield 5c895579ed Fix wrong params on feedback, disable debugging in compose file 2024-11-28 17:24:53 +09:00
Bradley Schofield 104a9b6074 Remove realtime support for bulk operations 2024-11-28 16:29:22 +09:00
shimon 5e3e0b6683 debug 2024-11-26 12:43:31 +02:00
shimon 9468b08eb2 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support 2024-11-26 12:31:22 +02:00
shimon d2bf15b20b debug 2024-11-26 11:50:34 +02:00
shimon b1e5a5b987 Merge branch 'multi-region-support' of https://github.com/appwrite/appwrite into multi-region-support 2024-11-26 11:11:51 +02:00
Shimon NewmanandGitHub 9ca420a0e6 Merge pull request #9027 from appwrite/fix-no-pool-access
Fix no pool access
2024-11-26 11:08:45 +02:00
shimon 6f8c38dfa0 debug 2024-11-26 09:26:14 +02:00
Jake Barnby ddb86127b7 Fix lint 2024-11-26 18:29:10 +13:00
Jake Barnby ea0a5a186c Merge remote-tracking branch 'origin/multi-region-support' into fix-no-pool-access 2024-11-26 16:21:48 +13:00
Jake Barnby 928590b175 Only create databases for current region 2024-11-26 16:20:11 +13:00
shimon 7656ba11ff debug 2024-11-25 12:31:06 +02:00
shimon 7ae7ccbe49 debug 2024-11-25 12:02:00 +02:00
shimon 6d376df00a updates 2024-11-25 09:44:57 +02:00
Bradley Schofield 2b08db9a38 Address Comments 2024-11-25 16:22:02 +09:00
Bradley Schofield 9d652d9e79 Remove double realtime 2024-11-25 16:08:50 +09:00
Bradley Schofield e1fffa775e Fix Tests 2024-11-25 15:23:22 +09:00
Bradley Schofield 2e60698ec1 Fix double event execution on document creation 2024-11-25 15:21:56 +09:00
Bradley Schofield 90521c6bd7 Update database library version 2024-11-25 15:02:36 +09:00
Bradley Schofield 558f7f06b4 Fix Missing Model 2024-11-25 14:53:35 +09:00
Bradley Schofield 19194dabc0 Remove Bulk Operation Model 2024-11-25 14:53:01 +09:00
Bradley Schofield e1230f7465 Address Comments 2024-11-25 14:45:21 +09:00
Bradley Schofield def25a8c9b Merge branch 'feat-bulk-deletes' of https://github.com/appwrite/appwrite into feat-bulk-deletes 2024-11-25 14:34:29 +09:00
Bradley Schofield 675227d25a Address Comments 2024-11-25 14:34:23 +09:00
4e5ad33d73 Update app/controllers/api/databases.php
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2024-11-25 14:29:51 +09:00
Jake Barnby 0e03842173 Move pool access inside not V2 block 2024-11-25 17:20:27 +13:00
shimon aa8af5a213 env var 2024-11-24 23:09:22 +02:00
shimon f1a3cd13ff env var 2024-11-24 22:52:20 +02:00
shimon 00989fcdde env var 2024-11-24 20:40:06 +02:00
shimon c677374a11 env var 2024-11-24 19:39:44 +02:00
shimon 3f0a8fbe21 env var 2024-11-24 19:03:46 +02:00
shimon 7d5ae2f1c3 env var 2024-11-24 19:01:24 +02:00
shimon 0f8ad539ad composer.lock 2024-11-24 10:32:27 +02:00
shimon 9839a4ef36 sync with 1.6.x 2024-11-24 10:31:21 +02:00
shimon e91c762953 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support 2024-11-24 10:30:54 +02:00
Bradley Schofield 54260b5a9a Use new API Spec and get realtime/events working 2024-11-22 11:51:17 +09:00
Bradley Schofield 67b95c4b39 Update API Signature to DB Lib and get realtime/events working 2024-11-22 11:07:05 +09:00
Bradley Schofield 90c4bad826 Run Linter 2024-11-22 10:44:19 +09:00
Bradley Schofield 791f0dda79 Update to use new DB Lib and get realtime working 2024-11-22 10:43:45 +09:00
shimon 3f6368f046 adding app region to console project 2024-11-21 23:35:45 +02:00
shimon d802639b0e Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	.github/workflows/tests.yml
#	app/controllers/api/projects.php
#	app/init.php
#	composer.lock
#	docker-compose.yml
#	src/Appwrite/Platform/Workers/Deletes.php
2024-11-21 22:11:35 +02:00
shimon 3d333633e4 Merge branch 'debug-whitelist-console' of https://github.com/appwrite/appwrite into multi-region-support 2024-11-21 22:00:17 +02:00
Bradley Schofield 79c043ec1f Fix Tests 2024-11-19 11:47:23 +09:00
Bradley Schofield 755e86020f Continue work on getting events working 2024-11-19 10:09:55 +09:00
Bradley Schofield 96e69b55e1 Add tests that are currently failing because of realtime and attempt to fix them 2024-11-15 12:00:11 +09:00
Bradley Schofield c210b2b874 Address Comments 2024-11-14 17:16:39 +09:00
Bradley Schofield c0ef832784 Try and fix events 2024-11-14 17:15:28 +09:00
Bradley Schofield bb7234fa98 Update database version 2024-11-13 13:45:16 +09:00
Bradley Schofield dd6bd745df Address Comments, fix permission bug 2024-11-13 13:41:18 +09:00
Bradley Schofield a8f3b63ded Add Tests for Relationships and Permissions, Update error messages to be a little clearer 2024-11-13 10:00:40 +09:00
Bradley Schofield aa42608528 Regen Specs 2024-11-13 09:22:47 +09:00
Christy Jacob 900f64bf8d feat: hack for multi region 2024-11-12 18:00:38 +01:00
loks0n dad8f597ca debug: whitelist console 2024-11-12 16:05:51 +01:00
Luke B. SilverandGitHub 90f18c57ac Merge pull request #8962 from appwrite/feat-fix-web-routes
feat fix web routes
2024-11-12 12:42:30 +01:00
loks0n 6e7dd26f75 feat: fix web routes 2024-11-12 12:37:15 +01:00
Christy JacobandGitHub 9151abc951 Merge pull request #8797 from appwrite/feat-migration
Feat migration
2024-11-12 10:27:24 +01:00
Jake Barnby 714f6b62ac Merge remote-tracking branch 'origin/feat-custom-cf-hostnames' into feat-migration 2024-11-12 21:45:04 +13:00
Jake Barnby 316693798e Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-12 21:44:50 +13:00
Jake Barnby c7f92fbb02 Merge remote-tracking branch 'origin/feat-custom-cf-hostnames' into feat-migration 2024-11-12 21:43:52 +13:00
Jake Barnby e715f9e90c Remove redundant V1 tests 2024-11-12 20:52:25 +13:00
Bradley Schofield 172d25d67c Address Comments 2024-11-12 15:43:36 +09:00
Jake Barnby f6ea6d2fc5 Fix matrix 2024-11-12 19:15:33 +13:00
Jake Barnby e626c2ad45 Run in all table modes in parallel 2024-11-12 19:14:46 +13:00
Bradley Schofield 92c93357cf Address Jake's Comments 2024-11-12 11:41:08 +09:00
Jake Barnby 3b19ef6b1e Remove V2 tests 2024-11-12 15:00:23 +13:00
Jake Barnby c1a3b29a97 Temp test all shared tables versions 2024-11-12 14:37:03 +13:00
Bradley Schofield 6faad29907 Initial Version 2024-11-12 10:20:46 +09:00
Jake Barnby aa2385ffb9 Merge branch 'revert-revert-8946-chore-update-database' into feat-migration
# Conflicts:
#	composer.json
#	composer.lock
2024-11-12 13:36:05 +13:00
Jake Barnby 8b99517dd0 Merge remote-tracking branch 'origin/1.6.x' into feat-migration 2024-11-12 13:34:54 +13:00
Jake Barnby 33037a3ae5 Update database 2024-11-12 13:34:40 +13:00
Jake Barnby b0852aeca3 Update database 2024-11-11 23:15:00 +13:00
Jake Barnby 09da4378c6 Merge remote-tracking branch 'origin/1.6.x' into feat-migration 2024-11-11 23:13:35 +13:00
Bradley Schofield 07738bdcf9 Update Specs 2024-11-11 15:29:59 +09:00
Bradley Schofield c6ca830801 Merge branch 'feat-bulk-operations' into feat-bulk-updates 2024-11-11 15:27:37 +09:00
Bradley Schofield 44234da995 Implement Bulk Updates API 2024-11-11 15:27:26 +09:00
Bradley SchofieldandGitHub 22dfcb78c4 Merge branch 'feat-bulk-operations' into feat-bulk-deletes 2024-11-11 03:59:23 +00:00
Bradley SchofieldandGitHub 60da24e521 Run Linter 2024-11-11 03:58:24 +00:00
Bradley Schofield f703a0db18 Merge branch 'feat-bulk-operations' into feat-bulk-deletes
# Conflicts:
#	app/config/specs/open-api3-latest-client.json
#	app/config/specs/open-api3-latest-console.json
#	app/config/specs/open-api3-latest-server.json
#	app/config/specs/swagger2-latest-client.json
#	app/config/specs/swagger2-latest-console.json
#	app/config/specs/swagger2-latest-server.json
#	src/Appwrite/Utopia/Response/Model/BulkOperation.php
2024-11-11 12:41:24 +09:00
Bradley Schofield 2a8ab8d610 Add base bulk operation models and envvars 2024-11-11 12:36:58 +09:00
Jake Barnby a85b43654c Reapply "Update database"
This reverts commit b1a1ad618a.
2024-11-11 15:22:57 +13:00
shimon ad8693c018 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	Dockerfile
2024-11-10 19:39:27 +02:00
shimon a0280e3c43 adding app region to console project 2024-11-10 12:26:34 +02:00
Christy Jacob 76216c3bf6 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-09 16:01:16 +00:00
loks0n c8c4576bbc Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-09 13:07:15 +01:00
loks0n dac8766eb4 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-08 22:02:31 +01:00
loks0n f6de256220 chore: composer update 2024-11-08 21:50:33 +01:00
loks0n 2f9b44930f Revert "Merge pull request #8946 from appwrite/chore-update-database"
This reverts commit c0bd1664be, reversing
changes made to b42dd86451.
2024-11-08 21:48:27 +01:00
loks0n 627df0d11f chore: remove redundant compression 2024-11-08 20:24:55 +01:00
loks0n fcd323baa4 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-08 20:24:35 +01:00
loks0n 0009b73b06 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-08 16:53:22 +01:00
shimon b5efbdbb0f updates 2024-11-08 14:43:30 +02:00
shimon a6e9d58f12 Merge branch 'feat-migration' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	app/cli.php
#	app/controllers/api/projects.php
2024-11-08 14:12:48 +02:00
shimon b496bcb6df updates 2024-11-08 14:06:02 +02:00
Jake Barnby 030e26b223 Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-08 23:33:10 +13:00
Bradley Schofield 5bf20289a5 Address Comments 2024-11-08 16:17:29 +09:00
Jake Barnby 9e69e41e02 Update lock 2024-11-08 17:04:29 +13:00
Jake Barnby 773fa6ffd6 Update lock 2024-11-08 16:34:07 +13:00
Jake Barnby 21bff77c50 Merge remote-tracking branch 'origin/feat-custom-cf-hostnames' into feat-migration
# Conflicts:
#	composer.json
#	composer.lock
2024-11-08 16:32:55 +13:00
loks0n 472f167b4a Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-07 20:31:41 +01:00
shimon f86bf6fdfd updates 2024-11-07 13:59:53 +02:00
shimon f3315c69a0 projects.php 2024-11-07 13:19:52 +02:00
shimon 76701b0cca composer 2024-11-07 13:03:45 +02:00
shimon 2cc73151d1 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.json
#	composer.lock
2024-11-07 13:02:45 +02:00
shimon 39e237dfb4 composer 2024-11-07 12:45:18 +02:00
shimon c624d94c45 composer 2024-11-07 12:44:51 +02:00
shimon b22188251d composer 2024-11-07 12:41:00 +02:00
shimon 68d017f452 composer 2024-11-07 12:36:53 +02:00
shimon 2ed854893d composer 2024-11-07 12:32:48 +02:00
shimon eb083a7e10 composer 2024-11-07 12:22:18 +02:00
shimon 2076a429c6 composer 2024-11-07 12:00:44 +02:00
shimon 59766b6ce6 composer 2024-11-07 12:00:26 +02:00
shimon 36bff12939 project creation fix 2024-11-07 11:56:09 +02:00
8a601ee058 Update src/Appwrite/Utopia/Response/Model/BulkOperation.php
Co-authored-by: Jake Barnby <jakeb994@gmail.com>
2024-11-07 14:41:14 +09:00
Bradley Schofield 95861d068d Fix Tests 2024-11-07 13:14:15 +09:00
Bradley Schofield 313adc7023 Merge branch '1.6.x' into feat-bulk-deletes
# Conflicts:
#	composer.json
#	composer.lock
2024-11-07 12:37:08 +09:00
Bradley Schofield bb40455cb7 Add documentation, update specs 2024-11-07 12:34:18 +09:00
Bradley Schofield 86053e9028 Implement Bulk Deletes API 2024-11-07 12:30:17 +09:00
Fabian Gruber b4c986839e Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-11-06 12:40:56 +01:00
Christy Jacob 4d81a901cb feat: update API endpoint in specs 2024-11-06 12:22:31 +01:00
Christy Jacob c11888c906 feat: update API endpoint in specs 2024-11-06 12:16:15 +01:00
Christy Jacob e6fb296666 feat: update API endpoint in the code examples 2024-11-06 12:07:14 +01:00
Damodar LohaniandGitHub d425c9f071 Merge pull request #8930 from appwrite/pathc-update-utopia-storage
upgrade utopia storage
2024-11-06 16:01:56 +05:45
Damodar Lohani e219ee2d84 upgrade utopia storage 2024-11-06 10:02:11 +00:00
Jake Barnby e66d0216c6 Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-06 17:02:06 +13:00
Steven NguyenandGitHub e3e20d2923 Merge pull request #8922 from appwrite/lohanidamodar-patch-4
Improve compression param checks
2024-11-05 17:35:39 -08:00
loks0n e0c503e249 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-05 19:47:29 +01:00
shimon c3a8db0ea4 Rollback cross regions connections 2024-11-05 17:14:23 +02:00
Jake Barnby 228cabab3a Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-05 23:38:24 +13:00
shimon 2b3e7f67a4 Rollback cross regions connections 2024-11-05 12:21:16 +02:00
shimon c2d5e8ec11 Rollback cross regions connections 2024-11-05 12:03:57 +02:00
Damodar Lohani 028c5366c2 make compression nullable and assign default in action
- also update the `update bucket` endpoint
2024-11-05 08:12:58 +00:00
Damodar LohaniandGitHub cca0c3ae45 Make compression param whitelist strict 2024-11-05 12:59:11 +05:45
Jake Barnby 0b85a64dab Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-04 22:44:25 +13:00
shimon 4eafce998d Rollback cross regions connections 2024-11-03 14:58:09 +02:00
shimon 4963d98331 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	composer.lock
2024-11-03 14:45:04 +02:00
Jake Barnby 1633acbdc3 Merge remote-tracking branch 'origin/feat-custom-cf-hostnames' into feat-migration
# Conflicts:
#	composer.json
#	composer.lock
2024-11-01 16:16:06 +13:00
shimon 9e07579a52 Rollback cross regions connections 2024-10-31 21:38:27 +02:00
shimon 16a2d61874 Rollback cross regions connections 2024-10-31 17:43:49 +02:00
Jake BarnbyandGitHub 75e8635563 Merge pull request #8904 from appwrite/1.6.x
Merge 1.6.x into feat-custom-cf-hostnames
2024-10-31 22:12:38 +13:00
Jake Barnby 83e94629dc Merge remote-tracking branch 'origin/feat-custom-cf-hostnames' into feat-migration 2024-10-31 21:49:49 +13:00
shimon b00b609621 sync against 1.6.x 2024-10-31 10:22:08 +02:00
shimon cdbd72ec3d sync against 1.6.x 2024-10-31 10:06:52 +02:00
shimon a6104ad8cd Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	app/worker.php
#	composer.json
#	composer.lock
#	src/Appwrite/Platform/Workers/Functions.php
2024-10-29 18:00:54 +02:00
Fabian Gruber 6e3160c502 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-29 16:15:54 +01:00
Fabian Gruber 104ec3188f Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-29 15:36:38 +01:00
shimon 4e37699e25 debug 2024-10-29 11:15:55 +02:00
shimon 118252d3af injecting poolForQueue to schedulers 2024-10-28 12:04:58 +02:00
shimon 509f06c2f0 injecting poolForQueue to schedulers 2024-10-28 11:41:59 +02:00
shimon 12458af84a injecting poolForQueue to schedulers 2024-10-28 11:34:02 +02:00
shimon 66bfc5748b injecting poolForQueue to schedulers 2024-10-28 11:15:41 +02:00
shimon cf32ba0351 debug 2024-10-27 18:10:30 +02:00
Fabian Gruber b47a4703c4 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-25 13:39:12 +02:00
Fabian Gruber 4ceff430f9 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-24 12:49:26 +02:00
Christy JacobandGitHub 5603516d88 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-23 23:56:43 +04:00
Jake Barnby 013d95ebf3 Update audit and abuse 2024-10-23 18:42:00 +13:00
Jake Barnby eca8d116c2 Fix attributes 2024-10-23 18:10:41 +13:00
Jake Barnby 8210808db0 Improve logic 2024-10-23 18:00:06 +13:00
Jake Barnby 4a003f2826 Force create audit/abuse metadata documents for shared tables v1 2024-10-23 17:41:44 +13:00
Christy Jacob 54f39494c0 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-10-22 19:51:03 +00:00
Christy Jacob ae4edf119f chore: linter 2024-10-22 19:49:10 +00:00
shimon 7be7b3389c debug 2024-10-22 21:31:32 +03:00
shimon 54555cb3cd updates 2024-10-22 19:39:57 +03:00
Fabian GruberandChristy Jacob a56293e018 chore: replace 'Expires' with 'Cache-Control: private' header to avoid CDN caching 2024-10-22 12:18:58 +00:00
shimon f8b2878943 sync with feat-migration 2024-10-22 11:09:27 +03:00
Jake Barnby a0c58317bd Merge remote-tracking branch 'origin/1.6.x' into feat-migration
# Conflicts:
#	composer.json
#	composer.lock
2024-10-22 15:13:45 +13:00
shimon e687c64ca0 sync with feat-migration 2024-10-21 18:58:11 +03:00
shimon 3ff5472543 sync with feat-migration 2024-10-21 18:57:11 +03:00
Jake Barnby d979c0c914 Create metadata document from outside if duplicate on shared tables V1 2024-10-21 22:43:47 +13:00
shimon a41b767400 debug 2024-10-21 10:32:53 +03:00
shimon ba0a495d3c debug 2024-10-21 10:01:32 +03:00
shimon 6435fa84af debug 2024-10-21 10:00:35 +03:00
shimon 8743330ad8 debug 2024-10-21 09:59:05 +03:00
shimon a37aa5551a debug 2024-10-20 17:59:39 +03:00
shimon b2521cf8a3 debug 2024-10-20 17:36:08 +03:00
shimon c853b6593a debug 2024-10-20 17:22:37 +03:00
shimon d980711c30 debug 2024-10-20 16:32:19 +03:00
shimon 7ab55e0694 debug 2024-10-20 16:21:39 +03:00
shimon db244937ff debug 2024-10-20 16:10:14 +03:00
shimon bcb593e6df debug 2024-10-20 15:56:43 +03:00
shimon 9bfab69062 debug 2024-10-20 15:33:10 +03:00
shimon 5451a9cd23 sync against feat-migration 2024-10-20 10:56:44 +03:00
Christy Jacob 5ea83b8827 chore: update cert generation 2024-10-18 23:45:42 +00:00
Christy Jacob 6fe7d92fea chore: update cert generation 2024-10-18 22:32:03 +00:00
Christy Jacob 28b02a4ba8 chore: fix bug 2024-10-18 21:18:20 +00:00
Christy Jacob f4d456fa4c chore: updat certs logic 2024-10-18 20:52:29 +00:00
Fabian Gruber 687252b15b fix adding custom hostname & error logging 2024-10-18 22:21:53 +02:00
Fabian Gruber f21b1c87a6 fix missing ssl object 2024-10-18 22:07:36 +02:00
Fabian Gruber ccbde6c470 fix zone id 2024-10-18 21:44:36 +02:00
Torsten Dittmann f189c41421 temp: custom cloudflare hostnames 2024-10-18 21:39:16 +02:00
Jake BarnbyandGitHub 5fcb990b1c Merge branch '1.6.x' into feat-migration 2024-10-15 21:17:15 +13:00
Jake Barnby 30bd25d134 Update lock 2024-10-15 20:19:19 +13:00
Jake Barnby 36d2b84301 Update lock 2024-10-15 18:09:54 +13:00
shimon a80b921927 debug 2024-10-14 16:21:23 +03:00
shimon 1373d62c52 debug 2024-10-14 16:18:01 +03:00
shimon d0481482ae debug 2024-10-14 10:36:52 +03:00
Jake Barnby 78b9be2e78 Lint 2024-10-14 14:55:18 +13:00
Jake Barnby a3b7cf84d5 Allow shared tables V1 and V2 2024-10-14 14:50:56 +13:00
Jake Barnby add6a60af4 Remove redundant files 2024-10-14 14:33:53 +13:00
Jake Barnby 4543c182b5 Merge remote-tracking branch 'origin/1.6.x' into feat-migration
# Conflicts:
#	Dockerfile
#	composer.json
#	composer.lock
#	src/Appwrite/Platform/Workers/Deletes.php
2024-10-14 14:29:04 +13:00
shimon 051d6e580c debug 2024-10-13 18:15:11 +03:00
shimon 36e4c8c399 debug 2024-10-10 12:53:45 +03:00
shimon 7921bd62d9 debug 2024-10-10 12:11:35 +03:00
shimon 74ecc20751 debug 2024-10-10 12:07:53 +03:00
shimon d477de256a update file preview cache save flow 2024-10-10 11:40:13 +03:00
shimon cffbc77d05 update file preview cache save flow 2024-10-10 11:05:54 +03:00
shimon 16fe23244b builds metric reduce 2024-10-09 20:13:28 +03:00
shimon 7d7b2c7544 debug 2024-10-08 21:51:43 +03:00
shimon d2c66894fd debug 2024-10-07 17:56:08 +03:00
shimon 1cd3e69161 debug 2024-10-07 11:42:14 +03:00
shimon 5850caff35 debug 2024-10-07 11:25:52 +03:00
shimon 0cce55565a updates 2024-10-06 20:16:00 +03:00
shimon 6b429c9da9 updates 2024-10-06 18:59:22 +03:00
shimon 8f6151a575 updates 2024-10-06 18:56:39 +03:00
shimon 3f19fac0b4 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into multi-region-support
# Conflicts:
#	app/init.php
#	app/realtime.php
#	composer.json
#	src/Appwrite/Platform/Tasks/ScheduleBase.php
#	src/Appwrite/Platform/Tasks/ScheduleExecutions.php
#	src/Appwrite/Platform/Tasks/ScheduleFunctions.php
#	src/Appwrite/Platform/Tasks/ScheduleMessages.php
#	src/Appwrite/Platform/Workers/Deletes.php
#	src/Appwrite/Platform/Workers/Migrations.php
2024-10-04 16:26:47 +03:00
shimon 08e5ed6a8a debug 2024-09-29 17:37:56 +03:00
shimon e4d554689f debug 2024-09-29 17:35:27 +03:00
shimon 19912c87c9 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2024-09-29 17:04:34 +03:00
shimon 0de1e64958 debug 2024-09-24 12:41:14 +03:00
shimon aa0a795ec6 Merge branch '1.6.x' of github.com:appwrite/appwrite into multi-region-support 2024-09-22 09:49:50 +03:00
shimon d1b062a418 Scheduled task fix 2024-09-19 20:03:15 +03:00
shimon 812d8a34cf updates 2024-09-18 13:45:09 +03:00
shimon ec02d881c9 updates 2024-09-18 11:52:59 +03:00
shimon b706571a21 _APP_OPTIONS_ROUTER_PROTECTION 2024-09-18 10:55:30 +03:00
shimon 134f90a464 fix 2024-09-17 23:32:36 +03:00
shimon eb553fa96c debug 2024-09-17 21:09:16 +03:00
shimon fd8b7eb6fc update 2024-09-17 15:35:48 +03:00
shimon 501411f5b5 1.6.x 2024-09-15 17:42:46 +02:00
shimon bee844fcdb sync against 1.6x 2024-09-15 17:40:55 +02:00
Jake Barnby d18a67e6d8 Update packages 2024-09-12 23:06:47 +12:00
Jake Barnby 25d44b5b4c Update generator 2024-09-12 23:04:44 +12:00
Jake Barnby ee7de0cb41 Update database 2024-09-12 23:02:12 +12:00
Jake Barnby 28642b9f04 Shared tables array 2024-09-12 17:06:16 +12:00
Jake Barnby c18308c024 Update database 2024-08-27 17:43:29 +12:00
Jake Barnby 1eafbf2ee2 Update database 2024-08-19 21:21:20 +12:00
Jake Barnby b98bcdd4a1 Update database 2024-08-19 18:27:45 +12:00
Jake Barnby 4c8cd5b6c6 Update audit, abuse, database 2024-08-19 14:52:15 +12:00
Jake Barnby 5b37a91b46 Merge remote-tracking branch 'origin/1.5.x' into feat-migration 2024-08-13 22:11:18 +12:00
Jake Barnby 52647cef23 Merge remote-tracking branch 'origin/feat-single-shared-metadata-docs' into feat-migration
# Conflicts:
#	composer.json
#	composer.lock
2024-08-13 22:10:57 +12:00
Jake Barnby 11ec31aefb Update database 2024-08-13 21:49:25 +12:00
Jake Barnby 73ca1efbeb Catch duplicate db on project create 2024-08-13 21:49:14 +12:00
Jake Barnby 340aa48d93 Catch duplicate on console db create 2024-08-13 21:14:52 +12:00
Jake Barnby 8ff72b341e Don't set tenant for project collections creation 2024-08-12 23:46:34 +12:00
Jake Barnby a23402075e Update database 2024-08-12 17:45:43 +12:00
Jake Barnby 6b86ed0117 Merge remote-tracking branch 'origin/1.5.x' into feat-migration
# Conflicts:
#	composer.lock
2024-08-07 22:10:04 +12:00
Jake Barnby e2a45cec8e Merge branch '1.5.x' into feat-migration
# Conflicts:
#	composer.json
#	composer.lock
2024-08-05 21:13:42 +12:00
Jake Barnby ec2eb2bfa3 Revert to utopia database instead of extension 2024-07-02 19:10:02 +12:00
Jake Barnby 10adfc5124 Add mirror override 2024-07-02 14:55:13 +12:00
Jake Barnby 5f7aae0e60 Add missing import 2024-06-21 13:43:01 +12:00
Jake Barnby 4952608b8d Merge remote-tracking branch 'origin/refactor-usage-sn' into feat-migration 2024-06-21 13:39:51 +12:00
Jake Barnby 42ebefef92 Merge remote-tracking branch 'origin/refactor-usage-sn' into feat-migration 2024-06-19 19:32:30 +12:00
Jake Barnby 03d33601b0 Override find 2024-06-14 13:08:30 +12:00
22866 changed files with 141145 additions and 37979 deletions
+3 -2
View File
@@ -15,6 +15,7 @@ _APP_SYSTEM_TEAM_EMAIL=team@appwrite.io
_APP_EMAIL_SECURITY=security@appwrite.io
_APP_EMAIL_CERTIFICATES=certificates@appwrite.io
_APP_SYSTEM_RESPONSE_FORMAT=
_APP_CUSTOM_DOMAIN_DENY_LIST=
_APP_OPTIONS_ABUSE=disabled
_APP_OPTIONS_ROUTER_PROTECTION=disabled
_APP_OPTIONS_FORCE_HTTPS=disabled
@@ -23,7 +24,7 @@ _APP_OPENSSL_KEY_V1=your-secret-key
_APP_DOMAIN=traefik
_APP_DOMAIN_FUNCTIONS=functions.localhost
_APP_DOMAIN_SITES=sites.localhost
_APP_DOMAIN_TARGET_CNAME=test.appwrite.io
_APP_DOMAIN_TARGET_CNAME=test.localhost
_APP_DOMAIN_TARGET_A=127.0.0.1
_APP_DOMAIN_TARGET_AAAA=::1
_APP_RULES_FORMAT=md5
@@ -86,7 +87,7 @@ _APP_EXECUTOR_HOST=http://exc1/v1
_APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1
_APP_SITES_RUNTIMES=static-1,node-22,flutter-3.29
_APP_MAINTENANCE_INTERVAL=86400
_APP_MAINTENANCE_DELAY=
_APP_MAINTENANCE_START_TIME=12:00
_APP_MAINTENANCE_RETENTION_CACHE=2592000
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
_APP_MAINTENANCE_RETENTION_ABUSE=86400
+26 -5
View File
@@ -1,25 +1,46 @@
name: "Console SDK Preview"
name: "SDK Preview"
on:
pull_request:
paths:
- 'app/config/specs/*-latest-console.json'
workflow_dispatch:
inputs:
platform:
type: choice
description: "Platform to build"
options:
- client
- server
jobs:
setup:
name: Setup & Build Console SDK
name: Setup & Build SDK
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set SDK type
id: set-sdk
run: |
PLATFORM="${{ github.event.inputs.platform }}"
if [ -z "$PLATFORM" ]; then
PLATFORM="console"
fi
if [ "$PLATFORM" = "server" ]; then
echo "sdk_type=nodejs" >> $GITHUB_OUTPUT
else
echo "sdk_type=web" >> $GITHUB_OUTPUT
fi
echo "platform=$PLATFORM" >> $GITHUB_OUTPUT
- name: Load and Start Appwrite
run: |
docker compose build
docker compose up -d
docker compose exec appwrite sdks --platform=console --sdk=web --version=latest --git=no
sudo chown -R $USER:$USER ./app/sdks/console-web
docker compose exec appwrite sdks --platform=${{ steps.set-sdk.outputs.platform }} --sdk=${{ steps.set-sdk.outputs.sdk_type }} --version=latest --git=no
sudo chown -R $USER:$USER ./app/sdks/${{ steps.set-sdk.outputs.platform }}-${{ steps.set-sdk.outputs.sdk_type }}
- uses: actions/setup-node@v4
with:
+2 -1
View File
@@ -156,6 +156,7 @@ jobs:
Sites,
Proxy,
Storage,
Tokens,
Teams,
Users,
Webhooks,
@@ -302,7 +303,7 @@ jobs:
docker compose up -d
sleep 30
- name: Run Projects tests with dev keys in ${{ matrix.tables-mode }} table mode
- name: Run Projects tests with dev keys in dedicated table mode
run: |
echo "Using project tables"
export _APP_DATABASE_SHARED_TABLES=
+264
View File
@@ -1,3 +1,267 @@
# Version 1.6.2
## What's Changed
### Notable changes
* Delete git folder to reduce build size in [9076](https://github.com/appwrite/appwrite/pull/9076)
* Upgrade assistant in [9100](https://github.com/appwrite/appwrite/pull/9100)
* Use redis adapter for abuse in [9121](https://github.com/appwrite/appwrite/pull/9121)
* Set base specification CPUs to 0.5 again in [9146](https://github.com/appwrite/appwrite/pull/9146)
* Add new push message parameters in [9060](https://github.com/appwrite/appwrite/pull/9060)
* Update audits to include user type in [9211](https://github.com/appwrite/appwrite/pull/9211)
* Enable HEIC in [9251](https://github.com/appwrite/appwrite/pull/9251)
* Added teamName to membership redirect url in [9269](https://github.com/appwrite/appwrite/pull/9269)
* Add support endpoint url for S3 in [9303](https://github.com/appwrite/appwrite/pull/9303)
* Added RuPay Credit Card Icon in Avatars Service in [5046](https://github.com/appwrite/appwrite/pull/5046)
* Add figma oauth provider in [9623](https://github.com/appwrite/appwrite/pull/9623)
* Update console to version 5.2.58 in [9637](https://github.com/appwrite/appwrite/pull/9637)
### Fixes
* Remove failed attribute in [9032](https://github.com/appwrite/appwrite/pull/9032)
* Fix delete notFound attribute in [9038](https://github.com/appwrite/appwrite/pull/9038)
* 🇮🇸 Added missing Icelandic translations for email strings. in [4848](https://github.com/appwrite/appwrite/pull/4848)
* fix doc comment for filter method in [5769](https://github.com/appwrite/appwrite/pull/5769)
* Delete attribute No throwing Exception on not found in [9157](https://github.com/appwrite/appwrite/pull/9157)
* Fix VCS identity collision in [9138](https://github.com/appwrite/appwrite/pull/9138)
* Fix disabling of email-otp when user wants to in [9200](https://github.com/appwrite/appwrite/pull/9200)
* Ensure user can delete session in [9209](https://github.com/appwrite/appwrite/pull/9209)
* Fix resend invitation in [9218](https://github.com/appwrite/appwrite/pull/9218)
* Fix phone number parsing exception handling in [9246](https://github.com/appwrite/appwrite/pull/9246)
* Fix amazon oauth in [9253](https://github.com/appwrite/appwrite/pull/9253)
* Fix slack oauth scopes, and updated to v2 in [9228](https://github.com/appwrite/appwrite/pull/9228)
* Fix forwarded user agent in [9271](https://github.com/appwrite/appwrite/pull/9271)
* Fix WEBP File Preview Rendering Issue in [9321](https://github.com/appwrite/appwrite/pull/9321)
* Fix build memory specifications in [9360](https://github.com/appwrite/appwrite/pull/9360)
* Fix Self Hosting functions by adding missed config in [9373](https://github.com/appwrite/appwrite/pull/9373)
* Fix resend team invite if already accepted in [9348](https://github.com/appwrite/appwrite/pull/9348)
* Fix null errors on team invite in [9391](https://github.com/appwrite/appwrite/pull/9391)
* Fix email (smtp) to multiple recipients in [9243](https://github.com/appwrite/appwrite/pull/9243)
* Fix stats timing by using receivedAt date when available in [9428](https://github.com/appwrite/appwrite/pull/9428)
* Make min/max params optional for attribute update in [9387](https://github.com/appwrite/appwrite/pull/9387)
* Fix blocking of phone sessions when disabled on console in [9447](https://github.com/appwrite/appwrite/pull/9447)
* Fix logging config in [9467](https://github.com/appwrite/appwrite/pull/9467)
* Update audit timestamp origin in [9481](https://github.com/appwrite/appwrite/pull/9481)
* Fix certificates in deletes worker in [9466](https://github.com/appwrite/appwrite/pull/9466)
* Fix console audits delete in [9547](https://github.com/appwrite/appwrite/pull/9547)
* Fix migrations in [9633](https://github.com/appwrite/appwrite/pull/9633)
* Ensure all 4xx errors in OAuth redirect lead to the failure URL in [9679](https://github.com/appwrite/appwrite/pull/9679)
* Treat 0 as unlimited for CPUs and memory in [9638](https://github.com/appwrite/appwrite/pull/9638)
* Add contextual dispatch logic to fix high CPU usage in [9687](https://github.com/appwrite/appwrite/pull/9687)
### Miscellaneous
* Merge 1.6.x into feat-custom-cf-hostnames in [8904](https://github.com/appwrite/appwrite/pull/8904)
* Improve compression param checks in [8922](https://github.com/appwrite/appwrite/pull/8922)
* upgrade utopia storage in [8930](https://github.com/appwrite/appwrite/pull/8930)
* Feat migration in [8797](https://github.com/appwrite/appwrite/pull/8797)
* feat fix web routes in [8962](https://github.com/appwrite/appwrite/pull/8962)
* Fix no pool access in [9027](https://github.com/appwrite/appwrite/pull/9027)
* feat: use environment variable to check rules format in [9039](https://github.com/appwrite/appwrite/pull/9039)
* Update storage.php in [9037](https://github.com/appwrite/appwrite/pull/9037)
* Upgrade db 0.53.200 in [9050](https://github.com/appwrite/appwrite/pull/9050)
* Chore: upgrade utopia storage in [9066](https://github.com/appwrite/appwrite/pull/9066)
* Update usage-dump payload in [9085](https://github.com/appwrite/appwrite/pull/9085)
* GitHub Workflows security hardening in [3728](https://github.com/appwrite/appwrite/pull/3728)
* Update add-oauth2-provider.md in [4313](https://github.com/appwrite/appwrite/pull/4313)
* update readme-cn some doc in [5278](https://github.com/appwrite/appwrite/pull/5278)
* Add accessibility features in [7042](https://github.com/appwrite/appwrite/pull/7042)
* Add Appwrite Cloud to read me. in [5445](https://github.com/appwrite/appwrite/pull/5445)
* Migration throw error in [9092](https://github.com/appwrite/appwrite/pull/9092)
* Fix usage payload bug in [9097](https://github.com/appwrite/appwrite/pull/9097)
* chore: replace occurrences of dbForConsole to dbForPlatform in [9096](https://github.com/appwrite/appwrite/pull/9096)
* fix(realtime): decrement connectionCounter only if connection is known in [9055](https://github.com/appwrite/appwrite/pull/9055)
* payload bug fix in [9098](https://github.com/appwrite/appwrite/pull/9098)
* Fix usage payload bug in [9099](https://github.com/appwrite/appwrite/pull/9099)
* Usage payload debug in [9101](https://github.com/appwrite/appwrite/pull/9101)
* Usage payload debug in [9103](https://github.com/appwrite/appwrite/pull/9103)
* Usage payload debug in [9104](https://github.com/appwrite/appwrite/pull/9104)
* Feat: createFunction abuse labels in [9102](https://github.com/appwrite/appwrite/pull/9102)
* Docs-create-document in [9105](https://github.com/appwrite/appwrite/pull/9105)
* Docs: Create document and unknown attribute error messages. in [5427](https://github.com/appwrite/appwrite/pull/5427)
* Fix: update project accessed at from router and schedulers in [9109](https://github.com/appwrite/appwrite/pull/9109)
* chore: initial commit in [9111](https://github.com/appwrite/appwrite/pull/9111)
* chore: optimise webhooks payload in [9115](https://github.com/appwrite/appwrite/pull/9115)
* Revert "chore: initial commit" in [9117](https://github.com/appwrite/appwrite/pull/9117)
* chore: fix attribute name in [9118](https://github.com/appwrite/appwrite/pull/9118)
* Migrate to redis abuse in [9124](https://github.com/appwrite/appwrite/pull/9124)
* Added webhooks usage stats in [9125](https://github.com/appwrite/appwrite/pull/9125)
* chore remove abuse cleanup in [9137](https://github.com/appwrite/appwrite/pull/9137)
* fix: remove abuse delete trigger in [9139](https://github.com/appwrite/appwrite/pull/9139)
* Remove firebase OAuth API endpoints in [9144](https://github.com/appwrite/appwrite/pull/9144)
* chore: release client sdks in [9112](https://github.com/appwrite/appwrite/pull/9112)
* Update general.php in [9155](https://github.com/appwrite/appwrite/pull/9155)
* feat(swoole): allow configuration override of available cpus in [9177](https://github.com/appwrite/appwrite/pull/9177)
* Usage databases api read writes addition in [9142](https://github.com/appwrite/appwrite/pull/9142)
* Fix dead connections in [9190](https://github.com/appwrite/appwrite/pull/9190)
* Add hostname to audits in [9165](https://github.com/appwrite/appwrite/pull/9165)
* chore: shifted authphone usage tracking to api calls in [9191](https://github.com/appwrite/appwrite/pull/9191)
* Revert "Fix dead connections" in [9201](https://github.com/appwrite/appwrite/pull/9201)
* Add assertEventually to messaging provider logs test in [9192](https://github.com/appwrite/appwrite/pull/9192)
* feat project sms usage in [9198](https://github.com/appwrite/appwrite/pull/9198)
* chore: add audit labels to project resources in [9056](https://github.com/appwrite/appwrite/pull/9056)
* fix sms usage in [9207](https://github.com/appwrite/appwrite/pull/9207)
* Update database in [9202](https://github.com/appwrite/appwrite/pull/9202)
* Fix dead connections in [9213](https://github.com/appwrite/appwrite/pull/9213)
* Revert "Fix dead connections" in [9214](https://github.com/appwrite/appwrite/pull/9214)
* Add logs db init for consistency in [9163](https://github.com/appwrite/appwrite/pull/9163)
* Split the collection definitions in [9153](https://github.com/appwrite/appwrite/pull/9153)
* Log path with populated parameters in [9220](https://github.com/appwrite/appwrite/pull/9220)
* Add missing scope on function template in [9208](https://github.com/appwrite/appwrite/pull/9208)
* Add relatedCollection default in [9225](https://github.com/appwrite/appwrite/pull/9225)
* fix: function usage in [9235](https://github.com/appwrite/appwrite/pull/9235)
* feat: optimise events payloads in [9232](https://github.com/appwrite/appwrite/pull/9232)
* Optimise webhook events in [9168](https://github.com/appwrite/appwrite/pull/9168)
* fix: maintenance job missing type in [9238](https://github.com/appwrite/appwrite/pull/9238)
* Update Fetch to 0.3.0 in [9245](https://github.com/appwrite/appwrite/pull/9245)
* Fix maintenance job in [9247](https://github.com/appwrite/appwrite/pull/9247)
* chore: add missing case for executions in [9248](https://github.com/appwrite/appwrite/pull/9248)
* Add index dependency exception in [9226](https://github.com/appwrite/appwrite/pull/9226)
* chore: fix benchmarking test when made from fork in [9233](https://github.com/appwrite/appwrite/pull/9233)
* Update SDK Generator versions in [9188](https://github.com/appwrite/appwrite/pull/9188)
* chore: skipped job instead of throwing error in [9250](https://github.com/appwrite/appwrite/pull/9250)
* Implement new SDK Class on 1.6.x in [9237](https://github.com/appwrite/appwrite/pull/9237)
* Delete collection before Appwrite's attributes in [9256](https://github.com/appwrite/appwrite/pull/9256)
* Feat batch usage dump in [9255](https://github.com/appwrite/appwrite/pull/9255)
* Fix cloud tests in [9261](https://github.com/appwrite/appwrite/pull/9261)
* Usage: Databases reads writes in [9260](https://github.com/appwrite/appwrite/pull/9260)
* Update: Latest sdk specs in [9274](https://github.com/appwrite/appwrite/pull/9274)
* Revert "Feat batch usage dump" in [9276](https://github.com/appwrite/appwrite/pull/9276)
* feat: add fast2SMS adapter in [9263](https://github.com/appwrite/appwrite/pull/9263)
* Update Sdk Generator dependency in [9280](https://github.com/appwrite/appwrite/pull/9280)
* Transformed at addition in [9281](https://github.com/appwrite/appwrite/pull/9281)
* Docs: clarify update endpoints only work on draft messages in [9236](https://github.com/appwrite/appwrite/pull/9236)
* Update sdk generator dependency in [9282](https://github.com/appwrite/appwrite/pull/9282)
* Revert "Transformed at addition" in [9284](https://github.com/appwrite/appwrite/pull/9284)
* replaced init for cloud link in [9285](https://github.com/appwrite/appwrite/pull/9285)
* Add transformed at in [9289](https://github.com/appwrite/appwrite/pull/9289)
* Make migrations use Dynamic keys for destination in [9291](https://github.com/appwrite/appwrite/pull/9291)
* Make sessions limit tests assert eventually in [9298](https://github.com/appwrite/appwrite/pull/9298)
* Chore update database in [9306](https://github.com/appwrite/appwrite/pull/9306)
* feat: add AMQP queues in [9287](https://github.com/appwrite/appwrite/pull/9287)
* fix(test): use assertEventually instead of while(true) in [9308](https://github.com/appwrite/appwrite/pull/9308)
* fix(certificate worker): events are published without queue name in [9309](https://github.com/appwrite/appwrite/pull/9309)
* chore: update utopia-php/queue to 0.8.1 in [9311](https://github.com/appwrite/appwrite/pull/9311)
* chore: update utopia-php/queue to 0.8.2 in [9312](https://github.com/appwrite/appwrite/pull/9312)
* fix(schedule-tasks): revert back to direct pool usage in [9313](https://github.com/appwrite/appwrite/pull/9313)
* feat: custom app schemes in [9262](https://github.com/appwrite/appwrite/pull/9262)
* Revert "feat: custom app schemes" in [9319](https://github.com/appwrite/appwrite/pull/9319)
* Restore "feat: custom app schemes"" in [9320](https://github.com/appwrite/appwrite/pull/9320)
* Revert "Restore "feat: custom app schemes""" in [9323](https://github.com/appwrite/appwrite/pull/9323)
* chore: update dependencies in [9330](https://github.com/appwrite/appwrite/pull/9330)
* Feat: logs DB in [9272](https://github.com/appwrite/appwrite/pull/9272)
* Catch invalid index in [9329](https://github.com/appwrite/appwrite/pull/9329)
* Fix: missing call for image transformations counting in [9342](https://github.com/appwrite/appwrite/pull/9342)
* Fix drop abuse on shared table project delete in [9346](https://github.com/appwrite/appwrite/pull/9346)
* Only run all table mode tests on db update in [9338](https://github.com/appwrite/appwrite/pull/9338)
* Fix: missing periodic metric in [9350](https://github.com/appwrite/appwrite/pull/9350)
* feat(builds): check if function is blocked before building in [9332](https://github.com/appwrite/appwrite/pull/9332)
* feat: batch create audit logs in [9347](https://github.com/appwrite/appwrite/pull/9347)
* Chore: Update migrations in [9355](https://github.com/appwrite/appwrite/pull/9355)
* Fix: metric time was not being written to DB in [9354](https://github.com/appwrite/appwrite/pull/9354)
* Fix patch index validation in [9356](https://github.com/appwrite/appwrite/pull/9356)
* Fix image trnasformation metrics in [9370](https://github.com/appwrite/appwrite/pull/9370)
* Use batch delete in worker in [9375](https://github.com/appwrite/appwrite/pull/9375)
* Fix Model Platform is missing response key: store in [9361](https://github.com/appwrite/appwrite/pull/9361)
* Feat key segmented usage in [9336](https://github.com/appwrite/appwrite/pull/9336)
* Feat messaging metrics in [9353](https://github.com/appwrite/appwrite/pull/9353)
* Fix removed audits for shared v2 in [9388](https://github.com/appwrite/appwrite/pull/9388)
* chore: bump utopia-php/image to 0.8.0 in [9390](https://github.com/appwrite/appwrite/pull/9390)
* Fix outdated CLI commands in documentation in [9122](https://github.com/appwrite/appwrite/pull/9122)
* disable logs display in [9398](https://github.com/appwrite/appwrite/pull/9398)
* Log batches per project in [9403](https://github.com/appwrite/appwrite/pull/9403)
* Batch per project in [9410](https://github.com/appwrite/appwrite/pull/9410)
* Fix: stats resources only queue projects accessed in last 3 hours in [9411](https://github.com/appwrite/appwrite/pull/9411)
* Track options requests in [9397](https://github.com/appwrite/appwrite/pull/9397)
* chore: bump docker-base in [9406](https://github.com/appwrite/appwrite/pull/9406)
* refactor: migrate Realtime::send calls to queueForRealtime in [9325](https://github.com/appwrite/appwrite/pull/9325)
* Revert "Fix: stats resources only queue projects accessed in last 3 hours" in [9424](https://github.com/appwrite/appwrite/pull/9424)
* Remove usage and usage dump in favor of stats-usage and stats-usage-dump in [9339](https://github.com/appwrite/appwrite/pull/9339)
* Fix: disable dual writing in [9429](https://github.com/appwrite/appwrite/pull/9429)
* Disable transformedAt update for console users in [9425](https://github.com/appwrite/appwrite/pull/9425)
* chore: add image transformation stats to usage endpoint in [9393](https://github.com/appwrite/appwrite/pull/9393)
* chore: added timeout to deployment builds in tests in [9426](https://github.com/appwrite/appwrite/pull/9426)
* fix: model for image transformations in usage project in [9442](https://github.com/appwrite/appwrite/pull/9442)
* Feat: calculate database storage in stats-resources in [9443](https://github.com/appwrite/appwrite/pull/9443)
* Activities batch writes in [9438](https://github.com/appwrite/appwrite/pull/9438)
* chore: bump cache 0.12.x in [9412](https://github.com/appwrite/appwrite/pull/9412)
* chore: queue console project for maintenance delete in [9479](https://github.com/appwrite/appwrite/pull/9479)
* chore: added logsdb for deletes worker in [9462](https://github.com/appwrite/appwrite/pull/9462)
* Feat: calculate and log time taken for each project in [9491](https://github.com/appwrite/appwrite/pull/9491)
* chore: update initializing dbForLogs in [9494](https://github.com/appwrite/appwrite/pull/9494)
* Feat bulk audit delete in [9487](https://github.com/appwrite/appwrite/pull/9487)
* Prepare 1.6.2 release in [9499](https://github.com/appwrite/appwrite/pull/9499)
* Regenerate specs in [9497](https://github.com/appwrite/appwrite/pull/9497)
* Regenerate examples in [9498](https://github.com/appwrite/appwrite/pull/9498)
* chore: bump sdk in [9414](https://github.com/appwrite/appwrite/pull/9414)
* update queue to 0.9.* in [9505](https://github.com/appwrite/appwrite/pull/9505)
* Feat improve delete queries in [9507](https://github.com/appwrite/appwrite/pull/9507)
* Feat: Add rule attributes in [9508](https://github.com/appwrite/appwrite/pull/9508)
* Sync main into 1.6.x in [9496](https://github.com/appwrite/appwrite/pull/9496)
* Bump console to version 5.2.53 in [9495](https://github.com/appwrite/appwrite/pull/9495)
* Prepare 1.6.1 release in [9294](https://github.com/appwrite/appwrite/pull/9294)
* Improve delete ordering in [9512](https://github.com/appwrite/appwrite/pull/9512)
* Cleanups in [9511](https://github.com/appwrite/appwrite/pull/9511)
* Feat dynamic regions in [9408](https://github.com/appwrite/appwrite/pull/9408)
* Feat env vars to system lib in [9515](https://github.com/appwrite/appwrite/pull/9515)
* Feat: domains count in [9514](https://github.com/appwrite/appwrite/pull/9514)
* Migration read from db in [9529](https://github.com/appwrite/appwrite/pull/9529)
* feat: add pool telemetry in [9530](https://github.com/appwrite/appwrite/pull/9530)
* Disable PDO persistence since we manage our own pool in [9526](https://github.com/appwrite/appwrite/pull/9526)
* chore: set min operations to 1 for reads and writes in [9536](https://github.com/appwrite/appwrite/pull/9536)
* Remove default region in [9430](https://github.com/appwrite/appwrite/pull/9430)
* Use cursor pagination with bigger limit for maintenance project loop in [9546](https://github.com/appwrite/appwrite/pull/9546)
* chore: stop tests on failure in [9525](https://github.com/appwrite/appwrite/pull/9525)
* chore: only update total count for privileged users in [9554](https://github.com/appwrite/appwrite/pull/9554)
* refactor: initialization of audit retention in [9563](https://github.com/appwrite/appwrite/pull/9563)
* Delete worker queries fixes in [9523](https://github.com/appwrite/appwrite/pull/9523)
* Bump database 0.62.x in [9568](https://github.com/appwrite/appwrite/pull/9568)
* Fix: schedules region filtering in [9577](https://github.com/appwrite/appwrite/pull/9577)
* Deletes worker fix selects for pagination in [9578](https://github.com/appwrite/appwrite/pull/9578)
* Add $permissions for delete documents selects in [9579](https://github.com/appwrite/appwrite/pull/9579)
* chore(audits): return queue pre-fetch results in [9533](https://github.com/appwrite/appwrite/pull/9533)
* Revert "chore(audits): return queue pre-fetch results" in [9586](https://github.com/appwrite/appwrite/pull/9586)
* Feat multi tenant insert in [9573](https://github.com/appwrite/appwrite/pull/9573)
* Add order by for cursor in [9588](https://github.com/appwrite/appwrite/pull/9588)
* Feat update fetch in [9592](https://github.com/appwrite/appwrite/pull/9592)
* Fix tenant casting in [9598](https://github.com/appwrite/appwrite/pull/9598)
* Feat update ws in [9602](https://github.com/appwrite/appwrite/pull/9602)
* Update database in [9603](https://github.com/appwrite/appwrite/pull/9603)
* Fix: image transformation cache in [9608](https://github.com/appwrite/appwrite/pull/9608)
* Remove audit payload in [9610](https://github.com/appwrite/appwrite/pull/9610)
* Sample rate from DSN in [9559](https://github.com/appwrite/appwrite/pull/9559)
* Restrict role change for sole org owner in [9615](https://github.com/appwrite/appwrite/pull/9615)
* chore: update php image to 0.8.1 in [9616](https://github.com/appwrite/appwrite/pull/9616)
* feat: refactor executor setup in [9420](https://github.com/appwrite/appwrite/pull/9420)
* chore: update gitpod.yml config in [9561](https://github.com/appwrite/appwrite/pull/9561)
* chore: update dependencies in [9625](https://github.com/appwrite/appwrite/pull/9625)
* Update migrations lib in [9628](https://github.com/appwrite/appwrite/pull/9628)
* feat: cache telemetry in [9624](https://github.com/appwrite/appwrite/pull/9624)
* Bump console to version 5.2.56 in [9631](https://github.com/appwrite/appwrite/pull/9631)
* Multi region support in [8667](https://github.com/appwrite/appwrite/pull/8667)
* Revert "Multi region support" in [9632](https://github.com/appwrite/appwrite/pull/9632)
* Revert "Revert "Multi region support"" in [9636](https://github.com/appwrite/appwrite/pull/9636)
* Fix tasks in [9644](https://github.com/appwrite/appwrite/pull/9644)
* chore: updated the migration version to 8.6 in [9646](https://github.com/appwrite/appwrite/pull/9646)
* Fix: merge the working of StatsUsage and StatsUsageDump in [9585](https://github.com/appwrite/appwrite/pull/9585)
* Update database in [9643](https://github.com/appwrite/appwrite/pull/9643)
* chore: fix error logging for CLI tasks in [9651](https://github.com/appwrite/appwrite/pull/9651)
* fix: usage test assertion in [9653](https://github.com/appwrite/appwrite/pull/9653)
* Fix keys in [9656](https://github.com/appwrite/appwrite/pull/9656)
* Feat: multi tenant dual writing in [9583](https://github.com/appwrite/appwrite/pull/9583)
* Fix/throwing 400 for null order attributes in [9657](https://github.com/appwrite/appwrite/pull/9657)
* feat: sdk group attribute in [9596](https://github.com/appwrite/appwrite/pull/9596)
* Add configurable function and build size in [9648](https://github.com/appwrite/appwrite/pull/9648)
* feat: update API endpoint in the code examples in [8933](https://github.com/appwrite/appwrite/pull/8933)
* chore: abstract token secret hiding to response model in [9574](https://github.com/appwrite/appwrite/pull/9574)
* chore: update sdks in [9655](https://github.com/appwrite/appwrite/pull/9655)
* feat: allow non-critical events to ignore exceptions when enqueuing the event in [9680](https://github.com/appwrite/appwrite/pull/9680)
* Revert "Add configurable function and build size" in [9681](https://github.com/appwrite/appwrite/pull/9681)
* core: introduce endpoint.docs in specs in [9685](https://github.com/appwrite/appwrite/pull/9685)
* fix: remove content-type header from get request specs in [9666](https://github.com/appwrite/appwrite/pull/9666)
* chore: update flutter sdk in [9691](https://github.com/appwrite/appwrite/pull/9691)
# Version 1.6.1
## What's Changed
+5 -5
View File
@@ -415,8 +415,8 @@ In addition, you will also need to add some logic to the `reduce()` method of th
```php
case $document->getCollection() === 'buckets':
$files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES)));
$storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE)));
$files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES)));
$storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE)));
if (!empty($files['value'])) {
$metrics[] = [
@@ -463,9 +463,9 @@ $queueForStatsUsage
->addMetric(METRIC_BUILDS, 1)
->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0))
->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000)
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1)
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0))
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000)
->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS), 1)
->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0))
->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000)
->setProject($project)
->trigger();
```
-1
View File
@@ -89,7 +89,6 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/worker-migrations && \
chmod +x /usr/local/bin/worker-webhooks && \
chmod +x /usr/local/bin/worker-stats-usage && \
chmod +x /usr/local/bin/worker-stats-usage-dump && \
chmod +x /usr/local/bin/stats-resources && \
chmod +x /usr/local/bin/worker-stats-resources
+3 -3
View File
@@ -72,7 +72,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.6.2
appwrite/appwrite:1.7.4
```
### Windows
@@ -84,7 +84,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^
appwrite/appwrite:1.6.2
appwrite/appwrite:1.7.4
```
#### PowerShell
@@ -94,7 +94,7 @@ docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock `
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
--entrypoint="install" `
appwrite/appwrite:1.6.2
appwrite/appwrite:1.7.4
```
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
+4 -3
View File
@@ -1,4 +1,5 @@
> [Get started with Appwrite](https://apwr.dev/appcloud)
> [Join the Init kick off event 19th of May: The future of Appwrite with Founder & CEO Eldad Fux](https://www.youtube.com/watch?v=1g8tuogsp7A)
<br />
<p align="center">
@@ -77,7 +78,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.6.2
appwrite/appwrite:1.7.4
```
### Windows
@@ -89,7 +90,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^
appwrite/appwrite:1.6.2
appwrite/appwrite:1.7.4
```
#### PowerShell
@@ -99,7 +100,7 @@ docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock `
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
--entrypoint="install" `
appwrite/appwrite:1.6.2
appwrite/appwrite:1.7.4
```
Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation.
+57 -42
View File
@@ -10,11 +10,15 @@ use Appwrite\Event\StatsUsage;
use Appwrite\Platform\Appwrite;
use Appwrite\Runtimes\Runtimes;
use Executor\Executor;
use Swoole\Runtime;
use Swoole\Timer;
use Utopia\Cache\Adapter\Pool as CachePool;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\CLI;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Adapter\Pool as DatabasePool;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
@@ -22,9 +26,13 @@ use Utopia\DSN\DSN;
use Utopia\Logger\Log;
use Utopia\Platform\Service;
use Utopia\Pools\Group;
use Utopia\Queue\Broker\Pool as BrokerPool;
use Utopia\Queue\Publisher;
use Utopia\Registry\Registry;
use Utopia\System\System;
use Utopia\Telemetry\Adapter\None as NoTelemetry;
use function Swoole\Coroutine\run;
// overwriting runtimes to be architecture agnostic for CLI
Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
@@ -41,10 +49,7 @@ CLI::setResource('cache', function ($pools) {
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
->pop()
->getResource();
$adapters[] = new CachePool($pools->get($value));
}
return new Cache(new Sharding($adapters));
@@ -64,12 +69,8 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) {
$attempts++;
try {
// Prepare database connection
$dbAdapter = $pools
->get('console')
->pop()
->getResource();
$dbForPlatform = new Database($dbAdapter, $cache);
$adapter = new DatabasePool($pools->get('console'));
$dbForPlatform = new Database($adapter, $cache);
$dbForPlatform
->setNamespace('_console')
@@ -87,7 +88,6 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) {
$ready = true;
} catch (\Throwable $err) {
Console::warning($err->getMessage());
$pools->get('console')->reclaim();
sleep($sleep);
}
} while ($attempts < $maxAttempts && !$ready);
@@ -125,37 +125,33 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
return $database;
}
$dbAdapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$adapter = new DatabasePool($pools->get($dsn->getHost()));
$database = new Database($adapter, $cache);
$databases[$dsn->getHost()] = $database;
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
$database
@@ -168,21 +164,15 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
$database = null;
return function (?Document $project = null) use ($pools, $cache, $database) {
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
$database->setTenant($project->getSequence());
return $database;
}
$dbAdapter = $pools
->get('logs')
->pop()
->getResource();
$database = new Database(
$dbAdapter,
$cache
);
$adapter = new DatabasePool($pools->get('logs'));
$database = new Database($adapter, $cache);
$database
->setSharedTables(true)
@@ -192,21 +182,21 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
// set tenant
if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
$database->setTenant($project->getSequence());
}
return $database;
};
}, ['pools', 'cache']);
CLI::setResource('queueForStatsUsage', function (Connection $publisher) {
CLI::setResource('queueForStatsUsage', function (Publisher $publisher) {
return new StatsUsage($publisher);
}, ['publisher']);
CLI::setResource('queueForStatsResources', function (Publisher $publisher) {
return new StatsResources($publisher);
}, ['publisher']);
CLI::setResource('publisher', function (Group $pools) {
return $pools->get('publisher')->pop()->getResource();
return new BrokerPool(publisher: $pools->get('publisher'));
}, ['pools']);
CLI::setResource('queueForFunctions', function (Publisher $publisher) {
return new Func($publisher);
@@ -219,6 +209,13 @@ CLI::setResource('queueForCertificates', function (Publisher $publisher) {
}, ['publisher']);
CLI::setResource('logError', function (Registry $register) {
return function (Throwable $error, string $namespace, string $action) use ($register) {
Console::error('[Error] Timestamp: ' . date('c', time()));
Console::error('[Error] Type: ' . get_class($error));
Console::error('[Error] Message: ' . $error->getMessage());
Console::error('[Error] File: ' . $error->getFile());
Console::error('[Error] Line: ' . $error->getLine());
Console::error('[Error] Trace: ' . $error->getTraceAsString());
$logger = $register->get('logger');
if ($logger) {
@@ -237,6 +234,7 @@ CLI::setResource('logError', function (Registry $register) {
$log->addExtra('file', $error->getFile());
$log->addExtra('line', $error->getLine());
$log->addExtra('trace', $error->getTraceAsString());
$log->addExtra('detailedTrace', $error->getTrace());
$log->setAction($action);
@@ -250,24 +248,41 @@ CLI::setResource('logError', function (Registry $register) {
Console::error('Error pushing log: ' . $th->getMessage());
}
}
Console::warning("Failed: {$error->getMessage()}");
Console::warning($error->getTraceAsString());
};
}, ['register']);
CLI::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
$platform = new Appwrite();
$platform->init(Service::TYPE_TASK);
CLI::setResource('telemetry', fn () => new NoTelemetry());
$platform = new Appwrite();
$args = $platform->getEnv('argv');
if (!isset($args[0])) {
Console::error('Missing task name');
Console::exit(1);
}
\array_shift($args);
$taskName = $args[0];
$platform->init(Service::TYPE_TASK);
$cli = $platform->getCli();
$cli
->error()
->inject('error')
->action(function (Throwable $error) {
Console::error($error->getMessage());
->inject('logError')
->action(function (Throwable $error, callable $logError) use ($taskName) {
call_user_func_array($logError, [
$error,
'Task',
$taskName,
]);
Timer::clearAll();
});
$cli->run();
$cli->shutdown()->action(fn () => Timer::clearAll());
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
run($cli->run(...));
+36
View File
@@ -1101,6 +1101,28 @@ return [
'array' => false,
'filters' => ['json', 'encrypt'],
],
[
'$id' => ID::custom('scopes'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => true,
'filters' => [],
],
[
'$id' => ID::custom('expire'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'required' => false,
'signed' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
],
'indexes' => [
[
@@ -2359,6 +2381,20 @@ return [
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_expired'),
'type' => Database::INDEX_KEY,
'attributes' => ['expired'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_session_internal_id'),
'type' => Database::INDEX_KEY,
'attributes' => ['sessionInternalId'],
'lengths' => [],
'orders' => [],
],
],
],
+54 -23
View File
@@ -225,7 +225,7 @@ return [
'$id' => ID::custom('templates'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 1000000, // TODO make sure size fits
'size' => 1_000_000, // TODO make sure size fits
'signed' => true,
'required' => false,
'default' => [],
@@ -367,7 +367,21 @@ return [
'attributes' => ['pingedAt'],
'lengths' => [],
'orders' => [],
]
],
[
'$id' => ID::custom('_key_database'),
'type' => Database::INDEX_KEY,
'attributes' => ['database'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_region_accessed_at'),
'type' => Database::INDEX_KEY,
'attributes' => ['region', 'accessedAt'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -491,6 +505,20 @@ return [
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_project_id_region'),
'type' => Database::INDEX_KEY,
'attributes' => ['projectId', 'region'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_region_rt_active'),
'type' => Database::INDEX_KEY,
'attributes' => ['region', 'resourceType', 'active'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -782,17 +810,6 @@ return [
'array' => true,
'filters' => [],
],
[
'$id' => ID::custom('search'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
@@ -809,13 +826,6 @@ return [
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_search'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['search'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -1148,7 +1158,7 @@ return [
'format' => '',
'size' => 32,
'signed' => true,
'required' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
@@ -1407,6 +1417,13 @@ return [
'lengths' => [16],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_piid_riid_rt'),
'type' => Database::INDEX_KEY,
'attributes' => ['projectInternalId', 'deploymentInternalId', 'deploymentResourceType'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -1702,7 +1719,14 @@ return [
'attributes' => ['resourceType'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
]
],
[
'$id' => ID::custom('_key_piid_riid_rt'),
'type' => Database::INDEX_KEY,
'attributes' => ['projectInternalId', 'resourceInternalId', 'resourceType'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -1850,6 +1874,13 @@ return [
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_piid_prid_rt'),
'type' => Database::INDEX_KEY,
'attributes' => ['projectInternalId', 'providerRepositoryId'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -1859,5 +1890,5 @@ return [
'name' => 'vcsCommentLocks',
'attributes' => [],
'indexes' => []
]
],
];
+74 -39
View File
@@ -1029,7 +1029,7 @@ return [
'$id' => ID::custom('fallbackFile'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
@@ -1205,7 +1205,7 @@ return [
'$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks
'type' => Database::VAR_STRING,
'format' => '',
'size' => 128,
'size' => 16,
'signed' => true,
'required' => false,
'default' => '',
@@ -1361,7 +1361,7 @@ return [
'$id' => ID::custom('sourcePath'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
@@ -1372,7 +1372,7 @@ return [
'$id' => ID::custom('type'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 32,
'size' => 2048,
'signed' => true,
'required' => true,
'default' => null,
@@ -1554,8 +1554,8 @@ return [
'$id' => ID::custom('sourceSize'),
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'size' => 8,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
@@ -1594,17 +1594,6 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('search'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('activate'),
'type' => Database::VAR_BOOLEAN,
@@ -1639,7 +1628,7 @@ return [
'filters' => [],
],
[
'$id' => ID::custom('buildStartAt'),
'$id' => ID::custom('buildStartedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
@@ -1650,7 +1639,7 @@ return [
'filters' => ['datetime'],
],
[
'$id' => ID::custom('buildEndAt'),
'$id' => ID::custom('buildEndedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
@@ -1665,7 +1654,7 @@ return [
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
@@ -1675,8 +1664,8 @@ return [
'$id' => ID::custom('buildSize'),
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'size' => 8,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
@@ -1686,8 +1675,8 @@ return [
'$id' => ID::custom('totalSize'),
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'size' => 8,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
@@ -1699,7 +1688,7 @@ return [
'format' => '',
'size' => 16,
'signed' => true,
'required' => true,
'required' => false,
'default' => 'waiting',
'array' => false,
'filters' => [],
@@ -1708,7 +1697,7 @@ return [
'$id' => ID::custom('buildPath'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'size' => 16384,
'signed' => true,
'required' => false,
'default' => '',
@@ -1730,7 +1719,7 @@ return [
'$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks
'type' => Database::VAR_STRING,
'format' => '',
'size' => 128,
'size' => 16,
'signed' => true,
'required' => false,
'default' => '',
@@ -1741,7 +1730,7 @@ return [
'$id' => ID::custom('fallbackFile'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
@@ -1764,13 +1753,6 @@ return [
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_search'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['search'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_sourceSize'),
'type' => Database::INDEX_KEY,
@@ -1812,13 +1794,28 @@ return [
'attributes' => ['type'],
'lengths' => [32],
'orders' => [Database::ORDER_ASC],
], [
],
[
'$id' => ID::custom('_key_status'),
'type' => Database::INDEX_KEY,
'attributes' => ['status'],
'lengths' => [16],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_resourceId_resourceType'),
'type' => Database::INDEX_KEY,
'attributes' => ['resourceId', 'resourceType'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_resource_internal_id'),
'type' => Database::INDEX_KEY,
'attributes' => ['resourceInternalId'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -2083,6 +2080,13 @@ return [
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_function_internal_id'),
'type' => Database::INDEX_KEY,
'attributes' => ['resourceInternalId'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -2212,6 +2216,13 @@ return [
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_resource_internal_id_resource_type'),
'type' => Database::INDEX_KEY,
'attributes' => ['resourceInternalId', 'resourceType'],
'lengths' => [],
'orders' => [],
],
],
],
@@ -2461,8 +2472,19 @@ return [
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
]
'filters' => ['datetime'],
],
[
'$id' => ID::custom('accessedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
],
'indexes' => [
[
@@ -2472,7 +2494,20 @@ return [
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => '_key_accessedAt',
'type' => Database::INDEX_KEY,
'attributes' => ['accessedAt'],
'lengths' => [],
'orders' => [],
],
[
'$id' => '_key_resourceInternalId_resourceType',
'type' => Database::INDEX_KEY,
'attributes' => ['resourceInternalId', 'resourceType'],
'lengths' => [],
'orders' => [],
],
],
],
];
+1 -1
View File
@@ -11,7 +11,7 @@ use Utopia\System\System;
$console = [
'$id' => ID::custom('console'),
'$internalId' => ID::custom('console'),
'$sequence' => ID::custom('console'),
'name' => 'Appwrite',
'$collection' => ID::custom('projects'),
'description' => 'Appwrite core engine',
+11 -1
View File
@@ -81,7 +81,7 @@ return [
],
Exception::GENERAL_ROUTE_NOT_FOUND => [
'name' => Exception::GENERAL_ROUTE_NOT_FOUND,
'description' => 'The requested route was not found. Please refer to the API docs and try again.',
'description' => 'Route not found. Please ensure the endpoint is configured correctly and that the API route is valid for this SDK version. Refer to the API docs for more details.',
'code' => 404,
],
Exception::GENERAL_CURSOR_NOT_FOUND => [
@@ -499,6 +499,11 @@ return [
'description' => 'The requested file token has expired.',
'code' => 401,
],
Exception::TOKEN_RESOURCE_TYPE_INVALID => [
'name' => Exception::TOKEN_RESOURCE_TYPE_INVALID,
'description' => 'The resource type for the token is invalid.',
'code' => 400,
],
/** VCS */
Exception::INSTALLATION_NOT_FOUND => [
@@ -651,6 +656,11 @@ return [
'description' => 'Database timed out. Try adjusting your queries or adding an index.',
'code' => 408
],
Exception::DATABASE_QUERY_ORDER_NULL => [
'name' => Exception::DATABASE_QUERY_ORDER_NULL,
'description' => 'The order attribute had a null value. Cursor pagination requires all documents order attribute values are non-null.',
'code' => 400,
],
/** Collections */
Exception::COLLECTION_NOT_FOUND => [
+19 -2
View File
@@ -253,13 +253,30 @@ return [
'adapters' => [
'static' => [
'key' => 'static',
'buildCommand' => 'flutter build web',
'installCommand' => '',
'buildCommand' => 'flutter build web --release -t lib/main.dart',
'installCommand' => 'flutter pub get',
'outputDirectory' => './build/web',
'startCommand' => 'bash helpers/server.sh',
],
],
],
'react-native' => [
'key' => 'react-native',
'name' => 'React Native',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
'static' => [
'key' => 'static',
'buildCommand' => 'npm run build',
'installCommand' => 'npm install',
'outputDirectory' => './dist',
'startCommand' => 'bash helpers/server.sh',
'fallbackFile' => 'index.html'
]
]
],
'vite' => [
'key' => 'vite',
'name' => 'Vite',
@@ -79,7 +79,7 @@
<style>
a.button {
display: inline-block;
background: #fd366e;
background: {{accentColor}};
color: #ffffff;
border-radius: 8px;
height: 48px;
@@ -88,7 +88,7 @@
cursor: pointer;
text-align: center;
text-decoration: none;
border-color: #fd366e;
border-color: {{accentColor}};
border-style: solid;
border-width: 1px;
margin-right: 24px;
@@ -126,7 +126,7 @@
<td>
<img
height="32px"
src="https://cloud.appwrite.io/images/mails/logo.png"
src="{{logoUrl}}"
/>
</td>
</tr>
@@ -164,7 +164,7 @@
<tr>
<td style="padding-left: 4px; padding-right: 4px">
<a
href="https://twitter.com/appwrite"
href="{{twitterUrl}}"
class="social-icon"
title="Twitter"
>
@@ -173,7 +173,7 @@
</td>
<td style="padding-left: 4px; padding-right: 4px">
<a
href="https://appwrite.io/discord"
href="{{discordUrl}}"
class="social-icon"
>
<img src="https://cloud.appwrite.io/images/mails/discord.png" height="24" width="24" />
@@ -181,7 +181,7 @@
</td>
<td style="padding-left: 4px; padding-right: 4px">
<a
href="https://github.com/appwrite/appwrite"
href="{{githubUrl}}"
class="social-icon"
>
<img src="https://cloud.appwrite.io/images/mails/github.png" height="24" width="24" />
@@ -191,11 +191,11 @@
</table>
<table style="width: auto; margin: 0 auto; margin-top: 60px">
<tr>
<td><a href="https://appwrite.io/terms">Terms</a></td>
<td><a href="{{termsUrl}}">Terms</a></td>
<td style="color: #e8e9f0">
<div style="margin: 0 8px">|</div>
</td>
<td><a href="https://appwrite.io/privacy">Privacy</a></td>
<td><a href="{{privacyUrl}}">Privacy</a></td>
</tr>
</table>
<p style="text-align: center" align="center">
+59 -7
View File
@@ -11,6 +11,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Amazon',
],
'apple' => [
'name' => 'Apple',
@@ -21,6 +22,7 @@ return [
'form' => 'apple.phtml', // Preparation for adding ability to customized OAuth UI forms, currently handled hardcoded.
'beta' => true,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Apple',
],
'auth0' => [
'name' => 'Auth0',
@@ -31,6 +33,7 @@ return [
'form' => 'auth0.phtml',
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Auth0',
],
'authentik' => [
'name' => 'Authentik',
@@ -41,6 +44,7 @@ return [
'form' => 'authentik.phtml',
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Authentik',
],
'autodesk' => [
'name' => 'Autodesk',
@@ -51,6 +55,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Autodesk',
],
'bitbucket' => [
'name' => 'BitBucket',
@@ -61,6 +66,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Bitbucket',
],
'bitly' => [
'name' => 'Bitly',
@@ -70,7 +76,8 @@ return [
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Bitly',
],
'box' => [
'name' => 'Box',
@@ -80,7 +87,8 @@ return [
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Box',
],
'dailymotion' => [
'name' => 'Dailymotion',
@@ -90,7 +98,8 @@ return [
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Dailymotion',
],
'discord' => [
'name' => 'Discord',
@@ -101,6 +110,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Discord',
],
'disqus' => [
'name' => 'Disqus',
@@ -111,6 +121,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Disqus',
],
'dropbox' => [
'name' => 'Dropbox',
@@ -121,6 +132,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Dropbox',
],
'etsy' => [
'name' => 'Etsy',
@@ -131,6 +143,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Etsy',
],
'facebook' => [
'name' => 'Facebook',
@@ -141,6 +154,18 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Facebook',
],
'figma' => [
'name' => 'Figma',
'developers' => 'https://www.figma.com/developers/api#oauth2',
'icon' => 'icon-figma',
'enabled' => true,
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Figma',
],
'github' => [
'name' => 'GitHub',
@@ -151,6 +176,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Github',
],
'gitlab' => [
'name' => 'GitLab',
@@ -161,6 +187,7 @@ return [
'form' => 'gitlab.phtml',
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Gitlab',
],
'google' => [
'name' => 'Google',
@@ -171,6 +198,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Google',
],
'linkedin' => [
'name' => 'LinkedIn',
@@ -181,6 +209,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Linkedin',
],
'microsoft' => [
'name' => 'Microsoft',
@@ -191,6 +220,7 @@ return [
'form' => 'microsoft.phtml',
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Microsoft',
],
'notion' => [
'name' => 'Notion',
@@ -201,6 +231,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Notion',
],
'oidc' => [
'name' => 'OpenID Connect',
@@ -211,6 +242,7 @@ return [
'form' => 'oidc.phtml',
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Oidc',
],
'okta' => [
'name' => 'Okta',
@@ -221,6 +253,7 @@ return [
'form' => 'okta.phtml',
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Okta',
],
'paypal' => [
'name' => 'PayPal',
@@ -230,7 +263,8 @@ return [
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Paypal',
],
'paypalSandbox' => [
'name' => 'PayPal Sandbox',
@@ -240,7 +274,8 @@ return [
'sandbox' => true,
'form' => false,
'beta' => false,
'mock' => false
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Paypal',
],
'podio' => [
'name' => 'Podio',
@@ -251,6 +286,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Podio',
],
'salesforce' => [
'name' => 'Salesforce',
@@ -261,6 +297,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Salesforce',
],
'slack' => [
'name' => 'Slack',
@@ -271,6 +308,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Slack',
],
'spotify' => [
'name' => 'Spotify',
@@ -281,6 +319,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Spotify',
],
'stripe' => [
'name' => 'Stripe',
@@ -290,7 +329,8 @@ return [
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Stripe',
],
'tradeshift' => [
'name' => 'Tradeshift',
@@ -301,6 +341,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Tradeshift',
],
'tradeshiftBox' => [
'name' => 'Tradeshift Sandbox',
@@ -311,6 +352,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Tradeshift',
],
'twitch' => [
'name' => 'Twitch',
@@ -321,6 +363,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Twitch',
],
'wordpress' => [
'name' => 'WordPress',
@@ -330,7 +373,8 @@ return [
'sandbox' => false,
'form' => false,
'beta' => false,
'mock' => false
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Wordpress',
],
'yahoo' => [
'name' => 'Yahoo',
@@ -341,6 +385,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Yahoo',
],
'yammer' => [
'name' => 'Yammer',
@@ -351,6 +396,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Yammer',
],
'yandex' => [
'name' => 'Yandex',
@@ -361,6 +407,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Yandex',
],
'zoho' => [
'name' => 'Zoho',
@@ -371,6 +418,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Zoho',
],
'zoom' => [
'name' => 'Zoom',
@@ -381,6 +429,7 @@ return [
'form' => false,
'beta' => false,
'mock' => false,
'class' => 'Appwrite\\Auth\\OAuth2\\Zoom',
],
// 'instagram' => [
// 'name' => 'Instagram',
@@ -389,6 +438,7 @@ return [
// 'enabled' => false,
// 'beta' => false,
// 'mock' => false,
// 'class' => 'Appwrite\\Auth\\OAuth2\\Instagram',
// ],
// 'twitter' => [
// 'name' => 'twitter',
@@ -397,6 +447,7 @@ return [
// 'enabled' => false,
// 'beta' => false,
// 'mock' => false,
// 'class' => 'Appwrite\\Auth\\OAuth2\\Twitter',
// ],
// Keep Last
@@ -409,5 +460,6 @@ return [
'form' => false,
'beta' => false,
'mock' => true,
'class' => 'Appwrite\\Auth\\OAuth2\\Mock',
],
];
+17 -17
View File
@@ -11,7 +11,7 @@ return [
[
'key' => 'web',
'name' => 'Web',
'version' => '17.0.1',
'version' => '18.1.0',
'url' => 'https://github.com/appwrite/sdk-for-web',
'package' => 'https://www.npmjs.com/package/appwrite',
'enabled' => true,
@@ -59,7 +59,7 @@ return [
[
'key' => 'flutter',
'name' => 'Flutter',
'version' => '15.0.0',
'version' => '16.1.0',
'url' => 'https://github.com/appwrite/sdk-for-flutter',
'package' => 'https://pub.dev/packages/appwrite',
'enabled' => true,
@@ -77,7 +77,7 @@ return [
[
'key' => 'apple',
'name' => 'Apple',
'version' => '9.0.0',
'version' => '10.1.0',
'url' => 'https://github.com/appwrite/sdk-for-apple',
'package' => 'https://github.com/appwrite/sdk-for-apple',
'enabled' => true,
@@ -112,7 +112,7 @@ return [
[
'key' => 'android',
'name' => 'Android',
'version' => '6.1.0',
'version' => '8.1.0',
'url' => 'https://github.com/appwrite/sdk-for-android',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
'enabled' => true,
@@ -134,7 +134,7 @@ return [
[
'key' => 'react-native',
'name' => 'React Native',
'version' => '0.7.1',
'version' => '0.9.1',
'url' => 'https://github.com/appwrite/sdk-for-react-native',
'package' => 'https://npmjs.com/package/react-native-appwrite',
'enabled' => true,
@@ -199,7 +199,7 @@ return [
[
'key' => 'web',
'name' => 'Console',
'version' => '1.2.1',
'version' => '1.7.0',
'url' => 'https://github.com/appwrite/sdk-for-console',
'package' => '',
'enabled' => true,
@@ -217,7 +217,7 @@ return [
[
'key' => 'cli',
'name' => 'Command Line',
'version' => '6.2.2',
'version' => '6.2.3',
'url' => 'https://github.com/appwrite/sdk-for-cli',
'package' => 'https://www.npmjs.com/package/appwrite-cli',
'enabled' => true,
@@ -245,7 +245,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '15.0.1',
'version' => '17.0.0',
'url' => 'https://github.com/appwrite/sdk-for-node',
'package' => 'https://www.npmjs.com/package/node-appwrite',
'enabled' => true,
@@ -263,7 +263,7 @@ return [
[
'key' => 'deno',
'name' => 'Deno',
'version' => '12.2.0',
'version' => '15.0.0',
'url' => 'https://github.com/appwrite/sdk-for-deno',
'package' => 'https://deno.land/x/appwrite',
'enabled' => true,
@@ -281,7 +281,7 @@ return [
[
'key' => 'php',
'name' => 'PHP',
'version' => '12.2.0',
'version' => '15.0.0',
'url' => 'https://github.com/appwrite/sdk-for-php',
'package' => 'https://packagist.org/packages/appwrite/appwrite',
'enabled' => true,
@@ -299,7 +299,7 @@ return [
[
'key' => 'python',
'name' => 'Python',
'version' => '9.0.2',
'version' => '11.0.0',
'url' => 'https://github.com/appwrite/sdk-for-python',
'package' => 'https://pypi.org/project/appwrite/',
'enabled' => true,
@@ -317,7 +317,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '12.2.0',
'version' => '16.0.0',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'package' => 'https://rubygems.org/gems/appwrite',
'enabled' => true,
@@ -335,7 +335,7 @@ return [
[
'key' => 'go',
'name' => 'Go',
'version' => '0.3.0',
'version' => '0.8.0',
'url' => 'https://github.com/appwrite/sdk-for-go',
'package' => 'https://github.com/appwrite/sdk-for-go',
'enabled' => true,
@@ -353,7 +353,7 @@ return [
[
'key' => 'dotnet',
'name' => '.NET',
'version' => '0.11.0',
'version' => '0.13.0',
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
'package' => 'https://www.nuget.org/packages/Appwrite',
'enabled' => true,
@@ -371,7 +371,7 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '14.0.0',
'version' => '16.0.0',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'package' => 'https://pub.dev/packages/dart_appwrite',
'enabled' => true,
@@ -389,7 +389,7 @@ return [
[
'key' => 'kotlin',
'name' => 'Kotlin',
'version' => '6.2.0',
'version' => '9.0.0',
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
'enabled' => true,
@@ -411,7 +411,7 @@ return [
[
'key' => 'swift',
'name' => 'Swift',
'version' => '8.0.0',
'version' => '10.0.0',
'url' => 'https://github.com/appwrite/sdk-for-swift',
'package' => 'https://github.com/appwrite/sdk-for-swift',
'enabled' => true,
-3
View File
@@ -65,9 +65,6 @@ return [
'tests' => false,
'optional' => true,
'icon' => '/images/services/databases.png',
'globalAttributes' => [
'databaseId'
]
],
'locale' => [
'key' => 'locale',
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
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
-1
View File
@@ -4,7 +4,6 @@ return [
// Accepted inputs files
"jpg" => "image/jpeg",
"jpeg" => "image/jpeg",
"gif" => "image/gif",
"png" => "image/png",
"heic" => "image/heic",
"webp" => "image/webp",
-1
View File
@@ -4,7 +4,6 @@ return [
// Accepted outputs files
"jpg" => "image/jpeg",
"jpeg" => "image/jpeg",
"gif" => "image/gif",
"png" => "image/png",
"webp" => "image/webp",
"heic" => "image/heic",
+243 -20
View File
@@ -106,6 +106,16 @@ const TEMPLATE_FRAMEWORKS = [
'outputDirectory' => './dist',
'fallbackFile' => 'index.html',
],
'REACT_NATIVE' => [
'key' => 'react-native',
'name' => 'React Native',
'installCommand' => 'npm install',
'buildCommand' => 'npm run build',
'buildRuntime' => 'node-22',
'adapter' => 'static',
'outputDirectory' => './dist',
'fallbackFile' => '+not-found.html',
],
'ANGULAR' => [
'key' => 'angular',
'name' => 'Angular',
@@ -183,13 +193,15 @@ return [
'variables' => []
],
[
'key' => 'lynx-starter',
'name' => 'Lynx Starter',
'tagline' => 'Sample application built with Lynx, a cross-platform framework focused on performance.',
'key' => 'playground-for-lynx',
'name' => 'Lynx playground',
'tagline' => 'A basic Lynx website without Appwrite SDK integration.',
// When we add Lynx with Appwrite SDK, use following tagline for it:
// 'tagline' => 'Sample application built with Lynx, a cross-platform framework focused on performance.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/lynx-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/lynx-starter-light.png',
'screenshotDark' => $url . '/images/sites/templates/playground-for-lynx-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-lynx-light.png',
'frameworks' => [
getFramework('LYNX', [
'providerRootDirectory' => './lynx/starter',
@@ -864,9 +876,8 @@ return [
'screenshotDark' => $url . '/images/sites/templates/starter-for-react-native-dark.png',
'screenshotLight' => $url . '/images/sites/templates/starter-for-react-native-light.png',
'frameworks' => [
getFramework('REACT', [
getFramework('REACT_NATIVE', [
'providerRootDirectory' => './',
'fallbackFile' => '+not-found.html',
]),
],
'vcsProvider' => 'github',
@@ -1108,15 +1119,14 @@ return [
'providerVersion' => '0.1.*',
'variables' => []
],
// TODO: Remove astro starter eventually, or add all frameworks's starters
[
'key' => 'astro-starter',
'name' => 'Astro starter',
'tagline' => 'Sample application built with Astro, a content-driven web framework.',
'key' => 'playground-for-astro',
'name' => 'Astro playground',
'tagline' => 'A basic Astro website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/astro-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/astro-starter-light.png',
'screenshotDark' => $url . '/images/sites/templates/playground-for-astro-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-astro-light.png',
'frameworks' => [
getFramework('ASTRO', [
'providerRootDirectory' => './astro/starter',
@@ -1125,17 +1135,17 @@ return [
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'remix-starter',
'name' => 'Remix starter',
'tagline' => 'Sample application built with Remix, a React meta-framework.',
'key' => 'playground-for-remix',
'name' => 'Remix playground',
'tagline' => 'A basic Remix website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/remix-starter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/remix-starter-light.png',
'screenshotDark' => $url . '/images/sites/templates/playground-for-remix-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-remix-light.png',
'frameworks' => [
getFramework('REMIX', [
'providerRootDirectory' => './remix/starter',
@@ -1144,7 +1154,220 @@ return [
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.2.*',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-nextjs',
'name' => 'Next.js playground',
'tagline' => 'A basic Next.js website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-nextjs-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-nextjs-light.png',
'frameworks' => [
getFramework('NEXTJS', [
'providerRootDirectory' => './nextjs/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-flutter',
'name' => 'Flutter playground',
'tagline' => 'A basic Flutter website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-flutter-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-flutter-light.png',
'frameworks' => [
getFramework('FLUTTER', [
'providerRootDirectory' => './flutter/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-vite',
'name' => 'Vite playground',
'tagline' => 'A basic Vite website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-vite-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-vite-light.png',
'frameworks' => [
getFramework('VITE', [
'providerRootDirectory' => './vite/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-angular',
'name' => 'Angular playground',
'tagline' => 'A basic Angular website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-angular-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-angular-light.png',
'frameworks' => [
getFramework('ANGULAR', [
'providerRootDirectory' => './angular/starter',
'outputDirectory' => './dist/starter/browser',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-analog',
'name' => 'Analog playground',
'tagline' => 'A basic Analog website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-analog-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-analog-light.png',
'frameworks' => [
getFramework('ANALOG', [
'providerRootDirectory' => './analog/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-svelte',
'name' => 'Svelte playground',
'tagline' => 'A basic Svelte website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-svelte-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-svelte-light.png',
'frameworks' => [
getFramework('SVELTEKIT', [
'providerRootDirectory' => './sveltekit/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-react',
'name' => 'React playground',
'tagline' => 'A basic React website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-react-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-react-light.png',
'frameworks' => [
getFramework('REACT', [
'outputDirectory' => './build',
'providerRootDirectory' => './react/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-vue',
'name' => 'Vue playground',
'tagline' => 'A basic Vue website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-vue-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-vue-light.png',
'frameworks' => [
getFramework('VUE', [
'providerRootDirectory' => './vue/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-nuxt',
'name' => 'Nuxt playground',
'tagline' => 'A basic Nuxt website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-nuxt-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-nuxt-light.png',
'frameworks' => [
getFramework('NUXT', [
'providerRootDirectory' => './nuxt/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'playground-for-react-native',
'name' => 'React Native playground',
'tagline' => 'A basic React Native website without Appwrite SDK integration.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/playground-for-react-native-dark.png',
'screenshotLight' => $url . '/images/sites/templates/playground-for-react-native-light.png',
'frameworks' => [
getFramework('REACT_NATIVE', [
'providerRootDirectory' => './react-native/starter',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => [],
],
[
'key' => 'gallery-for-lynx',
'name' => 'Lynx gallery',
'tagline' => 'A Lynx website showcasing gallery with smooth animations.',
'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
'useCases' => [UseCases::STARTER],
'screenshotDark' => $url . '/images/sites/templates/gallery-for-lynx-dark.png',
'screenshotLight' => $url . '/images/sites/templates/gallery-for-lynx-light.png',
'frameworks' => [
getFramework('LYNX', [
'providerRootDirectory' => './lynx/gallery',
]),
],
'vcsProvider' => 'github',
'providerRepositoryId' => 'templates-for-sites',
'providerOwner' => 'appwrite',
'providerVersion' => '0.3.*',
'variables' => []
],
];
+30 -3
View File
@@ -88,6 +88,15 @@ return [
'question' => 'Enter your Appwrite hostname',
'filter' => ''
],
[
'name' => '_APP_CUSTOM_DOMAIN_DENY_LIST',
'description' => 'List of reserved or prohibited domains when configuring custom domains.',
'introduction' => '',
'default' => 'example.com,test.com,app.example.com',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOMAIN_FUNCTIONS',
'description' => 'A domain to use for function preview URLs. Setting to empty turns off function preview URLs.',
@@ -97,6 +106,15 @@ return [
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOMAIN_SITES',
'description' => 'A domain to use for site preview URLs.',
'introduction' => '',
'default' => 'sites.localhost',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOMAIN_TARGET',
'description' => 'Deprecated since 1.7.0. A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.',
@@ -845,7 +863,7 @@ return [
],
[
'name' => '_APP_FUNCTIONS_CPUS',
'description' => 'Deprecated since 1.7.0. The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.',
'description' => 'Deprecated since 1.7.0. The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty or 0, CPU limit will be disabled',
'introduction' => '0.7.0',
'default' => '0',
'required' => false,
@@ -863,7 +881,7 @@ return [
],
[
'name' => '_APP_FUNCTIONS_MEMORY',
'description' => 'Deprecated since 1.7.0. The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.',
'description' => 'Deprecated since 1.7.0. The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty or 0, memory limit will be disabled.',
'introduction' => '0.7.0',
'default' => '0',
'required' => false,
@@ -1145,13 +1163,22 @@ return [
],
[
'name' => '_APP_MAINTENANCE_DELAY',
'description' => 'Delay value containing the number of seconds that the Appwrite maintenance process should wait before executing system cleanups and optimizations. The default value is 0 seconds.',
'description' => 'Deprecated with 1.6.2 use _APP_MAINTENANCE_START_TIME instead to run the maintenance at a specific time per day.',
'introduction' => '1.5.0',
'default' => '0',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_MAINTENANCE_START_TIME',
'description' => 'The time of day (in 24-hour format) when the maintenance process should start. The default value is 00:00.',
'introduction' => '1.6.2',
'default' => '00:00',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_MAINTENANCE_RETENTION_CACHE',
'description' => 'The maximum duration (in seconds) upto which to retain cached files. The default value is 2592000 seconds (30 days).',
File diff suppressed because it is too large Load Diff
+16 -9
View File
@@ -171,6 +171,7 @@ App::get('/v1/avatars/credit-cards/:code')
->label('cache.resource', 'avatar/credit-card')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getCreditCard',
description: '/docs/references/avatars/get-credit-card.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -186,7 +187,7 @@ App::get('/v1/avatars/credit-cards/:code')
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->param('quality', -1, new Range(-1, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.', true)
->inject('response')
->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('credit-cards', $code, $width, $height, $quality, $response));
@@ -198,6 +199,7 @@ App::get('/v1/avatars/browsers/:code')
->label('cache.resource', 'avatar/browser')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getBrowser',
description: '/docs/references/avatars/get-browser.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -213,7 +215,7 @@ App::get('/v1/avatars/browsers/:code')
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-browsers'))), 'Browser Code.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->param('quality', -1, new Range(-1, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.', true)
->inject('response')
->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('browsers', $code, $width, $height, $quality, $response));
@@ -225,6 +227,7 @@ App::get('/v1/avatars/flags/:code')
->label('cache.resource', 'avatar/flag')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getFlag',
description: '/docs/references/avatars/get-flag.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -240,7 +243,7 @@ App::get('/v1/avatars/flags/:code')
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-flags'))), 'Country Code. ISO Alpha-2 country code format.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->param('quality', -1, new Range(-1, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.', true)
->inject('response')
->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('flags', $code, $width, $height, $quality, $response));
@@ -252,6 +255,7 @@ App::get('/v1/avatars/image')
->label('cache.resource', 'avatar/image')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getImage',
description: '/docs/references/avatars/get-image.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -322,6 +326,7 @@ App::get('/v1/avatars/favicon')
->label('cache.resource', 'avatar/favicon')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getFavicon',
description: '/docs/references/avatars/get-favicon.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -472,6 +477,7 @@ App::get('/v1/avatars/qr')
->label('scope', 'avatars.read')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getQR',
description: '/docs/references/avatars/get-qr.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -521,6 +527,7 @@ App::get('/v1/avatars/initials')
->label('cache.resource', 'avatar/initials')
->label('sdk', new Method(
namespace: 'avatars',
group: null,
name: 'getInitials',
description: '/docs/references/avatars/get-initials.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -662,7 +669,7 @@ App::get('/v1/cards/cloud')
}
}
$isPlatinum = $user->getInternalId() % 100 === 0;
$isPlatinum = $user->getSequence() % 100 === 0;
} else {
$name = $mock === 'normal-long' ? 'Sir First Walter O\'Brian Junior' : 'Walter O\'Brian';
$createdAt = new \DateTime('now');
@@ -852,7 +859,7 @@ App::get('/v1/cards/cloud-back')
$isEmployee = \array_key_exists($email, $employees);
$isGolden = $isEmployee || $isHero || $isContributor;
$isPlatinum = $user->getInternalId() % 100 === 0;
$isPlatinum = $user->getSequence() % 100 === 0;
} else {
$userId = '63e0bcf3c3eb803ba530';
@@ -919,9 +926,9 @@ App::get('/v1/cards/cloud-og')
}
if (!$mock) {
$internalId = $user->getInternalId();
$bgVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3');
$cardVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3');
$sequence = $user->getSequence();
$bgVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3');
$cardVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3');
$name = $user->getAttribute('name', 'Anonymous');
$email = $user->getAttribute('email', '');
@@ -951,7 +958,7 @@ App::get('/v1/cards/cloud-og')
}
}
$isPlatinum = $user->getInternalId() % 100 === 0;
$isPlatinum = $user->getSequence() % 100 === 0;
} else {
$bgVariation = \str_ends_with($mock, '-bg2') ? '2' : (\str_ends_with($mock, '-bg3') ? '3' : '1');
$cardVariation = \str_ends_with($mock, '-right') ? '2' : (\str_ends_with($mock, '-middle') ? '3' : '1');
+3 -1
View File
@@ -29,6 +29,7 @@ App::get('/v1/console/variables')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'console',
group: 'console',
name: 'variables',
description: '/docs/references/console/variables.md',
auth: [AuthType::ADMIN],
@@ -86,11 +87,12 @@ App::get('/v1/console/variables')
});
App::post('/v1/console/assistant')
->desc('Ask query')
->desc('Create assistant query')
->groups(['api', 'assistant'])
->label('scope', 'assistant.read')
->label('sdk', new Method(
namespace: 'assistant',
group: 'console',
name: 'chat',
description: '/docs/references/assistant/chat.md',
auth: [AuthType::ADMIN],
File diff suppressed because it is too large Load Diff
+3
View File
@@ -44,6 +44,7 @@ App::get('/v1/graphql')
->label('scope', 'graphql')
->label('sdk', new Method(
namespace: 'graphql',
group: 'graphql',
name: 'get',
auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT],
hide: true,
@@ -90,6 +91,7 @@ App::post('/v1/graphql/mutation')
->label('scope', 'graphql')
->label('sdk', new Method(
namespace: 'graphql',
group: 'graphql',
name: 'mutation',
auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT],
description: '/docs/references/graphql/post.md',
@@ -140,6 +142,7 @@ App::post('/v1/graphql')
->label('scope', 'graphql')
->label('sdk', new Method(
namespace: 'graphql',
group: 'graphql',
name: 'query',
auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT],
description: '/docs/references/graphql/post.md',
+93 -111
View File
@@ -3,13 +3,16 @@
use Appwrite\ClamAV\Network;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\PubSub\Adapter\Pool as PubSubPool;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Cache\Adapter\Pool as CachePool;
use Utopia\Config\Config;
use Utopia\Database\Adapter\Pool as DatabasePool;
use Utopia\Database\Document;
use Utopia\Domains\Validator\PublicDomain;
use Utopia\Pools\Group;
@@ -32,9 +35,10 @@ App::get('/v1/health')
->label('scope', 'health.read')
->label('sdk', new Method(
namespace: 'health',
group: 'health',
name: 'get',
auth: [AuthType::KEY],
description: '/docs/references/health/get.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -69,10 +73,11 @@ App::get('/v1/health/db')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getDB',
description: '/docs/references/health/get-db.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -84,8 +89,8 @@ App::get('/v1/health/db')
->inject('response')
->inject('pools')
->action(function (Response $response, Group $pools) {
$output = [];
$failures = [];
$configs = [
'Console.DB' => Config::getParam('pools-console'),
@@ -95,7 +100,7 @@ App::get('/v1/health/db')
foreach ($configs as $key => $config) {
foreach ($config as $database) {
try {
$adapter = $pools->get($database)->pop()->getResource();
$adapter = new DatabasePool($pools->get($database));
$checkStart = \microtime(true);
@@ -106,16 +111,16 @@ App::get('/v1/health/db')
'ping' => \round((\microtime(true) - $checkStart) / 1000)
]);
} else {
$failure[] = $database;
$failures[] = $database;
}
} catch (\Throwable $th) {
$failure[] = $database;
} catch (\Throwable) {
$failures[] = $database;
}
}
}
if (!empty($failure)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failure));
if (!empty($failures)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures));
}
$response->dynamic(new Document([
@@ -129,10 +134,11 @@ App::get('/v1/health/cache')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getCache',
description: '/docs/references/health/get-cache.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -144,44 +150,39 @@ App::get('/v1/health/cache')
->inject('response')
->inject('pools')
->action(function (Response $response, Group $pools) {
$output = [];
$failures = [];
$configs = [
'Cache' => Config::getParam('pools-cache'),
];
foreach ($configs as $key => $config) {
foreach ($config as $database) {
foreach ($config as $cache) {
try {
/** @var \Utopia\Cache\Adapter $adapter */
$adapter = $pools->get($database)->pop()->getResource();
$adapter = new CachePool($pools->get($cache));
$checkStart = \microtime(true);
if ($adapter->ping()) {
$output[] = new Document([
'name' => $key . " ($database)",
'name' => $key . " ($cache)",
'status' => 'pass',
'ping' => \round((\microtime(true) - $checkStart) / 1000)
]);
} else {
$output[] = new Document([
'name' => $key . " ($database)",
'status' => 'fail',
'ping' => \round((\microtime(true) - $checkStart) / 1000)
]);
$failures[] = $cache;
}
} catch (\Throwable $th) {
$output[] = new Document([
'name' => $key . " ($database)",
'status' => 'fail',
'ping' => \round((\microtime(true) - $checkStart) / 1000)
]);
} catch (\Throwable) {
$failures[] = $cache;
}
}
}
if (!empty($failures)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Cache failure on: ' . implode(", ", $failures));
}
$response->dynamic(new Document([
'statuses' => $output,
'total' => count($output),
@@ -193,10 +194,11 @@ App::get('/v1/health/pubsub')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getPubSub',
description: '/docs/references/health/get-pubsub.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -208,44 +210,39 @@ App::get('/v1/health/pubsub')
->inject('response')
->inject('pools')
->action(function (Response $response, Group $pools) {
$output = [];
$failures = [];
$configs = [
'PubSub' => Config::getParam('pools-pubsub'),
];
foreach ($configs as $key => $config) {
foreach ($config as $database) {
foreach ($config as $pubsub) {
try {
/** @var \Appwrite\PubSub\Adapter $adapter */
$adapter = $pools->get($database)->pop()->getResource();
$adapter = new PubSubPool($pools->get($pubsub));
$checkStart = \microtime(true);
if ($adapter->ping()) {
$output[] = new Document([
'name' => $key . " ($database)",
'name' => $key . " ($pubsub)",
'status' => 'pass',
'ping' => \round((\microtime(true) - $checkStart) / 1000)
]);
} else {
$output[] = new Document([
'name' => $key . " ($database)",
'status' => 'fail',
'ping' => \round((\microtime(true) - $checkStart) / 1000)
]);
$failures[] = $pubsub;
}
} catch (\Throwable $th) {
$output[] = new Document([
'name' => $key . " ($database)",
'status' => 'fail',
'ping' => \round((\microtime(true) - $checkStart) / 1000)
]);
} catch (\Throwable) {
$failures[] = $pubsub;
}
}
}
if (!empty($failures)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Pubsub failure on: ' . implode(", ", $failures));
}
$response->dynamic(new Document([
'statuses' => $output,
'total' => count($output),
@@ -257,10 +254,11 @@ App::get('/v1/health/time')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getTime',
description: '/docs/references/health/get-time.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -320,10 +318,11 @@ App::get('/v1/health/queue/webhooks')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueWebhooks',
description: '/docs/references/health/get-queue-webhooks.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -345,17 +344,18 @@ App::get('/v1/health/queue/webhooks')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/logs')
->desc('Get logs queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueLogs',
description: '/docs/references/health/get-queue-logs.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -377,17 +377,18 @@ App::get('/v1/health/queue/logs')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/certificate')
->desc('Get the SSL certificate for a domain')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getCertificate',
description: '/docs/references/health/get-certificate.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -433,17 +434,18 @@ App::get('/v1/health/certificate')
'validTo' => $certificatePayload['validTo_time_t'],
'signatureTypeSN' => $certificatePayload['signatureTypeSN'],
]), Response::MODEL_HEALTH_CERTIFICATE);
}, ['response']);
});
App::get('/v1/health/queue/certificates')
->desc('Get certificates queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueCertificates',
description: '/docs/references/health/get-queue-certificates.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -465,17 +467,18 @@ App::get('/v1/health/queue/certificates')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/builds')
->desc('Get builds queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueBuilds',
description: '/docs/references/health/get-queue-builds.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -497,17 +500,18 @@ App::get('/v1/health/queue/builds')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/databases')
->desc('Get databases queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueDatabases',
description: '/docs/references/health/get-queue-databases.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -530,17 +534,18 @@ App::get('/v1/health/queue/databases')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/deletes')
->desc('Get deletes queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueDeletes',
description: '/docs/references/health/get-queue-deletes.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -562,17 +567,18 @@ App::get('/v1/health/queue/deletes')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/mails')
->desc('Get mails queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueMails',
description: '/docs/references/health/get-queue-mails.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -594,17 +600,18 @@ App::get('/v1/health/queue/mails')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/messaging')
->desc('Get messaging queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueMessaging',
description: '/docs/references/health/get-queue-messaging.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -626,17 +633,18 @@ App::get('/v1/health/queue/messaging')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/migrations')
->desc('Get migrations queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueMigrations',
description: '/docs/references/health/get-queue-migrations.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -658,17 +666,18 @@ App::get('/v1/health/queue/migrations')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/functions')
->desc('Get functions queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueFunctions',
description: '/docs/references/health/get-queue-functions.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -690,17 +699,18 @@ App::get('/v1/health/queue/functions')
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
}, ['response']);
});
App::get('/v1/health/queue/stats-resources')
->desc('Get stats resources queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueStatsResources',
description: '/docs/references/health/get-queue-stats-resources.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -729,10 +739,11 @@ App::get('/v1/health/queue/stats-usage')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getQueueUsage',
description: '/docs/references/health/get-queue-stats-usage.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -756,47 +767,16 @@ App::get('/v1/health/queue/stats-usage')
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
});
App::get('/v1/health/queue/stats-usage-dump')
->desc('Get usage dump queue')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
name: 'getQueueStatsUsageDump',
description: '/docs/references/health/get-queue-stats-usage-dump.md',
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_HEALTH_QUEUE,
)
],
contentType: ContentType::JSON
))
->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true)
->inject('publisher')
->inject('response')
->action(function (int|string $threshold, Publisher $publisher, Response $response) {
$threshold = \intval($threshold);
$size = $publisher->getQueueSize(new Queue(Event::STATS_USAGE_DUMP_QUEUE_NAME));
if ($size >= $threshold) {
throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}.");
}
$response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE);
});
App::get('/v1/health/storage/local')
->desc('Get local storage')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'storage',
name: 'getStorageLocal',
description: '/docs/references/health/get-storage-local.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -842,10 +822,11 @@ App::get('/v1/health/storage')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'storage',
name: 'getStorage',
description: '/docs/references/health/get-storage.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -864,15 +845,18 @@ App::get('/v1/health/storage')
$checkStart = \microtime(true);
foreach ($devices as $device) {
if (!$device->write($device->getPath('health.txt'), 'test', 'text/plain')) {
$uniqueFileName = \uniqid('health', true);
$filePath = $device->getPath($uniqueFileName);
if (!$device->write($filePath, 'test', 'text/plain')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot());
}
if ($device->read($device->getPath('health.txt')) !== 'test') {
if ($device->read($filePath) !== 'test') {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot());
}
if (!$device->delete($device->getPath('health.txt'))) {
if (!$device->delete($filePath)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot());
}
}
@@ -890,10 +874,11 @@ App::get('/v1/health/anti-virus')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'health',
name: 'getAntivirus',
description: '/docs/references/health/get-storage-anti-virus.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -935,10 +920,11 @@ App::get('/v1/health/queue/failed/:name')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk', new Method(
auth: [AuthType::KEY],
namespace: 'health',
group: 'queue',
name: 'getFailedJobs',
description: '/docs/references/health/get-failed-queue-jobs.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
@@ -955,7 +941,6 @@ App::get('/v1/health/queue/failed/:name')
Event::FUNCTIONS_QUEUE_NAME,
Event::STATS_RESOURCES_QUEUE_NAME,
Event::STATS_USAGE_QUEUE_NAME,
Event::STATS_USAGE_DUMP_QUEUE_NAME,
Event::WEBHOOK_QUEUE_NAME,
Event::CERTIFICATES_QUEUE_NAME,
Event::BUILDS_QUEUE_NAME,
@@ -981,9 +966,6 @@ App::get('/v1/health/stats') // Currently only used internally
->desc('Get system stats')
->groups(['api', 'health'])
->label('scope', 'root')
// ->label('sdk.auth', [APP_AUTH_TYPE_KEY])
// ->label('sdk.namespace', 'health')
// ->label('sdk.method', 'getStats')
->label('docs', false)
->inject('response')
->inject('register')
+8
View File
@@ -17,6 +17,7 @@ App::get('/v1/locale')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'get',
description: '/docs/references/locale/get-locale.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -80,6 +81,7 @@ App::get('/v1/locale/codes')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCodes',
description: '/docs/references/locale/list-locale-codes.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -105,6 +107,7 @@ App::get('/v1/locale/countries')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCountries',
description: '/docs/references/locale/list-countries.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -141,6 +144,7 @@ App::get('/v1/locale/countries/eu')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCountriesEU',
description: '/docs/references/locale/list-countries-eu.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -179,6 +183,7 @@ App::get('/v1/locale/countries/phones')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCountriesPhones',
description: '/docs/references/locale/list-countries-phones.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -216,6 +221,7 @@ App::get('/v1/locale/continents')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listContinents',
description: '/docs/references/locale/list-continents.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -251,6 +257,7 @@ App::get('/v1/locale/currencies')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listCurrencies',
description: '/docs/references/locale/list-currencies.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -277,6 +284,7 @@ App::get('/v1/locale/languages')
->label('scope', 'locale.read')
->label('sdk', new Method(
namespace: 'locale',
group: null,
name: 'listLanguages',
description: '/docs/references/locale/list-languages.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
+98 -28
View File
@@ -30,6 +30,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
@@ -63,6 +64,7 @@ App::post('/v1/messaging/providers/mailgun')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createMailgunProvider',
description: '/docs/references/messaging/create-mailgun-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -156,6 +158,7 @@ App::post('/v1/messaging/providers/sendgrid')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createSendgridProvider',
description: '/docs/references/messaging/create-sendgrid-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -237,6 +240,7 @@ App::post('/v1/messaging/providers/smtp')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createSmtpProvider',
description: '/docs/references/messaging/create-smtp-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -331,6 +335,7 @@ App::post('/v1/messaging/providers/msg91')
->label('event', 'providers.[providerId].create')
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createMsg91Provider',
description: '/docs/references/messaging/create-msg91-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -413,6 +418,7 @@ App::post('/v1/messaging/providers/telesign')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createTelesignProvider',
description: '/docs/references/messaging/create-telesign-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -496,6 +502,7 @@ App::post('/v1/messaging/providers/textmagic')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createTextmagicProvider',
description: '/docs/references/messaging/create-textmagic-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -579,6 +586,7 @@ App::post('/v1/messaging/providers/twilio')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createTwilioProvider',
description: '/docs/references/messaging/create-twilio-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -662,6 +670,7 @@ App::post('/v1/messaging/providers/vonage')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createVonageProvider',
description: '/docs/references/messaging/create-vonage-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -745,6 +754,7 @@ App::post('/v1/messaging/providers/fcm')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createFcmProvider',
description: '/docs/references/messaging/create-fcm-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -814,6 +824,7 @@ App::post('/v1/messaging/providers/apns')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'createApnsProvider',
description: '/docs/references/messaging/create-apns-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -903,6 +914,7 @@ App::get('/v1/messaging/providers')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'listProviders',
description: '/docs/references/messaging/list-providers.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -951,10 +963,15 @@ App::get('/v1/messaging/providers')
$cursor->setValue($cursorDocument);
}
try {
$providers = $dbForProject->find('providers', $queries);
$total = $dbForProject->count('providers', $queries, 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.");
}
$response->dynamic(new Document([
'providers' => $dbForProject->find('providers', $queries),
'total' => $dbForProject->count('providers', $queries, APP_LIMIT_COUNT),
'providers' => $providers,
'total' => $total,
]), Response::MODEL_PROVIDER_LIST);
});
@@ -965,6 +982,7 @@ App::get('/v1/messaging/providers/:providerId/logs')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'listProviderLogs',
description: '/docs/references/messaging/list-provider-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1061,6 +1079,7 @@ App::get('/v1/messaging/providers/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'getProvider',
description: '/docs/references/messaging/get-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1094,6 +1113,7 @@ App::patch('/v1/messaging/providers/mailgun/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateMailgunProvider',
description: '/docs/references/messaging/update-mailgun-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1206,6 +1226,7 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateSendgridProvider',
description: '/docs/references/messaging/update-sendgrid-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1303,6 +1324,7 @@ App::patch('/v1/messaging/providers/smtp/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateSmtpProvider',
description: '/docs/references/messaging/update-smtp-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1431,6 +1453,7 @@ App::patch('/v1/messaging/providers/msg91/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateMsg91Provider',
description: '/docs/references/messaging/update-msg91-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1517,6 +1540,7 @@ App::patch('/v1/messaging/providers/telesign/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateTelesignProvider',
description: '/docs/references/messaging/update-telesign-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1605,6 +1629,7 @@ App::patch('/v1/messaging/providers/textmagic/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateTextmagicProvider',
description: '/docs/references/messaging/update-textmagic-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1693,6 +1718,7 @@ App::patch('/v1/messaging/providers/twilio/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateTwilioProvider',
description: '/docs/references/messaging/update-twilio-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1781,6 +1807,7 @@ App::patch('/v1/messaging/providers/vonage/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateVonageProvider',
description: '/docs/references/messaging/update-vonage-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1869,6 +1896,7 @@ App::patch('/v1/messaging/providers/fcm/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateFcmProvider',
description: '/docs/references/messaging/update-fcm-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -1944,6 +1972,7 @@ App::patch('/v1/messaging/providers/apns/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'updateApnsProvider',
description: '/docs/references/messaging/update-apns-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2045,6 +2074,7 @@ App::delete('/v1/messaging/providers/:providerId')
->label('resourceType', RESOURCE_TYPE_PROVIDERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'providers',
name: 'deleteProvider',
description: '/docs/references/messaging/delete-provider.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2087,6 +2117,7 @@ App::post('/v1/messaging/topics')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'createTopic',
description: '/docs/references/messaging/create-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2133,6 +2164,7 @@ App::get('/v1/messaging/topics')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'listTopics',
description: '/docs/references/messaging/list-topics.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2181,10 +2213,15 @@ App::get('/v1/messaging/topics')
$cursor->setValue($cursorDocument[0]);
}
try {
$topics = $dbForProject->find('topics', $queries);
$total = $dbForProject->count('topics', $queries, 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.");
}
$response->dynamic(new Document([
'topics' => $dbForProject->find('topics', $queries),
'total' => $dbForProject->count('topics', $queries, APP_LIMIT_COUNT),
'topics' => $topics,
'total' => $total,
]), Response::MODEL_TOPIC_LIST);
});
@@ -2195,6 +2232,7 @@ App::get('/v1/messaging/topics/:topicId/logs')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'listTopicLogs',
description: '/docs/references/messaging/list-topic-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2292,6 +2330,7 @@ App::get('/v1/messaging/topics/:topicId')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'getTopic',
description: '/docs/references/messaging/get-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2326,6 +2365,7 @@ App::patch('/v1/messaging/topics/:topicId')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'updateTopic',
description: '/docs/references/messaging/update-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2376,6 +2416,7 @@ App::delete('/v1/messaging/topics/:topicId')
->label('resourceType', RESOURCE_TYPE_TOPICS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'topics',
name: 'deleteTopic',
description: '/docs/references/messaging/delete-topic.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2423,6 +2464,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'createSubscriber',
description: '/docs/references/messaging/create-subscriber.md',
auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY],
@@ -2469,11 +2511,11 @@ App::post('/v1/messaging/topics/:topicId/subscribers')
Permission::delete(Role::user($user->getId())),
],
'topicId' => $topicId,
'topicInternalId' => $topic->getInternalId(),
'topicInternalId' => $topic->getSequence(),
'targetId' => $targetId,
'targetInternalId' => $target->getInternalId(),
'targetInternalId' => $target->getSequence(),
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'providerType' => $target->getAttribute('providerType'),
'search' => implode(' ', [
$subscriberId,
@@ -2522,6 +2564,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'listSubscribers',
description: '/docs/references/messaging/list-subscribers.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2554,7 +2597,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
throw new Exception(Exception::TOPIC_NOT_FOUND);
}
$queries[] = Query::equal('topicInternalId', [$topic->getInternalId()]);
$queries[] = Query::equal('topicInternalId', [$topic->getSequence()]);
/**
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
@@ -2579,8 +2622,11 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
$cursor->setValue($cursorDocument);
}
$subscribers = $dbForProject->find('subscribers', $queries);
try {
$subscribers = $dbForProject->find('subscribers', $queries);
} 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.");
}
$subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) {
return function () use ($subscriber, $dbForProject) {
@@ -2607,6 +2653,7 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'listSubscriberLogs',
description: '/docs/references/messaging/list-subscriber-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2704,6 +2751,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'getSubscriber',
description: '/docs/references/messaging/get-subscriber.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2752,6 +2800,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS)
->label('sdk', new Method(
namespace: 'messaging',
group: 'subscribers',
name: 'deleteSubscriber',
description: '/docs/references/messaging/delete-subscriber.md',
auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY],
@@ -2818,6 +2867,7 @@ App::post('/v1/messaging/messages/email')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'createEmail',
description: '/docs/references/messaging/create-email.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -2897,7 +2947,7 @@ App::post('/v1/messaging/messages/email')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
@@ -2939,7 +2989,7 @@ App::post('/v1/messaging/messages/email')
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
'projectId' => $project->getId(),
'schedule' => $scheduledAt,
@@ -2976,6 +3026,7 @@ App::post('/v1/messaging/messages/sms')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'createSms',
description: '/docs/references/messaging/create-sms.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3061,7 +3112,7 @@ App::post('/v1/messaging/messages/sms')
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
'projectId' => $project->getId(),
'schedule' => $scheduledAt,
@@ -3098,6 +3149,7 @@ App::post('/v1/messaging/messages/push')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'createPush',
description: '/docs/references/messaging/create-push.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3180,7 +3232,7 @@ App::post('/v1/messaging/messages/push')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
@@ -3278,7 +3330,7 @@ App::post('/v1/messaging/messages/push')
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
'projectId' => $project->getId(),
'schedule' => $scheduledAt,
@@ -3312,6 +3364,7 @@ App::get('/v1/messaging/messages')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'listMessages',
description: '/docs/references/messaging/list-messages.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3360,10 +3413,15 @@ App::get('/v1/messaging/messages')
$cursor->setValue($cursorDocument);
}
try {
$messages = $dbForProject->find('messages', $queries);
$total = $dbForProject->count('messages', $queries, 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.");
}
$response->dynamic(new Document([
'messages' => $dbForProject->find('messages', $queries),
'total' => $dbForProject->count('messages', $queries, APP_LIMIT_COUNT),
'messages' => $messages,
'total' => $total,
]), Response::MODEL_MESSAGE_LIST);
});
@@ -3374,6 +3432,7 @@ App::get('/v1/messaging/messages/:messageId/logs')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'logs',
name: 'listMessageLogs',
description: '/docs/references/messaging/list-message-logs.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3471,6 +3530,7 @@ App::get('/v1/messaging/messages/:messageId/targets')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'listTargets',
description: '/docs/references/messaging/list-message-targets.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3533,10 +3593,15 @@ App::get('/v1/messaging/messages/:messageId/targets')
$cursor->setValue($cursorDocument);
}
try {
$targets = $dbForProject->find('targets', $queries);
$total = $dbForProject->count('targets', $queries, 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.");
}
$response->dynamic(new Document([
'targets' => $dbForProject->find('targets', $queries),
'total' => $dbForProject->count('targets', $queries, APP_LIMIT_COUNT),
'targets' => $targets,
'total' => $total,
]), Response::MODEL_TARGET_LIST);
});
@@ -3547,6 +3612,7 @@ App::get('/v1/messaging/messages/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'getMessage',
description: '/docs/references/messaging/get-message.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3580,6 +3646,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'updateEmail',
description: '/docs/references/messaging/update-email.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3664,7 +3731,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
'projectId' => $project->getId(),
'schedule' => $scheduledAt,
@@ -3729,7 +3796,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
@@ -3786,6 +3853,7 @@ App::patch('/v1/messaging/messages/sms/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'updateSms',
description: '/docs/references/messaging/update-sms.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -3865,7 +3933,7 @@ App::patch('/v1/messaging/messages/sms/:messageId')
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
'projectId' => $project->getId(),
'schedule' => $scheduledAt,
@@ -3947,6 +4015,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'updatePush',
description: '/docs/references/messaging/update-push.md',
auth: [AuthType::ADMIN, AuthType::KEY],
@@ -4038,7 +4107,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
'region' => $project->getAttribute('region'),
'resourceType' => 'message',
'resourceId' => $message->getId(),
'resourceInternalId' => $message->getInternalId(),
'resourceInternalId' => $message->getSequence(),
'resourceUpdatedAt' => DateTime::now(),
'projectId' => $project->getId(),
'schedule' => $scheduledAt,
@@ -4141,7 +4210,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
@@ -4206,6 +4275,7 @@ App::delete('/v1/messaging/messages/:messageId')
->label('resourceType', RESOURCE_TYPE_MESSAGES)
->label('sdk', new Method(
namespace: 'messaging',
group: 'messages',
name: 'delete',
description: '/docs/references/messaging/delete-message.md',
auth: [AuthType::ADMIN, AuthType::KEY],
+33 -13
View File
@@ -15,6 +15,7 @@ use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
@@ -43,12 +44,13 @@ include_once __DIR__ . '/../shared/api.php';
App::post('/v1/migrations/appwrite')
->groups(['api', 'migrations'])
->desc('Migrate Appwrite data')
->desc('Create Appwrite migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createAppwriteMigration',
description: '/docs/references/migrations/migration-appwrite.md',
auth: [AuthType::ADMIN],
@@ -103,12 +105,13 @@ App::post('/v1/migrations/appwrite')
App::post('/v1/migrations/firebase')
->groups(['api', 'migrations'])
->desc('Migrate Firebase data')
->desc('Create Firebase migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createFirebaseMigration',
description: '/docs/references/migrations/migration-firebase.md',
auth: [AuthType::ADMIN],
@@ -169,12 +172,13 @@ App::post('/v1/migrations/firebase')
App::post('/v1/migrations/supabase')
->groups(['api', 'migrations'])
->desc('Migrate Supabase data')
->desc('Create Supabase migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createSupabaseMigration',
description: '/docs/references/migrations/migration-supabase.md',
auth: [AuthType::ADMIN],
@@ -235,12 +239,13 @@ App::post('/v1/migrations/supabase')
App::post('/v1/migrations/nhost')
->groups(['api', 'migrations'])
->desc('Migrate NHost data')
->desc('Create NHost migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].create')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createNHostMigration',
description: '/docs/references/migrations/migration-nhost.md',
auth: [AuthType::ADMIN],
@@ -309,6 +314,7 @@ App::post('/v1/migrations/csv')
->label('audits.event', 'migration.create')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'createCsvMigration',
description: '/docs/references/migrations/migration-csv.md',
auth: [AuthType::ADMIN],
@@ -339,7 +345,7 @@ App::post('/v1/migrations/csv')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
}
@@ -431,6 +437,7 @@ App::get('/v1/migrations')
->label('scope', 'migrations.read')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'list',
description: '/docs/references/migrations/list-migrations.md',
auth: [AuthType::ADMIN],
@@ -482,10 +489,15 @@ App::get('/v1/migrations')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$migrations = $dbForProject->find('migrations', $queries);
$total = $dbForProject->count('migrations', $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.");
}
$response->dynamic(new Document([
'migrations' => $dbForProject->find('migrations', $queries),
'total' => $dbForProject->count('migrations', $filterQueries, APP_LIMIT_COUNT),
'migrations' => $migrations,
'total' => $total,
]), Response::MODEL_MIGRATION_LIST);
});
@@ -495,6 +507,7 @@ App::get('/v1/migrations/:migrationId')
->label('scope', 'migrations.read')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'get',
description: '/docs/references/migrations/get-migration.md',
auth: [AuthType::ADMIN],
@@ -520,10 +533,11 @@ App::get('/v1/migrations/:migrationId')
App::get('/v1/migrations/appwrite/report')
->groups(['api', 'migrations'])
->desc('Generate a report on Appwrite data')
->desc('Get Appwrite migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getAppwriteReport',
description: '/docs/references/migrations/migration-appwrite-report.md',
auth: [AuthType::ADMIN],
@@ -543,6 +557,7 @@ App::get('/v1/migrations/appwrite/report')
->inject('project')
->inject('user')
->action(function (array $resources, string $endpoint, string $projectID, string $key, Response $response) {
$appwrite = new Appwrite($projectID, $endpoint, $key);
try {
@@ -567,10 +582,11 @@ App::get('/v1/migrations/appwrite/report')
App::get('/v1/migrations/firebase/report')
->groups(['api', 'migrations'])
->desc('Generate a report on Firebase data')
->desc('Get Firebase migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getFirebaseReport',
description: '/docs/references/migrations/migration-firebase-report.md',
auth: [AuthType::ADMIN],
@@ -619,10 +635,11 @@ App::get('/v1/migrations/firebase/report')
App::get('/v1/migrations/supabase/report')
->groups(['api', 'migrations'])
->desc('Generate a report on Supabase Data')
->desc('Get Supabase migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getSupabaseReport',
description: '/docs/references/migrations/migration-supabase-report.md',
auth: [AuthType::ADMIN],
@@ -667,10 +684,11 @@ App::get('/v1/migrations/supabase/report')
App::get('/v1/migrations/nhost/report')
->groups(['api', 'migrations'])
->desc('Generate a report on NHost Data')
->desc('Get NHost migration report')
->label('scope', 'migrations.write')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'getNHostReport',
description: '/docs/references/migrations/migration-nhost-report.md',
auth: [AuthType::ADMIN],
@@ -715,13 +733,14 @@ App::get('/v1/migrations/nhost/report')
App::patch('/v1/migrations/:migrationId')
->groups(['api', 'migrations'])
->desc('Retry migration')
->desc('Update retry migration')
->label('scope', 'migrations.write')
->label('event', 'migrations.[migrationId].retry')
->label('audits.event', 'migration.retry')
->label('audits.resource', 'migrations/{request.migrationId}')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'retry',
description: '/docs/references/migrations/retry-migration.md',
auth: [AuthType::ADMIN],
@@ -772,6 +791,7 @@ App::delete('/v1/migrations/:migrationId')
->label('audits.resource', 'migrations/{request.migrationId}')
->label('sdk', new Method(
namespace: 'migrations',
group: null,
name: 'delete',
description: '/docs/references/migrations/delete-migration.md',
auth: [AuthType::ADMIN],
+15 -9
View File
@@ -27,6 +27,7 @@ App::get('/v1/project/usage')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'getUsage',
description: '/docs/references/project/get-usage.md',
auth: [AuthType::ADMIN],
@@ -149,7 +150,7 @@ App::get('/v1/project/usage')
$executionsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -165,7 +166,7 @@ App::get('/v1/project/usage')
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -181,7 +182,7 @@ App::get('/v1/project/usage')
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -197,7 +198,7 @@ App::get('/v1/project/usage')
$bucketsBreakdown = array_map(function ($bucket) use ($dbForProject) {
$id = $bucket->getId();
$name = $bucket->getAttribute('name');
$metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE);
$metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -213,7 +214,7 @@ App::get('/v1/project/usage')
$databasesStorageBreakdown = array_map(function ($database) use ($dbForProject) {
$id = $database->getId();
$name = $database->getAttribute('name');
$metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE);
$metric = str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
@@ -230,13 +231,13 @@ App::get('/v1/project/usage')
$functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE);
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE);
$deploymentValue = $dbForProject->findOne('stats', [
Query::equal('metric', [$deploymentMetric]),
Query::equal('period', ['inf'])
]);
$buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE);
$buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE);
$buildValue = $dbForProject->findOne('stats', [
Query::equal('metric', [$buildMetric]),
Query::equal('period', ['inf'])
@@ -254,7 +255,7 @@ App::get('/v1/project/usage')
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -270,7 +271,7 @@ App::get('/v1/project/usage')
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
$id = $function->getId();
$name = $function->getAttribute('name');
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
$value = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
@@ -388,6 +389,7 @@ App::post('/v1/project/variables')
->label('audits.event', 'variable.create')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'createVariable',
description: '/docs/references/project/create-variable.md',
auth: [AuthType::ADMIN],
@@ -449,6 +451,7 @@ App::get('/v1/project/variables')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'listVariables',
description: '/docs/references/project/list-variables.md',
auth: [AuthType::ADMIN],
@@ -479,6 +482,7 @@ App::get('/v1/project/variables/:variableId')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'getVariable',
description: '/docs/references/project/get-variable.md',
auth: [AuthType::ADMIN],
@@ -508,6 +512,7 @@ App::put('/v1/project/variables/:variableId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'updateVariable',
description: '/docs/references/project/update-variable.md',
auth: [AuthType::ADMIN],
@@ -565,6 +570,7 @@ App::delete('/v1/project/variables/:variableId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'project',
group: null,
name: 'deleteVariable',
description: '/docs/references/project/delete-variable.md',
auth: [AuthType::ADMIN],
+102 -33
View File
@@ -24,10 +24,12 @@ use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Cache\Cache;
use Utopia\Config\Config;
use Utopia\Database\Adapter\Pool as DatabasePool;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@@ -68,6 +70,7 @@ App::post('/v1/projects')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'create',
description: '/docs/references/projects/create.md',
auth: [AuthType::ADMIN],
@@ -138,6 +141,14 @@ App::post('/v1/projects')
$databases = Config::getParam('pools-database', []);
if ($region !== 'default') {
$databaseKeys = System::getEnv('_APP_DATABASE_KEYS', '');
$keys = explode(',', $databaseKeys);
$databases = array_filter($keys, function ($value) use ($region) {
return str_contains($value, $region);
});
}
$databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE');
$index = \array_search($databaseOverride, $databases);
if ($index !== false) {
@@ -171,7 +182,7 @@ App::post('/v1/projects')
Permission::delete(Role::team(ID::custom($teamId), 'developer')),
],
'name' => $name,
'teamInternalId' => $team->getInternalId(),
'teamInternalId' => $team->getSequence(),
'teamId' => $team->getId(),
'region' => $region,
'description' => $description,
@@ -205,27 +216,27 @@ App::post('/v1/projects')
$dsn = new DSN('mysql://' . $dsn);
}
$adapter = $pools->get($dsn->getHost())->pop()->getResource();
$dbForProject = new Database($adapter, $cache);
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
$sharedTables = $sharedTablesV1 || $sharedTablesV2;
if (!$sharedTablesV2) {
$adapter = new DatabasePool($pools->get($dsn->getHost()));
$dbForProject = new Database($adapter, $cache);
if ($sharedTables) {
$dbForProject
->setSharedTables(true)
->setTenant($sharedTablesV1 ? $project->getInternalId() : null)
->setTenant($sharedTablesV1 ? $project->getSequence() : null)
->setNamespace($dsn->getParam('namespace'));
} else {
$dbForProject
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
$create = true;
@@ -297,6 +308,7 @@ App::get('/v1/projects')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'list',
description: '/docs/references/projects/list.md',
auth: [AuthType::ADMIN],
@@ -349,10 +361,15 @@ App::get('/v1/projects')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$projects = $dbForPlatform->find('projects', $queries);
$total = $dbForPlatform->count('projects', $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.");
}
$response->dynamic(new Document([
'projects' => $dbForPlatform->find('projects', $queries),
'total' => $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT),
'projects' => $projects,
'total' => $total,
]), Response::MODEL_PROJECT_LIST);
});
@@ -362,6 +379,7 @@ App::get('/v1/projects/:projectId')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'get',
description: '/docs/references/projects/get.md',
auth: [AuthType::ADMIN],
@@ -394,6 +412,7 @@ App::patch('/v1/projects/:projectId')
->label('audits.resource', 'project/{request.projectId}')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'update',
description: '/docs/references/projects/update.md',
auth: [AuthType::ADMIN],
@@ -447,6 +466,7 @@ App::patch('/v1/projects/:projectId/team')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateTeam',
description: '/docs/references/projects/update-team.md',
auth: [AuthType::ADMIN],
@@ -484,12 +504,12 @@ App::patch('/v1/projects/:projectId/team')
$project
->setAttribute('teamId', $teamId)
->setAttribute('teamInternalId', $team->getInternalId())
->setAttribute('teamInternalId', $team->getSequence())
->setAttribute('$permissions', $permissions);
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project);
$installations = $dbForPlatform->find('installations', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
foreach ($installations as $installation) {
$installation->getAttribute('$permissions', $permissions);
@@ -497,7 +517,7 @@ App::patch('/v1/projects/:projectId/team')
}
$repositories = $dbForPlatform->find('repositories', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
foreach ($repositories as $repository) {
$repository->getAttribute('$permissions', $permissions);
@@ -505,7 +525,7 @@ App::patch('/v1/projects/:projectId/team')
}
$vcsComments = $dbForPlatform->find('vcsComments', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
foreach ($vcsComments as $vcsComment) {
$vcsComment->getAttribute('$permissions', $permissions);
@@ -521,6 +541,7 @@ App::patch('/v1/projects/:projectId/service')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateServiceStatus',
description: '/docs/references/projects/update-service-status.md',
auth: [AuthType::ADMIN],
@@ -558,6 +579,7 @@ App::patch('/v1/projects/:projectId/service/all')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateServiceStatusAll',
description: '/docs/references/projects/update-service-status-all.md',
auth: [AuthType::ADMIN],
@@ -598,6 +620,7 @@ App::patch('/v1/projects/:projectId/api')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateApiStatus',
description: '/docs/references/projects/update-api-status.md',
auth: [AuthType::ADMIN],
@@ -635,6 +658,7 @@ App::patch('/v1/projects/:projectId/api/all')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'updateApiStatusAll',
description: '/docs/references/projects/update-api-status-all.md',
auth: [AuthType::ADMIN],
@@ -675,6 +699,7 @@ App::patch('/v1/projects/:projectId/oauth2')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateOAuth2',
description: '/docs/references/projects/update-oauth2.md',
auth: [AuthType::ADMIN],
@@ -725,6 +750,7 @@ App::patch('/v1/projects/:projectId/auth/session-alerts')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateSessionAlerts',
description: '/docs/references/projects/update-session-alerts.md',
auth: [AuthType::ADMIN],
@@ -762,6 +788,7 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateMembershipsPrivacy',
description: '/docs/references/projects/update-memberships-privacy.md',
auth: [AuthType::ADMIN],
@@ -803,6 +830,7 @@ App::patch('/v1/projects/:projectId/auth/limit')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthLimit',
description: '/docs/references/projects/update-auth-limit.md',
auth: [AuthType::ADMIN],
@@ -840,6 +868,7 @@ App::patch('/v1/projects/:projectId/auth/duration')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthDuration',
description: '/docs/references/projects/update-auth-duration.md',
auth: [AuthType::ADMIN],
@@ -877,6 +906,7 @@ App::patch('/v1/projects/:projectId/auth/:method')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthStatus',
description: '/docs/references/projects/update-auth-status.md',
auth: [AuthType::ADMIN],
@@ -917,6 +947,7 @@ App::patch('/v1/projects/:projectId/auth/password-history')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthPasswordHistory',
description: '/docs/references/projects/update-auth-password-history.md',
auth: [AuthType::ADMIN],
@@ -954,6 +985,7 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthPasswordDictionary',
description: '/docs/references/projects/update-auth-password-dictionary.md',
auth: [AuthType::ADMIN],
@@ -986,11 +1018,12 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary')
});
App::patch('/v1/projects/:projectId/auth/personal-data')
->desc('Enable or disable checking user passwords for similarity with their personal data.')
->desc('Update personal data check')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updatePersonalDataCheck',
description: '/docs/references/projects/update-personal-data-check.md',
auth: [AuthType::ADMIN],
@@ -1028,6 +1061,7 @@ App::patch('/v1/projects/:projectId/auth/max-sessions')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateAuthSessionsLimit',
description: '/docs/references/projects/update-auth-sessions-limit.md',
auth: [AuthType::ADMIN],
@@ -1065,6 +1099,7 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'updateMockNumbers',
description: '/docs/references/projects/update-mock-numbers.md',
auth: [AuthType::ADMIN],
@@ -1112,6 +1147,7 @@ App::delete('/v1/projects/:projectId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'projects',
name: 'delete',
description: '/docs/references/projects/delete.md',
auth: [AuthType::ADMIN],
@@ -1155,6 +1191,7 @@ App::post('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'createWebhook',
description: '/docs/references/projects/create-webhook.md',
auth: [AuthType::ADMIN],
@@ -1192,7 +1229,7 @@ App::post('/v1/projects/:projectId/webhooks')
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'projectId' => $project->getId(),
'name' => $name,
'events' => $events,
@@ -1219,6 +1256,7 @@ App::get('/v1/projects/:projectId/webhooks')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'listWebhooks',
description: '/docs/references/projects/list-webhooks.md',
auth: [AuthType::ADMIN],
@@ -1241,7 +1279,7 @@ App::get('/v1/projects/:projectId/webhooks')
}
$webhooks = $dbForPlatform->find('webhooks', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
Query::limit(5000),
]);
@@ -1257,6 +1295,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'getWebhook',
description: '/docs/references/projects/get-webhook.md',
auth: [AuthType::ADMIN],
@@ -1281,7 +1320,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
$webhook = $dbForPlatform->findOne('webhooks', [
Query::equal('$id', [$webhookId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($webhook->isEmpty()) {
@@ -1297,6 +1336,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'updateWebhook',
description: '/docs/references/projects/update-webhook.md',
auth: [AuthType::ADMIN],
@@ -1330,7 +1370,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
$webhook = $dbForPlatform->findOne('webhooks', [
Query::equal('$id', [$webhookId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($webhook->isEmpty()) {
@@ -1362,6 +1402,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'updateWebhookSignature',
description: '/docs/references/projects/update-webhook-signature.md',
auth: [AuthType::ADMIN],
@@ -1386,7 +1427,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
$webhook = $dbForPlatform->findOne('webhooks', [
Query::equal('$id', [$webhookId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($webhook->isEmpty()) {
@@ -1407,6 +1448,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'webhooks',
name: 'deleteWebhook',
description: '/docs/references/projects/delete-webhook.md',
auth: [AuthType::ADMIN],
@@ -1432,7 +1474,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
$webhook = $dbForPlatform->findOne('webhooks', [
Query::equal('$id', [$webhookId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($webhook->isEmpty()) {
@@ -1454,6 +1496,7 @@ App::post('/v1/projects/:projectId/keys')
->label('scope', 'keys.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'createKey',
description: '/docs/references/projects/create-key.md',
auth: [AuthType::ADMIN],
@@ -1485,7 +1528,7 @@ App::post('/v1/projects/:projectId/keys')
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'projectId' => $project->getId(),
'name' => $name,
'scopes' => $scopes,
@@ -1510,6 +1553,7 @@ App::get('/v1/projects/:projectId/keys')
->label('scope', 'keys.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'listKeys',
description: '/docs/references/projects/list-keys.md',
auth: [AuthType::ADMIN],
@@ -1532,7 +1576,7 @@ App::get('/v1/projects/:projectId/keys')
}
$keys = $dbForPlatform->find('keys', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
Query::limit(5000),
]);
@@ -1548,6 +1592,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'keys.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'getKey',
description: '/docs/references/projects/get-key.md',
auth: [AuthType::ADMIN],
@@ -1572,7 +1617,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
$key = $dbForPlatform->findOne('keys', [
Query::equal('$id', [$keyId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($key->isEmpty()) {
@@ -1588,6 +1633,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'keys.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'updateKey',
description: '/docs/references/projects/update-key.md',
auth: [AuthType::ADMIN],
@@ -1615,7 +1661,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
$key = $dbForPlatform->findOne('keys', [
Query::equal('$id', [$keyId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($key->isEmpty()) {
@@ -1640,6 +1686,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
->label('scope', 'keys.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'keys',
name: 'deleteKey',
description: '/docs/references/projects/delete-key.md',
auth: [AuthType::ADMIN],
@@ -1665,7 +1712,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
$key = $dbForPlatform->findOne('keys', [
Query::equal('$id', [$keyId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($key->isEmpty()) {
@@ -1687,6 +1734,7 @@ App::post('/v1/projects/:projectId/jwts')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'auth',
name: 'createJWT',
description: '/docs/references/projects/create-jwt.md',
auth: [AuthType::ADMIN],
@@ -1730,6 +1778,7 @@ App::post('/v1/projects/:projectId/platforms')
->label('scope', 'platforms.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'createPlatform',
description: '/docs/references/projects/create-platform.md',
auth: [AuthType::ADMIN],
@@ -1762,7 +1811,7 @@ App::post('/v1/projects/:projectId/platforms')
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'projectId' => $project->getId(),
'type' => $type,
'name' => $name,
@@ -1786,6 +1835,7 @@ App::get('/v1/projects/:projectId/platforms')
->label('scope', 'platforms.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'listPlatforms',
description: '/docs/references/projects/list-platforms.md',
auth: [AuthType::ADMIN],
@@ -1808,7 +1858,7 @@ App::get('/v1/projects/:projectId/platforms')
}
$platforms = $dbForPlatform->find('platforms', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
Query::limit(5000),
]);
@@ -1824,6 +1874,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'platforms.read')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'getPlatform',
description: '/docs/references/projects/get-platform.md',
auth: [AuthType::ADMIN],
@@ -1848,7 +1899,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
$platform = $dbForPlatform->findOne('platforms', [
Query::equal('$id', [$platformId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($platform->isEmpty()) {
@@ -1864,6 +1915,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'platforms.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'updatePlatform',
description: '/docs/references/projects/update-platform.md',
auth: [AuthType::ADMIN],
@@ -1891,7 +1943,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
$platform = $dbForPlatform->findOne('platforms', [
Query::equal('$id', [$platformId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($platform->isEmpty()) {
@@ -1919,6 +1971,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
->label('scope', 'platforms.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'platforms',
name: 'deletePlatform',
description: '/docs/references/projects/delete-platform.md',
auth: [AuthType::ADMIN],
@@ -1944,7 +1997,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
$platform = $dbForPlatform->findOne('platforms', [
Query::equal('$id', [$platformId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::equal('projectInternalId', [$project->getSequence()]),
]);
if ($platform->isEmpty()) {
@@ -1966,6 +2019,7 @@ App::patch('/v1/projects/:projectId/smtp')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'updateSmtp',
description: '/docs/references/projects/update-smtp.md',
auth: [AuthType::ADMIN],
@@ -2062,6 +2116,7 @@ App::post('/v1/projects/:projectId/smtp/tests')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'createSmtpTest',
description: '/docs/references/projects/create-smtp-test.md',
auth: [AuthType::ADMIN],
@@ -2085,7 +2140,8 @@ App::post('/v1/projects/:projectId/smtp/tests')
->inject('response')
->inject('dbForPlatform')
->inject('queueForMails')
->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails) {
->inject('plan')
->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails, array $plan) {
$project = $dbForPlatform->getDocument('projects', $projectId);
if ($project->isEmpty()) {
@@ -2098,7 +2154,14 @@ App::post('/v1/projects/:projectId/smtp/tests')
$template = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-smtp-test.tpl');
$template
->setParam('{{from}}', "{$senderName} ({$senderEmail})")
->setParam('{{replyTo}}', "{$senderName} ({$replyToEmail})");
->setParam('{{replyTo}}', "{$senderName} ({$replyToEmail})")
->setParam('{{logoUrl}}', $plan['logoUrl'] ?? APP_EMAIL_LOGO_URL)
->setParam('{{accentColor}}', $plan['accentColor'] ?? APP_EMAIL_ACCENT_COLOR)
->setParam('{{twitterUrl}}', $plan['twitterUrl'] ?? APP_SOCIAL_TWITTER)
->setParam('{{discordUrl}}', $plan['discordUrl'] ?? APP_SOCIAL_DISCORD)
->setParam('{{githubUrl}}', $plan['githubUrl'] ?? APP_SOCIAL_GITHUB_APPWRITE)
->setParam('{{termsUrl}}', $plan['termsUrl'] ?? APP_EMAIL_TERMS_URL)
->setParam('{{privacyUrl}}', $plan['privacyUrl'] ?? APP_EMAIL_PRIVACY_URL);
foreach ($emails as $email) {
$queueForMails
@@ -2128,6 +2191,7 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'getSmsTemplate',
description: '/docs/references/projects/get-sms-template.md',
auth: [AuthType::ADMIN],
@@ -2175,6 +2239,7 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'getEmailTemplate',
description: '/docs/references/projects/get-email-template.md',
auth: [AuthType::ADMIN],
@@ -2233,6 +2298,7 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'updateSmsTemplate',
description: '/docs/references/projects/update-sms-template.md',
auth: [AuthType::ADMIN],
@@ -2279,6 +2345,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'updateEmailTemplate',
description: '/docs/references/projects/update-email-template.md',
auth: [AuthType::ADMIN],
@@ -2335,6 +2402,7 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'deleteSmsTemplate',
description: '/docs/references/projects/delete-sms-template.md',
auth: [AuthType::ADMIN],
@@ -2380,11 +2448,12 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale')
});
App::delete('/v1/projects/:projectId/templates/email/:type/:locale')
->desc('Reset custom email template')
->desc('Delete custom email template')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk', new Method(
namespace: 'projects',
group: 'templates',
name: 'deleteEmailTemplate',
description: '/docs/references/projects/delete-email-template.md',
auth: [AuthType::ADMIN],
+45 -9
View File
@@ -31,6 +31,7 @@ App::get('/v1/proxy/rules')
->label('scope', 'rules.read')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'listRules',
description: '/docs/references/proxy/list-rules.md',
auth: [AuthType::ADMIN],
@@ -57,7 +58,7 @@ App::get('/v1/proxy/rules')
$queries[] = Query::search('search', $search);
}
$queries[] = Query::equal('projectInternalId', [$project->getInternalId()]);
$queries[] = Query::equal('projectInternalId', [$project->getSequence()]);
/**
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
@@ -105,6 +106,7 @@ App::get('/v1/proxy/rules/:ruleId')
->label('scope', 'rules.read')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'getRule',
description: '/docs/references/proxy/get-rule.md',
auth: [AuthType::ADMIN],
@@ -122,7 +124,7 @@ App::get('/v1/proxy/rules/:ruleId')
->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform) {
$rule = $dbForPlatform->getDocument('rules', $ruleId);
if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) {
if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) {
throw new Exception(Exception::RULE_NOT_FOUND);
}
@@ -142,6 +144,7 @@ App::delete('/v1/proxy/rules/:ruleId')
->label('audits.resource', 'rule/{request.ruleId}')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'deleteRule',
description: '/docs/references/proxy/delete-rule.md',
auth: [AuthType::ADMIN],
@@ -162,7 +165,7 @@ App::delete('/v1/proxy/rules/:ruleId')
->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform, Delete $queueForDeletes, Event $queueForEvents) {
$rule = $dbForPlatform->getDocument('rules', $ruleId);
if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) {
if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) {
throw new Exception(Exception::RULE_NOT_FOUND);
}
@@ -186,6 +189,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
->label('audits.resource', 'rule/{response.$id}')
->label('sdk', new Method(
namespace: 'proxy',
group: null,
name: 'updateRuleVerification',
description: '/docs/references/proxy/update-rule-verification.md',
auth: [AuthType::ADMIN],
@@ -206,15 +210,46 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
->action(function (string $ruleId, Response $response, Certificate $queueForCertificates, Event $queueForEvents, Document $project, Database $dbForPlatform, Log $log) {
$rule = $dbForPlatform->getDocument('rules', $ruleId);
if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) {
if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) {
throw new Exception(Exception::RULE_NOT_FOUND);
}
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if (!$targetCNAME->isKnown() || $targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
$targetCNAME = null;
switch ($rule->getAttribute('type', '')) {
case 'api':
// For example: fra.cloud.appwrite.io
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
break;
case 'redirect':
// For example: appwrite.network
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
break;
case 'deployment':
switch ($rule->getAttribute('deploymentResourceType', '')) {
case 'function':
// For example: fra.appwrite.run
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_FUNCTIONS', ''));
break;
case 'site':
// For example: appwrite.network
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', ''));
break;
default:
break;
}
// no break
default:
break;
}
$validators = [];
if (!is_null($targetCNAME)) {
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
}
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
}
@@ -256,7 +291,8 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
// Issue a TLS certificate when domain is verified
$queueForCertificates
->setDomain(new Document([
'domain' => $rule->getAttribute('domain')
'domain' => $rule->getAttribute('domain'),
'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')),
]))
->trigger();
+124 -81
View File
@@ -24,6 +24,7 @@ use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\NotFound as NotFoundException;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@@ -62,6 +63,7 @@ App::post('/v1/storage/buckets')
->label('audits.resource', 'bucket/{response.$id}')
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'createBucket',
description: '/docs/references/storage/create-bucket.md',
auth: [AuthType::KEY],
@@ -143,7 +145,7 @@ App::post('/v1/storage/buckets')
$bucket = $dbForProject->getDocument('buckets', $bucketId);
$dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity);
$dbForProject->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity);
} catch (DuplicateException) {
throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS);
}
@@ -164,6 +166,7 @@ App::get('/v1/storage/buckets')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'listBuckets',
description: '/docs/references/storage/list-buckets.md',
auth: [AuthType::KEY],
@@ -216,10 +219,15 @@ App::get('/v1/storage/buckets')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$buckets = $dbForProject->find('buckets', $queries);
$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.");
}
$response->dynamic(new Document([
'buckets' => $dbForProject->find('buckets', $queries),
'total' => $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT),
'buckets' => $buckets,
'total' => $total,
]), Response::MODEL_BUCKET_LIST);
});
@@ -230,6 +238,7 @@ App::get('/v1/storage/buckets/:bucketId')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'getBucket',
description: '/docs/references/storage/get-bucket.md',
auth: [AuthType::KEY],
@@ -264,6 +273,7 @@ App::put('/v1/storage/buckets/:bucketId')
->label('audits.resource', 'bucket/{response.$id}')
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'updateBucket',
description: '/docs/references/storage/update-bucket.md',
auth: [AuthType::KEY],
@@ -316,7 +326,7 @@ App::put('/v1/storage/buckets/:bucketId')
->setAttribute('compression', $compression)
->setAttribute('antivirus', $antivirus));
$dbForProject->updateCollection('bucket_' . $bucket->getInternalId(), $permissions, $fileSecurity);
$dbForProject->updateCollection('bucket_' . $bucket->getSequence(), $permissions, $fileSecurity);
$queueForEvents
->setParam('bucketId', $bucket->getId());
@@ -334,6 +344,7 @@ App::delete('/v1/storage/buckets/:bucketId')
->label('audits.resource', 'bucket/{request.bucketId}')
->label('sdk', new Method(
namespace: 'storage',
group: 'buckets',
name: 'deleteBucket',
description: '/docs/references/storage/delete-bucket.md',
auth: [AuthType::KEY],
@@ -387,17 +398,18 @@ App::post('/v1/storage/buckets/:bucketId/files')
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'createFile',
description: '/docs/references/storage/create-file.md',
type: MethodType::UPLOAD,
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
requestType: 'multipart/form-data',
responses: [
new SDKResponse(
code: Response::STATUS_CODE_CREATED,
model: Response::MODEL_FILE,
)
]
],
type: MethodType::UPLOAD,
requestType: ContentType::MULTIPART
))
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
->param('fileId', '', new CustomId(), 'File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
@@ -546,7 +558,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
$path = $deviceForFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION));
$path = str_ireplace($deviceForFiles->getRoot(), $deviceForFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
$metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)];
if (!$file->isEmpty()) {
@@ -640,7 +652,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
'$id' => $fileId,
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'bucketInternalId' => $bucket->getSequence(),
'name' => $fileName,
'path' => $path,
'signature' => $fileHash,
@@ -659,7 +671,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
'metadata' => $metadata,
]);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
$file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc);
} else {
$file = $file
->setAttribute('$permissions', $permissions)
@@ -684,7 +696,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file));
}
} else {
if ($file->isEmpty()) {
@@ -692,7 +704,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
'$id' => ID::custom($fileId),
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'bucketInternalId' => $bucket->getSequence(),
'name' => $fileName,
'path' => $path,
'signature' => '',
@@ -708,7 +720,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
]);
try {
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
$file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc);
} catch (NotFoundException) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
@@ -729,7 +741,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
}
try {
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file));
} catch (NotFoundException) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
@@ -756,6 +768,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'listFiles',
description: '/docs/references/storage/list-files.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -813,9 +826,9 @@ App::get('/v1/storage/buckets/:bucketId/files')
$fileId = $cursor->getValue();
if ($fileSecurity && !$valid) {
$cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
} else {
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
}
if ($cursorDocument->isEmpty()) {
@@ -829,14 +842,16 @@ App::get('/v1/storage/buckets/:bucketId/files')
try {
if ($fileSecurity && !$valid) {
$files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries);
$total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT);
$files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries);
$total = $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT);
} else {
$files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries));
$total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT));
$files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries));
$total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT));
}
} catch (NotFoundException) {
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.");
}
$response->dynamic(new Document([
@@ -853,6 +868,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFile',
description: '/docs/references/storage/get-file.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -886,9 +902,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId')
}
if ($fileSecurity && !$valid) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
} else {
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
}
if ($file->isEmpty()) {
@@ -909,6 +925,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
->label('cache.resource', 'file/{request.fileId}')
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFilePreview',
description: '/docs/references/storage/get-file-preview.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -926,7 +943,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true)
->param('height', 0, new Range(0, 4000), 'Resize preview image height, Pass an integer between 0 to 4000.', true)
->param('gravity', Image::GRAVITY_CENTER, new WhiteList(Image::getGravityTypes()), 'Image crop gravity. Can be one of ' . implode(",", Image::getGravityTypes()), true)
->param('quality', 100, new Range(0, 100), 'Preview image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
->param('quality', -1, new Range(-1, 100), 'Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.', true)
->param('borderWidth', 0, new Range(0, 100), 'Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.', true)
->param('borderColor', '', new HexColor(), 'Preview image border color. Use a valid HEX color, no # is needed for prefix.', true)
->param('borderRadius', 0, new Range(0, 4000), 'Preview image border radius in pixels. Pass an integer between 0 to 4000.', true)
@@ -934,12 +951,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
->param('rotation', 0, new Range(-360, 360), 'Preview image rotation in degrees. Pass an integer between -360 and 360.', true)
->param('background', '', new HexColor(), 'Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.', true)
->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', true)
// NOTE: this is only for the sdk generator and is not used in the action below and is utilised in `resources.php` for `resourceToken`.
->param('token', '', new Text(512), 'File token for accessing this file.', true)
->inject('response')
->inject('dbForProject')
->inject('resourceToken')
->inject('deviceForFiles')
->inject('deviceForLocal')
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal) {
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal) {
if (!\extension_loaded('imagick')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
@@ -954,7 +973,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId();
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence();
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
@@ -963,12 +982,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
}
if ($fileSecurity && !$valid && !$isToken) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
} else {
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
}
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) {
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@@ -985,7 +1004,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
$algorithm = $file->getAttribute('algorithm', Compression::NONE);
$cipher = $file->getAttribute('openSSLCipher');
$mime = $file->getAttribute('mimeType');
if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) {
if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', APP_STORAGE_READ_BUFFER)) {
if (!\in_array($mime, $inputs)) {
$path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default'];
} else {
@@ -1097,6 +1116,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFileDownload',
description: '/docs/references/storage/get-file-download.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -1111,12 +1131,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
))
->param('bucketId', '', new UID(), 'Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
->param('fileId', '', new UID(), 'File ID.')
// NOTE: this is only for the sdk generator and is not used in the action below and is utilised in `resources.php` for `resourceToken`.
->param('token', '', new Text(512), 'File token for accessing this file.', true)
->inject('request')
->inject('response')
->inject('dbForProject')
->inject('mode')
->inject('resourceToken')
->inject('deviceForFiles')
->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceForFiles) {
->action(function (string $bucketId, string $fileId, ?string $token, Request $request, Response $response, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) {
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -1127,17 +1150,22 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence();
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
if (!$fileSecurity && !$valid) {
if (!$fileSecurity && !$valid && !$isToken) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if ($fileSecurity && !$valid) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
} else {
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
}
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if ($file->isEmpty()) {
@@ -1150,13 +1178,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path);
}
$response
->setContentType($file->getAttribute('mimeType'))
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
->addHeader('X-Peak', \memory_get_peak_usage())
->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"')
;
$size = $file->getAttribute('sizeOriginal', 0);
$rangeHeader = $request->getHeader('range');
@@ -1165,7 +1186,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
$end = $request->getRangeEnd();
$unit = $request->getRangeUnit();
if ($end === null) {
if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) {
$end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1));
}
@@ -1180,6 +1201,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT);
}
$response
->setContentType($file->getAttribute('mimeType'))
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
->addHeader('X-Peak', \memory_get_peak_usage())
->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"')
;
$source = '';
if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt
$source = $deviceForFiles->read($path);
@@ -1213,12 +1241,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
if (!empty($source)) {
if (!empty($rangeHeader)) {
$response->send(substr($source, $start, ($end - $start + 1)));
return;
}
$response->send($source);
return;
}
if (!empty($rangeHeader)) {
$response->send($deviceForFiles->read($path, $start, ($end - $start + 1)));
return;
}
if ($size > APP_STORAGE_READ_BUFFER) {
@@ -1245,6 +1276,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'getFileView',
description: '/docs/references/storage/get-file-view.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -1259,12 +1291,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
))
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
->param('fileId', '', new UID(), 'File ID.')
// NOTE: this is only for the sdk generator and is not used in the action below and is utilised in `resources.php` for `resourceToken`.
->param('token', '', new Text(512), 'File token for accessing this file.', true)
->inject('response')
->inject('request')
->inject('dbForProject')
->inject('mode')
->inject('resourceToken')
->inject('deviceForFiles')
->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceForFiles) {
->action(function (string $bucketId, string $fileId, ?string $token, Response $response, Request $request, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) {
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
@@ -1274,17 +1309,22 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence();
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
if (!$fileSecurity && !$valid) {
if (!$fileSecurity && !$valid && !$isToken) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if ($fileSecurity && !$valid) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
} else {
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
}
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if ($file->isEmpty()) {
@@ -1305,15 +1345,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
$contentType = $file->getAttribute('mimeType');
}
$response
->setContentType($contentType)
->addHeader('Content-Security-Policy', 'script-src none;')
->addHeader('X-Content-Type-Options', 'nosniff')
->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"')
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
->addHeader('X-Peak', \memory_get_peak_usage())
;
$size = $file->getAttribute('sizeOriginal', 0);
$rangeHeader = $request->getHeader('range');
@@ -1322,8 +1353,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
$end = $request->getRangeEnd();
$unit = $request->getRangeUnit();
if ($end === null) {
$end = min(($start + 2000000 - 1), ($size - 1));
if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) {
$end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1));
}
if ($unit != 'bytes' || $start >= $end || $end >= $size) {
@@ -1337,6 +1368,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT);
}
$response
->setContentType($contentType)
->addHeader('Content-Security-Policy', 'script-src none;')
->addHeader('X-Content-Type-Options', 'nosniff')
->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"')
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
->addHeader('X-Peak', \memory_get_peak_usage())
;
$source = '';
if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt
$source = $deviceForFiles->read($path);
@@ -1370,6 +1410,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
if (!empty($source)) {
if (!empty($rangeHeader)) {
$response->send(substr($source, $start, ($end - $start + 1)));
return;
}
$response->send($source);
return;
@@ -1402,9 +1443,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push')
->groups(['api', 'storage'])
->label('scope', 'public')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', '*/*')
->label('sdk.methodType', 'location')
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
->param('fileId', '', new UID(), 'File ID.')
->param('jwt', '', new Text(2048, 0), 'JSON Web Token to validate', true)
@@ -1440,7 +1478,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
@@ -1460,14 +1498,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push')
$contentType = $file->getAttribute('mimeType');
}
$response
->setContentType($contentType)
->addHeader('Content-Security-Policy', 'script-src none;')
->addHeader('X-Content-Type-Options', 'nosniff')
->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"')
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
->addHeader('X-Peak', \memory_get_peak_usage());
$size = $file->getAttribute('sizeOriginal', 0);
$rangeHeader = $request->getHeader('range');
@@ -1476,8 +1506,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push')
$end = $request->getRangeEnd();
$unit = $request->getRangeUnit();
if ($end === null) {
$end = min(($start + 2000000 - 1), ($size - 1));
if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) {
$end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1));
}
if ($unit != 'bytes' || $start >= $end || $end >= $size) {
@@ -1491,6 +1521,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push')
->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT);
}
$response
->setContentType($contentType)
->addHeader('Content-Security-Policy', 'script-src none;')
->addHeader('X-Content-Type-Options', 'nosniff')
->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"')
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
->addHeader('X-Peak', \memory_get_peak_usage());
$source = '';
if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt
$source = $deviceForFiles->read($path);
@@ -1524,6 +1562,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push')
if (!empty($source)) {
if (!empty($rangeHeader)) {
$response->send(substr($source, $start, ($end - $start + 1)));
return;
}
$response->send($source);
return;
@@ -1565,6 +1604,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'updateFile',
description: '/docs/references/storage/update-file.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -1603,7 +1643,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
}
// Read permission should not be required for update
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
@@ -1649,9 +1689,9 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
try {
if ($fileSecurity && !$valid) {
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
$file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file);
} else {
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
$file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file));
}
} catch (NotFoundException) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
@@ -1679,6 +1719,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'storage',
group: 'files',
name: 'deleteFile',
description: '/docs/references/storage/delete-file.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -1716,7 +1757,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
}
// Read permission should not be required for delete
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
@@ -1746,9 +1787,9 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
try {
if ($fileSecurity && !$valid) {
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId);
} else {
$deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId));
$deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId));
}
} catch (NotFoundException) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
@@ -1779,6 +1820,7 @@ App::get('/v1/storage/usage')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: null,
name: 'getUsage',
description: '/docs/references/storage/get-usage.md',
auth: [AuthType::ADMIN],
@@ -1865,6 +1907,7 @@ App::get('/v1/storage/:bucketId/usage')
->label('resourceType', RESOURCE_TYPE_BUCKETS)
->label('sdk', new Method(
namespace: 'storage',
group: null,
name: 'getBucketUsage',
description: '/docs/references/storage/get-bucket-usage.md',
auth: [AuthType::ADMIN],
@@ -1894,14 +1937,14 @@ App::get('/v1/storage/:bucketId/usage')
$stats = $usage = [];
$days = $periods[$range];
$metrics = [
str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES),
str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE),
str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED),
str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES),
str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE),
str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED),
];
Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) {
foreach ($metrics as $metric) {
$db = ($metric === str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED))
$db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED))
? $dbForLogs
: $dbForProject;
+50 -28
View File
@@ -33,6 +33,7 @@ use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Authorization as AuthorizationException;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@@ -63,6 +64,7 @@ App::post('/v1/teams')
->label('audits.resource', 'team/{response.$id}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'create',
description: '/docs/references/teams/create-team.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -121,9 +123,9 @@ App::post('/v1/teams')
Permission::delete(Role::team($team->getId(), 'owner')),
],
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'teamId' => $team->getId(),
'teamInternalId' => $team->getInternalId(),
'teamInternalId' => $team->getSequence(),
'roles' => $roles,
'invited' => DateTime::now(),
'joined' => DateTime::now(),
@@ -153,6 +155,7 @@ App::get('/v1/teams')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'list',
description: '/docs/references/teams/list-teams.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -205,9 +208,12 @@ App::get('/v1/teams')
}
$filterQueries = Query::groupByType($queries)['filters'];
$results = $dbForProject->find('teams', $queries);
$total = $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT);
try {
$results = $dbForProject->find('teams', $queries);
$total = $dbForProject->count('teams', $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.");
}
$response->dynamic(new Document([
'teams' => $results,
@@ -221,6 +227,7 @@ App::get('/v1/teams/:teamId')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'get',
description: '/docs/references/teams/get-team.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -251,6 +258,7 @@ App::get('/v1/teams/:teamId/prefs')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'getPrefs',
description: '/docs/references/teams/get-team-prefs.md',
auth: [AuthType::SESSION, AuthType::JWT],
@@ -286,6 +294,7 @@ App::put('/v1/teams/:teamId')
->label('audits.resource', 'team/{response.$id}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'updateName',
description: '/docs/references/teams/update-team-name.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -314,9 +323,7 @@ App::put('/v1/teams/:teamId')
->setAttribute('name', $name)
->setAttribute('search', implode(' ', [$teamId, $name]));
$team = $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $team) {
return $dbForProject->updateDocument('teams', $team->getId(), $team);
});
$team = $dbForProject->updateDocument('teams', $team->getId(), $team);
$queueForEvents->setParam('teamId', $team->getId());
@@ -333,6 +340,7 @@ App::put('/v1/teams/:teamId/prefs')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'updatePrefs',
description: '/docs/references/teams/update-team-prefs.md',
auth: [AuthType::SESSION, AuthType::JWT],
@@ -372,6 +380,7 @@ App::delete('/v1/teams/:teamId')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'teams',
name: 'delete',
description: '/docs/references/teams/delete-team.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -430,6 +439,7 @@ App::post('/v1/teams/:teamId/memberships')
->label('audits.userId', '{request.userId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'createMembership',
description: '/docs/references/teams/create-team-membership.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -585,8 +595,8 @@ App::post('/v1/teams/:teamId/memberships')
}
$membership = $dbForProject->findOne('memberships', [
Query::equal('userInternalId', [$invitee->getInternalId()]),
Query::equal('teamInternalId', [$team->getInternalId()]),
Query::equal('userInternalId', [$invitee->getSequence()]),
Query::equal('teamInternalId', [$team->getSequence()]),
]);
$secret = Auth::tokenGenerator();
@@ -602,9 +612,9 @@ App::post('/v1/teams/:teamId/memberships')
Permission::delete(Role::team($team->getId(), 'owner')),
],
'userId' => $invitee->getId(),
'userInternalId' => $invitee->getInternalId(),
'userInternalId' => $invitee->getSequence(),
'teamId' => $team->getId(),
'teamInternalId' => $team->getInternalId(),
'teamInternalId' => $team->getSequence(),
'roles' => $roles,
'invited' => DateTime::now(),
'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null,
@@ -797,6 +807,7 @@ App::get('/v1/teams/:teamId/memberships')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'listMemberships',
description: '/docs/references/teams/list-team-members.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -831,7 +842,7 @@ App::get('/v1/teams/:teamId/memberships')
}
// Set internal queries
$queries[] = Query::equal('teamInternalId', [$team->getInternalId()]);
$queries[] = Query::equal('teamInternalId', [$team->getSequence()]);
/**
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
@@ -860,17 +871,20 @@ App::get('/v1/teams/:teamId/memberships')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$memberships = $dbForProject->find(
collection: 'memberships',
queries: $queries,
);
$total = $dbForProject->count(
collection: 'memberships',
queries: $filterQueries,
max: 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.");
}
$memberships = $dbForProject->find(
collection: 'memberships',
queries: $queries,
);
$total = $dbForProject->count(
collection: 'memberships',
queries: $filterQueries,
max: APP_LIMIT_COUNT
);
$memberships = array_filter($memberships, fn (Document $membership) => !empty($membership->getAttribute('userId')));
@@ -935,6 +949,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'getMembership',
description: '/docs/references/teams/get-team-member.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -1021,6 +1036,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'updateMembership',
description: '/docs/references/teams/update-team-membership.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -1074,7 +1090,10 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
// Quick check: fetch up to 2 owners to determine if only one exists
$ownersCount = $dbForProject->count(
collection: 'memberships',
queries: [Query::contains('roles', ['owner'])],
queries: [
Query::contains('roles', ['owner']),
Query::equal('teamInternalId', [$team->getSequence()])
],
max: 2
);
@@ -1124,6 +1143,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->label('audits.userId', '{request.userId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'updateMembershipStatus',
description: '/docs/references/teams/update-team-membership-status.md',
auth: [AuthType::SESSION, AuthType::JWT],
@@ -1160,7 +1180,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
throw new Exception(Exception::TEAM_NOT_FOUND);
}
if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) {
if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) {
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
}
@@ -1177,7 +1197,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
$user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user
}
if ($membership->getAttribute('userInternalId') !== $user->getInternalId()) {
if ($membership->getAttribute('userInternalId') !== $user->getSequence()) {
throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')');
}
@@ -1209,7 +1229,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
Permission::delete(Role::user($user->getId())),
],
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'provider' => Auth::SESSION_PROVIDER_EMAIL,
'providerUid' => $user->getAttribute('email'),
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
@@ -1281,6 +1301,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk', new Method(
namespace: 'teams',
group: 'memberships',
name: 'deleteMembership',
description: '/docs/references/teams/delete-team-membership.md',
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
@@ -1317,7 +1338,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
throw new Exception(Exception::TEAM_NOT_FOUND);
}
if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) {
if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) {
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
}
@@ -1351,6 +1372,7 @@ App::get('/v1/teams/:teamId/logs')
->label('scope', 'teams.read')
->label('sdk', new Method(
namespace: 'teams',
group: 'logs',
name: 'listLogs',
description: '/docs/references/teams/get-team-logs.md',
auth: [AuthType::ADMIN],
+86 -23
View File
@@ -9,6 +9,8 @@ use Appwrite\Auth\Validator\PasswordDictionary;
use Appwrite\Auth\Validator\PasswordHistory;
use Appwrite\Auth\Validator\PersonalData;
use Appwrite\Auth\Validator\Phone;
use Appwrite\Deletes\Identities as DeleteIdentities;
use Appwrite\Deletes\Targets as DeleteTargets;
use Appwrite\Detector\Detector;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
@@ -34,6 +36,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@@ -137,7 +140,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
Permission::delete(Role::user($user->getId())),
],
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'providerType' => 'email',
'identifier' => $email,
]));
@@ -161,7 +164,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
Permission::delete(Role::user($user->getId())),
],
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'providerType' => 'sms',
'identifier' => $phone,
]));
@@ -192,6 +195,7 @@ App::post('/v1/users')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'create',
description: '/docs/references/users/create-user.md',
auth: [AuthType::KEY],
@@ -226,6 +230,7 @@ App::post('/v1/users/bcrypt')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createBcryptUser',
description: '/docs/references/users/create-bcrypt-user.md',
auth: [AuthType::KEY],
@@ -260,6 +265,7 @@ App::post('/v1/users/md5')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createMD5User',
description: '/docs/references/users/create-md5-user.md',
auth: [AuthType::KEY],
@@ -294,6 +300,7 @@ App::post('/v1/users/argon2')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createArgon2User',
description: '/docs/references/users/create-argon2-user.md',
auth: [AuthType::KEY],
@@ -328,6 +335,7 @@ App::post('/v1/users/sha')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createSHAUser',
description: '/docs/references/users/create-sha-user.md',
auth: [AuthType::KEY],
@@ -369,6 +377,7 @@ App::post('/v1/users/phpass')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createPHPassUser',
description: '/docs/references/users/create-phpass-user.md',
auth: [AuthType::KEY],
@@ -403,6 +412,7 @@ App::post('/v1/users/scrypt')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createScryptUser',
description: '/docs/references/users/create-scrypt-user.md',
auth: [AuthType::KEY],
@@ -450,6 +460,7 @@ App::post('/v1/users/scrypt-modified')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'createScryptModifiedUser',
description: '/docs/references/users/create-scrypt-modified-user.md',
auth: [AuthType::KEY],
@@ -488,6 +499,7 @@ App::post('/v1/users/:userId/targets')
->label('scope', 'targets.write')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'createTarget',
description: '/docs/references/users/create-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@@ -552,10 +564,10 @@ App::post('/v1/users/:userId/targets')
Permission::delete(Role::user($user->getId())),
],
'providerId' => empty($provider->getId()) ? null : $provider->getId(),
'providerInternalId' => $provider->isEmpty() ? null : $provider->getInternalId(),
'providerInternalId' => $provider->isEmpty() ? null : $provider->getSequence(),
'providerType' => $providerType,
'userId' => $userId,
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'identifier' => $identifier,
'name' => ($name !== '') ? $name : null,
]));
@@ -579,6 +591,7 @@ App::get('/v1/users')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'list',
description: '/docs/references/users/list-users.md',
auth: [AuthType::KEY],
@@ -631,10 +644,15 @@ App::get('/v1/users')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$users = $dbForProject->find('users', $queries);
$total = $dbForProject->count('users', $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.");
}
$response->dynamic(new Document([
'users' => $dbForProject->find('users', $queries),
'total' => $dbForProject->count('users', $filterQueries, APP_LIMIT_COUNT),
'users' => $users,
'total' => $total,
]), Response::MODEL_USER_LIST);
});
@@ -644,6 +662,7 @@ App::get('/v1/users/:userId')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'get',
description: '/docs/references/users/get-user.md',
auth: [AuthType::KEY],
@@ -674,6 +693,7 @@ App::get('/v1/users/:userId/prefs')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'getPrefs',
description: '/docs/references/users/get-user-prefs.md',
auth: [AuthType::KEY],
@@ -706,6 +726,7 @@ App::get('/v1/users/:userId/targets/:targetId')
->label('scope', 'targets.read')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'getTarget',
description: '/docs/references/users/get-user-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@@ -743,6 +764,7 @@ App::get('/v1/users/:userId/sessions')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'listSessions',
description: '/docs/references/users/list-user-sessions.md',
auth: [AuthType::KEY],
@@ -789,6 +811,7 @@ App::get('/v1/users/:userId/memberships')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'memberships',
name: 'listMemberships',
description: '/docs/references/users/list-user-memberships.md',
auth: [AuthType::KEY],
@@ -823,7 +846,7 @@ App::get('/v1/users/:userId/memberships')
}
// Set internal queries
$queries[] = Query::equal('userInternalId', [$user->getInternalId()]);
$queries[] = Query::equal('userInternalId', [$user->getSequence()]);
$memberships = array_map(function ($membership) use ($dbForProject, $user) {
$team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId'));
@@ -848,6 +871,7 @@ App::get('/v1/users/:userId/logs')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'logs',
name: 'listLogs',
description: '/docs/references/users/list-user-logs.md',
auth: [AuthType::KEY],
@@ -886,7 +910,7 @@ App::get('/v1/users/:userId/logs')
$audit = new Audit($dbForProject);
$logs = $audit->getLogsByUser($user->getInternalId(), $queries);
$logs = $audit->getLogsByUser($user->getSequence(), $queries);
$output = [];
@@ -933,7 +957,7 @@ App::get('/v1/users/:userId/logs')
}
$response->dynamic(new Document([
'total' => $audit->countLogsByUser($user->getInternalId(), $queries),
'total' => $audit->countLogsByUser($user->getSequence(), $queries),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
@@ -944,6 +968,7 @@ App::get('/v1/users/:userId/targets')
->label('scope', 'targets.read')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'listTargets',
description: '/docs/references/users/list-user-targets.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@@ -996,10 +1021,15 @@ App::get('/v1/users/:userId/targets')
$cursor->setValue($cursorDocument);
}
try {
$targets = $dbForProject->find('targets', $queries);
$total = $dbForProject->count('targets', $queries, 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.");
}
$response->dynamic(new Document([
'targets' => $dbForProject->find('targets', $queries),
'total' => $dbForProject->count('targets', $queries, APP_LIMIT_COUNT),
'targets' => $targets,
'total' => $total,
]), Response::MODEL_TARGET_LIST);
});
@@ -1009,6 +1039,7 @@ App::get('/v1/users/identities')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: 'identities',
name: 'listIdentities',
description: '/docs/references/users/list-identities.md',
auth: [AuthType::KEY],
@@ -1061,10 +1092,15 @@ App::get('/v1/users/identities')
}
$filterQueries = Query::groupByType($queries)['filters'];
try {
$identities = $dbForProject->find('identities', $queries);
$total = $dbForProject->count('identities', $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.");
}
$response->dynamic(new Document([
'identities' => $dbForProject->find('identities', $queries),
'total' => $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT),
'identities' => $identities,
'total' => $total,
]), Response::MODEL_IDENTITY_LIST);
});
@@ -1078,6 +1114,7 @@ App::patch('/v1/users/:userId/status')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateStatus',
description: '/docs/references/users/update-user-status.md',
auth: [AuthType::KEY],
@@ -1118,6 +1155,7 @@ App::put('/v1/users/:userId/labels')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateLabels',
description: '/docs/references/users/update-user-labels.md',
auth: [AuthType::KEY],
@@ -1160,6 +1198,7 @@ App::patch('/v1/users/:userId/verification/phone')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePhoneVerification',
description: '/docs/references/users/update-user-phone-verification.md',
auth: [AuthType::KEY],
@@ -1201,6 +1240,7 @@ App::patch('/v1/users/:userId/name')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateName',
description: '/docs/references/users/update-user-name.md',
auth: [AuthType::KEY],
@@ -1243,6 +1283,7 @@ App::patch('/v1/users/:userId/password')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePassword',
description: '/docs/references/users/update-user-password.md',
auth: [AuthType::KEY],
@@ -1325,6 +1366,7 @@ App::patch('/v1/users/:userId/email')
->label('audits.userId', '{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateEmail',
description: '/docs/references/users/update-user-email.md',
auth: [AuthType::KEY],
@@ -1354,7 +1396,7 @@ App::patch('/v1/users/:userId/email')
// Makes sure this email is not already used in another identity
$identityWithMatchingEmail = $dbForProject->findOne('identities', [
Query::equal('providerEmail', [$email]),
Query::notEqual('userInternalId', $user->getInternalId()),
Query::notEqual('userInternalId', $user->getSequence()),
]);
if (!$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
@@ -1398,7 +1440,7 @@ App::patch('/v1/users/:userId/email')
Permission::delete(Role::user($user->getId())),
],
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'providerType' => 'email',
'identifier' => $email,
]));
@@ -1424,6 +1466,7 @@ App::patch('/v1/users/:userId/phone')
->label('audits.resource', 'user/{response.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePhone',
description: '/docs/references/users/update-user-phone.md',
auth: [AuthType::KEY],
@@ -1486,7 +1529,7 @@ App::patch('/v1/users/:userId/phone')
Permission::delete(Role::user($user->getId())),
],
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'providerType' => 'sms',
'identifier' => $number,
]));
@@ -1513,6 +1556,7 @@ App::patch('/v1/users/:userId/verification')
->label('audits.userId', '{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateEmailVerification',
description: '/docs/references/users/update-user-email-verification.md',
auth: [AuthType::KEY],
@@ -1550,6 +1594,7 @@ App::patch('/v1/users/:userId/prefs')
->label('scope', 'users.write')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updatePrefs',
description: '/docs/references/users/update-user-prefs.md',
auth: [AuthType::KEY],
@@ -1590,6 +1635,7 @@ App::patch('/v1/users/:userId/targets/:targetId')
->label('scope', 'targets.write')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'updateTarget',
description: '/docs/references/users/update-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@@ -1665,7 +1711,7 @@ App::patch('/v1/users/:userId/targets/:targetId')
$target
->setAttribute('providerId', $provider->getId())
->setAttribute('providerInternalId', $provider->getInternalId());
->setAttribute('providerInternalId', $provider->getSequence());
}
if ($name) {
@@ -1694,6 +1740,7 @@ App::patch('/v1/users/:userId/mfa')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'updateMfa',
description: '/docs/references/users/update-user-mfa.md',
auth: [AuthType::KEY],
@@ -1733,6 +1780,7 @@ App::get('/v1/users/:userId/mfa/factors')
->label('usage.metric', 'users.{scope}.requests.read')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'listMfaFactors',
description: '/docs/references/users/list-mfa-factors.md',
auth: [AuthType::KEY],
@@ -1771,6 +1819,7 @@ App::get('/v1/users/:userId/mfa/recovery-codes')
->label('usage.metric', 'users.{scope}.requests.read')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'getMfaRecoveryCodes',
description: '/docs/references/users/get-mfa-recovery-codes.md',
auth: [AuthType::KEY],
@@ -1815,6 +1864,7 @@ App::patch('/v1/users/:userId/mfa/recovery-codes')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'createMfaRecoveryCodes',
description: '/docs/references/users/create-mfa-recovery-codes.md',
auth: [AuthType::KEY],
@@ -1856,7 +1906,7 @@ App::patch('/v1/users/:userId/mfa/recovery-codes')
});
App::put('/v1/users/:userId/mfa/recovery-codes')
->desc('Regenerate MFA recovery codes')
->desc('Update MFA recovery codes (regenerate)')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.mfa.recovery-codes')
->label('scope', 'users.write')
@@ -1866,6 +1916,7 @@ App::put('/v1/users/:userId/mfa/recovery-codes')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'updateMfaRecoveryCodes',
description: '/docs/references/users/update-mfa-recovery-codes.md',
auth: [AuthType::KEY],
@@ -1916,6 +1967,7 @@ App::delete('/v1/users/:userId/mfa/authenticators/:type')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk', new Method(
namespace: 'users',
group: 'mfa',
name: 'deleteMfaAuthenticator',
description: '/docs/references/users/delete-mfa-authenticator.md',
auth: [AuthType::KEY],
@@ -1963,6 +2015,7 @@ App::post('/v1/users/:userId/sessions')
->label('usage.metric', 'sessions.{scope}.requests.create')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'createSession',
description: '/docs/references/users/create-session.md',
auth: [AuthType::KEY],
@@ -1998,7 +2051,7 @@ App::post('/v1/users/:userId/sessions')
[
'$id' => ID::unique(),
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'provider' => Auth::SESSION_PROVIDER_SERVER,
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'userAgent' => $request->getUserAgent('UNKNOWN'),
@@ -2047,6 +2100,7 @@ App::post('/v1/users/:userId/tokens')
->label('audits.resource', 'user/{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'createToken',
description: '/docs/references/users/create-token.md',
auth: [AuthType::KEY],
@@ -2077,7 +2131,7 @@ App::post('/v1/users/:userId/tokens')
$token = new Document([
'$id' => ID::unique(),
'userId' => $user->getId(),
'userInternalId' => $user->getInternalId(),
'userInternalId' => $user->getSequence(),
'type' => Auth::TOKEN_TYPE_GENERIC,
'secret' => Auth::hash($secret),
'expire' => $expire,
@@ -2109,6 +2163,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
->label('audits.resource', 'user/{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'deleteSession',
description: '/docs/references/users/delete-user-session.md',
auth: [AuthType::KEY],
@@ -2159,6 +2214,7 @@ App::delete('/v1/users/:userId/sessions')
->label('audits.resource', 'user/{user.$id}')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'deleteSessions',
description: '/docs/references/users/delete-user-sessions.md',
auth: [AuthType::KEY],
@@ -2208,6 +2264,7 @@ App::delete('/v1/users/:userId')
->label('audits.resource', 'user/{request.userId}')
->label('sdk', new Method(
namespace: 'users',
group: 'users',
name: 'delete',
description: '/docs/references/users/delete.md',
auth: [AuthType::KEY],
@@ -2236,6 +2293,8 @@ App::delete('/v1/users/:userId')
$clone = clone $user;
$dbForProject->deleteDocument('users', $userId);
DeleteIdentities::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()]));
DeleteTargets::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()]));
$queueForDeletes
->setType(DELETE_TYPE_DOCUMENT)
@@ -2257,6 +2316,7 @@ App::delete('/v1/users/:userId/targets/:targetId')
->label('scope', 'targets.write')
->label('sdk', new Method(
namespace: 'users',
group: 'targets',
name: 'deleteTarget',
description: '/docs/references/users/delete-target.md',
auth: [AuthType::KEY, AuthType::ADMIN],
@@ -2314,6 +2374,7 @@ App::delete('/v1/users/identities/:identityId')
->label('audits.resource', 'identity/{request.$identityId}')
->label('sdk', new Method(
namespace: 'users',
group: 'identities',
name: 'deleteIdentity',
description: '/docs/references/users/delete-identity.md',
auth: [AuthType::KEY],
@@ -2353,6 +2414,7 @@ App::post('/v1/users/:userId/jwts')
->label('scope', 'users.write')
->label('sdk', new Method(
namespace: 'users',
group: 'sessions',
name: 'createJWT',
description: '/docs/references/users/create-user-jwt.md',
auth: [AuthType::KEY],
@@ -2408,6 +2470,7 @@ App::get('/v1/users/usage')
->label('scope', 'users.read')
->label('sdk', new Method(
namespace: 'users',
group: null,
name: 'getUsage',
description: '/docs/references/users/get-usage.md',
auth: [AuthType::ADMIN],
+37 -23
View File
@@ -19,6 +19,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@@ -77,11 +78,11 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
$resourceCollection = $resourceType === "function" ? 'functions' : 'sites';
$resourceId = $repository->getAttribute('resourceId');
$resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId));
$resourceInternalId = $resource->getInternalId();
$resourceInternalId = $resource->getSequence();
$deploymentId = ID::unique();
$repositoryId = $repository->getId();
$repositoryInternalId = $repository->getInternalId();
$repositoryInternalId = $repository->getSequence();
$providerRepositoryId = $repository->getAttribute('providerRepositoryId');
$installationId = $repository->getAttribute('installationId');
$installationInternalId = $repository->getAttribute('installationInternalId');
@@ -156,7 +157,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
],
'installationInternalId' => $installationInternalId,
'installationId' => $installationId,
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'projectId' => $project->getId(),
'providerRepositoryId' => $providerRepositoryId,
'providerBranch' => $providerBranch,
@@ -251,13 +252,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
'providerCommitUrl' => $providerCommitUrl,
'providerCommentId' => \strval($latestCommentId),
'providerBranch' => $providerBranch,
'search' => implode(' ', [$deploymentId, $resource->getAttribute('entrypoint', '')]),
'activate' => $activate,
])));
$resource = $resource
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentInternalId', $deployment->getSequence())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource));
@@ -273,12 +273,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
fn () => $dbForPlatform->createDocument('rules', new Document([
'$id' => $ruleId,
'projectId' => $project->getId(),
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'domain' => $domain,
'type' => 'deployment',
'trigger' => 'deployment',
'deploymentId' => $deployment->getId(),
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentInternalId' => $deployment->getSequence(),
'deploymentResourceType' => 'site',
'deploymentResourceId' => $resourceId,
'deploymentResourceInternalId' => $resourceInternalId,
@@ -300,12 +300,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
fn () => $dbForPlatform->createDocument('rules', new Document([
'$id' => $ruleId,
'projectId' => $project->getId(),
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'domain' => $domain,
'type' => 'deployment',
'trigger' => 'deployment',
'deploymentId' => $deployment->getId(),
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentInternalId' => $deployment->getSequence(),
'deploymentResourceType' => 'site',
'deploymentResourceId' => $resourceId,
'deploymentResourceInternalId' => $resourceInternalId,
@@ -331,12 +331,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
fn () => $dbForPlatform->createDocument('rules', new Document([
'$id' => $ruleId,
'projectId' => $project->getId(),
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'domain' => $domain,
'type' => 'deployment',
'trigger' => 'deployment',
'deploymentId' => $deployment->getId(),
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentInternalId' => $deployment->getSequence(),
'deploymentResourceType' => 'site',
'deploymentResourceId' => $resourceId,
'deploymentResourceInternalId' => $resourceInternalId,
@@ -397,12 +397,13 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
};
App::get('/v1/vcs/github/authorize')
->desc('Install GitHub app')
->desc('Create GitHub app installation')
->groups(['api', 'vcs'])
->label('scope', 'vcs.read')
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'createGitHubInstallation',
description: '/docs/references/vcs/create-github-installation.md',
auth: [AuthType::ADMIN],
@@ -446,7 +447,7 @@ App::get('/v1/vcs/github/authorize')
});
App::get('/v1/vcs/github/callback')
->desc('Capture installation and authorization from GitHub app')
->desc('Get installation and authorization from GitHub app')
->groups(['api', 'vcs'])
->label('scope', 'public')
->label('error', __DIR__ . '/../../views/general/error.phtml')
@@ -502,7 +503,7 @@ App::get('/v1/vcs/github/callback')
$github->initializeVariables($providerInstallationId, $privateKey, $githubAppId);
$owner = $github->getOwnerName($providerInstallationId) ?? '';
$projectInternalId = $project->getInternalId();
$projectInternalId = $project->getSequence();
$installation = $dbForPlatform->findOne('installations', [
Query::equal('providerInstallationId', [$providerInstallationId]),
@@ -584,6 +585,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'getRepositoryContents',
description: '/docs/references/vcs/get-repository-contents.md',
auth: [AuthType::ADMIN],
@@ -651,6 +653,7 @@ App::post('/v1/vcs/github/installations/:installationId/detections')
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'createRepositoryDetection',
description: '/docs/references/vcs/create-repository-detection.md',
auth: [AuthType::ADMIN],
@@ -808,6 +811,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'listRepositories',
description: '/docs/references/vcs/list-repositories.md',
auth: [AuthType::ADMIN],
@@ -959,6 +963,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories')
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'createRepository',
description: '/docs/references/vcs/create-repository.md',
auth: [AuthType::ADMIN],
@@ -994,7 +999,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories')
if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) {
$identity = $dbForPlatform->findOne('identities', [
Query::equal('provider', ['github']),
Query::equal('userInternalId', [$user->getInternalId()]),
Query::equal('userInternalId', [$user->getSequence()]),
]);
if ($identity->isEmpty()) {
throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
@@ -1071,6 +1076,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'getRepository',
description: '/docs/references/vcs/get-repository.md',
auth: [AuthType::ADMIN],
@@ -1125,6 +1131,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'listRepositoryBranches',
description: '/docs/references/vcs/list-repository-branches.md',
auth: [AuthType::ADMIN],
@@ -1239,7 +1246,7 @@ App::post('/v1/vcs/github/events')
foreach ($installations as $installation) {
$repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [
Query::equal('installationInternalId', [$installation->getInternalId()]),
Query::equal('installationInternalId', [$installation->getSequence()]),
Query::limit(1000)
]));
@@ -1318,6 +1325,7 @@ App::get('/v1/vcs/installations')
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'listInstallations',
description: '/docs/references/vcs/list-installations.md',
auth: [AuthType::ADMIN],
@@ -1341,7 +1349,7 @@ App::get('/v1/vcs/installations')
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
$queries[] = Query::equal('projectInternalId', [$project->getInternalId()]);
$queries[] = Query::equal('projectInternalId', [$project->getSequence()]);
if (!empty($search)) {
$queries[] = Query::search('search', $search);
@@ -1373,9 +1381,12 @@ App::get('/v1/vcs/installations')
}
$filterQueries = Query::groupByType($queries)['filters'];
$results = $dbForPlatform->find('installations', $queries);
$total = $dbForPlatform->count('installations', $filterQueries, APP_LIMIT_COUNT);
try {
$results = $dbForPlatform->find('installations', $queries);
$total = $dbForPlatform->count('installations', $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.");
}
$response->dynamic(new Document([
'installations' => $results,
@@ -1389,6 +1400,7 @@ App::get('/v1/vcs/installations/:installationId')
->label('scope', 'vcs.read')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'getInstallation',
description: '/docs/references/vcs/get-installation.md',
auth: [AuthType::ADMIN],
@@ -1410,7 +1422,7 @@ App::get('/v1/vcs/installations/:installationId')
throw new Exception(Exception::INSTALLATION_NOT_FOUND);
}
if ($installation->getAttribute('projectInternalId') !== $project->getInternalId()) {
if ($installation->getAttribute('projectInternalId') !== $project->getSequence()) {
throw new Exception(Exception::INSTALLATION_NOT_FOUND);
}
@@ -1423,6 +1435,7 @@ App::delete('/v1/vcs/installations/:installationId')
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'installations',
name: 'deleteInstallation',
description: '/docs/references/vcs/delete-installation.md',
auth: [AuthType::ADMIN],
@@ -1458,11 +1471,12 @@ App::delete('/v1/vcs/installations/:installationId')
});
App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositoryId')
->desc('Authorize external deployment')
->desc('Update external deployment (authorize)')
->groups(['api', 'vcs'])
->label('scope', 'vcs.write')
->label('sdk', new Method(
namespace: 'vcs',
group: 'repositories',
name: 'updateExternalDeployments',
description: '/docs/references/vcs/update-external-deployments.md',
auth: [AuthType::ADMIN],
@@ -1491,7 +1505,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor
}
$repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [
Query::equal('projectInternalId', [$project->getInternalId()])
Query::equal('projectInternalId', [$project->getSequence()])
]));
if ($repository->isEmpty()) {
+85 -51
View File
@@ -79,11 +79,18 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', '');
if ($rule->isEmpty()) {
if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '') || $host === System::getEnv('_APP_DOMAIN_SITES', '')) {
$appDomainFunctionsFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
$appDomainFunctions = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
$appDomainSites = System::getEnv('_APP_DOMAIN_SITES', '');
if (!empty($appDomainFunctionsFallback) && \str_ends_with($host, $appDomainFunctionsFallback)) {
$appDomainFunctions = $appDomainFunctionsFallback;
}
if ($host === $appDomainFunctions || $host === $appDomainSites) {
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.', view: $errorView);
}
if (\str_ends_with($host, System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) || \str_ends_with($host, System::getEnv('_APP_DOMAIN_SITES', ''))) {
if (\str_ends_with($host, $appDomainFunctions) || \str_ends_with($host, $appDomainSites)) {
$exception = new AppwriteException(AppwriteException::RULE_NOT_FOUND, 'This domain is not connected to any Appwrite resources. Visit domains tab under function/site settings to configure it.', view: $errorView);
$exception->addCTA('Start with this domain', $url . '/console');
@@ -142,7 +149,31 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$dbForProject = $getProjectDB($project);
/** @var Document $deployment */
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId')));
if (!empty($rule->getAttribute('deploymentId', ''))) {
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId')));
} else {
// 1.6.x DB schema compatibility
// TODO: Make sure deploymentId is never empty, and remove this code
// Check if site or function; should never be site, but better safe than sorry
// Attempts to use attribute from both schemas (1.6 and 1.7)
$resourceType = $rule->getAttribute('deploymentResourceType', $rule->getAttribute('resourceType', ''));
// ID of site or function
$resourceId = $rule->getAttribute('deploymentResourceId', '');
// Document of site or function
$resource = $resourceType === 'function' ?
Authorization::skip(fn () => $dbForProject->getDocument('functions', $resourceId)) :
Authorization::skip(fn () => $dbForProject->getDocument('sites', $resourceId));
// ID of active deployments
// Attempts to use attribute from both schemas (1.6 and 1.7)
$activeDeploymentId = $resource->getAttribute('deploymentId', $resource->getAttribute('deployment', ''));
// Get deployment document, as intended originally
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId));
}
if ($deployment->getAttribute('resourceType', '') === 'functions') {
$type = 'function';
@@ -360,9 +391,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$execution = new Document([
'$id' => $executionId,
'$permissions' => [],
'resourceInternalId' => $resource->getInternalId(),
'resourceInternalId' => $resource->getSequence(),
'resourceId' => $resource->getId(),
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentInternalId' => $deployment->getSequence(),
'deploymentId' => $deployment->getId(),
'responseStatusCode' => 0,
'responseHeaders' => [],
@@ -421,16 +452,33 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
$endpoint = $protocol . '://' . $hostname . "/v1";
// Appwrite vars
if ($type === 'function') {
$vars = \array_merge($vars, [
'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint,
'APPWRITE_FUNCTION_ID' => $resource->getId(),
'APPWRITE_FUNCTION_NAME' => $resource->getAttribute('name'),
'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(),
'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(),
'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '',
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '',
'APPWRITE_FUNCTION_CPUS' => $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT,
'APPWRITE_FUNCTION_MEMORY' => $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT,
]);
} elseif ($type === 'site') {
$vars = \array_merge($vars, [
'APPWRITE_SITE_API_ENDPOINT' => $endpoint,
'APPWRITE_SITE_ID' => $resource->getId(),
'APPWRITE_SITE_NAME' => $resource->getAttribute('name'),
'APPWRITE_SITE_DEPLOYMENT' => $deployment->getId(),
'APPWRITE_SITE_PROJECT_ID' => $project->getId(),
'APPWRITE_SITE_RUNTIME_NAME' => $runtime['name'] ?? '',
'APPWRITE_SITE_RUNTIME_VERSION' => $runtime['version'] ?? '',
'APPWRITE_SITE_CPUS' => $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT,
'APPWRITE_SITE_MEMORY' => $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT,
]);
}
$vars = \array_merge($vars, [
'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint,
'APPWRITE_FUNCTION_ID' => $resource->getId(),
'APPWRITE_FUNCTION_NAME' => $resource->getAttribute('name'),
'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(),
'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(),
'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '',
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '',
'APPWRITE_FUNCTION_CPUS' => $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT,
'APPWRITE_FUNCTION_MEMORY' => $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT,
'APPWRITE_VERSION' => APP_VERSION_STABLE,
'APPWRITE_REGION' => $project->getAttribute('region'),
'APPWRITE_DEPLOYMENT_TYPE' => $deployment->getAttribute('type', ''),
@@ -644,11 +692,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
}
$metricTypeExecutions = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS);
$metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
$metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
$metricTypeExecutionsCompute = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE);
$metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE);
$metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE);
$metricTypeExecutionsMbSeconds = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS);
$metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
$metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
if ($deployment->getAttribute('resourceType') === 'sites') {
$queueForStatsUsage
->disableMetric(METRIC_NETWORK_REQUESTS)
@@ -671,9 +719,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
->addMetric(METRIC_SITES_REQUESTS, 1)
->addMetric(METRIC_SITES_INBOUND, $request->getSize() + $fileSize)
->addMetric(METRIC_SITES_OUTBOUND, $response->getSize())
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_REQUESTS), 1)
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize)
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_OUTBOUND), $response->getSize())
->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_REQUESTS), 1)
->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize)
->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_OUTBOUND), $response->getSize())
;
}
@@ -843,8 +891,17 @@ App::init()
}
$owner = '';
$functionsDomainFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
if (!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) {
$siteDomain = System::getEnv('_APP_DOMAIN_SITES', '');
if (!empty($functionsDomainFallback) && \str_ends_with($host, $functionsDomainFallback)) {
$functionsDomain = $functionsDomainFallback;
}
if (
(!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) ||
(!empty($siteDomain) && \str_ends_with($domain->get(), $siteDomain))
) {
$owner = 'Appwrite';
}
@@ -857,7 +914,7 @@ App::init()
'type' => 'api',
'status' => 'verifying',
'projectId' => $console->getId(),
'projectInternalId' => $console->getInternalId(),
'projectInternalId' => $console->getSequence(),
'search' => implode(' ', [$ruleId, $domain->get()]),
'owner' => $owner,
'region' => $console->getAttribute('region')
@@ -907,7 +964,7 @@ App::init()
)[0] ?? new Document();
}
if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getInternalId()) {
if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) {
$refDomainOrigin = $origin;
}
}
@@ -990,7 +1047,7 @@ App::init()
->addHeader('Server', 'Appwrite')
->addHeader('X-Content-Type-Options', 'nosniff')
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Forwarded-For, X-Forwarded-User-Agent')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Forwarded-For, X-Forwarded-User-Agent')
->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $refDomain)
->addHeader('Access-Control-Allow-Credentials', 'true');
@@ -1053,7 +1110,7 @@ App::options()
$response
->addHeader('Server', 'Appwrite')
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent')
->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $origin)
->addHeader('Access-Control-Allow-Credentials', 'true')
@@ -1120,35 +1177,11 @@ App::error()
break;
}
break;
case 'Utopia\Database\Exception\Conflict':
$error = new AppwriteException(AppwriteException::DOCUMENT_UPDATE_CONFLICT, previous: $error);
break;
case 'Utopia\Database\Exception\Timeout':
$error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error);
break;
case 'Utopia\Database\Exception\Query':
$error = new AppwriteException(AppwriteException::GENERAL_QUERY_INVALID, $error->getMessage(), previous: $error);
break;
case 'Utopia\Database\Exception\Structure':
$error = new AppwriteException(AppwriteException::DOCUMENT_INVALID_STRUCTURE, $error->getMessage(), previous: $error);
break;
case 'Utopia\Database\Exception\Duplicate':
$error = new AppwriteException(AppwriteException::DOCUMENT_ALREADY_EXISTS);
break;
case 'Utopia\Database\Exception\Restricted':
$error = new AppwriteException(AppwriteException::DOCUMENT_DELETE_RESTRICTED);
break;
case 'Utopia\Database\Exception\Authorization':
$error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED);
break;
case 'Utopia\Database\Exception\Relationship':
$error = new AppwriteException(AppwriteException::RELATIONSHIP_VALUE_INVALID, $error->getMessage(), previous: $error);
break;
case 'Utopia\Database\Exception\NotFound':
$error = new AppwriteException(AppwriteException::COLLECTION_NOT_FOUND, $error->getMessage(), previous: $error);
break;
case 'Utopia\Database\Exception\Dependency':
$error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, null, previous: $error);
case 'Utopia\Database\Exception\Timeout':
$error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error);
break;
}
@@ -1474,6 +1507,7 @@ App::get('/v1/ping')
->label('event', 'projects.[projectId].ping')
->label('sdk', new Method(
namespace: 'ping',
group: null,
name: 'get',
hide: true,
description: <<<EOT
+2 -2
View File
@@ -185,7 +185,7 @@ App::post('/v1/mock/api-key-unprefixed')
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'projectInternalId' => $project->getInternalId(),
'projectInternalId' => $project->getSequence(),
'projectId' => $project->getId(),
'name' => 'Outdated key',
'scopes' => $scopes,
@@ -235,7 +235,7 @@ App::get('/v1/mock/github/callback')
$github->initializeVariables($providerInstallationId, $privateKey, $githubAppId);
$owner = $github->getOwnerName($providerInstallationId) ?? '';
$projectInternalId = $project->getInternalId();
$projectInternalId = $project->getSequence();
$teamId = $project->getAttribute('teamId', '');
+51 -32
View File
@@ -92,8 +92,20 @@ $eventDatabaseListener = function (Document $project, Document $document, Respon
$usageDatabaseListener = function (string $event, Document $document, StatsUsage $queueForStatsUsage) {
$value = 1;
if ($event === Database::EVENT_DOCUMENT_DELETE) {
$value = -1;
switch ($event) {
case Database::EVENT_DOCUMENT_DELETE:
$value = -1;
break;
case Database::EVENT_DOCUMENTS_DELETE:
$value = -1 * $document->getAttribute('modified', 0);
break;
case Database::EVENT_DOCUMENTS_CREATE:
$value = $document->getAttribute('modified', 0);
break;
case Database::EVENT_DOCUMENTS_UPSERT:
$value = $document->getAttribute('created', 0);
break;
}
switch (true) {
@@ -249,34 +261,36 @@ App::init()
subject: 'keys'
);
if ($dbKey) {
$accessedAt = $dbKey->getAttribute('accessedAt', 0);
if (!$dbKey) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
$dbKey->setAttribute('accessedAt', DateTime::now());
$accessedAt = $dbKey->getAttribute('accessedAt', 0);
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
$dbKey->setAttribute('accessedAt', DateTime::now());
$dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey);
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
}
$sdkValidator = new WhiteList($servers, true);
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
$sdks = $dbKey->getAttribute('sdks', []);
if (!in_array($sdk, $sdks)) {
$sdks[] = $sdk;
$dbKey->setAttribute('sdks', $sdks);
/** Update access time as well */
$dbKey->setAttribute('accessedAt', Datetime::now());
$dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey);
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
}
$sdkValidator = new WhiteList($servers, true);
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
$sdks = $dbKey->getAttribute('sdks', []);
if (!in_array($sdk, $sdks)) {
$sdks[] = $sdk;
$dbKey->setAttribute('sdks', $sdks);
/** Update access time as well */
$dbKey->setAttribute('accessedAt', Datetime::now());
$dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey);
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
}
}
$queueForAudits->setUser($user);
}
$queueForAudits->setUser($user);
}
} // Admin User Authentication
elseif (($project->getId() === 'console' && !$team->isEmpty() && !$user->isEmpty()) || ($project->getId() !== 'console' && !$user->isEmpty() && $mode === APP_MODE_ADMIN)) {
@@ -337,6 +351,8 @@ App::init()
*/
$method = $route->getLabel('sdk', false);
// Take the first method if there's more than one,
// namespace can not differ between methods on the same route
if (\is_array($method)) {
$method = $method[0];
}
@@ -523,6 +539,9 @@ App::init()
$dbForProject
->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENTS_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENTS_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENTS_UPSERT, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENT_CREATE, 'create-trigger-events', fn ($event, $document) => $eventDatabaseListener(
$project,
$document,
@@ -539,7 +558,7 @@ App::init()
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser(Authorization::getRoles());
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
$key = $request->cacheIdentifier();
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
$cache = new Cache(
new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId())
@@ -548,14 +567,14 @@ App::init()
$data = $cache->load($key, $timestamp);
if (!empty($data) && !$cacheLog->isEmpty()) {
$parts = explode('/', $cacheLog->getAttribute('resourceType'));
$parts = explode('/', $cacheLog->getAttribute('resourceType', ''));
$type = $parts[0] ?? null;
if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) {
$bucketId = $parts[1] ?? null;
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId();
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence();
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
@@ -574,12 +593,12 @@ App::init()
$fileId = $parts[1] ?? null;
if ($fileSecurity && !$valid && !$isToken) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
} else {
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
}
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) {
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@@ -805,7 +824,7 @@ App::shutdown()
$resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user);
}
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
$key = $request->cacheIdentifier();
$signature = md5($data['payload']);
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
$accessedAt = $cacheLog->getAttribute('accessedAt', 0);
+100 -99
View File
@@ -15,9 +15,11 @@ use Utopia\Audit\Audit;
use Utopia\CLI\Console;
use Utopia\Compression\Compression;
use Utopia\Config\Config;
use Utopia\Database\Adapter\Pool as DatabasePool;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
@@ -46,29 +48,6 @@ $http = new Server(
$payloadSize = 12 * (1024 * 1024); // 12MB - adding slight buffer for headers and other data that might be sent with the payload - update later with valid testing
$totalWorkers = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
$http
->set([
'worker_num' => $totalWorkers,
'dispatch_func' => 'dispatch',
'open_http2_protocol' => true,
'http_compression' => false,
'package_max_length' => $payloadSize,
'buffer_output_size' => $payloadSize,
'task_worker_num' => 1, // required for the task to fetch domains background
]);
$http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) {
Console::success('Worker ' . ++$workerId . ' started successfully');
});
$http->on(Constant::EVENT_BEFORE_RELOAD, function ($server, $workerId) {
Console::success('Starting reload...');
});
$http->on(Constant::EVENT_AFTER_RELOAD, function ($server, $workerId) {
Console::success('Reload completed...');
});
/**
* Assigns HTTP requests to worker threads by analyzing its payload/content.
*
@@ -86,76 +65,105 @@ $http->on(Constant::EVENT_AFTER_RELOAD, function ($server, $workerId) {
*/
function dispatch(Server $server, int $fd, int $type, $data = null): int
{
global $totalWorkers, $domains;
$resolveWorkerId = function (Server $server, $data = null) {
global $totalWorkers, $domains;
// If data is not set we can send request to any worker
// first we try to pick idle worker, if not we randomly pick a worker
if ($data === null) {
// If data is not set we can send request to any worker
// first we try to pick idle worker, if not we randomly pick a worker
if ($data === null) {
for ($i = 0; $i < $totalWorkers; $i++) {
if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) {
return $i;
}
}
return rand(0, $totalWorkers - 1);
}
$riskyWorkersPercent = intval(System::getEnv('_APP_RISKY_WORKERS_PERCENT', 80)) / 100; // Decimal form 0 to 1
// Each worker has numeric ID, starting from 0 and incrementing
// From 0 to riskyWorkers, we consider safe workers
// From riskyWorkers to totalWorkers, we consider risky workers
$riskyWorkers = (int)floor($totalWorkers * $riskyWorkersPercent); // Absolute amount of risky workers
$domain = '';
// max up to 3 as first line has request details and second line has host
$lines = explode("\n", $data, 3);
$request = $lines[0];
if (count($lines) > 1) {
$domain = trim(explode('Host: ', $lines[1])[1]);
}
// Sync executions are considered risky
$risky = false;
if (str_starts_with($request, 'POST') && str_contains($request, '/executions')) {
$risky = true;
} elseif (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS'))) {
$risky = true;
} elseif ($domains->get(md5($domain), 'value') === 1) {
// executions request coming from custom domain
$risky = true;
}
if ($risky) {
// If risky request, only consider risky workers
for ($j = $riskyWorkers; $j < $totalWorkers; $j++) {
/** Reference https://openswoole.com/docs/modules/swoole-server-getWorkerStatus#description */
if ($server->getWorkerStatus($j) === SWOOLE_WORKER_IDLE) {
// If idle worker found, give to him
return $j;
}
}
// If no idle workers, give to random risky worker
$worker = rand($riskyWorkers, $totalWorkers - 1);
Console::warning("swoole_dispatch: Risky branch: did not find a idle worker, picking random worker {$worker}");
return $worker;
}
// If safe request, give to any idle worker
// Its fine to pick risky worker here, because it's idle. Idle is never actually risky
for ($i = 0; $i < $totalWorkers; $i++) {
if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) {
return $i;
}
}
return rand(0, $totalWorkers - 1);
}
$riskyWorkersPercent = intval(System::getEnv('_APP_RISKY_WORKERS_PERCENT', 80)) / 100; // Decimal form 0 to 1
// Each worker has numeric ID, starting from 0 and incrementing
// From 0 to riskyWorkers, we consider safe workers
// From riskyWorkers to totalWorkers, we consider risky workers
$riskyWorkers = (int) floor($totalWorkers * $riskyWorkersPercent); // Absolute amount of risky workers
$domain = '';
// max up to 3 as first line has request details and second line has host
$lines = explode("\n", $data, 3);
$request = $lines[0];
if (count($lines) > 1) {
$domain = trim(explode('Host: ', $lines[1])[1]);
}
// Sync executions are considered risky
$risky = false;
if (str_starts_with($request, 'POST') && str_contains($request, '/executions')) {
$risky = true;
} elseif (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS'))) {
$risky = true;
} elseif ($domains->get(md5($domain), 'value') === 1) {
// executions request coming from custom domain
$risky = true;
}
if ($risky) {
// If risky request, only consider risky workers
for ($j = $riskyWorkers; $j < $totalWorkers; $j++) {
/** Reference https://openswoole.com/docs/modules/swoole-server-getWorkerStatus#description */
if ($server->getWorkerStatus($j) === SWOOLE_WORKER_IDLE) {
// If idle worker found, give to him
return $j;
}
}
// If no idle workers, give to random risky worker
$worker = rand($riskyWorkers, $totalWorkers - 1);
Console::warning("swoole_dispatch: Risky branch: did not find a idle worker, picking random worker {$worker}");
// If no idle worker found, give to random safe worker
// We avoid risky workers here, as it could be in work - not idle. Thats exactly when they are risky.
$worker = rand(0, $riskyWorkers - 1);
Console::warning("swoole_dispatch: Non-risky branch: did not find a idle worker, picking random worker {$worker}");
return $worker;
}
// If safe request, give to any idle worker
// Its fine to pick risky worker here, because it's idle. Idle is never actually risky
for ($i = 0; $i < $totalWorkers; $i++) {
if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) {
return $i;
}
}
// If no idle worker found, give to random safe worker
// We avoid risky workers here, as it could be in work - not idle. Thats exactly when they are risky.
$worker = rand(0, $riskyWorkers - 1);
Console::warning("swoole_dispatch: Non-risky branch: did not find a idle worker, picking random worker {$worker}");
return $worker;
};
$workerId = $resolveWorkerId($server, $data);
$server->bind($fd, $workerId);
return $workerId;
}
$http
->set([
Constant::OPTION_WORKER_NUM => $totalWorkers,
Constant::OPTION_DISPATCH_FUNC => dispatch(...),
Constant::OPTION_DISPATCH_MODE => SWOOLE_DISPATCH_UIDMOD,
Constant::OPTION_HTTP_COMPRESSION => false,
Constant::OPTION_PACKAGE_MAX_LENGTH => $payloadSize,
Constant::OPTION_OUTPUT_BUFFER_SIZE => $payloadSize,
Constant::OPTION_TASK_WORKER_NUM => 1, // required for the task to fetch domains background
]);
$http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) {
Console::success('Worker ' . ++$workerId . ' started successfully');
});
$http->on(Constant::EVENT_BEFORE_RELOAD, function ($server, $workerId) {
Console::success('Starting reload...');
});
$http->on(Constant::EVENT_AFTER_RELOAD, function ($server, $workerId) {
Console::success('Reload completed...');
});
include __DIR__ . '/controllers/general.php';
function createDatabase(App $app, string $resourceKey, string $dbName, array $collections, mixed $pools, callable $extraSetup = null): void
@@ -164,7 +172,7 @@ function createDatabase(App $app, string $resourceKey, string $dbName, array $co
$sleep = 1;
$attempts = 0;
do {
while (true) {
try {
$attempts++;
$resource = $app->getResource($resourceKey);
@@ -173,13 +181,12 @@ function createDatabase(App $app, string $resourceKey, string $dbName, array $co
break; // exit loop on success
} catch (\Exception $e) {
Console::warning(" └── Database not ready. Retrying connection ({$attempts})...");
$pools->reclaim();
if ($attempts >= $max) {
throw new \Exception(' └── Failed to connect to database: ' . $e->getMessage());
}
sleep($sleep);
}
} while ($attempts < $max);
}
Console::success("[Setup] - $dbName database init started...");
@@ -302,7 +309,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
'orders' => $index['orders'],
]), $files['indexes']);
$dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes);
$dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes);
}
if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) {
@@ -311,7 +318,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
'$id' => ID::custom('screenshots'),
'$collection' => ID::custom('buckets'),
'name' => 'Screenshots',
'maximumFileSize' => 5000000, // ~5MB
'maximumFileSize' => 20000000, // ~20MB
'allowedFileExtensions' => [ 'png' ],
'enabled' => true,
'compression' => Compression::GZIP,
@@ -350,7 +357,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
'orders' => $index['orders'],
]), $files['indexes']);
Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes));
Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes));
}
});
@@ -362,11 +369,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$cache = $app->getResource('cache');
foreach ($sharedTablesV2 as $hostname) {
$adapter = $pools
->get($hostname)
->pop()
->getResource();
$adapter = new DatabasePool($pools->get($hostname));
$dbForProject = (new Database($adapter, $cache))
->setDatabase('appwrite')
->setSharedTables(true)
@@ -376,7 +379,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
try {
Console::success('[Setup] - Creating project database: ' . $hostname . '...');
$dbForProject->create();
} catch (Duplicate) {
} catch (DuplicateException) {
Console::success('[Setup] - Skip: metadata table already exists');
}
@@ -402,7 +405,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
}
}
$pools->reclaim();
Console::success('[Setup] - Server database init completed...');
});
@@ -517,6 +519,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
Console::error('[Error] Message: ' . $th->getMessage());
Console::error('[Error] File: ' . $th->getFile());
Console::error('[Error] Line: ' . $th->getLine());
Console::error('[Error] Trace: ' . $th->getTraceAsString());
$swooleResponse->setStatusCode(500);
@@ -534,13 +537,11 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
];
$swooleResponse->end(\json_encode($output));
} finally {
$pools->reclaim();
}
});
// Fetch domains every `DOMAIN_SYNC_TIMER` seconds and update in the memory
$http->on('Task', function () use ($register, $domains) {
$http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
$lastSyncUpdate = null;
$pools = $register->get('pools');
App::setResource('pools', fn () => $pools);
+17 -2
View File
@@ -6,6 +6,10 @@ const APP_NAME = 'Appwrite';
const APP_DOMAIN = 'appwrite.io';
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
const APP_EMAIL_SECURITY = ''; // Default security email address
const APP_EMAIL_LOGO_URL = 'https://cloud.appwrite.io/images/mails/logo.png';
const APP_EMAIL_ACCENT_COLOR = '#fd366e';
const APP_EMAIL_TERMS_URL = 'https://appwrite.io/terms';
const APP_EMAIL_PRIVACY_URL = 'https://appwrite.io/privacy';
const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s';
const APP_MODE_DEFAULT = 'default';
const APP_MODE_ADMIN = 'admin';
@@ -26,13 +30,15 @@ const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000;
const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate period
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_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
const APP_RESOURCE_TOKEN_ACCESS = 24 * 60 * 60; // 24 hours
const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
const APP_CACHE_BUSTER = 4318;
const APP_VERSION_STABLE = '1.7.0';
const APP_CACHE_BUSTER = 4320;
const APP_VERSION_STABLE = '1.7.4';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
@@ -45,6 +51,7 @@ const APP_DATABASE_TIMEOUT_MILLISECONDS_API = 15 * 1000; // 15 seconds
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_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_SITES = '/storage/sites';
const APP_STORAGE_FUNCTIONS = '/storage/functions';
@@ -60,6 +67,7 @@ const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io';
const APP_SOCIAL_LINKEDIN = 'https://www.linkedin.com/company/appwrite';
const APP_SOCIAL_INSTAGRAM = 'https://www.instagram.com/appwrite.io';
const APP_SOCIAL_GITHUB = 'https://github.com/appwrite';
const APP_SOCIAL_GITHUB_APPWRITE = 'https://github.com/appwrite/appwrite';
const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord';
const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244';
const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
@@ -257,3 +265,10 @@ const RESOURCE_TYPE_PROVIDERS = 'providers';
const RESOURCE_TYPE_TOPICS = 'topics';
const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers';
const RESOURCE_TYPE_MESSAGES = 'messages';
// 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';
+30 -21
View File
@@ -71,18 +71,27 @@ Database::addFilter(
},
function (mixed $value, Document $document, Database $database) {
$attributes = $database->find('attributes', [
Query::equal('collectionInternalId', [$document->getInternalId()]),
Query::equal('collectionInternalId', [$document->getSequence()]),
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
Query::limit($database->getLimitForAttributes()),
]);
foreach ($attributes as $attribute) {
if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) {
$options = $attribute->getAttribute('options');
foreach ($options as $key => $value) {
$attribute->setAttribute($key, $value);
}
$attribute->removeAttribute('options');
$attributeType = $attribute->getAttribute('type');
switch ($attributeType) {
case Database::VAR_RELATIONSHIP:
$options = $attribute->getAttribute('options');
foreach ($options as $key => $value) {
$attribute->setAttribute($key, $value);
}
$attribute->removeAttribute('options');
break;
case Database::VAR_STRING:
$filters = $attribute->getAttribute('filters', []);
$attribute->setAttribute('encrypt', in_array('encrypt', $filters));
break;
}
}
@@ -98,7 +107,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return $database
->find('indexes', [
Query::equal('collectionInternalId', [$document->getInternalId()]),
Query::equal('collectionInternalId', [$document->getSequence()]),
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
Query::limit($database->getLimitForIndexes()),
]);
@@ -113,7 +122,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return $database
->find('platforms', [
Query::equal('projectInternalId', [$document->getInternalId()]),
Query::equal('projectInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
@@ -127,7 +136,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return $database
->find('keys', [
Query::equal('projectInternalId', [$document->getInternalId()]),
Query::equal('projectInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
@@ -141,7 +150,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return $database
->find('devKeys', [
Query::equal('projectInternalId', [$document->getInternalId()]),
Query::equal('projectInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
@@ -155,7 +164,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return $database
->find('webhooks', [
Query::equal('projectInternalId', [$document->getInternalId()]),
Query::equal('projectInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]);
}
@@ -168,7 +177,7 @@ Database::addFilter(
},
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database->find('sessions', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::equal('userInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
@@ -182,7 +191,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('tokens', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::equal('userInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
@@ -196,7 +205,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('challenges', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::equal('userInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
@@ -210,7 +219,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('authenticators', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::equal('userInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
@@ -224,7 +233,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('memberships', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::equal('userInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
]));
}
@@ -238,7 +247,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return $database
->find('variables', [
Query::equal('resourceInternalId', [$document->getInternalId()]),
Query::equal('resourceInternalId', [$document->getSequence()]),
Query::equal('resourceType', ['function', 'site']),
Query::limit(APP_LIMIT_SUBQUERY),
]);
@@ -316,7 +325,7 @@ Database::addFilter(
function (mixed $value, Document $document, Database $database) {
return Authorization::skip(fn () => $database
->find('targets', [
Query::equal('userInternalId', [$document->getInternalId()]),
Query::equal('userInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY)
]));
}
@@ -331,13 +340,13 @@ Database::addFilter(
$targetIds = Authorization::skip(fn () => \array_map(
fn ($document) => $document->getAttribute('targetInternalId'),
$database->find('subscribers', [
Query::equal('topicInternalId', [$document->getInternalId()]),
Query::equal('topicInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY)
])
));
if (\count($targetIds) > 0) {
return $database->skipValidation(fn () => $database->find('targets', [
Query::equal('$internalId', $targetIds)
Query::equal('$sequence', $targetIds)
]));
}
return [];
+8 -7
View File
@@ -15,6 +15,7 @@ use Utopia\Config\Config;
use Utopia\Database\Adapter\MariaDB;
use Utopia\Database\Adapter\MySQL;
use Utopia\Database\Adapter\SQL;
use Utopia\Database\PDO;
use Utopia\Domains\Validator\PublicDomain;
use Utopia\DSN\DSN;
use Utopia\Logger\Adapter\AppSignal;
@@ -215,13 +216,13 @@ $register->set('pools', function () {
'mysql',
'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array(
PDO::ATTR_TIMEOUT => 3, // Seconds
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_STRINGIFY_FETCHES => true
));
return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, [
\PDO::ATTR_TIMEOUT => 3, // Seconds
\PDO::ATTR_PERSISTENT => false,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => true,
\PDO::ATTR_STRINGIFY_FETCHES => true
]);
});
},
'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) {
+68 -67
View File
@@ -24,10 +24,12 @@ use Appwrite\Utopia\Request;
use Executor\Executor;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\App;
use Utopia\Cache\Adapter\Pool as CachePool;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Adapter\Pool as DatabasePool;
use Utopia\Database\Database;
use Utopia\Database\DateTime as DatabaseDateTime;
use Utopia\Database\Document;
@@ -38,6 +40,7 @@ use Utopia\DSN\DSN;
use Utopia\Locale\Locale;
use Utopia\Logger\Log;
use Utopia\Pools\Group;
use Utopia\Queue\Broker\Pool as BrokerPool;
use Utopia\Queue\Publisher;
use Utopia\Storage\Device;
use Utopia\Storage\Device\AWS;
@@ -49,6 +52,7 @@ use Utopia\Storage\Device\S3;
use Utopia\Storage\Device\Wasabi;
use Utopia\Storage\Storage;
use Utopia\System\System;
use Utopia\Telemetry\Adapter\None as NoTelemetry;
use Utopia\Validator\Hostname;
use Utopia\Validator\WhiteList;
use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub;
@@ -72,10 +76,10 @@ App::setResource('localeCodes', function () {
// Queues
App::setResource('publisher', function (Group $pools) {
return $pools->get('publisher')->pop()->getResource();
return new BrokerPool(publisher: $pools->get('publisher'));
}, ['pools']);
App::setResource('consumer', function (Group $pools) {
return $pools->get('consumer')->pop()->getResource();
return new BrokerPool(consumer: $pools->get('consumer'));
}, ['pools']);
App::setResource('queueForMessaging', function (Publisher $publisher) {
return new Messaging($publisher);
@@ -329,12 +333,8 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$dbAdapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$adapter = new DatabasePool($pools->get($dsn->getHost()));
$database = new Database($adapter, $cache);
$database
->setMetadata('host', \gethostname())
@@ -347,25 +347,21 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
return $database;
}, ['pools', 'dbForPlatform', 'cache', 'project']);
App::setResource('dbForPlatform', function (Group $pools, Cache $cache) {
$dbAdapter = $pools
->get('console')
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$adapter = new DatabasePool($pools->get('console'));
$database = new Database($adapter, $cache);
$database
->setNamespace('_console')
@@ -378,7 +374,7 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache) {
}, ['pools', 'cache']);
App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) {
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
$databases = [];
return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) {
if ($project->isEmpty() || $project->getId() === 'console') {
@@ -404,13 +400,13 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
});
@@ -420,12 +416,8 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
return $database;
}
$dbAdapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$adapter = new DatabasePool($pools->get($dsn->getHost()));
$database = new Database($adapter, $cache);
$databases[$dsn->getHost()] = $database;
$configure($database);
@@ -435,21 +427,15 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
$database = null;
return function (?Document $project = null) use ($pools, $cache, $database) {
return function (?Document $project = null) use ($pools, $cache, &$database) {
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
$database->setTenant($project->getSequence());
return $database;
}
$dbAdapter = $pools
->get('logs')
->pop()
->getResource();
$database = new Database(
$dbAdapter,
$cache
);
$adapter = new DatabasePool($pools->get('logs'));
$database = new Database($adapter, $cache);
$database
->setSharedTables(true)
@@ -459,23 +445,21 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
// set tenant
if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
$database->setTenant($project->getSequence());
}
return $database;
};
}, ['pools', 'cache']);
App::setResource('telemetry', fn () => new NoTelemetry());
App::setResource('cache', function (Group $pools) {
$list = Config::getParam('pools-cache', []);
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
$adapters[] = new CachePool($pools->get($value));
}
return new Cache(new Sharding($adapters));
@@ -505,23 +489,18 @@ App::setResource('timelimit', function (\Redis $redis) {
App::setResource('deviceForLocal', function () {
return new Local();
});
App::setResource('deviceForFiles', function ($project) {
return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForSites', function ($project) {
return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForImports', function (Document $project) {
App::setResource('deviceForImports', function ($project) {
return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForFunctions', function ($project) {
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
}, ['project']);
App::setResource('deviceForBuilds', function ($project) {
return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId());
}, ['project']);
@@ -553,7 +532,8 @@ function getDevice(string $root, string $connection = ''): Device
switch ($device) {
case Storage::DEVICE_S3:
if (!empty($url)) {
return new S3($root, $accessKey, $accessSecret, $url, $region, $acl);
$bucketRoot = (!empty($bucket) ? $bucket . '/' : '') . \ltrim($root, '/');
return new S3($bucketRoot, $accessKey, $accessSecret, $url, $region, $acl);
} else {
return new AWS($root, $accessKey, $accessSecret, $bucket, $region, $acl);
}
@@ -585,7 +565,8 @@ function getDevice(string $root, string $connection = ''): Device
$s3Acl = 'private';
$s3EndpointUrl = System::getEnv('_APP_STORAGE_S3_ENDPOINT', '');
if (!empty($s3EndpointUrl)) {
return new S3($root, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl);
$bucketRoot = (!empty($s3Bucket) ? $s3Bucket . '/' : '') . \ltrim($root, '/');
return new S3($bucketRoot, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl);
} else {
return new AWS($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
}
@@ -816,7 +797,7 @@ App::setResource('devKey', function (Request $request, Document $project, array
// add sdk to key
$sdkValidator = new WhiteList($servers, true);
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
$sdk = \strtolower($request->getHeader('x-sdk-name', 'UNKNOWN'));
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
$sdks = $key->getAttribute('sdks', []);
@@ -855,7 +836,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A
$team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) {
return $dbForPlatform->findOne('teams', [
Query::equal('$internalId', [$teamInternalId]),
Query::equal('$sequence', [$teamInternalId]),
]);
});
@@ -902,7 +883,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) {
$tokenJWT = $request->getParam('token');
if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication
$jwt = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
try {
$payload = $jwt->decode($tokenJWT);
@@ -911,32 +892,52 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) {
}
$tokenId = $payload['tokenId'] ?? '';
$secret = $payload['secret'] ?? '';
if (empty($tokenId) || empty($secret)) {
if (empty($tokenId)) {
return new Document([]);
}
$token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId));
if ($token->isEmpty() || $token->getAttribute('secret') !== $secret) {
if ($token->isEmpty()) {
return new Document([]);
}
if ($token->getAttribute('resourceType') === 'file') {
$internalIds = explode(':', $token->getAttribute('resourceInternalId'));
$ids = explode(':', $token->getAttribute('resourceId'));
$expiry = $token->getAttribute('expire');
if (count($internalIds) !== 2 || count($ids) !== 2) {
if ($expiry !== null) {
$now = new \DateTime();
$expiryDate = new \DateTime($expiry);
if ($expiryDate < $now) {
return new Document([]);
}
return new Document([
'bucketId' => $ids[0],
'fileId' => $ids[1],
'bucketInternalId' => $internalIds[0],
'fileInternalId' => $internalIds[1],
]);
}
return match ($token->getAttribute('resourceType')) {
TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) {
$sequences = explode(':', $token->getAttribute('resourceInternalId'));
$ids = explode(':', $token->getAttribute('resourceId'));
if (count($sequences) !== 2 || count($ids) !== 2) {
return new Document([]);
}
$accessedAt = $token->getAttribute('accessedAt', 0);
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));
}
return new Document([
'bucketId' => $ids[0],
'fileId' => $ids[1],
'bucketInternalId' => $sequences[0],
'fileInternalId' => $sequences[1],
]);
})(),
default => throw new Exception(Exception::TOKEN_RESOURCE_TYPE_INVALID),
};
}
return new Document([]);
}, ['project', 'dbForProject', 'request']);
+67 -47
View File
@@ -5,6 +5,7 @@ use Appwrite\Extend\Exception;
use Appwrite\Extend\Exception as AppwriteException;
use Appwrite\Messaging\Adapter\Realtime;
use Appwrite\Network\Validator\Origin;
use Appwrite\PubSub\Adapter\Pool as PubSubPool;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Swoole\Http\Request as SwooleRequest;
@@ -15,10 +16,12 @@ use Swoole\Timer;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\App;
use Utopia\Cache\Adapter\Pool as CachePool;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Adapter\Pool as DatabasePool;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
@@ -28,13 +31,15 @@ use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\DSN\DSN;
use Utopia\Logger\Log;
use Utopia\Pools\Group;
use Utopia\Registry\Registry;
use Utopia\System\System;
use Utopia\Telemetry\Adapter\None as NoTelemetry;
use Utopia\WebSocket\Adapter;
use Utopia\WebSocket\Server;
/**
* @var \Utopia\Registry\Registry $register
* @var Registry $register
*/
require_once __DIR__ . '/init.php';
@@ -46,17 +51,17 @@ if (!function_exists('getConsoleDB')) {
{
global $register;
/** @var \Utopia\Pools\Group $pools */
static $database = null;
if ($database !== null) {
return $database;
}
/** @var Group $pools */
$pools = $register->get('pools');
$dbAdapter = $pools
->get('console')
->pop()
->getResource()
;
$database = new Database($dbAdapter, getCache());
$adapter = new DatabasePool($pools->get('console'));
$database = new Database($adapter, getCache());
$database
->setNamespace('_console')
->setMetadata('host', \gethostname())
@@ -72,7 +77,13 @@ if (!function_exists('getProjectDB')) {
{
global $register;
/** @var \Utopia\Pools\Group $pools */
static $databases = [];
if (isset($databases[$project->getSequence()])) {
return $databases[$project->getSequence()];
}
/** @var Group $pools */
$pools = $register->get('pools');
if ($project->isEmpty() || $project->getId() === 'console') {
@@ -86,11 +97,7 @@ if (!function_exists('getProjectDB')) {
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$adapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$adapter = new DatabasePool($pools->get($dsn->getHost()));
$database = new Database($adapter, getCache());
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
@@ -98,20 +105,20 @@ if (!function_exists('getProjectDB')) {
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
$database
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId());
return $database;
return $databases[$project->getSequence()] = $database;
}
}
@@ -121,20 +128,22 @@ if (!function_exists('getCache')) {
{
global $register;
$pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */
static $cache = null;
if ($cache !== null) {
return $cache;
}
$pools = $register->get('pools'); /** @var Group $pools */
$list = Config::getParam('pools-cache', []);
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
$adapters[] = new CachePool($pools->get($value));
}
return new Cache(new Sharding($adapters));
return $cache = new Cache(new Sharding($adapters));
}
}
@@ -142,6 +151,12 @@ if (!function_exists('getCache')) {
if (!function_exists('getRedis')) {
function getRedis(): \Redis
{
static $redis = null;
if ($redis !== null) {
return $redis;
}
$host = System::getEnv('_APP_REDIS_HOST', 'localhost');
$port = System::getEnv('_APP_REDIS_PORT', 6379);
$pass = System::getEnv('_APP_REDIS_PASS', '');
@@ -160,21 +175,39 @@ if (!function_exists('getRedis')) {
if (!function_exists('getTimelimit')) {
function getTimelimit(): TimeLimitRedis
{
return new TimeLimitRedis("", 0, 1, getRedis());
static $timelimit = null;
if ($timelimit !== null) {
return $timelimit;
}
return $timelimit = new TimeLimitRedis("", 0, 1, getRedis());
}
}
if (!function_exists('getRealtime')) {
function getRealtime(): Realtime
{
return new Realtime();
static $realtime = null;
if ($realtime !== null) {
return $realtime;
}
return $realtime = new Realtime();
}
}
if (!function_exists('getTelemetry')) {
function getTelemetry(int $workerId): Utopia\Telemetry\Adapter
{
return new NoTelemetry();
static $telemetry = null;
if ($telemetry !== null) {
return $telemetry;
}
return $telemetry = new NoTelemetry();
}
}
@@ -273,7 +306,6 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
sleep(DATABASE_RECONNECT_SLEEP);
}
} while (true);
$register->get('pools')->reclaim();
});
/**
@@ -299,9 +331,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument));
} catch (Throwable $th) {
call_user_func($logError, $th, "updateWorkerDocument");
} finally {
$register->get('pools')->reclaim();
$logError($th, "updateWorkerDocument");
}
});
}
@@ -370,8 +400,6 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
'data' => $event['data']
]));
}
$register->get('pools')->reclaim();
}
}
/**
@@ -407,8 +435,8 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
}
$start = time();
/** @var \Appwrite\PubSub\Adapter $pubsub */
$pubsub = $register->get('pools')->get('pubsub')->pop()->getResource();
$pubsub = new PubSubPool($register->get('pools')->get('pubsub'));
if ($pubsub->ping(true)) {
$attempts = 0;
Console::success('Pub/sub connection established (worker: ' . $workerId . ')');
@@ -436,8 +464,6 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
$realtime->unsubscribe($connection);
$realtime->subscribe($projectId, $connection, $roles, $channels);
$register->get('pools')->reclaim();
}
}
@@ -463,14 +489,12 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
}
});
} catch (Throwable $th) {
call_user_func($logError, $th, "pubSubConnection");
$logError($th, "pubSubConnection");
Console::error('Pub/sub error: ' . $th->getMessage());
$attempts++;
sleep(DATABASE_RECONNECT_SLEEP);
continue;
} finally {
$register->get('pools')->reclaim();
}
}
@@ -572,7 +596,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
$stats->incr($project->getId(), 'connections');
$stats->incr($project->getId(), 'connectionsTotal');
} catch (Throwable $th) {
call_user_func($logError, $th, "initServer");
$logError($th, "initServer");
// Handle SQL error code is 'HY000'
$code = $th->getCode();
@@ -596,8 +620,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
Console::error('[Error] Code: ' . $response['data']['code']);
Console::error('[Error] Message: ' . $response['data']['message']);
}
} finally {
$register->get('pools')->reclaim();
}
});
@@ -696,8 +718,6 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
if ($th->getCode() === 1008) {
$server->close($connection, $th->getCode());
}
} finally {
$register->get('pools')->reclaim();
}
});
+28 -26
View File
@@ -479,35 +479,37 @@ switch ($type) {
</div>
</div>
<div x-show="page === 'trace'" class="error-trace">
<button class="back-button" x-on:click="page = 'error'">
Back
</button>
<div class="trace-grid-header">Error trace</div>
<?php foreach ($trace as $index => $traceItem): ?>
<div class="trace-grid">
<?php if (isset($traceItem['file'])): ?>
<div class="trace-label">file</div>
<div class="trace-value"><?php echo $this->print($traceItem['file']); ?></div>
<?php endif; ?>
<?php if ($development) : ?>
<div x-show="page === 'trace'" class="error-trace">
<button class="back-button" x-on:click="page = 'error'">
Back
</button>
<div class="trace-grid-header">Error trace</div>
<?php foreach ($trace as $index => $traceItem): ?>
<div class="trace-grid">
<?php if (isset($traceItem['file'])): ?>
<div class="trace-label">file</div>
<div class="trace-value"><?php echo $this->print($traceItem['file']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['line'])): ?>
<div class="trace-label">line</div>
<div class="trace-value"><?php echo $this->print($traceItem['line']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['line'])): ?>
<div class="trace-label">line</div>
<div class="trace-value"><?php echo $this->print($traceItem['line']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['function'])): ?>
<div class="trace-label">function</div>
<div class="trace-value"><?php echo $this->print($traceItem['function']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['function'])): ?>
<div class="trace-label">function</div>
<div class="trace-value"><?php echo $this->print($traceItem['function']); ?></div>
<?php endif; ?>
<?php if (isset($traceItem['args'])): ?>
<div class="trace-label">args</div>
<div class="trace-args"><pre><?php echo $this->print(\var_export($traceItem['args'], true)); ?></pre></div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php if (isset($traceItem['args'])): ?>
<div class="trace-label">args</div>
<div class="trace-args"><pre><?php echo $this->print(\var_export($traceItem['args'], true)); ?></pre></div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<div x-show="page === 'error'" class="brand">
+9 -34
View File
@@ -61,6 +61,7 @@ $image = $this->getParam('image', '');
- traefik.http.routers.appwrite_api_https.tls=true
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-imports:/storage/imports:rw
- appwrite-cache:/storage/cache:rw
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
@@ -151,6 +152,7 @@ $image = $this->getParam('image', '');
- _APP_LOGGING_CONFIG
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_DELAY
- _APP_MAINTENANCE_START_TIME
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
@@ -175,7 +177,7 @@ $image = $this->getParam('image', '');
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: <?php echo $organization; ?>/console:5.2.53
image: <?php echo $organization; ?>/console:6.0.13
restart: unless-stopped
networks:
- appwrite
@@ -615,6 +617,8 @@ $image = $this->getParam('image', '');
restart: unless-stopped
networks:
- appwrite
volumes:
- appwrite-imports:/storage/imports:rw
depends_on:
- mariadb
environment:
@@ -681,11 +685,9 @@ $image = $this->getParam('image', '');
container_name: appwrite-task-stats-resources
entrypoint: stats-resources
<<: *x-logging
restart: unless-stopped
networks:
- appwrite
volumes:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
depends_on:
- redis
- mariadb
@@ -763,34 +765,6 @@ $image = $this->getParam('image', '');
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-worker-stats-usage-dump:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
entrypoint: worker-stats-usage-dump
<<: *x-logging
container_name: appwrite-worker-stats-usage-dump
restart: unless-stopped
networks:
- appwrite
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-task-scheduler-functions:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
entrypoint: schedule-functions
@@ -877,7 +851,7 @@ $image = $this->getParam('image', '');
- _APP_ASSISTANT_OPENAI_API_KEY
appwrite-browser:
image: appwrite/browser:0.2.2
image: appwrite/browser:0.2.4
container_name: appwrite-browser
<<: *x-logging
restart: unless-stopped
@@ -890,7 +864,7 @@ $image = $this->getParam('image', '');
<<: *x-logging
restart: unless-stopped
stop_signal: SIGINT
image: openruntimes/executor:0.7.13
image: openruntimes/executor:0.7.14
networks:
- appwrite
- runtimes
@@ -990,6 +964,7 @@ volumes:
appwrite-redis:
appwrite-cache:
appwrite-uploads:
appwrite-imports:
appwrite-certificates:
appwrite-functions:
appwrite-sites:
+33 -65
View File
@@ -15,16 +15,17 @@ use Appwrite\Event\Messaging;
use Appwrite\Event\Migration;
use Appwrite\Event\Realtime;
use Appwrite\Event\StatsUsage;
use Appwrite\Event\StatsUsageDump;
use Appwrite\Event\Webhook;
use Appwrite\Platform\Appwrite;
use Executor\Executor;
use Swoole\Runtime;
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
use Utopia\Cache\Adapter\Pool as CachePool;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Adapter\Pool as DatabasePool;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
@@ -34,28 +35,26 @@ use Utopia\Logger\Log;
use Utopia\Logger\Logger;
use Utopia\Platform\Service;
use Utopia\Pools\Group;
use Utopia\Queue\Broker\Pool as BrokerPool;
use Utopia\Queue\Message;
use Utopia\Queue\Publisher;
use Utopia\Queue\Server;
use Utopia\Registry\Registry;
use Utopia\System\System;
use Utopia\Telemetry\Adapter\None as NoTelemetry;
Authorization::disable();
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
Runtime::enableCoroutine();
Server::setResource('register', fn () => $register);
Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) {
$pools = $register->get('pools');
$database = $pools
->get('console')
->pop()
->getResource();
$adapter = new DatabasePool($pools->get('console'));
$dbForPlatform = new Database($adapter, $cache);
$dbForPlatform->setNamespace('_console');
$adapter = new Database($database, $cache);
$adapter->setNamespace('_console');
return $adapter;
return $dbForPlatform;
}, ['cache', 'register']);
Server::setResource('project', function (Message $message, Database $dbForPlatform) {
@@ -83,32 +82,21 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register,
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$adapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$adapter = new DatabasePool($pools->get($dsn->getHost()));
$database = new Database($adapter, $cache);
try {
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
$database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
@@ -139,24 +127,20 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
return $database;
}
$dbAdapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$adapter = new DatabasePool($pools->get($dsn->getHost()));
$database = new Database($adapter, $cache);
$databases[$dsn->getHost()] = $database;
@@ -165,13 +149,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf
if (\in_array($dsn->getHost(), $sharedTables)) {
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setTenant($project->getSequence())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
->setNamespace('_' . $project->getSequence());
}
$database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER);
@@ -184,19 +168,12 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
$database = null;
return function (?Document $project = null) use ($pools, $cache, $database) {
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
$database->setTenant($project->getSequence());
return $database;
}
$dbAdapter = $pools
->get('logs')
->pop()
->getResource();
$database = new Database(
$dbAdapter,
$cache
);
$adapter = new DatabasePool($pools->get('logs'));
$database = new Database($adapter, $cache);
$database
->setSharedTables(true)
@@ -206,7 +183,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
// set tenant
if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
$database->setTenant($project->getSequence());
}
return $database;
@@ -234,11 +211,7 @@ Server::setResource('cache', function (Registry $register) {
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
$adapters[] = new CachePool($pools->get($value));
}
return new Cache(new Sharding($adapters));
@@ -267,22 +240,19 @@ Server::setResource('timelimit', function (\Redis $redis) {
Server::setResource('log', fn () => new Log());
Server::setResource('publisher', function (Group $pools) {
return $pools->get('publisher')->pop()->getResource();
return new BrokerPool(publisher: $pools->get('publisher'));
}, ['pools']);
Server::setResource('consumer', function (Group $pools) {
return $pools->get('consumer')->pop()->getResource();
return new BrokerPool(consumer: $pools->get('consumer'));
}, ['pools']);
Server::setResource('queueForStatsUsage', function (Publisher $publisher) {
return new StatsUsage($publisher);
}, ['publisher']);
Server::setResource('queueForStatsUsageDump', function (Publisher $publisher) {
return new StatsUsageDump($publisher);
}, ['publisher']);
Server::setResource('queueForDatabase', function (Publisher $publisher) {
return new EventDatabase($publisher);
}, ['publisher']);
@@ -339,6 +309,8 @@ Server::setResource('pools', function (Registry $register) {
return $register->get('pools');
}, ['register']);
Server::setResource('telemetry', fn () => new NoTelemetry());
Server::setResource('deviceForSites', function (Document $project) {
return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId());
}, ['project']);
@@ -368,6 +340,10 @@ Server::setResource(
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
);
Server::setResource('plan', function (array $plan = []) {
return [];
});
Server::setResource('certificates', function () {
$email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS'));
if (empty($email)) {
@@ -461,13 +437,6 @@ try {
$worker = $platform->getWorker();
$worker
->shutdown()
->inject('pools')
->action(function (Group $pools) {
$pools->reclaim();
});
$worker
->error()
->inject('error')
@@ -475,8 +444,7 @@ $worker
->inject('log')
->inject('pools')
->inject('project')
->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($queueName) {
$pools->reclaim();
->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) {
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
if ($logger) {
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
php /usr/src/code/app/worker.php stats-usage-dump $@
+7 -7
View File
@@ -31,7 +31,7 @@
}
},
"require": {
"php": ">=8.0.0",
"php": ">=8.3.0",
"ext-curl": "*",
"ext-imagick": "*",
"ext-mbstring": "*",
@@ -49,25 +49,25 @@
"utopia-php/abuse": "0.52.*",
"utopia-php/analytics": "0.10.*",
"utopia-php/audit": "0.55.*",
"utopia-php/cache": "0.12.*",
"utopia-php/cache": "0.13.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/detector": "0.1.*",
"utopia-php/database": "0.64.*",
"utopia-php/domains": "0.5.*",
"utopia-php/database": "0.71.*",
"utopia-php/domains": "0.8.0",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
"utopia-php/fetch": "0.4.*",
"utopia-php/image": "0.8.*",
"utopia-php/locale": "0.4.*",
"utopia-php/logger": "0.6.*",
"utopia-php/messaging": "0.16.*",
"utopia-php/migration": "0.9.1",
"utopia-php/messaging": "0.17.*",
"utopia-php/migration": "0.10.*",
"utopia-php/orchestration": "0.9.*",
"utopia-php/platform": "0.7.*",
"utopia-php/pools": "0.8.*",
"utopia-php/preloader": "0.2.*",
"utopia-php/queue": "0.9.*",
"utopia-php/queue": "0.10.*",
"utopia-php/registry": "0.5.*",
"utopia-php/storage": "0.18.*",
"utopia-php/swoole": "0.8.*",
Generated
+197 -184
View File
File diff suppressed because it is too large Load Diff
+5 -36
View File
@@ -206,13 +206,14 @@ services:
- _APP_DATABASE_SHARED_TABLES_V1
- _APP_DATABASE_SHARED_NAMESPACE
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
- _APP_CUSTOM_DOMAIN_DENY_LIST
extra_hosts:
- "host.docker.internal:host-gateway"
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: appwrite/console:5.3.0-sites-rc.40
image: appwrite/console:6.0.13
restart: unless-stopped
networks:
- appwrite
@@ -752,7 +753,7 @@ services:
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_MAINTENANCE_DELAY
- _APP_MAINTENANCE_START_TIME
- _APP_DATABASE_SHARED_TABLES
appwrite-task-stats-resources:
@@ -848,38 +849,6 @@ services:
- _APP_USAGE_AGGREGATION_INTERVAL
- _APP_DATABASE_SHARED_TABLES
appwrite-worker-stats-usage-dump:
entrypoint: worker-stats-usage-dump
<<: *x-logging
container_name: appwrite-worker-stats-usage-dump
image: appwrite-dev
networks:
- appwrite
volumes:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
- _APP_DATABASE_SHARED_TABLES
- _APP_STATS_USAGE_DUAL_WRITING_DBS
appwrite-task-scheduler-functions:
entrypoint: schedule-functions
<<: *x-logging
@@ -973,7 +942,7 @@ services:
appwrite-browser:
container_name: appwrite-browser
image: appwrite/browser:0.2.2
image: appwrite/browser:0.2.4
networks:
- appwrite
@@ -982,7 +951,7 @@ services:
hostname: exc1
<<: *x-logging
stop_signal: SIGINT
image: openruntimes/executor:0.7.13
image: openruntimes/executor:0.7.16
restart: unless-stopped
networks:
- appwrite
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
@@ -13,7 +13,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);

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