Compare commits

..
Author SHA1 Message Date
Matej Bačo d89f8cc6b9 Upgrade pools lib 2024-04-19 13:14:00 +02:00
Christy Jacob c5316681ca chore: update database library 2024-04-18 13:43:32 +00:00
Christy JacobandGitHub ccfe363905 Merge pull request #7992 from appwrite/chore-task-addition
Chore task addition
2024-04-18 14:17:14 +04:00
shimon e3ed9b43f4 adding QueueRetry,QueueCount to tasks list 2024-04-18 13:13:40 +03:00
Christy JacobandGitHub f97f24eb16 Merge pull request #7991 from appwrite/chore-queue-retry-update
Chore: queue retry update
2024-04-18 13:32:19 +04:00
shimon 92716ed72e queue retry validator update 2024-04-18 12:09:39 +03:00
Matej Bačo 43b8030f10 Upgrade DB lib 2024-04-18 10:32:14 +02:00
Matej Bačo fd81c95e38 Merge branch 'refactor-usage-sn' of github.com:appwrite/appwrite into refactor-usage-sn 2024-04-16 09:59:24 +02:00
Matej Bačo 487d93bf04 Revert breaking changes 2024-04-16 09:59:02 +02:00
Christy JacobandGitHub d1a7d8f54a Merge pull request #7960 from appwrite/revert-connection-changes
Revert connection changes
2024-04-16 11:56:33 +04:00
Jake Barnby f95800de73 Revert connection changes 2024-04-12 14:37:15 +12:00
Jake BarnbyandGitHub 3f92987002 Merge pull request #7953 from appwrite/feat-check-internal-id
Match memberships on internal ID
2024-04-11 19:12:11 +12:00
Jake Barnby ff8ebb4f7e Match memberships on internal ID 2024-04-11 19:09:04 +12:00
Jake Barnby 114a450f26 Update websockets to release version (no change) 2024-04-11 14:18:31 +12:00
Eldad A. FuxandGitHub 143b73deef Merge pull request #7951 from appwrite/fix-admin-mode-on-console
fix: admin mode on console
2024-04-10 20:18:51 +02:00
Torsten Dittmann 7cff879e58 style: remove unused imports 2024-04-10 19:52:14 +02:00
Torsten Dittmann 11fdefa2b8 chore: run formatter 2024-04-10 19:49:16 +02:00
Torsten Dittmann 8cad8f5533 fix: admin mode on console 2024-04-10 19:46:31 +02:00
Jake BarnbyandGitHub d6be999c12 Merge pull request #7941 from appwrite/feat-reclaim-only-current-connection
Reclaim only current connection
2024-04-10 17:08:53 +12:00
Jake Barnby 3859f037a1 Revert "Reclaim only used connections for workers"
This reverts commit fefb60557d.

