Compare commits

...
Author SHA1 Message Date
Jake Barnby 7fc214afbe Update libs 2024-03-05 11:55:29 +01:00
Jake Barnby c768375e13 Set tenant for CLI scope db 2024-03-04 20:54:35 +01:00
Jake Barnby fcc5a747d1 Fix test 2024-03-04 20:26:11 +01:00
Jake Barnby 78e4c0611b Update deps 2024-03-04 20:02:45 +01:00
Jake Barnby 74a3d6531f Merge remote-tracking branch 'origin/refactor-usage-sn' into feat-isolation-modes
# Conflicts:
#	composer.json
#	composer.lock
#	src/Appwrite/Platform/Tasks/CalcTierStats.php
#	tests/e2e/Services/Projects/ProjectsConsoleClientTest.php
2024-03-04 19:50:10 +01:00
Christy JacobandGitHub 45092a1049 Update docker-compose.yml 2024-03-01 22:10:25 +05:30
868bba52aa Update app/init.php
Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2024-03-01 22:05:42 +05:30
Christy Jacob 0b4716721d chore: update composer 2024-03-01 16:16:29 +00:00
Christy Jacob 2ffcb9b07e Merge branch 'main' of https://github.com/appwrite/appwrite into refactor-usage-sn 2024-03-01 16:08:03 +00:00
Christy JacobandGitHub d91f6960f7 Merge pull request #7661 from appwrite/chore-usage-queue-health
usage/usage-dump queue health endpoints
2024-03-01 21:25:02 +05:30
Torsten DittmannandGitHub 3542d360b0 Merge pull request #7698 from appwrite/update-error-message
chore: update error types for create account endpoints
2024-03-01 14:03:49 +01:00
Torsten DittmannandGitHub 9a821e250f Merge pull request #7697 from appwrite/chore-sync-1.4.x-into-main
Chore sync 1.4.x into main
2024-03-01 13:59:33 +01:00
Christy Jacob d1715e3bf4 chore: update tests 2024-03-01 12:50:11 +00:00
Christy Jacob c8a3b709ee chore: update error types for create account endpoints 2024-03-01 07:37:31 +00:00
Steven NguyenandGitHub fed197a313 Merge branch '1.4.x' into chore-sync-1.4.x-into-main 2024-02-29 21:53:39 +00:00
Christy JacobandGitHub ec85ec9f2a Merge pull request #7692 from appwrite/deletes-queue-retry
adding limit to queue retry
2024-02-29 00:47:09 +05:30
shimon 1a59361200 adding limit to queue retry 2024-02-28 21:15:59 +02:00
shimon 658396b4a8 adding limit to queue retry 2024-02-28 21:09:10 +02:00
shimon 53438accce adding limit to queue retry 2024-02-28 21:01:42 +02:00
shimon 84f47dc1d2 adding limit to queue retry 2024-02-28 20:21:35 +02:00
Christy JacobandGitHub 1538f78c18 Merge pull request #7672 from appwrite/fix-error-code
Change status code from 503 to 403
2024-02-28 10:41:19 +05:30
Christy JacobandGitHub 6acf6adf99 Merge pull request #7674 from appwrite/feat-add-ssl-to-smtp
Allow ssl along with tls in custom smtp
2024-02-28 10:40:49 +05:30
Khushboo Verma af3d6b2308 Allow ssl along with tls in custom smtp 2024-02-26 20:40:41 +05:30
Khushboo Verma 260928942b Update tests 2024-02-26 17:58:57 +05:30
Khushboo Verma bbcb5e8a6e Change status code from 503 to 403 2024-02-26 17:41:19 +05:30
Christy JacobandGitHub 03d6eb7401 Merge pull request #7669 from appwrite/main
Sync main
2024-02-26 17:39:33 +05:30
Jake BarnbyandGitHub 821e323a40 Merge pull request #7648 from UtkarshAhuja2003/fix-7587-list-api-select
[Fix]: Remove internal attributes on select query
2024-02-26 18:33:36 +13:00
navjotNSKandTorsten Dittmann cab2233816 Formatting 2024-02-25 20:24:36 +01:00
navjotNSKandTorsten Dittmann 3a8c5a2e65 Default value added for name 2024-02-25 20:24:36 +01:00
Utkarsh Ahuja faeb9aa8d4 tests: internal id in query select 2024-02-25 14:22:12 +00:00
shimon 92dfe93033 Merge branch 'main' of github.com:appwrite/appwrite into chore-usage-queue-health 2024-02-25 10:32:02 +02:00
Torsten DittmannandGitHub 3a524c24d9 Merge pull request #7656 from appwrite/fix-function-id-2
Fix-function-id-2
2024-02-24 19:32:24 +01:00
Eldad Fux b78725e650 Hide error messages from HTML templates 2024-02-24 19:12:27 +01:00
Eldad Fux e7a847a417 Fixed ID class namespace 2024-02-24 19:01:00 +01:00
Christy JacobandGitHub 0ad44ceb94 Merge pull request #7654 from appwrite/lohanidamodar-patch-3
Fix return
2024-02-24 20:49:37 +05:30
Damodar LohaniandGitHub 9fe0a5a31b Update Mail.php 2024-02-24 21:03:18 +05:45
Christy JacobandGitHub 07f7271c51 Merge pull request #7653 from appwrite/fix-mail-reset-attachment
Fix mail reset attachment
2024-02-24 20:29:41 +05:30
Damodar Lohani d91a0e3048 reset variables 2024-02-24 14:56:53 +00:00
Damodar Lohani ea484e593b format 2024-02-24 14:49:17 +00:00
Damodar Lohani ca1c83c2cf method to reset attachment 2024-02-24 14:33:38 +00:00
Utkarsh Ahuja 8c4473932f fix: list api select query 2024-02-24 10:55:33 +00:00
Christy JacobandGitHub d5c24df28d Merge pull request #7643 from appwrite/fix-storage-health-check
Fix content-type of file
2024-02-24 01:30:16 +05:30
Khushboo Verma 141cdf4c82 Fix content-type of file 2024-02-23 20:10:25 +05:30
Christy JacobandGitHub f79a310965 Merge pull request #7622 from appwrite/feat-publish-arm64
Add ARM64 to docker publish
2024-02-23 18:59:18 +05:30
Christy JacobandGitHub 65d99f8f90 Merge pull request #7632 from appwrite/revert-7630-revert-7627-fix-double-proxy
Fix: Router CURL
2024-02-22 15:17:12 +05:30
Christy JacobandGitHub c04f54da64 Revert "Revert "Fix: Router CURL"" 2024-02-22 15:10:18 +05:30
Christy JacobandGitHub 17888cc02d Merge pull request #7630 from appwrite/revert-7627-fix-double-proxy
Revert "Fix: Router CURL"
2024-02-22 12:27:36 +05:30
Christy JacobandGitHub d2787c8555 Revert "Fix: Router CURL" 2024-02-22 12:26:01 +05:30
Christy JacobandGitHub 42ca924557 Merge pull request #7629 from appwrite/revert-7614-chore-usage-queue-health
Revert "usage/usage-dump queue health endpoints"
2024-02-22 12:24:55 +05:30
Christy JacobandGitHub a8098831a3 Revert "usage/usage-dump queue health endpoints" 2024-02-22 12:21:48 +05:30
Christy JacobandGitHub 3f5e40ad46 Merge pull request #7591 from appwrite/feat-storage-health-check
Add storage health check
2024-02-22 12:16:10 +05:30
Eldad A. FuxandGitHub 10d882ce50 Merge pull request #7627 from appwrite/fix-double-proxy
Fix: Router CURL
2024-02-21 20:07:57 +01:00
Bradley Schofield 7a5d64a85f Merge branch 'refactor-usage-sn' into fix-double-proxy 2024-02-21 18:24:44 +00:00
Matej Bačo b03783c588 Fix bigs until works 2024-02-21 18:14:24 +01:00
Matej Bačo 6567cff5dc Fix missing todo 2024-02-21 17:03:48 +00:00
Shimon NewmanandGitHub db5c44c843 Merge pull request #7626 from appwrite/fix-msg91
fix: msg91
2024-02-21 18:41:27 +02:00
loks0n b2e1c162d2 chore: fmt 2024-02-21 16:27:37 +00:00
loks0n e3c261b9e4 fix: msg91 2024-02-21 16:24:55 +00:00
Matej Bačo 0dd2889de5 Fix double router curl 2024-02-21 14:51:21 +00:00
Bradley Schofield cc8705253e Add Docker Buildx for multiplatform 2024-02-21 10:12:20 +00:00
Eldad A. FuxandGitHub 14e81c2e27 Merge pull request #6826 from GuptaPratik02/doc-sdks-python-update-getting-started-guide
Update GETTING_STARTED.md
2024-02-20 17:50:41 +01:00
Bradley Schofield d60e7c641f Add ARM64 to docker publish 2024-02-20 15:56:25 +00:00
Vincent (Wen Yu) GeandGitHub f287e60e87 Merge branch 'main' into doc-sdks-python-update-getting-started-guide 2024-02-20 10:25:16 -05:00
Shimon NewmanandGitHub 3f7d35065e Merge pull request #7614 from appwrite/chore-usage-queue-health
usage/usage-dump queue health endpoints
2024-02-20 09:59:52 +02:00
Christy JacobandGitHub abc67ab0c6 Merge pull request #7615 from appwrite/fix-project-usage
usage logs updates
2024-02-20 09:26:03 +05:30
Damodar LohaniandGitHub c2ae330888 fix bandwidth usage 2024-02-20 09:14:48 +05:45
shimon 1577be9172 usage/usage-dump queue health endpoints 2024-02-19 21:36:14 +02:00
Matej Bačo 505b481537 Revert "Add smarter traefik load balancing with health check"
This reverts commit 2ab6156db4.
2024-02-19 14:10:35 +00:00
Matej Bačo 2ab6156db4 Add smarter traefik load balancing with health check 2024-02-19 14:08:15 +00:00
Eldad A. FuxandGitHub 0f7c73c1ab Merge pull request #7608 from appwrite/fix-project-usage
fix project network usage
2024-02-19 08:58:29 +01:00
Damodar Lohani 928ae74ffe fix project network usage 2024-02-19 06:04:29 +00:00
Khushboo Verma e4a86d9777 Remove global function 2024-02-19 09:19:54 +05:30
Eldad A. FuxandGitHub 44a9aed48e Merge pull request #7165 from appwrite/feat-more-phone-validation
Feat more phone validation
2024-02-18 22:39:45 +01:00
Eldad A. FuxandGitHub ad78259c10 Merge pull request #7375 from appwrite/fix-sentry-errors
Update exception for github session not found
2024-02-18 22:37:00 +01:00
Eldad A. FuxandGitHub 2c4a9e5ea9 Merge pull request #7566 from appwrite/chore-update-image-lib
Update image lib
2024-02-18 21:47:10 +01:00
Khushboo Verma 3b1233eaa9 Add deviceFunctions and deviceBuilds as well 2024-02-18 18:28:41 +05:30
Eldad A. FuxandGitHub 2a5df03c89 Merge pull request #7583 from appwrite/dev-introduce-redis-insights
dev: introduce redis insights
2024-02-18 06:46:35 +01:00
Christy JacobandGitHub c3ddc6a05d Merge pull request #5616 from appwrite/refactor-cache-poc
Refactor cache
2024-02-15 21:00:16 +05:30
Christy JacobandGitHub db792999c1 Merge pull request #7598 from appwrite/projectId-to-logger-2
Project id to logger
2024-02-15 20:46:14 +05:30
shimon ed4319314a Addressed comments 2024-02-15 17:15:10 +02:00
shimon 2a5f21e982 Addressed comments 2024-02-15 17:12:37 +02:00
Christy JacobandGitHub 7dbb1c6399 Merge branch 'main' into refactor-cache-poc 2024-02-15 20:33:57 +05:30
Khushboo Verma 00db19257d Add health storage check 2024-02-15 11:57:24 +05:30
Christy JacobandGitHub f0a4cf78ab Merge pull request #7588 from appwrite/feat-usage-log
usage logs updates
2024-02-15 02:41:19 +05:30
shimon dae01f7077 usage logs updates 2024-02-14 23:07:25 +02:00
shimon 26af9b7463 usage logs updates 2024-02-14 23:05:01 +02:00
shimon 459db9b43e usage updates 2024-02-14 07:34:12 +02:00
Torsten Dittmann 3476ab2627 dev: introduce redis insights 2024-02-13 12:26:02 +00:00
Jake BarnbyandGitHub cbf1085850 Merge pull request #7135 from appwrite/remove-deletes-db-leftovers
Remove database methods from deletes worker
2024-02-13 23:13:24 +13:00
shimon dac0e2a543 Merge branch 'main' of github.com:appwrite/appwrite into refactor-cache-poc
 Conflicts:
	src/Appwrite/Platform/Workers/UsageHook.php
2024-02-13 10:48:47 +02:00
Christy JacobandGitHub c076dfe6f1 Merge pull request #7576 from appwrite/refactor-usage-sn
Refactor usage sn
2024-02-12 23:05:56 +05:30
Jake BarnbyandGitHub f5aebe6673 Merge pull request #7559 from Souptik2001/fix-7109-user-activity-log
Fix missing user activity logs
2024-02-12 23:04:20 +13:00
shimon 70effd1e99 Sync against main 2024-02-12 11:14:26 +02:00
shimon e7ace61273 Sync against main 2024-02-12 11:10:52 +02:00
shimon 6b6f04d2d3 Merge branch 'main' of github.com:appwrite/appwrite into refactor-cache-poc
 Conflicts:
	app/config/collections.php
	app/controllers/shared/api.php
