mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Compare commits
52
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bbd87ecb2 | ||
|
|
fe8c4cb479 | ||
|
|
b07674ccd3 | ||
|
|
aa5e3bf9a9 | ||
|
|
c1b50e9941 | ||
|
|
3a76249d80 | ||
|
|
b2991709dc | ||
|
|
fcc07533e1 | ||
|
|
3a6d907b42 | ||
|
|
a9c9f602ec | ||
|
|
d90b4c2f19 | ||
|
|
79d733486c | ||
|
|
d862245090 | ||
|
|
aacaadcce0 | ||
|
|
69ee6e0659 | ||
|
|
cfd62cf0a1 | ||
|
|
279682941a | ||
|
|
eae26d90af | ||
|
|
b46ebb95a3 | ||
|
|
ffcb6a4677 | ||
|
|
142e359dba | ||
|
|
4130983210 | ||
|
|
e01ac65ce8 | ||
|
|
97454c0768 | ||
|
|
8b4a56cd9b | ||
|
|
da0a6b167f | ||
|
|
27d0c511ac | ||
|
|
8a58f7b6d7 | ||
|
|
cc97d78b5a | ||
|
|
91c24b671b | ||
|
|
b28e536967 | ||
|
|
ce7f40dd34 | ||
|
|
49318b5dac | ||
|
|
6096c42ff9 | ||
|
|
5afae248ae | ||
|
|
98255fe628 | ||
|
|
7c408d675e | ||
|
|
4d47bc2ebf | ||
|
|
119d6c1789 | ||
|
|
1f0e3e0f51 | ||
|
|
fe9d49c346 | ||
|
|
6a41f8b2b9 | ||
|
|
503145734b | ||
|
|
371cab0658 | ||
|
|
ca8cb6f260 | ||
|
|
fea1630909 | ||
|
|
e40e88c322 | ||
|
|
037d60633b | ||
|
|
218bb4c537 | ||
|
|
c13a70e226 | ||
|
|
ac604b11e3 | ||
|
|
f68d49c4d6 |
@@ -364,6 +364,61 @@ return [
|
||||
'array' => false,
|
||||
'filters' => ['datetime'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('emailCanonical'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 320,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('emailIsFree'),
|
||||
'type' => Database::VAR_BOOLEAN,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('emailIsDisposable'),
|
||||
'type' => Database::VAR_BOOLEAN,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('emailIsCorporate'),
|
||||
'type' => Database::VAR_BOOLEAN,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('emailIsCanonical'),
|
||||
'type' => Database::VAR_BOOLEAN,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
|
||||
@@ -2345,7 +2345,7 @@ return [
|
||||
'$id' => ID::custom('errors'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 65535,
|
||||
'size' => 1_000_000,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
|
||||
@@ -273,7 +273,7 @@ return [
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'screenshotSleep' => 5000,
|
||||
'buildRuntime' => 'flutter-3.29',
|
||||
'buildRuntime' => 'flutter-3.35',
|
||||
'runtimes' => getVersions($templateRuntimes['FLUTTER']['versions'], 'flutter'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
@@ -282,6 +282,7 @@ return [
|
||||
'installCommand' => 'flutter pub get',
|
||||
'outputDirectory' => './build/web',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
@@ -60,7 +60,7 @@ return [
|
||||
[
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'version' => '20.3.0',
|
||||
'version' => '20.3.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-flutter',
|
||||
'package' => 'https://pub.dev/packages/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -376,7 +376,7 @@ return [
|
||||
[
|
||||
'key' => 'dart',
|
||||
'name' => 'Dart',
|
||||
'version' => '19.3.0',
|
||||
'version' => '19.4.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dart',
|
||||
'package' => 'https://pub.dev/packages/dart_appwrite',
|
||||
'enabled' => true,
|
||||
|
||||
@@ -13105,6 +13105,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13131,7 +13132,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -13746,6 +13748,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13772,7 +13775,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -30954,6 +30958,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -30980,7 +30985,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -31601,6 +31607,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -31627,7 +31634,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -12127,6 +12127,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12153,7 +12154,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -12529,6 +12531,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12555,7 +12558,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -21703,6 +21707,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -21729,7 +21734,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -22122,6 +22128,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -22148,7 +22155,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -13105,6 +13105,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13131,7 +13132,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -13746,6 +13748,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13772,7 +13775,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -30954,6 +30958,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -30980,7 +30985,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -31601,6 +31607,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -31627,7 +31634,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -12127,6 +12127,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12153,7 +12154,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -12529,6 +12531,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12555,7 +12558,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -21703,6 +21707,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -21729,7 +21734,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -22122,6 +22128,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -22148,7 +22155,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -13041,6 +13041,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13067,7 +13068,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -13683,6 +13685,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13709,7 +13712,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -31058,6 +31062,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -31084,7 +31089,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -31708,6 +31714,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -31734,7 +31741,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -12078,6 +12078,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12104,7 +12105,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -12493,6 +12495,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12519,7 +12522,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -21845,6 +21849,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -21871,7 +21876,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -22277,6 +22283,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -22303,7 +22310,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -13041,6 +13041,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13067,7 +13068,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -13683,6 +13685,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -13709,7 +13712,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -31058,6 +31062,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -31084,7 +31089,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -31708,6 +31714,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -31734,7 +31741,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -12078,6 +12078,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12104,7 +12105,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -12493,6 +12495,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -12519,7 +12522,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -21845,6 +21849,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -21871,7 +21876,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -22277,6 +22283,7 @@
|
||||
"dart-3.3",
|
||||
"dart-3.5",
|
||||
"dart-3.8",
|
||||
"dart-3.9",
|
||||
"dotnet-6.0",
|
||||
"dotnet-7.0",
|
||||
"dotnet-8.0",
|
||||
@@ -22303,7 +22310,8 @@
|
||||
"flutter-3.24",
|
||||
"flutter-3.27",
|
||||
"flutter-3.29",
|
||||
"flutter-3.32"
|
||||
"flutter-3.32",
|
||||
"flutter-3.35"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
|
||||
@@ -14,7 +14,7 @@ return [
|
||||
],
|
||||
'DART' => [
|
||||
'name' => 'dart',
|
||||
'versions' => ['3.8', '3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16']
|
||||
'versions' => ['3.9', '3.8', '3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16']
|
||||
],
|
||||
'GO' => [
|
||||
'name' => 'go',
|
||||
@@ -38,6 +38,6 @@ return [
|
||||
],
|
||||
'FLUTTER' => [
|
||||
'name' => 'flutter',
|
||||
'versions' => ['3.32', '3.24']
|
||||
'versions' => ['3.35', '3.32', '3.24']
|
||||
],
|
||||
];
|
||||
|
||||
@@ -84,7 +84,7 @@ const TEMPLATE_FRAMEWORKS = [
|
||||
'installCommand' => '',
|
||||
'buildCommand' => 'flutter build web',
|
||||
'outputDirectory' => './build/web',
|
||||
'buildRuntime' => 'flutter-3.29',
|
||||
'buildRuntime' => 'flutter-3.35',
|
||||
'adapter' => 'static',
|
||||
'fallbackFile' => '',
|
||||
],
|
||||
|
||||
@@ -20,7 +20,7 @@ use Appwrite\Event\Messaging;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Hooks\Hooks;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Network\Validator\Email as EmailValidator;
|
||||
use Appwrite\Network\Validator\Redirect;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\SDK\AuthType;
|
||||
@@ -57,6 +57,7 @@ use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\Query\Limit;
|
||||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Emails\Email;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Storage\Validator\FileName;
|
||||
use Utopia\System\System;
|
||||
@@ -337,7 +338,7 @@ App::post('/v1/account')
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be between 8 and 256 chars.', false, ['project', 'passwordsDictionary'])
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
->inject('request')
|
||||
@@ -394,6 +395,13 @@ App::post('/v1/account')
|
||||
|
||||
$passwordHistory = $project->getAttribute('auths', [])['passwordHistory'] ?? 0;
|
||||
$password = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS);
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
try {
|
||||
$userId = $userId == 'unique()' ? ID::unique() : $userId;
|
||||
$user->setAttributes([
|
||||
@@ -422,7 +430,13 @@ App::post('/v1/account')
|
||||
'authenticators' => null,
|
||||
'search' => implode(' ', [$userId, $email, $name]),
|
||||
'accessedAt' => DateTime::now(),
|
||||
'emailCanonical' => $emailCanonical?->getCanonical(),
|
||||
'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(),
|
||||
'emailIsCorporate' => $emailCanonical?->isCorporate(),
|
||||
'emailIsDisposable' => $emailCanonical?->isDisposable(),
|
||||
'emailIsFree' => $emailCanonical?->isFree(),
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
$user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
try {
|
||||
@@ -903,7 +917,7 @@ App::post('/v1/account/sessions/email')
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'url:{url},email:{param-email}')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password. Must be at least 8 chars.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
@@ -1598,6 +1612,12 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
$failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
|
||||
}
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
try {
|
||||
$userId = ID::unique();
|
||||
$user->setAttributes([
|
||||
@@ -1625,7 +1645,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
'authenticators' => null,
|
||||
'search' => implode(' ', [$userId, $email, $name]),
|
||||
'accessedAt' => DateTime::now(),
|
||||
'emailCanonical' => $emailCanonical?->getCanonical(),
|
||||
'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(),
|
||||
'emailIsCorporate' => $emailCanonical?->isCorporate(),
|
||||
'emailIsDisposable' => $emailCanonical?->isDisposable(),
|
||||
'emailIsFree' => $emailCanonical?->isFree(),
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
$userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
|
||||
$dbForProject->createDocument('targets', new Document([
|
||||
@@ -1696,6 +1722,18 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
|
||||
if (empty($user->getAttribute('email'))) {
|
||||
$user->setAttribute('email', $oauth2->getUserEmail($accessToken));
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($user->getAttribute('email'));
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
$user->setAttribute('emailCanonical', $emailCanonical?->getCanonical());
|
||||
$user->setAttribute('emailIsCanonical', $emailCanonical?->isCanonicalSupported());
|
||||
$user->setAttribute('emailIsCorporate', $emailCanonical?->isCorporate());
|
||||
$user->setAttribute('emailIsDisposable', $emailCanonical?->isDisposable());
|
||||
$user->setAttribute('emailIsFree', $emailCanonical?->isFree());
|
||||
}
|
||||
|
||||
if (empty($user->getAttribute('name'))) {
|
||||
@@ -1944,7 +1982,7 @@ App::post('/v1/account/tokens/magic-url')
|
||||
->label('abuse-limit', 60)
|
||||
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
|
||||
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('url', '', fn ($platforms, $devKey) => $devKey->isEmpty() ? new Redirect($platforms) : new URL(), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['platforms', 'devKey'])
|
||||
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
|
||||
->inject('request')
|
||||
@@ -1990,6 +2028,12 @@ App::post('/v1/account/tokens/magic-url')
|
||||
|
||||
$userId = $userId === 'unique()' ? ID::unique() : $userId;
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
$user->setAttributes([
|
||||
'$id' => $userId,
|
||||
'$permissions' => [
|
||||
@@ -2014,6 +2058,11 @@ App::post('/v1/account/tokens/magic-url')
|
||||
'authenticators' => null,
|
||||
'search' => implode(' ', [$userId, $email]),
|
||||
'accessedAt' => DateTime::now(),
|
||||
'emailCanonical' => $emailCanonical?->getCanonical(),
|
||||
'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(),
|
||||
'emailIsCorporate' => $emailCanonical?->isCorporate(),
|
||||
'emailIsDisposable' => $emailCanonical?->isDisposable(),
|
||||
'emailIsFree' => $emailCanonical?->isFree(),
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
@@ -2197,7 +2246,7 @@ App::post('/v1/account/tokens/email')
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
@@ -2240,6 +2289,12 @@ App::post('/v1/account/tokens/email')
|
||||
|
||||
$userId = $userId === 'unique()' ? ID::unique() : $userId;
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
$user->setAttributes([
|
||||
'$id' => $userId,
|
||||
'$permissions' => [
|
||||
@@ -2262,6 +2317,11 @@ App::post('/v1/account/tokens/email')
|
||||
'memberships' => null,
|
||||
'search' => implode(' ', [$userId, $email]),
|
||||
'accessedAt' => DateTime::now(),
|
||||
'emailCanonical' => $emailCanonical?->getCanonical(),
|
||||
'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(),
|
||||
'emailIsCorporate' => $emailCanonical?->isCorporate(),
|
||||
'emailIsDisposable' => $emailCanonical?->isDisposable(),
|
||||
'emailIsFree' => $emailCanonical?->isFree(),
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
@@ -2609,6 +2669,11 @@ App::post('/v1/account/tokens/phone')
|
||||
'memberships' => null,
|
||||
'search' => implode(' ', [$userId, $phone]),
|
||||
'accessedAt' => DateTime::now(),
|
||||
'emailCanonical' => null,
|
||||
'emailIsCanonical' => null,
|
||||
'emailIsCorporate' => null,
|
||||
'emailIsDisposable' => null,
|
||||
'emailIsFree' => null,
|
||||
]);
|
||||
|
||||
$user->removeAttribute('$sequence');
|
||||
@@ -3037,7 +3102,7 @@ App::patch('/v1/account/email')
|
||||
],
|
||||
contentType: ContentType::JSON
|
||||
))
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password. Must be at least 8 chars.')
|
||||
->inject('requestTimestamp')
|
||||
->inject('response')
|
||||
@@ -3072,9 +3137,20 @@ App::patch('/v1/account/email')
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */
|
||||
}
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
$user
|
||||
->setAttribute('email', $email)
|
||||
->setAttribute('emailVerification', false) // After this user needs to confirm mail again
|
||||
->setAttribute('emailCanonical', $emailCanonical?->getCanonical())
|
||||
->setAttribute('emailIsCanonical', $emailCanonical?->isCanonicalSupported())
|
||||
->setAttribute('emailIsCorporate', $emailCanonical?->isCorporate())
|
||||
->setAttribute('emailIsDisposable', $emailCanonical?->isDisposable())
|
||||
->setAttribute('emailIsFree', $emailCanonical?->isFree())
|
||||
;
|
||||
|
||||
if (empty($passwordUpdate)) {
|
||||
@@ -3311,7 +3387,7 @@ App::post('/v1/account/recovery')
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('url', '', fn ($platforms, $devKey) => $devKey->isEmpty() ? new Redirect($platforms) : new URL(), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['platforms', 'devKey'])
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
||||
@@ -10,7 +10,7 @@ use Appwrite\Event\Mail;
|
||||
use Appwrite\Event\Messaging;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Network\Validator\Email as EmailValidator;
|
||||
use Appwrite\Network\Validator\Redirect;
|
||||
use Appwrite\Platform\Workers\Deletes;
|
||||
use Appwrite\SDK\AuthType;
|
||||
@@ -48,6 +48,7 @@ use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\Query\Limit;
|
||||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Emails\Email;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
@@ -468,7 +469,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('email', '', new Email(), 'Email of the new team member.', true)
|
||||
->param('email', '', new EmailValidator(), 'Email of the new team member.', true)
|
||||
->param('userId', '', new UID(), 'ID of the user to be added to a team.', true)
|
||||
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('roles', [], function (Document $project) {
|
||||
@@ -567,38 +568,52 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
}
|
||||
|
||||
try {
|
||||
$userId = ID::unique();
|
||||
$invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([
|
||||
'$id' => $userId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::update(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
],
|
||||
'email' => empty($email) ? null : $email,
|
||||
'phone' => empty($phone) ? null : $phone,
|
||||
'emailVerification' => false,
|
||||
'status' => true,
|
||||
// TODO: Set password empty?
|
||||
'password' => Auth::passwordHash(Auth::passwordGenerator(), Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS),
|
||||
'hash' => Auth::DEFAULT_ALGO,
|
||||
'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS,
|
||||
/**
|
||||
* Set the password update time to 0 for users created using
|
||||
* team invite and OAuth to allow password updates without an
|
||||
* old password
|
||||
*/
|
||||
'passwordUpdate' => null,
|
||||
'registration' => DateTime::now(),
|
||||
'reset' => false,
|
||||
'name' => $name,
|
||||
'prefs' => new \stdClass(),
|
||||
'sessions' => null,
|
||||
'tokens' => null,
|
||||
'memberships' => null,
|
||||
'search' => implode(' ', [$userId, $email, $name]),
|
||||
])));
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
$userId = ID::unique();
|
||||
|
||||
$userDocument = new Document([
|
||||
'$id' => $userId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::read(Role::user($userId)),
|
||||
Permission::update(Role::user($userId)),
|
||||
Permission::delete(Role::user($userId)),
|
||||
],
|
||||
'email' => empty($email) ? null : $email,
|
||||
'phone' => empty($phone) ? null : $phone,
|
||||
'emailVerification' => false,
|
||||
'status' => true,
|
||||
// TODO: Set password empty?
|
||||
'password' => Auth::passwordHash(Auth::passwordGenerator(), Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS),
|
||||
'hash' => Auth::DEFAULT_ALGO,
|
||||
'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS,
|
||||
/**
|
||||
* Set the password update time to 0 for users created using
|
||||
* team invite and OAuth to allow password updates without an
|
||||
* old password
|
||||
*/
|
||||
'passwordUpdate' => null,
|
||||
'registration' => DateTime::now(),
|
||||
'reset' => false,
|
||||
'name' => $name,
|
||||
'prefs' => new \stdClass(),
|
||||
'sessions' => null,
|
||||
'tokens' => null,
|
||||
'memberships' => null,
|
||||
'search' => implode(' ', [$userId, $email, $name]),
|
||||
'emailCanonical' => $emailCanonical?->getCanonical(),
|
||||
'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(),
|
||||
'emailIsCorporate' => $emailCanonical?->isCorporate(),
|
||||
'emailIsDisposable' => $emailCanonical?->isDisposable(),
|
||||
'emailIsFree' => $emailCanonical?->isFree(),
|
||||
]);
|
||||
|
||||
try {
|
||||
$invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', $userDocument));
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Hooks\Hooks;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Network\Validator\Email as EmailValidator;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Deprecated;
|
||||
@@ -49,6 +49,7 @@ use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\Query\Limit;
|
||||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Emails\Email;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
@@ -97,6 +98,12 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
$password = (!empty($password)) ? ($hash === 'plaintext' ? Auth::passwordHash($password, $hash, $hashOptionsObject) : $password) : null;
|
||||
$user = new Document([
|
||||
'$id' => $userId,
|
||||
@@ -124,6 +131,11 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
|
||||
'tokens' => null,
|
||||
'memberships' => null,
|
||||
'search' => implode(' ', [$userId, $email, $phone, $name]),
|
||||
'emailCanonical' => $emailCanonical?->getCanonical(),
|
||||
'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(),
|
||||
'emailIsCorporate' => $emailCanonical?->isCorporate(),
|
||||
'emailIsDisposable' => $emailCanonical?->isDisposable(),
|
||||
'emailIsFree' => $emailCanonical?->isFree(),
|
||||
]);
|
||||
|
||||
if ($hash === 'plaintext') {
|
||||
@@ -208,7 +220,7 @@ App::post('/v1/users')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', null, new Email(), 'User email.', true)
|
||||
->param('email', null, new EmailValidator(), 'User email.', true)
|
||||
->param('phone', null, new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'Plain text user password. Must be at least 8 chars.', true, ['project', 'passwordsDictionary'])
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
@@ -243,7 +255,7 @@ App::post('/v1/users/bcrypt')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Bcrypt.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
@@ -278,7 +290,7 @@ App::post('/v1/users/md5')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using MD5.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
@@ -313,7 +325,7 @@ App::post('/v1/users/argon2')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Argon2.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
@@ -348,7 +360,7 @@ App::post('/v1/users/sha')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using SHA.')
|
||||
->param('passwordVersion', '', new WhiteList(['sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512']), "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", true)
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
@@ -390,7 +402,7 @@ App::post('/v1/users/phpass')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using PHPass.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
@@ -425,7 +437,7 @@ App::post('/v1/users/scrypt')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Scrypt.')
|
||||
->param('passwordSalt', '', new Text(128), 'Optional salt used to hash password.')
|
||||
->param('passwordCpu', 8, new Integer(), 'Optional CPU cost used to hash password.')
|
||||
@@ -473,7 +485,7 @@ App::post('/v1/users/scrypt-modified')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Scrypt Modified.')
|
||||
->param('passwordSalt', '', new Text(128), 'Salt used to hash password.')
|
||||
->param('passwordSaltSeparator', '', new Text(128), 'Salt separator used to hash password.')
|
||||
@@ -527,7 +539,7 @@ App::post('/v1/users/:userId/targets')
|
||||
|
||||
switch ($providerType) {
|
||||
case 'email':
|
||||
$validator = new Email();
|
||||
$validator = new EmailValidator();
|
||||
if (!$validator->isValid($identifier)) {
|
||||
throw new Exception(Exception::GENERAL_INVALID_EMAIL);
|
||||
}
|
||||
@@ -1402,7 +1414,7 @@ App::patch('/v1/users/:userId/email')
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('email', '', new Email(allowEmpty: true), 'User email.')
|
||||
->param('email', '', new EmailValidator(allowEmpty: true), 'User email.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
@@ -1437,9 +1449,20 @@ App::patch('/v1/users/:userId/email')
|
||||
|
||||
$oldEmail = $user->getAttribute('email');
|
||||
|
||||
try {
|
||||
$emailCanonical = new Email($email);
|
||||
} catch (Throwable) {
|
||||
$emailCanonical = null;
|
||||
}
|
||||
|
||||
$user
|
||||
->setAttribute('email', $email)
|
||||
->setAttribute('emailVerification', false)
|
||||
->setAttribute('emailCanonical', $emailCanonical?->getCanonical())
|
||||
->setAttribute('emailIsCanonical', $emailCanonical?->isCanonicalSupported())
|
||||
->setAttribute('emailIsCorporate', $emailCanonical?->isCorporate())
|
||||
->setAttribute('emailIsDisposable', $emailCanonical?->isDisposable())
|
||||
->setAttribute('emailIsFree', $emailCanonical?->isFree())
|
||||
;
|
||||
|
||||
try {
|
||||
@@ -1700,7 +1723,7 @@ App::patch('/v1/users/:userId/targets/:targetId')
|
||||
|
||||
switch ($providerType) {
|
||||
case 'email':
|
||||
$validator = new Email();
|
||||
$validator = new EmailValidator();
|
||||
if (!$validator->isValid($identifier)) {
|
||||
throw new Exception(Exception::GENERAL_INVALID_EMAIL);
|
||||
}
|
||||
|
||||
Generated
+24
-24
@@ -161,16 +161,16 @@
|
||||
},
|
||||
{
|
||||
"name": "appwrite/php-runtimes",
|
||||
"version": "0.19.1",
|
||||
"version": "0.19.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/runtimes.git",
|
||||
"reference": "7bd0cc3cb97de625d7b07230bd91b121f88e72ae"
|
||||
"reference": "e5c142519df5aced37de9c302971c29c079ce3d9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/runtimes/zipball/7bd0cc3cb97de625d7b07230bd91b121f88e72ae",
|
||||
"reference": "7bd0cc3cb97de625d7b07230bd91b121f88e72ae",
|
||||
"url": "https://api.github.com/repos/appwrite/runtimes/zipball/e5c142519df5aced37de9c302971c29c079ce3d9",
|
||||
"reference": "e5c142519df5aced37de9c302971c29c079ce3d9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -210,9 +210,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/runtimes/issues",
|
||||
"source": "https://github.com/appwrite/runtimes/tree/0.19.1"
|
||||
"source": "https://github.com/appwrite/runtimes/tree/0.19.2"
|
||||
},
|
||||
"time": "2025-05-27T07:12:56+00:00"
|
||||
"time": "2025-11-11T13:44:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "beberlei/assert",
|
||||
@@ -756,16 +756,16 @@
|
||||
},
|
||||
{
|
||||
"name": "google/protobuf",
|
||||
"version": "v4.33.0",
|
||||
"version": "v4.33.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/protocolbuffers/protobuf-php.git",
|
||||
"reference": "b50269e23204e5ae859a326ec3d90f09efe3047d"
|
||||
"reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/b50269e23204e5ae859a326ec3d90f09efe3047d",
|
||||
"reference": "b50269e23204e5ae859a326ec3d90f09efe3047d",
|
||||
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/0cd73ccf0cd26c3e72299cce1ea6144091a57e12",
|
||||
"reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -794,9 +794,9 @@
|
||||
"proto"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.0"
|
||||
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.1"
|
||||
},
|
||||
"time": "2025-10-15T20:10:28+00:00"
|
||||
"time": "2025-11-12T21:58:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
@@ -3844,16 +3844,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "3.2.0",
|
||||
"version": "3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "f2d01b6b38057891184f62107bf70a55bc2ea068"
|
||||
"reference": "e10b4faa4f3a3ef30a5f6d76acdb605469924aec"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/f2d01b6b38057891184f62107bf70a55bc2ea068",
|
||||
"reference": "f2d01b6b38057891184f62107bf70a55bc2ea068",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/e10b4faa4f3a3ef30a5f6d76acdb605469924aec",
|
||||
"reference": "e10b4faa4f3a3ef30a5f6d76acdb605469924aec",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3896,9 +3896,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/3.2.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/3.4.0"
|
||||
},
|
||||
"time": "2025-11-06T05:41:54+00:00"
|
||||
"time": "2025-11-13T06:34:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/detector",
|
||||
@@ -5383,16 +5383,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d"
|
||||
"reference": "958947b6483a79e11c3812f23bb3056199fa4105"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d",
|
||||
"reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/958947b6483a79e11c3812f23bb3056199fa4105",
|
||||
"reference": "958947b6483a79e11c3812f23bb3056199fa4105",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5428,9 +5428,9 @@
|
||||
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/1.5.3"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/1.5.4"
|
||||
},
|
||||
"time": "2025-11-10T09:50:41+00:00"
|
||||
"time": "2025-11-12T12:43:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Avatars;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Avatars avatars = new Avatars(client);
|
||||
|
||||
avatars.getScreenshot(
|
||||
"https://example.com", // url
|
||||
mapOf( "a" to "b" ), // headers (optional)
|
||||
1, // viewportWidth (optional)
|
||||
1, // viewportHeight (optional)
|
||||
0.1, // scale (optional)
|
||||
theme.LIGHT, // theme (optional)
|
||||
"<USER_AGENT>", // userAgent (optional)
|
||||
false, // fullpage (optional)
|
||||
"<LOCALE>", // locale (optional)
|
||||
timezone.AFRICA_ABIDJAN, // timezone (optional)
|
||||
-90, // latitude (optional)
|
||||
-180, // longitude (optional)
|
||||
0, // accuracy (optional)
|
||||
false, // touch (optional)
|
||||
listOf(), // permissions (optional)
|
||||
0, // sleep (optional)
|
||||
0, // width (optional)
|
||||
0, // height (optional)
|
||||
-1, // quality (optional)
|
||||
output.JPG, // output (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.coroutines.CoroutineCallback
|
||||
import io.appwrite.services.Avatars
|
||||
|
||||
val client = Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>") // Your project ID
|
||||
|
||||
val avatars = Avatars(client)
|
||||
|
||||
val result = avatars.getScreenshot(
|
||||
url = "https://example.com",
|
||||
headers = mapOf( "a" to "b" ), // (optional)
|
||||
viewportWidth = 1, // (optional)
|
||||
viewportHeight = 1, // (optional)
|
||||
scale = 0.1, // (optional)
|
||||
theme = theme.LIGHT, // (optional)
|
||||
userAgent = "<USER_AGENT>", // (optional)
|
||||
fullpage = false, // (optional)
|
||||
locale = "<LOCALE>", // (optional)
|
||||
timezone = timezone.AFRICA_ABIDJAN, // (optional)
|
||||
latitude = -90, // (optional)
|
||||
longitude = -180, // (optional)
|
||||
accuracy = 0, // (optional)
|
||||
touch = false, // (optional)
|
||||
permissions = listOf(), // (optional)
|
||||
sleep = 0, // (optional)
|
||||
width = 0, // (optional)
|
||||
height = 0, // (optional)
|
||||
quality = -1, // (optional)
|
||||
output = output.JPG, // (optional)
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
import Appwrite
|
||||
import AppwriteEnums
|
||||
|
||||
let client = Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>") // Your project ID
|
||||
|
||||
let avatars = Avatars(client)
|
||||
|
||||
let bytes = try await avatars.getScreenshot(
|
||||
url: "https://example.com",
|
||||
headers: [:], // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: .light, // optional
|
||||
userAgent: "<USER_AGENT>", // optional
|
||||
fullpage: false, // optional
|
||||
locale: "<LOCALE>", // optional
|
||||
timezone: .africaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: .jpg // optional
|
||||
)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
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
|
||||
|
||||
Avatars avatars = Avatars(client);
|
||||
|
||||
// Downloading file
|
||||
UInt8List bytes = await avatars.getScreenshot(
|
||||
url: 'https://example.com',
|
||||
headers: {}, // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: .light, // optional
|
||||
userAgent: '<USER_AGENT>', // optional
|
||||
fullpage: false, // optional
|
||||
locale: '<LOCALE>', // optional
|
||||
timezone: .africaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: .jpg, // optional
|
||||
)
|
||||
|
||||
final file = File('path_to_file/filename.ext');
|
||||
file.writeAsBytesSync(bytes);
|
||||
|
||||
// Displaying image preview
|
||||
FutureBuilder(
|
||||
future: avatars.getScreenshot(
|
||||
url:'https://example.com' ,
|
||||
headers:{} , // optional
|
||||
viewportWidth:1 , // optional
|
||||
viewportHeight:1 , // optional
|
||||
scale:0.1 , // optional
|
||||
theme: .light, // optional
|
||||
userAgent:'<USER_AGENT>' , // optional
|
||||
fullpage:false , // optional
|
||||
locale:'<LOCALE>' , // optional
|
||||
timezone: .africaAbidjan, // optional
|
||||
latitude:-90 , // optional
|
||||
longitude:-180 , // optional
|
||||
accuracy:0 , // optional
|
||||
touch:false , // optional
|
||||
permissions:[] , // optional
|
||||
sleep:0 , // optional
|
||||
width:0 , // optional
|
||||
height:0 , // optional
|
||||
quality:-1 , // optional
|
||||
output: .jpg, // optional
|
||||
), // Works for both public file and private file, for private files you need to be logged in
|
||||
builder: (context, snapshot) {
|
||||
return snapshot.hasData && snapshot.data != null
|
||||
? Image.memory(snapshot.data)
|
||||
: CircularProgressIndicator();
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Client, Avatars, , , } 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 avatars = new Avatars(client);
|
||||
|
||||
const result = avatars.getScreenshot({
|
||||
url: 'https://example.com',
|
||||
headers: {}, // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: .Light, // optional
|
||||
userAgent: '<USER_AGENT>', // optional
|
||||
fullpage: false, // optional
|
||||
locale: '<LOCALE>', // optional
|
||||
timezone: .AfricaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: .Jpg // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
@@ -0,0 +1,6 @@
|
||||
GET /v1/avatars/screenshots HTTP/1.1
|
||||
Host: cloud.appwrite.io
|
||||
X-Appwrite-Response-Format: 1.8.0
|
||||
X-Appwrite-Project: <YOUR_PROJECT_ID>
|
||||
X-Appwrite-Session:
|
||||
X-Appwrite-JWT: <YOUR_JWT>
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Client, Avatars, , , } from "appwrite";
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
|
||||
|
||||
const avatars = new Avatars(client);
|
||||
|
||||
const result = avatars.getScreenshot({
|
||||
url: 'https://example.com',
|
||||
headers: {}, // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: .Light, // optional
|
||||
userAgent: '<USER_AGENT>', // optional
|
||||
fullpage: false, // optional
|
||||
locale: '<LOCALE>', // optional
|
||||
timezone: .AfricaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: .Jpg // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Client, Avatars, , , } 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 avatars = new Avatars(client);
|
||||
|
||||
const result = avatars.getScreenshot({
|
||||
url: 'https://example.com',
|
||||
headers: {}, // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: .Light, // optional
|
||||
userAgent: '<USER_AGENT>', // optional
|
||||
fullpage: false, // optional
|
||||
locale: '<LOCALE>', // optional
|
||||
timezone: .AfricaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: .Jpg // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
@@ -0,0 +1,31 @@
|
||||
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
|
||||
.setSession(''); // The user session to authenticate with
|
||||
|
||||
Avatars avatars = Avatars(client);
|
||||
|
||||
UInt8List result = await avatars.getScreenshot(
|
||||
url: 'https://example.com',
|
||||
headers: {}, // (optional)
|
||||
viewportWidth: 1, // (optional)
|
||||
viewportHeight: 1, // (optional)
|
||||
scale: 0.1, // (optional)
|
||||
theme: .light, // (optional)
|
||||
userAgent: '<USER_AGENT>', // (optional)
|
||||
fullpage: false, // (optional)
|
||||
locale: '<LOCALE>', // (optional)
|
||||
timezone: .africaAbidjan, // (optional)
|
||||
latitude: -90, // (optional)
|
||||
longitude: -180, // (optional)
|
||||
accuracy: 0, // (optional)
|
||||
touch: false, // (optional)
|
||||
permissions: [], // (optional)
|
||||
sleep: 0, // (optional)
|
||||
width: 0, // (optional)
|
||||
height: 0, // (optional)
|
||||
quality: -1, // (optional)
|
||||
output: .jpg, // (optional)
|
||||
);
|
||||
@@ -0,0 +1,34 @@
|
||||
using Appwrite;
|
||||
using Appwrite.Enums;
|
||||
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
|
||||
.SetSession(""); // The user session to authenticate with
|
||||
|
||||
Avatars avatars = new Avatars(client);
|
||||
|
||||
byte[] result = await avatars.GetScreenshot(
|
||||
url: "https://example.com",
|
||||
headers: [object], // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: .Light, // optional
|
||||
userAgent: "<USER_AGENT>", // optional
|
||||
fullpage: false, // optional
|
||||
locale: "<LOCALE>", // optional
|
||||
timezone: .AfricaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: new List<string>(), // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: .Jpg // optional
|
||||
);
|
||||
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/appwrite/sdk-for-go/client"
|
||||
"github.com/appwrite/sdk-for-go/avatars"
|
||||
)
|
||||
|
||||
client := client.New(
|
||||
client.WithEndpoint("https://<REGION>.cloud.appwrite.io/v1")
|
||||
client.WithProject("<YOUR_PROJECT_ID>")
|
||||
client.WithSession("")
|
||||
)
|
||||
|
||||
service := avatars.New(client)
|
||||
|
||||
response, error := service.GetScreenshot(
|
||||
"https://example.com",
|
||||
avatars.WithGetScreenshotHeaders(map[string]interface{}{}),
|
||||
avatars.WithGetScreenshotViewportWidth(1),
|
||||
avatars.WithGetScreenshotViewportHeight(1),
|
||||
avatars.WithGetScreenshotScale(0.1),
|
||||
avatars.WithGetScreenshotTheme("light"),
|
||||
avatars.WithGetScreenshotUserAgent("<USER_AGENT>"),
|
||||
avatars.WithGetScreenshotFullpage(false),
|
||||
avatars.WithGetScreenshotLocale("<LOCALE>"),
|
||||
avatars.WithGetScreenshotTimezone("africa/abidjan"),
|
||||
avatars.WithGetScreenshotLatitude(-90),
|
||||
avatars.WithGetScreenshotLongitude(-180),
|
||||
avatars.WithGetScreenshotAccuracy(0),
|
||||
avatars.WithGetScreenshotTouch(false),
|
||||
avatars.WithGetScreenshotPermissions([]interface{}{}),
|
||||
avatars.WithGetScreenshotSleep(0),
|
||||
avatars.WithGetScreenshotWidth(0),
|
||||
avatars.WithGetScreenshotHeight(0),
|
||||
avatars.WithGetScreenshotQuality(-1),
|
||||
avatars.WithGetScreenshotOutput("jpg"),
|
||||
)
|
||||
@@ -0,0 +1,42 @@
|
||||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Avatars;
|
||||
|
||||
Client 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
|
||||
|
||||
Avatars avatars = new Avatars(client);
|
||||
|
||||
avatars.getScreenshot(
|
||||
"https://example.com", // url
|
||||
mapOf( "a" to "b" ), // headers (optional)
|
||||
1, // viewportWidth (optional)
|
||||
1, // viewportHeight (optional)
|
||||
0.1, // scale (optional)
|
||||
.LIGHT, // theme (optional)
|
||||
"<USER_AGENT>", // userAgent (optional)
|
||||
false, // fullpage (optional)
|
||||
"<LOCALE>", // locale (optional)
|
||||
.AFRICA_ABIDJAN, // timezone (optional)
|
||||
-90, // latitude (optional)
|
||||
-180, // longitude (optional)
|
||||
0, // accuracy (optional)
|
||||
false, // touch (optional)
|
||||
listOf(), // permissions (optional)
|
||||
0, // sleep (optional)
|
||||
0, // width (optional)
|
||||
0, // height (optional)
|
||||
-1, // quality (optional)
|
||||
.JPG, // output (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println(result);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.coroutines.CoroutineCallback
|
||||
import io.appwrite.services.Avatars
|
||||
|
||||
val client = 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
|
||||
|
||||
val avatars = Avatars(client)
|
||||
|
||||
val result = avatars.getScreenshot(
|
||||
url = "https://example.com",
|
||||
headers = mapOf( "a" to "b" ), // optional
|
||||
viewportWidth = 1, // optional
|
||||
viewportHeight = 1, // optional
|
||||
scale = 0.1, // optional
|
||||
theme = "light", // optional
|
||||
userAgent = "<USER_AGENT>", // optional
|
||||
fullpage = false, // optional
|
||||
locale = "<LOCALE>", // optional
|
||||
timezone = "africa/abidjan", // optional
|
||||
latitude = -90, // optional
|
||||
longitude = -180, // optional
|
||||
accuracy = 0, // optional
|
||||
touch = false, // optional
|
||||
permissions = listOf(), // optional
|
||||
sleep = 0, // optional
|
||||
width = 0, // optional
|
||||
height = 0, // optional
|
||||
quality = -1, // optional
|
||||
output = "jpg" // optional
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
const sdk = require('node-appwrite');
|
||||
|
||||
const client = new sdk.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 avatars = new sdk.Avatars(client);
|
||||
|
||||
const result = await avatars.getScreenshot({
|
||||
url: 'https://example.com',
|
||||
headers: {}, // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: sdk..Light, // optional
|
||||
userAgent: '<USER_AGENT>', // optional
|
||||
fullpage: false, // optional
|
||||
locale: '<LOCALE>', // optional
|
||||
timezone: sdk..AfricaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: sdk..Jpg // optional
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
from appwrite.client import Client
|
||||
from appwrite.services.avatars import Avatars
|
||||
|
||||
client = Client()
|
||||
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
|
||||
client.set_project('<YOUR_PROJECT_ID>') # Your project ID
|
||||
client.set_session('') # The user session to authenticate with
|
||||
|
||||
avatars = Avatars(client)
|
||||
|
||||
result = avatars.get_screenshot(
|
||||
url = 'https://example.com',
|
||||
headers = {}, # optional
|
||||
viewport_width = 1, # optional
|
||||
viewport_height = 1, # optional
|
||||
scale = 0.1, # optional
|
||||
theme = .LIGHT, # optional
|
||||
user_agent = '<USER_AGENT>', # optional
|
||||
fullpage = False, # optional
|
||||
locale = '<LOCALE>', # optional
|
||||
timezone = .AFRICA_ABIDJAN, # optional
|
||||
latitude = -90, # optional
|
||||
longitude = -180, # optional
|
||||
accuracy = 0, # optional
|
||||
touch = False, # optional
|
||||
permissions = [], # optional
|
||||
sleep = 0, # optional
|
||||
width = 0, # optional
|
||||
height = 0, # optional
|
||||
quality = -1, # optional
|
||||
output = .JPG # optional
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
GET /v1/avatars/screenshots HTTP/1.1
|
||||
Host: cloud.appwrite.io
|
||||
X-Appwrite-Response-Format: 1.8.0
|
||||
X-Appwrite-Project: <YOUR_PROJECT_ID>
|
||||
X-Appwrite-Session:
|
||||
X-Appwrite-Key: <YOUR_API_KEY>
|
||||
X-Appwrite-JWT: <YOUR_JWT>
|
||||
@@ -0,0 +1,33 @@
|
||||
require 'appwrite'
|
||||
|
||||
include Appwrite
|
||||
|
||||
client = Client.new
|
||||
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
|
||||
.set_project('<YOUR_PROJECT_ID>') # Your project ID
|
||||
.set_session('') # The user session to authenticate with
|
||||
|
||||
avatars = Avatars.new(client)
|
||||
|
||||
result = avatars.get_screenshot(
|
||||
url: 'https://example.com',
|
||||
headers: {}, # optional
|
||||
viewport_width: 1, # optional
|
||||
viewport_height: 1, # optional
|
||||
scale: 0.1, # optional
|
||||
theme: ::LIGHT, # optional
|
||||
user_agent: '<USER_AGENT>', # optional
|
||||
fullpage: false, # optional
|
||||
locale: '<LOCALE>', # optional
|
||||
timezone: ::AFRICA_ABIDJAN, # optional
|
||||
latitude: -90, # optional
|
||||
longitude: -180, # optional
|
||||
accuracy: 0, # optional
|
||||
touch: false, # optional
|
||||
permissions: [], # optional
|
||||
sleep: 0, # optional
|
||||
width: 0, # optional
|
||||
height: 0, # optional
|
||||
quality: -1, # optional
|
||||
output: ::JPG # optional
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
import Appwrite
|
||||
import AppwriteEnums
|
||||
|
||||
let client = 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
|
||||
|
||||
let avatars = Avatars(client)
|
||||
|
||||
let bytes = try await avatars.getScreenshot(
|
||||
url: "https://example.com",
|
||||
headers: [:], // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: .light, // optional
|
||||
userAgent: "<USER_AGENT>", // optional
|
||||
fullpage: false, // optional
|
||||
locale: "<LOCALE>", // optional
|
||||
timezone: .africaAbidjan, // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: .jpg // optional
|
||||
)
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Change Log
|
||||
|
||||
## 19.4.0
|
||||
|
||||
* Add `getScreenshot` method to `Avatars` service
|
||||
* Add enums `Theme`, `Output` and `Timezone`
|
||||
* Update runtime enums to add support for `dart39` and `flutter335` runtimes
|
||||
* Fix passing of `null` values and stripping only non-nullable optional parameters from the request body
|
||||
|
||||
## 19.3.0
|
||||
|
||||
* Add `total` parameter to list queries allowing skipping counting rows in a table for improved performance
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Change Log
|
||||
|
||||
## 20.3.1
|
||||
|
||||
* Fix passing of `null` values and stripping only non-nullable optional parameters from the request body
|
||||
|
||||
## 20.3.0
|
||||
|
||||
* Add `total` parameter to list queries allowing skipping counting rows in a table for improved performance
|
||||
|
||||
@@ -6,6 +6,7 @@ use Appwrite\Migration\Migration;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Conflict;
|
||||
@@ -132,6 +133,13 @@ class V23 extends Migration
|
||||
}
|
||||
$this->dbForProject->purgeCachedCollection($id);
|
||||
break;
|
||||
case 'migrations':
|
||||
try {
|
||||
$this->updateMigrateErrorSize();
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("Failed to migration error attribute size in collection {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -201,4 +209,46 @@ class V23 extends Migration
|
||||
}
|
||||
return $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update migration attribute size
|
||||
* @return void
|
||||
*/
|
||||
private function updateMigrateErrorSize(): void
|
||||
{
|
||||
|
||||
if ($this->project->getId() === 'console') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Read-modify-write from the live schema to avoid overwriting unrelated changes.
|
||||
$migration = $this->dbForProject->getCollection('migrations');
|
||||
$attributes = $migration->getAttribute('attributes', []);
|
||||
$attrsArray = \array_map(fn (Document $doc) => $doc->getArrayCopy(), $attributes);
|
||||
$errorsIdx = \array_search('errors', \array_column($attrsArray, '$id'));
|
||||
|
||||
if ($errorsIdx === false) {
|
||||
Console::warning("Skipping: 'errors' attribute not found in migrations collection for project {$this->project->getId()}");
|
||||
return;
|
||||
}
|
||||
|
||||
$desiredSize = 1_000_000;
|
||||
$migrationAttributes = Config::getParam('collections', [])['projects']['migrations']['attributes'] ?? [];
|
||||
$migrationIndex = \array_search('errors', \array_column($migrationAttributes, '$id'));
|
||||
|
||||
if ($migrationIndex !== false && isset($migrationAttributes[$migrationIndex]['size'])) {
|
||||
$desiredSize = (int) $migrationAttributes[$migrationIndex]['size'];
|
||||
}
|
||||
|
||||
$currentSize = (int) ($attributes[$errorsIdx]['size'] ?? 0);
|
||||
|
||||
if ($currentSize === $desiredSize) {
|
||||
Console::warning("Skipping: 'errors' attribute already of desired size {$desiredSize} in migrations collection for project {$this->project->getId()}");
|
||||
return;
|
||||
}
|
||||
$attributes[$errorsIdx]['size'] = $desiredSize;
|
||||
$migration->setAttribute('attributes', $attributes);
|
||||
$this->dbForProject->updateDocument($migration->getCollection(), $migration->getId(), $migration);
|
||||
$this->dbForProject->purgeCachedCollection('migrations');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,10 +255,21 @@ class OpenAPI3 extends Format
|
||||
}
|
||||
|
||||
foreach ($methodObj->getResponses() as $response) {
|
||||
if (\is_array($response->getModel())) {
|
||||
/** @var Response|array $response */
|
||||
$responseModel = $response->getModel();
|
||||
|
||||
if (\is_array($responseModel)) {
|
||||
foreach ($responseModel as $modelName) {
|
||||
foreach ($this->models as $value) {
|
||||
if ($value->getType() === $modelName) {
|
||||
$usedModels[] = $modelName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$additionalMethod['responses'][] = [
|
||||
'code' => $response->getCode(),
|
||||
'model' => \array_map(fn ($m) => '#/components/schemas/' . $m, $response->getModel())
|
||||
'model' => \array_map(fn ($m) => '#/components/schemas/' . $m, $responseModel)
|
||||
];
|
||||
} else {
|
||||
$responseData = [
|
||||
@@ -267,7 +278,13 @@ class OpenAPI3 extends Format
|
||||
|
||||
// lets not assume stuff here!
|
||||
if ($response->getCode() !== 204) {
|
||||
$responseData['model'] = '#/components/schemas/' . $response->getModel();
|
||||
$responseData['model'] = '#/components/schemas/' . $responseModel;
|
||||
foreach ($this->models as $value) {
|
||||
if ($value->getType() === $responseModel) {
|
||||
$usedModels[] = $responseModel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$additionalMethod['responses'][] = $responseData;
|
||||
|
||||
@@ -264,11 +264,20 @@ class Swagger2 extends Format
|
||||
}
|
||||
|
||||
foreach ($methodObj->getResponses() as $response) {
|
||||
/** @var Response $response */
|
||||
if (\is_array($response->getModel())) {
|
||||
/** @var Response|array $response */
|
||||
$responseModel = $response->getModel();
|
||||
if (\is_array($responseModel)) {
|
||||
foreach ($responseModel as $modelName) {
|
||||
foreach ($this->models as $value) {
|
||||
if ($value->getType() === $modelName) {
|
||||
$usedModels[] = $modelName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$additionalMethod['responses'][] = [
|
||||
'code' => $response->getCode(),
|
||||
'model' => \array_map(fn ($m) => '#/definitions/' . $m, $response->getModel())
|
||||
'model' => \array_map(fn ($m) => '#/definitions/' . $m, $responseModel)
|
||||
];
|
||||
} else {
|
||||
$responseData = [
|
||||
@@ -277,7 +286,13 @@ class Swagger2 extends Format
|
||||
|
||||
// lets not assume stuff here!
|
||||
if ($response->getCode() !== 204) {
|
||||
$responseData['model'] = '#/definitions/' . $response->getModel();
|
||||
$responseData['model'] = '#/definitions/' . $responseModel;
|
||||
foreach ($this->models as $value) {
|
||||
if ($value->getType() === $responseModel) {
|
||||
$usedModels[] = $responseModel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$additionalMethod['responses'][] = $responseData;
|
||||
|
||||
@@ -41,6 +41,11 @@ trait AccountBase
|
||||
$this->assertNotEmpty($response['body']['accessedAt']);
|
||||
$this->assertArrayHasKey('targets', $response['body']);
|
||||
$this->assertEquals($email, $response['body']['targets'][0]['identifier']);
|
||||
$this->assertArrayNotHasKey('emailCanonical', $response['body']);
|
||||
$this->assertArrayNotHasKey('emailIsFree', $response['body']);
|
||||
$this->assertArrayNotHasKey('emailIsDisposable', $response['body']);
|
||||
$this->assertArrayNotHasKey('emailIsCorporate', $response['body']);
|
||||
$this->assertArrayNotHasKey('emailIsCanonical', $response['body']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
|
||||
Reference in New Issue
Block a user