# Conflicts:
#	app/worker.php
2024-04-09 20:50:33 +12:00
Jake Barnby 9a3f6e7f71 Add connections test 2024-04-09 20:27:30 +12:00
Jake Barnby b50ec49ac1 Move Connections to pools namespace 2024-04-09 20:26:42 +12:00
Jake Barnby 388f450d89 Fix missing injection 2024-04-09 18:11:08 +12:00
Jake Barnby 4bef6125f7 Use on worker stop to properly reclaim realtime redis connections and unsubscribe 2024-04-09 17:05:44 +12:00
Jake Barnby fefb60557d Reclaim only used connections for workers 2024-04-09 17:04:31 +12:00
Jake Barnby 730e7319df Use connection group to reclaim all use connections for request 2024-04-09 17:03:28 +12:00
Jake BarnbyandGitHub 0e5f6a34b0 Merge pull request #7937 from appwrite/feat-reclaim-only-current-connection
Update database
2024-04-08 20:29:39 +12:00
Jake Barnby a0051eaa81 Update database 2024-04-08 19:59:36 +12:00
Jake BarnbyandGitHub c5c0c8a8e6 Merge pull request #6886 from appwrite/feat-reclaim-only-current-connection
Fix connection reclaim logic.
2024-04-08 16:14:04 +12:00
Jake Barnby 7b66cc5672 Revert getProjectDB change 2024-04-08 15:48:57 +12:00
Jake Barnby 899bba64d1 Add try/catch/reclaim around sending stats 2024-04-08 14:55:41 +12:00
Jake Barnby fc4cbb8174 Move getConsole tick inside try/catch 2024-04-08 14:40:51 +12:00
Jake BarnbyandGitHub be761dd5cd Merge branch 'refactor-usage-sn' into feat-reclaim-only-current-connection 2024-04-08 14:34:52 +12:00
Jake Barnby 293d85525c Fix on message db resource fetch 2024-04-08 13:43:53 +12:00
Khushboo VermaandGitHub 9f7ecb98d3 Merge pull request #7925 from appwrite/chore-bump-executor-version
Bump executor version to 0.5.1
2024-04-05 23:04:00 +05:30
Khushboo Verma 6d5b087605 Bump executor version to 0.5.1 2024-04-05 22:39:52 +05:30
Jake Barnby 048b4f76c8 Merge remote-tracking branch 'origin/refactor-usage-sn' into feat-reclaim-only-current-connection 2024-04-04 20:28:14 +13:00
Jake BarnbyandGitHub 6ff50103ac Merge pull request #7917 from appwrite/feat-db-update
Update db for relationships and object as array attributes fixes
2024-04-04 20:16:44 +13:00
Jake Barnby ccf437dac4 Update db for relationships and object as array attributes fixes 2024-04-04 19:56:09 +13:00
Jake Barnby 2452d3a479 Reclaim only the used connection for realtime 2024-04-04 18:57:33 +13:00
Jake Barnby 479ed3d0b1 Inline defaults 2024-04-04 18:51:40 +13:00
Jake Barnby 8974dcfb39 Merge remote-tracking branch 'origin/refactor-usage-sn' into feat-reclaim-only-current-connection
# Conflicts:
#	app/console
#	app/init.php
2024-04-04 17:21:16 +13:00
Eldad A. FuxandGitHub 47213c50b6 Merge pull request #7911 from appwrite/remove-realtime-timer-tick
Comment timer tick
2024-04-03 19:49:26 +02:00
Khushboo Verma f66a65f27b Comment timer tick 2024-04-03 22:54:14 +05:30
Matej BačoandGitHub aa92257c76 Merge pull request #7910 from appwrite/chore-update-executor-version
Update executor version
2024-04-03 14:08:26 +02:00
Khushboo Verma 008c3ac19a Update executor version 2024-04-03 17:18:15 +05:30
Christy JacobandGitHub a792f3de1d Merge pull request #7896 from appwrite/fix-deployment-not-found-error
Create failed execution from worker if deployment doesn't exist
2024-04-02 17:49:28 +04:00
Khushboo Verma 26db6fa4c5 Remove var-dump 2024-04-02 17:49:09 +05:30
Matej Bačo 7c691b3c7c Fix version missmatch 2024-04-02 13:01:55 +02:00
Matej Bačo e3a039db49 Merge branch 'refactor-usage-sn' of github.com:appwrite/appwrite into refactor-usage-sn 2024-04-02 11:42:18 +02:00
Matej Bačo 7a25a3c529 Upgrade database lib for ZDT 2024-04-02 11:42:10 +02:00
Damodar LohaniandGitHub 76eacaf8e2 Merge pull request #7905 from appwrite/PEA-649-fix-storage-issue
PEA-649 storage do adapter http version
2024-04-02 14:37:43 +05:45
Damodar Lohani 026f5dde2d set http version to 1.1 for do spaces 2024-04-02 08:35:14 +00:00
Damodar Lohani 39da1b8028 composer update 2024-04-02 08:32:30 +00:00
Eldad A. FuxandGitHub f875c6aa70 Merge pull request #7884 from appwrite/refactor-var-dump
Remove var_dump calls
2024-04-01 20:11:49 +02:00
Khushboo Verma 3469ebf7b0 Add var_dump to debug flaky test 2024-04-01 23:07:11 +05:30
Khushboo Verma 7f038ec704 Merge branch 'refactor-usage-sn' into fix-deployment-not-found-error 2024-04-01 22:10:00 +05:30
Eldad A. FuxandGitHub 532ed5b340 Merge pull request #7893 from appwrite/fix-oauth-error-code
Fix OAuth error code
2024-04-01 18:36:55 +02:00
Christy JacobandGitHub 4e08c6d02d Merge pull request #7882 from appwrite/feat-configurable-collections
Feat configurable collections
2024-04-01 21:35:47 +05:30
Khushboo Verma e7e85bfb76 Update response code 2024-04-01 19:37:51 +05:30
Khushboo Verma a3a7763340 Created failed execution for build errors 2024-04-01 19:07:17 +05:30
Khushboo Verma ec930bf125 Add request headers 2024-04-01 17:18:42 +05:30
Khushboo Verma eb8543c690 Create failed execution if deployment doesn't exist 2024-04-01 17:04:36 +05:30
Khushboo Verma 75d8cc3327 Updated error code for OAuth error 2024-04-01 13:27:44 +05:30
Steven NguyenandGitHub 5ee5ffb288 refactor: remove var_dump calls 2024-03-29 21:24:05 +00:00
Christy Jacob f8c44c8a50 chore: linter 2024-03-29 10:18:33 +00:00
Matej Bačo 803ba6182c Update composer.lock 2024-03-29 10:48:31 +01:00
Matej Bačo 5275d0b021 Merge branch 'refactor-usage-sn' into feat-configurable-collections 2024-03-29 10:48:11 +01:00
Jake BarnbyandGitHub 3d53249335 Merge pull request #7877 from appwrite/refactor-usage-sn-45-8
Transaction and reconnection fixes
2024-03-29 00:54:28 +13:00
fogelito 5ff5c930a5 composer.lock 2024-03-28 13:32:54 +02:00
fogelito 5657e7d04e Bust database 45-8 2024-03-28 13:08:55 +02:00
Christy JacobandGitHub 9adf124274 Merge pull request #7854 from appwrite/feat-improve-vcs-comment-1
Update VCS Comment
2024-03-25 19:24:38 +05:30
Christy JacobandGitHub 20e82b1b8b Merge pull request #7777 from appwrite/fix-cloud-tests
Fix tests required for Cloud
2024-03-25 12:38:33 +05:30
Damodar LohaniandGitHub 7d68c12f1b Update init.php 2024-03-25 11:35:28 +05:45
Damodar LohaniandGitHub b3c2b54d09 Merge branch 'refactor-usage-sn' into fix-cloud-tests 2024-03-25 07:03:45 +05:45
Damodar LohaniandGitHub 061368fae0 Update init.php 2024-03-24 12:09:30 +05:45
Christy JacobandGitHub f2dbda10c0 Merge pull request #7852 from appwrite/fix-function-domain-permissions
Fix function domain permissions
2024-03-21 12:29:21 +05:30
Christy JacobandGitHub 380b5f7f84 Merge pull request #7414 from appwrite/remove-cloud-scripts
remove cloud related scripts
2024-03-21 01:27:34 +05:30
Khushboo Verma fe4362c29f Update VCS Comment 2024-03-20 22:17:48 +05:30
Steven NguyenandGitHub 47f442b98e fix(functions): fix permissions for function domains
Execution via domain should be blocked if permissions does not contain
any and permissions does not contain guests.
2024-03-20 15:49:05 +00:00
Steven NguyenandGitHub ac397935a1 fix: remove escaping
It's done automatically when setting the params already.
2024-03-20 15:47:33 +00:00
Steven NguyenandGitHub fcfff2ab04 chore: remove dead code in error template 2024-03-20 15:46:42 +00:00
Matej Bačo 440d924518 Allow getCache override 2024-03-20 14:14:23 +01:00
Matej Bačo 2ae9d0b710 Make realtime resources configurable 2024-03-20 13:47:20 +01:00
Christy JacobandGitHub 446ebfffee Merge pull request #7683 from appwrite/fix-vcs-silent-mode
Fix vcs silent mode
2024-03-20 02:57:10 +05:30
Eldad A. FuxandGitHub f824c3c83e Merge pull request #7838 from appwrite/fix-identities-query-to-use-internal-ids
use internal ids for query
2024-03-18 18:35:01 +01:00
Christy JacobandGitHub a2d8e6d44e Merge pull request #7840 from appwrite/update-avatars-api
chore: update avatars API
2024-03-18 22:44:34 +05:30
Christy Jacob eeba452fb5 chore: linter 2024-03-18 12:43:42 +00:00
Christy Jacob 5e6c94d307 chore: update checks 2024-03-18 12:41:51 +00:00
Christy Jacob a306cb87d8 chore: update avatars API 2024-03-18 12:07:14 +00:00
Damodar Lohani 979f6ee150 Merge remote-tracking branch 'origin/refactor-usage-sn' into fix-cloud-tests 2024-03-18 09:41:43 +00:00
Damodar Lohani 21d4b8feef check user internal Id on membership 2024-03-18 09:01:54 +00:00
Damodar Lohani 2a6da11842 Merge remote-tracking branch 'origin/refactor-usage-sn' into fix-identities-query-to-use-internal-ids 2024-03-18 08:55:30 +00:00
Damodar Lohani c849ff0b0f use internal ids for query 2024-03-18 08:52:47 +00:00
Damodar LohaniandGitHub a75ce14218 Merge pull request #7835 from appwrite/lohanidamodar-patch-5
Admin mode use teamInternalId
2024-03-17 15:50:40 +05:45
Damodar LohaniandGitHub 795f1035ef Merge pull request #7834 from appwrite/lohanidamodar-patch-4
Fix membership query to use internalId
2024-03-17 15:50:06 +05:45
Damodar LohaniandGitHub c5512ae010 Update init.php 2024-03-17 15:01:09 +05:45
Damodar LohaniandGitHub 05221334e2 use team internal id in delete memberships 2024-03-17 14:55:31 +05:45
Damodar LohaniandGitHub 4fcb399867 use team internal id for membership check on update 2024-03-17 14:54:08 +05:45
Damodar LohaniandGitHub 24319b8417 Fix membership query to use internalId 2024-03-17 14:51:27 +05:45
Damodar Lohani 17d85a478a fix event test dsn 2024-03-14 01:18:17 +00:00
Jake BarnbyandGitHub f2cdd9cc1d Merge pull request #7825 from appwrite/chore-update
Update db
2024-03-13 19:10:07 +01:00
Jake Barnby 310aa56e5d Update db 2024-03-13 19:08:07 +01:00
Jake BarnbyandGitHub 5c0df92346 Merge pull request #7818 from appwrite/fix-exception-wrap-order
Fix exception wrap order
2024-03-13 12:46:41 +01:00
Jake Barnby a4bdf63afd Fix exception wrap order of operations 2024-03-13 12:41:55 +01:00
Damodar LohaniandGitHub f356f13ee6 Merge branch 'refactor-usage-sn' into fix-cloud-tests 2024-03-13 11:20:12 +05:45
Eldad A. FuxandGitHub 993c9df840 Merge pull request #7808 from appwrite/escape-function-build-command
Escape function build command
2024-03-13 01:21:11 +01:00
Steven Nguyen b4c065a342 Escape function build command
The extra trim is neded to because the extra quotes interfere with
additional operations in the executor/orchestration library.
2024-03-13 01:03:51 +01:00
Jake BarnbyandGitHub 267f6bc752 Merge pull request #7787 from appwrite/fix-query-exceptions
Fix database exception wrapping
2024-03-12 10:17:10 +01:00
Jake Barnby a1d86c9b3f Switch over errors 2024-03-11 16:11:37 +01:00
Jake Barnby 550837b572 Pass through query exception message 2024-03-11 13:46:02 +01:00
Jake Barnby 22b3ea7e8d Catch auth fixes 2024-03-11 13:03:30 +01:00
Jake Barnby cea4e0d8b6 Wrap all db exceptions in error handler 2024-03-11 12:54:42 +01:00
Christy JacobandGitHub f482d96225 Merge pull request #7784 from appwrite/feat-cloud-log-400
Upload 400s to separate error logger
2024-03-11 15:47:53 +05:30
Bradley Schofield 9c100758de Update general.php 2024-03-11 10:29:57 +01:00
Bradley Schofield 15a6c510a0 Upload 400s to separate error logger 2024-03-11 10:23:52 +01:00
Damodar Lohani b409efc492 fix path 2024-03-10 08:01:10 +00:00
shimon 54a02fbb96 Merge remote-tracking branch 'origin/remove-cloud-scripts' into remove-cloud-scripts 2024-03-06 18:00:00 +01:00
shimon dfac3d585a Merge branch 'main' of github.com:appwrite/appwrite into remove-cloud-scripts 2024-03-06 17:58:58 +01:00
Torsten DittmannandGitHub 05f73fbe46 Merge pull request #7728 from appwrite/update-header
Updated header
2024-03-05 11:45:48 +01:00
Dylan ed62a0ca4a Updated header 2024-03-05 11:31:58 +01:00
Damodar Lohani 57d7995e36 fix file path 2024-03-04 12:58:28 +00:00
Damodar Lohani 5e6f53d6aa reclaim pool 2024-03-04 12:50:49 +00:00
Damodar Lohani 5f4970befd fix path 2024-03-04 12:49:56 +00:00
Damodar Lohani 060ec455b3 fix 2024-03-04 12:44:40 +00:00
Damodar Lohani 86dc85f3a4 fix file path 2024-03-04 12:17:35 +00:00
Damodar Lohani 064ac2ccf8 fix dsn in event test 2024-03-04 11:15:45 +00:00
Eldad A. FuxandGitHub 9e4250ad9f Merge pull request #7715 from appwrite/lohanidamodar-patch-3
update cover image for SDKs
2024-03-03 07:35:45 +01:00
Damodar LohaniandGitHub fc498fd80f update cover image for SDKs 2024-03-03 08:19:36 +05:45
Christy JacobandGitHub 9ea34ce068 Merge pull request #7660 from appwrite/refactor-usage-sn
Refactor usage sn
2024-03-01 22:14:28 +05:30
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
Khushboo Verma 4e2120952f Fix vcs silent mode 2024-02-28 13:27:36 +05:30
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
Christy JacobandGitHub ac5d45d71c Merge branch 'refactor-usage-sn' into remove-cloud-scripts 2024-02-28 09:52:12 +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
shimon 22e7c58d7d Merge branch 'refactor-usage-sn' of github.com:appwrite/appwrite into remove-cloud-scripts 2024-02-19 17:38:13 +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
shimon 207811a224 usage updates 2024-02-13 19:26:23 +02:00
shimon 84e4748625 usage updates 2024-02-13 17:58:27 +02:00
shimon 7d38860d16 usage updates 2024-02-13 17:04:16 +02:00
shimon e1e5f5d96b usage updates 2024-02-13 16:27:01 +02:00
shimon 219b28e9bf usage updates 2024-02-13 16:08:40 +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
shimon 96317f0acb sync with main 2024-02-13 10:46:24 +02:00
shimon a0e82ccfab sync with main 2024-02-13 10:35:33 +02:00
shimon 8c44627da1 Merge branch 'main' of github.com:appwrite/appwrite into remove-cloud-scripts
 Conflicts:
	Dockerfile
	src/Appwrite/Platform/Services/Workers.php