2024-02-12 10:55:53 +02:00
Jake Barnby be761b31c1 Update image lib 2024-02-12 14:21:06 +13:00
Eldad A. FuxandGitHub eb75b527ad Merge pull request #7560 from appwrite/update-x-example-format
Update place holders from [PARAM_NAME] to <PARAM_NAME>
2024-02-11 23:04:42 +01:00
Damodar LohaniandGitHub d4ad369a7e Merge pull request #7563 from appwrite/fix-user-deletion
PEA-233-prevent console user deletion before deleting their team
2024-02-11 16:04:59 +05:45
Damodar Lohani eb7e2fd23b fix injection 2024-02-11 09:46:39 +00:00
Damodar Lohani 36eabfa2dd fix check twice 2024-02-11 09:45:36 +00:00
Damodar Lohani 2634c928c7 fix format 2024-02-11 09:34:13 +00:00
Damodar Lohani e462d73f65 prevent user with active team, from deletion 2024-02-11 09:31:09 +00:00
Christy JacobandGitHub e2baefe8c6 Merge pull request #7500 from appwrite/fix-account-delete
PEA-233-prevent console user deletion before deleting their team
2024-02-11 14:52:24 +05:30
Damodar LohaniandGitHub 4ffde8e827 fix indentation 2024-02-11 14:55:14 +05:45
Damodar LohaniandGitHub 57a695367b fix typo 2024-02-11 14:54:32 +05:45
Damodar LohaniandGitHub 681688e252 fix rename 2024-02-11 14:52:54 +05:45
Damodar LohaniandGitHub a8718bccb5 fix rename 2024-02-11 14:42:21 +05:45
eba03cb126 Update app/config/errors.php
Co-authored-by: Christy Jacob <christyjacob4@gmail.com>
2024-02-11 14:41:32 +05:45
622bdb7b2b Update app/config/errors.php
Co-authored-by: Christy Jacob <christyjacob4@gmail.com>
2024-02-11 14:41:25 +05:45
c8720805c7 Update app/controllers/api/account.php
Co-authored-by: Christy Jacob <christyjacob4@gmail.com>
2024-02-11 14:41:19 +05:45
Christy JacobandGitHub fdb11af6bb Merge pull request #7561 from appwrite/update-team-counts
Update team counts
2024-02-11 12:15:05 +05:30
shimon b09386727b Usage logs text update 2024-02-10 10:34:44 +02:00
Christy Jacob f3e8994bb8 fix: use atomic operations for updating team count 2024-02-09 23:21:17 +05:30
Christy Jacob fb68dcc89e fix: use atomic operations for updating team count 2024-02-09 23:20:37 +05:30
Christy Jacob 5abcb86fd7 fix: use atomic operations for updating team count 2024-02-09 23:18:18 +05:30
Christy JacobandGitHub ff93957922 Merge pull request #7503 from appwrite/usage-queue-poc
Usage queue poc
2024-02-09 20:12:40 +05:30
shimon 179a045399 Merge branch 'refactor-usage-sn' of github.com:appwrite/appwrite into usage-queue-poc
 Conflicts:
	composer.lock
2024-02-09 16:29:26 +02:00
shimon d0985db27d interval update 2024-02-09 13:22:48 +02:00
shimon 3788d5bceb interval update 2024-02-09 12:56:37 +02:00
Vincent (Wen Yu) Ge f785ffbd71 Update place holders from [PARAM_NAME] to <PARAM_NAME> 2024-02-09 03:06:38 +00:00
shimon c1fb4ecf39 interval update 2024-02-08 21:41:23 +02:00
Souptik Datta e6a97bb36a Merge branch 'master' into fix-7109-user-activity-log 2024-02-09 00:40:36 +05:30
shimon a1539395c6 interval update 2024-02-08 21:08:29 +02:00
Christy JacobandGitHub 94468aa28f Merge pull request #7556 from appwrite/refactor-usage-sn
Sync main with refactor-usage-sn
2024-02-09 00:25:07 +05:30
shimon 72ee7d7f34 interval update 2024-02-08 20:51:54 +02:00
Souptik Datta 8d7be399d3 fix: Fix project user activity log's missing fields and total count
Signed-off-by: Souptik Datta <souptikdatta2001@gmail.com>
2024-02-09 00:15:48 +05:30
Souptik Datta f42a78ef9c fix: Fix account activity logs total count
Signed-off-by: Souptik Datta <souptikdatta2001@gmail.com>
2024-02-09 00:14:37 +05:30
Christy Jacob 5842f1950a chore: linter 2024-02-08 18:02:35 +00:00
ba4f708137 Apply suggestions from code review
Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
2024-02-08 23:26:43 +05:30
Christy Jacob 2fdd0656d0 Merge branch 'main' of https://github.com/appwrite/appwrite into refactor-usage-sn 2024-02-08 11:48:53 +00:00
shimon 790cdc297b composer update 2024-02-08 10:26:45 +02:00
shimon 990698e423 composer update 2024-02-08 09:32:05 +02:00
shimon 632f78140f Merge branch 'refactor-usage-sn' of github.com:appwrite/appwrite into usage-queue-poc
 Conflicts:
	composer.json
	composer.lock
2024-02-08 09:29:12 +02:00
Christy JacobandGitHub 243ddd4b33 Merge pull request #7519 from appwrite/update-param-name
Update param name
2024-02-08 12:55:19 +05:30
shimon 93a99b561c remove debug lines 2024-02-07 11:54:18 +02:00
Christy JacobandGitHub 6a5defb91c Merge pull request #7520 from appwrite/feat-sms-metric
Add count for messages(sms) metric
2024-02-06 22:44:06 +05:30
Christy JacobandGitHub 2f93dcc4df Merge pull request #7547 from appwrite/feat-certificate-health-check
Add health certificate validity endpoint
2024-02-06 22:31:07 +05:30
Christy JacobandGitHub 603b8ebd8c Merge pull request #7544 from appwrite/fix-add-delay-to-maintenance-worker
Add a 20 second delay to maintenance worker
2024-02-06 22:28:47 +05:30
Christy JacobandGitHub 4dee937e36 Update app/config/variables.php 2024-02-06 22:26:47 +05:30
Christy JacobandGitHub bb92074093 Update .env 2024-02-06 22:26:40 +05:30
Khushboo Verma fb127270ce Add test for empty domain 2024-02-06 16:04:58 +05:30
Khushboo Verma 11ceeff5ca Add health certificate validity endpoint 2024-02-06 15:15:03 +05:30
Khushboo Verma 8ed5489d9c Added env variable to variables.php and compose.phtml 2024-02-05 16:11:37 +05:30
Khushboo Verma 1fefb7e133 Add a 20 second delay to maintenance worker 2024-02-05 15:01:23 +05:30
shimon 6a6c3445fa updates 2024-02-04 20:02:01 +02:00
Eldad A. FuxandGitHub 6fe725ff9d Merge pull request #7539 from appwrite/fix-client-error-reporting
Fix: client error reporting
2024-02-02 15:12:24 +01:00
Matej Bačo 4115537f72 Fix client error reporting 2024-02-02 14:33:52 +01:00
Jake BarnbyandGitHub 26b2c27eb0 Merge pull request #7531 from appwrite/remove-debug-sn
remove debug leftovers
2024-02-01 21:38:26 +13:00
shimon 62bc540db0 removed var_dump leftovers 2024-02-01 10:35:38 +02:00
shimon 1ef5c9bfcd removed var_dump leftovers 2024-02-01 10:32:40 +02:00
shimon bfe042dc3e fix 2024-01-30 13:29:15 +02:00
shimon 5518ca165e remarks 2024-01-30 13:24:57 +02:00
shimon 13a879c274 Add count for messages(sms) metric 2024-01-30 11:19:10 +02:00
Christy Jacob 7b5be4e154 chore: update team membership deletion 2024-01-30 08:42:46 +00:00
Christy Jacob 3c7fae7843 chore: update param name 2024-01-30 08:10:13 +00:00
shimon 44ed6826a9 refactor usage poc 2024-01-28 15:33:04 +02:00
shimon 36fddd4156 refactor usage poc 2024-01-28 11:46:13 +02:00
shimon 7a2ee683e3 refactor usage poc 2024-01-28 11:28:59 +02:00
Damodar Lohani 359b3326d9 remove unused import 2024-01-28 03:03:20 +00:00
Damodar Lohani 7a94bd143c update account delete test 2024-01-28 03:02:44 +00:00
Damodar Lohani 9b7a5f55b7 fix linter 2024-01-28 03:01:34 +00:00
Damodar Lohani e5dfed0aa3 fix, check only for confirmed membership 2024-01-28 02:47:23 +00:00
Damodar Lohani 215a139e87 prevent console user deletion before deleting their team 2024-01-28 02:10:14 +00:00
Jake BarnbyandGitHub 64fde6cddd Merge pull request #7464 from appwrite/fix-ruby-null-params
Update ruby
2024-01-24 18:50:47 +13:00
shimon 370704fafd moved cache collection to $commonCollections collection config 2024-01-21 10:47:00 +02:00
Jake Barnby 6629fdd87f Bump generator 2024-01-20 00:24:09 +13:00
shimon 554bc89cb5 sync config::collections against main 2024-01-18 14:14:24 +02:00
shimon b08e3d4e7b sync config::collections against main 2024-01-18 14:12:00 +02:00
shimon 90cf28389c sync config::collections against main 2024-01-18 14:10:57 +02:00
shimon 8581df9c14 Merge branch 'main' of github.com:appwrite/appwrite into refactor-cache-poc 2024-01-18 14:05:58 +02:00
Jake Barnby de96e0f3dc Update ruby 2024-01-18 20:07:39 +13:00
shimon 03f2041913 Merge branch 'main' of github.com:appwrite/appwrite into refactor-cache-poc 2024-01-07 18:09:48 +02:00
Torsten DittmannandGitHub 6b1330e400 Merge pull request #7385 from appwrite/fix-app-console-hostnames-check
Fix app console hostnames check
2024-01-03 21:28:29 +01:00
Steven Nguyen faf39fcc81 Fix _APP_CONSOLE_HOSTNAMES check
Ensure invalid hostnames such as empty strings are not added as a
hostname.
2024-01-03 19:30:49 +00:00
Steven Nguyen 06e385b346 Add changes from previous console platforms variable PR
See https://github.com/appwrite/appwrite/pull/4581
2024-01-03 19:30:42 +00:00
Torsten DittmannandGitHub 7a2f7f5a17 Merge pull request #7360 from appwrite/feat-console-hostnames
feat: console hostname env variable
2024-01-02 17:16:34 +01:00
Khushboo Verma 671b1624d5 Update exception for github session not found 2024-01-02 16:20:20 +05:30
Torsten Dittmann cc1272f80b feat: add new env variable to compsoe files 2023-12-29 22:09:59 +01:00
Torsten Dittmann 9b2fbc5c52 feat: console hostname env variable 2023-12-29 21:52:50 +01:00
Jake Barnby 4710310629 Check if self-hosted 2023-12-08 18:33:35 +01:00
Jake Barnby 4245c0b86e Update dependencies 2023-12-08 18:07:38 +01:00
Jake Barnby 6b0586eaf6 Remove DB attribute 2023-12-08 18:06:53 +01:00
Jake Barnby 018b7c38bd Merge remote-tracking branch 'origin/1.4.x' into feat-isolation-modes
# Conflicts:
#	src/Appwrite/Platform/Tasks/Hamster.php
2023-12-08 13:34:28 +01:00
Jake Barnby 7e12da5a2a Use hard-coded DB name instead of project attribute 2023-11-30 16:32:15 +13:00
Jake Barnby e109f1e008 Add metadata in worker dbs 2023-11-30 16:06:49 +13:00
Jake Barnby 4f539f1ed4 Update switch to match 2023-11-30 16:04:15 +13:00
Jake Barnby 7104f9e2c8 Add comments marking shareTables project attributes + header overrides as temporary 2023-11-28 02:08:04 +13:00
Jake Barnby 632c902e1c Remove debug trace 2023-11-28 01:53:24 +13:00
Jake Barnby c1f10b06a3 Fix index limit test 2023-11-28 01:34:29 +13:00
Jake Barnby c4806e883e Update lock 2023-11-28 01:00:22 +13:00
Jake Barnby 2c71de1d1b Merge remote-tracking branch 'origin/1.4.x' into feat-isolation-modes
# Conflicts:
#	composer.lock
2023-11-28 00:57:17 +13:00
Jake Barnby 2e89113e6a Self review 2023-11-28 00:52:46 +13:00
Jake Barnby edee5400ba Fix casing 2023-11-28 00:43:21 +13:00
Jake Barnby 82dfe5ddee Add tests 2023-11-28 00:30:02 +13:00
Jake Barnby 0885f31dd7 Update database 2023-11-28 00:29:23 +13:00
Jake Barnby 9472bff8f9 Fix project create tenant set/reset 2023-11-28 00:27:41 +13:00
Jake Barnby 68548ebd47 Fix worker tenant set/reset 2023-11-28 00:27:16 +13:00
Jake Barnby b9ac8e644d Set/reset tenant on init 2023-11-28 00:26:35 +13:00
Jake Barnby 7b8e37b03d Update method names 2023-11-27 15:22:05 +13:00
shimon 9960912bb1 sync against main 2023-11-26 18:52:02 +02:00
shimon 1869852985 Merge branch 'main' of github.com:appwrite/appwrite into refactor-cache-poc
 Conflicts:
	app/controllers/shared/api.php
	composer.lock
	src/Appwrite/Platform/Workers/Deletes.php
