Compare commits

...
Author SHA1 Message Date
Jake Barnby 96b7f31abb Fix tests 2025-08-09 00:53:33 +12:00
Jake Barnby 10254c5e24 Update migrations 2025-08-08 23:45:31 +12:00
Christy JacobandGitHub f537f5f901 Merge pull request #10271 from appwrite/update-android-kotlin-sdks
chore: update SDK generator and sdks
2025-08-08 00:19:41 +04:00
Matej BačoandGitHub 7dd9ade894 Merge pull request #10267 from appwrite/feat-check-CAA-in-DNS
Feat: CAA validator
2025-08-06 12:09:25 +02:00
Matej Bačo aa837c7b43 PR review fixes 2025-08-06 11:43:07 +02:00
Matej Bačo 3541fcb237 Fix manual QA edge case 2025-08-06 11:30:56 +02:00
Matej Bačo 10a7f8acfe Formatting fix 2025-08-06 11:06:35 +02:00
Matej Bačo 61ec98bc5e Improve tests 2025-08-06 11:06:18 +02:00
Christy Jacob 217cd48249 chore: update SDK generator and sdks 2025-08-06 12:08:36 +04:00
Matej Bačo 2d4e99cb1a Revert revert of CAA validation 2025-08-05 13:44:06 +02:00
Matej Bačo 8fe999d6d7 Merge branch '1.7.x' into feat-check-CAA-in-DNS 2025-08-05 13:43:17 +02:00
Matej Bačo dade82706a Fix caa records inheritance 2025-08-05 13:38:56 +02:00
Jake BarnbyandGitHub 0109ca218e Merge pull request #10264 from appwrite/fix-dec-min-0
Fix atomic number ops with limit 0
2025-08-05 21:33:33 +12:00
Jake Barnby 43f0849979 Fix atomic num ops with limit 0 2025-08-05 20:38:26 +12:00
Matej BačoandGitHub b882a5d5b0 Merge pull request #10263 from appwrite/revert-10258-feat-check-CAA-in-DNS
Revert "Check CAA record before issuing certificate"
2025-08-05 10:30:19 +02:00
Matej BačoandGitHub 9c320f9c71 Revert "Check CAA record before issuing certificate" 2025-08-05 10:23:39 +02:00
Matej BačoandGitHub f8a75494b8 Merge pull request #10258 from appwrite/feat-check-CAA-in-DNS
Check CAA record before issuing certificate
2025-08-05 09:51:42 +02:00
Matej Bačo 7f690a1048 Simplify implementation 2025-08-04 16:51:49 +02:00
Matej Bačo 8c3530ee60 Fix caa validation breaking existing validations 2025-08-04 16:18:06 +02:00
Matej Bačo 5e294d0849 Support empty CAA records 2025-08-04 15:35:40 +02:00
Matej Bačo 2a63de0c46 Improve docs 2025-08-04 14:57:35 +02:00
Matej Bačo 48a977526e Fix tests 2025-08-04 14:53:13 +02:00
Matej Bačo 75bf37a074 Update composer.lock 2025-08-04 14:32:38 +02:00
Matej Bačo 689fbee10c Merge branch '1.7.x' into feat-check-CAA-in-DNS 2025-08-04 14:32:20 +02:00
Matej Bačo 4cafd2e07d Improve PR quality 2025-08-04 14:28:50 +02:00
Luke B. SilverandGitHub 24a9183d90 Merge pull request #10260 from appwrite/update-avatars-endpoint
fix: favicons endpoint to fallback to ico instead of throwing error
2025-08-04 13:18:09 +01:00
Chirag Aggarwal 84e3dc0275 fix: favicons endpoint to fallback to ico instead of throwing error 2025-08-04 17:14:38 +05:30
Luke B. SilverandGitHub d28e0152fd Merge pull request #10255 from appwrite/chore-support-svg-favicon
chore: add support for svg favicons
2025-08-04 10:42:38 +01:00
Chirag Aggarwal 7a507917c9 fix: minify 2025-08-04 14:41:57 +05:30
Chirag Aggarwal 048dbe81c7 chore: minify svg 2025-08-04 14:34:45 +05:30
Christy JacobandGitHub 19fe5881a4 Merge pull request #10249 from appwrite/feat-definition-examples 2025-08-04 09:04:33 +04:00
Chirag Aggarwal 55938fa3c3 update 1.7.x examples 2025-08-04 08:52:07 +05:30
Khushboo Verma 16685dad4e Update console tests 2025-08-04 01:49:08 +05:30
Khushboo Verma 783894a82b Add default value 2025-08-04 01:40:39 +05:30
Khushboo Verma 69dbb3222f Add check in proxy 2025-08-04 01:33:47 +05:30
Khushboo Verma d48aa60609 Update test 2025-08-04 01:22:10 +05:30
Khushboo Verma 9f8fabe58a Verify domain CAA after certificate issuance 2025-08-04 01:12:58 +05:30
Khushboo Verma 484ebb5059 Check CAA record in DNSTest 2025-08-04 00:42:00 +05:30
Chirag Aggarwal 10b82716e4 chore: update test 2025-08-03 22:31:26 +05:30
Chirag Aggarwal 4c971910bb chore: fix import 2025-08-03 22:08:25 +05:30
Chirag Aggarwal a00b93416d fix: cleansvg 2025-08-03 13:39:30 +05:30
Chirag Aggarwal 7c5dd9d0f4 add test 2025-08-03 13:38:59 +05:30
Chirag Aggarwal 4adebc8ba2 chore: add svg sanitization 2025-08-03 13:33:10 +05:30
Chirag Aggarwal f5682c0516 chore: add support for svg favicons 2025-08-03 13:23:34 +05:30
Chirag Aggarwal c235870112 chore: add placeholder version 2025-08-01 17:36:03 +05:30
Chirag Aggarwal 9929facd73 chore: update sdk gen 2025-08-01 16:44:27 +05:30
Luke B. SilverandGitHub 469ac59199 Merge pull request #10240 from appwrite/pla-3153
feat: telemetry for cache hits and misses
2025-08-01 11:42:39 +01:00
Chirag Aggarwal 58d556aab5 chore: update metric naming 2025-08-01 15:52:27 +05:30
Luke B. SilverandGitHub 596657ac26 Merge pull request #10248 from appwrite/pla-3271
fix: 500 errors on robots and humans txt files
2025-08-01 11:04:18 +01:00
Chirag Aggarwal b3ba91cd52 chore: update naming and specs 2025-08-01 15:26:34 +05:30
Chirag Aggarwal 3d5b755115 chore: simplify 2025-08-01 13:17:45 +05:30
Chirag Aggarwal 26be1b5caf feat: add model examples + additonal examples to specs 2025-08-01 13:09:39 +05:30
Jake BarnbyandGitHub 5d9be26a45 Merge pull request #10247 from appwrite/update-sdks-php-dotnet
chore: update changelog and sdk gen
2025-08-01 16:53:36 +12:00
Chirag Aggarwal 471d261114 chore: fallback to main domain 2025-08-01 09:28:07 +05:30
Chirag Aggarwal 59bebe6be9 fix: 500 errors on robots and humans txt files 2025-08-01 09:13:34 +05:30
Chirag Aggarwal 5689fd6e7e chore: update changelog and sdk gen 2025-08-01 09:09:11 +05:30
Harsh MahajanandGitHub 2d7ae4329b Merge branch '1.7.x' into pla-3153 2025-07-31 19:23:54 +05:30
Chirag Aggarwal 81e656e42c chore: update counter 2025-07-31 18:59:17 +05:30
Chirag Aggarwal 588087eda6 chore: add total 2025-07-31 17:17:15 +05:30
Chirag Aggarwal da1fa09e9c chore: update name 2025-07-31 17:06:29 +05:30
Jake BarnbyandGitHub 476ea76814 Merge pull request #10231 from appwrite/feat-csv-allow-internals
Feat CSV allow internals
2025-07-31 23:15:56 +12:00
Chirag Aggarwal d1c3a84ba1 chore: update to use gauge 2025-07-31 16:40:40 +05:30
Chirag Aggarwal 5c0579fbc7 feat: telemetry for cache hits and misses 2025-07-31 13:50:34 +05:30
Jake Barnby 1ea9aca90f Fix test 2025-07-31 02:10:29 +12:00
Jake Barnby efc21d3dcf Fix tests 2025-07-31 00:12:59 +12:00
Jake Barnby 152882d05d Fix ref 2025-07-30 23:59:30 +12:00
Jake Barnby a21e37b054 Add permissions support for CSV 2025-07-30 23:42:01 +12:00
Christy JacobandGitHub 1b1c28d319 Merge pull request #10233 from appwrite/remove-console-sdk
chore: move changelog to sdks platforms array
2025-07-30 12:44:21 +04:00
Chirag Aggarwal d2dcddaf13 chore: add console back 2025-07-30 13:52:37 +05:30
Chirag Aggarwal 5977e62e9a chore: move changelog path to platforms config 2025-07-30 13:32:56 +05:30
Chirag Aggarwal 7ffa11c75d chore: remove console sdk from platforms 2025-07-30 13:22:22 +05:30
Jake Barnby 5b12a6c8b1 Add internal attributes CSV test 2025-07-30 16:50:09 +12:00
Jake Barnby 01c8dab34d Fix CSV success test 2025-07-30 16:46:14 +12:00
Jake BarnbyandGitHub 811a1fa701 Merge pull request #10227 from appwrite/pla-3204
chore: filter certificates renewal task in maintenance by region
2025-07-30 16:24:24 +12:00
Jake BarnbyandGitHub d76db6ec62 Merge pull request #10228 from appwrite/feat-strip-seq
Remove sequence on incoming docs
2025-07-30 01:18:29 +12:00
Jake Barnby 933f07c175 Add missing removal 2025-07-30 01:18:08 +12:00
Jake Barnby ccf0a23bdf Remove sequence on incoming docs 2025-07-30 01:02:21 +12:00
Chirag Aggarwal 66786f20f0 chore: use md5 if enabled 2025-07-29 16:53:55 +05:30
Chirag Aggarwal 1731212ebb chore: improve check 2025-07-29 15:26:37 +05:30
Chirag Aggarwal 3db9cd06d5 chore: filter certificates renewal task in maintenance by region 2025-07-29 15:21:15 +05:30
Luke B. SilverandGitHub 3eb5cd80f3 Merge pull request #10224 from appwrite/pla-692
fix: create email target when using email otp registration
2025-07-29 10:27:43 +01:00
Chirag Aggarwal 7ad01fcada linebreak 2025-07-29 12:23:06 +05:30
Chirag Aggarwal 06e4920ee2 fix: create email target when using email otp registration 2025-07-29 11:57:57 +05:30
Jake BarnbyandGitHub f89e46817f Merge pull request #10221 from appwrite/fix-sequence-type
Filter sequence to int because any models skip rule checks
2025-07-29 17:56:18 +12:00
Jake BarnbyandGitHub 9b0a6bf33a Merge pull request #10222 from appwrite/update-migration
updated migration release
2025-07-29 17:12:36 +12:00
ArnabChatterjee20k b69ad22485 updated migration release 2025-07-29 10:25:31 +05:30
Jake Barnby 360e4ce992 Add test case 2025-07-29 16:54:39 +12:00
Jake Barnby 2529d64791 Filter sequence to int because any models skip rule checks 2025-07-29 16:53:13 +12:00
Luke B. SilverandGitHub 5924434e1d Merge pull request #10202 from appwrite/update-sdks-1.7.x
chore: update sdks 1.7.x
2025-07-27 14:28:18 +01:00
Luke B. SilverandGitHub 1d736dec54 Merge pull request #10204 from appwrite/add-docs-swift-apple
chore: add docs for nestedType, encode, from and toMap
2025-07-27 12:55:21 +01:00
Chirag Aggarwal 1f13a0d437 fix: gitignore 2025-07-27 10:19:14 +05:30
Chirag Aggarwal f2a3369131 chore: use config.json 2025-07-27 10:18:51 +05:30
Chirag Aggarwal 1f26f98568 chore: update go 2025-07-27 10:01:37 +05:30
Chirag AggarwalandGitHub 3c6291024b Merge branch 'update-sdks-1.7.x' into add-docs-swift-apple 2025-07-27 09:57:52 +05:30
Chirag AggarwalandGitHub b23f382dcc Merge branch '1.7.x' into update-sdks-1.7.x 2025-07-27 09:52:05 +05:30
Chirag Aggarwal 9be01f2ac9 add docs in rn 2025-07-26 11:24:19 +05:30
Chirag Aggarwal f39fe22e6f chore: add docs in web and node 2025-07-26 11:17:43 +05:30
Chirag Aggarwal cf3abd0f6c add java example 2025-07-26 11:10:24 +05:30
Chirag Aggarwal aa91189848 add docs for android as well 2025-07-25 17:08:43 +05:30
Matej BačoandGitHub 30d18f6f09 Merge pull request #10205 from hmacr/fix-mfa-email-preview
Change preview & body for MFA email
2025-07-25 12:54:00 +02:00
Chirag Aggarwal eeed9a08ec chore: add docs for nestedType, encode, from and toMap 2025-07-25 16:18:52 +05:30
hmacr 4940dcbf3a Change preview & body for MFA email 2025-07-25 16:08:11 +05:30
Chirag Aggarwal 6bd3e6fe96 update version for rn 2025-07-25 16:05:16 +05:30
Matej BačoandGitHub 91fda66d78 Merge pull request #10203 from appwrite/fix-templates
Fix: templates on `1.7.x`.
2025-07-25 11:14:26 +02:00
Darshan e67e6303b2 fix: templates on 1.7.x. 2025-07-25 14:30:03 +05:30
Luke B. SilverandGitHub 2f39e16b97 Merge pull request #10156 from appwrite/feat-stats-usage-on-redis
feat: stats-usage on redis
2025-07-24 22:42:09 +01:00
Matej BačoandGitHub d0b04cd61b Merge pull request #10190 from hmacr/1we24-auto-suggest-default-branch
Add defaultBranch in getRepository response
2025-07-24 17:25:51 +02:00
loks0n 1d86cc6010 feat: stats-usage on redis 2025-07-24 16:19:13 +01:00
Steven Nguyenandloks0n 8d1bc10cc6 docs: update CONTRIBUTING.md to clarify how to start 2025-07-24 16:19:13 +01:00
Khushboo VermaandGitHub 607cc9a926 Merge branch '1.7.x' into 1we24-auto-suggest-default-branch 2025-07-24 20:31:10 +05:30
Matej BačoandGitHub e4dc36edf0 Merge pull request #10198 from hmacr/1we17-preview-for-emails
Preview text for emails
2025-07-24 16:47:08 +02:00
Matej BačoandGitHub ce1ba58e73 Merge pull request #10201 from hmacr/1we6-better-error-msg-for-scheduled-date
Better error message for invalid function scheduled time
2025-07-24 16:40:14 +02:00
HemachandarandGitHub d7f85f9f58 remove dot 2025-07-24 20:06:49 +05:30
hmacr a8d5fc9998 format 2025-07-24 19:49:52 +05:30
Matej BačoandGitHub fc31787e9a Merge branch '1.7.x' into 1we6-better-error-msg-for-scheduled-date 2025-07-24 16:15:06 +02:00
hmacr 5ce141b75b change error msg 2025-07-24 19:43:14 +05:30
hmacr ee5a644771 tests 2025-07-24 19:39:23 +05:30
Khushboo VermaandGitHub d607f227a2 Merge branch '1.7.x' into 1we24-auto-suggest-default-branch 2025-07-24 19:38:17 +05:30
Matej BačoandGitHub 3439951538 Merge pull request #10199 from hmacr/1we21-handle-failed-git-action-in-worker
Suppress git-action exception in deployment worker
2025-07-24 14:50:57 +02:00
hmacr 9055d41aa0 send log to queue 2025-07-24 17:56:24 +05:30
Chirag Aggarwal 6c5cdfbe85 chore: update to use angle brackets 2025-07-24 17:11:21 +05:30
Matej BačoandGitHub b762e7fb73 Merge pull request #10181 from hmacr/1we9-use-preview-for-screenshots
fix: Use direct source for file-preview when empty
2025-07-24 13:39:24 +02:00
Matej BačoandGitHub f70a5e67be Merge pull request #10187 from hmacr/1we19-fix-double-deployment
Skip deployment when commit is created by us
2025-07-24 13:38:48 +02:00
Chirag Aggarwal e68acd3f02 chore: add more changelog 2025-07-24 16:47:24 +05:30
Chirag Aggarwal 2dfd2f4426 chore: add more changelog 2025-07-24 16:11:59 +05:30
Chirag Aggarwal 89b9afd066 update swift 2025-07-24 13:53:03 +05:30
Chirag Aggarwal 32bb8b7c7e chore: update sdks 1.7.x 2025-07-24 13:42:55 +05:30
hmacr ed4e85f28a validate only when scheduledAt is available 2025-07-24 11:56:05 +05:30
hmacr 7ae237e433 Better error message for invalid function scheduled time 2025-07-24 11:44:44 +05:30
Jake BarnbyandGitHub cc8e04f4fa Merge pull request #10197 from appwrite/fix-specs
fix: specs (1.7.x)
2025-07-24 17:10:55 +12:00
Chirag Aggarwal 3cbded226b fix: unwanted method being added to specs 2025-07-24 10:07:46 +05:30
hmacr 7ca03a5889 Suppress git-action exception in deployment worker 2025-07-23 22:26:35 +05:30
hmacr f75b53f3bc Merge branch '1.7.x' into 1we17-preview-for-emails 2025-07-23 22:05:23 +05:30
hmacr c5f8bdfd36 Preview texts for emails 2025-07-23 22:04:25 +05:30
Chirag Aggarwal 309f6ca1f7 chore: regen 2025-07-23 21:41:17 +05:30
Chirag Aggarwal 01cd296132 fix: compose 2025-07-23 21:30:28 +05:30
Chirag Aggarwal b3124f7288 uncomment 2025-07-23 21:16:55 +05:30
Chirag Aggarwal e8f53f27e3 regen sdks 2025-07-23 21:14:50 +05:30
Chirag Aggarwal 1340d14e7c chore: regen 2025-07-23 21:13:59 +05:30
Chirag Aggarwal 132b8f8234 chore: remove 2025-07-23 21:01:18 +05:30
Chirag Aggarwal 715ae4857b chore: remove 2025-07-23 21:00:12 +05:30
Chirag Aggarwal 69142048af chore: regen 2025-07-23 20:58:37 +05:30
Chirag Aggarwal 8fe62a2585 chore: regen 2025-07-23 20:57:31 +05:30
Chirag Aggarwal a53dcd8a23 chore: regen 2025-07-23 20:56:20 +05:30
hmacr f8d6706fde update composer 2025-07-23 20:45:46 +05:30
hmacr 8240c9ccdc add tests 2025-07-23 20:39:02 +05:30
Matej Bačo b194558226 Switch from gzip to none compression 2025-07-23 15:49:07 +02:00
hmacr c29ef4087b compress screenshots before uploading 2025-07-23 16:28:09 +05:30
hmacr f85a7410df Merge branch '1.7.x' into 1we9-use-preview-for-screenshots 2025-07-23 12:13:04 +05:30
hmacr c83dd7aa13 Add defaultBranch in getRepository response 2025-07-23 11:45:27 +05:30
hmacr 50eca9ebbc update commit author name param 2025-07-23 09:53:09 +05:30
hmacr 2a7ce13224 Merge branch '1.7.x' into 1we19-fix-double-deployment 2025-07-23 09:38:37 +05:30
hmacr 9c0e6f4203 Skip deployment when commit is created by us 2025-07-22 20:39:36 +05:30
hmacr bf3efea98d framework support + content for OTP & add-member email 2025-07-22 16:43:17 +05:30
Jake BarnbyandGitHub cd39bd6512 Merge pull request #10179 from appwrite/dat-579
Added the cases of null permissions in the upsert route and update th…
2025-07-22 20:22:56 +12:00
ArnabChatterjee20k 7bb760b4a1 added test for relation related upsert , fixed formatting 2025-07-22 13:10:05 +05:30
hmacr 9da57a457b fix: Use direct source for file-preview when empty 2025-07-21 22:31:06 +05:30
ArnabChatterjee20k 8b88a09374 added the cases of null permissions in the upsert route and update the e2e test 2025-07-21 19:32:27 +05:30
Jake BarnbyandGitHub c35a7cc09b Merge pull request #9897 from appwrite/1.7.x
1.7.x
2025-07-21 20:40:41 +12:00
Jake Barnby 891db255bc Fix tests 2025-07-21 19:59:38 +12:00
Jake Barnby f082cfacfa Fix tests 2025-07-21 19:43:33 +12:00
Jake Barnby d32da05f92 Merge remote-tracking branch 'origin/main' into 1.7.x
# Conflicts:
#	app/config/specs/open-api3-1.7.x-console.json
#	app/config/specs/open-api3-1.7.x-server.json
#	app/config/specs/open-api3-latest-console.json
#	app/config/specs/open-api3-latest-server.json
#	app/config/specs/swagger2-1.7.x-console.json
#	app/config/specs/swagger2-1.7.x-server.json
#	app/config/specs/swagger2-latest-console.json
#	app/config/specs/swagger2-latest-server.json
#	app/init/constants.php
#	composer.lock
#	docs/references/databases/upsert-documents.md
#	tests/e2e/Services/Account/AccountCustomClientTest.php
2025-07-21 19:22:15 +12:00
Matej BačoandGitHub 91f3c6e95e Merge pull request #10153 from Veera-mulge/change-desc
Update README.md
2025-07-16 14:11:20 +02:00
VeereshandGitHub 7b87decba4 Update README.md 2025-07-15 17:47:34 +05:30
Steven NguyenandGitHub a7e164e019 Merge pull request #10134 from Veera-mulge/main
Update README.md
2025-07-10 16:30:57 -07:00
VeereshandGitHub c6f6b6db90 Update README.md 2025-07-10 19:30:13 +05:30
Matej BačoandGitHub 5de2547cf6 Merge pull request #10112 from Veera-mulge/change-desc
Update README.md to add Upsert announcement
2025-07-08 16:56:51 +02:00
VeereshandGitHub b5035c7034 Update README.md 2025-07-07 11:03:40 +05:30
Matej BačoandGitHub 41a1bb928e Merge pull request #10095 from Veera-mulge/change-desc
Update README to add Bulk API link
2025-07-03 14:48:44 +02:00
VeereshandGitHub a8982bfb80 Update README.md 2025-07-03 14:44:39 +05:30
Eldad A. FuxandGitHub b119ecf92c Merge pull request #10084 from appwrite/LauraDuRy-patch-5
Update README.md
2025-07-01 15:50:14 +01:00
Laura Du RyandGitHub 925ac33536 Update README.md 2025-07-01 16:47:10 +02:00
Laura Du RyandGitHub eea09c56f8 Update README.md 2025-07-01 15:38:19 +02:00
Laura Du RyandGitHub 991c86c937 Update README.md 2025-07-01 14:26:25 +02:00
Eldad A. FuxandGitHub 9ab8097387 Merge pull request #10063 from appwrite/LauraDuRy-patch-4
Update README.md
2025-06-26 12:23:21 +01:00
Laura Du RyandGitHub 484d5ca4b4 Update README.md 2025-06-26 13:10:57 +02:00
Steven NguyenandGitHub e56c03a007 Merge pull request #10001 from appwrite/fix-golang-sdk-examples
Fix Golang SDK examples for docs
2025-06-19 15:11:29 -07:00
Eldad A. FuxandGitHub 179acec25c Merge pull request #10026 from appwrite/LauraDuRy-patch-3
Update README.md
2025-06-18 13:26:00 +01:00
Eldad A. FuxandGitHub 8379ea2469 Merge branch 'main' into LauraDuRy-patch-3 2025-06-18 13:25:52 +01:00
Eldad A. FuxandGitHub 2acb9c5b99 Merge pull request #9867 from appwrite/update-readme
Update Appwrite description to include Sites, add MCP to products list
2025-06-18 13:25:12 +01:00
Laura Du RyandGitHub 8b160d7dc0 Update README.md 2025-06-18 13:47:24 +02:00
Aditya Oberai d799891f53 Update Go SDK examples 2025-06-12 14:23:25 +00:00
Aditya Oberai fe86a446da Update sdk generator dependency 2025-06-12 14:13:23 +00:00
Damodar LohaniandGitHub 45e5509113 Merge pull request #9959 from appwrite/chore-add-warning
chore: update version to 1.7.4 and add experimental warnings
2025-06-04 10:59:56 +05:45
Chirag Aggarwal 4d66aeed5a fix: account tests 2025-06-03 08:52:43 +00:00
Chirag Aggarwal 848d38b75d chore: update version to 1.7.4 and add experimental feature warnings to document endpoints 2025-06-03 06:59:30 +00:00
Steven NguyenandGitHub 623369e426 Merge pull request #9600 from jmastr/fix-4982-expire-sessions-format-for-multiple-api
fix: expire format account recovery, verification, phone and mfa
2025-05-31 09:23:55 -07:00
Eldad A. FuxandGitHub fed881a611 Merge branch 'main' into update-readme 2025-05-23 20:02:55 +01:00
Ebenezer DonandGitHub ba4592609c Merge branch 'main' into update-readme 2025-05-23 11:41:33 +01:00
Ebenezer Don 1030053d5a Fix typo 2025-05-23 11:41:11 +01:00
Ebenezer Don 6b8aa1544b Improve formatting by adding line break between links 2025-05-23 11:39:16 +01:00
Ebenezer Don c82d0b5dc3 Rename duplicate getting Started section to Installation & Setup in README 2025-05-23 11:18:18 +01:00
Ebenezer Don f306e5e868 Update Chinese translation of README to include hosting/MCP 2025-05-22 22:23:23 +01:00
Ebenezer Don e27f1e1f6a Add Sites info to readme 2025-05-22 22:07:10 +01:00
Ebenezer Don e9c6ab491a Add info about Appwrite MCP to readme 2025-05-22 22:00:59 +01:00
Ebenezer Don 8c2235816e Update Appwrite description in readme 2025-05-22 22:00:28 +01:00
Julian Strobl 0da3602426 fix: expire format account recovery, verification, phone and mfa
closes: #4982