2024-02-13 10:29:17 +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
Matej Bačo abb1007385 Rework project creation 2024-02-07 12:04:46 +01:00
shimon 93a99b561c remove debug lines 2024-02-07 11:54:18 +02:00
Matej Bačo a89b73d20b Fix bug 2024-02-07 10:48:02 +01:00
Matej Bačo d5216d5b14 Linter fix 2024-02-07 10:17:34 +01:00
Matej Bačo 939aec866e Add getProxyProjectDatabase hook 2024-02-07 10:16:17 +01: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
Matej Bačo a7e95588c6 Fix bug on ZDT 2024-02-06 16:08:42 +01:00
Matej Bačo 3a5c233b59 Fix bug 2024-02-06 11:47:43 +00:00
Matej Bačo 8154b4c131 Linter fix 2024-02-06 12:11:27 +01:00
Matej Bačo d4afe22396 Add ZDT migration support to project creation 2024-02-06 12:07:47 +01:00
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 ab80999d1e cleanup 2024-01-31 12:13:02 +02:00
shimon be829e2db4 Merge branch 'refactor-usage-sn' of github.com:appwrite/appwrite into remove-cloud-scripts
 Conflicts:
	Dockerfile
	docker-compose.yml
	src/Appwrite/Platform/Services/Tasks.php
	src/Appwrite/Platform/Services/Workers.php
	src/Appwrite/Platform/Tasks/CalcTierStats.php
	src/Appwrite/Platform/Workers/Hamster.php