2023-11-26 16:29:18 +02:00
Jake Barnby 35163ff52a Check project shareTables status when configuring databases 2023-11-23 01:13:24 +13:00
Jake Barnby f44543f083 Add shareTables attribute to project 2023-11-23 01:12:19 +13:00
Jake Barnby cefc1b6519 Add base share tables check when creating project 2023-11-23 01:11:48 +13:00
Jake Barnby eb5fc0797f Update abuse/audit 2023-11-23 00:43:32 +13:00
Jake Barnby 464b913e90 Update for function name change 2023-11-22 21:32:36 +13:00
shimon 336afc5ca2 Merge branch 'main' of github.com:appwrite/appwrite into remove-deletes-db-leftovers 2023-11-19 15:30:36 +02:00
loks0n 33f92d9ab3 chore: fmt 2023-11-17 18:12:15 +00:00
loks0n 61e2b7a787 feat: more phone validation 2023-11-17 18:09:20 +00:00
shimon 5a3fd99a28 remove deleteCollection()
and deleteDatabase() from deletes worker
2023-11-14 20:05:59 +02:00
Pratik GuptaandGitHub eefbc68f6b Update web GETTING_STARTED.md
Removed phone number from account.create() function as it does not accept it.
2023-10-24 09:12:13 +05:30
Pratik GuptaandGitHub 7791cdc201 Rectified flutter EXAMPLES.md
Removed phone number from account.create() function as it does not accept it.
2023-10-24 09:09:18 +05:30
Pratik GuptaandGitHub daec743e8c Rectified flutter GETTING_STARTED.md
Removed phone number from account.create() function as it does not accept it.
2023-10-24 09:07:04 +05:30
Pratik GuptaandGitHub c2ce7d0aa1 Rectified flutter-dev EXAMPLES.md
Removed phone number from account.create() function as it does not accept it.
2023-10-24 09:04:48 +05:30
Pratik GuptaandGitHub 9eea574df5 Rectified apple GETTING_STARTED.md
Removed phone number from account.create() function as it does not accept it.
2023-10-24 09:01:28 +05:30
Pratik GuptaandGitHub da504ba46c Rectified android GETTING_STARTED.md
removed phone number from account.create() function as it does not accept it.
2023-10-24 08:59:36 +05:30
Pratik GuptaandGitHub c2c645188d Update nodejs GETTING_STARTED.md 2023-10-19 21:10:08 +05:30
Pratik GuptaandGitHub 7d23b0af5f Update dotnet GETTING_STARTED.md 2023-10-19 21:08:47 +05:30
Pratik GuptaandGitHub 0853de0760 Update web GETTING_STARTED.md 2023-10-19 01:21:22 +05:30
Pratik GuptaandGitHub b2e4513af3 Update swift GETTING_STARTED.md 2023-10-19 01:19:07 +05:30
Pratik GuptaandGitHub a26c9214cb Update ruby GETTING_STARTED.md 2023-10-19 01:17:18 +05:30
Pratik GuptaandGitHub d3b91b5ec5 Update python GETTING_STARTED.md 2023-10-19 01:14:58 +05:30
Pratik GuptaandGitHub a5ea32c237 Update php GETTING_STARTED.md 2023-10-19 01:12:31 +05:30
Pratik GuptaandGitHub 88efb36ead Update nodejs GETTING_STARTED.md 2023-10-19 01:10:28 +05:30
Pratik GuptaandGitHub 902f20f20c Update kotlin GETTING_STARTED.md 2023-10-19 01:08:06 +05:30
Pratik GuptaandGitHub f6281158a2 Update flutter EXAMPLES.md 2023-10-19 01:05:43 +05:30
Pratik GuptaandGitHub 154e972217 Update flutter GETTING_STARTED.md 2023-10-19 01:04:32 +05:30
Pratik GuptaandGitHub 0c2374e66a Update flutter-dev EXAMPLES.md 2023-10-19 01:02:17 +05:30
Pratik GuptaandGitHub 15863c2886 Update dotnet GETTING_STARTED.md 2023-10-19 00:57:12 +05:30
Pratik GuptaandGitHub 618c14524d Update deno GETTING_STARTED.md 2023-10-19 00:55:24 +05:30
Pratik GuptaandGitHub 6c4983f65f Update dart EXAMPLES.md 2023-10-19 00:52:39 +05:30
Pratik GuptaandGitHub ea282a1761 Update dart GETTING_STARTED.md 2023-10-19 00:51:10 +05:30
Pratik GuptaandGitHub 8fed930b7d Update apple GETTING_STARTED.md 2023-10-19 00:43:47 +05:30
Pratik GuptaandGitHub a66fc13ebc Update android GETTING_STARTED.md 2023-10-19 00:40:09 +05:30
Pratik GuptaandGitHub 8d7ab130ff changes made web GETTING_STARTED.md 2023-10-17 18:52:28 +05:30
Pratik GuptaandGitHub 569d54bee3 changes made swift GETTING_STARTED.md 2023-10-17 18:49:51 +05:30
Pratik GuptaandGitHub 5138d4c0f9 changes made ruby GETTING_STARTED.md 2023-10-17 18:45:24 +05:30
Pratik GuptaandGitHub d37bfa0a5e changes made php GETTING_STARTED.md 2023-10-17 18:41:10 +05:30
Pratik GuptaandGitHub 2cce14418c changes made nodejs GETTING_STARTED.md 2023-10-17 18:37:53 +05:30
Pratik GuptaandGitHub e6b0d22e07 changes made flutter EXAMPLES.md 2023-10-17 18:26:57 +05:30
Pratik GuptaandGitHub ba8cafbd45 changes made flutter GETTING_STARTED.md 2023-10-17 18:25:00 +05:30
Pratik GuptaandGitHub e920c1f8b4 changes made flutter-dev EXAMPLES.md 2023-10-17 18:21:19 +05:30
Pratik GuptaandGitHub 8ac7aca2a4 changes made dotnet GETTING_STARTED.md 2023-10-17 18:19:02 +05:30
Pratik GuptaandGitHub ec17284bfd changes made deno GETTING_STARTED.md 2023-10-17 18:15:42 +05:30
Pratik GuptaandGitHub 2d123f60e1 changes made dart EXAMPLES.md 2023-10-17 18:12:29 +05:30
Pratik GuptaandGitHub 7721f29d0e changes made dart GETTING_STARTED.md 2023-10-17 18:09:33 +05:30
Pratik GuptaandGitHub af87c24cfd changes made apple GETTING_STARTED.md 2023-10-17 18:06:43 +05:30
Pratik GuptaandGitHub 4b7c13d3e2 changes made android GETTING_STARTED.md 2023-10-17 18:02:37 +05:30
Pratik GuptaandGitHub bb9dd4423d Update web GETTING_STARTED.md 2023-10-17 01:49:47 +05:30
Pratik GuptaandGitHub 303212fba8 Update swift GETTING_STARTED.md 2023-10-17 01:47:43 +05:30
Pratik GuptaandGitHub acc408f5ab Update ruby GETTING_STARTED.md 2023-10-17 01:45:54 +05:30
Pratik GuptaandGitHub 086116d0f0 Update php GETTING_STARTED.md 2023-10-17 01:43:09 +05:30
Pratik GuptaandGitHub e93681afc0 Update nodejs GETTING_STARTED.md 2023-10-17 01:36:49 +05:30
Pratik GuptaandGitHub 7d2b4503e3 Update kotlin GETTING_STARTED.md 2023-10-17 01:34:32 +05:30
Pratik GuptaandGitHub 0d314df561 Update flutter EXAMPLES.md 2023-10-17 01:31:20 +05:30
Pratik GuptaandGitHub 006d4237f5 Update flutter GETTING_STARTED.md 2023-10-17 01:30:16 +05:30
Pratik GuptaandGitHub 2c3b860e63 Update flutter-dev EXAMPLES.md 2023-10-17 01:28:09 +05:30
Pratik GuptaandGitHub 613a733169 Update dart EXAMPLES.md 2023-10-17 01:25:54 +05:30
Pratik GuptaandGitHub 0587aec643 Update dotnet GETTING_STARTED.md 2023-10-17 01:22:16 +05:30
Pratik GuptaandGitHub b334f2e345 Update deno GETTING_STARTED.md 2023-10-17 01:19:54 +05:30
Pratik GuptaandGitHub 777c8dd587 Update dart GETTING_STARTED.md 2023-10-17 01:18:01 +05:30
Pratik GuptaandGitHub 4be8be1353 Update apple GETTING_STARTED.md 2023-10-17 01:14:26 +05:30
Pratik GuptaandGitHub 8cc1c0d6dc Update android GETTING_STARTED.md 2023-10-17 01:07:53 +05:30
Vincent (Wen Yu) GeandGitHub eaba2eb7e5 Merge branch 'main' into doc-sdks-python-update-getting-started-guide 2023-10-12 11:00:06 -04:00
Pratik GuptaandGitHub 9ccaa5a883 Update GETTING_STARTED.md
Changed user1 name and (email1 -> email).
2023-10-11 18:14:12 +05:30
Pratik GuptaandGitHub 93fa7496b1 Update GETTING_STARTED.md
Fixed the issue mentioned in sdk-for-python repository Issue - 62.
Issue link - https://github.com/appwrite/sdk-for-python/issues/62
2023-10-06 18:10:24 +05:30
shimon 45f16e560c sync against master 2023-09-05 21:17:54 +03:00
shimon ec93239630 Merge branch 'master' of github.com:appwrite/appwrite into refactor-cache-poc
 Conflicts:
	app/config/collections.php
	app/controllers/api/storage.php
	app/controllers/shared/api.php
	app/init.php
	app/workers/deletes.php
2023-09-05 19:19:59 +03:00
shimon 2f7b0c9938 added bucketId to cache::deleteByResource 2023-07-22 17:31:33 +03:00
shimon ef12b75013 Merge branch 'master' of github.com:appwrite/appwrite into refactor-cache-poc
 Conflicts:
	app/init.php