Signed-off-by: Julian Strobl <jmastr@mailbox.org>
2025-04-01 18:29:32 +02:00
520 changed files with 20564 additions and 175658 deletions
+2
View File
@@ -21,6 +21,7 @@ _APP_OPTIONS_ROUTER_PROTECTION=disabled
_APP_OPTIONS_FORCE_HTTPS=disabled
_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled
_APP_OPENSSL_KEY_V1=your-secret-key
_APP_DNS=8.8.8.8
_APP_DOMAIN=traefik
_APP_CONSOLE_DOMAIN=localhost
_APP_DOMAIN_FUNCTIONS=functions.localhost
@@ -28,6 +29,7 @@ _APP_DOMAIN_SITES=sites.localhost
_APP_DOMAIN_TARGET_CNAME=test.localhost
_APP_DOMAIN_TARGET_A=127.0.0.1
_APP_DOMAIN_TARGET_AAAA=::1
_APP_DOMAIN_TARGET_CAA=digicert.com
_APP_RULES_FORMAT=md5
_APP_REDIS_HOST=redis
_APP_REDIS_PORT=6379
+1 -1
View File
@@ -16,5 +16,5 @@ app/sdks
dev/yasd_init.php
.phpunit.result.cache
Makefile
appwrite.json
appwrite.config.json
/.zed/
+25 -1
View File
@@ -9,7 +9,31 @@ You can [find issues using this query](https://github.com/search?q=org%3Aappwrit
## How to Start?
If you are worried or dont know where to start, check out the next section that explains what kind of help we could use and where you can get involved. You can send your questions to [@appwrite on Twitter](https://twitter.com/appwrite) or to anyone from the [Appwrite team on Discord](https://appwrite.io/discord). You can also submit an issue, and a maintainer can guide you!
Welcome! We're excited that you're interested in contributing to Appwrite. To make sure your time is valued and your contributions are successful, please follow these steps before writing any code:
### 🔍 Step 1: Find an Issue
Browse open issues and look for ones labeled [good first issue](https://github.com/search?q=org%3Aappwrite+is%3Aopen+type%3Aissue+label%3A%22good+first+issue%22&type=issues) or [help wanted](https://github.com/search?q=org%3Aappwrite+is%3Aopen+type%3Aissue+label%3A%22help+wanted%22&type=issues).
If you're not sure which issue to pick, ask in our [maintainers channel](https://discord.com/channels/564160730845151244/636852860709240842) on Discord.
### 📝 Step 2: Ask to Be Assigned
Before working on an issue, comment on the GitHub issue asking to be assigned. This prevents multiple people working on the same task.
Then, create a thread in the [maintainers channel](https://discord.com/channels/564160730845151244/636852860709240842) on Discord with a link to the issue.
Our team is small and may not see your GitHub comment right away - posting in the [maintainers channel](https://discord.com/channels/564160730845151244/636852860709240842) ensures it gets seen.
### 💬 Step 3: Dont Submit Random PRs
If you're not working on an assigned issue, create a GitHub issue first.
PRs submitted without context or discussion may not align with our roadmap and may be closed without review.
### ⚠️ Please Note
Were a very small team managing a large project. Many PRs are submitted, and while we appreciate every effort, we can only review contributions that follow the process above. This helps us keep things fair and organized.
## Code of Conduct
+3 -1
View File
@@ -26,7 +26,7 @@
[**Appwrite 云公开测试版!立即注册!**](https://cloud.appwrite.io)
Appwrite 是一个基于 Docker 的端到端开发者平台,其容器化的微服务库可应用于网页端,移动端,以及后端。Appwrite 通过视觉化界面简化了从零开始编写 API 的繁琐过程,在保证软件安全的前提下为开发者创造了一个高效的开发环境
Appwrite 是一个基于 Docker 的端到端开发者平台,其容器化的微服务库可应用于网页端,移动端,原生应用,以及后端。它既包含后端服务器,也提供了用于部署静态和服务器端渲染前端的完全集成托管解决方案。Appwrite 通过视觉化界面简化了从零开始构建现代应用的复杂性和重复性,让您能够更快地构建安全的全栈应用
Appwrite 可以提供给开发者用户验证,外部授权,用户数据读写检索,文件储存,图像处理,云函数计算,[等多种服务](https://appwrite.io/docs).
@@ -179,6 +179,8 @@ docker run -it --rm `
- [**消息传递**](https://appwrite.io/docs/references/cloud/client-web/messaging) - 使用 Appwrite 消息传递功能通过推送通知、电子邮件和短信与用户进行通信。
- [**语言适配**](https://appwrite.io/docs/references/cloud/client-web/locale) - 根据用户所在的的国家和地区做出合适的语言适配。
- [**头像**](https://appwrite.io/docs/references/cloud/client-web/avatars) -管理用户头像、国家旗帜、浏览器图标、信用卡符号,和生成二维码。
- [**MCP**](https://appwrite.io/docs/tooling/mcp) - 使用 Appwrite 的模型上下文协议(Model Context Protocol)服务器,允许大语言模型(LLM)和 AI 工具(如 Claude Desktop、Cursor 和 Windsurf Editor)通过自然语言直接与您的 Appwrite 项目交互。
- [**站点**](https://appwrite.io/docs/products/sites) - 直接从 Appwrite 开发、部署和扩展您的 Web 应用程序,与您的后端一起。
如需完整的 API 界面文档,请访问 [https://appwrite.io/docs](https://appwrite.io/docs)。如需更多教程、新闻和公告,请订阅我们的 [博客](https://medium.com/appwrite-io) 和 加入我们的[Discord 社区](https://discord.gg/GSeTUeA)。
### 开发套件
+14 -9
View File
@@ -1,12 +1,14 @@
> We just announced Auto-increment support for Appwrite Databases - [Learn more](https://appwrite.io/blog/post/announcing-auto-increment-support)
> [Get started with Appwrite](https://apwr.dev/appcloud)
> [Join the Init kick off event 19th of May: The future of Appwrite with Founder & CEO Eldad Fux](https://www.youtube.com/watch?v=1g8tuogsp7A)
<br />
<p align="center">
<a href="https://appwrite.io" target="_blank"><img src="./public/images/banner.png" alt="Appwrite banner, with logo and text saying "Build Like a Team of Hundreds"></a>
<br />
<br />
<b>Appwrite is a backend platform for developing Web, Mobile, and Flutter applications. Built with the open source community and optimized for developer experience in the coding languages you love.</b>
<b>Appwrite is an all-in-one development platform for Web, Mobile, and Flutter applications. Use built-in backend infrastructure and web hosting, all from a single place. Built with the open source community and optimized for developer experience in the coding languages you love.</b>
<br />
<br />
</p>
@@ -25,7 +27,7 @@
English | [简体中文](README-CN.md)
Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker<nobr> microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.
Appwrite is an end-to-end platform for building Web, Mobile, Native, or Backend apps, packaged as a set of Docker microservices. It includes both a backend server and a fully integrated hosting solution for deploying static and server-side rendered frontends. Appwrite abstracts the complexity and repetitiveness required to build modern apps from scratch and allows you to build secure, full-stack applications faster.
Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and [more services](https://appwrite.io/docs).
@@ -42,7 +44,7 @@ Find out more at: [https://appwrite.io](https://appwrite.io).
Table of Contents:
- [Getting Started](#getting-started)
- [Installation \& Setup](#installation--setup)
- [Self-Hosting](#self-hosting)
- [Unix](#unix)
- [Windows](#windows)
@@ -62,8 +64,9 @@ Table of Contents:
- [Follow Us](#follow-us)
- [License](#license)
## Getting Started
The easiest way to get started with Appwrite is by [signing up for Appwrite Cloud](https://cloud.appwrite.io/). While Appwrite Cloud is in public beta, you can build with Appwrite completely free, and we won't collect you credit card information.
## Installation & Setup
The easiest way to get started with Appwrite is by [signing up for Appwrite Cloud](https://cloud.appwrite.io/). While Appwrite Cloud is in public beta, you can build with Appwrite completely free, and we won't collect your credit card information.
## Self-Hosting
@@ -128,19 +131,19 @@ Choose from one of the providers below:
<td align="center" width="100" height="100">
<a href="https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod">
<img width="50" height="39" src="public/images/integrations/gitpod-logo.svg" alt="Gitpod Logo" />
<br /><sub><b>Gitpod</b></sub></a>
<br /><sub><b>Gitpod</b></sub></a>
</a>
</td>
<td align="center" width="100" height="100">
<a href="https://www.linode.com/marketplace/apps/appwrite/appwrite/">
<img width="50" height="39" src="public/images/integrations/akamai-logo.svg" alt="Akamai Logo" />
<br /><sub><b>Akamai Compute</b></sub></a>
<br /><sub><b>Akamai Compute</b></sub></a>
</a>
</td>
<td align="center" width="100" height="100">
<a href="https://aws.amazon.com/marketplace/pp/prodview-2hiaeo2px4md6">
<img width="50" height="39" src="public/images/integrations/aws-logo.svg" alt="AWS Logo" />
<br /><sub><b>AWS Marketplace</b></sub></a>
<br /><sub><b>AWS Marketplace</b></sub></a>
</a>
</td>
</tr>
@@ -186,6 +189,8 @@ Getting started with Appwrite is as easy as creating a new project, choosing you
- [**Realtime**](https://appwrite.io/docs/realtime) - Listen to real-time events for any of your Appwrite services including users, storage, functions, databases, and more.
- [**Locale**](https://appwrite.io/docs/references/cloud/client-web/locale) - Track your user's location and manage your app locale-based data.
- [**Avatars**](https://appwrite.io/docs/references/cloud/client-web/avatars) - Manage your users' avatars, countries' flags, browser icons, and credit card symbols. Generate QR codes from links or plaintext strings.
- [**MCP**](https://appwrite.io/docs/tooling/mcp) - Use Appwrite's Model Context Protocol (MCP) server to allow LLMs and AI tools like Claude Desktop, Cursor, and Windsurf Editor to directly interact with your Appwrite project through natural language.
- [**Sites**](https://appwrite.io/docs/products/sites) - Develop, deploy, and scale your web applications directly from Appwrite, alongside your backend.
For the complete API documentation, visit [https://appwrite.io/docs](https://appwrite.io/docs). For more tutorials, news and announcements check out our [blog](https://medium.com/appwrite-io) and [Discord Server](https://discord.gg/GSeTUeA).
+9 -3
View File
@@ -191,9 +191,15 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
CLI::setResource('publisher', function (Group $pools) {
return new BrokerPool(publisher: $pools->get('publisher'));
}, ['pools']);
CLI::setResource('publisherRedis', function () {
// Stub
});
CLI::setResource('publisherDatabases', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
CLI::setResource('publisherMigrations', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
CLI::setResource('publisherStatsUsage', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
CLI::setResource('queueForStatsUsage', function (Publisher $publisher) {
return new StatsUsage($publisher);
}, ['publisher']);
@@ -120,6 +120,11 @@
</head>
<body>
<div style="display: none; overflow: hidden; max-height: 0; max-width: 0; opacity: 0; line-height: 1px;">
{{preview}}
<div>{{previewWhitespace}}</div>
</div>
<div class="main">
<table>
<tr>
@@ -121,6 +121,11 @@
<body style="direction: {{direction}}">
<div style="display: none; overflow: hidden; max-height: 0; max-width: 0; opacity: 0; line-height: 1px;">
{{preview}}
<div>{{previewWhitespace}}</div>
</div>
<div style="max-width:650px; word-wrap: break-word; overflow-wrap: break-word;
word-break: normal; margin:0 auto;">
<table style="margin-top: 32px">
@@ -9,4 +9,4 @@
<p>If you have trouble with the sender's image, ensure it is set in the <a href="https://gravatar.com/">Gravatar database</a>.</p>
<p style="margin-block-end: 0;">Best regards,</p>
<p style="margin-block-start: 0;">Appwrtite team</p>
<p style="margin-block-start: 0;">Appwrite team</p>
@@ -14,7 +14,7 @@
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; margin-top: 32px">
<tr>
<td style="border-radius: 8px; display: block; width: 100%;">
<a class="mobile-full-width" rel="noopener" target="_blank" href="{{host}}{{path}}" style="font-size: 14px; font-family: Inter; color: #ffffff; text-decoration: none; background-color: #FD366E; border-radius: 8px; padding: 9px 14px; border: 1px solid #FD366E; display: inline-block; text-align:center; box-sizing: border-box;">Webhook settings</a>
<a class="mobile-full-width" rel="noopener" target="_blank" href="{{host}}{{path}}" style="font-size: 14px; font-family: Inter; color: #ffffff; text-decoration: none; background-color: #2D2D31; border-radius: 8px; padding: 9px 14px; border: 1px solid #414146; display: inline-block; text-align:center; box-sizing: border-box;">Webhook settings</a>
</td>
</tr>
</table>
+9 -1
View File
@@ -4,6 +4,7 @@
"settings.direction": "ltr",
"emails.sender": "%s Team",
"emails.verification.subject": "Account Verification",
"emails.verification.preview": "Verify your email to activate your {{project}} account.",
"emails.verification.hello": "Hello {{user}},",
"emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.",
"emails.verification.footer": "If you didnt ask to verify this address, you can ignore this message.",
@@ -11,6 +12,7 @@
"emails.verification.buttonText": "Confirm email address",
"emails.verification.signature": "{{project}} team",
"emails.magicSession.subject": "{{project}} Login",
"emails.magicSession.preview": "Sign in to {{project}} with your secure link. Expires in 1 hour.",
"emails.magicSession.hello": "Hello {{user}},",
"emails.magicSession.optionButton": "Click the button below to securely sign in to your {{b}}{{project}}{{/b}} account. This link will expire in 1 hour.",
"emails.magicSession.buttonText": "Sign in to {{project}}",
@@ -20,6 +22,7 @@
"emails.magicSession.thanks": "Thanks,",
"emails.magicSession.signature": "{{project}} team",
"emails.sessionAlert.subject": "Security alert: new session on your {{project}} account",
"emails.sessionAlert.preview": "New login detected on {{project}} at {{time}} UTC.",
"emails.sessionAlert.hello": "Hello {{user}},",
"emails.sessionAlert.body": "A new session has been created on your {{b}}{{project}}{{/b}} account, {{b}}on {{date}}, {{year}} at {{time}} UTC{{/b}}.\nHere are the details of the new session: ",
"emails.sessionAlert.listDevice": "Device: {{b}}{{device}}{{/b}}",
@@ -29,6 +32,7 @@
"emails.sessionAlert.thanks": "Thanks,",
"emails.sessionAlert.signature": "{{project}} team",
"emails.otpSession.subject": "OTP for {{project}} Login",
"emails.otpSession.preview": "Use OTP {{otp}} to sign in to {{project}}. Expires in 15 minutes.",
"emails.otpSession.hello": "Hello {{user}},",
"emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.",
"emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.",
@@ -36,12 +40,14 @@
"emails.otpSession.thanks": "Thanks,",
"emails.otpSession.signature": "{{project}} team",
"emails.mfaChallenge.subject": "Verification Code for {{project}}",
"emails.mfaChallenge.preview": "Use code {{otp}} for two-step verification in {{project}}. Expires in 15 minutes.",
"emails.mfaChallenge.hello": "Hello {{user}},",
"emails.mfaChallenge.description": "Enter the following verification code to verify your email and activate two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.",
"emails.mfaChallenge.description": "Enter the following code to confirm your two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.",
"emails.mfaChallenge.clientInfo": "This verification code was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the verification code, you can safely ignore this email.",
"emails.mfaChallenge.thanks": "Thanks,",
"emails.mfaChallenge.signature": "{{project}} team",
"emails.recovery.subject": "Password Reset",
"emails.recovery.preview": "Reset your {{project}} password using the link.",
"emails.recovery.hello": "Hello {{user}},",
"emails.recovery.body": "Follow this link to reset your {{b}}{{project}}{{/b}} password.",
"emails.recovery.footer": "If you didn't ask to reset your password, you can ignore this message.",
@@ -49,6 +55,7 @@
"emails.recovery.buttonText": "Reset password",
"emails.recovery.signature": "{{project}} team",
"emails.invitation.subject": "Invitation to %s Team at %s",
"emails.invitation.preview": "{{owner}} invited you to join {{team}} at {{project}}",
"emails.invitation.hello": "Hello {{user}},",
"emails.invitation.body": "This mail was sent to you because {{b}}{{owner}}{{/b}} wanted to invite you to become a member of the {{b}}{{team}}{{/b}} team at {{b}}{{project}}{{/b}}.",
"emails.invitation.footer": "If you are not interested, you can ignore this message.",
@@ -56,6 +63,7 @@
"emails.invitation.buttonText": "Accept invite to {{team}}",
"emails.invitation.signature": "{{project}} team",
"emails.certificate.subject": "Certificate failure for %s",
"emails.certificate.preview": "Your domain %s certificate generation has failed.",
"emails.certificate.hello": "Hello,",
"emails.certificate.body": "Certificate for your domain '{{domain}}' could not be generated. This is attempt no. {{attempt}}, and the failure was caused by: {{error}}",
"emails.certificate.footer": "Your previous certificate will be valid for 30 days since the first failure. We highly recommend investigating this case, otherwise your domain will end up without a valid SSL communication.",
+43 -21
View File
@@ -11,7 +11,7 @@ return [
[
'key' => 'web',
'name' => 'Web',
'version' => '18.1.0',
'version' => '18.2.0',
'url' => 'https://github.com/appwrite/sdk-for-web',
'package' => 'https://www.npmjs.com/package/appwrite',
'enabled' => true,
@@ -25,6 +25,7 @@ return [
'gitRepoName' => 'sdk-for-web',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/web/CHANGELOG.md'),
'demos' => [
[
'icon' => 'react.svg',
@@ -59,7 +60,7 @@ return [
[
'key' => 'flutter',
'name' => 'Flutter',
'version' => '17.0.2',
'version' => '17.1.0',
'url' => 'https://github.com/appwrite/sdk-for-flutter',
'package' => 'https://pub.dev/packages/appwrite',
'enabled' => true,
@@ -73,11 +74,12 @@ return [
'gitRepoName' => 'sdk-for-flutter',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/flutter/CHANGELOG.md'),
],
[
'key' => 'apple',
'name' => 'Apple',
'version' => '10.1.1',
'version' => '10.2.0',
'url' => 'https://github.com/appwrite/sdk-for-apple',
'package' => 'https://github.com/appwrite/sdk-for-apple',
'enabled' => true,
@@ -91,6 +93,7 @@ return [
'gitRepoName' => 'sdk-for-apple',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/apple/CHANGELOG.md'),
],
[
'key' => 'objective-c',
@@ -108,11 +111,12 @@ return [
'gitRepoName' => 'sdk-for-objective-c',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/objective-c/CHANGELOG.md'),
],
[
'key' => 'android',
'name' => 'Android',
'version' => '8.1.0',
'version' => '8.2.2',
'url' => 'https://github.com/appwrite/sdk-for-android',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
'enabled' => true,
@@ -130,11 +134,12 @@ return [
'Kotlin' => 'kotlin',
'Java' => 'java',
],
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/android/CHANGELOG.md'),
],
[
'key' => 'react-native',
'name' => 'React Native',
'version' => '0.10.1',
'version' => '0.11.0',
'url' => 'https://github.com/appwrite/sdk-for-react-native',
'package' => 'https://npmjs.com/package/react-native-appwrite',
'enabled' => true,
@@ -148,6 +153,7 @@ return [
'gitRepoName' => 'sdk-for-react-native',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/react-native/CHANGELOG.md'),
],
[
'key' => 'graphql',
@@ -167,6 +173,7 @@ return [
'gitUserName' => '',
'gitBranch' => '',
'isSDK' => false,
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/graphql/CHANGELOG.md'),
],
[
'key' => 'rest',
@@ -186,6 +193,7 @@ return [
'gitUserName' => '',
'gitBranch' => '',
'isSDK' => false,
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/rest/CHANGELOG.md'),
],
],
],
@@ -199,8 +207,8 @@ return [
[
'key' => 'web',
'name' => 'Console',
'version' => '1.7.0',
'url' => 'https://github.com/appwrite/sdk-for-console',
'version' => '0.1.0',
'url' => '',
'package' => '',
'enabled' => true,
'beta' => false,
@@ -209,15 +217,16 @@ return [
'family' => APP_PLATFORM_CONSOLE,
'prism' => 'javascript',
'source' => \realpath(__DIR__ . '/../sdks/console-web'),
'gitUrl' => 'git@github.com:appwrite/sdk-for-console.git',
'gitUrl' => '',
'gitBranch' => 'dev',
'gitRepoName' => 'sdk-for-console',
'gitUserName' => 'appwrite',
'gitRepoName' => '',
'gitUserName' => '',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/console/CHANGELOG.md'),
],
[
'key' => 'cli',
'name' => 'Command Line',
'version' => '8.2.2',
'version' => '8.3.0',
'url' => 'https://github.com/appwrite/sdk-for-cli',
'package' => 'https://www.npmjs.com/package/appwrite-cli',
'enabled' => true,
@@ -232,6 +241,7 @@ return [
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'repoBranch' => 'master',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/cli/CHANGELOG.md'),
'exclude' => [
'services' => [
['name' => 'assistant'],
@@ -251,7 +261,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '17.1.0',
'version' => '17.2.0',
'url' => 'https://github.com/appwrite/sdk-for-node',
'package' => 'https://www.npmjs.com/package/node-appwrite',
'enabled' => true,
@@ -265,11 +275,12 @@ return [
'gitRepoName' => 'sdk-for-node',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/nodejs/CHANGELOG.md'),
],
[
'key' => 'deno',
'name' => 'Deno',
'version' => '15.0.0',
'version' => '15.1.0',
'url' => 'https://github.com/appwrite/sdk-for-deno',
'package' => 'https://deno.land/x/appwrite',
'enabled' => true,
@@ -283,11 +294,12 @@ return [
'gitRepoName' => 'sdk-for-deno',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/deno/CHANGELOG.md'),
],
[
'key' => 'php',
'name' => 'PHP',
'version' => '15.0.0',
'version' => '15.1.0',
'url' => 'https://github.com/appwrite/sdk-for-php',
'package' => 'https://packagist.org/packages/appwrite/appwrite',
'enabled' => true,
@@ -301,11 +313,12 @@ return [
'gitRepoName' => 'sdk-for-php',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/php/CHANGELOG.md'),
],
[
'key' => 'python',
'name' => 'Python',
'version' => '11.0.0',
'version' => '11.1.0',
'url' => 'https://github.com/appwrite/sdk-for-python',
'package' => 'https://pypi.org/project/appwrite/',
'enabled' => true,
@@ -319,11 +332,12 @@ return [
'gitRepoName' => 'sdk-for-python',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/python/CHANGELOG.md'),
],
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '16.0.0',
'version' => '16.1.0',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'package' => 'https://rubygems.org/gems/appwrite',
'enabled' => true,
@@ -337,11 +351,12 @@ return [
'gitRepoName' => 'sdk-for-ruby',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/ruby/CHANGELOG.md'),
],
[
'key' => 'go',
'name' => 'Go',
'version' => '0.8.0',
'version' => '0.9.0',
'url' => 'https://github.com/appwrite/sdk-for-go',
'package' => 'https://github.com/appwrite/sdk-for-go',
'enabled' => true,
@@ -355,11 +370,12 @@ return [
'gitRepoName' => 'sdk-for-go',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/go/CHANGELOG.md'),
],
[
'key' => 'dotnet',
'name' => '.NET',
'version' => '0.14.0',
'version' => '0.15.0',
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
'package' => 'https://www.nuget.org/packages/Appwrite',
'enabled' => true,
@@ -373,11 +389,12 @@ return [
'gitRepoName' => 'sdk-for-dotnet',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/dotnet/CHANGELOG.md'),
],
[
'key' => 'dart',
'name' => 'Dart',
'version' => '16.1.0',
'version' => '16.2.0',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'package' => 'https://pub.dev/packages/dart_appwrite',
'enabled' => true,
@@ -391,11 +408,12 @@ return [
'gitRepoName' => 'sdk-for-dart',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/dart/CHANGELOG.md'),
],
[
'key' => 'kotlin',
'name' => 'Kotlin',
'version' => '9.0.0',
'version' => '9.1.2',
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
'enabled' => true,
@@ -413,11 +431,12 @@ return [
'Kotlin' => 'kotlin',
'Java' => 'java',
],
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/kotlin/CHANGELOG.md'),
],
[
'key' => 'swift',
'name' => 'Swift',
'version' => '10.1.0',
'version' => '10.2.0',
'url' => 'https://github.com/appwrite/sdk-for-swift',
'package' => 'https://github.com/appwrite/sdk-for-swift',
'enabled' => true,
@@ -431,6 +450,7 @@ return [
'gitRepoName' => 'sdk-for-swift',
'gitUserName' => 'appwrite',
'gitBranch' => 'dev',
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/swift/CHANGELOG.md'),
],
[
'key' => 'graphql',
@@ -450,6 +470,7 @@ return [
'gitUserName' => '',
'gitBranch' => '',
'isSDK' => false,
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/graphql/CHANGELOG.md'),
],
[
'key' => 'rest',
@@ -469,6 +490,7 @@ return [
'gitUserName' => '',
'gitBranch' => '',
'isSDK' => false,
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/rest/CHANGELOG.md'),
],
],
],
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+447 -61
View File
@@ -4467,10 +4467,7 @@
{
"name": "createDocument",
"auth": {
"Admin": [],
"Session": [],
"Key": [],
"JWT": []
"Project": []
},
"parameters": [
"databaseId",
@@ -5206,7 +5203,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 394,
"weight": 393,
"cookies": false,
"type": "",
"deprecated": false,
@@ -5281,7 +5278,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 392,
"weight": 391,
"cookies": false,
"type": "",
"deprecated": false,
@@ -5364,7 +5361,7 @@
"scheduledAt": {
"type": "string",
"description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.",
"x-example": null
"x-example": "<SCHEDULED_AT>"
}
}
}
@@ -5396,7 +5393,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 393,
"weight": 392,
"cookies": false,
"type": "",
"deprecated": false,
@@ -5470,7 +5467,7 @@
"x-appwrite": {
"method": "query",
"group": "graphql",
"weight": 308,
"weight": 307,
"cookies": false,
"type": "graphql",
"deprecated": false,
@@ -5522,7 +5519,7 @@
"x-appwrite": {
"method": "mutation",
"group": "graphql",
"weight": 307,
"weight": 306,
"cookies": false,
"type": "graphql",
"deprecated": false,
@@ -5990,7 +5987,7 @@
"x-appwrite": {
"method": "createSubscriber",
"group": "subscribers",
"weight": 354,
"weight": 353,
"cookies": false,
"type": "",
"deprecated": false,
@@ -6073,7 +6070,7 @@
"x-appwrite": {
"method": "deleteSubscriber",
"group": "subscribers",
"weight": 358,
"weight": 357,
"cookies": false,
"type": "",
"deprecated": false,
@@ -8036,7 +8033,8 @@
"any": {
"description": "Any",
"type": "object",
"additionalProperties": true
"additionalProperties": true,
"example": []
},
"error": {
"description": "Error",
@@ -8068,7 +8066,13 @@
"code",
"type",
"version"
]
],
"example": {
"message": "Not found",
"code": "404",
"type": "not_found",
"version": "1.0"
}
},
"documentList": {
"description": "Documents List",
@@ -8092,7 +8096,11 @@
"required": [
"total",
"documents"
]
],
"example": {
"total": 5,
"documents": ""
}
},
"sessionList": {
"description": "Sessions List",
@@ -8116,7 +8124,11 @@
"required": [
"total",
"sessions"
]
],
"example": {
"total": 5,
"sessions": ""
}
},
"identityList": {
"description": "Identities List",
@@ -8140,7 +8152,11 @@
"required": [
"total",
"identities"
]
],
"example": {
"total": 5,
"identities": ""
}
},
"logList": {
"description": "Logs List",
@@ -8164,7 +8180,11 @@
"required": [
"total",
"logs"
]
],
"example": {
"total": 5,
"logs": ""
}
},
"fileList": {
"description": "Files List",
@@ -8188,7 +8208,11 @@
"required": [
"total",
"files"
]
],
"example": {
"total": 5,
"files": ""
}
},
"teamList": {
"description": "Teams List",
@@ -8212,7 +8236,11 @@
"required": [
"total",
"teams"
]
],
"example": {
"total": 5,
"teams": ""
}
},
"membershipList": {
"description": "Memberships List",
@@ -8236,7 +8264,11 @@
"required": [
"total",
"memberships"
]
],
"example": {
"total": 5,
"memberships": ""
}
},
"executionList": {
"description": "Executions List",
@@ -8260,7 +8292,11 @@
"required": [
"total",
"executions"
]
],
"example": {
"total": 5,
"executions": ""
}
},
"countryList": {
"description": "Countries List",
@@ -8284,7 +8320,11 @@
"required": [
"total",
"countries"
]
],
"example": {
"total": 5,
"countries": ""
}
},
"continentList": {
"description": "Continents List",
@@ -8308,7 +8348,11 @@
"required": [
"total",
"continents"
]
],
"example": {
"total": 5,
"continents": ""
}
},
"languageList": {
"description": "Languages List",
@@ -8332,7 +8376,11 @@
"required": [
"total",
"languages"
]
],
"example": {
"total": 5,
"languages": ""
}
},
"currencyList": {
"description": "Currencies List",
@@ -8356,7 +8404,11 @@
"required": [
"total",
"currencies"
]
],
"example": {
"total": 5,
"currencies": ""
}
},
"phoneList": {
"description": "Phones List",
@@ -8380,7 +8432,11 @@
"required": [
"total",
"phones"
]
],
"example": {
"total": 5,
"phones": ""
}
},
"localeCodeList": {
"description": "Locale codes list",
@@ -8404,7 +8460,11 @@
"required": [
"total",
"localeCodes"
]
],
"example": {
"total": 5,
"localeCodes": ""
}
},
"document": {
"description": "Document",
@@ -8461,7 +8521,23 @@
"$createdAt",
"$updatedAt",
"$permissions"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$sequence": 1,
"$collectionId": "5e5ea5c15117e",
"$databaseId": "5e5ea5c15117e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"$permissions": [
"read(\"any\")"
],
"username": "john.doe",
"email": "john.doe@example.com",
"fullName": "John Doe",
"age": 30,
"isAdmin": false
}
},
"log": {
"description": "Log",
@@ -8595,7 +8671,30 @@
"deviceModel",
"countryCode",
"countryName"
]
],
"example": {
"event": "account.sessions.create",
"userId": "610fc2f985ee0",
"userEmail": "john@appwrite.io",
"userName": "John Doe",
"mode": "admin",
"ip": "127.0.0.1",
"time": "2020-10-15T06:38:00.000+00:00",
"osCode": "Mac",
"osName": "Mac",
"osVersion": "Mac",
"clientType": "browser",
"clientCode": "CM",
"clientName": "Chrome Mobile iOS",
"clientVersion": "84.0",
"clientEngine": "WebKit",
"clientEngineVersion": "605.1.15",
"deviceName": "smartphone",
"deviceBrand": "Google",
"deviceModel": "Nexus 5",
"countryCode": "US",
"countryName": "United States"
}
},
"user": {
"description": "User",
@@ -8756,7 +8855,33 @@
"prefs",
"targets",
"accessedAt"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"name": "John Doe",
"password": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE",
"hash": "argon2",
"hashOptions": {},
"registration": "2020-10-15T06:38:00.000+00:00",
"status": true,
"labels": [
"vip"
],
"passwordUpdate": "2020-10-15T06:38:00.000+00:00",
"email": "john@appwrite.io",
"phone": "+4930901820",
"emailVerification": true,
"phoneVerification": true,
"mfa": true,
"prefs": {
"theme": "pink",
"timezone": "UTC"
},
"targets": [],
"accessedAt": "2020-10-15T06:38:00.000+00:00"
}
},
"algoMd5": {
"description": "AlgoMD5",
@@ -8770,7 +8895,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "md5"
}
},
"algoSha": {
"description": "AlgoSHA",
@@ -8784,7 +8912,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "sha"
}
},
"algoPhpass": {
"description": "AlgoPHPass",
@@ -8798,7 +8929,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "phpass"
}
},
"algoBcrypt": {
"description": "AlgoBcrypt",
@@ -8812,7 +8946,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "bcrypt"
}
},
"algoScrypt": {
"description": "AlgoScrypt",
@@ -8854,7 +8991,14 @@
"costMemory",
"costParallel",
"length"
]
],
"example": {
"type": "scrypt",
"costCpu": 8,
"costMemory": 14,
"costParallel": 1,
"length": 64
}
},
"algoScryptModified": {
"description": "AlgoScryptModified",
@@ -8886,7 +9030,13 @@
"salt",
"saltSeparator",
"signerKey"
]
],
"example": {
"type": "scryptMod",
"salt": "UxLMreBr6tYyjQ==",
"saltSeparator": "Bw==",
"signerKey": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ=="
}
},
"algoArgon2": {
"description": "AlgoArgon2",
@@ -8921,12 +9071,23 @@
"memoryCost",
"timeCost",
"threads"
]
],
"example": {
"type": "argon2",
"memoryCost": 65536,
"timeCost": 4,
"threads": 3
}
},
"preferences": {
"description": "Preferences",
"type": "object",
"additionalProperties": true
"additionalProperties": true,
"example": {
"language": "en",
"timezone": "UTC",
"darkTheme": true
}
},
"session": {
"description": "Session",
@@ -9113,7 +9274,40 @@
"factors",
"secret",
"mfaUpdatedAt"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5bb8c16897e",
"expire": "2020-10-15T06:38:00.000+00:00",
"provider": "email",
"providerUid": "user@example.com",
"providerAccessToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"providerAccessTokenExpiry": "2020-10-15T06:38:00.000+00:00",
"providerRefreshToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"ip": "127.0.0.1",
"osCode": "Mac",
"osName": "Mac",
"osVersion": "Mac",
"clientType": "browser",
"clientCode": "CM",
"clientName": "Chrome Mobile iOS",
"clientVersion": "84.0",
"clientEngine": "WebKit",
"clientEngineVersion": "605.1.15",
"deviceName": "smartphone",
"deviceBrand": "Google",
"deviceModel": "Nexus 5",
"countryCode": "US",
"countryName": "United States",
"current": true,
"factors": [
"email"
],
"secret": "5e5bb8c16897e",
"mfaUpdatedAt": "2020-10-15T06:38:00.000+00:00"
}
},
"identity": {
"description": "Identity",
@@ -9181,7 +9375,19 @@
"providerAccessToken",
"providerAccessTokenExpiry",
"providerRefreshToken"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5bb8c16897e",
"provider": "email",
"providerUid": "5e5bb8c16897e",
"providerEmail": "user@example.com",
"providerAccessToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"providerAccessTokenExpiry": "2020-10-15T06:38:00.000+00:00",
"providerRefreshToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3"
}
},
"token": {
"description": "Token",
@@ -9225,7 +9431,15 @@
"secret",
"expire",
"phrase"
]
],
"example": {
"$id": "bb8ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5ea5c168bb8",
"secret": "",
"expire": "2020-10-15T06:38:00.000+00:00",
"phrase": "Golden Fox"
}
},
"jwt": {
"description": "JWT",
@@ -9239,7 +9453,10 @@
},
"required": [
"jwt"
]
],
"example": {
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
},
"locale": {
"description": "Locale",
@@ -9289,7 +9506,16 @@
"continent",
"eu",
"currency"
]
],
"example": {
"ip": "127.0.0.1",
"countryCode": "US",
"country": "United States",
"continentCode": "NA",
"continent": "North America",
"eu": false,
"currency": "USD"
}
},
"localeCode": {
"description": "LocaleCode",
@@ -9309,7 +9535,11 @@
"required": [
"code",
"name"
]
],
"example": {
"code": "en-us",
"name": "US"
}
},
"file": {
"description": "File",
@@ -9391,7 +9621,22 @@
"sizeOriginal",
"chunksTotal",
"chunksUploaded"
]
],
"example": {
"$id": "5e5ea5c16897e",
"bucketId": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"$permissions": [
"read(\"any\")"
],
"name": "Pink.png",
"signature": "5d529fd02b544198ae075bd57c1762bb",
"mimeType": "image\/png",
"sizeOriginal": 17890,
"chunksTotal": 17890,
"chunksUploaded": 17890
}
},
"team": {
"description": "Team",
@@ -9442,7 +9687,18 @@
"name",
"total",
"prefs"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"name": "VIP",
"total": 7,
"prefs": {
"theme": "pink",
"timezone": "UTC"
}
}
},
"membership": {
"description": "Membership",
@@ -9533,7 +9789,24 @@
"confirm",
"mfa",
"roles"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5ea5c16897e",
"userName": "John Doe",
"userEmail": "john@appwrite.io",
"teamId": "5e5ea5c16897e",
"teamName": "VIP",
"invited": "2020-10-15T06:38:00.000+00:00",
"joined": "2020-10-15T06:38:00.000+00:00",
"confirm": false,
"mfa": false,
"roles": [
"owner"
]
}
},
"execution": {
"description": "Execution",
@@ -9664,7 +9937,36 @@
"logs",
"errors",
"duration"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"$permissions": [
"any"
],
"functionId": "5e5ea6g16897e",
"trigger": "http",
"status": "processing",
"requestMethod": "GET",
"requestPath": "\/articles?id=5",
"requestHeaders": [
{
"Content-Type": "application\/json"
}
],
"responseStatusCode": 200,
"responseBody": "",
"responseHeaders": [
{
"Content-Type": "application\/json"
}
],
"logs": "",
"errors": "",
"duration": 0.4,
"scheduledAt": "2020-10-15T06:38:00.000+00:00"
}
},
"country": {
"description": "Country",
@@ -9684,7 +9986,11 @@
"required": [
"name",
"code"
]
],
"example": {
"name": "United States",
"code": "US"
}
},
"continent": {
"description": "Continent",
@@ -9704,7 +10010,11 @@
"required": [
"name",
"code"
]
],
"example": {
"name": "Europe",
"code": "EU"
}
},
"language": {
"description": "Language",
@@ -9730,7 +10040,12 @@
"name",
"code",
"nativeName"
]
],
"example": {
"name": "Italian",
"code": "it",
"nativeName": "Italiano"
}
},
"currency": {
"description": "Currency",
@@ -9782,7 +10097,16 @@
"rounding",
"code",
"namePlural"
]
],
"example": {
"symbol": "$",
"name": "US dollar",
"symbolNative": "$",
"decimalDigits": 2,
"rounding": 0,
"code": "USD",
"namePlural": "US dollars"
}
},
"phone": {
"description": "Phone",
@@ -9808,7 +10132,12 @@
"code",
"countryCode",
"countryName"
]
],
"example": {
"code": "+1",
"countryCode": "US",
"countryName": "United States"
}
},
"headers": {
"description": "Headers",
@@ -9828,7 +10157,11 @@
"required": [
"name",
"value"
]
],
"example": {
"name": "Content-Type",
"value": "application\/json"
}
},
"mfaChallenge": {
"description": "MFA Challenge",
@@ -9860,7 +10193,13 @@
"$createdAt",
"userId",
"expire"
]
],
"example": {
"$id": "bb8ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5ea5c168bb8",
"expire": "2020-10-15T06:38:00.000+00:00"
}
},
"mfaRecoveryCodes": {
"description": "MFA Recovery Codes",
@@ -9880,7 +10219,13 @@
},
"required": [
"recoveryCodes"
]
],
"example": {
"recoveryCodes": [
"a3kf0-s0cl2",
"s0co1-as98s"
]
}
},
"mfaType": {
"description": "MFAType",
@@ -9900,7 +10245,11 @@
"required": [
"secret",
"uri"
]
],
"example": {
"secret": true,
"uri": true
}
},
"mfaFactors": {
"description": "MFAFactors",
@@ -9932,7 +10281,13 @@
"phone",
"email",
"recoveryCode"
]
],
"example": {
"totp": true,
"phone": true,
"email": true,
"recoveryCode": true
}
},
"subscriber": {
"description": "Subscriber",
@@ -10006,7 +10361,27 @@
"userName",
"topicId",
"providerType"
]
],
"example": {
"$id": "259125845563242502",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"targetId": "259125845563242502",
"target": {
"$id": "259125845563242502",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"providerType": "email",
"providerId": "259125845563242502",
"name": "ageon-app-email",
"identifier": "random-mail@email.org",
"userId": "5e5ea5c16897e"
},
"userId": "5e5ea5c16897e",
"userName": "Aegon Targaryen",
"topicId": "259125845563242502",
"providerType": "email"
}
},
"target": {
"description": "Target",
@@ -10068,7 +10443,18 @@
"providerType",
"identifier",
"expired"
]
],
"example": {
"$id": "259125845563242502",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"name": "Apple iPhone 12",
"userId": "259125845563242502",
"providerId": "259125845563242502",
"providerType": "email",
"identifier": "token",
"expired": false
}
}
},
"securitySchemes": {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+442 -64
View File
@@ -4604,10 +4604,7 @@
{
"name": "createDocument",
"auth": {
"Admin": [],
"Session": [],
"Key": [],
"JWT": []
"Project": []
},
"parameters": [
"databaseId",
@@ -5105,8 +5102,7 @@
"platforms": [
"console",
"server",
"client",
"server"
"client"
],
"packaging": false,
"auth": {
@@ -5214,8 +5210,7 @@
"platforms": [
"console",
"server",
"client",
"server"
"client"
],
"packaging": false,
"auth": {
@@ -5308,7 +5303,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 394,
"weight": 393,
"cookies": false,
"type": "",
"deprecated": false,
@@ -5381,7 +5376,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 392,
"weight": 391,
"cookies": false,
"type": "",
"deprecated": false,
@@ -5466,7 +5461,7 @@
"type": "string",
"description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.",
"default": null,
"x-example": null
"x-example": "<SCHEDULED_AT>"
}
}
}
@@ -5497,7 +5492,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 393,
"weight": 392,
"cookies": false,
"type": "",
"deprecated": false,
@@ -5568,7 +5563,7 @@
"x-appwrite": {
"method": "query",
"group": "graphql",
"weight": 308,
"weight": 307,
"cookies": false,
"type": "graphql",
"deprecated": false,
@@ -5641,7 +5636,7 @@
"x-appwrite": {
"method": "mutation",
"group": "graphql",
"weight": 307,
"weight": 306,
"cookies": false,
"type": "graphql",
"deprecated": false,
@@ -6122,7 +6117,7 @@
"x-appwrite": {
"method": "createSubscriber",
"group": "subscribers",
"weight": 354,
"weight": 353,
"cookies": false,
"type": "",
"deprecated": false,
@@ -6206,7 +6201,7 @@
"x-appwrite": {
"method": "deleteSubscriber",
"group": "subscribers",
"weight": 358,
"weight": 357,
"cookies": false,
"type": "",
"deprecated": false,
@@ -8099,7 +8094,8 @@
"any": {
"description": "Any",
"type": "object",
"additionalProperties": true
"additionalProperties": true,
"example": []
},
"documentList": {
"description": "Documents List",
@@ -8124,7 +8120,11 @@
"required": [
"total",
"documents"
]
],
"example": {
"total": 5,
"documents": ""
}
},
"sessionList": {
"description": "Sessions List",
@@ -8149,7 +8149,11 @@
"required": [
"total",
"sessions"
]
],
"example": {
"total": 5,
"sessions": ""
}
},
"identityList": {
"description": "Identities List",
@@ -8174,7 +8178,11 @@
"required": [
"total",
"identities"
]
],
"example": {
"total": 5,
"identities": ""
}
},
"logList": {
"description": "Logs List",
@@ -8199,7 +8207,11 @@
"required": [
"total",
"logs"
]
],
"example": {
"total": 5,
"logs": ""
}
},
"fileList": {
"description": "Files List",
@@ -8224,7 +8236,11 @@
"required": [
"total",
"files"
]
],
"example": {
"total": 5,
"files": ""
}
},
"teamList": {
"description": "Teams List",
@@ -8249,7 +8265,11 @@
"required": [
"total",
"teams"
]
],
"example": {
"total": 5,
"teams": ""
}
},
"membershipList": {
"description": "Memberships List",
@@ -8274,7 +8294,11 @@
"required": [
"total",
"memberships"
]
],
"example": {
"total": 5,
"memberships": ""
}
},
"executionList": {
"description": "Executions List",
@@ -8299,7 +8323,11 @@
"required": [
"total",
"executions"
]
],
"example": {
"total": 5,
"executions": ""
}
},
"countryList": {
"description": "Countries List",
@@ -8324,7 +8352,11 @@
"required": [
"total",
"countries"
]
],
"example": {
"total": 5,
"countries": ""
}
},
"continentList": {
"description": "Continents List",
@@ -8349,7 +8381,11 @@
"required": [
"total",
"continents"
]
],
"example": {
"total": 5,
"continents": ""
}
},
"languageList": {
"description": "Languages List",
@@ -8374,7 +8410,11 @@
"required": [
"total",
"languages"
]
],
"example": {
"total": 5,
"languages": ""
}
},
"currencyList": {
"description": "Currencies List",
@@ -8399,7 +8439,11 @@
"required": [
"total",
"currencies"
]
],
"example": {
"total": 5,
"currencies": ""
}
},
"phoneList": {
"description": "Phones List",
@@ -8424,7 +8468,11 @@
"required": [
"total",
"phones"
]
],
"example": {
"total": 5,
"phones": ""
}
},
"localeCodeList": {
"description": "Locale codes list",
@@ -8449,7 +8497,11 @@
"required": [
"total",
"localeCodes"
]
],
"example": {
"total": 5,
"localeCodes": ""
}
},
"document": {
"description": "Document",
@@ -8506,7 +8558,23 @@
"$createdAt",
"$updatedAt",
"$permissions"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$sequence": 1,
"$collectionId": "5e5ea5c15117e",
"$databaseId": "5e5ea5c15117e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"$permissions": [
"read(\"any\")"
],
"username": "john.doe",
"email": "john.doe@example.com",
"fullName": "John Doe",
"age": 30,
"isAdmin": false
}
},
"log": {
"description": "Log",
@@ -8640,7 +8708,30 @@
"deviceModel",
"countryCode",
"countryName"
]
],
"example": {
"event": "account.sessions.create",
"userId": "610fc2f985ee0",
"userEmail": "john@appwrite.io",
"userName": "John Doe",
"mode": "admin",
"ip": "127.0.0.1",
"time": "2020-10-15T06:38:00.000+00:00",
"osCode": "Mac",
"osName": "Mac",
"osVersion": "Mac",
"clientType": "browser",
"clientCode": "CM",
"clientName": "Chrome Mobile iOS",
"clientVersion": "84.0",
"clientEngine": "WebKit",
"clientEngineVersion": "605.1.15",
"deviceName": "smartphone",
"deviceBrand": "Google",
"deviceModel": "Nexus 5",
"countryCode": "US",
"countryName": "United States"
}
},
"user": {
"description": "User",
@@ -8803,7 +8894,33 @@
"prefs",
"targets",
"accessedAt"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"name": "John Doe",
"password": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE",
"hash": "argon2",
"hashOptions": {},
"registration": "2020-10-15T06:38:00.000+00:00",
"status": true,
"labels": [
"vip"
],
"passwordUpdate": "2020-10-15T06:38:00.000+00:00",
"email": "john@appwrite.io",
"phone": "+4930901820",
"emailVerification": true,
"phoneVerification": true,
"mfa": true,
"prefs": {
"theme": "pink",
"timezone": "UTC"
},
"targets": [],
"accessedAt": "2020-10-15T06:38:00.000+00:00"
}
},
"algoMd5": {
"description": "AlgoMD5",
@@ -8817,7 +8934,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "md5"
}
},
"algoSha": {
"description": "AlgoSHA",
@@ -8831,7 +8951,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "sha"
}
},
"algoPhpass": {
"description": "AlgoPHPass",
@@ -8845,7 +8968,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "phpass"
}
},
"algoBcrypt": {
"description": "AlgoBcrypt",
@@ -8859,7 +8985,10 @@
},
"required": [
"type"
]
],
"example": {
"type": "bcrypt"
}
},
"algoScrypt": {
"description": "AlgoScrypt",
@@ -8901,7 +9030,14 @@
"costMemory",
"costParallel",
"length"
]
],
"example": {
"type": "scrypt",
"costCpu": 8,
"costMemory": 14,
"costParallel": 1,
"length": 64
}
},
"algoScryptModified": {
"description": "AlgoScryptModified",
@@ -8933,7 +9069,13 @@
"salt",
"saltSeparator",
"signerKey"
]
],
"example": {
"type": "scryptMod",
"salt": "UxLMreBr6tYyjQ==",
"saltSeparator": "Bw==",
"signerKey": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ=="
}
},
"algoArgon2": {
"description": "AlgoArgon2",
@@ -8968,12 +9110,23 @@
"memoryCost",
"timeCost",
"threads"
]
],
"example": {
"type": "argon2",
"memoryCost": 65536,
"timeCost": 4,
"threads": 3
}
},
"preferences": {
"description": "Preferences",
"type": "object",
"additionalProperties": true
"additionalProperties": true,
"example": {
"language": "en",
"timezone": "UTC",
"darkTheme": true
}
},
"session": {
"description": "Session",
@@ -9160,7 +9313,40 @@
"factors",
"secret",
"mfaUpdatedAt"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5bb8c16897e",
"expire": "2020-10-15T06:38:00.000+00:00",
"provider": "email",
"providerUid": "user@example.com",
"providerAccessToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"providerAccessTokenExpiry": "2020-10-15T06:38:00.000+00:00",
"providerRefreshToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"ip": "127.0.0.1",
"osCode": "Mac",
"osName": "Mac",
"osVersion": "Mac",
"clientType": "browser",
"clientCode": "CM",
"clientName": "Chrome Mobile iOS",
"clientVersion": "84.0",
"clientEngine": "WebKit",
"clientEngineVersion": "605.1.15",
"deviceName": "smartphone",
"deviceBrand": "Google",
"deviceModel": "Nexus 5",
"countryCode": "US",
"countryName": "United States",
"current": true,
"factors": [
"email"
],
"secret": "5e5bb8c16897e",
"mfaUpdatedAt": "2020-10-15T06:38:00.000+00:00"
}
},
"identity": {
"description": "Identity",
@@ -9228,7 +9414,19 @@
"providerAccessToken",
"providerAccessTokenExpiry",
"providerRefreshToken"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5bb8c16897e",
"provider": "email",
"providerUid": "5e5bb8c16897e",
"providerEmail": "user@example.com",
"providerAccessToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"providerAccessTokenExpiry": "2020-10-15T06:38:00.000+00:00",
"providerRefreshToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3"
}
},
"token": {
"description": "Token",
@@ -9272,7 +9470,15 @@
"secret",
"expire",
"phrase"
]
],
"example": {
"$id": "bb8ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5ea5c168bb8",
"secret": "",
"expire": "2020-10-15T06:38:00.000+00:00",
"phrase": "Golden Fox"
}
},
"jwt": {
"description": "JWT",
@@ -9286,7 +9492,10 @@
},
"required": [
"jwt"
]
],
"example": {
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
},
"locale": {
"description": "Locale",
@@ -9336,7 +9545,16 @@
"continent",
"eu",
"currency"
]
],
"example": {
"ip": "127.0.0.1",
"countryCode": "US",
"country": "United States",
"continentCode": "NA",
"continent": "North America",
"eu": false,
"currency": "USD"
}
},
"localeCode": {
"description": "LocaleCode",
@@ -9356,7 +9574,11 @@
"required": [
"code",
"name"
]
],
"example": {
"code": "en-us",
"name": "US"
}
},
"file": {
"description": "File",
@@ -9438,7 +9660,22 @@
"sizeOriginal",
"chunksTotal",
"chunksUploaded"
]
],
"example": {
"$id": "5e5ea5c16897e",
"bucketId": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"$permissions": [
"read(\"any\")"
],
"name": "Pink.png",
"signature": "5d529fd02b544198ae075bd57c1762bb",
"mimeType": "image\/png",
"sizeOriginal": 17890,
"chunksTotal": 17890,
"chunksUploaded": 17890
}
},
"team": {
"description": "Team",
@@ -9490,7 +9727,18 @@
"name",
"total",
"prefs"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"name": "VIP",
"total": 7,
"prefs": {
"theme": "pink",
"timezone": "UTC"
}
}
},
"membership": {
"description": "Membership",
@@ -9581,7 +9829,24 @@
"confirm",
"mfa",
"roles"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5ea5c16897e",
"userName": "John Doe",
"userEmail": "john@appwrite.io",
"teamId": "5e5ea5c16897e",
"teamName": "VIP",
"invited": "2020-10-15T06:38:00.000+00:00",
"joined": "2020-10-15T06:38:00.000+00:00",
"confirm": false,
"mfa": false,
"roles": [
"owner"
]
}
},
"execution": {
"description": "Execution",
@@ -9714,7 +9979,36 @@
"logs",
"errors",
"duration"
]
],
"example": {
"$id": "5e5ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"$permissions": [
"any"
],
"functionId": "5e5ea6g16897e",
"trigger": "http",
"status": "processing",
"requestMethod": "GET",
"requestPath": "\/articles?id=5",
"requestHeaders": [
{
"Content-Type": "application\/json"
}
],
"responseStatusCode": 200,
"responseBody": "",
"responseHeaders": [
{
"Content-Type": "application\/json"
}
],
"logs": "",
"errors": "",
"duration": 0.4,
"scheduledAt": "2020-10-15T06:38:00.000+00:00"
}
},
"country": {
"description": "Country",
@@ -9734,7 +10028,11 @@
"required": [
"name",
"code"
]
],
"example": {
"name": "United States",
"code": "US"
}
},
"continent": {
"description": "Continent",
@@ -9754,7 +10052,11 @@
"required": [
"name",
"code"
]
],
"example": {
"name": "Europe",
"code": "EU"
}
},
"language": {
"description": "Language",
@@ -9780,7 +10082,12 @@
"name",
"code",
"nativeName"
]
],
"example": {
"name": "Italian",
"code": "it",
"nativeName": "Italiano"
}
},
"currency": {
"description": "Currency",
@@ -9832,7 +10139,16 @@
"rounding",
"code",
"namePlural"
]
],
"example": {
"symbol": "$",
"name": "US dollar",
"symbolNative": "$",
"decimalDigits": 2,
"rounding": 0,
"code": "USD",
"namePlural": "US dollars"
}
},
"phone": {
"description": "Phone",
@@ -9858,7 +10174,12 @@
"code",
"countryCode",
"countryName"
]
],
"example": {
"code": "+1",
"countryCode": "US",
"countryName": "United States"
}
},
"headers": {
"description": "Headers",
@@ -9878,7 +10199,11 @@
"required": [
"name",
"value"
]
],
"example": {
"name": "Content-Type",
"value": "application\/json"
}
},
"mfaChallenge": {
"description": "MFA Challenge",
@@ -9910,7 +10235,13 @@
"$createdAt",
"userId",
"expire"
]
],
"example": {
"$id": "bb8ea5c16897e",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"userId": "5e5ea5c168bb8",
"expire": "2020-10-15T06:38:00.000+00:00"
}
},
"mfaRecoveryCodes": {
"description": "MFA Recovery Codes",
@@ -9930,7 +10261,13 @@
},
"required": [
"recoveryCodes"
]
],
"example": {
"recoveryCodes": [
"a3kf0-s0cl2",
"s0co1-as98s"
]
}
},
"mfaType": {
"description": "MFAType",
@@ -9950,7 +10287,11 @@
"required": [
"secret",
"uri"
]
],
"example": {
"secret": true,
"uri": true
}
},
"mfaFactors": {
"description": "MFAFactors",
@@ -9982,7 +10323,13 @@
"phone",
"email",
"recoveryCode"
]
],
"example": {
"totp": true,
"phone": true,
"email": true,
"recoveryCode": true
}
},
"subscriber": {
"description": "Subscriber",
@@ -10057,7 +10404,27 @@
"userName",
"topicId",
"providerType"
]
],
"example": {
"$id": "259125845563242502",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"targetId": "259125845563242502",
"target": {
"$id": "259125845563242502",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"providerType": "email",
"providerId": "259125845563242502",
"name": "ageon-app-email",
"identifier": "random-mail@email.org",
"userId": "5e5ea5c16897e"
},
"userId": "5e5ea5c16897e",
"userName": "Aegon Targaryen",
"topicId": "259125845563242502",
"providerType": "email"
}
},
"target": {
"description": "Target",
@@ -10119,7 +10486,18 @@
"providerType",
"identifier",
"expired"
]
],
"example": {
"$id": "259125845563242502",
"$createdAt": "2020-10-15T06:38:00.000+00:00",
"$updatedAt": "2020-10-15T06:38:00.000+00:00",
"name": "Apple iPhone 12",
"userId": "259125845563242502",
"providerId": "259125845563242502",
"providerType": "email",
"identifier": "token",
"expired": false
}
}
},
"externalDocs": {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+20 -2
View File
@@ -151,6 +151,24 @@ return [
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DOMAIN_TARGET_CAA',
'description' => 'A CAA record domain that can be used to validate custom domains. Value should be domain\'s hostname.',
'introduction' => '',
'default' => '',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_DNS',
'description' => 'DNS server to use for domain validation. Default: 8.8.8.8',
'introduction' => '',
'default' => '8.8.8.8',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_CONSOLE_WHITELIST_ROOT',
'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by inviting them to your project. By default this option is enabled.',
@@ -827,7 +845,7 @@ return [
],
[
'name' => '_APP_FUNCTIONS_TIMEOUT',
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new function. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the function\'s settings or in appwrite.json.',
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new function. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the function\'s settings or in appwrite.config.json.',
'introduction' => '0.7.0',
'default' => '900',
'required' => false,
@@ -1070,7 +1088,7 @@ return [
'variables' => [
[
'name' => '_APP_SITES_TIMEOUT',
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new site. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the sites\'s settings or in appwrite.json.',
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new site. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the sites\'s settings or in appwrite.config.json.',
'introduction' => '1.7.0',
'default' => '900',
'required' => false,
+50 -5
View File
@@ -71,6 +71,7 @@ $oauthDefaultFailure = '/console/auth/oauth2/failure';
function sendSessionAlert(Locale $locale, Document $user, Document $project, Document $session, Mail $queueForMails)
{
$subject = $locale->getText("emails.sessionAlert.subject");
$preview = $locale->getText("emails.sessionAlert.preview");
$customTemplate = $project->getAttribute('templates', [])['email.sessionAlert-' . $locale->default] ?? [];
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-session-alert.tpl');
@@ -132,6 +133,16 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc
->setSmtpSenderName($senderName);
}
// session alerts should always have a client name!
$clientName = $session->getAttribute('clientName');
if (empty($clientName)) {
// fallback to the user agent and then unknown!
$userAgent = $session->getAttribute('userAgent');
$clientName = !empty($userAgent) ? $userAgent : 'UNKNOWN';
$session->setAttribute('clientName', $clientName);
}
$emailVariables = [
'direction' => $locale->getText('settings.direction'),
'date' => (new \DateTime())->format('F j'),
@@ -148,6 +159,7 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc
$queueForMails
->setSubject($subject)
->setPreview($preview)
->setBody($body)
->setVariables($emailVariables)
->setRecipient($email)
@@ -2025,6 +2037,7 @@ App::post('/v1/account/tokens/magic-url')
$url = Template::unParseURL($url);
$subject = $locale->getText("emails.magicSession.subject");
$preview = $locale->getText("emails.magicSession.preview");
$customTemplate = $project->getAttribute('templates', [])['email.magicSession-' . $locale->default] ?? [];
$detector = new Detector($request->getUserAgent('UNKNOWN'));
@@ -2113,6 +2126,7 @@ App::post('/v1/account/tokens/magic-url')
$queueForMails
->setSubject($subject)
->setPreview($preview)
->setBody($body)
->setVariables($emailVariables)
->setRecipient($email)
@@ -2225,7 +2239,30 @@ App::post('/v1/account/tokens/email')
]);
$user->removeAttribute('$sequence');
Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
$user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
try {
$target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([
'$permissions' => [
Permission::read(Role::user($user->getId())),
Permission::update(Role::user($user->getId())),
Permission::delete(Role::user($user->getId())),
],
'userId' => $user->getId(),
'userInternalId' => $user->getSequence(),
'providerType' => MESSAGE_TYPE_EMAIL,
'identifier' => $email,
])));
$user->setAttribute('targets', [...$user->getAttribute('targets', []), $target]);
} catch (Duplicate) {
$existingTarget = $dbForProject->findOne('targets', [
Query::equal('identifier', [$email]),
]);
if (!$existingTarget->isEmpty()) {
$user->setAttribute('targets', $existingTarget, Document::SET_TYPE_APPEND);
}
}
$dbForProject->purgeCachedDocument('users', $user->getId());
}
$tokenSecret = Auth::codeGenerator(6);
@@ -2254,6 +2291,7 @@ App::post('/v1/account/tokens/email')
$dbForProject->purgeCachedDocument('users', $user->getId());
$subject = $locale->getText("emails.otpSession.subject");
$preview = $locale->getText("emails.otpSession.preview");
$customTemplate = $project->getAttribute('templates', [])['email.otpSession-' . $locale->default] ?? [];
$detector = new Detector($request->getUserAgent('UNKNOWN'));
@@ -2339,6 +2377,7 @@ App::post('/v1/account/tokens/email')
$queueForMails
->setSubject($subject)
->setPreview($preview)
->setBody($body)
->setVariables($emailVariables)
->setRecipient($email)
@@ -3233,7 +3272,7 @@ App::post('/v1/account/recovery')
throw new Exception(Exception::USER_BLOCKED);
}
$expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_RECOVERY);
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_RECOVERY));
$secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_RECOVERY);
$recovery = new Document([
@@ -3265,6 +3304,7 @@ App::post('/v1/account/recovery')
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
$body = $locale->getText("emails.recovery.body");
$subject = $locale->getText("emails.recovery.subject");
$preview = $locale->getText("emails.recovery.preview");
$customTemplate = $project->getAttribute('templates', [])['email.recovery-' . $locale->default] ?? [];
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
@@ -3339,6 +3379,7 @@ App::post('/v1/account/recovery')
->setBody($body)
->setVariables($emailVariables)
->setSubject($subject)
->setPreview($preview)
->trigger();
$recovery->setAttribute('secret', $secret);
@@ -3490,7 +3531,7 @@ App::post('/v1/account/verification')
}
$verificationSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_VERIFICATION);
$expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM);
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM));
$verification = new Document([
'$id' => ID::unique(),
@@ -3520,6 +3561,7 @@ App::post('/v1/account/verification')
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
$body = $locale->getText("emails.verification.body");
$preview = $locale->getText("emails.verification.preview");
$subject = $locale->getText("emails.verification.subject");
$customTemplate = $project->getAttribute('templates', [])['email.verification-' . $locale->default] ?? [];
@@ -3592,6 +3634,7 @@ App::post('/v1/account/verification')
$queueForMails
->setSubject($subject)
->setPreview($preview)
->setBody($body)
->setVariables($emailVariables)
->setRecipient($user->getAttribute('email'))
@@ -3738,7 +3781,7 @@ App::post('/v1/account/verification/phone')
}
$secret ??= Auth::codeGenerator();
$expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM);
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM));
$verification = new Document([
'$id' => ID::unique(),
@@ -4346,7 +4389,7 @@ App::post('/v1/account/mfa/challenge')
->inject('plan')
->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) {
$expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM);
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM));
$code = Auth::codeGenerator();
$challenge = new Document([
'userId' => $user->getId(),
@@ -4437,6 +4480,7 @@ App::post('/v1/account/mfa/challenge')
}
$subject = $locale->getText("emails.mfaChallenge.subject");
$preview = $locale->getText("emails.mfaChallenge.preview");
$customTemplate = $project->getAttribute('templates', [])['email.mfaChallenge-' . $locale->default] ?? [];
$detector = new Detector($request->getUserAgent('UNKNOWN'));
@@ -4513,6 +4557,7 @@ App::post('/v1/account/mfa/challenge')
$queueForMails
->setSubject($subject)
->setPreview($preview)
->setBody($body)
->setVariables($emailVariables)
->setRecipient($user->getAttribute('email'))
+33 -9
View File
@@ -10,6 +10,7 @@ use Appwrite\URL\URL as URLParse;
use Appwrite\Utopia\Response;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
use enshrined\svgSanitize\Sanitizer as SvgSanitizer;
use Utopia\App;
use Utopia\Config\Config;
use Utopia\Database\Database;
@@ -362,7 +363,8 @@ App::get('/v1/avatars/favicon')
$client = new Client();
try {
$res = $client
->setAllowRedirects(false)
->setAllowRedirects(true)
->setMaxRedirects(5)
->setUserAgent(\sprintf(
APP_USERAGENT,
System::getEnv('_APP_VERSION', 'UNKNOWN'),
@@ -373,15 +375,11 @@ App::get('/v1/avatars/favicon')
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
if ($res->getStatusCode() !== 200) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
}
$doc = new DOMDocument();
$doc->strictErrorChecking = false;
@$doc->loadHTML($res->getBody());
$links = $doc->getElementsByTagName('link');
$links = $doc->getElementsByTagName('link') ?? [];
$outputHref = '';
$outputExt = '';
$space = 0;
@@ -399,6 +397,12 @@ App::get('/v1/avatars/favicon')
$ext = \pathinfo(\parse_url($absolute, PHP_URL_PATH), PATHINFO_EXTENSION);
switch ($ext) {
case 'svg':
// SVG icons are prioritized by assigning the maximum possible value.
$space = PHP_INT_MAX;
$outputHref = $absolute;
$outputExt = $ext;
break;
case 'ico':
case 'png':
case 'jpg':
@@ -437,7 +441,8 @@ App::get('/v1/avatars/favicon')
$client = new Client();
try {
$res = $client
->setAllowRedirects(false)
->setAllowRedirects(true)
->setMaxRedirects(5)
->fetch($outputHref);
} catch (\Throwable) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
@@ -449,14 +454,33 @@ App::get('/v1/avatars/favicon')
$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') {
if ('ico' === $outputExt) { // Skip crop, Imagick isn\'t supporting icon files
if (
empty($data) ||
stripos($data, '<html') === 0 ||
stripos($data, '<!doc') === 0
) {
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND, 'Favicon not found');
}
$response
->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days
->setContentType('image/x-icon')
->file($data);
return;
}
if ('svg' === $outputExt) { // Skip crop, Imagick isn\'t supporting svg files
$sanitizer = new SvgSanitizer();
$sanitizer->minify(true);
$cleanSvg = $sanitizer->sanitize($data);
if ($cleanSvg === false) {
throw new \Exception('SVG sanitization failed');
}
$response
->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days
->setContentType('image/svg+xml')
->file($cleanSvg);
return;
}
$image = new Image($data);
+2
View File
@@ -71,6 +71,8 @@ App::get('/v1/console/variables')
'_APP_DOMAIN_TARGET_CNAME' => System::getEnv('_APP_DOMAIN_TARGET_CNAME'),
'_APP_DOMAIN_TARGET_AAAA' => System::getEnv('_APP_DOMAIN_TARGET_AAAA'),
'_APP_DOMAIN_TARGET_A' => System::getEnv('_APP_DOMAIN_TARGET_A'),
// Combine CAA domain with most common flags and tag (no parameters)
'_APP_DOMAIN_TARGET_CAA' => '0 issue "' . System::getEnv('_APP_DOMAIN_TARGET_CAA') . '"',
'_APP_STORAGE_LIMIT' => +System::getEnv('_APP_STORAGE_LIMIT'),
'_APP_COMPUTE_SIZE_LIMIT' => +System::getEnv('_APP_COMPUTE_SIZE_LIMIT'),
'_APP_USAGE_STATS' => System::getEnv('_APP_USAGE_STATS'),
+33 -5
View File
@@ -3453,6 +3453,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
} else {
$relation->removeAttribute('$collectionId');
$relation->removeAttribute('$databaseId');
$relation->removeAttribute('$sequence');
$relation->setAttribute('$collection', $relatedCollection->getId());
$type = Database::PERMISSION_UPDATE;
}
@@ -3485,6 +3486,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
}
}
// Remove sequence if set
unset($document['$sequence']);
// Assign a unique ID if needed, otherwise use the provided ID.
$document['$id'] = $sourceId === 'unique()' ? ID::unique() : $sourceId;
$document = new Document($document);
@@ -4074,6 +4078,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$permissions = $document->getPermissions() ?? [];
}
// Remove sequence if set
unset($data['$sequence']);
$data['$id'] = $documentId;
$data['$permissions'] = $permissions;
$newDocument = new Document($data);
@@ -4126,6 +4133,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
));
$relation->removeAttribute('$collectionId');
$relation->removeAttribute('$databaseId');
$relation->removeAttribute('$sequence');
// Attribute $collection is required for Utopia.
$relation->setAttribute(
'$collection',
@@ -4257,10 +4265,11 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true)
->inject('requestTimestamp')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('queueForEvents')
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
if (empty($data) && \is_null($permissions)) {
@@ -4280,12 +4289,28 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
// Map aggregate permissions into the multiple permissions they represent.
$permissions = Permission::aggregate($permissions, [
$allowedPermissions = [
Database::PERMISSION_READ,
Database::PERMISSION_UPDATE,
Database::PERMISSION_DELETE,
]);
];
$permissions = Permission::aggregate($permissions, $allowedPermissions);
// if no permission, upsert permission from the old document if present (update scenario) else add default permission (create scenario)
if (\is_null($permissions)) {
$oldDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId));
if ($oldDocument->isEmpty()) {
if (!empty($user->getId())) {
$defaultPermissions = [];
foreach ($allowedPermissions as $permission) {
$defaultPermissions[] = (new Permission($permission, 'user', $user->getId()))->toString();
}
$permissions = $defaultPermissions;
}
} else {
$permissions = $oldDocument->getPermissions();
}
}
// Users can only manage their own roles, API keys and Admin users can manage any
$roles = Authorization::getRoles();
@@ -4691,6 +4716,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents')
}
}
// Remove sequence if set
unset($data['$sequence']);
$documents = [];
try {
@@ -4728,7 +4756,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents')
});
App::put('/v1/databases/:databaseId/collections/:collectionId/documents')
->desc('Create or update documents')
->desc('Upsert documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
+6 -17
View File
@@ -522,17 +522,11 @@ App::get('/v1/health/queue/databases')
))
->param('name', 'database_db_main', new Text(256), 'Queue name for which to check the queue size', true)
->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true)
->inject('publisher')
->inject('publisherRedis')
->inject('publisherDatabases')
->inject('response')
->action(function (string $name, int|string $threshold, Publisher $publisher, ?Publisher $publisherRedis, Response $response) {
->action(function (string $name, int|string $threshold, Publisher $publisherDatabases, Response $response) {
$threshold = \intval($threshold);
$isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'databases');
$size = $isRedisFallback
? $publisherRedis->getQueueSize(new Queue($name))
: $publisher->getQueueSize(new Queue($name));
$size = $publisherDatabases->getQueueSize(new Queue($name));
if ($size >= $threshold) {
throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}.");
@@ -659,17 +653,12 @@ App::get('/v1/health/queue/migrations')
contentType: ContentType::JSON
))
->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true)
->inject('publisher')
->inject('publisherRedis')
->inject('publisherMigrations')
->inject('response')
->action(function (int|string $threshold, Publisher $publisher, ?Publisher $publisherRedis, Response $response) {
->action(function (int|string $threshold, Publisher $publisherMigrations, Response $response) {
$threshold = \intval($threshold);
$isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'migrations');
$size = $isRedisFallback
? $publisherRedis->getQueueSize(new Queue(Event::MIGRATIONS_QUEUE_NAME))
: $publisher->getQueueSize(new Queue(Event::MIGRATIONS_QUEUE_NAME));
$size = $publisherMigrations->getQueueSize(new Queue(Event::MIGRATIONS_QUEUE_NAME));
if ($size >= $threshold) {
throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}.");
+45 -8
View File
@@ -2175,7 +2175,7 @@ App::post('/v1/projects/:projectId/smtp/tests')
->setSmtpSenderName($senderName)
->setRecipient($email)
->setName('')
->setbodyTemplate(__DIR__ . '/../../config/locale/templates/email-base-styled.tpl')
->setBodyTemplate(__DIR__ . '/../../config/locale/templates/email-base-styled.tpl')
->setBody($template->render())
->setVariables([])
->setSubject($subject)
@@ -2268,16 +2268,53 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale')
$localeObj = new Locale($locale);
if (is_null($template)) {
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
/**
* different templates, different placeholders.
*/
$templateConfigs = [
'magicSession' => [
'file' => 'email-magic-url.tpl',
'placeholders' => ['optionButton', 'buttonText', 'optionUrl', 'clientInfo', 'securityPhrase']
],
'mfaChallenge' => [
'file' => 'email-mfa-challenge.tpl',
'placeholders' => ['description', 'clientInfo']
],
'otpSession' => [
'file' => 'email-otp.tpl',
'placeholders' => ['description', 'clientInfo', 'securityPhrase']
],
'sessionAlert' => [
'file' => 'email-session-alert.tpl',
'placeholders' => ['body', 'listDevice', 'listIpAddress', 'listCountry', 'footer']
],
];
// fallback to the base template.
$config = $templateConfigs[$type] ?? [
'file' => 'email-inner-base.tpl',
'placeholders' => ['buttonText', 'body', 'footer']
];
$templateString = file_get_contents(__DIR__ . '/../../config/locale/templates/' . $config['file']);
// We use `fromString` due to the replace above
$message = Template::fromString($templateString);
// Set type-specific parameters
foreach ($config['placeholders'] as $param) {
$escapeHtml = !in_array($param, ['clientInfo', 'body', 'footer', 'description']);
$message->setParam("{{{$param}}}", $localeObj->getText("emails.{$type}.{$param}"), escapeHtml: $escapeHtml);
}
$message
// common placeholders on all the templates
->setParam('{{hello}}', $localeObj->getText("emails.{$type}.hello"))
->setParam('{{footer}}', $localeObj->getText("emails.{$type}.footer"))
->setParam('{{body}}', $localeObj->getText('emails.' . $type . '.body'), escapeHtml: false)
->setParam('{{thanks}}', $localeObj->getText("emails.{$type}.thanks"))
->setParam('{{buttonText}}', $localeObj->getText("emails.{$type}.buttonText"))
->setParam('{{signature}}', $localeObj->getText("emails.{$type}.signature"))
->setParam('{{direction}}', $localeObj->getText('settings.direction'));
$message = $message->render();
->setParam('{{signature}}', $localeObj->getText("emails.{$type}.signature"));
// `useContent: false` will strip new lines!
$message = $message->render(useContent: true);
$template = [
'message' => $message,
+13
View File
@@ -286,6 +286,19 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
throw new Exception(Exception::RULE_VERIFICATION_FAILED);
}
// Ensure CAA won't block certificate issuance
if (!empty(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''))) {
$validationStart = \microtime(true);
$validator = new DNS(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''), DNS::RECORD_CAA);
if (!$validator->isValid($domain->get())) {
$log->addExtra('dnsTimingCaa', \strval(\microtime(true) - $validationStart));
$log->addTag('dnsDomain', $domain->get());
$error = $validator->getDescription();
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
throw new Exception(Exception::RULE_VERIFICATION_FAILED, 'Domain verification failed because CAA records do not allow Appwrite\'s certificate issuer.');
}
}
$dbForPlatform->updateDocument('rules', $rule->getId(), $rule->setAttribute('status', 'verifying'));
// Issue a TLS certificate when domain is verified
+6 -6
View File
@@ -1870,7 +1870,7 @@ App::get('/v1/storage/usage')
$total = [];
Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) {
foreach ($metrics as $metric) {
$result = $dbForProject->findOne('stats', [
$result = $dbForProject->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
]);
@@ -1899,7 +1899,7 @@ App::get('/v1/storage/usage')
};
foreach ($metrics as $metric) {
$usage[$metric]['total'] = $stats[$metric]['total'];
$usage[$metric]['total'] = $stats[$metric]['total'];
$usage[$metric]['data'] = [];
$leap = time() - ($days['limit'] * $days['factor']);
while ($leap < time()) {
@@ -1917,8 +1917,8 @@ App::get('/v1/storage/usage')
'filesTotal' => $usage[$metrics[1]]['total'],
'filesStorageTotal' => $usage[$metrics[2]]['total'],
'buckets' => $usage[$metrics[0]]['data'],
'files' => $usage[$metrics[1]]['data'],
'storage' => $usage[$metrics[2]]['data'],
'files' => $usage[$metrics[1]]['data'],
'storage' => $usage[$metrics[2]]['data'],
]), Response::MODEL_USAGE_STORAGE);
});
@@ -1970,7 +1970,7 @@ App::get('/v1/storage/:bucketId/usage')
? $dbForLogs
: $dbForProject;
$result = $db->findOne('stats', [
$result = $db->findOne('stats', [
Query::equal('metric', [$metric]),
Query::equal('period', ['inf'])
]);
@@ -2000,7 +2000,7 @@ App::get('/v1/storage/:bucketId/usage')
};
foreach ($metrics as $metric) {
$usage[$metric]['total'] = $stats[$metric]['total'];
$usage[$metric]['total'] = $stats[$metric]['total'];
$usage[$metric]['data'] = [];
$leap = time() - ($days['limit'] * $days['factor']);
while ($leap < time()) {
+2
View File
@@ -657,6 +657,7 @@ App::post('/v1/teams/:teamId/memberships')
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
$body = $locale->getText("emails.invitation.body");
$preview = $locale->getText("emails.invitation.preview");
$subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName);
$customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? [];
@@ -729,6 +730,7 @@ App::post('/v1/teams/:teamId/memberships')
$queueForMails
->setSubject($subject)
->setBody($body)
->setPreview($preview)
->setRecipient($invitee->getAttribute('email'))
->setName($invitee->getAttribute('name', ''))
->setVariables($emailVariables)
+6 -4
View File
@@ -1137,6 +1137,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
$repository['pushedAt'] = $repository['pushed_at'] ?? '';
$repository['organization'] = $installation->getAttribute('organization', '');
$repository['provider'] = $installation->getAttribute('provider', '');
$repository['defaultBranch'] = $repository['default_branch'] ?? '';
$response->dynamic(new Document($repository), Response::MODEL_PROVIDER_REPOSITORY);
});
@@ -1234,7 +1235,8 @@ App::post('/v1/vcs/github/events')
$providerRepositoryUrl = $parsedPayload["repositoryUrl"] ?? '';
$providerCommitHash = $parsedPayload["commitHash"] ?? '';
$providerRepositoryOwner = $parsedPayload["owner"] ?? '';
$providerCommitAuthor = $parsedPayload["headCommitAuthor"] ?? '';
$providerCommitAuthorName = $parsedPayload["headCommitAuthorName"] ?? '';
$providerCommitAuthorEmail = $parsedPayload["headCommitAuthorEmail"] ?? '';
$providerCommitAuthorUrl = $parsedPayload["authorUrl"] ?? '';
$providerCommitMessage = $parsedPayload["headCommitMessage"] ?? '';
$providerCommitUrl = $parsedPayload["headCommitUrl"] ?? '';
@@ -1247,9 +1249,9 @@ App::post('/v1/vcs/github/events')
Query::limit(100),
]));
// create new deployment only on push and not when branch is created or deleted
if (!$providerBranchCreated && !$providerBranchDeleted) {
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $request);
// create new deployment only on push (not committed by us) and not when branch is created or deleted
if ($providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && !$providerBranchCreated && !$providerBranchDeleted) {
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $request);
}
} elseif ($event == $github::EVENT_INSTALLATION) {
if ($parsedPayload["action"] == "deleted") {
+4 -2
View File
@@ -1380,9 +1380,10 @@ App::get('/robots.txt')
->inject('apiKey')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
$host = $request->getHostname() ?? '';
$consoleDomain = System::getEnv('_APP_CONSOLE_DOMAIN', '');
$mainDomain = System::getEnv('_APP_DOMAIN', '');
if (($host === $mainDomain || $host === 'localhost') && empty($previewHostname)) {
if (($host === $consoleDomain || $host === $mainDomain || $host === 'localhost') && empty($previewHostname)) {
$template = new View(__DIR__ . '/../views/general/robots.phtml');
$response->text($template->render(false));
} else {
@@ -1413,9 +1414,10 @@ App::get('/humans.txt')
->inject('apiKey')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
$host = $request->getHostname() ?? '';
$consoleDomain = System::getEnv('_APP_CONSOLE_DOMAIN', '');
$mainDomain = System::getEnv('_APP_DOMAIN', '');
if (($host === $mainDomain || $host === 'localhost') && empty($previewHostname)) {
if (($host === $consoleDomain || $host === $mainDomain || $host === 'localhost') && empty($previewHostname)) {
$template = new View(__DIR__ . '/../views/general/humans.phtml');
$response->text($template->render(false));
} else {
+6 -1
View File
@@ -31,6 +31,7 @@ use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\Authorization;
use Utopia\Queue\Publisher;
use Utopia\System\System;
use Utopia\Telemetry\Adapter as Telemetry;
use Utopia\Validator\WhiteList;
$parseLabel = function (string $label, array $responsePayload, array $requestParams, Document $user) {
@@ -421,7 +422,8 @@ App::init()
->inject('apiKey')
->inject('plan')
->inject('devKey')
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey) use ($usageDatabaseListener, $eventDatabaseListener) {
->inject('telemetry')
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry) use ($usageDatabaseListener, $eventDatabaseListener) {
$route = $utopia->getRoute();
@@ -554,6 +556,7 @@ App::init()
));
$useCache = $route->getLabel('cache', false);
$storageCacheOperationsCounter = $telemetry->createCounter('storage.cache.operations.load');
if ($useCache) {
$route = $utopia->match($request);
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
@@ -619,10 +622,12 @@ App::init()
->addHeader('Cache-Control', sprintf('private, max-age=%d', $timestamp))
->addHeader('X-Appwrite-Cache', 'hit')
->setContentType($cacheLog->getAttribute('mimeType'));
$storageCacheOperationsCounter->add(1, ['result' => 'hit']);
if (!$isImageTransformation || !$isDisabled) {
$response->send($data);
}
} else {
$storageCacheOperationsCounter->add(1, ['result' => 'miss']);
$response
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
->addHeader('Pragma', 'no-cache')
+2
View File
@@ -80,6 +80,8 @@ const APP_COMPUTE_SPECIFICATION_DEFAULT = Specification::S_1VCPU_512MB;
const APP_PLATFORM_SERVER = 'server';
const APP_PLATFORM_CLIENT = 'client';
const APP_PLATFORM_CONSOLE = 'console';
const APP_VCS_GITHUB_USERNAME = 'Appwrite';
const APP_VCS_GITHUB_EMAIL = 'team@appwrite.io';
// Database Reconnect
const DATABASE_RECONNECT_SLEEP = 2;
+18 -6
View File
@@ -80,15 +80,27 @@ App::setResource('localeCodes', function () {
App::setResource('publisher', function (Group $pools) {
return new BrokerPool(publisher: $pools->get('publisher'));
}, ['pools']);
App::setResource('publisherRedis', function () {
// Stub
});
App::setResource('publisherDatabases', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
App::setResource('publisherMigrations', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
App::setResource('publisherStatsUsage', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
App::setResource('consumer', function (Group $pools) {
return new BrokerPool(consumer: $pools->get('consumer'));
}, ['pools']);
App::setResource('consumerRedis', function () {
// Stub
});
App::setResource('consumerDatabases', function (BrokerPool $consumer) {
return $consumer;
}, ['consumer']);
App::setResource('consumerMigrations', function (BrokerPool $consumer) {
return $consumer;
}, ['publisher']);
App::setResource('consumerStatsUsage', function (BrokerPool $consumer) {
return $consumer;
}, ['publisher']);
App::setResource('queueForMessaging', function (Publisher $publisher) {
return new Messaging($publisher);
}, ['publisher']);
+8
View File
@@ -95,6 +95,8 @@ $image = $this->getParam('image', '');
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -472,6 +474,8 @@ $image = $this->getParam('image', '');
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_EMAIL_CERTIFICATES
- _APP_REDIS_HOST
@@ -629,6 +633,8 @@ $image = $this->getParam('image', '');
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_EMAIL_SECURITY
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -660,6 +666,8 @@ $image = $this->getParam('image', '');
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
+22 -6
View File
@@ -247,17 +247,33 @@ Server::setResource('publisher', function (Group $pools) {
return new BrokerPool(publisher: $pools->get('publisher'));
}, ['pools']);
Server::setResource('publisherRedis', function () {
// Stub
});
Server::setResource('publisherDatabases', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
Server::setResource('publisherMigrations', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
Server::setResource('publisherStatsUsage', function (BrokerPool $publisher) {
return $publisher;
}, ['publisher']);
Server::setResource('consumer', function (Group $pools) {
return new BrokerPool(consumer: $pools->get('consumer'));
}, ['pools']);
Server::setResource('consumerRedis', function () {
// Stub
});
Server::setResource('consumerDatabases', function (BrokerPool $consumer) {
return $consumer;
}, ['consumer']);
Server::setResource('consumerMigrations', function (BrokerPool $consumer) {
return $consumer;
}, ['consumer']);
Server::setResource('consumerStatsUsage', function (BrokerPool $consumer) {
return $consumer;
}, ['consumer']);
Server::setResource('queueForStatsUsage', function (Publisher $publisher) {
return new StatsUsage($publisher);
+4 -2
View File
@@ -55,6 +55,7 @@
"utopia-php/database": "0.71.*",
"utopia-php/detector": "0.1.*",
"utopia-php/domains": "0.8.*",
"utopia-php/dns": "0.3.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
"utopia-php/fetch": "0.4.*",
@@ -73,7 +74,7 @@
"utopia-php/swoole": "0.8.*",
"utopia-php/system": "0.9.*",
"utopia-php/telemetry": "0.1.*",
"utopia-php/vcs": "0.10.*",
"utopia-php/vcs": "0.11.*",
"utopia-php/websocket": "0.3.*",
"matomo/device-detector": "6.1.*",
"dragonmantank/cron-expression": "3.3.*",
@@ -82,7 +83,8 @@
"adhocore/jwt": "1.1.*",
"spomky-labs/otphp": "^10.0",
"webonyx/graphql-php": "14.11.*",
"league/csv": "9.14.*"
"league/csv": "9.14.*",
"enshrined/svg-sanitize": "0.21.*"
},
"require-dev": {
"ext-fileinfo": "*",
Generated
+230 -102
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f53e1ccd394581428d9efcb53b46d479",
"content-hash": "761a7e17b49381e68038c92873888125",
"packages": [
{
"name": "adhocore/jwt",
@@ -69,16 +69,16 @@
},
{
"name": "appwrite/appwrite",
"version": "15.0.0",
"version": "15.1.0",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-for-php.git",
"reference": "deb97b62e0abed8a4fd5c5d48e77365cf89867cf"
"reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/deb97b62e0abed8a4fd5c5d48e77365cf89867cf",
"reference": "deb97b62e0abed8a4fd5c5d48e77365cf89867cf",
"url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/c438b3885071ac7c0329199dce5e6f6a24dd215b",
"reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b",
"shasum": ""
},
"require": {
@@ -104,10 +104,10 @@
"support": {
"email": "team@appwrite.io",
"issues": "https://github.com/appwrite/sdk-for-php/issues",
"source": "https://github.com/appwrite/sdk-for-php/tree/15.0.0",
"source": "https://github.com/appwrite/sdk-for-php/tree/15.1.0",
"url": "https://appwrite.io/support"
},
"time": "2025-05-18T09:47:10+00:00"
"time": "2025-08-01T04:50:51+00:00"
},
{
"name": "appwrite/php-clamav",
@@ -628,6 +628,51 @@
],
"time": "2023-08-10T19:36:49+00:00"
},
{
"name": "enshrined/svg-sanitize",
"version": "0.21.0",
"source": {
"type": "git",
"url": "https://github.com/darylldoyle/svg-sanitizer.git",
"reference": "5e477468fac5c5ce933dce53af3e8e4e58dcccc9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/5e477468fac5c5ce933dce53af3e8e4e58dcccc9",
"reference": "5e477468fac5c5ce933dce53af3e8e4e58dcccc9",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"php": "^7.1 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^6.5 || ^8.5"
},
"type": "library",
"autoload": {
"psr-4": {
"enshrined\\svgSanitize\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0-or-later"
],
"authors": [
{
"name": "Daryll Doyle",
"email": "daryll@enshrined.co.uk"
}
],
"description": "An SVG sanitizer for PHP",
"support": {
"issues": "https://github.com/darylldoyle/svg-sanitizer/issues",
"source": "https://github.com/darylldoyle/svg-sanitizer/tree/0.21.0"
},
"time": "2025-01-13T09:32:25+00:00"
},
{
"name": "giggsey/libphonenumber-for-php-lite",
"version": "8.13.36",
@@ -1183,16 +1228,16 @@
},
{
"name": "open-telemetry/context",
"version": "1.2.1",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/context.git",
"reference": "1eb2b837ee9362db064a6b65d5ecce15a9f9f020"
"reference": "4d5d98f1d4311a55b8d07e3d4c06d2430b4e6efc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/1eb2b837ee9362db064a6b65d5ecce15a9f9f020",
"reference": "1eb2b837ee9362db064a6b65d5ecce15a9f9f020",
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/4d5d98f1d4311a55b8d07e3d4c06d2430b4e6efc",
"reference": "4d5d98f1d4311a55b8d07e3d4c06d2430b4e6efc",
"shasum": ""
},
"require": {
@@ -1238,7 +1283,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-05-07T23:36:50+00:00"
"time": "2025-08-04T03:25:06+00:00"
},
{
"name": "open-telemetry/exporter-otlp",
@@ -1369,16 +1414,16 @@
},
{
"name": "open-telemetry/sdk",
"version": "1.6.0",
"version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/sdk.git",
"reference": "1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a"
"reference": "86287cf30fd6549444d7b8f7d8758d92e24086ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a",
"reference": "1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a",
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/86287cf30fd6549444d7b8f7d8758d92e24086ac",
"reference": "86287cf30fd6549444d7b8f7d8758d92e24086ac",
"shasum": ""
},
"require": {
@@ -1397,7 +1442,7 @@
"ramsey/uuid": "^3.0 || ^4.0",
"symfony/polyfill-mbstring": "^1.23",
"symfony/polyfill-php82": "^1.26",
"tbachert/spi": "^1.0.1"
"tbachert/spi": "^1.0.5"
},
"suggest": {
"ext-gmp": "To support unlimited number of synchronous metric readers",
@@ -1411,6 +1456,9 @@
"OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderHttpConfig",
"OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderPeerConfig"
],
"OpenTelemetry\\SDK\\Common\\Configuration\\Resolver\\ResolverInterface": [
"OpenTelemetry\\SDK\\Common\\Configuration\\Resolver\\SdkConfigurationResolver"
],
"OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [
"OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager"
]
@@ -1459,20 +1507,20 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-06-19T23:36:51+00:00"
"time": "2025-08-06T03:07:06+00:00"
},
{
"name": "open-telemetry/sem-conv",
"version": "1.32.1",
"version": "1.36.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/sem-conv.git",
"reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22"
"reference": "60dd18fd21d45e6f4234ecab89c14021b6e3de9a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/94daa85ea61a8e2b7e1b0af6be0e875bedda7c22",
"reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22",
"url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/60dd18fd21d45e6f4234ecab89c14021b6e3de9a",
"reference": "60dd18fd21d45e6f4234ecab89c14021b6e3de9a",
"shasum": ""
},
"require": {
@@ -1516,7 +1564,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-06-24T02:32:27+00:00"
"time": "2025-08-04T03:22:08+00:00"
},
{
"name": "paragonie/constant_time_encoding",
@@ -2547,16 +2595,16 @@
},
{
"name": "symfony/http-client",
"version": "v7.3.1",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
"reference": "4403d87a2c16f33345dca93407a8714ee8c05a64"
"reference": "1c064a0c67749923483216b081066642751cc2c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/4403d87a2c16f33345dca93407a8714ee8c05a64",
"reference": "4403d87a2c16f33345dca93407a8714ee8c05a64",
"url": "https://api.github.com/repos/symfony/http-client/zipball/1c064a0c67749923483216b081066642751cc2c7",
"reference": "1c064a0c67749923483216b081066642751cc2c7",
"shasum": ""
},
"require": {
@@ -2622,7 +2670,7 @@
"http"
],
"support": {
"source": "https://github.com/symfony/http-client/tree/v7.3.1"
"source": "https://github.com/symfony/http-client/tree/v7.3.2"
},
"funding": [
{
@@ -2633,12 +2681,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-06-28T07:58:39+00:00"
"time": "2025-07-15T11:36:08+00:00"
},
{
"name": "symfony/http-client-contracts",
@@ -3493,16 +3545,16 @@
},
{
"name": "utopia-php/database",
"version": "0.71.10",
"version": "0.71.12",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "83278d663f9c63c25a11d9e71c7922da7ec48636"
"reference": "72c2a9c185f0f606e4792913a071f744cca21d42"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/83278d663f9c63c25a11d9e71c7922da7ec48636",
"reference": "83278d663f9c63c25a11d9e71c7922da7ec48636",
"url": "https://api.github.com/repos/utopia-php/database/zipball/72c2a9c185f0f606e4792913a071f744cca21d42",
"reference": "72c2a9c185f0f606e4792913a071f744cca21d42",
"shasum": ""
},
"require": {
@@ -3543,9 +3595,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.71.10"
"source": "https://github.com/utopia-php/database/tree/0.71.12"
},
"time": "2025-07-18T00:05:55+00:00"
"time": "2025-08-05T09:38:25+00:00"
},
{
"name": "utopia-php/detector",
@@ -3592,6 +3644,62 @@
},
"time": "2025-05-19T11:01:28+00:00"
},
{
"name": "utopia-php/dns",
"version": "0.3.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/dns.git",
"reference": "8fd4161bc3a8021a670c1101b40f6b09a97f1a54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/dns/zipball/8fd4161bc3a8021a670c1101b40f6b09a97f1a54",
"reference": "8fd4161bc3a8021a670c1101b40f6b09a97f1a54",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/cli": "0.15.*",
"utopia-php/telemetry": "^0.1.1"
},
"require-dev": {
"laravel/pint": "1.2.*",
"phpstan/phpstan": "1.8.*",
"phpunit/phpunit": "^9.3",
"rregeer/phpunit-coverage-check": "^0.3.1",
"swoole/ide-helper": "4.6.6"
},
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\DNS\\": "src/DNS"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
}
],
"description": "Lite & fast micro PHP DNS server abstraction that is **easy to use**.",
"keywords": [
"dns",
"framework",
"php",
"upf",
"utopia"
],
"support": {
"issues": "https://github.com/utopia-php/dns/issues",
"source": "https://github.com/utopia-php/dns/tree/0.3.0"
},
"time": "2025-08-04T11:05:53+00:00"
},
{
"name": "utopia-php/domains",
"version": "0.8.0",
@@ -3942,16 +4050,16 @@
},
{
"name": "utopia-php/messaging",
"version": "0.18.1",
"version": "0.18.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/messaging.git",
"reference": "5d1245207a61d7ca065daddad7ac5f1d5640152f"
"reference": "0d364edacf4d4867964c7e17f653031dd39394bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/5d1245207a61d7ca065daddad7ac5f1d5640152f",
"reference": "5d1245207a61d7ca065daddad7ac5f1d5640152f",
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/0d364edacf4d4867964c7e17f653031dd39394bf",
"reference": "0d364edacf4d4867964c7e17f653031dd39394bf",
"shasum": ""
},
"require": {
@@ -3987,22 +4095,22 @@
],
"support": {
"issues": "https://github.com/utopia-php/messaging/issues",
"source": "https://github.com/utopia-php/messaging/tree/0.18.1"
"source": "https://github.com/utopia-php/messaging/tree/0.18.2"
},
"time": "2025-06-26T18:26:07+00:00"
"time": "2025-07-21T18:27:03+00:00"
},
{
"name": "utopia-php/migration",
"version": "0.11.1",
"version": "0.11.4",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "d528a454d5c1ed6564b2843a39ff13297bcdb1af"
"reference": "e924e6535c4368abd778252da6fa96e423412c67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/d528a454d5c1ed6564b2843a39ff13297bcdb1af",
"reference": "d528a454d5c1ed6564b2843a39ff13297bcdb1af",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/e924e6535c4368abd778252da6fa96e423412c67",
"reference": "e924e6535c4368abd778252da6fa96e423412c67",
"shasum": ""
},
"require": {
@@ -4010,7 +4118,7 @@
"ext-curl": "*",
"ext-openssl": "*",
"php": ">=8.1",
"utopia-php/database": "0.*.*",
"utopia-php/database": "0.71.*",
"utopia-php/dsn": "0.2.*",
"utopia-php/framework": "0.33.*",
"utopia-php/storage": "0.18.*"
@@ -4043,9 +4151,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/0.11.1"
"source": "https://github.com/utopia-php/migration/tree/0.11.4"
},
"time": "2025-07-11T13:46:37+00:00"
"time": "2025-08-08T11:22:24+00:00"
},
{
"name": "utopia-php/orchestration",
@@ -4587,16 +4695,16 @@
},
{
"name": "utopia-php/vcs",
"version": "0.10.5",
"version": "0.11.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/vcs.git",
"reference": "b358439dc387f6097019eb83ebb9fc258fe9da05"
"reference": "0e665eaa7d906168525bf6aac50b6bcc3e4fe528"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/b358439dc387f6097019eb83ebb9fc258fe9da05",
"reference": "b358439dc387f6097019eb83ebb9fc258fe9da05",
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/0e665eaa7d906168525bf6aac50b6bcc3e4fe528",
"reference": "0e665eaa7d906168525bf6aac50b6bcc3e4fe528",
"shasum": ""
},
"require": {
@@ -4630,9 +4738,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/vcs/issues",
"source": "https://github.com/utopia-php/vcs/tree/0.10.5"
"source": "https://github.com/utopia-php/vcs/tree/0.11.0"
},
"time": "2025-06-10T15:01:16+00:00"
"time": "2025-07-23T13:54:58+00:00"
},
{
"name": "utopia-php/websocket",
@@ -4810,16 +4918,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "0.41.17",
"version": "0.41.29",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "ef5e9d952032deecffee7f825a941c40ed4c84b8"
"reference": "4af563f3b0879747efc8434eb8ed8bf97e75039f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/ef5e9d952032deecffee7f825a941c40ed4c84b8",
"reference": "ef5e9d952032deecffee7f825a941c40ed4c84b8",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/4af563f3b0879747efc8434eb8ed8bf97e75039f",
"reference": "4af563f3b0879747efc8434eb8ed8bf97e75039f",
"shasum": ""
},
"require": {
@@ -4855,9 +4963,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.41.17"
"source": "https://github.com/appwrite/sdk-generator/tree/0.41.29"
},
"time": "2025-07-18T08:18:48+00:00"
"time": "2025-08-04T04:34:45+00:00"
},
{
"name": "doctrine/annotations",
@@ -5276,16 +5384,16 @@
},
{
"name": "myclabs/deep-copy",
"version": "1.13.3",
"version": "1.13.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "faed855a7b5f4d4637717c2b3863e277116beb36"
"reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36",
"reference": "faed855a7b5f4d4637717c2b3863e277116beb36",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"shasum": ""
},
"require": {
@@ -5324,7 +5432,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.3"
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
},
"funding": [
{
@@ -5332,20 +5440,20 @@
"type": "tidelift"
}
],
"time": "2025-07-05T12:25:42+00:00"
"time": "2025-08-01T08:46:24+00:00"
},
{
"name": "nikic/php-parser",
"version": "v5.5.0",
"version": "v5.6.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9"
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9",
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/221b0d0fdf1369c71047ad1d18bb5880017bbc56",
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56",
"shasum": ""
},
"require": {
@@ -5388,9 +5496,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.0"
},
"time": "2025-05-31T08:24:38+00:00"
"time": "2025-07-27T20:03:57+00:00"
},
{
"name": "phar-io/manifest",
@@ -7258,16 +7366,16 @@
},
{
"name": "symfony/console",
"version": "v7.3.1",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "9e27aecde8f506ba0fd1d9989620c04a87697101"
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101",
"reference": "9e27aecde8f506ba0fd1d9989620c04a87697101",
"url": "https://api.github.com/repos/symfony/console/zipball/5f360ebc65c55265a74d23d7fe27f957870158a1",
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1",
"shasum": ""
},
"require": {
@@ -7332,7 +7440,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.3.1"
"source": "https://github.com/symfony/console/tree/v7.3.2"
},
"funding": [
{
@@ -7343,25 +7451,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-06-27T19:55:54+00:00"
"time": "2025-07-30T17:13:41+00:00"
},
{
"name": "symfony/filesystem",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb"
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
"reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"shasum": ""
},
"require": {
@@ -7398,7 +7510,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v7.3.0"
"source": "https://github.com/symfony/filesystem/tree/v7.3.2"
},
"funding": [
{
@@ -7409,25 +7521,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-10-25T15:15:23+00:00"
"time": "2025-07-07T08:17:47+00:00"
},
{
"name": "symfony/finder",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d"
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d",
"reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d",
"url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe",
"shasum": ""
},
"require": {
@@ -7462,7 +7578,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v7.3.0"
"source": "https://github.com/symfony/finder/tree/v7.3.2"
},
"funding": [
{
@@ -7473,25 +7589,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-12-30T19:00:26+00:00"
"time": "2025-07-15T13:41:35+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "afb9a8038025e5dbc657378bfab9198d75f10fca"
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca",
"reference": "afb9a8038025e5dbc657378bfab9198d75f10fca",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/119bcf13e67dbd188e5dbc74228b1686f66acd37",
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37",
"shasum": ""
},
"require": {
@@ -7529,7 +7649,7 @@
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v7.3.0"
"source": "https://github.com/symfony/options-resolver/tree/v7.3.2"
},
"funding": [
{
@@ -7540,12 +7660,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-04T13:12:05+00:00"
"time": "2025-07-15T11:36:08+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -7924,16 +8048,16 @@
},
{
"name": "symfony/string",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125"
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125",
"reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125",
"url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca",
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca",
"shasum": ""
},
"require": {
@@ -7991,7 +8115,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v7.3.0"
"source": "https://github.com/symfony/string/tree/v7.3.2"
},
"funding": [
{
@@ -8002,12 +8126,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-20T20:19:01+00:00"
"time": "2025-07-10T08:47:49+00:00"
},
{
"name": "textalk/websocket",
+8
View File
@@ -120,6 +120,8 @@ services:
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -535,6 +537,8 @@ services:
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_EMAIL_CERTIFICATES
- _APP_REDIS_HOST
@@ -704,6 +708,8 @@ services:
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_EMAIL_SECURITY
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -738,6 +744,8 @@ services:
- _APP_DOMAIN_TARGET_CNAME
- _APP_DOMAIN_TARGET_AAAA
- _APP_DOMAIN_TARGET_A
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
@@ -4,9 +4,7 @@ import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setSession("") // The user session to authenticate with
.setKey("") //
.setJWT("<YOUR_JWT>"); // Your secret JSON Web Token
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
@@ -0,0 +1,27 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.decrementDocumentAttribute(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
"<DOCUMENT_ID>", // documentId
"", // attribute
0, // value (optional)
0, // min (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -0,0 +1,27 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
Databases databases = new Databases(client);
databases.incrementDocumentAttribute(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
"<DOCUMENT_ID>", // documentId
"", // attribute
0, // value (optional)
0, // max (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
Log.d("Appwrite", result.toString());
})
);
@@ -15,7 +15,7 @@ functions.createExecution(
"<PATH>", // path (optional)
ExecutionMethod.GET, // method (optional)
mapOf( "a" to "b" ), // headers (optional)
"", // scheduledAt (optional)
"<SCHEDULED_AT>", // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
@@ -4,9 +4,7 @@ import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setSession("") // The user session to authenticate with
.setKey("") //
.setJWT("<YOUR_JWT>") // Your secret JSON Web Token
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
@@ -0,0 +1,18 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.decrementDocumentAttribute(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = "<DOCUMENT_ID>",
attribute = "",
value = 0, // (optional)
min = 0, // (optional)
)
@@ -0,0 +1,18 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val databases = Databases(client)
val result = databases.incrementDocumentAttribute(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = "<DOCUMENT_ID>",
attribute = "",
value = 0, // (optional)
max = 0, // (optional)
)
@@ -15,5 +15,5 @@ val result = functions.createExecution(
path = "<PATH>", // (optional)
method = ExecutionMethod.GET, // (optional)
headers = mapOf( "a" to "b" ), // (optional)
scheduledAt = "", // (optional)
scheduledAt = "<SCHEDULED_AT>", // (optional)
)
@@ -2,9 +2,7 @@ import Appwrite
let client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setSession("") // The user session to authenticate with
.setKey("") //
.setJWT("<YOUR_JWT>") // Your secret JSON Web Token
.setProject("<YOUR_PROJECT_ID>") // Your project ID
let databases = Databases(client)
@@ -0,0 +1,17 @@
import Appwrite
let client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
let databases = Databases(client)
let document = try await databases.decrementDocumentAttribute(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: "<DOCUMENT_ID>",
attribute: "",
value: 0, // optional
min: 0 // optional
)
@@ -0,0 +1,17 @@
import Appwrite
let client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
let databases = Databases(client)
let document = try await databases.incrementDocumentAttribute(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: "<DOCUMENT_ID>",
attribute: "",
value: 0, // optional
max: 0 // optional
)
@@ -2,9 +2,7 @@ import 'package:appwrite/appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setSession('') // The user session to authenticate with
.setKey('') //
.setJWT('<YOUR_JWT>'); // Your secret JSON Web Token
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
Databases databases = Databases(client);
@@ -0,0 +1,16 @@
import 'package:appwrite/appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
Databases databases = Databases(client);
Document result = await databases.decrementDocumentAttribute(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documentId: '<DOCUMENT_ID>',
attribute: '',
value: 0, // optional
min: 0, // optional
);
@@ -0,0 +1,16 @@
import 'package:appwrite/appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
Databases databases = Databases(client);
Document result = await databases.incrementDocumentAttribute(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documentId: '<DOCUMENT_ID>',
attribute: '',
value: 0, // optional
max: 0, // optional
);
@@ -7,6 +7,7 @@ mutation {
permissions: ["read("any")"]
) {
_id
_sequence
_collectionId
_databaseId
_createdAt
@@ -0,0 +1,19 @@
mutation {
databasesDecrementDocumentAttribute(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: "<DOCUMENT_ID>",
attribute: "",
value: 0,
min: 0
) {
_id
_sequence
_collectionId
_databaseId
_createdAt
_updatedAt
_permissions
data
}
}
@@ -0,0 +1,19 @@
mutation {
databasesIncrementDocumentAttribute(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: "<DOCUMENT_ID>",
attribute: "",
value: 0,
max: 0
) {
_id
_sequence
_collectionId
_databaseId
_createdAt
_updatedAt
_permissions
data
}
}
@@ -7,6 +7,7 @@ mutation {
permissions: ["read("any")"]
) {
_id
_sequence
_collectionId
_databaseId
_createdAt
@@ -7,6 +7,7 @@ mutation {
permissions: ["read("any")"]
) {
_id
_sequence
_collectionId
_databaseId
_createdAt
@@ -2,9 +2,7 @@ import { Client, Databases } from "react-native-appwrite";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setSession('') // The user session to authenticate with
.setKey('') //
.setJWT('<YOUR_JWT>'); // Your secret JSON Web Token
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
@@ -0,0 +1,18 @@
import { Client, Databases } from "react-native-appwrite";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
const result = await databases.decrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // min (optional)
);
console.log(result);
@@ -0,0 +1,18 @@
import { Client, Databases } from "react-native-appwrite";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
const result = await databases.incrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // max (optional)
);
console.log(result);
@@ -0,0 +1,12 @@
PATCH /v1/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/decrement HTTP/1.1
Host: cloud.appwrite.io
Content-Type: application/json
X-Appwrite-Response-Format: 1.7.0
X-Appwrite-Project: <YOUR_PROJECT_ID>
X-Appwrite-Session:
X-Appwrite-JWT: <YOUR_JWT>
{
"value": 0,
"min": 0
}
@@ -0,0 +1,12 @@
PATCH /v1/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/increment HTTP/1.1
Host: cloud.appwrite.io
Content-Type: application/json
X-Appwrite-Response-Format: 1.7.0
X-Appwrite-Project: <YOUR_PROJECT_ID>
X-Appwrite-Session:
X-Appwrite-JWT: <YOUR_JWT>
{
"value": 0,
"max": 0
}
@@ -2,9 +2,7 @@ import { Client, Databases } from "appwrite";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setSession('') // The user session to authenticate with
.setKey('') //
.setJWT('<YOUR_JWT>'); // Your secret JSON Web Token
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
@@ -0,0 +1,18 @@
import { Client, Databases } from "appwrite";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
const result = await databases.decrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // min (optional)
);
console.log(result);
@@ -0,0 +1,18 @@
import { Client, Databases } from "appwrite";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
const result = await databases.incrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // max (optional)
);
console.log(result);
@@ -0,0 +1,7 @@
appwrite databases decrementDocumentAttribute \
--databaseId <DATABASE_ID> \
--collectionId <COLLECTION_ID> \
--documentId <DOCUMENT_ID> \
--attribute '' \
@@ -0,0 +1,7 @@
appwrite databases incrementDocumentAttribute \
--databaseId <DATABASE_ID> \
--collectionId <COLLECTION_ID> \
--documentId <DOCUMENT_ID> \
--attribute '' \
@@ -2,9 +2,7 @@ import { Client, Databases } from "@appwrite.io/console";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setSession('') //
.setKey('<YOUR_API_KEY>') // Your secret API key
.setJWT('<YOUR_JWT>'); // Your secret JSON Web Token
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
@@ -2,7 +2,7 @@ import { Client, Databases } from "@appwrite.io/console";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setKey('<YOUR_API_KEY>'); // Your secret API key
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
@@ -0,0 +1,18 @@
import { Client, Databases } from "@appwrite.io/console";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
const result = await databases.decrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // min (optional)
);
console.log(result);
@@ -0,0 +1,18 @@
import { Client, Databases } from "@appwrite.io/console";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
const result = await databases.incrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // max (optional)
);
console.log(result);
@@ -0,0 +1,17 @@
import { Client, Databases } from "@appwrite.io/console";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const databases = new Databases(client);
const result = await databases.upsertDocument(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
{}, // data
["read("any")"] // permissions (optional)
);
console.log(result);
@@ -9,7 +9,7 @@ const databases = new Databases(client);
const result = await databases.upsertDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // documents (optional)
[] // documents
);
console.log(result);
@@ -1,4 +1,4 @@
import { Client, Proxy, } from "@appwrite.io/console";
import { Client, Proxy, , ProxyResourceType } from "@appwrite.io/console";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
@@ -9,7 +9,9 @@ const proxy = new Proxy(client);
const result = await proxy.createRedirectRule(
'', // domain
'https://example.com', // url
.MovedPermanently301 // statusCode
.MovedPermanently301, // statusCode
'<RESOURCE_ID>', // resourceId
ProxyResourceType.Site // resourceType
);
console.log(result);
@@ -9,7 +9,8 @@ const vcs = new Vcs(client);
const result = await vcs.getRepositoryContents(
'<INSTALLATION_ID>', // installationId
'<PROVIDER_REPOSITORY_ID>', // providerRepositoryId
'<PROVIDER_ROOT_DIRECTORY>' // providerRootDirectory (optional)
'<PROVIDER_ROOT_DIRECTORY>', // providerRootDirectory (optional)
'<PROVIDER_REFERENCE>' // providerReference (optional)
);
console.log(result);
@@ -2,9 +2,8 @@ import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setSession('') // The user session to authenticate with
.setKey('<YOUR_API_KEY>') // Your secret API key
.setJWT('<YOUR_JWT>'); // Your secret JSON Web Token
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setSession(''); // The user session to authenticate with
Databases databases = Databases(client);
@@ -2,6 +2,7 @@ import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
Databases databases = Databases(client);
@@ -0,0 +1,17 @@
import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
Databases databases = Databases(client);
Document result = await databases.decrementDocumentAttribute(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documentId: '<DOCUMENT_ID>',
attribute: '',
value: 0, // (optional)
min: 0, // (optional)
);
@@ -0,0 +1,17 @@
import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
Databases databases = Databases(client);
Document result = await databases.incrementDocumentAttribute(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documentId: '<DOCUMENT_ID>',
attribute: '',
value: 0, // (optional)
max: 0, // (optional)
);
@@ -2,9 +2,8 @@ import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setSession('') // The user session to authenticate with
.setKey('<YOUR_API_KEY>') // Your secret API key
.setJWT('<YOUR_JWT>'); // Your secret JSON Web Token
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setSession(''); // The user session to authenticate with
const databases = new Databases(client);
@@ -2,6 +2,7 @@ import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new Databases(client);
@@ -0,0 +1,17 @@
import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new Databases(client);
const response = await databases.decrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // min (optional)
);
@@ -0,0 +1,17 @@
import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new Databases(client);
const response = await databases.incrementDocumentAttribute(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
'', // attribute
null, // value (optional)
null // max (optional)
);
@@ -0,0 +1,16 @@
import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setSession(''); // The user session to authenticate with
const databases = new Databases(client);
const response = await databases.upsertDocument(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
'<DOCUMENT_ID>', // documentId
{}, // data
["read("any")"] // permissions (optional)
);
@@ -10,5 +10,5 @@ const databases = new Databases(client);
const response = await databases.upsertDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // documents (optional)
[] // documents
);
@@ -4,9 +4,8 @@ using Appwrite.Services;
Client client = new Client()
.SetEndPoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.SetSession("") // The user session to authenticate with
.SetKey("<YOUR_API_KEY>") // Your secret API key
.SetJWT("<YOUR_JWT>"); // Your secret JSON Web Token
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetSession(""); // The user session to authenticate with
Databases databases = new Databases(client);
@@ -4,6 +4,7 @@ using Appwrite.Services;
Client client = new Client()
.SetEndPoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
@@ -0,0 +1,19 @@
using Appwrite;
using Appwrite.Models;
using Appwrite.Services;
Client client = new Client()
.SetEndPoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
Document result = await databases.DecrementDocumentAttribute(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: "<DOCUMENT_ID>",
attribute: "",
value: 0, // optional
min: 0 // optional
);

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