2024-01-30 20:47:35 +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 6ad63b6f7b addressing comments 2024-01-17 10:44:16 +02:00
shimon 4b23440c2d remove cloud related scripts 2024-01-09 15:44:56 +02:00
shimon 85950868f2 remove cloud related scripts 2024-01-09 15:30:43 +02:00
shimon eb70990bf0 remove cloud related scripts 2024-01-09 15:22:02 +02:00
shimon 880526d6d3 Merge branch 'main' of github.com:appwrite/appwrite into remove-cloud-scripts 2024-01-09 12:11:32 +02:00
shimon 1da476e5ac remove cloud related scripts 2024-01-09 11:13:58 +02: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
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
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
Eldad Fux f4fedc832e Fix formating 2023-10-21 08:30:35 -04:00
Eldad Fux 92538c57f6 cleanups 2023-10-21 07:29:23 -04:00
Eldad Fux 77a4300669 cleanups 2023-10-21 07:22:46 -04:00
Eldad Fux 2884cb636b cleanup 2023-10-21 07:18:21 -04:00
Eldad Fux 025a0292f4 Revert "Sync with main"
This reverts commit 0ea1418132.
2023-10-21 07:02:44 -04:00
Eldad Fux 0ea1418132 Sync with main 2023-10-21 07:00:21 -04:00
Eldad A. FuxandGitHub e5fca85d88 Merge branch 'main' into feat-reclaim-only-current-connection 2023-10-21 06:42:59 -04:00
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
Eldad Fux c6c7734c29 Merge pull request #6496 from appwrite/fix-readme-cn
Update logo in README-CN.md

<!--
Thank you for sending the PR! We appreciate you spending the time to work on these changes.

Help us understand your motivation by explaining why you decided to make this change.

You can learn more about contributing to appwrite here: https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md

Happy contributing!

-->

## What does this PR do?