2023-07-22 17:09:49 +03:00
shimon bed88baa6c added bucketId to cache::deleteByResource 2023-07-22 17:08:28 +03:00
shimon 9562b95285 saving file output to cache instead of decoding data to json 2023-05-31 19:34:12 +03:00
shimon e9fda6168c saving file output to cache instead of decoding data to json 2023-05-31 15:50:19 +03:00
shimon a6768bdc32 saving file output to cache instead of decoding data to json 2023-05-31 14:41:56 +03:00
265 changed files with 2578 additions and 1212 deletions
+3 -1
View File
@@ -1,4 +1,5 @@
_APP_ENV=development
_APP_EDITION=self-hosted
_APP_LOCALE=en
_APP_WORKER_PER_CORE=6
_APP_CONSOLE_WHITELIST_ROOT=disabled
@@ -73,11 +74,12 @@ _APP_EXECUTOR_SECRET=your-secret-key
_APP_EXECUTOR_HOST=http://proxy/v1
_APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1
_APP_MAINTENANCE_INTERVAL=86400
_APP_MAINTENANCE_DELAY=
_APP_MAINTENANCE_RETENTION_CACHE=2592000
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
_APP_MAINTENANCE_RETENTION_ABUSE=86400
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
_APP_USAGE_AGGREGATION_INTERVAL=60000
_APP_USAGE_AGGREGATION_INTERVAL=20
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
_APP_USAGE_STATS=enabled
+8 -2
View File
@@ -17,6 +17,12 @@ jobs:
fetch-depth: 2
submodules: recursive
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
@@ -35,11 +41,11 @@ jobs:
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
build-args: |
VERSION=${{ steps.meta.outputs.version }}
VITE_APPWRITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1
VITE_GA_PROJECT=G-L7G2B6PLDS
VITE_CONSOLE_MODE=cloud
push: true
tags: ${{ steps.meta.outputs.tags }}
tags: ${{ steps.meta.outputs.tags }}
+1
View File
@@ -13,3 +13,4 @@ debug/
app/sdks
dev/yasd_init.php
.phpunit.result.cache
appwrite.json
+2 -1
View File
@@ -99,7 +99,8 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/worker-webhooks && \
chmod +x /usr/local/bin/worker-migrations && \
chmod +x /usr/local/bin/worker-hamster && \
chmod +x /usr/local/bin/worker-usage
chmod +x /usr/local/bin/worker-usage && \
chmod +x /usr/local/bin/worker-usage-dump
# Cloud Executabless
+27 -3
View File
@@ -25,7 +25,7 @@ use Utopia\Registry\Registry;
Authorization::disable();
CLI::setResource('register', fn()=>$register);
CLI::setResource('register', fn() => $register);
CLI::setResource('cache', function ($pools) {
$list = Config::getParam('pools-cache', []);
@@ -72,7 +72,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) {
$collections = Config::getParam('collections', [])['console'];
$last = \array_key_last($collections);
if (!($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */
if (!($dbForConsole->exists($dbForConsole->getDatabase(), $last))) { /** TODO cache ready variable using registry */
throw new Exception('Tables not ready yet.');
}
@@ -103,7 +103,19 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
if (isset($databases[$databaseName])) {
$database = $databases[$databaseName];
$database->setNamespace('_' . $project->getInternalId());
if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) {
$database
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$database
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
return $database;
}
@@ -116,6 +128,18 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
$databases[$databaseName] = $database;
if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) {
$database
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$database
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
$database
->setNamespace('_' . $project->getInternalId())
->setMetadata('host', \gethostname())
+25 -3
View File
@@ -31,7 +31,7 @@ return [
Exception::GENERAL_SERVICE_DISABLED => [
'name' => Exception::GENERAL_SERVICE_DISABLED,
'description' => 'The requested service is disabled. You can enable the service from the Appwrite console.',
'code' => 503,
'code' => 403,
],
Exception::GENERAL_UNAUTHORIZED_SCOPE => [
'name' => Exception::GENERAL_UNAUTHORIZED_SCOPE,
@@ -103,6 +103,11 @@ return [
'description' => 'This method was not fully implemented yet. If you believe this is a mistake, please upgrade your Appwrite server version.',
'code' => 405,
],
Exception::GENERAL_BAD_REQUEST => [
'name' => Exception::GENERAL_BAD_REQUEST,
'description' => 'There was an error processing your request. Please check the inputs and try again.',
'code' => 400,
],
/** User Errors */
Exception::USER_COUNT_EXCEEDED => [
@@ -251,6 +256,11 @@ return [
'description' => 'User phone is already verified',
'code' => 409
],
Exception::USER_DELETION_PROHIBITED => [
'name' => Exception::USER_DELETION_PROHIBITED,
'description' => 'User deletion is not allowed for users with active memberships. Please delete all confirmed memberships before deleting the account.',
'code' => 400
],
/** Teams */
Exception::TEAM_NOT_FOUND => [
@@ -768,10 +778,22 @@ return [
],
/** Health */
Exception::QUEUE_SIZE_EXCEEDED => [
'name' => Exception::QUEUE_SIZE_EXCEEDED,
Exception::HEALTH_QUEUE_SIZE_EXCEEDED => [
'name' => Exception::HEALTH_QUEUE_SIZE_EXCEEDED,
'description' => 'Queue size threshold hit.',
'code' => 503,
'publish' => false
],
Exception::HEALTH_CERTIFICATE_EXPIRED => [
'name' => Exception::HEALTH_CERTIFICATE_EXPIRED,
'description' => 'The SSL certificate for the specified domain has expired and is no longer valid.',
'code' => 404,
],
Exception::HEALTH_INVALID_HOST => [
'name' => Exception::HEALTH_INVALID_HOST,
'description' => 'Failed to establish a connection to the specified domain. Please verify the domain name and ensure that the server is running and accessible.',
'code' => 404,
],
];
+1 -1
View File
@@ -303,7 +303,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '10.1.0',
'version' => '10.1.1',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'package' => 'https://rubygems.org/gems/appwrite',
'enabled' => true,
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10 -1
View File
@@ -408,7 +408,7 @@ return [
],
[
'name' => '_APP_SMTP_SECURE',
'description' => 'SMTP secure connection protocol. Empty by default, change to \'tls\' if running on a secure connection.',
'description' => 'SMTP secure connection protocol. Empty by default, change to \'tls\' or \'ssl\' if running on a secure connection.',
'introduction' => '',
'default' => '',
'required' => false,
@@ -948,6 +948,15 @@ return [
'question' => '',
'filter' => ''
],
[
'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.',
'introduction' => '1.5.0',
'default' => '0',
'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).',
+39 -31
View File
@@ -110,7 +110,7 @@ App::post('/v1/account')
Query::equal('providerEmail', [$email]),
]);
if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
if ($project->getAttribute('auths', [])['personalDataCheck'] ?? false) {
@@ -253,7 +253,7 @@ App::post('/v1/account/sessions/email')
$dbForProject->updateDocument('users', $user->getId(), $user);
}
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [
Permission::read(Role::user($user->getId())),
@@ -578,7 +578,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$currentDocument = $dbForProject->getDocument('sessions', $current);
if (!$currentDocument->isEmpty()) {
$dbForProject->deleteDocument('sessions', $currentDocument->getId());
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
}
}
@@ -637,7 +637,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Query::equal('providerEmail', [$email]),
]);
if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
try {
@@ -695,7 +695,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Query::notEqual('userId', $user->getId()),
]);
if (!empty($identitiesWithMatchingEmail)) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
$dbForProject->createDocument('identities', new Document([
@@ -766,7 +766,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$session->setAttribute('expire', $expire);
@@ -944,7 +944,7 @@ App::post('/v1/account/sessions/magic-url')
Query::equal('providerEmail', [$email]),
]);
if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
$userId = $userId === 'unique()' ? ID::unique() : $userId;
@@ -1000,7 +1000,7 @@ App::post('/v1/account/sessions/magic-url')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
if (empty($url)) {
$url = $request->getProtocol() . '://' . $request->getHostname() . '/auth/magic-url';
@@ -1177,7 +1177,7 @@ App::put('/v1/account/sessions/magic-url')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$tokens = $user->getAttribute('tokens', []);
@@ -1186,7 +1186,7 @@ App::put('/v1/account/sessions/magic-url')
* the recovery token but actually we don't need it anymore.
*/
$dbForProject->deleteDocument('tokens', $token);
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$user->setAttribute('emailVerification', true);
@@ -1324,7 +1324,7 @@ App::post('/v1/account/sessions/phone')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl');
@@ -1336,8 +1336,6 @@ App::post('/v1/account/sessions/phone')
$message = $message->setParam('{{token}}', $secret);
$message = $message->render();
var_dump($request->getIP());
var_dump($project->getId());
$queueForMessaging
->setRecipient($phone)
->setMessage($message)
@@ -1431,14 +1429,14 @@ App::put('/v1/account/sessions/phone')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
/**
* We act like we're updating and validating
* the recovery token but actually we don't need it anymore.
*/
$dbForProject->deleteDocument('tokens', $token);
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$user->setAttribute('phoneVerification', true);
@@ -1583,7 +1581,7 @@ App::post('/v1/account/sessions/anonymous')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$queueForEvents
->setParam('userId', $user->getId())
@@ -1990,7 +1988,7 @@ App::patch('/v1/account/email')
Query::notEqual('userId', $user->getId()),
]);
if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
$user
@@ -2009,7 +2007,7 @@ App::patch('/v1/account/email')
try {
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
} catch (Duplicate) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
}
$queueForEvents->setParam('userId', $user->getId());
@@ -2216,7 +2214,7 @@ App::delete('/v1/account/sessions/:sessionId')
;
}
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$queueForEvents
->setParam('userId', $user->getId())
@@ -2296,7 +2294,7 @@ App::patch('/v1/account/sessions/:sessionId')
$dbForProject->updateDocument('sessions', $sessionId, $session);
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
@@ -2366,7 +2364,7 @@ App::delete('/v1/account/sessions')
}
}
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$queueForEvents
->setParam('userId', $user->getId())
@@ -2451,7 +2449,7 @@ App::post('/v1/account/recovery')
Permission::delete(Role::user($profile->getId())),
]));
$dbForProject->deleteCachedDocument('users', $profile->getId());
$dbForProject->purgeCachedDocument('users', $profile->getId());
$url = Template::parseURL($url);
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $profile->getId(), 'secret' => $secret, 'expire' => $expire]);
@@ -2528,7 +2526,7 @@ App::post('/v1/account/recovery')
$queueForMails
->setRecipient($profile->getAttribute('email', ''))
->setName($profile->getAttribute('name'))
->setName($profile->getAttribute('name', ''))
->setBody($body)
->setVariables($emailVariables)
->setSubject($subject)
@@ -2632,7 +2630,7 @@ App::put('/v1/account/recovery')
* the recovery token but actually we don't need it anymore.
*/
$dbForProject->deleteDocument('tokens', $recovery);
$dbForProject->deleteCachedDocument('users', $profile->getId());
$dbForProject->purgeCachedDocument('users', $profile->getId());
$queueForEvents
->setParam('userId', $profile->getId())
@@ -2703,7 +2701,7 @@ App::post('/v1/account/verification')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$url = Template::parseURL($url);
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $verificationSecret, 'expire' => $expire]);
@@ -2852,7 +2850,7 @@ App::put('/v1/account/verification')
* the verification token but actually we don't need it anymore.
*/
$dbForProject->deleteDocument('tokens', $verification);
$dbForProject->deleteCachedDocument('users', $profile->getId());
$dbForProject->purgeCachedDocument('users', $profile->getId());
$queueForEvents
->setParam('userId', $userId)
@@ -2927,7 +2925,7 @@ App::post('/v1/account/verification/phone')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl');
@@ -2939,8 +2937,6 @@ App::post('/v1/account/verification/phone')
$message = $message->setParam('{{token}}', $secret);
$message = $message->render();
var_dump($request->getIP());
var_dump($project->getId());
$queueForMessaging
->setRecipient($user->getAttribute('phone'))
->setMessage($message)
@@ -3013,7 +3009,7 @@ App::put('/v1/account/verification/phone')
* We act like we're updating and validating the verification token but actually we don't need it anymore.
*/
$dbForProject->deleteDocument('tokens', $verification);
$dbForProject->deleteCachedDocument('users', $profile->getId());
$dbForProject->purgeCachedDocument('users', $profile->getId());
$queueForEvents
->setParam('userId', $user->getId())
@@ -3038,15 +3034,27 @@ App::delete('/v1/account')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->inject('user')
->inject('project')
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->inject('queueForDeletes')
->action(function (Document $user, Response $response, Database $dbForProject, Event $queueForEvents, Delete $queueForDeletes) {
->action(function (Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents, Delete $queueForDeletes) {
if ($user->isEmpty()) {
throw new Exception(Exception::USER_NOT_FOUND);
}
if ($project->getId() === 'console') {
// get all memberships
$memberships = $user->getAttribute('memberships', []);
foreach ($memberships as $membership) {
// prevent deletion if at least one active membership
if ($membership->getAttribute('confirm', false)) {
throw new Exception(Exception::USER_DELETION_PROHIBITED);
}
}
}
$dbForProject->deleteDocument('users', $user->getId());
$queueForDeletes
+1 -1
View File
@@ -116,7 +116,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro
Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
} catch (Throwable $err) {
$index = 0;
do {
+46 -19
View File
@@ -153,13 +153,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
} catch (LimitException) {
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded');
} catch (\Exception $e) {
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
throw $e;
}
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) {
$twoWayKey = $options['twoWayKey'];
@@ -197,13 +197,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
$dbForProject->deleteDocument('attributes', $attribute->getId());
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded');
} catch (\Exception $e) {
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
throw $e;
}
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
}
$queueForDatabase
@@ -358,7 +358,7 @@ function updateAttribute(
$relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options);
$relatedAttribute->setAttribute('options', $relatedOptions);
$dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute);
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
}
} else {
$dbForProject->updateAttribute(
@@ -371,7 +371,7 @@ function updateAttribute(
}
$attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute);
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collection->getId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId());
$queueForEvents
->setContext('collection', $collection)
@@ -703,8 +703,8 @@ App::delete('/v1/databases/:databaseId')
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB');
}
$dbForProject->deleteCachedDocument('databases', $database->getId());
$dbForProject->deleteCachedCollection('databases_' . $database->getInternalId());
$dbForProject->purgeCachedDocument('databases', $database->getId());
$dbForProject->purgeCachedCollection('databases_' . $database->getInternalId());
$queueForDatabase
->setType(DATABASE_TYPE_DELETE_DATABASE)
@@ -1076,7 +1076,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB');
}
$dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
$queueForDatabase
->setType(DATABASE_TYPE_DELETE_COLLECTION)
@@ -2248,8 +2248,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
$attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting'));
}
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) {
$options = $attribute->getAttribute('options');
@@ -2270,8 +2270,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
$dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting'));
}
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']);
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']);
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
}
}
@@ -2453,7 +2453,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
throw new Exception(Exception::INDEX_ALREADY_EXISTS);
}
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
$queueForDatabase
->setType(DATABASE_TYPE_CREATE_INDEX)
@@ -2620,7 +2620,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
$index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting'));
}
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
$queueForDatabase
->setType(DATABASE_TYPE_DELETE_INDEX)
@@ -2997,6 +2997,33 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$processDocument($collection, $document);
}
$select = \array_reduce($queries, function ($result, $query) {
return $result || ($query->getMethod() === Query::TYPE_SELECT);
}, false);
// Check if the SELECT query includes $databaseId and $collectionId
$hasDatabaseId = false;
$hasCollectionId = false;
if ($select) {
$hasDatabaseId = \array_reduce($queries, function ($result, $query) {
return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues()));
}, false);
$hasCollectionId = \array_reduce($queries, function ($result, $query) {
return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues()));
}, false);
}
if ($select) {
foreach ($documents as $document) {
if (!$hasDatabaseId) {
$document->removeAttribute('$databaseId');
}
if (!$hasCollectionId) {
$document->removeAttribute('$collectionId');
}
}
}
$response->dynamic(new Document([
'total' => $total,
'documents' => $documents,
+106 -12
View File
@@ -7,6 +7,7 @@ use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Config\Config;
use Utopia\Database\Document;
use Utopia\Domains\Validator\PublicDomain;
use Utopia\Pools\Group;
use Utopia\Queue\Client;
use Utopia\Queue\Connection;
@@ -14,7 +15,9 @@ use Utopia\Registry\Registry;
use Utopia\Storage\Device;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Storage;
use Utopia\Validator\Domain;
use Utopia\Validator\Integer;
use Utopia\Validator\Multiple;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
@@ -356,7 +359,7 @@ App::get('/v1/health/queue/webhooks')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -383,12 +386,62 @@ App::get('/v1/health/queue/logs')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
}, ['response']);
App::get('/v1/health/certificate')
->desc('Get the SSL certificate for a domain')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'health')
->label('sdk.method', 'getCertificate')
->label('sdk.description', '/docs/references/health/get-certificate.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_CERTIFICATE)
->param('domain', null, new Multiple([new Domain(), new PublicDomain()]), Multiple::TYPE_STRING, 'Domain name')
->inject('response')
->action(function (string $domain, Response $response) {
if (filter_var($domain, FILTER_VALIDATE_URL)) {
$domain = parse_url($domain, PHP_URL_HOST);
}
$sslContext = stream_context_create([
"ssl" => [
"capture_peer_cert" => true
]
]);
$sslSocket = stream_socket_client("ssl://" . $domain . ":443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $sslContext);
if (!$sslSocket) {
throw new Exception(Exception::HEALTH_INVALID_HOST);
}
$streamContextParams = stream_context_get_params($sslSocket);
$peerCertificate = $streamContextParams['options']['ssl']['peer_certificate'];
$certificatePayload = openssl_x509_parse($peerCertificate);
$sslExpiration = $certificatePayload['validTo_time_t'];
$status = $sslExpiration < time() ? 'fail' : 'pass';
if ($status === 'fail') {
throw new Exception(Exception::HEALTH_CERTIFICATE_EXPIRED);
}
$response->dynamic(new Document([
'name' => $certificatePayload['name'],
'subjectSN' => $certificatePayload['subject']['CN'],
'issuerOrganisation' => $certificatePayload['issuer']['O'],
'validFrom' => $certificatePayload['validFrom_time_t'],
'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'])
@@ -410,7 +463,7 @@ App::get('/v1/health/queue/certificates')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -437,7 +490,7 @@ App::get('/v1/health/queue/builds')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -465,7 +518,7 @@ App::get('/v1/health/queue/databases')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -492,7 +545,7 @@ App::get('/v1/health/queue/deletes')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -519,7 +572,7 @@ App::get('/v1/health/queue/mails')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -546,7 +599,7 @@ App::get('/v1/health/queue/messaging')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -573,7 +626,7 @@ App::get('/v1/health/queue/migrations')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -600,7 +653,7 @@ App::get('/v1/health/queue/functions')
$size = $client->getQueueSize();
if ($size >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$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);
@@ -649,6 +702,47 @@ App::get('/v1/health/storage/local')
$response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS);
});
App::get('/v1/health/storage')
->desc('Get storage')
->groups(['api', 'health'])
->label('scope', 'health.read')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'health')
->label('sdk.method', 'getStorage')
->label('sdk.description', '/docs/references/health/get-storage.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_HEALTH_STATUS)
->inject('response')
->inject('deviceFiles')
->inject('deviceFunctions')
->inject('deviceBuilds')
->action(function (Response $response, Device $deviceFiles, Device $deviceFunctions, Device $deviceBuilds) {
$devices = [$deviceFiles, $deviceFunctions, $deviceBuilds];
$checkStart = \microtime(true);
foreach ($devices as $device) {
if (!$device->write($device->getPath('health.txt'), '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') {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot());
}
if (!$device->delete($device->getPath('health.txt'))) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot());
}
}
$output = [
'status' => 'pass',
'ping' => \round((\microtime(true) - $checkStart) / 1000)
];
$response->dynamic(new Document($output), Response::MODEL_HEALTH_STATUS);
});
App::get('/v1/health/anti-virus')
->desc('Get antivirus')
->groups(['api', 'health'])
@@ -695,7 +789,7 @@ App::get('/v1/health/queue/failed/:name')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'health')
->label('sdk.method', 'getFailedJobs')
->param('queueName', '', new WhiteList([
->param('name', '', new WhiteList([
Event::DATABASE_QUEUE_NAME,
Event::DELETE_QUEUE_NAME,
Event::AUDITS_QUEUE_NAME,
@@ -723,7 +817,7 @@ App::get('/v1/health/queue/failed/:name')
$failed = $client->countFailedJobs();
if ($failed >= $threshold) {
throw new Exception(Exception::QUEUE_SIZE_EXCEEDED, "Queue failed jobs threshold hit. Current size is {$failed} and threshold is {$threshold}.");
throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue failed jobs threshold hit. Current size is {$failed} and threshold is {$threshold}.");
}
$response->dynamic(new Document([ 'size' => $failed ]), Response::MODEL_HEALTH_QUEUE);
+22 -1
View File
@@ -144,9 +144,30 @@ App::get('/v1/project/usage')
];
}, $dbForProject->find('buckets'));
// merge network inbound + outbound
$projectBandwidth = [];
foreach ($usage[METRIC_NETWORK_INBOUND] as $item) {
$projectBandwidth[$item['date']] ??= 0;
$projectBandwidth[$item['date']] += $item['value'];
}
foreach ($usage[METRIC_NETWORK_OUTBOUND] as $item) {
$projectBandwidth[$item['date']] ??= 0;
$projectBandwidth[$item['date']] += $item['value'];
}
$network = [];
foreach ($projectBandwidth as $date => $value) {
$network[] = [
'date' => $date,
'value' => $value
];
}
$response->dynamic(new Document([
'requests' => ($usage[METRIC_NETWORK_REQUESTS]),
'network' => ($usage[METRIC_NETWORK_INBOUND] + $usage[METRIC_NETWORK_OUTBOUND]),
'network' => $network,
'users' => ($usage[METRIC_USERS]),
'executions' => ($usage[METRIC_EXECUTIONS]),
'executionsTotal' => $total[METRIC_EXECUTIONS],
+66 -43
View File
@@ -9,6 +9,7 @@ use Appwrite\Network\Validator\Origin;
use Appwrite\Template\Template;
use Appwrite\Utopia\Database\Validator\ProjectId;
use Appwrite\Utopia\Database\Validator\Queries\Projects;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use PHPMailer\PHPMailer\PHPMailer;
use Utopia\Abuse\Adapters\TimeLimit;
@@ -71,12 +72,12 @@ App::post('/v1/projects')
->param('legalCity', '', new Text(256), 'Project legal City. Max length: 256 chars.', true)
->param('legalAddress', '', new Text(256), 'Project legal Address. Max length: 256 chars.', true)
->param('legalTaxId', '', new Text(256), 'Project legal Tax ID. Max length: 256 chars.', true)
->inject('request')
->inject('response')
->inject('dbForConsole')
->inject('cache')
->inject('pools')
->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole, Cache $cache, Group $pools) {
->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForConsole, Cache $cache, Group $pools) {
$team = $dbForConsole->getDocument('teams', $teamId);
@@ -85,8 +86,15 @@ App::post('/v1/projects')
}
$auth = Config::getParam('auth', []);
$auths = ['limit' => 0, 'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT, 'passwordHistory' => 0, 'passwordDictionary' => false, 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, 'personalDataCheck' => false];
foreach ($auth as $index => $method) {
$auths = [
'limit' => 0,
'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT,
'passwordHistory' => 0,
'passwordDictionary' => false,
'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG,
'personalDataCheck' => false
];
foreach ($auth as $method) {
$auths[$method['key'] ?? ''] = true;
}
@@ -121,7 +129,7 @@ App::post('/v1/projects')
}
}
$databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE', null);
$databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE');
$index = array_search($databaseOverride, $databases);
if ($index !== false) {
$database = $databases[$index];
@@ -133,6 +141,23 @@ App::post('/v1/projects')
throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project.");
}
// TODO: One in 20 projects use shared tables. Temporary until all projects are using shared tables.
if (
!\mt_rand(0, 19)
&& App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted'
) {
$database = DATABASE_SHARED_TABLES;
}
// TODO: Allow overriding in development mode. Temporary until all projects are using shared tables.
if (
App::isDevelopment()
&& App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted'
&& $request->getHeader('x-appwrite-share-tables', false)
) {
$database = DATABASE_SHARED_TABLES;
}
try {
$project = $dbForConsole->createDocument('projects', new Document([
'$id' => $projectId,
@@ -164,14 +189,26 @@ App::post('/v1/projects')
'keys' => null,
'auths' => $auths,
'search' => implode(' ', [$projectId, $name]),
'database' => $database
'database' => $database,
]));
} catch (Duplicate $th) {
} catch (Duplicate) {
throw new Exception(Exception::PROJECT_ALREADY_EXISTS);
}
$dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache);
$dbForProject->setNamespace("_{$project->getInternalId()}");
if ($database === DATABASE_SHARED_TABLES) {
$dbForProject
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$dbForProject
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
$dbForProject->create();
$audit = new Audit($dbForProject);
@@ -188,33 +225,19 @@ App::post('/v1/projects')
continue;
}
$attributes = [];
$indexes = [];
$attributes = \array_map(function (array $attribute) {
return new Document($attribute);
}, $collection['attributes']);
foreach ($collection['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => $attribute['$id'],
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
'default' => $attribute['default'] ?? null,
'format' => $attribute['format'] ?? ''
]);
}
$indexes = \array_map(function (array $index) {
return new Document($index);
}, $collection['indexes']);
foreach ($collection['indexes'] as $index) {
$indexes[] = new Document([
'$id' => $index['$id'],
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
try {
$dbForProject->createCollection($key, $attributes, $indexes);
} catch (Duplicate) {
// Collection already exists
}
$dbForProject->createCollection($key, $attributes, $indexes);
}
$response
@@ -820,7 +843,7 @@ App::post('/v1/projects/:projectId/webhooks')
$webhook = $dbForConsole->createDocument('webhooks', $webhook);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -941,7 +964,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
->setAttribute('httpPass', $httpPass);
$dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
});
@@ -980,7 +1003,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
$webhook->setAttribute('signatureKey', \bin2hex(\random_bytes(64)));
$dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
});
@@ -1017,7 +1040,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
$dbForConsole->deleteDocument('webhooks', $webhook->getId());
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response->noContent();
});
@@ -1067,7 +1090,7 @@ App::post('/v1/projects/:projectId/keys')
$key = $dbForConsole->createDocument('keys', $key);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -1181,7 +1204,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
$dbForConsole->updateDocument('keys', $key->getId(), $key);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response->dynamic($key, Response::MODEL_KEY);
});
@@ -1218,7 +1241,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
$dbForConsole->deleteDocument('keys', $key->getId());
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response->noContent();
});
@@ -1268,7 +1291,7 @@ App::post('/v1/projects/:projectId/platforms')
$platform = $dbForConsole->createDocument('platforms', $platform);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
@@ -1383,7 +1406,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
$dbForConsole->updateDocument('platforms', $platform->getId(), $platform);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response->dynamic($platform, Response::MODEL_PLATFORM);
});
@@ -1420,7 +1443,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
$dbForConsole->deleteDocument('platforms', $platformId);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
$response->noContent();
});
@@ -1446,7 +1469,7 @@ App::patch('/v1/projects/:projectId/smtp')
->param('port', 587, new Integer(), 'SMTP server port', true)
->param('username', '', new Text(0, 0), 'SMTP server username', true)
->param('password', '', new Text(0, 0), 'SMTP server password', true)
->param('secure', '', new WhiteList(['tls'], true), 'Does SMTP server use secure connection', true)
->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true)
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) {
+9 -13
View File
@@ -114,7 +114,7 @@ App::post('/v1/teams')
]);
$membership = $dbForProject->createDocument('memberships', $membership);
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
}
$queueForEvents->setParam('teamId', $team->getId());
@@ -380,7 +380,6 @@ App::post('/v1/teams/:teamId/memberships')
->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.')
->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) // TODO add our own built-in confirm page
->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true)
->inject('request')
->inject('response')
->inject('project')
->inject('user')
@@ -389,7 +388,7 @@ App::post('/v1/teams/:teamId/memberships')
->inject('queueForMails')
->inject('queueForMessaging')
->inject('queueForEvents')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, EventPhone $queueForMessaging, Event $queueForEvents) {
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, EventPhone $queueForMessaging, Event $queueForEvents) {
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
@@ -537,7 +536,7 @@ App::post('/v1/teams/:teamId/memberships')
Authorization::skip(fn() => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
$dbForProject->deleteCachedDocument('users', $invitee->getId());
$dbForProject->purgeCachedDocument('users', $invitee->getId());
} else {
try {
$membership = $dbForProject->createDocument('memberships', $membership);
@@ -639,8 +638,6 @@ App::post('/v1/teams/:teamId/memberships')
$message = $message->setParam('{{token}}', $url);
$message = $message->render();
var_dump($request->getIP());
var_dump($project->getId());
$queueForMessaging
->setRecipient($phone)
->setMessage($message)
@@ -847,7 +844,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
/**
* Replace membership on profile
*/
$dbForProject->deleteCachedDocument('users', $profile->getId());
$dbForProject->purgeCachedDocument('users', $profile->getId());
$queueForEvents
->setParam('teamId', $team->getId())
@@ -962,15 +959,15 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
Permission::delete(Role::user($user->getId())),
]));
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
Authorization::setRole(Role::user($userId)->toString());
$membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership);
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1)));
Authorization::skip(fn() => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
$queueForEvents
->setParam('teamId', $team->getId())
@@ -1047,11 +1044,10 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership from DB');
}
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
if ($membership->getAttribute('confirm')) { // Count only confirmed members
$team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0));
Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team));
Authorization::skip(fn() => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0));
}
$queueForEvents
+3 -3
View File
@@ -9,6 +9,7 @@ use Appwrite\Event\Event;
use Appwrite\Network\Validator\Email;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Identities;
use Utopia\CLI\Console;
use Utopia\Database\Validator\Queries;
use Appwrite\Utopia\Database\Validator\Queries\Users;
use Utopia\Database\Validator\Query\Limit;
@@ -141,7 +142,6 @@ App::post('/v1/users')
->inject('hooks')
->action(function (string $userId, ?string $email, ?string $phone, ?string $password, string $name, Response $response, Document $project, Database $dbForProject, Event $queueForEvents, Hooks $hooks) {
$user = createUser('plaintext', '{}', $userId, $email, $password, $phone, $name, $project, $dbForProject, $queueForEvents, $hooks);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($user, Response::MODEL_USER);
@@ -1108,7 +1108,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
}
$dbForProject->deleteDocument('sessions', $session->getId());
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$queueForEvents
->setParam('userId', $user->getId())
@@ -1151,7 +1151,7 @@ App::delete('/v1/users/:userId/sessions')
//TODO: fix this
}
$dbForProject->deleteCachedDocument('users', $user->getId());
$dbForProject->purgeCachedDocument('users', $user->getId());
$queueForEvents
->setParam('userId', $user->getId())
+236 -54
View File
@@ -9,9 +9,8 @@ use Utopia\Logger\Logger;
use Utopia\Logger\Log;
use Utopia\Logger\Log\User;
use Swoole\Http\Request as SwooleRequest;
use Utopia\Cache\Cache;
use Utopia\Pools\Group;
use Appwrite\Utopia\Request;
use MaxMind\Db\Reader;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\View;
use Appwrite\Extend\Exception as AppwriteException;
@@ -19,6 +18,8 @@ use Utopia\Config\Config;
use Utopia\Domains\Domain;
use Appwrite\Auth\Auth;
use Appwrite\Event\Certificate;
use Appwrite\Event\Event;
use Appwrite\Event\Usage;
use Appwrite\Network\Validator\Origin;
use Appwrite\Utopia\Response\Filters\V11 as ResponseV11;
use Appwrite\Utopia\Response\Filters\V12 as ResponseV12;
@@ -31,6 +32,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\Authorization;
use Utopia\Validator\Hostname;
use Appwrite\Utopia\Request\Filters\V12 as RequestV12;
@@ -38,6 +40,7 @@ use Appwrite\Utopia\Request\Filters\V13 as RequestV13;
use Appwrite\Utopia\Request\Filters\V14 as RequestV14;
use Appwrite\Utopia\Request\Filters\V15 as RequestV15;
use Appwrite\Utopia\Request\Filters\V16 as RequestV16;
use Executor\Executor;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
@@ -45,7 +48,7 @@ Config::setParam('domainVerification', false);
Config::setParam('cookieDomain', 'localhost');
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleRequest, Request $request, Response $response)
function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb)
{
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
@@ -117,59 +120,218 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques
$path .= '?' . $query;
}
$body = $swooleRequest->getContent() ?? '';
$method = $swooleRequest->server['request_method'];
$requestHeaders = $request->getHeaders();
$body = \json_encode([
'async' => false,
'body' => $swooleRequest->getContent() ?? '',
'method' => $swooleRequest->server['request_method'],
'path' => $path,
'headers' => $requestHeaders
$project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId));
$dbForProject = $getProjectDB($project);
$function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
if ($function->isEmpty() || !$function->getAttribute('enabled')) {
throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND);
}
$version = $function->getAttribute('version', 'v2');
$runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []);
$runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null;
if (\is_null($runtime)) {
throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported');
}
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', '')));
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function');
}
if ($deployment->isEmpty()) {
throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function');
}
/** Check if build has completed */
$build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')));
if ($build->isEmpty()) {
throw new AppwriteException(AppwriteException::BUILD_NOT_FOUND);
}
if ($build->getAttribute('status') !== 'ready') {
throw new AppwriteException(AppwriteException::BUILD_NOT_READY);
}
$permissions = $function->getAttribute('execute');
if (!(\in_array('any', $permissions)) && (\in_array('guests', $permissions))) {
throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"');
}
$headers = \array_merge([], $requestHeaders);
$headers['x-appwrite-trigger'] = 'http';
$headers['x-appwrite-user-id'] = '';
$headers['x-appwrite-user-jwt'] = '';
$headers['x-appwrite-country-code'] = '';
$headers['x-appwrite-continent-code'] = '';
$headers['x-appwrite-continent-eu'] = 'false';
$ip = $headers['x-real-ip'] ?? '';
if (!empty($ip)) {
$record = $geodb->get($ip);
if ($record) {
$eu = Config::getParam('locale-eu');
$headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? '';
$headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? '';
$headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false';
}
}
$headersFiltered = [];
foreach ($headers as $key => $value) {
if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) {
$headersFiltered[] = ['name' => $key, 'value' => $value];
}
}
$executionId = ID::unique();
$execution = new Document([
'$id' => $executionId,
'$permissions' => [],
'functionInternalId' => $function->getInternalId(),
'functionId' => $function->getId(),
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentId' => $deployment->getId(),
'trigger' => 'http', // http / schedule / event
'status' => 'processing', // waiting / processing / completed / failed
'responseStatusCode' => 0,
'responseHeaders' => [],
'requestPath' => $path,
'requestMethod' => $method,
'requestHeaders' => $headersFiltered,
'errors' => '',
'logs' => '',
'duration' => 0.0,
'search' => implode(' ', [$functionId, $executionId]),
]);
$headers = [
'Content-Type: application/json',
'Content-Length: ' . \strlen($body),
'X-Appwrite-Project: ' . $projectId
];
$queueForEvents
->setParam('functionId', $function->getId())
->setParam('executionId', $execution->getId())
->setContext('function', $function);
$ch = \curl_init();
\curl_setopt($ch, CURLOPT_URL, "http://localhost/v1/functions/{$functionId}/executions");
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
\curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
\curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// \curl_setopt($ch, CURLOPT_HEADER, true);
\curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
\curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$durationStart = \microtime(true);
$executionResponse = \curl_exec($ch);
$statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = \curl_error($ch);
$errNo = \curl_errno($ch);
$vars = [];
\curl_close($ch);
if ($errNo !== 0) {
throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Internal error: " . $error);
// V2 vars
if ($version === 'v2') {
$vars = \array_merge($vars, [
'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '',
'APPWRITE_FUNCTION_DATA' => $body ?? '',
'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '',
'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? ''
]);
}
if ($statusCode >= 400) {
$error = \json_decode($executionResponse, true)['message'];
throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, "Execution error: " . $error);
// Shared vars
foreach ($function->getAttribute('varsProject', []) as $var) {
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
}
$execution = \json_decode($executionResponse, true);
// Function vars
foreach ($function->getAttribute('vars', []) as $var) {
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
}
$contentType = 'text/plain';
foreach ($execution['responseHeaders'] as $header) {
if (\strtolower($header['name']) === 'content-type') {
$contentType = $header['value'];
// Appwrite vars
$vars = \array_merge($vars, [
'APPWRITE_FUNCTION_ID' => $functionId,
'APPWRITE_FUNCTION_NAME' => $function->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'] ?? '',
]);
/** Execute function */
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
try {
$version = $function->getAttribute('version', 'v2');
$command = $runtime['startCommand'];
$command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"';
$executionResponse = $executor->createExecution(
projectId: $project->getId(),
deploymentId: $deployment->getId(),
body: \strlen($body) > 0 ? $body : null,
variables: $vars,
timeout: $function->getAttribute('timeout', 0),
image: $runtime['image'],
source: $build->getAttribute('path', ''),
entrypoint: $deployment->getAttribute('entrypoint', ''),
version: $version,
path: $path,
method: $method,
headers: $headers,
runtimeEntrypoint: $command,
requestTimeout: 30
);
$headersFiltered = [];
foreach ($executionResponse['headers'] as $key => $value) {
if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) {
$headersFiltered[] = ['name' => $key, 'value' => $value];
}
}
$response->setHeader($header['name'], $header['value']);
/** Update execution status */
$status = $executionResponse['statusCode'] >= 400 ? 'failed' : 'completed';
$execution->setAttribute('status', $status);
$execution->setAttribute('responseStatusCode', $executionResponse['statusCode']);
$execution->setAttribute('responseHeaders', $headersFiltered);
$execution->setAttribute('logs', $executionResponse['logs']);
$execution->setAttribute('errors', $executionResponse['errors']);
$execution->setAttribute('duration', $executionResponse['duration']);
} catch (\Throwable $th) {
$durationEnd = \microtime(true);
$execution
->setAttribute('duration', $durationEnd - $durationStart)
->setAttribute('status', 'failed')
->setAttribute('responseStatusCode', 500)
->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode());
Console::error($th->getMessage());
} finally {
$queueForUsage
->addMetric(METRIC_EXECUTIONS, 1)
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1)
->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project
->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function
;
}
if ($function->getAttribute('logging')) {
/** @var Document $execution */
$execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution));
}
$execution->setAttribute('logs', '');
$execution->setAttribute('errors', '');
$headers = [];
foreach (($executionResponse['headers'] ?? []) as $key => $value) {
$headers[] = ['name' => $key, 'value' => $value];
}
$execution->setAttribute('responseBody', $executionResponse['body'] ?? '');
$execution->setAttribute('responseHeaders', $headers);
$body = $execution['responseBody'] ?? '';
$encodingKey = \array_search('x-open-runtimes-encoding', \array_column($execution['responseHeaders'], 'name'));
@@ -179,6 +341,15 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques
}
}
$contentType = 'text/plain';
foreach ($execution['responseHeaders'] as $header) {
if (\strtolower($header['name']) === 'content-type') {
$contentType = $header['value'];
}
$response->setHeader($header['name'], $header['value']);
}
$response
->setContentType($contentType)
->setStatusCode($execution['responseStatusCode'] ?? 200)
@@ -205,13 +376,17 @@ App::init()
->inject('console')
->inject('project')
->inject('dbForConsole')
->inject('getProjectDB')
->inject('user')
->inject('locale')
->inject('localeCodes')
->inject('clients')
->inject('servers')
->inject('queueForCertificates')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates) {
->inject('queueForEvents')
->inject('queueForUsage')
->inject('geodb')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Document $user, Locale $locale, array $localeCodes, array $clients, array $servers, Certificate $queueForCertificates, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) {
/*
* Appwrite Router
*/
@@ -220,7 +395,7 @@ App::init()
$mainDomain = App::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain) {
if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) {
if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) {
return;
}
}
@@ -232,7 +407,9 @@ App::init()
Request::setRoute($route);
if ($route === null) {
return $response->setStatusCode(404)->send('Not Found');
return $response
->setStatusCode(404)
->send('Not Found');
}
$requestFormat = $request->getHeader('x-appwrite-response-format', App::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', ''));
@@ -425,7 +602,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')
->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-Appwrite-Share-Tables, 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')
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $refDomain)
->addHeader('Access-Control-Allow-Credentials', 'true');
@@ -511,7 +688,7 @@ App::init()
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCCESS)) > $accessedAt) {
$key->setAttribute('accessedAt', DateTime::now());
$dbForConsole->updateDocument('keys', $key->getId(), $key);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
}
$sdkValidator = new WhiteList($servers, true);
@@ -525,7 +702,7 @@ App::init()
/** Update access time as well */
$key->setAttribute('accessedAt', Datetime::now());
$dbForConsole->updateDocument('keys', $key->getId(), $key);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$dbForConsole->purgeCachedDocument('projects', $project->getId());
}
}
}
@@ -571,7 +748,11 @@ App::options()
->inject('request')
->inject('response')
->inject('dbForConsole')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole) {
->inject('getProjectDB')
->inject('queueForEvents')
->inject('queueForUsage')
->inject('geodb')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) {
/*
* Appwrite Router
*/
@@ -579,7 +760,7 @@ App::options()
$mainDomain = App::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain) {
if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) {
if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) {
return;
}
}
@@ -589,7 +770,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-Fallback-Cookies')
->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-Appwrite-Share-Tables, 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-Fallback-Cookies')
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $origin)
->addHeader('Access-Control-Allow-Credentials', 'true')
@@ -607,10 +788,11 @@ App::error()
->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log) {
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
$route = $utopia->getRoute();
$publish = true;
if ($error instanceof AppwriteException) {
$publish = $error->isPublishable();
} else {
$publish = $error->getCode() === 0 || $error->getCode() >= 500;
}
if ($logger && ($publish || $error->getCode() === 0)) {
@@ -756,10 +938,10 @@ App::error()
->setParam('development', App::isDevelopment())
->setParam('projectName', $project->getAttribute('name'))
->setParam('projectURL', $project->getAttribute('url'))
->setParam('message', $error->getMessage())
->setParam('type', $type)
->setParam('code', $code)
->setParam('trace', $trace);
->setParam('message', $output['message'] ?? '')
->setParam('type', $output['type'] ?? '')
->setParam('code', $output['code'] ?? '')
->setParam('trace', $output['trace'] ?? []);
$response->html($layout->render());
}
+1 -1
View File
@@ -407,7 +407,7 @@ App::shutdown()
$session = array_shift($sessions);
$dbForProject->deleteDocument('sessions', $session->getId());
}
$dbForProject->deleteCachedDocument('users', $userId);
$dbForProject->purgeCachedDocument('users', $userId);
});
App::shutdown()
+1 -1
View File
@@ -147,7 +147,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
$dbForConsole->createCollection($key, $attributes, $indexes);
}
if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDefaultDatabase(), 'bucket_1')) {
if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDatabase(), 'bucket_1')) {
Console::success('[Setup] - Creating default bucket...');
$dbForConsole->createDocument('buckets', new Document([
'$id' => ID::custom('default'),
+138 -133
View File
@@ -12,11 +12,11 @@ if (\file_exists(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
ini_set('memory_limit', '512M');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('default_socket_timeout', -1);
error_reporting(E_ALL);
\ini_set('memory_limit', '512M');
\ini_set('display_errors', 1);
\ini_set('display_startup_errors', 1);
\ini_set('default_socket_timeout', -1);
\error_reporting(E_ALL);
use Appwrite\Event\Migration;
use Appwrite\Event\Usage;
@@ -34,6 +34,7 @@ use Appwrite\Network\Validator\Origin;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\URL\URL as AppwriteURL;
use Utopia\App;
use Utopia\CLI\Console;
use Utopia\Logger\Logger;
use Utopia\Cache\Adapter\Redis as RedisCache;
use Utopia\Cache\Cache;
@@ -112,7 +113,7 @@ const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return
const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours
const APP_USER_ACCCESS = 24 * 60 * 60; // 24 hours
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
const APP_CACHE_BUSTER = 329;
const APP_CACHE_BUSTER = 331;
const APP_VERSION_STABLE = '1.4.13';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
@@ -142,7 +143,8 @@ const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite';
const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1';
const APP_HOSTNAME_INTERNAL = 'appwrite';
// Database Reconnect
// Database
const DATABASE_SHARED_TABLES = 'database_db_self_hosted_shared_tables';
const DATABASE_RECONNECT_SLEEP = 2;
const DATABASE_RECONNECT_MAX_ATTEMPTS = 10;
// Database Worker Types
@@ -195,6 +197,7 @@ const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length'];
// Usage metrics
const METRIC_TEAMS = 'teams';
const METRIC_USERS = 'users';
const METRIC_MESSAGES = 'messages';
const METRIC_SESSIONS = 'sessions';
const METRIC_DATABASES = 'databases';
const METRIC_COLLECTIONS = 'collections';
@@ -653,14 +656,13 @@ $register->set('pools', function () {
foreach ($connections as $key => $connection) {
$type = $connection['type'] ?? '';
$dsns = $connection['dsns'] ?? '';
$multipe = $connection['multiple'] ?? false;
$multiple = $connection['multiple'] ?? false;
$schemes = $connection['schemes'] ?? [];
$config = [];
$dsns = explode(',', $connection['dsns'] ?? '');
foreach ($dsns as &$dsn) {
$dsn = explode('=', $dsn);
$name = ($multipe) ? $key . '_' . $dsn[0] : $key;
$name = ($multiple) ? $key . '_' . $dsn[0] : $key;
$dsn = $dsn[1] ?? '';
$config[] = $name;
if (empty($dsn)) {
@@ -683,47 +685,38 @@ $register->set('pools', function () {
/**
* Get Resource
*
* Creation could be reused accross connection types like database, cache, queue, etc.
* Creation could be reused across connection types like database, cache, queue, etc.
*
* Resource assignment to an adapter will happen below.
*/
switch ($dsnScheme) {
case 'mysql':
case 'mariadb':
$resource = 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 => true,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_STRINGIFY_FETCHES => true
));
});
};
break;
case 'redis':
$resource = function () use ($dsnHost, $dsnPort, $dsnPass) {
$redis = new Redis();
@$redis->pconnect($dsnHost, (int)$dsnPort);
if ($dsnPass) {
$redis->auth($dsnPass);
}
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
$resource = match ($dsnScheme) {
'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 => true,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_STRINGIFY_FETCHES => true
));
});
},
'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) {
$redis = new Redis();
@$redis->pconnect($dsnHost, (int)$dsnPort);
if ($dsnPass) {
$redis->auth($dsnPass);
}
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
return $redis;
};
break;
default:
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme");
break;
}
return $redis;
},
default => throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme"),
};
$pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) {
// Get Adapter
$adapter = null;
switch ($type) {
case 'database':
$adapter = match ($dsn->getScheme()) {
@@ -732,7 +725,7 @@ $register->set('pools', function () {
default => null
};
$adapter->setDefaultDatabase($dsn->getPath());
$adapter->setDatabase($dsn->getPath());
break;
case 'pubsub':
$adapter = $resource();
@@ -752,7 +745,6 @@ $register->set('pools', function () {
default:
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation.");
break;
}
return $adapter;
@@ -949,24 +941,25 @@ App::setResource('clients', function ($request, $console, $project) {
fn ($node) => $node['hostname'],
\array_filter(
$console->getAttribute('platforms', []),
fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && !empty($node['hostname']))
fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && !empty($node['hostname']))
)
);
$clients = \array_unique(
\array_merge(
$clientsConsole,
\array_map(
fn ($node) => $node['hostname'],
\array_filter(
$project->getAttribute('platforms', []),
fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && !empty($node['hostname']))
)
)
)
);
$clients = $clientsConsole;
$platforms = $project->getAttribute('platforms', []);
return $clients;
foreach ($platforms as $node) {
if (
isset($node['type']) &&
($node['type'] === Origin::CLIENT_TYPE_WEB ||
$node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) &&
!empty($node['hostname'])
) {
$clients[] = $node['hostname'];
}
}
return \array_unique($clients);
}, ['request', 'console', 'project']);
App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForConsole) {
@@ -1138,11 +1131,22 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole,
$database = new Database($dbAdapter, $cache);
$database
->setNamespace('_' . $project->getInternalId())
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS);
if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) {
$database
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$database
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
return $database;
}, ['pools', 'dbForConsole', 'cache', 'project']);
@@ -1150,8 +1154,7 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache) {
$dbAdapter = $pools
->get('console')
->pop()
->getResource()
;
->getResource();
$database = new Database($dbAdapter, $cache);
@@ -1167,22 +1170,35 @@ App::setResource('dbForConsole', function (Group $pools, Cache $cache) {
App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) {
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
$getProjectDB = function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) {
return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForConsole;
}
$databaseName = $project->getAttribute('database');
if (isset($databases[$databaseName])) {
$database = $databases[$databaseName];
$configure = (function (Database $database) use ($project) {
$database
->setNamespace('_' . $project->getInternalId())
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS);
if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) {
$database
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$database
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
});
if (isset($databases[$databaseName])) {
$database = $databases[$databaseName];
$configure($database);
return $database;
}
@@ -1192,19 +1208,10 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
->getResource();
$database = new Database($dbAdapter, $cache);
$databases[$databaseName] = $database;
$database
->setNamespace('_' . $project->getInternalId())
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId())
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS);
$configure($database);
return $database;
};
return $getProjectDB;
}, ['pools', 'dbForConsole', 'cache']);
App::setResource('cache', function (Group $pools) {
@@ -1261,62 +1268,60 @@ function getDevice($root): Device
Console::warning($e->getMessage() . 'Invalid DSN. Defaulting to Local device.');
}
switch ($device) {
case Storage::DEVICE_S3:
return new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case STORAGE::DEVICE_DO_SPACES:
return new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_BACKBLAZE:
return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_LINODE:
return new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_WASABI:
return new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_LOCAL:
default:
return new Local($root);
}
return match ($device) {
Storage::DEVICE_S3 => new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl),
Storage::DEVICE_DO_SPACES => new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl),
Storage::DEVICE_BACKBLAZE => new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl),
Storage::DEVICE_LINODE => new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl),
Storage::DEVICE_WASABI => new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl),
default => new Local($root),
};
} else {
switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '')) {
case Storage::DEVICE_LOCAL:
default:
return new Local($root);
case Storage::DEVICE_S3:
$s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', '');
$s3SecretKey = App::getEnv('_APP_STORAGE_S3_SECRET', '');
$s3Region = App::getEnv('_APP_STORAGE_S3_REGION', '');
$s3Bucket = App::getEnv('_APP_STORAGE_S3_BUCKET', '');
$s3Acl = 'private';
return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
case Storage::DEVICE_DO_SPACES:
$doSpacesAccessKey = App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', '');
$doSpacesSecretKey = App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', '');
$doSpacesRegion = App::getEnv('_APP_STORAGE_DO_SPACES_REGION', '');
$doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', '');
$doSpacesAcl = 'private';
return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl);
case Storage::DEVICE_BACKBLAZE:
$backblazeAccessKey = App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', '');
$backblazeSecretKey = App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', '');
$backblazeRegion = App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', '');
$backblazeBucket = App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', '');
$backblazeAcl = 'private';
return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl);
case Storage::DEVICE_LINODE:
$linodeAccessKey = App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', '');
$linodeSecretKey = App::getEnv('_APP_STORAGE_LINODE_SECRET', '');
$linodeRegion = App::getEnv('_APP_STORAGE_LINODE_REGION', '');
$linodeBucket = App::getEnv('_APP_STORAGE_LINODE_BUCKET', '');
$linodeAcl = 'private';
return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl);
case Storage::DEVICE_WASABI:
$wasabiAccessKey = App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', '');
$wasabiSecretKey = App::getEnv('_APP_STORAGE_WASABI_SECRET', '');
$wasabiRegion = App::getEnv('_APP_STORAGE_WASABI_REGION', '');
$wasabiBucket = App::getEnv('_APP_STORAGE_WASABI_BUCKET', '');
$wasabiAcl = 'private';
return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl);
}
$device = strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '');
return match ($device) {
Storage::DEVICE_S3 => new S3(
$root,
App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''),
App::getEnv('_APP_STORAGE_S3_SECRET', ''),
App::getEnv('_APP_STORAGE_S3_BUCKET', ''),
App::getEnv('_APP_STORAGE_S3_REGION', ''),
'private'
),
Storage::DEVICE_DO_SPACES => new DOSpaces(
$root,
App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''),
App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''),
App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''),
App::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''),
'private'
),
Storage::DEVICE_BACKBLAZE => new Backblaze(
$root,
App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''),
App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''),
App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''),
App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''),
'private'
),
Storage::DEVICE_LINODE => new Linode(
$root,
App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''),
App::getEnv('_APP_STORAGE_LINODE_SECRET', ''),
App::getEnv('_APP_STORAGE_LINODE_BUCKET', ''),
App::getEnv('_APP_STORAGE_LINODE_REGION', ''),
'private'
),
Storage::DEVICE_WASABI => new Wasabi(
$root,
App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''),
App::getEnv('_APP_STORAGE_WASABI_SECRET', ''),
App::getEnv('_APP_STORAGE_WASABI_BUCKET', ''),
App::getEnv('_APP_STORAGE_WASABI_REGION', ''),
'private'
),
default => new Local($root),
};
}
}
+1
View File
@@ -143,6 +143,7 @@ services:
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_DELAY
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
+58 -18
View File
@@ -14,6 +14,7 @@ use Appwrite\Event\Mail;
use Appwrite\Event\Migration;
use Appwrite\Event\Phone;
use Appwrite\Event\Usage;
use Appwrite\Event\UsageDump;
use Appwrite\Platform\Appwrite;
use Swoole\Runtime;
use Utopia\App;
@@ -62,15 +63,31 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register,
}
$pools = $register->get('pools');
$database = $pools
$adapter = $pools
->get($project->getAttribute('database'))
->pop()
->getResource()
;
->getResource();
$adapter = new Database($database, $cache);
$adapter->setNamespace('_' . $project->getInternalId());
return $adapter;
$database = new Database($adapter, $cache);
$database
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId());
if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) {
$database
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$database
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
return $database;
}, ['cache', 'register', 'message', 'dbForConsole']);
Server::setResource('project', function (Message $message, Database $dbForConsole) {
@@ -96,7 +113,19 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
if (isset($databases[$databaseName])) {
$database = $databases[$databaseName];
$database->setNamespace('_' . $project->getInternalId());
if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) {
$database
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$database
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
return $database;
}
@@ -109,7 +138,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
$databases[$databaseName] = $database;
$database->setNamespace('_' . $project->getInternalId());
if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) {
$database
->setShareTables(true)
->setTenant($project->getInternalId())
->setNamespace('');
} else {
$database
->setShareTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
return $database;
};
@@ -146,6 +185,9 @@ Server::setResource('log', fn() => new Log());
Server::setResource('queueForUsage', function (Connection $queue) {
return new Usage($queue);
}, ['queue']);
Server::setResource('queueForUsageDump', function (Connection $queue) {
return new UsageDump($queue);
}, ['queue']);
Server::setResource('queue', function (Group $pools) {
return $pools->get('queue')->pop()->getResource();
}, ['pools']);
@@ -231,7 +273,7 @@ try {
* Any worker can be configured with the following env vars:
* - _APP_WORKERS_NUM The total number of worker processes
* - _APP_WORKER_PER_CORE The number of worker processes per core (ignored if _APP_WORKERS_NUM is set)
* - _APP_QUEUE_NAME The name of the queue to read for database events
* - _APP_QUEUE_NAME The name of the queue to read for database events
*/
if ($workerName === 'databases') {
$queueName = App::getEnv('_APP_QUEUE_NAME', 'database_db_main');
@@ -249,7 +291,6 @@ try {
Console::error($e->getMessage() . ', File: ' . $e->getFile() . ', Line: ' . $e->getLine());
}
$worker = $platform->getWorker();
$worker
@@ -264,7 +305,8 @@ $worker
->inject('error')
->inject('logger')
->inject('log')
->action(function (Throwable $error, ?Logger $logger, Log $log) {
->inject('project')
->action(function (Throwable $error, ?Logger $logger, Log $log, Document $project) {
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
if ($error instanceof PDOException) {
@@ -280,6 +322,7 @@ $worker
$log->setAction('appwrite-queue-' . App::getEnv('QUEUE'));
$log->addTag('verboseType', get_class($error));
$log->addTag('code', $error->getCode());
$log->addTag('projectId', $project->getId() ?? 'n/a');
$log->addExtra('file', $error->getFile());
$log->addExtra('line', $error->getLine());
$log->addExtra('trace', $error->getTraceAsString());
@@ -299,12 +342,9 @@ $worker
Console::error('[Error] Line: ' . $error->getLine());
});
try {
$workerStart = $worker->getWorkerStart();
} catch (\Throwable $error) {
$worker->workerStart();
} finally {
Console::info("Worker $workerName started");
}
$worker->workerStart()
->action(function () use ($workerName) {
Console::info("Worker $workerName started");
});
$worker->start();
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
php /usr/src/code/app/worker.php usage-dump $@
+7 -6
View File
@@ -1,4 +1,5 @@
{
"name": "appwrite/server-ce",
"description": "End to end backend server for frontend and mobile apps.",
"type": "project",
@@ -43,20 +44,20 @@
"ext-sockets": "*",
"appwrite/php-runtimes": "0.13.*",
"appwrite/php-clamav": "2.0.*",
"utopia-php/abuse": "0.33.*",
"utopia-php/abuse": "0.34.*",
"utopia-php/analytics": "0.10.*",
"utopia-php/audit": "0.35.*",
"utopia-php/audit": "0.36.*",
"utopia-php/cache": "0.9.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.45.*",
"utopia-php/domains": "0.3.*",
"utopia-php/database": "0.45.7",
"utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.1.*",
"utopia-php/framework": "0.33.*",
"utopia-php/image": "0.5.*",
"utopia-php/image": "0.6.*",
"utopia-php/locale": "0.4.*",
"utopia-php/logger": "0.3.*",
"utopia-php/messaging": "0.2.*",
"utopia-php/messaging": "0.3.*",
"utopia-php/migration": "0.3.*",
"utopia-php/orchestration": "0.9.*",
"utopia-php/platform": "0.5.*",
Generated
+160 -166
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "35dcde03d0eb9a0d27de653b9fa038d4",
"content-hash": "9ab28ccc7cde35e834aac175d331c346",
"packages": [
{
"name": "adhocore/jwt",
@@ -156,11 +156,11 @@
},
{
"name": "appwrite/php-runtimes",
"version": "0.13.2",
"version": "0.13.3",
"source": {
"type": "git",
"url": "https://github.com/appwrite/runtimes.git",
"reference": "214a37c2c66e0f2bc9c30fdfde66955d9fd084a1"
"reference": "5d93fc578a9a543bcdc9b2c0562d80a51d56c73d"
},
"require": {
"php": ">=8.0",
@@ -195,7 +195,7 @@
"php",
"runtimes"
],
"time": "2023-11-22T15:36:00+00:00"
"time": "2024-03-01T14:47:47+00:00"
},
{
"name": "chillerlan/php-qrcode",
@@ -815,16 +815,16 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.28.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"shasum": ""
},
"require": {
@@ -832,9 +832,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@@ -878,7 +875,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0"
},
"funding": [
{
@@ -894,20 +891,20 @@
"type": "tidelift"
}
],
"time": "2023-01-26T09:26:14+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "utopia-php/abuse",
"version": "0.33.0",
"version": "0.34.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "1ba8d5f2793885cbf779e3b5b9d886968af43d2c"
"reference": "c8497650cd3ee0d04fe8a9e6391572262c1d89e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/1ba8d5f2793885cbf779e3b5b9d886968af43d2c",
"reference": "1ba8d5f2793885cbf779e3b5b9d886968af43d2c",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/c8497650cd3ee0d04fe8a9e6391572262c1d89e0",
"reference": "c8497650cd3ee0d04fe8a9e6391572262c1d89e0",
"shasum": ""
},
"require": {
@@ -941,9 +938,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.33.0"
"source": "https://github.com/utopia-php/abuse/tree/0.34.1"
},
"time": "2023-11-01T08:51:33+00:00"
"time": "2024-03-05T10:43:41+00:00"
},
{
"name": "utopia-php/analytics",
@@ -993,16 +990,16 @@
},
{
"name": "utopia-php/audit",
"version": "0.35.0",
"version": "0.36.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "ed9366ef05556da040de7a8b570f4160c7d8ea4a"
"reference": "9db48fed0558c33c9ddbb493fe2171844a3f0fd4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/ed9366ef05556da040de7a8b570f4160c7d8ea4a",
"reference": "ed9366ef05556da040de7a8b570f4160c7d8ea4a",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/9db48fed0558c33c9ddbb493fe2171844a3f0fd4",
"reference": "9db48fed0558c33c9ddbb493fe2171844a3f0fd4",
"shasum": ""
},
"require": {
@@ -1034,9 +1031,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.35.0"
"source": "https://github.com/utopia-php/audit/tree/0.36.1"
},
"time": "2023-11-01T08:51:29+00:00"
"time": "2024-03-05T10:50:30+00:00"
},
{
"name": "utopia-php/cache",
@@ -1190,16 +1187,16 @@
},
{
"name": "utopia-php/database",
"version": "0.45.5",
"version": "0.45.7",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "0b66a017f817a910acb83e6aea92bccea9571fe6"
"reference": "f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/0b66a017f817a910acb83e6aea92bccea9571fe6",
"reference": "0b66a017f817a910acb83e6aea92bccea9571fe6",
"url": "https://api.github.com/repos/utopia-php/database/zipball/f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03",
"reference": "f508c5fcec8e4b2c323a12dd4355a8cb0cc6ad03",
"shasum": ""
},
"require": {
@@ -1207,7 +1204,7 @@
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/cache": "0.9.*",
"utopia-php/framework": "0.*.*",
"utopia-php/framework": "0.33.*",
"utopia-php/mongo": "0.3.*"
},
"require-dev": {
@@ -1240,22 +1237,22 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.45.5"
"source": "https://github.com/utopia-php/database/tree/0.45.7"
},
"time": "2024-01-08T17:08:15+00:00"
"time": "2024-03-05T10:28:02+00:00"
},
{
"name": "utopia-php/domains",
"version": "0.3.2",
"version": "0.5.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/domains.git",
"reference": "aaa8c9a96c69ccb397997b1f4f2299c66f77eefb"
"reference": "bf07f60326f8389f378ddf6fcde86217e5cfe18c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/aaa8c9a96c69ccb397997b1f4f2299c66f77eefb",
"reference": "aaa8c9a96c69ccb397997b1f4f2299c66f77eefb",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/bf07f60326f8389f378ddf6fcde86217e5cfe18c",
"reference": "bf07f60326f8389f378ddf6fcde86217e5cfe18c",
"shasum": ""
},
"require": {
@@ -1300,9 +1297,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/domains/issues",
"source": "https://github.com/utopia-php/domains/tree/0.3.2"
"source": "https://github.com/utopia-php/domains/tree/0.5.0"
},
"time": "2023-07-19T16:39:24+00:00"
"time": "2024-01-03T22:04:27+00:00"
},
{
"name": "utopia-php/dsn",
@@ -1353,16 +1350,16 @@
},
{
"name": "utopia-php/framework",
"version": "0.33.1",
"version": "0.33.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/http.git",
"reference": "b745607aa1875554a0ad52e28f6db918da1ce11c"
"reference": "b1423ca3e3b61c6c4c2e619d2cb80672809a19f3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/http/zipball/b745607aa1875554a0ad52e28f6db918da1ce11c",
"reference": "b745607aa1875554a0ad52e28f6db918da1ce11c",
"url": "https://api.github.com/repos/utopia-php/http/zipball/b1423ca3e3b61c6c4c2e619d2cb80672809a19f3",
"reference": "b1423ca3e3b61c6c4c2e619d2cb80672809a19f3",
"shasum": ""
},
"require": {
@@ -1392,22 +1389,22 @@
],
"support": {
"issues": "https://github.com/utopia-php/http/issues",
"source": "https://github.com/utopia-php/http/tree/0.33.1"
"source": "https://github.com/utopia-php/http/tree/0.33.2"
},
"time": "2024-01-17T16:48:32+00:00"
"time": "2024-01-31T10:35:59+00:00"
},
{
"name": "utopia-php/image",
"version": "0.5.4",
"version": "0.6.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/image.git",
"reference": "ca5f436f9aa22dedaa6648f24f3687733808e336"
"reference": "2d74c27e69e65a93cf94a16586598a04fe435bf0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/image/zipball/ca5f436f9aa22dedaa6648f24f3687733808e336",
"reference": "ca5f436f9aa22dedaa6648f24f3687733808e336",
"url": "https://api.github.com/repos/utopia-php/image/zipball/2d74c27e69e65a93cf94a16586598a04fe435bf0",
"reference": "2d74c27e69e65a93cf94a16586598a04fe435bf0",
"shasum": ""
},
"require": {
@@ -1415,6 +1412,8 @@
"php": ">=8.0"
},
"require-dev": {
"laravel/pint": "1.2.*",
"phpstan/phpstan": "1.9.x-dev",
"phpunit/phpunit": "^9.3",
"vimeo/psalm": "4.13.1"
},
@@ -1428,12 +1427,6 @@
"license": [
"MIT"
],
"authors": [
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
}
],
"description": "A simple Image manipulation library",
"keywords": [
"framework",
@@ -1444,9 +1437,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/image/issues",
"source": "https://github.com/utopia-php/image/tree/0.5.4"
"source": "https://github.com/utopia-php/image/tree/0.6.1"
},
"time": "2022-05-11T12:30:41+00:00"
"time": "2024-02-05T13:31:44+00:00"
},
{
"name": "utopia-php/locale",
@@ -1554,16 +1547,16 @@
},
{
"name": "utopia-php/messaging",
"version": "0.2.0",
"version": "0.3.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/messaging.git",
"reference": "2d0f474a106bb1da285f85e105c29b46085d3a43"
"reference": "d488223876f88f97bb76fd6681fed0df80558f62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/2d0f474a106bb1da285f85e105c29b46085d3a43",
"reference": "2d0f474a106bb1da285f85e105c29b46085d3a43",
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/d488223876f88f97bb76fd6681fed0df80558f62",
"reference": "d488223876f88f97bb76fd6681fed0df80558f62",
"shasum": ""
},
"require": {
@@ -1596,9 +1589,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/messaging/issues",
"source": "https://github.com/utopia-php/messaging/tree/0.2.0"
"source": "https://github.com/utopia-php/messaging/tree/0.3.0"
},
"time": "2023-09-14T20:48:42+00:00"
"time": "2023-11-14T21:02:37+00:00"
},
{
"name": "utopia-php/migration",
@@ -2420,16 +2413,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "0.36.2",
"version": "0.36.4",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "0aa67479d75f0e0cb7b60454031534d7f0abaece"
"reference": "8d932098009d62d37dda73cfe4ebc11f83e21405"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0aa67479d75f0e0cb7b60454031534d7f0abaece",
"reference": "0aa67479d75f0e0cb7b60454031534d7f0abaece",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8d932098009d62d37dda73cfe4ebc11f83e21405",
"reference": "8d932098009d62d37dda73cfe4ebc11f83e21405",
"shasum": ""
},
"require": {
@@ -2465,22 +2458,22 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.36.2"
"source": "https://github.com/appwrite/sdk-generator/tree/0.36.4"
},
"time": "2024-01-19T01:04:35+00:00"
"time": "2024-02-20T16:36:15+00:00"
},
{
"name": "doctrine/deprecations",
"version": "1.1.2",
"version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
"reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931"
"reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
"reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab",
"reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab",
"shasum": ""
},
"require": {
@@ -2512,9 +2505,9 @@
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
"source": "https://github.com/doctrine/deprecations/tree/1.1.2"
"source": "https://github.com/doctrine/deprecations/tree/1.1.3"
},
"time": "2023-09-27T20:04:15+00:00"
"time": "2024-01-30T19:34:25+00:00"
},
{
"name": "doctrine/instantiator",
@@ -2771,16 +2764,16 @@
},
{
"name": "nikic/php-parser",
"version": "v5.0.0",
"version": "v5.0.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc"
"reference": "2218c2252c874a4624ab2f613d86ac32d227bc69"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69",
"reference": "2218c2252c874a4624ab2f613d86ac32d227bc69",
"shasum": ""
},
"require": {
@@ -2823,26 +2816,27 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1"
},
"time": "2024-01-07T17:17:35+00:00"
"time": "2024-02-21T19:24:10+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
"reference": "54750ef60c58e43759730615a392c31c80e23176"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
"reference": "54750ef60c58e43759730615a392c31c80e23176",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
@@ -2883,9 +2877,15 @@
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
"source": "https://github.com/phar-io/manifest/tree/2.0.4"
},
"time": "2021-07-20T11:28:43+00:00"
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2024-03-03T12:33:53+00:00"
},
{
"name": "phar-io/version",
@@ -3050,21 +3050,21 @@
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.8.0",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc"
"reference": "153ae662783729388a584b4361f2545e4d841e3c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fad452781b3d774e3337b0c0b245dd8e5a4455fc",
"reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c",
"reference": "153ae662783729388a584b4361f2545e4d841e3c",
"shasum": ""
},
"require": {
"doctrine/deprecations": "^1.0",
"php": "^7.4 || ^8.0",
"php": "^7.3 || ^8.0",
"phpdocumentor/reflection-common": "^2.0",
"phpstan/phpdoc-parser": "^1.13"
},
@@ -3102,30 +3102,30 @@
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.0"
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2"
},
"time": "2024-01-11T11:49:22+00:00"
"time": "2024-02-23T11:10:43+00:00"
},
{
"name": "phpspec/prophecy",
"version": "v1.18.0",
"version": "v1.19.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "d4f454f7e1193933f04e6500de3e79191648ed0c"
"reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/d4f454f7e1193933f04e6500de3e79191648ed0c",
"reference": "d4f454f7e1193933f04e6500de3e79191648ed0c",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/67a759e7d8746d501c41536ba40cd9c0a07d6a87",
"reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.2 || ^2.0",
"php": "^7.2 || 8.0.* || 8.1.* || 8.2.* || 8.3.*",
"phpdocumentor/reflection-docblock": "^5.2",
"sebastian/comparator": "^3.0 || ^4.0 || ^5.0",
"sebastian/recursion-context": "^3.0 || ^4.0 || ^5.0"
"sebastian/comparator": "^3.0 || ^4.0 || ^5.0 || ^6.0",
"sebastian/recursion-context": "^3.0 || ^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
"phpspec/phpspec": "^6.0 || ^7.0",
@@ -3171,22 +3171,22 @@
],
"support": {
"issues": "https://github.com/phpspec/prophecy/issues",
"source": "https://github.com/phpspec/prophecy/tree/v1.18.0"
"source": "https://github.com/phpspec/prophecy/tree/v1.19.0"
},
"time": "2023-12-07T16:22:33+00:00"
"time": "2024-02-29T11:52:51+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.25.0",
"version": "1.26.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240"
"reference": "231e3186624c03d7e7c890ec662b81e6b0405227"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bd84b629c8de41aa2ae82c067c955e06f1b00240",
"reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227",
"reference": "231e3186624c03d7e7c890ec662b81e6b0405227",
"shasum": ""
},
"require": {
@@ -3218,22 +3218,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.25.0"
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.26.0"
},
"time": "2024-01-04T17:06:16+00:00"
"time": "2024-02-23T16:05:55+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.30",
"version": "9.2.31",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089"
"reference": "48c34b5d8d983006bd2adc2d0de92963b9155965"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089",
"reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965",
"reference": "48c34b5d8d983006bd2adc2d0de92963b9155965",
"shasum": ""
},
"require": {
@@ -3290,7 +3290,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31"
},
"funding": [
{
@@ -3298,7 +3298,7 @@
"type": "github"
}
],
"time": "2023-12-22T06:47:57+00:00"
"time": "2024-03-02T06:37:42+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -3696,16 +3696,16 @@
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
"reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
"reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
"shasum": ""
},
"require": {
@@ -3740,7 +3740,7 @@
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2"
},
"funding": [
{
@@ -3748,7 +3748,7 @@
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
"time": "2024-03-02T06:27:43+00:00"
},
{
"name": "sebastian/code-unit",
@@ -3994,16 +3994,16 @@
},
{
"name": "sebastian/diff",
"version": "4.0.5",
"version": "4.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
"reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
"reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc",
"reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc",
"shasum": ""
},
"require": {
@@ -4048,7 +4048,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.5"
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.6"
},
"funding": [
{
@@ -4056,7 +4056,7 @@
"type": "github"
}
],
"time": "2023-05-07T05:35:17+00:00"
"time": "2024-03-02T06:30:58+00:00"
},
{
"name": "sebastian/environment",
@@ -4123,16 +4123,16 @@
},
{
"name": "sebastian/exporter",
"version": "4.0.5",
"version": "4.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72",
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72",
"shasum": ""
},
"require": {
@@ -4188,7 +4188,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6"
},
"funding": [
{
@@ -4196,20 +4196,20 @@
"type": "github"
}
],
"time": "2022-09-14T06:03:37+00:00"
"time": "2024-03-02T06:33:00+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.6",
"version": "5.0.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bde739e7565280bda77be70044ac1047bc007e34"
"reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
"reference": "bde739e7565280bda77be70044ac1047bc007e34",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
"reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
"shasum": ""
},
"require": {
@@ -4252,7 +4252,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7"
},
"funding": [
{
@@ -4260,7 +4260,7 @@
"type": "github"
}
],
"time": "2023-08-02T09:26:13+00:00"
"time": "2024-03-02T06:35:11+00:00"
},
{
"name": "sebastian/lines-of-code",
@@ -4660,16 +4660,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.8.1",
"version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
"reference": "14f5fff1e64118595db5408e946f3a22c75807f7"
"reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/14f5fff1e64118595db5408e946f3a22c75807f7",
"reference": "14f5fff1e64118595db5408e946f3a22c75807f7",
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b",
"reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b",
"shasum": ""
},
"require": {
@@ -4736,7 +4736,7 @@
"type": "open_collective"
}
],
"time": "2024-01-11T20:47:48+00:00"
"time": "2024-02-16T15:06:51+00:00"
},
{
"name": "swoole/ide-helper",
@@ -4772,16 +4772,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.28.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
"shasum": ""
},
"require": {
@@ -4795,9 +4795,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@@ -4834,7 +4831,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0"
},
"funding": [
{
@@ -4850,20 +4847,20 @@
"type": "tidelift"
}
],
"time": "2023-01-26T09:26:14+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.28.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "42292d99c55abe617799667f454222c54c60e229"
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"shasum": ""
},
"require": {
@@ -4877,9 +4874,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@@ -4917,7 +4911,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
},
"funding": [
{
@@ -4933,7 +4927,7 @@
"type": "tidelift"
}
],
"time": "2023-07-28T09:04:16+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "textalk/websocket",
@@ -4986,16 +4980,16 @@
},
{
"name": "theseer/tokenizer",
"version": "1.2.2",
"version": "1.2.3",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
"shasum": ""
},
"require": {
@@ -5024,7 +5018,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.2"
"source": "https://github.com/theseer/tokenizer/tree/1.2.3"
},
"funding": [
{
@@ -5032,7 +5026,7 @@
"type": "github"
}
],
"time": "2023-11-20T00:12:19+00:00"
"time": "2024-03-03T12:36:25+00:00"
},
{
"name": "twig/twig",
+51 -25
View File
@@ -5,12 +5,12 @@
x-logging: &x-logging
logging:
driver: 'json-file'
driver: "json-file"
options:
max-file: '5'
max-size: '10m'
max-file: "5"
max-size: "10m"
version: '3'
version: "3"
services:
traefik:
@@ -645,6 +645,7 @@ services:
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_MAINTENANCE_DELAY
appwrite-worker-usage:
entrypoint: worker-usage
@@ -677,6 +678,37 @@ services:
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-worker-usage-dump:
entrypoint: worker-usage-dump
<<: *x-logging
container_name: appwrite-worker-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_PROVIDER
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-schedule:
entrypoint: schedule
<<: *x-logging
@@ -857,7 +889,7 @@ services:
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
- MYSQL_USER=${_APP_DB_USER}
- MYSQL_PASSWORD=${_APP_DB_PASS}
command: 'mysqld --innodb-flush-method=fsync' # add ' --query_cache_size=0' for DB tests
command: "mysqld --innodb-flush-method=fsync" # add ' --query_cache_size=0' for DB tests
# command: mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bu && mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bu
# smtp:
@@ -903,15 +935,16 @@ services:
#
# MailCatcher - An SMTP server. Catches all system emails and displays them in a nice UI.
# RequestCatcher - An HTTP server. Catches all system https calls and displays them using a simple HTTP API. Used to debug & tests webhooks and HTTP tasks
# RedisCommander - A nice UI for exploring Redis data
# Webgrind - A nice UI for exploring and debugging code-level stuff
# Redis Insight - A nice UI for exploring Redis data
# Adminer - A nice UI for exploring MariaDB data
# GraphQl Explorer - A nice UI for exploring GraphQL API
maildev: # used mainly for dev tests
image: appwrite/mailcatcher:1.0.0
container_name: appwrite-mailcatcher
<<: *x-logging
ports:
- '9503:1080'
- "9503:1080"
networks:
- appwrite
@@ -920,7 +953,7 @@ services:
container_name: appwrite-requestcatcher
<<: *x-logging
ports:
- '9504:5000'
- "9504:5000"
networks:
- appwrite
@@ -934,21 +967,15 @@ services:
networks:
- appwrite
# redis-commander:
# image: rediscommander/redis-commander:latest
# restart: unless-stopped
# networks:
# - appwrite
# environment:
# - REDIS_HOSTS=redis
# ports:
# - "8081:8081"
# webgrind:
# image: 'jokkedk/webgrind:latest'
# volumes:
# - './debug:/tmp'
# ports:
# - '3001:80'
redis-insight:
image: redis/redisinsight:latest
restart: unless-stopped
networks:
- appwrite
environment:
- REDIS_HOSTS=redis
ports:
- "8081:5540"
graphql-explorer:
container_name: appwrite-graphql-explorer
@@ -961,7 +988,6 @@ services:
environment:
- SERVER_URL=http://localhost/v1/graphql
# Dev Tools End ------------------------------------------------------------------------------------------
networks:
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.create_phone_verification()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.create_recovery(email: 'email@example.com', url: 'https://example.com')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.create_verification(url: 'https://example.com')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.delete_identity(identity_id: '[IDENTITY_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.delete_session(session_id: '[SESSION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.delete_sessions()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.get_prefs()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.get_session(session_id: '[SESSION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.get()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.list_identities()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.list_logs()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.list_sessions()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_email(email: 'email@example.com', password: 'password')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_name(name: '[NAME]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_password(password: '')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_phone_verification(user_id: '[USER_ID]', secret: '[SECRET]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_phone(phone: '+12065550100', password: 'password')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_prefs(prefs: {})
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_recovery(user_id: '[USER_ID]', secret: '[SECRET]', password: 'password', password_again: 'password')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_session(session_id: '[SESSION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_status()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ account = Account.new(client)
response = account.update_verification(user_id: '[USER_ID]', secret: '[SECRET]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ avatars = Avatars.new(client)
response = avatars.get_browser(code: 'aa')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ avatars = Avatars.new(client)
response = avatars.get_credit_card(code: 'amex')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ avatars = Avatars.new(client)
response = avatars.get_favicon(url: 'https://example.com')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ avatars = Avatars.new(client)
response = avatars.get_flag(code: 'af')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ avatars = Avatars.new(client)
response = avatars.get_image(url: 'https://example.com')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ avatars = Avatars.new(client)
response = avatars.get_initials()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ avatars = Avatars.new(client)
response = avatars.get_qr(text: '[TEXT]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_boolean_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_collection(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', name: '[NAME]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_datetime_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_document(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', document_id: '[DOCUMENT_ID]', data: {})
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_email_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_enum_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', elements: [], required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_float_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_index(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', type: 'key', attributes: [])
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_integer_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_ip_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_relationship_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', related_collection_id: '[RELATED_COLLECTION_ID]', type: 'oneToOne')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_string_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', size: 1, required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create_url_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.create(database_id: '[DATABASE_ID]', name: '[NAME]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.delete_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.delete_collection(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.delete_document(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', document_id: '[DOCUMENT_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.delete_index(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.delete(database_id: '[DATABASE_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.get_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.get_collection(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.get_document(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', document_id: '[DOCUMENT_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.get_index(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.get(database_id: '[DATABASE_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.list_attributes(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.list_collections(database_id: '[DATABASE_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.list_documents(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.list_indexes(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.list()
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.update_boolean_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false, default: false)
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.update_collection(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', name: '[NAME]')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.update_datetime_attribute(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', key: '', required: false, default: '')
puts response.inspect
puts response.inspect
@@ -1,4 +1,4 @@
require 'Appwrite'
require 'appwrite'
include Appwrite
@@ -11,4 +11,4 @@ databases = Databases.new(client)
response = databases.update_document(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', document_id: '[DOCUMENT_ID]')
puts response.inspect
puts response.inspect

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