(Provide a description of what this PR does and why it's needed.)

## Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)

## Related PRs and Issues

- (Related PR or issue)

## Checklist

- [ ] Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
- [ ] If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?
2023-10-11 22:01:01 +02: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
269 changed files with 2404 additions and 1438 deletions
+2 -1
View File
@@ -73,11 +73,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 }}
+2 -2
View File
@@ -98,8 +98,8 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/worker-messaging && \
chmod +x /usr/local/bin/worker-webhooks && \
chmod +x /usr/local/bin/worker-migrations && \
chmod +x /usr/local/bin/worker-usage
chmod +x /usr/local/bin/worker-usage && \
chmod +x /usr/local/bin/worker-usage-dump
# Letsencrypt Permissions
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
+1 -1
View File
@@ -1,4 +1,4 @@
> Great news! Appwrite Cloud is now in public beta! Sign up at [cloud.appwrite.io](https://cloud.appwrite.io) for a hassle-free, hosted experience. Join us in the Cloud today! ☁️🎉
> Our Appwrite Init event has concluded. You can check out all the new and upcoming features [on our Init website](https://appwrite.io/init) 🚀
<br />
<p align="center">
-3
View File
@@ -131,9 +131,6 @@ CLI::setResource('queue', function (Group $pools) {
CLI::setResource('queueForFunctions', function (Connection $queue) {
return new Func($queue);
}, ['queue']);
CLI::setResource('queueForHamster', function (Connection $queue) {
return new Hamster($queue);
}, ['queue']);
CLI::setResource('queueForDeletes', function (Connection $queue) {
return new Delete($queue);
}, ['queue']);
+26 -4
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 => [
@@ -629,7 +639,7 @@ return [
Exception::PROJECT_PROVIDER_UNSUPPORTED => [
'name' => Exception::PROJECT_PROVIDER_UNSUPPORTED,
'description' => 'The chosen OAuth provider is unsupported. Please check the <a href="/docs/client/account?sdk=web-default#accountCreateOAuth2Session">Create OAuth2 Session docs</a> for the complete list of supported OAuth providers.',
'code' => 501,
'code' => 400,
],
Exception::PROJECT_INVALID_SUCCESS_URL => [
'name' => Exception::PROJECT_INVALID_SUCCESS_URL,
@@ -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).',
+22 -14
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) {
@@ -555,7 +555,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$identityWithMatchingEmail = $dbForProject->findOne('identities', [
Query::equal('providerEmail', [$email]),
Query::notEqual('userId', $userId),
Query::notEqual('userInternalId', $user->getInternalId()),
]);
if (!empty($identityWithMatchingEmail)) {
throw new Exception(Exception::USER_ALREADY_EXISTS);
@@ -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([
@@ -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;
@@ -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)
@@ -1987,10 +1985,10 @@ App::patch('/v1/account/email')
// Makes sure this email is not already used in another identity
$identityWithMatchingEmail = $dbForProject->findOne('identities', [
Query::equal('providerEmail', [$email]),
Query::notEqual('userId', $user->getId()),
Query::notEqual('userInternalId', $user->getInternalId()),
]);
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());
@@ -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)
@@ -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)
@@ -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
+42 -31
View File
@@ -23,6 +23,7 @@ use Utopia\Validator\URL;
use Utopia\Validator\WhiteList;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
use Utopia\Fetch\Client;
$avatarCallback = function (string $type, string $code, int $width, int $height, int $quality, Response $response) {
@@ -283,14 +284,21 @@ App::get('/v1/avatars/image')
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
$fetch = @\file_get_contents($url);
$client = new Client();
try {
$res = $client
->setAllowRedirects(false)
->fetch($url);
} catch (\Throwable) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
if (!$fetch) {
if ($res->getStatusCode() !== 200) {
throw new Exception(Exception::AVATAR_IMAGE_NOT_FOUND);
}
try {
$image = new Image($fetch);
$image = new Image($res->getBody());
} catch (\Exception $exception) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unable to parse image');
}
@@ -339,31 +347,27 @@ App::get('/v1/avatars/favicon')
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
$curl = \curl_init();
$client = new Client();
try {
$res = $client
->setAllowRedirects(false)
->setUserAgent(\sprintf(
APP_USERAGENT,
App::getEnv('_APP_VERSION', 'UNKNOWN'),
App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY)
))
->fetch($url);
} catch (\Throwable) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
\curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 3,
CURLOPT_URL => $url,
CURLOPT_USERAGENT => \sprintf(
APP_USERAGENT,
App::getEnv('_APP_VERSION', 'UNKNOWN'),
App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY)
),
]);
$html = \curl_exec($curl);
\curl_close($curl);
if (!$html) {
if ($res->getStatusCode() !== 200) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
$doc = new DOMDocument();
$doc->strictErrorChecking = false;
@$doc->loadHTML($html);
@$doc->loadHTML($res->getBody());
$links = $doc->getElementsByTagName('link');
$outputHref = '';
@@ -418,9 +422,22 @@ App::get('/v1/avatars/favicon')
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
if ('ico' == $outputExt) { // Skip crop, Imagick isn\'t supporting icon files
$data = @\file_get_contents($outputHref, false);
$client = new Client();
try {
$res = $client
->setAllowRedirects(false)
->fetch($outputHref);
} catch (\Throwable) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
if ($res->getStatusCode() !== 200) {
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND);
}
$data = $res->getBody();
if ('ico' == $outputExt) { // Skip crop, Imagick isn\'t supporting icon files
if (empty($data) || (\mb_substr($data, 0, 5) === '<html') || \mb_substr($data, 0, 5) === '<!doc') {
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND, 'Favicon not found');
}
@@ -430,13 +447,7 @@ App::get('/v1/avatars/favicon')
->file($data);
}
$fetch = @\file_get_contents($outputHref, false);
if (!$fetch) {
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND);
}
$image = new Image($fetch);
$image = new Image($data);
$image->crop((int) $width, (int) $height);
$output = (empty($output)) ? $type : $output;
$data = $image->output($output, $quality);
+54 -73
View File
@@ -19,16 +19,13 @@ use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Authorization as AuthorizationException;
use Utopia\Database\Exception\Conflict as ConflictException;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Limit as LimitException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Exception\Restricted as RestrictedException;
use Utopia\Database\Exception\Structure as StructureException;
use Utopia\Database\Exception\Timeout as TimeoutException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
@@ -657,16 +654,10 @@ App::put('/v1/databases/:databaseId')
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
try {
$database = $dbForProject->updateDocument('databases', $databaseId, $database
->setAttribute('name', $name)
->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$databaseId, $name])));
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
}
$database = $dbForProject->updateDocument('databases', $databaseId, $database
->setAttribute('name', $name)
->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$databaseId, $name])));
$queueForEvents->setParam('databaseId', $database->getId());
@@ -1015,19 +1006,14 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
$enabled ??= $collection->getAttribute('enabled', true);
try {
$collection = $dbForProject->updateDocument('database_' . $database->getInternalId(), $collectionId, $collection
->setAttribute('name', $name)
->setAttribute('$permissions', $permissions)
->setAttribute('documentSecurity', $documentSecurity)
->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$collectionId, $name])));
$dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
}
$collection = $dbForProject->updateDocument('database_' . $database->getInternalId(), $collectionId, $collection
->setAttribute('name', $name)
->setAttribute('$permissions', $permissions)
->setAttribute('documentSecurity', $documentSecurity)
->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$collectionId, $name])));
$dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity);
$queueForEvents
->setContext('database', $database)
@@ -2822,13 +2808,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
$checkPermissions($collection, $document, Database::PERMISSION_CREATE);
try {
$document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
} catch (DuplicateException $exception) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
}
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
@@ -2936,14 +2916,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$filters = Query::groupByType($queries)['filters'];
try {
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filters, APP_LIMIT_COUNT);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $e->getMessage());
}
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filters, APP_LIMIT_COUNT);
// Add $collectionId and $databaseId for all documents
$processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool {
@@ -2997,6 +2971,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,
@@ -3042,13 +3043,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$queries = Query::parseQueries($queries);
try {
$document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $e->getMessage());
}
$document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries);
if ($document->isEmpty()) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
@@ -3360,22 +3355,14 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$setCollection($collection, $newDocument);
try {
$document = $dbForProject->withRequestTimestamp(
$requestTimestamp,
fn() => $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$document->getId(),
$newDocument
)
);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
}
$document = $dbForProject->withRequestTimestamp(
$requestTimestamp,
fn() => $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$document->getId(),
$newDocument
)
);
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
@@ -3475,16 +3462,10 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
}
$dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) {
try {
$dbForProject->deleteDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documentId
);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (RestrictedException) {
throw new Exception(Exception::DOCUMENT_DELETE_RESTRICTED);
}
$dbForProject->deleteDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documentId
);
});
// Add $collectionId and $databaseId for all documents
+108 -14
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,19 +789,19 @@ 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,
Event::MAILS_QUEUE_NAME,
Event::FUNCTIONS_QUEUE_NAME,
Event::USAGE_QUEUE_NAME,
Event::USAGE_DUMP_QUEUE_NAME,
Event::WEBHOOK_CLASS_NAME,
Event::CERTIFICATES_QUEUE_NAME,
Event::BUILDS_QUEUE_NAME,
Event::MESSAGING_QUEUE_NAME,
Event::MIGRATIONS_QUEUE_NAME,
Event::HAMSTER_CLASS_NAME
Event::MIGRATIONS_QUEUE_NAME
]), 'The name of the queue')
->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true)
->label('sdk.description', '/docs/references/health/get-failed-queue-jobs.md')
@@ -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],
+6 -2
View File
@@ -4,6 +4,7 @@ use Appwrite\Auth\Auth;
use Appwrite\Event\Delete;
use Appwrite\Event\Validator\Event;
use Appwrite\Extend\Exception;
use Appwrite\Hooks\Hooks;
use Appwrite\Network\Validator\Email;
use Appwrite\Network\Validator\Origin;
use Appwrite\Template\Template;
@@ -75,7 +76,8 @@ App::post('/v1/projects')
->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) {
->inject('hooks')
->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, Hooks $hooks) {
$team = $dbForConsole->getDocument('teams', $teamId);
@@ -217,6 +219,8 @@ App::post('/v1/projects')
$dbForProject->createCollection($key, $attributes, $indexes);
}
$hooks->trigger('afterProjectCreation', [ $project, $pools, $cache ]);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($project, Response::MODEL_PROJECT);
@@ -1446,7 +1450,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) {
+83 -107
View File
@@ -581,111 +581,95 @@ App::post('/v1/storage/buckets/:bucketId/files')
$openSSLIV = \bin2hex($iv);
}
try {
if ($file->isEmpty()) {
$doc = new Document([
'$id' => $fileId,
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => $fileHash,
'mimeType' => $mimeType,
'sizeOriginal' => $fileSize,
'sizeActual' => $sizeActual,
'algorithm' => $algorithm,
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'openSSLVersion' => $openSSLVersion,
'openSSLCipher' => $openSSLCipher,
'openSSLTag' => $openSSLTag,
'openSSLIV' => $openSSLIV,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
if ($file->isEmpty()) {
$doc = new Document([
'$id' => $fileId,
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => $fileHash,
'mimeType' => $mimeType,
'sizeOriginal' => $fileSize,
'sizeActual' => $sizeActual,
'algorithm' => $algorithm,
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'openSSLVersion' => $openSSLVersion,
'openSSLCipher' => $openSSLCipher,
'openSSLTag' => $openSSLTag,
'openSSLIV' => $openSSLIV,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('$permissions', $permissions)
->setAttribute('signature', $fileHash)
->setAttribute('mimeType', $mimeType)
->setAttribute('sizeActual', $sizeActual)
->setAttribute('algorithm', $algorithm)
->setAttribute('openSSLVersion', $openSSLVersion)
->setAttribute('openSSLCipher', $openSSLCipher)
->setAttribute('openSSLTag', $openSSLTag)
->setAttribute('openSSLIV', $openSSLIV)
->setAttribute('metadata', $metadata)
->setAttribute('chunksUploaded', $chunksUploaded);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('$permissions', $permissions)
->setAttribute('signature', $fileHash)
->setAttribute('mimeType', $mimeType)
->setAttribute('sizeActual', $sizeActual)
->setAttribute('algorithm', $algorithm)
->setAttribute('openSSLVersion', $openSSLVersion)
->setAttribute('openSSLCipher', $openSSLCipher)
->setAttribute('openSSLTag', $openSSLTag)
->setAttribute('openSSLIV', $openSSLIV)
->setAttribute('metadata', $metadata)
->setAttribute('chunksUploaded', $chunksUploaded);
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* However as with chunk upload even if we are updating, we are essentially creating a file
* adding it's new chunk so we validate create permission instead of update
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* However as with chunk upload even if we are updating, we are essentially creating a file
* adding it's new chunk so we validate create permission instead of update
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
}
} else {
try {
if ($file->isEmpty()) {
$doc = new Document([
'$id' => ID::custom($fileId),
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => '',
'mimeType' => '',
'sizeOriginal' => $fileSize,
'sizeActual' => 0,
'algorithm' => '',
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
if ($file->isEmpty()) {
$doc = new Document([
'$id' => ID::custom($fileId),
'$permissions' => $permissions,
'bucketId' => $bucket->getId(),
'bucketInternalId' => $bucket->getInternalId(),
'name' => $fileName,
'path' => $path,
'signature' => '',
'mimeType' => '',
'sizeOriginal' => $fileSize,
'sizeActual' => 0,
'algorithm' => '',
'comment' => '',
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'search' => implode(' ', [$fileId, $fileName]),
'metadata' => $metadata,
]);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('chunksUploaded', $chunksUploaded)
->setAttribute('metadata', $metadata);
$file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc);
} else {
$file = $file
->setAttribute('chunksUploaded', $chunksUploaded)
->setAttribute('metadata', $metadata);
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* However as with chunk upload even if we are updating, we are essentially creating a file
* adding it's new chunk so we validate create permission instead of update
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
/**
* Validate create permission and skip authorization in updateDocument
* Without this, the file creation will fail when user doesn't have update permission
* However as with chunk upload even if we are updating, we are essentially creating a file
* adding it's new chunk so we validate create permission instead of update
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
}
}
@@ -1383,11 +1367,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
}
if ($fileSecurity && !$valid) {
try {
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file);
} else {
$file = Authorization::skip(fn() => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
}
@@ -1471,11 +1451,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
;
if ($fileSecurity && !$valid) {
try {
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
} else {
$deleted = Authorization::skip(fn() => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId));
}
+12 -23
View File
@@ -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());
@@ -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)
@@ -697,7 +694,7 @@ App::get('/v1/teams/:teamId/memberships')
}
// Set internal queries
$queries[] = Query::equal('teamId', [$teamId]);
$queries[] = Query::equal('teamInternalId', [$team->getInternalId()]);
// Get cursor document if there was a cursor query
$cursor = \array_filter($queries, function ($query) {
@@ -897,16 +894,16 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
throw new Exception(Exception::MEMBERSHIP_NOT_FOUND);
}
if ($membership->getAttribute('teamId') !== $teamId) {
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
}
$team = Authorization::skip(fn() => $dbForProject->getDocument('teams', $teamId));
if ($team->isEmpty()) {
throw new Exception(Exception::TEAM_NOT_FOUND);
}
if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) {
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
}
if (Auth::hash($secret) !== $membership->getAttribute('secret')) {
throw new Exception(Exception::TEAM_INVALID_SECRET);
}
@@ -919,7 +916,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
$user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user
}
if ($membership->getAttribute('userId') !== $user->getId()) {
if ($membership->getAttribute('userInternalId') !== $user->getInternalId()) {
throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')');
}
@@ -970,7 +967,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
$dbForProject->deleteCachedDocument('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())
@@ -1023,10 +1020,6 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
throw new Exception(Exception::TEAM_INVITE_NOT_FOUND);
}
if ($membership->getAttribute('teamId') !== $teamId) {
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
}
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
if ($user->isEmpty()) {
@@ -1039,19 +1032,15 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
throw new Exception(Exception::TEAM_NOT_FOUND);
}
try {
$dbForProject->deleteDocument('memberships', $membership->getId());
} catch (AuthorizationException $exception) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (\Exception $exception) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership from DB');
if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) {
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
}
$dbForProject->deleteDocument('memberships', $membership->getId());
$dbForProject->deleteCachedDocument('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
+2 -2
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);
@@ -941,7 +941,7 @@ App::patch('/v1/users/:userId/email')
// Makes sure this email is not already used in another identity
$identityWithMatchingEmail = $dbForProject->findOne('identities', [
Query::equal('providerEmail', [$email]),
Query::notEqual('userId', $user->getId()),
Query::notEqual('userInternalId', $user->getInternalId()),
]);
if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
+1 -1
View File
@@ -95,7 +95,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
$latestCommentId = '';
if (!empty($providerPullRequestId)) {
if (!empty($providerPullRequestId) && $function->getAttribute('providerSilentMode', false) === false) {
$latestComment = Authorization::skip(fn () => $dbForConsole->findOne('vcsComments', [
Query::equal('providerRepositoryId', [$providerRepositoryId]),
Query::equal('providerPullRequestId', [$providerPullRequestId]),
+319 -93
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)
@@ -196,6 +367,18 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques
return false;
}
/*
App::init()
->groups(['api'])
->inject('project')
->inject('mode')
->action(function (Document $project, string $mode) {
if ($mode === APP_MODE_ADMIN && $project->getId() === 'console') {
throw new AppwriteException(AppwriteException::GENERAL_BAD_REQUEST, 'Admin mode is not allowed for console project');
}
});
*/
App::init()
->groups(['api', 'web'])
->inject('utopia')
@@ -205,13 +388,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 +407,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;
}
}
@@ -455,7 +642,7 @@ App::init()
: Role::users()->toString();
// Add user roles
$memberships = $user->find('teamId', $project->getAttribute('teamId'), 'memberships');
$memberships = $user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships');
if ($memberships) {
foreach ($memberships->getAttribute('roles', []) as $memberRole) {
@@ -571,7 +758,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 +770,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;
}
}
@@ -607,17 +798,93 @@ 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;
$class = \get_class($error);
$code = $error->getCode();
$message = $error->getMessage();
$file = $error->getFile();
$line = $error->getLine();
$trace = $error->getTrace();
if (php_sapi_name() === 'cli') {
Console::error('[Error] Timestamp: ' . date('c', time()));
if ($route) {
Console::error('[Error] Method: ' . $route->getMethod());
Console::error('[Error] URL: ' . $route->getPath());
}
Console::error('[Error] Type: ' . get_class($error));
Console::error('[Error] Message: ' . $message);
Console::error('[Error] File: ' . $file);
Console::error('[Error] Line: ' . $line);
}
switch ($class) {
case 'Utopia\Exception':
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
switch ($code) {
case 400:
$error->setType(AppwriteException::GENERAL_ARGUMENT_INVALID);
break;
case 404:
$error->setType(AppwriteException::GENERAL_ROUTE_NOT_FOUND);
break;
}
break;
case 'Utopia\Database\Exception\Conflict':
$error = new AppwriteException(AppwriteException::DOCUMENT_UPDATE_CONFLICT, previous: $error);
break;
case 'Utopia\Database\Exception\Timeout':
$error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error);
break;
case 'Utopia\Database\Exception\Query':
$error = new AppwriteException(AppwriteException::GENERAL_QUERY_INVALID, $error->getMessage(), previous: $error);
break;
case 'Utopia\Database\Exception\Structure':
$error = new AppwriteException(AppwriteException::DOCUMENT_INVALID_STRUCTURE, $error->getMessage(), previous: $error);
break;
case 'Utopia\Database\Exception\Duplicate':
$error = new AppwriteException(AppwriteException::DOCUMENT_ALREADY_EXISTS);
break;
case 'Utopia\Database\Exception\Restricted':
$error = new AppwriteException(AppwriteException::DOCUMENT_DELETE_RESTRICTED);
break;
case 'Utopia\Database\Exception\Authorization':
$error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED);
break;
}
$code = $error->getCode();
$message = $error->getMessage();
if ($error instanceof AppwriteException) {
$publish = $error->isPublishable();
} else {
$publish = $error->getCode() === 0 || $error->getCode() >= 500;
}
if ($logger && ($publish || $error->getCode() === 0)) {
if ($error->getCode() >= 400 && $error->getCode() < 500) {
// Register error logger
$providerName = App::getEnv('_APP_EXPERIMENT_LOGGING_PROVIDER', '');
$providerConfig = App::getEnv('_APP_EXPERIMENT_LOGGING_CONFIG', '');
if (!(empty($providerName) || empty($providerConfig))) {
if (!Logger::hasProvider($providerName)) {
throw new Exception("Logging provider not supported. Logging is disabled");
}
$classname = '\\Utopia\\Logger\\Adapter\\' . \ucfirst($providerName);
$adapter = new $classname($providerConfig);
$logger = new Logger($adapter);
$publish = true;
}
}
if ($logger && $publish) {
try {
/** @var Utopia\Database\Document $user */
$user = $utopia->getResource('user');
} catch (\Throwable $th) {
} catch (\Throwable) {
// All good, user is optional information for logger
}
@@ -656,47 +923,6 @@ App::error()
Console::info('Log pushed with status code: ' . $responseCode);
}
$code = $error->getCode();
$message = $error->getMessage();
$file = $error->getFile();
$line = $error->getLine();
$trace = $error->getTrace();
if (php_sapi_name() === 'cli') {
Console::error('[Error] Timestamp: ' . date('c', time()));
if ($route) {
Console::error('[Error] Method: ' . $route->getMethod());
Console::error('[Error] URL: ' . $route->getPath());
}
Console::error('[Error] Type: ' . get_class($error));
Console::error('[Error] Message: ' . $message);
Console::error('[Error] File: ' . $file);
Console::error('[Error] Line: ' . $line);
}
/** Handle Utopia Errors */
if ($error instanceof Utopia\Exception) {
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
switch ($code) {
case 400:
$error->setType(AppwriteException::GENERAL_ARGUMENT_INVALID);
break;
case 404:
$error->setType(AppwriteException::GENERAL_ROUTE_NOT_FOUND);
break;
}
} elseif ($error instanceof Utopia\Database\Exception\Conflict) {
$error = new AppwriteException(AppwriteException::DOCUMENT_UPDATE_CONFLICT, previous: $error);
$code = $error->getCode();
$message = $error->getMessage();
} elseif ($error instanceof Utopia\Database\Exception\Timeout) {
$error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error);
$code = $error->getCode();
$message = $error->getMessage();
}
/** Wrap all exceptions inside Appwrite\Extend\Exception */
if (!($error instanceof AppwriteException)) {
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
@@ -756,10 +982,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());
}
+9 -4
View File
@@ -112,7 +112,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';
@@ -195,6 +195,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';
@@ -1033,7 +1034,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons
}
if (APP_MODE_ADMIN === $mode) {
if ($user->find('teamId', $project->getAttribute('teamId'), 'memberships')) {
if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) {
Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
} else {
$user = new Document([]);
@@ -1265,7 +1266,9 @@ function getDevice($root): 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);
$device = new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl);
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
return $device;
case Storage::DEVICE_BACKBLAZE:
return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl);
case Storage::DEVICE_LINODE:
@@ -1294,7 +1297,9 @@ function getDevice($root): Device
$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);
$device = new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl);
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
return $device;
case Storage::DEVICE_BACKBLAZE:
$backblazeAccessKey = App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', '');
$backblazeSecretKey = App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', '');
+91 -82
View File
@@ -36,74 +36,83 @@ require_once __DIR__ . '/init.php';
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
function getConsoleDB(): Database
{
global $register;
// Allows overriding
if (!function_exists("getConsoleDB")) {
function getConsoleDB(): Database
{
global $register;
/** @var \Utopia\Pools\Group $pools */
$pools = $register->get('pools');
/** @var \Utopia\Pools\Group $pools */
$pools = $register->get('pools');
$dbAdapter = $pools
->get('console')
->pop()
->getResource()
;
$database = new Database($dbAdapter, getCache());
$database
->setNamespace('_console')
->setMetadata('host', \gethostname())
->setMetadata('project', '_console');
return $database;
}
function getProjectDB(Document $project): Database
{
global $register;
/** @var \Utopia\Pools\Group $pools */
$pools = $register->get('pools');
if ($project->isEmpty() || $project->getId() === 'console') {
return getConsoleDB();
}
$dbAdapter = $pools
->get($project->getAttribute('database'))
->pop()
->getResource()
;
$database = new Database($dbAdapter, getCache());
$database
->setNamespace('_' . $project->getInternalId())
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId());
return $database;
}
function getCache(): Cache
{
global $register;
$pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */
$list = Config::getParam('pools-cache', []);
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
$dbAdapter = $pools
->get('console')
->pop()
->getResource()
;
}
return new Cache(new Sharding($adapters));
$database = new Database($dbAdapter, getCache());
$database
->setNamespace('_console')
->setMetadata('host', \gethostname())
->setMetadata('project', '_console');
return $database;
}
}
// Allows overriding
if (!function_exists("getProjectDB")) {
function getProjectDB(Document $project): Database
{
global $register;
/** @var \Utopia\Pools\Group $pools */
$pools = $register->get('pools');
if ($project->isEmpty() || $project->getId() === 'console') {
return getConsoleDB();
}
$dbAdapter = $pools
->get($project->getAttribute('database'))
->pop()
->getResource()
;
$database = new Database($dbAdapter, getCache());
$database
->setNamespace('_' . $project->getInternalId())
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId());
return $database;
}
}
// Allows overriding
if (!function_exists("getCache")) {
function getCache(): Cache
{
global $register;
$pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */
$list = Config::getParam('pools-cache', []);
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
}
return new Cache(new Sharding($adapters));
}
}
$realtime = new Realtime();
@@ -204,29 +213,29 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
/**
* Save current connections to the Database every 5 seconds.
*/
Timer::tick(5000, function () use ($register, $stats, &$statsDocument, $logError) {
$payload = [];
foreach ($stats as $projectId => $value) {
$payload[$projectId] = $stats->get($projectId, 'connectionsTotal');
}
if (empty($payload) || empty($statsDocument)) {
return;
}
// Timer::tick(5000, function () use ($register, $stats, &$statsDocument, $logError) {
// $payload = [];
// foreach ($stats as $projectId => $value) {
// $payload[$projectId] = $stats->get($projectId, 'connectionsTotal');
// }
// if (empty($payload) || empty($statsDocument)) {
// return;
// }
try {
$database = getConsoleDB();
// try {
// $database = getConsoleDB();
$statsDocument
->setAttribute('timestamp', DateTime::now())
->setAttribute('value', json_encode($payload));
// $statsDocument
// ->setAttribute('timestamp', DateTime::now())
// ->setAttribute('value', json_encode($payload));
Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument));
} catch (Throwable $th) {
call_user_func($logError, $th, "updateWorkerDocument");
} finally {
$register->get('pools')->reclaim();
}
});
// Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument));
// } catch (Throwable $th) {
// call_user_func($logError, $th, "updateWorkerDocument");
// } finally {
// $register->get('pools')->reclaim();
// }
// });
});
$server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $realtime, $logError) {
+4 -43
View File
@@ -59,7 +59,7 @@ $title = $this->getParam('title', '')
<link rel="stylesheet" href="/fonts/main.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-security-policy" content="">
<title><?php echo $this->print($title, self::FILTER_ESCAPE); ?></title>
<title><?php echo $this->print($title); ?></title>
<style>
@media(min-width:768px) {
@@ -74,11 +74,11 @@ $title = $this->getParam('title', '')
<div class="container u-margin-block-start-24">
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<h1 class="heading-level-4 u-trim-1">Error <?php echo $this->print($code, self::FILTER_ESCAPE); ?></h1>
<p class="text"><?php echo $this->print($message, self::FILTER_ESCAPE); ?></p>
<h1 class="heading-level-4 u-trim-1">Error <?php echo $this->print($code); ?></h1>
<p class="text"><?php echo $this->print($message); ?></p>
<div class="u-flex u-flex-vertical u-gap-8">
<p class="text">Type</p>
<p><code class="inline-code"><?php echo $this->print($type, self::FILTER_ESCAPE); ?></code></p>
<p><code class="inline-code"><?php echo $this->print($type); ?></code></p>
</div>
<?php if ($development) : ?>
<h2 class="heading-level-5 u-trim-1">Error Trace</h2>
@@ -111,45 +111,6 @@ $title = $this->getParam('title', '')
</div>
</article>
</div>
<!--section>
<h1>Error <?php echo $this->print($code, self::FILTER_ESCAPE); ?></h1>
<p><?php echo $this->print($message, self::FILTER_ESCAPE); ?></p>
<small>Error ID: <?php echo $this->print($errorID, self::FILTER_ESCAPE); ?></small>
<?php if (!empty($projectURL)) : ?>
<hr />
<p><a href="<?php echo $this->print($projectURL, self::FILTER_ESCAPE); ?>" rel="noopener">Back to <?php echo $this->print($projectName, self::FILTER_ESCAPE); ?></a></p>
<?php endif; ?>
<?php if ($development) : ?>
<div>
<h2>Error Trace</h2>
<?php foreach ($trace as $log) : ?>
<table>
<?php foreach ($log as $key => $value) : ?>
<tr>
<td style="width: 120px"><?php echo $this->print($key, self::FILTER_ESCAPE); ?></td>
<td>
<?php if (is_array($value)) : ?>
<?php echo $this->print(var_export($value, true), self::FILTER_ESCAPE); ?>
<?php else : ?>
<?php echo $this->print($value, self::FILTER_ESCAPE); ?>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section-->
<script type="text/javascript">
const app = (JSON.parse(localStorage.getItem('appwrite')) ?? {});
const theme = app.theme ?? 'auto';
+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
+11 -12
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;
@@ -146,6 +147,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']);
@@ -179,9 +183,6 @@ Server::setResource('queueForCertificates', function (Connection $queue) {
Server::setResource('queueForMigrations', function (Connection $queue) {
return new Migration($queue);
}, ['queue']);
Server::setResource('queueForHamster', function (Connection $queue) {
return new Hamster($queue);
}, ['queue']);
Server::setResource('logger', function (Registry $register) {
return $register->get('logger');
}, ['register']);
@@ -249,7 +250,6 @@ try {
Console::error($e->getMessage() . ', File: ' . $e->getFile() . ', Line: ' . $e->getLine());
}
$worker = $platform->getWorker();
$worker
@@ -264,7 +264,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 +281,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 +301,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
@@ -1,3 +0,0 @@
#!/bin/sh
php /usr/src/code/app/cli.php create-inf-metric $@
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
php /usr/src/code/app/cli.php patch-delete-project-collections $@
@@ -1,3 +0,0 @@
#!/bin/sh
php /usr/src/code/app/cli.php patch-delete-schedule-updated-at-attribute $@
@@ -1,3 +0,0 @@
#!/bin/sh
php /usr/src/code/app/cli.php patch-recreate-repositories-documents $@
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
php /usr/src/code/app/cli.php volume-sync $@
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
php /usr/src/code/app/worker.php usage-dump $@
+7 -5
View File
@@ -1,4 +1,5 @@
{
"name": "appwrite/server-ce",
"description": "End to end backend server for frontend and mobile apps.",
"type": "project",
@@ -49,18 +50,19 @@
"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.14",
"utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.1.*",
"utopia-php/framework": "0.33.*",
"utopia-php/image": "0.5.*",
"utopia-php/fetch": "0.2.*",
"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.*",
"utopia-php/pools": "0.4.*",
"utopia-php/pools": "0.5.*",
"utopia-php/preloader": "0.2.*",
"utopia-php/queue": "0.7.*",
"utopia-php/registry": "0.5.*",
Generated
+342 -225
View File
File diff suppressed because it is too large Load Diff
+55 -27
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:
@@ -53,7 +53,7 @@ services:
DEBUG: false
TESTING: true
VERSION: dev
ports:
ports:
- 9501:80
networks:
- appwrite
@@ -185,6 +185,8 @@ services:
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
- _APP_ASSISTANT_OPENAI_API_KEY
- _APP_EXPERIMENT_LOGGING_PROVIDER
- _APP_EXPERIMENT_LOGGING_CONFIG
appwrite-realtime:
entrypoint: realtime
@@ -645,6 +647,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 +680,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
@@ -717,7 +751,7 @@ services:
hostname: appwrite-executor
<<: *x-logging
stop_signal: SIGINT
image: openruntimes/executor:0.4.5
image: openruntimes/executor:0.5.1
restart: unless-stopped
networks:
- appwrite
@@ -800,7 +834,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:
@@ -846,15 +880,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
@@ -863,7 +898,7 @@ services:
container_name: appwrite-requestcatcher
<<: *x-logging
ports:
- '9504:5000'
- "9504:5000"
networks:
- appwrite
@@ -877,21 +912,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
@@ -904,7 +933,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

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