mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6943d29ff2 | ||
|
|
46a0350742 | ||
|
|
48e0da014f | ||
|
|
fefb831d71 | ||
|
|
c453252c39 | ||
|
|
13a50ee6e5 | ||
|
|
43204a87cd | ||
|
|
dcf1b1c122 |
@@ -15,7 +15,6 @@ _APP_SYSTEM_TEAM_EMAIL=team@appwrite.io
|
||||
_APP_EMAIL_SECURITY=security@appwrite.io
|
||||
_APP_EMAIL_CERTIFICATES=certificates@appwrite.io
|
||||
_APP_SYSTEM_RESPONSE_FORMAT=
|
||||
_APP_CUSTOM_DOMAIN_DENY_LIST=
|
||||
_APP_OPTIONS_ABUSE=disabled
|
||||
_APP_OPTIONS_ROUTER_PROTECTION=disabled
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||
@@ -87,7 +86,6 @@ _APP_MAINTENANCE_RETENTION_CACHE=2592000
|
||||
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
|
||||
_APP_MAINTENANCE_RETENTION_ABUSE=86400
|
||||
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
|
||||
_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800
|
||||
_APP_USAGE_AGGREGATION_INTERVAL=30
|
||||
_APP_STATS_RESOURCES_INTERVAL=3600
|
||||
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
|
||||
|
||||
+8
-1
@@ -7,7 +7,6 @@ tasks:
|
||||
docker pull composer
|
||||
command: |
|
||||
docker run --rm --interactive --tty \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--volume $PWD:/app \
|
||||
composer install \
|
||||
--ignore-platform-reqs \
|
||||
@@ -24,3 +23,11 @@ vscode:
|
||||
extensions:
|
||||
- ms-azuretools.vscode-docker
|
||||
- zobo.php-intellisense
|
||||
|
||||
github:
|
||||
# https://www.gitpod.io/docs/prebuilds#github-specific-configuration
|
||||
prebuilds:
|
||||
# enable for pull requests coming from forks (defaults to false)
|
||||
pullRequestsFromForks: true
|
||||
# add a check to pull requests (defaults to true)
|
||||
addCheck: false
|
||||
|
||||
@@ -9,7 +9,6 @@ use Appwrite\Event\StatsResources;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Platform\Appwrite;
|
||||
use Appwrite\Runtimes\Runtimes;
|
||||
use Executor\Executor;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\CLI;
|
||||
@@ -256,8 +255,6 @@ CLI::setResource('logError', function (Registry $register) {
|
||||
};
|
||||
}, ['register']);
|
||||
|
||||
CLI::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
|
||||
|
||||
$platform = new Appwrite();
|
||||
$platform->init(Service::TYPE_TASK);
|
||||
|
||||
|
||||
@@ -1038,7 +1038,7 @@ return [
|
||||
'$id' => ID::custom('providerUid'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 2048, // Decrease to 128 as in index length?
|
||||
'size' => 2048,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
@@ -1107,14 +1107,14 @@ return [
|
||||
'$id' => ID::custom('_key_userInternalId_provider_providerUid'),
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'attributes' => ['userInternalId', 'provider', 'providerUid'],
|
||||
'lengths' => [11, 128, 128], // providerUid is length 2000!
|
||||
'lengths' => [11, 128, 128],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_provider_providerUid'),
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'attributes' => ['provider', 'providerUid'],
|
||||
'lengths' => [128, 128], // providerUid is length 2000!
|
||||
'lengths' => [128, 128],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
|
||||
@@ -142,16 +142,6 @@ return [
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'figma' => [
|
||||
'name' => 'Figma',
|
||||
'developers' => 'https://www.figma.com/developers/api#oauth2',
|
||||
'icon' => 'icon-figma',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'github' => [
|
||||
'name' => 'GitHub',
|
||||
'developers' => 'https://developer.github.com/',
|
||||
|
||||
+65
-1
@@ -3,8 +3,72 @@
|
||||
return [
|
||||
'default' => [
|
||||
'$id' => 'default',
|
||||
'name' => 'default',
|
||||
'name' => 'Frankfurt',
|
||||
'disabled' => false,
|
||||
'flag' => 'de',
|
||||
'default' => true,
|
||||
],
|
||||
'fra' => [
|
||||
'$id' => 'fra',
|
||||
'name' => 'Frankfurt',
|
||||
'disabled' => false,
|
||||
'flag' => 'de',
|
||||
'default' => true,
|
||||
],
|
||||
'nyc' => [
|
||||
'$id' => 'nyc',
|
||||
'name' => 'New York',
|
||||
'disabled' => true,
|
||||
'flag' => 'us',
|
||||
'default' => true,
|
||||
],
|
||||
'sfo' => [
|
||||
'$id' => 'sfo',
|
||||
'name' => 'San Francisco',
|
||||
'disabled' => true,
|
||||
'flag' => 'us',
|
||||
'default' => true,
|
||||
],
|
||||
'blr' => [
|
||||
'$id' => 'blr',
|
||||
'name' => 'Bengaluru',
|
||||
'disabled' => true,
|
||||
'flag' => 'in',
|
||||
'default' => true,
|
||||
],
|
||||
'lon' => [
|
||||
'$id' => 'lon',
|
||||
'name' => 'London',
|
||||
'disabled' => true,
|
||||
'flag' => 'gb',
|
||||
'default' => true,
|
||||
],
|
||||
'ams' => [
|
||||
'$id' => 'ams',
|
||||
'name' => 'Amsterdam',
|
||||
'disabled' => true,
|
||||
'flag' => 'nl',
|
||||
'default' => true,
|
||||
],
|
||||
'sgp' => [
|
||||
'$id' => 'sgp',
|
||||
'name' => 'Singapore',
|
||||
'disabled' => true,
|
||||
'flag' => 'sg',
|
||||
'default' => true,
|
||||
],
|
||||
'tor' => [
|
||||
'$id' => 'tor',
|
||||
'name' => 'Toronto',
|
||||
'disabled' => true,
|
||||
'flag' => 'ca',
|
||||
'default' => true,
|
||||
],
|
||||
'syd' => [
|
||||
'$id' => 'syd',
|
||||
'name' => 'Sydney',
|
||||
'disabled' => true,
|
||||
'flag' => 'au',
|
||||
'default' => true,
|
||||
],
|
||||
];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -1902,7 +1902,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
@@ -1922,7 +1922,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
@@ -2779,7 +2778,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
@@ -2799,7 +2798,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -1917,7 +1917,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
@@ -1937,7 +1937,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
@@ -2787,7 +2786,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
@@ -2807,7 +2806,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
@@ -19058,7 +19056,8 @@
|
||||
"description": "Project Region.",
|
||||
"x-example": "default",
|
||||
"enum": [
|
||||
"default"
|
||||
"default",
|
||||
"fra"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -20881,7 +20880,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -2464,7 +2464,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
@@ -2484,7 +2484,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -2028,7 +2028,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "amazon",
|
||||
@@ -2047,7 +2047,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
@@ -2933,7 +2932,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "amazon",
|
||||
@@ -2952,7 +2951,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -2059,7 +2059,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "amazon",
|
||||
@@ -2078,7 +2078,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
@@ -2957,7 +2956,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "amazon",
|
||||
@@ -2976,7 +2975,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
@@ -19524,7 +19522,8 @@
|
||||
"default": "default",
|
||||
"x-example": "default",
|
||||
"enum": [
|
||||
"default"
|
||||
"default",
|
||||
"fra"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
@@ -21352,7 +21351,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.1",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
@@ -2628,7 +2628,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "amazon",
|
||||
@@ -2647,7 +2647,6 @@
|
||||
"dropbox",
|
||||
"etsy",
|
||||
"facebook",
|
||||
"figma",
|
||||
"github",
|
||||
"gitlab",
|
||||
"google",
|
||||
|
||||
@@ -79,15 +79,6 @@ return [
|
||||
'question' => 'Enter your Appwrite hostname',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_CUSTOM_DOMAIN_DENY_LIST',
|
||||
'description' => 'List of reserved or prohibited domains when configuring custom domains.',
|
||||
'introduction' => '',
|
||||
'default' => 'example.com,test.com,app.example.com',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN_FUNCTIONS',
|
||||
'description' => 'A domain to use for function preview URLs. Setting to empty turns off function preview URLs.',
|
||||
@@ -1057,22 +1048,13 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_AUDIT',
|
||||
'description' => 'The maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).',
|
||||
'description' => 'IThe maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).',
|
||||
'introduction' => '0.7.0',
|
||||
'default' => '1209600',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE',
|
||||
'description' => 'The maximum duration (in seconds) upto which to retain console audit logs. The default value is 15778800 seconds (6 months).',
|
||||
'introduction' => '1.6.2',
|
||||
'default' => '15778800',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_ABUSE',
|
||||
'description' => 'The maximum duration (in seconds) upto which to retain abuse logs. The default value is 86400 seconds (1 day).',
|
||||
|
||||
+301
-293
File diff suppressed because it is too large
Load Diff
@@ -3355,7 +3355,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
||||
$processDocument($collection, $document);
|
||||
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations)
|
||||
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations)
|
||||
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection
|
||||
|
||||
@@ -3520,7 +3520,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
||||
}
|
||||
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations)
|
||||
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
|
||||
|
||||
$response->addHeader('X-Debug-Operations', $operations);
|
||||
@@ -3661,7 +3661,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
||||
$processDocument($collection, $document);
|
||||
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations)
|
||||
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
|
||||
|
||||
$response->addHeader('X-Debug-Operations', $operations);
|
||||
@@ -3959,7 +3959,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
||||
$setCollection($collection, $newDocument);
|
||||
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
|
||||
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations)
|
||||
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations);
|
||||
|
||||
$response->addHeader('X-Debug-Operations', $operations);
|
||||
|
||||
@@ -295,7 +295,7 @@ App::post('/v1/functions')
|
||||
|
||||
$schedule = Authorization::skip(
|
||||
fn () => $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'), // Todo replace with projects region
|
||||
'resourceType' => 'function',
|
||||
'resourceId' => $function->getId(),
|
||||
'resourceInternalId' => $function->getInternalId(),
|
||||
@@ -869,8 +869,7 @@ App::put('/v1/functions/:functionId')
|
||||
->inject('queueForBuilds')
|
||||
->inject('dbForPlatform')
|
||||
->inject('gitHub')
|
||||
->inject('executor')
|
||||
->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github, Executor $executor) use ($redeployVcs) {
|
||||
->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) use ($redeployVcs) {
|
||||
// TODO: If only branch changes, re-deploy
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
@@ -973,6 +972,7 @@ App::put('/v1/functions/:functionId')
|
||||
|
||||
// Enforce Cold Start if spec limits change.
|
||||
if ($function->getAttribute('specification') !== $specification && !empty($function->getAttribute('deployment'))) {
|
||||
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
|
||||
try {
|
||||
$executor->deleteRuntime($project->getId(), $function->getAttribute('deployment'));
|
||||
} catch (\Throwable $th) {
|
||||
@@ -1278,8 +1278,7 @@ App::post('/v1/functions/:functionId/deployments')
|
||||
->inject('deviceForFunctions')
|
||||
->inject('deviceForLocal')
|
||||
->inject('queueForBuilds')
|
||||
->inject('plan')
|
||||
->action(function (string $functionId, ?string $entrypoint, ?string $commands, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Event $queueForEvents, Document $project, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds, array $plan) {
|
||||
->action(function (string $functionId, ?string $entrypoint, ?string $commands, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Event $queueForEvents, Document $project, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds) {
|
||||
|
||||
$activate = \strval($activate) === 'true' || \strval($activate) === '1';
|
||||
|
||||
@@ -1312,14 +1311,8 @@ App::post('/v1/functions/:functionId/deployments')
|
||||
throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent');
|
||||
}
|
||||
|
||||
$functionSizeLimit = (int) System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000');
|
||||
|
||||
if (isset($plan['functionSize'])) {
|
||||
$functionSizeLimit = $plan['functionSize'] * 1000 * 1000;
|
||||
}
|
||||
|
||||
$fileExt = new FileExt([FileExt::TYPE_GZIP]);
|
||||
$fileSizeValidator = new FileSize($functionSizeLimit);
|
||||
$fileSizeValidator = new FileSize(System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000'));
|
||||
$upload = new Upload();
|
||||
|
||||
// Make sure we handle a single file and multiple files the same way
|
||||
@@ -1786,8 +1779,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId/build')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('queueForEvents')
|
||||
->inject('executor')
|
||||
->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Executor $executor) {
|
||||
->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $queueForEvents) {
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
@@ -1842,6 +1834,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId/build')
|
||||
$dbForProject->purgeCachedDocument('deployments', $deployment->getId());
|
||||
|
||||
try {
|
||||
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
|
||||
$executor->deleteRuntime($project->getId(), $deploymentId . "-build");
|
||||
} catch (\Throwable $th) {
|
||||
// Don't throw if the deployment doesn't exist
|
||||
@@ -1893,9 +1886,8 @@ App::post('/v1/functions/:functionId/executions')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->action(function (string $functionId, string $body, mixed $async, string $path, string $method, mixed $headers, ?string $scheduledAt, Response $response, Request $request, Document $project, Database $dbForProject, Database $dbForPlatform, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb) {
|
||||
->action(function (string $functionId, string $body, mixed $async, string $path, string $method, mixed $headers, ?string $scheduledAt, Response $response, Request $request, Document $project, Database $dbForProject, Database $dbForPlatform, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb) {
|
||||
$async = \strval($async) === 'true' || \strval($async) === '1';
|
||||
|
||||
if (!$async && !is_null($scheduledAt)) {
|
||||
@@ -2087,7 +2079,7 @@ App::post('/v1/functions/:functionId/executions')
|
||||
];
|
||||
|
||||
$schedule = $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'resourceType' => ScheduleExecutions::getSupportedResource(),
|
||||
'resourceId' => $execution->getId(),
|
||||
'resourceInternalId' => $execution->getInternalId(),
|
||||
@@ -2168,6 +2160,7 @@ App::post('/v1/functions/:functionId/executions')
|
||||
]);
|
||||
|
||||
/** Execute function */
|
||||
$executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST'));
|
||||
try {
|
||||
$version = $function->getAttribute('version', 'v2');
|
||||
$command = $runtime['startCommand'];
|
||||
|
||||
@@ -2936,7 +2936,7 @@ App::post('/v1/messaging/messages/email')
|
||||
break;
|
||||
case MessageStatus::SCHEDULED:
|
||||
$schedule = $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'resourceType' => 'message',
|
||||
'resourceId' => $message->getId(),
|
||||
'resourceInternalId' => $message->getInternalId(),
|
||||
@@ -3058,7 +3058,7 @@ App::post('/v1/messaging/messages/sms')
|
||||
break;
|
||||
case MessageStatus::SCHEDULED:
|
||||
$schedule = $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'resourceType' => 'message',
|
||||
'resourceId' => $message->getId(),
|
||||
'resourceInternalId' => $message->getInternalId(),
|
||||
@@ -3275,7 +3275,7 @@ App::post('/v1/messaging/messages/push')
|
||||
break;
|
||||
case MessageStatus::SCHEDULED:
|
||||
$schedule = $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'resourceType' => 'message',
|
||||
'resourceId' => $message->getId(),
|
||||
'resourceInternalId' => $message->getInternalId(),
|
||||
@@ -3661,7 +3661,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
|
||||
|
||||
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
|
||||
$schedule = $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'resourceType' => 'message',
|
||||
'resourceId' => $message->getId(),
|
||||
'resourceInternalId' => $message->getInternalId(),
|
||||
@@ -3862,7 +3862,7 @@ App::patch('/v1/messaging/messages/sms/:messageId')
|
||||
|
||||
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
|
||||
$schedule = $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'resourceType' => 'message',
|
||||
'resourceId' => $message->getId(),
|
||||
'resourceInternalId' => $message->getInternalId(),
|
||||
@@ -4035,7 +4035,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||
|
||||
if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) {
|
||||
$schedule = $dbForPlatform->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'resourceType' => 'message',
|
||||
'resourceId' => $message->getId(),
|
||||
'resourceInternalId' => $message->getInternalId(),
|
||||
|
||||
@@ -408,7 +408,6 @@ App::get('/v1/migrations/appwrite/report')
|
||||
->inject('project')
|
||||
->inject('user')
|
||||
->action(function (array $resources, string $endpoint, string $projectID, string $key, Response $response) {
|
||||
|
||||
$appwrite = new Appwrite($projectID, $endpoint, $key);
|
||||
|
||||
try {
|
||||
|
||||
@@ -138,14 +138,6 @@ App::post('/v1/projects')
|
||||
|
||||
$databases = Config::getParam('pools-database', []);
|
||||
|
||||
if ($region !== 'default') {
|
||||
$databaseKeys = System::getEnv('_APP_DATABASE_KEYS', '');
|
||||
$keys = explode(',', $databaseKeys);
|
||||
$databases = array_filter($keys, function ($value) use ($region) {
|
||||
return str_contains($value, $region);
|
||||
});
|
||||
}
|
||||
|
||||
$databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE');
|
||||
$index = \array_search($databaseOverride, $databases);
|
||||
if ($index !== false) {
|
||||
@@ -213,17 +205,17 @@ App::post('/v1/projects')
|
||||
$dsn = new DSN('mysql://' . $dsn);
|
||||
}
|
||||
|
||||
$adapter = $pools->get($dsn->getHost())->pop()->getResource();
|
||||
$dbForProject = new Database($adapter, $cache);
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
|
||||
|
||||
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
|
||||
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
|
||||
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
|
||||
$sharedTables = $sharedTablesV1 || $sharedTablesV2;
|
||||
|
||||
if (!$sharedTablesV2) {
|
||||
$adapter = $pools->get($dsn->getHost())->pop()->getResource();
|
||||
$dbForProject = new Database($adapter, $cache);
|
||||
|
||||
if ($sharedTables) {
|
||||
$dbForProject
|
||||
->setSharedTables(true)
|
||||
|
||||
@@ -55,25 +55,14 @@ App::post('/v1/proxy/rules')
|
||||
->inject('dbForPlatform')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $domain, string $resourceType, string $resourceId, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) {
|
||||
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
if ($domain === $mainDomain) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your main domain to specific resource. Please use subdomain or a different domain.');
|
||||
}
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS');
|
||||
$denyListDomains = System::getEnv('_APP_CUSTOM_DOMAIN_DENY_LIST');
|
||||
|
||||
if (!empty($denyListDomains)) {
|
||||
$functionsDomain .= ',' . $denyListDomains;
|
||||
}
|
||||
|
||||
$deniedDomains = array_map('trim', explode(',', $functionsDomain));
|
||||
|
||||
foreach ($deniedDomains as $deniedDomain) {
|
||||
if (str_ends_with($domain, $deniedDomain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or its subdomain to a specific resource. Please use a different domain.');
|
||||
}
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
if ($functionsDomain != '' && str_ends_with($domain, $functionsDomain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or it\'s subdomain to specific resource. Please use different domain.');
|
||||
}
|
||||
|
||||
if ($domain === 'localhost' || $domain === APP_HOSTNAME_INTERNAL) {
|
||||
|
||||
@@ -615,10 +615,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
$membership = ($isPrivilegedUser || $isAppUser) ?
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) :
|
||||
$dbForProject->createDocument('memberships', $membership);
|
||||
|
||||
if ($isPrivilegedUser || $isAppUser) {
|
||||
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
}
|
||||
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
|
||||
} elseif ($membership->getAttribute('confirm') === false) {
|
||||
$membership->setAttribute('secret', Auth::hash($secret));
|
||||
@@ -1034,6 +1031,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('roles', [], function (Document $project) {
|
||||
if ($project->getId() === 'console') {
|
||||
;
|
||||
$roles = array_keys(Config::getParam('roles', []));
|
||||
array_filter($roles, function ($role) {
|
||||
return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]);
|
||||
@@ -1045,10 +1043,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) {
|
||||
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
|
||||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
if ($team->isEmpty()) {
|
||||
@@ -1069,21 +1066,6 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
$isAppUser = Auth::isAppUser(Authorization::getRoles());
|
||||
$isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');
|
||||
|
||||
if ($project->getId() === 'console') {
|
||||
// Quick check: fetch up to 2 owners to determine if only one exists
|
||||
$ownersCount = $dbForProject->count(
|
||||
collection: 'memberships',
|
||||
queries: [Query::contains('roles', ['owner'])],
|
||||
max: 2
|
||||
);
|
||||
|
||||
// Prevent role change if there's only one owner left,
|
||||
// the requester is that owner, and the new `$roles` no longer include 'owner'!
|
||||
if ($ownersCount === 1 && $isOwner && !\in_array('owner', $roles)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'There must be at least one owner in the organization.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to modify roles');
|
||||
}
|
||||
|
||||
+14
-26
@@ -50,7 +50,7 @@ Config::setParam('domainVerification', false);
|
||||
Config::setParam('cookieDomain', 'localhost');
|
||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname)
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname)
|
||||
{
|
||||
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
|
||||
|
||||
@@ -72,19 +72,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
|
||||
if ($route->isEmpty()) {
|
||||
|
||||
$appDomainFunctionsFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', '');
|
||||
$appDomainFunctions = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
if (!empty($appDomainFunctionsFallback) && \str_ends_with($host, $appDomainFunctionsFallback)) {
|
||||
$appDomainFunctions = $appDomainFunctionsFallback;
|
||||
}
|
||||
|
||||
if ($host === $appDomainFunctions) {
|
||||
if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.');
|
||||
}
|
||||
|
||||
if (\str_ends_with($host, $appDomainFunctions)) {
|
||||
if (\str_ends_with($host, System::getEnv('_APP_DOMAIN_FUNCTIONS', ''))) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain is not connected to any Appwrite resource yet. Please configure custom domain or function domain to allow this request.');
|
||||
}
|
||||
|
||||
@@ -347,6 +339,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
]);
|
||||
|
||||
/** Execute function */
|
||||
$executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST'));
|
||||
try {
|
||||
$version = $function->getAttribute('version', 'v2');
|
||||
$command = $runtime['startCommand'];
|
||||
@@ -510,10 +503,9 @@ App::init()
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
@@ -521,7 +513,7 @@ App::init()
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
// Only run Router when external domain
|
||||
if ($host !== $mainDomain || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -750,12 +742,11 @@ App::options()
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->inject('project')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
@@ -763,7 +754,7 @@ App::options()
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
// Only run Router when external domain
|
||||
if ($host !== $mainDomain || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -880,18 +871,17 @@ App::error()
|
||||
if (!empty($providerConfig) && $error->getCode() >= 400 && $error->getCode() < 500) {
|
||||
// Register error logger
|
||||
try {
|
||||
$loggingProvider = new DSN($providerConfig);
|
||||
$loggingProvider = new DSN($providerConfig ?? '');
|
||||
$providerName = $loggingProvider->getScheme();
|
||||
|
||||
if (!empty($providerName) && $providerName === 'sentry') {
|
||||
$key = $loggingProvider->getPassword();
|
||||
$projectId = $loggingProvider->getUser() ?? '';
|
||||
$host = 'https://' . $loggingProvider->getHost();
|
||||
$sampleRate = $loggingProvider->getParam('sample', 0.01);
|
||||
|
||||
$adapter = new Sentry($projectId, $key, $host);
|
||||
$logger = new Logger($adapter);
|
||||
$logger->setSample($sampleRate);
|
||||
$logger->setSample(0.01);
|
||||
$publish = true;
|
||||
} else {
|
||||
throw new \Exception('Invalid experimental logging provider');
|
||||
@@ -1071,11 +1061,10 @@ App::get('/robots.txt')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) {
|
||||
$host = $request->getHostname() ?? '';
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
@@ -1083,7 +1072,7 @@ App::get('/robots.txt')
|
||||
$template = new View(__DIR__ . '/../views/general/robots.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname);
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1100,11 +1089,10 @@ App::get('/humans.txt')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) {
|
||||
$host = $request->getHostname() ?? '';
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
@@ -1112,7 +1100,7 @@ App::get('/humans.txt')
|
||||
$template = new View(__DIR__ . '/../views/general/humans.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname);
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -390,8 +390,7 @@ App::init()
|
||||
->inject('timelimit')
|
||||
->inject('mode')
|
||||
->inject('apiKey')
|
||||
->inject('plan')
|
||||
->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, string $mode, ?Key $apiKey, array $plan) use ($usageDatabaseListener, $eventDatabaseListener) {
|
||||
->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, string $mode, ?Key $apiKey) use ($usageDatabaseListener, $eventDatabaseListener) {
|
||||
|
||||
$route = $utopia->getRoute();
|
||||
|
||||
@@ -521,10 +520,6 @@ App::init()
|
||||
|
||||
$useCache = $route->getLabel('cache', false);
|
||||
if ($useCache) {
|
||||
$route = $utopia->match($request);
|
||||
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
|
||||
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser(Authorization::getRoles());
|
||||
|
||||
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
|
||||
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$cache = new Cache(
|
||||
@@ -534,10 +529,10 @@ App::init()
|
||||
$data = $cache->load($key, $timestamp);
|
||||
|
||||
if (!empty($data) && !$cacheLog->isEmpty()) {
|
||||
$parts = explode('/', $cacheLog->getAttribute('resourceType', ''));
|
||||
$parts = explode('/', $cacheLog->getAttribute('resourceType'));
|
||||
$type = $parts[0] ?? null;
|
||||
|
||||
if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) {
|
||||
if ($type === 'bucket') {
|
||||
$bucketId = $parts[1] ?? null;
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
@@ -578,10 +573,8 @@ App::init()
|
||||
$response
|
||||
->addHeader('Cache-Control', sprintf('private, max-age=%d', $timestamp))
|
||||
->addHeader('X-Appwrite-Cache', 'hit')
|
||||
->setContentType($cacheLog->getAttribute('mimeType'));
|
||||
if (!$isImageTransformation || !$isDisabled) {
|
||||
$response->send($data);
|
||||
}
|
||||
->setContentType($cacheLog->getAttribute('mimeType'))
|
||||
->send($data);
|
||||
} else {
|
||||
$response
|
||||
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||
|
||||
@@ -217,7 +217,7 @@ $register->set('pools', function () {
|
||||
return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
|
||||
return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array(
|
||||
PDO::ATTR_TIMEOUT => 3, // Seconds
|
||||
PDO::ATTR_PERSISTENT => false,
|
||||
PDO::ATTR_PERSISTENT => true,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => true,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => true
|
||||
|
||||
+56
-29
@@ -21,13 +21,13 @@ use Appwrite\Extend\Exception;
|
||||
use Appwrite\GraphQL\Schema;
|
||||
use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Executor\Executor;
|
||||
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
|
||||
use Utopia\App;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Adapter;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
@@ -39,7 +39,6 @@ use Utopia\Logger\Log;
|
||||
use Utopia\Pools\Group;
|
||||
use Utopia\Queue\Publisher;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Storage\Device\AWS;
|
||||
use Utopia\Storage\Device\Backblaze;
|
||||
use Utopia\Storage\Device\DOSpaces;
|
||||
use Utopia\Storage\Device\Linode;
|
||||
@@ -48,8 +47,6 @@ use Utopia\Storage\Device\S3;
|
||||
use Utopia\Storage\Device\Wasabi;
|
||||
use Utopia\Storage\Storage;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Telemetry\Adapter as Telemetry;
|
||||
use Utopia\Telemetry\Adapter\None as NoTelemetry;
|
||||
use Utopia\Validator\Hostname;
|
||||
use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub;
|
||||
|
||||
@@ -317,7 +314,7 @@ App::setResource('console', function () {
|
||||
return new Document(Config::getParam('console'));
|
||||
}, []);
|
||||
|
||||
App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) {
|
||||
App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project): Database {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $dbForPlatform;
|
||||
}
|
||||
@@ -359,6 +356,53 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform
|
||||
return $database;
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'project']);
|
||||
|
||||
App::setResource('useProjectDB', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) {
|
||||
/**
|
||||
* @template T
|
||||
* @param callable(Database): T $callback
|
||||
*/
|
||||
return function (callable $callback) use ($pools, $dbForPlatform, $cache, $project): mixed {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $callback($dbForPlatform);
|
||||
}
|
||||
|
||||
try {
|
||||
$dsn = new DSN($project->getAttribute('database'));
|
||||
} catch (\InvalidArgumentException) {
|
||||
// TODO: Temporary until all projects are using shared tables
|
||||
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
|
||||
}
|
||||
|
||||
return $pools
|
||||
->get($dsn->getHost())
|
||||
->use(function (Adapter $adapter) use ($callback, $cache, $project, $dsn) {
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$database
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', $project->getId())
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API)
|
||||
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
|
||||
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
if (\in_array($dsn->getHost(), $sharedTables)) {
|
||||
$database
|
||||
->setSharedTables(true)
|
||||
->setTenant($project->getInternalId())
|
||||
->setNamespace($dsn->getParam('namespace'));
|
||||
} else {
|
||||
$database
|
||||
->setSharedTables(false)
|
||||
->setTenant(null)
|
||||
->setNamespace('_' . $project->getInternalId());
|
||||
}
|
||||
|
||||
return $callback($database);
|
||||
});
|
||||
};
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'project']);
|
||||
|
||||
App::setResource('dbForPlatform', function (Group $pools, Cache $cache) {
|
||||
$dbAdapter = $pools
|
||||
->get('console')
|
||||
@@ -466,9 +510,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
};
|
||||
}, ['pools', 'cache']);
|
||||
|
||||
App::setResource('telemetry', fn () => new NoTelemetry());
|
||||
|
||||
App::setResource('cache', function (Group $pools, Telemetry $telemetry) {
|
||||
App::setResource('cache', function (Group $pools) {
|
||||
$list = Config::getParam('pools-cache', []);
|
||||
$adapters = [];
|
||||
|
||||
@@ -476,15 +518,12 @@ App::setResource('cache', function (Group $pools, Telemetry $telemetry) {
|
||||
$adapters[] = $pools
|
||||
->get($value)
|
||||
->pop()
|
||||
->getResource();
|
||||
->getResource()
|
||||
;
|
||||
}
|
||||
|
||||
$cache = new Cache(new Sharding($adapters));
|
||||
|
||||
$cache->setTelemetry($telemetry);
|
||||
|
||||
return $cache;
|
||||
}, ['pools', 'telemetry']);
|
||||
return new Cache(new Sharding($adapters));
|
||||
}, ['pools']);
|
||||
|
||||
App::setResource('redis', function () {
|
||||
$host = System::getEnv('_APP_REDIS_HOST', 'localhost');
|
||||
@@ -549,12 +588,7 @@ function getDevice(string $root, string $connection = ''): Device
|
||||
|
||||
switch ($device) {
|
||||
case Storage::DEVICE_S3:
|
||||
if (!empty($url)) {
|
||||
return new S3($root, $accessKey, $accessSecret, $url, $region, $acl);
|
||||
} else {
|
||||
return new AWS($root, $accessKey, $accessSecret, $bucket, $region, $acl);
|
||||
}
|
||||
// no break
|
||||
return new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl, $url);
|
||||
case STORAGE::DEVICE_DO_SPACES:
|
||||
$device = new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl);
|
||||
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
|
||||
@@ -581,12 +615,7 @@ function getDevice(string $root, string $connection = ''): Device
|
||||
$s3Bucket = System::getEnv('_APP_STORAGE_S3_BUCKET', '');
|
||||
$s3Acl = 'private';
|
||||
$s3EndpointUrl = System::getEnv('_APP_STORAGE_S3_ENDPOINT', '');
|
||||
if (!empty($s3EndpointUrl)) {
|
||||
return new S3($root, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl);
|
||||
} else {
|
||||
return new AWS($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
|
||||
}
|
||||
// no break
|
||||
return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl, $s3EndpointUrl);
|
||||
case Storage::DEVICE_DO_SPACES:
|
||||
$doSpacesAccessKey = System::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', '');
|
||||
$doSpacesSecretKey = System::getEnv('_APP_STORAGE_DO_SPACES_SECRET', '');
|
||||
@@ -841,5 +870,3 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key
|
||||
|
||||
return Key::decode($project, $key);
|
||||
}, ['request', 'project']);
|
||||
|
||||
App::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
|
||||
|
||||
@@ -148,7 +148,6 @@ $image = $this->getParam('image', '');
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_SMS_PROVIDER
|
||||
@@ -165,10 +164,11 @@ $image = $this->getParam('image', '');
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
|
||||
appwrite-console:
|
||||
<<: *x-logging
|
||||
container_name: appwrite-console
|
||||
image: <?php echo $organization; ?>/console:5.2.58
|
||||
image: <?php echo $organization; ?>/console:5.2.53
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
@@ -341,7 +341,6 @@ $image = $this->getParam('image', '');
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
@@ -653,7 +652,6 @@ $image = $this->getParam('image', '');
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
|
||||
|
||||
+7
-15
@@ -16,9 +16,10 @@ use Appwrite\Event\Migration;
|
||||
use Appwrite\Event\Realtime;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Event\StatsUsageDump;
|
||||
/** remove */
|
||||
/** /remove */
|
||||
use Appwrite\Event\Webhook;
|
||||
use Appwrite\Platform\Appwrite;
|
||||
use Executor\Executor;
|
||||
use Swoole\Runtime;
|
||||
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
@@ -214,18 +215,15 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
}, ['pools', 'cache']);
|
||||
|
||||
Server::setResource('abuseRetention', function () {
|
||||
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day
|
||||
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400);
|
||||
});
|
||||
|
||||
Server::setResource('auditRetention', function (Document $project) {
|
||||
if ($project->getId() === 'console') {
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE', 15778800)); // 6 months
|
||||
}
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600)); // 14 days
|
||||
}, ['project']);
|
||||
Server::setResource('auditRetention', function () {
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600));
|
||||
});
|
||||
|
||||
Server::setResource('executionRetention', function () {
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600)); // 14 days
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600));
|
||||
});
|
||||
|
||||
Server::setResource('cache', function (Registry $register) {
|
||||
@@ -267,10 +265,6 @@ Server::setResource('timelimit', function (\Redis $redis) {
|
||||
|
||||
Server::setResource('log', fn () => new Log());
|
||||
|
||||
Server::setResource('plan', function (array $plan = []) {
|
||||
return [];
|
||||
});
|
||||
|
||||
Server::setResource('publisher', function (Group $pools) {
|
||||
return $pools->get('publisher')->pop()->getResource();
|
||||
}, ['pools']);
|
||||
@@ -418,8 +412,6 @@ Server::setResource('logError', function (Registry $register, Document $project)
|
||||
};
|
||||
}, ['register', 'project']);
|
||||
|
||||
Server::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
|
||||
|
||||
$pools = $register->get('pools');
|
||||
$platform = new Appwrite();
|
||||
$args = $platform->getEnv('argv');
|
||||
|
||||
+4
-4
@@ -51,11 +51,11 @@
|
||||
"utopia-php/cache": "0.12.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.64.*",
|
||||
"utopia-php/database": "0.61.*",
|
||||
"utopia-php/domains": "0.5.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/fetch": "0.4.*",
|
||||
"utopia-php/fetch": "0.3.*",
|
||||
"utopia-php/image": "0.8.*",
|
||||
"utopia-php/locale": "0.4.*",
|
||||
"utopia-php/logger": "0.6.*",
|
||||
@@ -63,7 +63,7 @@
|
||||
"utopia-php/migration": "0.8.*",
|
||||
"utopia-php/orchestration": "0.9.*",
|
||||
"utopia-php/platform": "0.7.*",
|
||||
"utopia-php/pools": "0.8.*",
|
||||
"utopia-php/pools": "0.7.*",
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
"utopia-php/queue": "0.9.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
@@ -72,7 +72,7 @@
|
||||
"utopia-php/system": "0.9.*",
|
||||
"utopia-php/telemetry": "0.1.*",
|
||||
"utopia-php/vcs": "0.9.*",
|
||||
"utopia-php/websocket": "0.3.*",
|
||||
"utopia-php/websocket": "0.1.*",
|
||||
"matomo/device-detector": "6.1.*",
|
||||
"dragonmantank/cron-expression": "3.3.2",
|
||||
"phpmailer/phpmailer": "6.9.1",
|
||||
|
||||
Generated
+381
-104
@@ -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": "6a54c8bc4f9f14cd3883f55880864630",
|
||||
"content-hash": "e0d7f21b681e4591144fec16c4f0d6aa",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -709,16 +709,16 @@
|
||||
},
|
||||
{
|
||||
"name": "google/protobuf",
|
||||
"version": "v4.30.2",
|
||||
"version": "v4.30.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/protocolbuffers/protobuf-php.git",
|
||||
"reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced"
|
||||
"reference": "f29ba8a30dfd940efb3a8a75dc44446539101f24"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/a4c4d8565b40b9f76debc9dfeb221412eacb8ced",
|
||||
"reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced",
|
||||
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/f29ba8a30dfd940efb3a8a75dc44446539101f24",
|
||||
"reference": "f29ba8a30dfd940efb3a8a75dc44446539101f24",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -747,9 +747,68 @@
|
||||
"proto"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.30.2"
|
||||
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.30.1"
|
||||
},
|
||||
"time": "2025-03-26T18:01:50+00:00"
|
||||
"time": "2025-03-13T21:08:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Jean85/pretty-package-versions.git",
|
||||
"reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
|
||||
"reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.1.0",
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"jean85/composer-provided-replaced-stub-package": "^1.0",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpunit/phpunit": "^7.5|^8.5|^9.6",
|
||||
"vimeo/psalm": "^4.3 || ^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Jean85\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alessandro Lai",
|
||||
"email": "alessandro.lai85@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to get pretty versions strings of installed dependencies",
|
||||
"keywords": [
|
||||
"composer",
|
||||
"package",
|
||||
"release",
|
||||
"versions"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
|
||||
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0"
|
||||
},
|
||||
"time": "2024-11-18T16:19:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
@@ -909,6 +968,75 @@
|
||||
},
|
||||
"time": "2023-10-02T10:01:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mongodb/mongodb",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mongodb/mongo-php-library.git",
|
||||
"reference": "b0bbd657f84219212487d01a8ffe93a789e1e488"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/b0bbd657f84219212487d01a8ffe93a789e1e488",
|
||||
"reference": "b0bbd657f84219212487d01a8ffe93a789e1e488",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mongodb": "^1.11.0",
|
||||
"jean85/pretty-package-versions": "^1.2 || ^2.0.1",
|
||||
"php": "^7.1 || ^8.0",
|
||||
"symfony/polyfill-php80": "^1.19"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.6",
|
||||
"symfony/phpunit-bridge": "^5.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.10.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"MongoDB\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Braun",
|
||||
"email": "andreas.braun@mongodb.com"
|
||||
},
|
||||
{
|
||||
"name": "Jeremy Mikola",
|
||||
"email": "jmikola@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "MongoDB driver library",
|
||||
"homepage": "https://jira.mongodb.org/browse/PHPLIB",
|
||||
"keywords": [
|
||||
"database",
|
||||
"driver",
|
||||
"mongodb",
|
||||
"persistence"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mongodb/mongo-php-library/issues",
|
||||
"source": "https://github.com/mongodb/mongo-php-library/tree/1.10.0"
|
||||
},
|
||||
"time": "2021-10-20T22:22:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mustangostang/spyc",
|
||||
"version": "0.6.3",
|
||||
@@ -1365,16 +1493,16 @@
|
||||
},
|
||||
{
|
||||
"name": "open-telemetry/sdk",
|
||||
"version": "1.2.3",
|
||||
"version": "1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opentelemetry-php/sdk.git",
|
||||
"reference": "0e7804c176c4b09d95b7985400aa38ce544cb7fc"
|
||||
"reference": "37eec0fe47ddd627911f318f29b6cd48196be0c0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/0e7804c176c4b09d95b7985400aa38ce544cb7fc",
|
||||
"reference": "0e7804c176c4b09d95b7985400aa38ce544cb7fc",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/37eec0fe47ddd627911f318f29b6cd48196be0c0",
|
||||
"reference": "37eec0fe47ddd627911f318f29b6cd48196be0c0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1451,7 +1579,7 @@
|
||||
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
|
||||
"source": "https://github.com/open-telemetry/opentelemetry-php"
|
||||
},
|
||||
"time": "2025-04-08T09:55:41+00:00"
|
||||
"time": "2025-01-29T21:40:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "open-telemetry/sem-conv",
|
||||
@@ -2243,16 +2371,16 @@
|
||||
},
|
||||
{
|
||||
"name": "ramsey/collection",
|
||||
"version": "2.1.1",
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/collection.git",
|
||||
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
|
||||
"reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
|
||||
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
|
||||
"reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2313,9 +2441,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/collection/issues",
|
||||
"source": "https://github.com/ramsey/collection/tree/2.1.1"
|
||||
"source": "https://github.com/ramsey/collection/tree/2.1.0"
|
||||
},
|
||||
"time": "2025-03-22T05:38:12+00:00"
|
||||
"time": "2025-03-02T04:48:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
@@ -2804,6 +2932,86 @@
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.31.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php80\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ion Bazan",
|
||||
"email": "ion.bazan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php82",
|
||||
"version": "v1.31.0",
|
||||
@@ -2965,16 +3173,16 @@
|
||||
},
|
||||
{
|
||||
"name": "tbachert/spi",
|
||||
"version": "v1.0.3",
|
||||
"version": "v1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Nevay/spi.git",
|
||||
"reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a"
|
||||
"reference": "2ddfaf815dafb45791a61b08170de8d583c16062"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a",
|
||||
"reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a",
|
||||
"url": "https://api.github.com/repos/Nevay/spi/zipball/2ddfaf815dafb45791a61b08170de8d583c16062",
|
||||
"reference": "2ddfaf815dafb45791a61b08170de8d583c16062",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3011,9 +3219,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Nevay/spi/issues",
|
||||
"source": "https://github.com/Nevay/spi/tree/v1.0.3"
|
||||
"source": "https://github.com/Nevay/spi/tree/v1.0.2"
|
||||
},
|
||||
"time": "2025-04-02T19:38:14+00:00"
|
||||
"time": "2024-10-04T16:36:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "thecodingmachine/safe",
|
||||
@@ -3497,16 +3705,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.64.2",
|
||||
"version": "0.61.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "dc9c4a68c93e8bea2dfaa76d1ba308be539998bd"
|
||||
"reference": "349fbdf4bc088f7775c7dfb8b80239a617a88436"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/dc9c4a68c93e8bea2dfaa76d1ba308be539998bd",
|
||||
"reference": "dc9c4a68c93e8bea2dfaa76d1ba308be539998bd",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/349fbdf4bc088f7775c7dfb8b80239a617a88436",
|
||||
"reference": "349fbdf4bc088f7775c7dfb8b80239a617a88436",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3515,7 +3723,7 @@
|
||||
"php": ">=8.1",
|
||||
"utopia-php/cache": "0.12.*",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/pools": "0.8.*"
|
||||
"utopia-php/mongo": "0.3.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "1.23.*",
|
||||
@@ -3547,9 +3755,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.64.2"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.61.2"
|
||||
},
|
||||
"time": "2025-04-09T07:53:05+00:00"
|
||||
"time": "2025-03-15T11:47:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
@@ -3660,16 +3868,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/fetch",
|
||||
"version": "0.4.1",
|
||||
"version": "0.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/fetch.git",
|
||||
"reference": "65095dac14037db0c822fb5e209e5bd3187a0303"
|
||||
"reference": "524dd50afa8c64670c4fb18f1df4db9b5bb4b3d0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/fetch/zipball/65095dac14037db0c822fb5e209e5bd3187a0303",
|
||||
"reference": "65095dac14037db0c822fb5e209e5bd3187a0303",
|
||||
"url": "https://api.github.com/repos/utopia-php/fetch/zipball/524dd50afa8c64670c4fb18f1df4db9b5bb4b3d0",
|
||||
"reference": "524dd50afa8c64670c4fb18f1df4db9b5bb4b3d0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3693,9 +3901,9 @@
|
||||
"description": "A simple library that provides an interface for making HTTP Requests.",
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/fetch/issues",
|
||||
"source": "https://github.com/utopia-php/fetch/tree/0.4.1"
|
||||
"source": "https://github.com/utopia-php/fetch/tree/0.3.1"
|
||||
},
|
||||
"time": "2025-04-14T07:34:27+00:00"
|
||||
"time": "2025-03-05T18:08:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/framework",
|
||||
@@ -3746,16 +3954,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/image",
|
||||
"version": "0.8.2",
|
||||
"version": "0.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/image.git",
|
||||
"reference": "6c736965177f9a9e71311e22b80cfa88511768e9"
|
||||
"reference": "dcae5b1c6deb3ff6865f4e68f012b3709c289bca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/image/zipball/6c736965177f9a9e71311e22b80cfa88511768e9",
|
||||
"reference": "6c736965177f9a9e71311e22b80cfa88511768e9",
|
||||
"url": "https://api.github.com/repos/utopia-php/image/zipball/dcae5b1c6deb3ff6865f4e68f012b3709c289bca",
|
||||
"reference": "dcae5b1c6deb3ff6865f4e68f012b3709c289bca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3789,9 +3997,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/image/issues",
|
||||
"source": "https://github.com/utopia-php/image/tree/0.8.2"
|
||||
"source": "https://github.com/utopia-php/image/tree/0.8.0"
|
||||
},
|
||||
"time": "2025-04-08T11:31:45+00:00"
|
||||
"time": "2025-02-20T11:49:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/locale",
|
||||
@@ -3951,16 +4159,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/migration.git",
|
||||
"reference": "84163e16edc0b2e64c34ad7b7c4cc5f05d762daf"
|
||||
"reference": "36ec7af2e6bf78de5d86e1b0a953fd7dcdf69dab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/84163e16edc0b2e64c34ad7b7c4cc5f05d762daf",
|
||||
"reference": "84163e16edc0b2e64c34ad7b7c4cc5f05d762daf",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/36ec7af2e6bf78de5d86e1b0a953fd7dcdf69dab",
|
||||
"reference": "36ec7af2e6bf78de5d86e1b0a953fd7dcdf69dab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3968,7 +4176,7 @@
|
||||
"ext-curl": "*",
|
||||
"ext-openssl": "*",
|
||||
"php": ">=8.1",
|
||||
"utopia-php/database": "0.*.*",
|
||||
"utopia-php/database": "0.61.*",
|
||||
"utopia-php/dsn": "0.2.*",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/storage": "0.18.*"
|
||||
@@ -4001,9 +4209,69 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/migration/issues",
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.8.6"
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.8.1"
|
||||
},
|
||||
"time": "2025-04-14T08:22:09+00:00"
|
||||
"time": "2025-03-18T07:48:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/mongo",
|
||||
"version": "0.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/mongo.git",
|
||||
"reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/mongo/zipball/52326a9a43e2d27ff0c15c48ba746dacbe9a7aee",
|
||||
"reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mongodb": "*",
|
||||
"mongodb/mongodb": "1.10.0",
|
||||
"php": ">=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.14",
|
||||
"laravel/pint": "1.2.*",
|
||||
"phpstan/phpstan": "1.8.*",
|
||||
"phpunit/phpunit": "^9.4",
|
||||
"swoole/ide-helper": "4.8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Utopia\\Mongo\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Eldad Fux",
|
||||
"email": "eldad@appwrite.io"
|
||||
},
|
||||
{
|
||||
"name": "Wess",
|
||||
"email": "wess@appwrite.io"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to manage Mongo database",
|
||||
"keywords": [
|
||||
"database",
|
||||
"mongo",
|
||||
"php",
|
||||
"upf",
|
||||
"utopia"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/mongo/issues",
|
||||
"source": "https://github.com/utopia-php/mongo/tree/0.3.1"
|
||||
},
|
||||
"time": "2023-09-01T17:25:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/orchestration",
|
||||
@@ -4107,16 +4375,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/pools",
|
||||
"version": "0.8.0",
|
||||
"version": "0.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/pools.git",
|
||||
"reference": "60733929dc328e7ea47e800579c8bbf0d49df5ba"
|
||||
"reference": "ad64d45afda08ec8b29e2642a8d18075964d40bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/pools/zipball/60733929dc328e7ea47e800579c8bbf0d49df5ba",
|
||||
"reference": "60733929dc328e7ea47e800579c8bbf0d49df5ba",
|
||||
"url": "https://api.github.com/repos/utopia-php/pools/zipball/ad64d45afda08ec8b29e2642a8d18075964d40bf",
|
||||
"reference": "ad64d45afda08ec8b29e2642a8d18075964d40bf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4153,9 +4421,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/pools/issues",
|
||||
"source": "https://github.com/utopia-php/pools/tree/0.8.0"
|
||||
"source": "https://github.com/utopia-php/pools/tree/0.7.0"
|
||||
},
|
||||
"time": "2025-03-19T10:22:03+00:00"
|
||||
"time": "2025-03-18T03:55:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/preloader",
|
||||
@@ -4212,23 +4480,23 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/queue",
|
||||
"version": "0.9.1",
|
||||
"version": "0.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/queue.git",
|
||||
"reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32"
|
||||
"reference": "077075f1d57afa430f76c35ed3bf4616e0eee8e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32",
|
||||
"reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/077075f1d57afa430f76c35ed3bf4616e0eee8e7",
|
||||
"reference": "077075f1d57afa430f76c35ed3bf4616e0eee8e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3",
|
||||
"php-amqplib/php-amqplib": "^3.7",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/fetch": "0.4.*",
|
||||
"utopia-php/fetch": "^0.3.0",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/telemetry": "0.1.*"
|
||||
},
|
||||
@@ -4271,9 +4539,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/queue/issues",
|
||||
"source": "https://github.com/utopia-php/queue/tree/0.9.1"
|
||||
"source": "https://github.com/utopia-php/queue/tree/0.9.0"
|
||||
},
|
||||
"time": "2025-03-28T19:49:36+00:00"
|
||||
"time": "2025-03-13T12:22:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/registry",
|
||||
@@ -4386,16 +4654,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/swoole",
|
||||
"version": "0.8.3",
|
||||
"version": "0.8.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/swoole.git",
|
||||
"reference": "1af73dd3e73987cf729c7db399054e4a70befd99"
|
||||
"reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/1af73dd3e73987cf729c7db399054e4a70befd99",
|
||||
"reference": "1af73dd3e73987cf729c7db399054e4a70befd99",
|
||||
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4",
|
||||
"reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4431,9 +4699,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/swoole/issues",
|
||||
"source": "https://github.com/utopia-php/swoole/tree/0.8.3"
|
||||
"source": "https://github.com/utopia-php/swoole/tree/0.8.2"
|
||||
},
|
||||
"time": "2025-03-26T10:09:05+00:00"
|
||||
"time": "2024-02-01T14:54:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/system",
|
||||
@@ -4593,28 +4861,27 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/websocket",
|
||||
"version": "0.3.0",
|
||||
"version": "0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/websocket.git",
|
||||
"reference": "629e53640b108eab43c7cc9ab375efade8622d43"
|
||||
"reference": "51fcb86171400d8aa40d76c54593481fd273dab5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/websocket/zipball/629e53640b108eab43c7cc9ab375efade8622d43",
|
||||
"reference": "629e53640b108eab43c7cc9ab375efade8622d43",
|
||||
"url": "https://api.github.com/repos/utopia-php/websocket/zipball/51fcb86171400d8aa40d76c54593481fd273dab5",
|
||||
"reference": "51fcb86171400d8aa40d76c54593481fd273dab5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.15",
|
||||
"phpstan/phpstan": "^1.12",
|
||||
"phpunit/phpunit": "^9.5.5",
|
||||
"swoole/ide-helper": "5.1.2",
|
||||
"swoole/ide-helper": "4.6.6",
|
||||
"textalk/websocket": "1.5.2",
|
||||
"workerman/workerman": "4.1.*"
|
||||
"vimeo/psalm": "^4.8.1",
|
||||
"workerman/workerman": "^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -4626,6 +4893,16 @@
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Eldad Fux",
|
||||
"email": "eldad@appwrite.io"
|
||||
},
|
||||
{
|
||||
"name": "Torsten Dittmann",
|
||||
"email": "torsten@appwrite.io"
|
||||
}
|
||||
],
|
||||
"description": "A simple abstraction for WebSocket servers.",
|
||||
"keywords": [
|
||||
"framework",
|
||||
@@ -4636,9 +4913,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/websocket/issues",
|
||||
"source": "https://github.com/utopia-php/websocket/tree/0.3.0"
|
||||
"source": "https://github.com/utopia-php/websocket/tree/0.1.0"
|
||||
},
|
||||
"time": "2025-03-28T01:11:13+00:00"
|
||||
"time": "2021-12-20T10:50:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
@@ -4767,16 +5044,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "0.40.11",
|
||||
"version": "0.40.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "0ec5f4a60c15e33e208bc3444ba6148b1d0f0027"
|
||||
"reference": "dbb45a5db22cdc3368fe2573c07ba6088f188fa4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0ec5f4a60c15e33e208bc3444ba6148b1d0f0027",
|
||||
"reference": "0ec5f4a60c15e33e208bc3444ba6148b1d0f0027",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/dbb45a5db22cdc3368fe2573c07ba6088f188fa4",
|
||||
"reference": "dbb45a5db22cdc3368fe2573c07ba6088f188fa4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4812,9 +5089,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.40.11"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.9"
|
||||
},
|
||||
"time": "2025-03-26T10:53:16+00:00"
|
||||
"time": "2025-03-17T18:39:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
@@ -5041,16 +5318,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/pint",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.21.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/pint.git",
|
||||
"reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36"
|
||||
"reference": "370772e7d9e9da087678a0edf2b11b6960e40558"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36",
|
||||
"reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/370772e7d9e9da087678a0edf2b11b6960e40558",
|
||||
"reference": "370772e7d9e9da087678a0edf2b11b6960e40558",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5061,9 +5338,9 @@
|
||||
"php": "^8.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.75.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.72.0",
|
||||
"illuminate/view": "^11.44.2",
|
||||
"larastan/larastan": "^3.3.1",
|
||||
"larastan/larastan": "^3.2.0",
|
||||
"laravel-zero/framework": "^11.36.1",
|
||||
"mockery/mockery": "^1.6.12",
|
||||
"nunomaduro/termwind": "^2.3",
|
||||
@@ -5103,7 +5380,7 @@
|
||||
"issues": "https://github.com/laravel/pint/issues",
|
||||
"source": "https://github.com/laravel/pint"
|
||||
},
|
||||
"time": "2025-04-08T22:11:45+00:00"
|
||||
"time": "2025-03-14T22:31:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "matthiasmullie/minify",
|
||||
@@ -7146,16 +7423,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.2.5",
|
||||
"version": "v7.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "e51498ea18570c062e7df29d05a7003585b19b88"
|
||||
"reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88",
|
||||
"reference": "e51498ea18570c062e7df29d05a7003585b19b88",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
|
||||
"reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7219,7 +7496,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.2.5"
|
||||
"source": "https://github.com/symfony/console/tree/v7.2.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7235,7 +7512,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-12T08:11:12+00:00"
|
||||
"time": "2024-12-11T03:49:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
@@ -7750,16 +8027,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v7.2.5",
|
||||
"version": "v7.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "87b7c93e57df9d8e39a093d32587702380ff045d"
|
||||
"reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d",
|
||||
"reference": "87b7c93e57df9d8e39a093d32587702380ff045d",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
|
||||
"reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7791,7 +8068,7 @@
|
||||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v7.2.5"
|
||||
"source": "https://github.com/symfony/process/tree/v7.2.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7807,7 +8084,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-13T12:21:46+00:00"
|
||||
"time": "2025-02-05T08:33:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
|
||||
+5
-14
@@ -171,7 +171,6 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_SMS_PROVIDER
|
||||
@@ -198,14 +197,11 @@ services:
|
||||
- _APP_DATABASE_SHARED_TABLES_V1
|
||||
- _APP_DATABASE_SHARED_NAMESPACE
|
||||
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
|
||||
- _APP_CUSTOM_DOMAIN_DENY_LIST
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
appwrite-console:
|
||||
<<: *x-logging
|
||||
container_name: appwrite-console
|
||||
image: appwrite/console:5.2.58
|
||||
image: appwrite/console:5.2.53
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
@@ -393,8 +389,6 @@ services:
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_DATABASE_SHARED_TABLES_V1
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
|
||||
appwrite-worker-databases:
|
||||
entrypoint: worker-databases
|
||||
@@ -492,8 +486,6 @@ services:
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
appwrite-worker-certificates:
|
||||
entrypoint: worker-certificates
|
||||
@@ -729,7 +721,6 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_MAINTENANCE_DELAY
|
||||
@@ -765,7 +756,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_STATS_RESOURCES_INTERVAL
|
||||
|
||||
|
||||
appwrite-worker-stats-resources:
|
||||
entrypoint: worker-stats-resources
|
||||
<<: *x-logging
|
||||
@@ -796,7 +787,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
|
||||
|
||||
appwrite-worker-stats-usage:
|
||||
entrypoint: worker-stats-usage
|
||||
<<: *x-logging
|
||||
@@ -859,7 +850,7 @@ services:
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_STATS_USAGE_DUAL_WRITING_DBS
|
||||
|
||||
|
||||
appwrite-task-scheduler-functions:
|
||||
entrypoint: schedule-functions
|
||||
<<: *x-logging
|
||||
@@ -1136,4 +1127,4 @@ volumes:
|
||||
appwrite-certificates:
|
||||
appwrite-functions:
|
||||
appwrite-builds:
|
||||
appwrite-config:
|
||||
appwrite-config:
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="true"
|
||||
stopOnFailure="false"
|
||||
>
|
||||
<extensions>
|
||||
<extension class="Appwrite\Tests\TestHook" />
|
||||
|
||||
@@ -196,9 +196,9 @@ abstract class OAuth2
|
||||
|
||||
if (!empty($payload)) {
|
||||
\curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
||||
$headers[] = 'Content-length: ' . \strlen($payload);
|
||||
}
|
||||
|
||||
$headers[] = 'Content-length: ' . \strlen($payload);
|
||||
\curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
// Send the request & save response to $response
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Auth\OAuth2;
|
||||
|
||||
use Appwrite\Auth\OAuth2;
|
||||
|
||||
// Reference Material
|
||||
// https://www.figma.com/developers/api#oauth2
|
||||
// https://www.figma.com/developers/api#authentication
|
||||
|
||||
class Figma extends OAuth2
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $user = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $tokens = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $scopes = [
|
||||
'current_user:read'
|
||||
];
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'figma';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
return 'https://www.figma.com/oauth?' . \http_build_query([
|
||||
'response_type' => 'code',
|
||||
'client_id' => $this->appID,
|
||||
'redirect_uri' => $this->callback,
|
||||
'scope' => \implode(' ', $this->getScopes()),
|
||||
'state' => \json_encode($this->state)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getTokens(string $code): array
|
||||
{
|
||||
if (empty($this->tokens)) {
|
||||
$headers = [
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)
|
||||
];
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
'https://api.figma.com/v1/oauth/token',
|
||||
$headers,
|
||||
\http_build_query([
|
||||
'redirect_uri' => $this->callback,
|
||||
'code' => $code,
|
||||
'grant_type' => 'authorization_code'
|
||||
])
|
||||
), true);
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $refreshToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function refreshTokens(string $refreshToken): array
|
||||
{
|
||||
$headers = [
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'Authorization: Basic ' . \base64_encode($this->appID . ':' . $this->appSecret)
|
||||
];
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
'https://api.figma.com/v1/oauth/refresh',
|
||||
$headers,
|
||||
\http_build_query([
|
||||
'refresh_token' => $refreshToken
|
||||
])
|
||||
), true);
|
||||
|
||||
if (empty($this->tokens['refresh_token'])) {
|
||||
$this->tokens['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
return $user['id'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
return $user['email'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the OAuth email is verified
|
||||
*
|
||||
* Figma requires email verification during signup,
|
||||
* so if we have an email, it's verified
|
||||
*
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmailVerified(string $accessToken): bool
|
||||
{
|
||||
$email = $this->getUserEmail($accessToken);
|
||||
|
||||
return !empty($email);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
return $user['handle'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
if (empty($this->user)) {
|
||||
$headers = ['Authorization: Bearer ' . $accessToken];
|
||||
$user = $this->request(
|
||||
'GET',
|
||||
'https://api.figma.com/v1/me',
|
||||
$headers
|
||||
);
|
||||
$this->user = \json_decode($user, true);
|
||||
}
|
||||
|
||||
return $this->user;
|
||||
}
|
||||
}
|
||||
@@ -351,7 +351,6 @@ class Event
|
||||
*/
|
||||
public function trigger(): string|bool
|
||||
{
|
||||
|
||||
if ($this->paused) {
|
||||
return false;
|
||||
}
|
||||
@@ -361,7 +360,6 @@ class Event
|
||||
|
||||
// Merge the base payload with any trimmed values
|
||||
$payload = array_merge($this->preparePayload(), $this->trimPayload());
|
||||
|
||||
return $this->publisher->enqueue($queue, $payload);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\System\System;
|
||||
|
||||
class V19 extends Migration
|
||||
{
|
||||
@@ -730,7 +731,7 @@ class V19 extends Migration
|
||||
|
||||
if (empty($document->getAttribute('scheduleId', null))) {
|
||||
$schedule = $this->consoleDB->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'), // Todo replace with projects region
|
||||
'resourceType' => 'function',
|
||||
'resourceId' => $document->getId(),
|
||||
'resourceInternalId' => $document->getInternalId(),
|
||||
|
||||
@@ -82,14 +82,6 @@ class V21 extends Migration
|
||||
Console::warning("'type' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
break;
|
||||
case 'migrations':
|
||||
// Create destination attribute
|
||||
try {
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'destination');
|
||||
} catch (Throwable $th) {
|
||||
Console::warning("'destination' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
break;
|
||||
case 'schedules':
|
||||
// Create data attribute
|
||||
try {
|
||||
@@ -99,14 +91,7 @@ class V21 extends Migration
|
||||
}
|
||||
|
||||
break;
|
||||
case 'databases':
|
||||
// Create originalId attribute
|
||||
try {
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'originalId');
|
||||
} catch (Throwable $th) {
|
||||
Console::warning("'originalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'functions':
|
||||
// Create scopes attribute
|
||||
try {
|
||||
|
||||
@@ -47,20 +47,13 @@ class Maintenance extends Action
|
||||
|
||||
Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds");
|
||||
|
||||
$dbForPlatform->foreach(
|
||||
'projects',
|
||||
function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) {
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_MAINTENANCE)
|
||||
->setProject($project)
|
||||
->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly))
|
||||
->trigger();
|
||||
},
|
||||
[
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]),
|
||||
Query::limit(100),
|
||||
]
|
||||
);
|
||||
$this->foreachProject($dbForPlatform, function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) {
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_MAINTENANCE)
|
||||
->setProject($project)
|
||||
->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly))
|
||||
->trigger();
|
||||
});
|
||||
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_MAINTENANCE)
|
||||
@@ -75,6 +68,33 @@ class Maintenance extends Action
|
||||
}, $interval, $delay);
|
||||
}
|
||||
|
||||
protected function foreachProject(Database $dbForPlatform, callable $callback): void
|
||||
{
|
||||
// TODO: @Meldiron name of this method no longer matches. It does not delete, and it gives whole document
|
||||
$count = 0;
|
||||
$chunk = 0;
|
||||
$limit = 50;
|
||||
$sum = $limit;
|
||||
$executionStart = \microtime(true);
|
||||
|
||||
while ($sum === $limit) {
|
||||
$projects = $dbForPlatform->find('projects', [Query::limit($limit), Query::offset($chunk * $limit)]);
|
||||
|
||||
$chunk++;
|
||||
|
||||
/** @var string[] $projectIds */
|
||||
$sum = count($projects);
|
||||
|
||||
foreach ($projects as $project) {
|
||||
$callback($project);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$executionEnd = \microtime(true);
|
||||
Console::info("Found {$count} projects " . ($executionEnd - $executionStart) . " seconds");
|
||||
}
|
||||
|
||||
private function notifyDeleteConnections(Delete $queueForDeletes): void
|
||||
{
|
||||
$queueForDeletes
|
||||
|
||||
@@ -103,15 +103,8 @@ abstract class ScheduleBase extends Action
|
||||
$paginationQueries[] = Query::cursorAfter($latestDocument);
|
||||
}
|
||||
|
||||
// Temporarly accepting both 'fra' and 'default'
|
||||
// When all migrated, only use _APP_REGION with 'default' as default value
|
||||
$regions = [System::getEnv('_APP_REGION', 'default')];
|
||||
if (!in_array('default', $regions)) {
|
||||
$regions[] = 'default';
|
||||
}
|
||||
|
||||
$results = $dbForPlatform->find('schedules', \array_merge($paginationQueries, [
|
||||
Query::equal('region', $regions),
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]),
|
||||
Query::equal('resourceType', [static::getSupportedResource()]),
|
||||
Query::equal('active', [true]),
|
||||
]));
|
||||
@@ -160,15 +153,8 @@ abstract class ScheduleBase extends Action
|
||||
$paginationQueries[] = Query::cursorAfter($latestDocument);
|
||||
}
|
||||
|
||||
// Temporarly accepting both 'fra' and 'default'
|
||||
// When all migrated, only use _APP_REGION with 'default' as default value
|
||||
$regions = [System::getEnv('_APP_REGION', 'default')];
|
||||
if (!in_array('default', $regions)) {
|
||||
$regions[] = 'default';
|
||||
}
|
||||
|
||||
$results = $dbForPlatform->find('schedules', \array_merge($paginationQueries, [
|
||||
Query::equal('region', $regions),
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]),
|
||||
Query::equal('resourceType', [static::getSupportedResource()]),
|
||||
Query::greaterThanEqual('resourceUpdatedAt', $lastSyncUpdate),
|
||||
]));
|
||||
|
||||
@@ -67,8 +67,7 @@ class StatsResources extends Action
|
||||
* For each project that were accessed in last 24 hours
|
||||
*/
|
||||
$this->foreachDocument($this->dbForPlatform, 'projects', [
|
||||
Query::greaterThanEqual('accessedAt', DateTime::format($last24Hours)),
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')])
|
||||
Query::greaterThanEqual('accessedAt', DateTime::format($last24Hours))
|
||||
], function ($project) use ($queue) {
|
||||
$queue
|
||||
->setProject($project)
|
||||
|
||||
@@ -74,11 +74,7 @@ class Audits extends Action
|
||||
Console::info('Aggregating audit logs');
|
||||
|
||||
$event = $payload['event'] ?? '';
|
||||
|
||||
$auditPayload = '';
|
||||
if ($project->getId() === 'console') {
|
||||
$auditPayload = $payload['payload'] ?? '';
|
||||
}
|
||||
$auditPayload = $payload['payload'] ?? '';
|
||||
$mode = $payload['mode'] ?? '';
|
||||
$resource = $payload['resource'] ?? '';
|
||||
$userAgent = $payload['userAgent'] ?? '';
|
||||
|
||||
@@ -59,10 +59,8 @@ class Builds extends Action
|
||||
->inject('deviceForFunctions')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('log')
|
||||
->inject('executor')
|
||||
->inject('plan')
|
||||
->callback(fn ($message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log, Executor $executor, array $plan) =>
|
||||
$this->action($message, $project, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $usage, $cache, $dbForProject, $deviceForFunctions, $isResourceBlocked, $log, $executor, $plan));
|
||||
->callback(fn ($message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log) =>
|
||||
$this->action($message, $project, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $usage, $cache, $dbForProject, $deviceForFunctions, $isResourceBlocked, $log));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,12 +76,10 @@ class Builds extends Action
|
||||
* @param Database $dbForProject
|
||||
* @param Device $deviceForFunctions
|
||||
* @param Log $log
|
||||
* @param Executor $executor
|
||||
* @param array $plan
|
||||
* @return void
|
||||
* @throws \Utopia\Database\Exception
|
||||
*/
|
||||
public function action(Message $message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $queueForStatsUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log, Executor $executor, array $plan): void
|
||||
public function action(Message $message, Document $project, Database $dbForPlatform, Event $queueForEvents, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, StatsUsage $queueForStatsUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, callable $isResourceBlocked, Log $log): void
|
||||
{
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
||||
@@ -104,7 +100,7 @@ class Builds extends Action
|
||||
case BUILD_TYPE_RETRY:
|
||||
Console::info('Creating build for deployment: ' . $deployment->getId());
|
||||
$github = new GitHub($cache);
|
||||
$this->buildDeployment($deviceForFunctions, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForEvents, $queueForStatsUsage, $dbForPlatform, $dbForProject, $github, $project, $resource, $deployment, $template, $isResourceBlocked, $log, $executor, $plan);
|
||||
$this->buildDeployment($deviceForFunctions, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForEvents, $queueForStatsUsage, $dbForPlatform, $dbForProject, $github, $project, $resource, $deployment, $template, $isResourceBlocked, $log);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -127,14 +123,14 @@ class Builds extends Action
|
||||
* @param Document $deployment
|
||||
* @param Document $template
|
||||
* @param Log $log
|
||||
* @param Executor $executor
|
||||
* @param array $plan
|
||||
* @return void
|
||||
* @throws \Utopia\Database\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function buildDeployment(Device $deviceForFunctions, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Database $dbForPlatform, Database $dbForProject, GitHub $github, Document $project, Document $function, Document $deployment, Document $template, callable $isResourceBlocked, Log $log, Executor $executor, array $plan): void
|
||||
protected function buildDeployment(Device $deviceForFunctions, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Database $dbForPlatform, Database $dbForProject, GitHub $github, Document $project, Document $function, Document $deployment, Document $template, callable $isResourceBlocked, Log $log): void
|
||||
{
|
||||
$executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST'));
|
||||
|
||||
$functionId = $function->getId();
|
||||
$log->addTag('functionId', $function->getId());
|
||||
|
||||
@@ -404,15 +400,9 @@ class Builds extends Action
|
||||
}
|
||||
|
||||
$directorySize = $localDevice->getDirectorySize($tmpDirectory);
|
||||
|
||||
$functionsSizeLimit = (int)System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000');
|
||||
|
||||
if (isset($plan['functionSize'])) {
|
||||
$functionsSizeLimit = (int) $plan['functionSize'] * 1000 * 1000;
|
||||
}
|
||||
|
||||
if ($directorySize > $functionsSizeLimit) {
|
||||
throw new \Exception('Repository directory size should be less than ' . number_format($functionsSizeLimit / (1000 * 1000), 2) . ' MBs.');
|
||||
throw new \Exception('Repository directory size should be less than ' . number_format($functionsSizeLimit / 1048576, 2) . ' MBs.');
|
||||
}
|
||||
|
||||
Console::execute('find ' . \escapeshellarg($tmpDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr);
|
||||
@@ -629,11 +619,8 @@ class Builds extends Action
|
||||
$durationEnd = \microtime(true);
|
||||
|
||||
$buildSizeLimit = (int)System::getEnv('_APP_FUNCTIONS_BUILD_SIZE_LIMIT', '2000000000');
|
||||
if (isset($plan['buildSize'])) {
|
||||
$buildSizeLimit = $plan['buildSize'] * 1000 * 1000;
|
||||
}
|
||||
if ($response['size'] > $buildSizeLimit) {
|
||||
throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / (1000 * 1000), 2) . ' MBs.');
|
||||
throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / 1048576, 2) . ' MBs.');
|
||||
}
|
||||
|
||||
/** Update the build document */
|
||||
|
||||
@@ -565,8 +565,7 @@ class Databases extends Action
|
||||
try {
|
||||
$documents = $database->deleteDocuments($collectionId, $queries);
|
||||
} catch (\Throwable $th) {
|
||||
$tenant = $database->getSharedTables() ? 'Tenant:'.$database->getTenant() : '';
|
||||
Console::error("Failed to delete documents for collection:{$database->getNamespace()}_{$collectionId} {$tenant} :{$th->getMessage()}");
|
||||
Console::error('Failed to delete documents for collection ' . $collectionId . ': ' . $th->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ use Utopia\System\System;
|
||||
|
||||
class Deletes extends Action
|
||||
{
|
||||
protected array $selects = ['$internalId', '$id', '$collection', '$permissions', '$updatedAt'];
|
||||
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'deletes';
|
||||
@@ -55,13 +53,12 @@ class Deletes extends Action
|
||||
->inject('deviceForBuilds')
|
||||
->inject('deviceForCache')
|
||||
->inject('certificates')
|
||||
->inject('executor')
|
||||
->inject('executionRetention')
|
||||
->inject('auditRetention')
|
||||
->inject('log')
|
||||
->callback(
|
||||
fn ($message, Document $project, Database $dbForPlatform, callable $getProjectDB, callable $getLogsDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Executor $executor, string $executionRetention, string $auditRetention, Log $log) =>
|
||||
$this->action($message, $project, $dbForPlatform, $getProjectDB, $getLogsDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $executor, $executionRetention, $auditRetention, $log)
|
||||
fn ($message, Document $project, Database $dbForPlatform, callable $getProjectDB, callable $getLogsDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log) =>
|
||||
$this->action($message, $project, $dbForPlatform, $getProjectDB, $getLogsDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $executionRetention, $auditRetention, $log)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,7 +66,7 @@ class Deletes extends Action
|
||||
* @throws Exception
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function action(Message $message, Document $project, Database $dbForPlatform, callable $getProjectDB, callable $getLogsDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Executor $executor, string $executionRetention, string $auditRetention, Log $log): void
|
||||
public function action(Message $message, Document $project, Database $dbForPlatform, callable $getProjectDB, callable $getLogsDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, string $executionRetention, string $auditRetention, Log $log): void
|
||||
{
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
||||
@@ -94,10 +91,10 @@ class Deletes extends Action
|
||||
$this->deleteProject($dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $document);
|
||||
break;
|
||||
case DELETE_TYPE_FUNCTIONS:
|
||||
$this->deleteFunction($dbForPlatform, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $certificates, $document, $project, $executor);
|
||||
$this->deleteFunction($dbForPlatform, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $certificates, $document, $project);
|
||||
break;
|
||||
case DELETE_TYPE_DEPLOYMENTS:
|
||||
$this->deleteDeployment($getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project, $executor);
|
||||
$this->deleteDeployment($getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project);
|
||||
break;
|
||||
case DELETE_TYPE_USERS:
|
||||
$this->deleteUser($getProjectDB, $document, $project);
|
||||
@@ -183,17 +180,10 @@ class Deletes extends Action
|
||||
*/
|
||||
private function deleteSchedules(Database $dbForPlatform, callable $getProjectDB, string $datetime): void
|
||||
{
|
||||
// Temporarly accepting both 'fra' and 'default'
|
||||
// When all migrated, only use _APP_REGION with 'default' as default value
|
||||
$regions = [System::getEnv('_APP_REGION', 'default')];
|
||||
if (!in_array('default', $regions)) {
|
||||
$regions[] = 'default';
|
||||
}
|
||||
|
||||
$this->listByGroup(
|
||||
'schedules',
|
||||
[
|
||||
Query::equal('region', $regions),
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]),
|
||||
Query::lessThanEqual('resourceUpdatedAt', $datetime),
|
||||
Query::equal('active', [false]),
|
||||
],
|
||||
@@ -258,8 +248,7 @@ class Deletes extends Action
|
||||
$this->deleteByGroup(
|
||||
'subscribers',
|
||||
[
|
||||
Query::equal('topicInternalId', [$topic->getInternalId()]),
|
||||
Query::orderAsc(),
|
||||
Query::equal('topicInternalId', [$topic->getInternalId()])
|
||||
],
|
||||
$getProjectDB($project)
|
||||
);
|
||||
@@ -280,8 +269,7 @@ class Deletes extends Action
|
||||
$this->deleteByGroup(
|
||||
'subscribers',
|
||||
[
|
||||
Query::equal('targetInternalId', [$target->getInternalId()]),
|
||||
Query::orderAsc(),
|
||||
Query::equal('targetInternalId', [$target->getInternalId()])
|
||||
],
|
||||
$dbForProject,
|
||||
function (Document $subscriber) use ($dbForProject, $target) {
|
||||
@@ -318,8 +306,7 @@ class Deletes extends Action
|
||||
$this->deleteByGroup(
|
||||
'targets',
|
||||
[
|
||||
Query::equal('expired', [true]),
|
||||
Query::orderAsc(),
|
||||
Query::equal('expired', [true])
|
||||
],
|
||||
$getProjectDB($project),
|
||||
function (Document $target) use ($getProjectDB, $project) {
|
||||
@@ -333,8 +320,7 @@ class Deletes extends Action
|
||||
$this->deleteByGroup(
|
||||
'targets',
|
||||
[
|
||||
Query::equal('sessionInternalId', [$session->getInternalId()]),
|
||||
Query::orderAsc(),
|
||||
Query::equal('sessionInternalId', [$session->getInternalId()])
|
||||
],
|
||||
$getProjectDB($project),
|
||||
function (Document $target) use ($getProjectDB, $project) {
|
||||
@@ -361,20 +347,14 @@ class Deletes extends Action
|
||||
new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId)
|
||||
);
|
||||
|
||||
$queries = [
|
||||
Query::equal('resource', [$resource])
|
||||
];
|
||||
|
||||
$query[] = Query::equal('resource', [$resource]);
|
||||
if (!empty($resourceType)) {
|
||||
$queries[] = Query::equal('resourceType', [$resourceType]);
|
||||
$query[] = Query::equal('resourceType', [$resourceType]);
|
||||
}
|
||||
|
||||
$queries[] = Query::select($this->selects);
|
||||
$queries[] = Query::orderAsc();
|
||||
|
||||
$this->deleteByGroup(
|
||||
'cache',
|
||||
$queries,
|
||||
$query,
|
||||
$dbForProject,
|
||||
function (Document $document) use ($cache, $projectId) {
|
||||
$path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId();
|
||||
@@ -405,16 +385,15 @@ class Deletes extends Action
|
||||
new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId)
|
||||
);
|
||||
|
||||
$queries = [
|
||||
Query::select([...$this->selects, 'accessedAt']),
|
||||
$query = [
|
||||
Query::lessThan('accessedAt', $datetime),
|
||||
Query::orderDesc('accessedAt'),
|
||||
Query::orderDesc(),
|
||||
Query::orderDesc('$internalId'),
|
||||
];
|
||||
|
||||
$this->deleteByGroup(
|
||||
'cache',
|
||||
$queries,
|
||||
$query,
|
||||
$dbForProject,
|
||||
function (Document $document) use ($cache, $projectId) {
|
||||
$path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId();
|
||||
@@ -440,15 +419,12 @@ class Deletes extends Action
|
||||
/** @var Database $dbForProject*/
|
||||
$dbForProject = $getProjectDB($project);
|
||||
|
||||
$selects = [...$this->selects, 'time'];
|
||||
|
||||
// Delete Usage stats from projectDB
|
||||
$this->deleteByGroup('stats', [
|
||||
Query::select($selects),
|
||||
Query::equal('period', ['1h']),
|
||||
Query::lessThan('time', $hourlyUsageRetentionDatetime),
|
||||
Query::orderDesc('time'),
|
||||
Query::orderDesc(),
|
||||
Query::orderDesc('$internalId'),
|
||||
Query::equal('period', ['1h']),
|
||||
], $dbForProject);
|
||||
|
||||
if ($project->getId() !== 'console') {
|
||||
@@ -457,11 +433,10 @@ class Deletes extends Action
|
||||
|
||||
// Delete Usage stats from logsDB
|
||||
$this->deleteByGroup('stats', [
|
||||
Query::select($selects),
|
||||
Query::equal('period', ['1h']),
|
||||
Query::lessThan('time', $hourlyUsageRetentionDatetime),
|
||||
Query::orderDesc('time'),
|
||||
Query::orderDesc(),
|
||||
Query::orderDesc('$internalId'),
|
||||
Query::equal('period', ['1h']),
|
||||
], $dbForLogs);
|
||||
}
|
||||
}
|
||||
@@ -482,8 +457,7 @@ class Deletes extends Action
|
||||
$this->deleteByGroup(
|
||||
'memberships',
|
||||
[
|
||||
Query::equal('teamInternalId', [$teamInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('teamInternalId', [$teamInternalId])
|
||||
],
|
||||
$dbForProject,
|
||||
function (Document $membership) use ($dbForProject) {
|
||||
@@ -494,22 +468,21 @@ class Deletes extends Action
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Database $dbForPlatform
|
||||
* @param Document $document
|
||||
* @return void
|
||||
* @throws Authorization
|
||||
* @throws DatabaseException
|
||||
* @throws Conflict
|
||||
* @throws Restricted
|
||||
* @throws Structure
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteProjectsByTeam(Database $dbForPlatform, callable $getProjectDB, CertificatesAdapter $certificates, Document $document): void
|
||||
* @param Database $dbForPlatform
|
||||
* @param Document $document
|
||||
* @return void
|
||||
* @throws Authorization
|
||||
* @throws DatabaseException
|
||||
* @throws Conflict
|
||||
* @throws Restricted
|
||||
* @throws Structure
|
||||
* @throws Exception
|
||||
*/
|
||||
private function deleteProjectsByTeam(Database $dbForPlatform, callable $getProjectDB, CertificatesAdapter $certificates, Document $document): void
|
||||
{
|
||||
|
||||
$projects = $dbForPlatform->find('projects', [
|
||||
Query::equal('teamInternalId', [$document->getInternalId()]),
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')])
|
||||
Query::equal('teamInternalId', [$document->getInternalId()])
|
||||
]);
|
||||
|
||||
foreach ($projects as $project) {
|
||||
@@ -574,13 +547,7 @@ class Deletes extends Action
|
||||
if ($projectTables || !\in_array($collection->getId(), $projectCollectionIds)) {
|
||||
$dbForProject->deleteCollection($collection->getId());
|
||||
} else {
|
||||
$this->deleteByGroup(
|
||||
$collection->getId(),
|
||||
[
|
||||
Query::orderAsc()
|
||||
],
|
||||
database: $dbForProject
|
||||
);
|
||||
$this->deleteByGroup($collection->getId(), [], database: $dbForProject);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
Console::error('Error deleting '.$collection->getId().' '.$e->getMessage());
|
||||
@@ -600,78 +567,58 @@ class Deletes extends Action
|
||||
|
||||
// Delete Platforms
|
||||
$this->deleteByGroup('platforms', [
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('projectInternalId', [$projectInternalId])
|
||||
], $dbForPlatform);
|
||||
|
||||
// Delete project and function rules
|
||||
$this->deleteByGroup('rules', [
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('projectInternalId', [$projectInternalId])
|
||||
], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) {
|
||||
$this->deleteRule($dbForPlatform, $document, $certificates);
|
||||
});
|
||||
|
||||
// Delete Keys
|
||||
$this->deleteByGroup('keys', [
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('projectInternalId', [$projectInternalId])
|
||||
], $dbForPlatform);
|
||||
|
||||
// Delete Webhooks
|
||||
$this->deleteByGroup('webhooks', [
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('projectInternalId', [$projectInternalId])
|
||||
], $dbForPlatform);
|
||||
|
||||
// Delete VCS Installations
|
||||
$this->deleteByGroup('installations', [
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('projectInternalId', [$projectInternalId])
|
||||
], $dbForPlatform);
|
||||
|
||||
// Delete VCS Repositories
|
||||
$this->deleteByGroup('repositories', [
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
], $dbForPlatform);
|
||||
|
||||
// Delete VCS comments
|
||||
$this->deleteByGroup('vcsComments', [
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
], $dbForPlatform);
|
||||
|
||||
// Delete Schedules
|
||||
// Delete Schedules (No projectInternalId in this collection)
|
||||
$this->deleteByGroup('schedules', [
|
||||
Query::equal('projectId', [$projectId]),
|
||||
Query::orderAsc()
|
||||
], $dbForPlatform);
|
||||
|
||||
// Delete metadata table
|
||||
if ($projectTables) {
|
||||
$dbForProject->deleteCollection(Database::METADATA);
|
||||
} elseif ($sharedTablesV1) {
|
||||
$this->deleteByGroup(
|
||||
Database::METADATA,
|
||||
[
|
||||
Query::orderAsc()
|
||||
],
|
||||
$dbForProject
|
||||
);
|
||||
$this->deleteByGroup(Database::METADATA, [], $dbForProject);
|
||||
} elseif ($sharedTablesV2) {
|
||||
$queries = \array_map(
|
||||
fn ($id) => Query::notEqual('$id', $id),
|
||||
$projectCollectionIds
|
||||
);
|
||||
|
||||
$queries[] = Query::orderAsc();
|
||||
|
||||
$this->deleteByGroup(
|
||||
Database::METADATA,
|
||||
$queries,
|
||||
$dbForProject
|
||||
);
|
||||
$this->deleteByGroup(Database::METADATA, $queries, $dbForProject);
|
||||
}
|
||||
|
||||
// Delete all storage directories
|
||||
@@ -696,16 +643,14 @@ class Deletes extends Action
|
||||
|
||||
// Delete all sessions of this user from the sessions table and update the sessions field of the user record
|
||||
$this->deleteByGroup('sessions', [
|
||||
Query::equal('userInternalId', [$userInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('userInternalId', [$userInternalId])
|
||||
], $dbForProject);
|
||||
|
||||
$dbForProject->purgeCachedDocument('users', $userId);
|
||||
|
||||
// Delete Memberships and decrement team membership counts
|
||||
$this->deleteByGroup('memberships', [
|
||||
Query::equal('userInternalId', [$userInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('userInternalId', [$userInternalId])
|
||||
], $dbForProject, function (Document $document) use ($dbForProject) {
|
||||
if ($document->getAttribute('confirm')) { // Count only confirmed members
|
||||
$teamId = $document->getAttribute('teamId');
|
||||
@@ -718,22 +663,19 @@ class Deletes extends Action
|
||||
|
||||
// Delete tokens
|
||||
$this->deleteByGroup('tokens', [
|
||||
Query::equal('userInternalId', [$userInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('userInternalId', [$userInternalId])
|
||||
], $dbForProject);
|
||||
|
||||
// Delete identities
|
||||
$this->deleteByGroup('identities', [
|
||||
Query::equal('userInternalId', [$userInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('userInternalId', [$userInternalId])
|
||||
], $dbForProject);
|
||||
|
||||
// Delete targets
|
||||
$this->deleteByGroup(
|
||||
'targets',
|
||||
[
|
||||
Query::equal('userInternalId', [$userInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('userInternalId', [$userInternalId])
|
||||
],
|
||||
$dbForProject,
|
||||
function (Document $target) use ($getProjectDB, $project) {
|
||||
@@ -755,10 +697,9 @@ class Deletes extends Action
|
||||
|
||||
// Delete Executions
|
||||
$this->deleteByGroup('executions', [
|
||||
Query::select([...$this->selects, '$createdAt']),
|
||||
Query::lessThan('$createdAt', $datetime),
|
||||
Query::orderDesc('$createdAt'),
|
||||
Query::orderDesc(),
|
||||
Query::orderDesc('$internalId'),
|
||||
], $dbForProject);
|
||||
}
|
||||
|
||||
@@ -776,10 +717,9 @@ class Deletes extends Action
|
||||
|
||||
// Delete Sessions
|
||||
$this->deleteByGroup('sessions', [
|
||||
Query::select([...$this->selects, '$createdAt']),
|
||||
Query::lessThan('$createdAt', $expired),
|
||||
Query::orderDesc('$createdAt'),
|
||||
Query::orderDesc(),
|
||||
Query::orderDesc('$internalId'),
|
||||
], $dbForProject);
|
||||
}
|
||||
|
||||
@@ -795,14 +735,14 @@ class Deletes extends Action
|
||||
$this->deleteByGroup('realtime', [
|
||||
Query::lessThan('timestamp', $datetime),
|
||||
Query::orderDesc('timestamp'),
|
||||
Query::orderAsc(),
|
||||
Query::orderDesc('$internalId'),
|
||||
], $dbForPlatform);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Database $dbForPlatform
|
||||
* @param callable $getProjectDB
|
||||
* @param string $auditRetention
|
||||
* @param string $datetime
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
@@ -813,10 +753,9 @@ class Deletes extends Action
|
||||
|
||||
try {
|
||||
$this->deleteByGroup(Audit::COLLECTION, [
|
||||
Query::select([...$this->selects, 'time']),
|
||||
Query::lessThan('time', $auditRetention),
|
||||
Query::orderDesc('time'),
|
||||
Query::orderAsc(),
|
||||
Query::orderDesc('$internalId'),
|
||||
], $dbForProject);
|
||||
} catch (DatabaseException $e) {
|
||||
Console::error('Failed to delete audit logs for project ' . $projectId . ': ' . $e->getMessage());
|
||||
@@ -829,11 +768,10 @@ class Deletes extends Action
|
||||
* @param Device $deviceForBuilds
|
||||
* @param Document $document function document
|
||||
* @param Document $project
|
||||
* @param Executor $executor
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function deleteFunction(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, CertificatesAdapter $certificates, Document $document, Document $project, Executor $executor): void
|
||||
private function deleteFunction(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, CertificatesAdapter $certificates, Document $document, Document $project): void
|
||||
{
|
||||
$projectId = $project->getId();
|
||||
$dbForProject = $getProjectDB($project);
|
||||
@@ -845,10 +783,9 @@ class Deletes extends Action
|
||||
*/
|
||||
Console::info("Deleting rules for function " . $functionId);
|
||||
$this->deleteByGroup('rules', [
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
Query::equal('resourceInternalId', [$functionInternalId]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
Query::orderAsc()
|
||||
Query::equal('resourceInternalId', [$functionInternalId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()])
|
||||
], $dbForPlatform, function (Document $document) use ($project, $dbForPlatform, $certificates) {
|
||||
$this->deleteRule($dbForPlatform, $document, $certificates);
|
||||
});
|
||||
@@ -858,9 +795,8 @@ class Deletes extends Action
|
||||
*/
|
||||
Console::info("Deleting variables for function " . $functionId);
|
||||
$this->deleteByGroup('variables', [
|
||||
Query::equal('resourceInternalId', [$functionInternalId]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
Query::orderAsc()
|
||||
Query::equal('resourceInternalId', [$functionInternalId])
|
||||
], $dbForProject);
|
||||
|
||||
/**
|
||||
@@ -870,8 +806,7 @@ class Deletes extends Action
|
||||
|
||||
$deploymentInternalIds = [];
|
||||
$this->deleteByGroup('deployments', [
|
||||
Query::equal('resourceInternalId', [$functionInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('resourceInternalId', [$functionInternalId])
|
||||
], $dbForProject, function (Document $document) use ($deviceForFunctions, &$deploymentInternalIds) {
|
||||
$deploymentInternalIds[] = $document->getInternalId();
|
||||
$this->deleteDeploymentFiles($deviceForFunctions, $document);
|
||||
@@ -884,8 +819,7 @@ class Deletes extends Action
|
||||
|
||||
foreach ($deploymentInternalIds as $deploymentInternalId) {
|
||||
$this->deleteByGroup('builds', [
|
||||
Query::equal('deploymentInternalId', [$deploymentInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('deploymentInternalId', [$deploymentInternalId])
|
||||
], $dbForProject, function (Document $document) use ($deviceForBuilds) {
|
||||
$this->deleteBuildFiles($deviceForBuilds, $document);
|
||||
});
|
||||
@@ -896,9 +830,7 @@ class Deletes extends Action
|
||||
*/
|
||||
Console::info("Deleting executions for function " . $functionId);
|
||||
$this->deleteByGroup('executions', [
|
||||
Query::select($this->selects),
|
||||
Query::equal('functionInternalId', [$functionInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('functionInternalId', [$functionInternalId])
|
||||
], $dbForProject);
|
||||
|
||||
/**
|
||||
@@ -909,15 +841,12 @@ class Deletes extends Action
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
Query::equal('resourceInternalId', [$functionInternalId]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
Query::orderAsc()
|
||||
], $dbForPlatform, function (Document $document) use ($dbForPlatform) {
|
||||
$providerRepositoryId = $document->getAttribute('providerRepositoryId', '');
|
||||
$projectInternalId = $document->getAttribute('projectInternalId', '');
|
||||
|
||||
$this->deleteByGroup('vcsComments', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::equal('projectInternalId', [$projectInternalId]),
|
||||
Query::orderAsc()
|
||||
], $dbForPlatform);
|
||||
});
|
||||
|
||||
@@ -925,7 +854,7 @@ class Deletes extends Action
|
||||
* Request executor to delete all deployment containers
|
||||
*/
|
||||
Console::info("Requesting executor to delete all deployment containers for function " . $functionId);
|
||||
$this->deleteRuntimes($getProjectDB, $document, $project, $executor);
|
||||
$this->deleteRuntimes($getProjectDB, $document, $project);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -996,11 +925,10 @@ class Deletes extends Action
|
||||
* @param Device $deviceForBuilds
|
||||
* @param Document $document
|
||||
* @param Document $project
|
||||
* @param Executor $executor
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function deleteDeployment(callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, Document $project, Executor $executor): void
|
||||
private function deleteDeployment(callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, Document $project): void
|
||||
{
|
||||
$projectId = $project->getId();
|
||||
$dbForProject = $getProjectDB($project);
|
||||
@@ -1018,8 +946,7 @@ class Deletes extends Action
|
||||
Console::info("Deleting builds for deployment " . $deploymentId);
|
||||
|
||||
$this->deleteByGroup('builds', [
|
||||
Query::equal('deploymentInternalId', [$deploymentInternalId]),
|
||||
Query::orderAsc()
|
||||
Query::equal('deploymentInternalId', [$deploymentInternalId])
|
||||
], $dbForProject, function (Document $document) use ($deviceForBuilds) {
|
||||
$this->deleteBuildFiles($deviceForBuilds, $document);
|
||||
});
|
||||
@@ -1028,7 +955,7 @@ class Deletes extends Action
|
||||
* Request executor to delete all deployment containers
|
||||
*/
|
||||
Console::info("Requesting executor to delete deployment container for deployment " . $deploymentId);
|
||||
$this->deleteRuntimes($getProjectDB, $document, $project, $executor);
|
||||
$this->deleteRuntimes($getProjectDB, $document, $project);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1047,15 +974,10 @@ class Deletes extends Action
|
||||
): void {
|
||||
$start = \microtime(true);
|
||||
|
||||
/**
|
||||
* deleteDocuments uses a cursor, we need to add a unique order by field or use default
|
||||
*/
|
||||
|
||||
try {
|
||||
$documents = $database->deleteDocuments($collection, $queries);
|
||||
} catch (Throwable $th) {
|
||||
$tenant = $database->getSharedTables() ? 'Tenant:'.$database->getTenant() : '';
|
||||
Console::error("Failed to delete documents for collection:{$database->getNamespace()}_{$collection} {$tenant} :{$th->getMessage()}");
|
||||
Console::error('Failed to delete documents for collection ' . $collection . ': ' . $th->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1184,12 +1106,13 @@ class Deletes extends Action
|
||||
* @param callable $getProjectDB
|
||||
* @param ?Document $function
|
||||
* @param Document $project
|
||||
* @param Executor $executor
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function deleteRuntimes(callable $getProjectDB, ?Document $function, Document $project, Executor $executor): void
|
||||
private function deleteRuntimes(callable $getProjectDB, ?Document $function, Document $project): void
|
||||
{
|
||||
$executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST'));
|
||||
|
||||
$deleteByFunction = function (Document $function) use ($getProjectDB, $project, $executor) {
|
||||
$this->listByGroup(
|
||||
'deployments',
|
||||
|
||||
@@ -51,12 +51,11 @@ class Functions extends Action
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('log')
|
||||
->inject('executor')
|
||||
->inject('isResourceBlocked')
|
||||
->callback(fn (Document $project, Message $message, Database $dbForProject, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Log $log, Executor $executor, callable $isResourceBlocked) => $this->action($project, $message, $dbForProject, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForEvents, $queueForStatsUsage, $log, $executor, $isResourceBlocked));
|
||||
->callback(fn (Document $project, Message $message, Database $dbForProject, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Log $log, callable $isResourceBlocked) => $this->action($project, $message, $dbForProject, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $queueForEvents, $queueForStatsUsage, $log, $isResourceBlocked));
|
||||
}
|
||||
|
||||
public function action(Document $project, Message $message, Database $dbForProject, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Log $log, Executor $executor, callable $isResourceBlocked): void
|
||||
public function action(Document $project, Message $message, Database $dbForProject, Webhook $queueForWebhooks, Func $queueForFunctions, Realtime $queueForRealtime, Event $queueForEvents, StatsUsage $queueForStatsUsage, Log $log, callable $isResourceBlocked): void
|
||||
{
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
||||
@@ -147,7 +146,6 @@ class Functions extends Action
|
||||
queueForEvents: $queueForEvents,
|
||||
project: $project,
|
||||
function: $function,
|
||||
executor: $executor,
|
||||
trigger: 'event',
|
||||
path: '/',
|
||||
method: 'POST',
|
||||
@@ -190,7 +188,6 @@ class Functions extends Action
|
||||
queueForEvents: $queueForEvents,
|
||||
project: $project,
|
||||
function: $function,
|
||||
executor: $executor,
|
||||
trigger: 'http',
|
||||
path: $path,
|
||||
method: $method,
|
||||
@@ -215,7 +212,6 @@ class Functions extends Action
|
||||
queueForEvents: $queueForEvents,
|
||||
project: $project,
|
||||
function: $function,
|
||||
executor: $executor,
|
||||
trigger: 'schedule',
|
||||
path: $path,
|
||||
method: $method,
|
||||
@@ -302,7 +298,6 @@ class Functions extends Action
|
||||
* @param Event $queueForEvents
|
||||
* @param Document $project
|
||||
* @param Document $function
|
||||
* @param Executor $executor
|
||||
* @param string $trigger
|
||||
* @param string $path
|
||||
* @param string $method
|
||||
@@ -329,7 +324,6 @@ class Functions extends Action
|
||||
Event $queueForEvents,
|
||||
Document $project,
|
||||
Document $function,
|
||||
Executor $executor,
|
||||
string $trigger,
|
||||
string $path,
|
||||
string $method,
|
||||
@@ -520,6 +514,7 @@ class Functions extends Action
|
||||
try {
|
||||
$version = $function->getAttribute('version', 'v2');
|
||||
$command = $runtime['startCommand'];
|
||||
$executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST'));
|
||||
$command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"';
|
||||
$executionResponse = $executor->createExecution(
|
||||
projectId: $project->getId(),
|
||||
|
||||
@@ -70,6 +70,7 @@ class StatsResources extends Action
|
||||
}
|
||||
|
||||
if (empty($project->getAttribute('database'))) {
|
||||
var_dump($payload);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,6 @@ class Webhooks extends Action
|
||||
$this->errors = [];
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
||||
|
||||
|
||||
if (empty($payload)) {
|
||||
throw new Exception('Missing payload');
|
||||
}
|
||||
|
||||
@@ -71,18 +71,12 @@ class Base extends Queries
|
||||
'array' => false,
|
||||
]);
|
||||
|
||||
$internalId = new Document([
|
||||
'key' => '$internalId',
|
||||
'type' => Database::VAR_STRING,
|
||||
'array' => false,
|
||||
]);
|
||||
|
||||
$validators = [
|
||||
new Limit(),
|
||||
new Offset(),
|
||||
new Cursor(),
|
||||
new Filter($attributes, APP_DATABASE_QUERY_MAX_VALUES),
|
||||
new Order([...$attributes, $internalId]),
|
||||
new Order($attributes),
|
||||
];
|
||||
|
||||
parent::__construct($validators);
|
||||
|
||||
+14
-29
@@ -21,19 +21,17 @@ class Executor
|
||||
|
||||
private bool $selfSigned = false;
|
||||
|
||||
/**
|
||||
* @var callable(string, string): string $endpoint
|
||||
*/
|
||||
private $endpointSelector;
|
||||
private string $endpoint;
|
||||
|
||||
protected array $headers;
|
||||
|
||||
/**
|
||||
* @param callable(string, string): string $endpointSelector
|
||||
*/
|
||||
public function __construct(callable $endpointSelector)
|
||||
public function __construct(string $endpoint)
|
||||
{
|
||||
$this->endpointSelector = $endpointSelector;
|
||||
if (!filter_var($endpoint, FILTER_VALIDATE_URL)) {
|
||||
throw new Exception('Unsupported endpoint');
|
||||
}
|
||||
|
||||
$this->endpoint = $endpoint;
|
||||
$this->headers = [
|
||||
'content-type' => 'application/json',
|
||||
'authorization' => 'Bearer ' . System::getEnv('_APP_EXECUTOR_SECRET', ''),
|
||||
@@ -94,8 +92,7 @@ class Executor
|
||||
'timeout' => $timeout,
|
||||
];
|
||||
|
||||
$endpoint = $this->selectEndpoint($projectId, $deploymentId);
|
||||
$response = $this->call($endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout);
|
||||
$response = $this->call(self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout);
|
||||
|
||||
$status = $response['headers']['status-code'];
|
||||
if ($status >= 400) {
|
||||
@@ -126,8 +123,7 @@ class Executor
|
||||
'timeout' => $timeout
|
||||
];
|
||||
|
||||
$endpoint = $this->selectEndpoint($projectId, $deploymentId);
|
||||
$this->call($endpoint, self::METHOD_GET, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout, $callback);
|
||||
$this->call(self::METHOD_GET, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,8 +139,7 @@ class Executor
|
||||
$runtimeId = "$projectId-$deploymentId";
|
||||
$route = "/runtimes/$runtimeId";
|
||||
|
||||
$endpoint = $this->selectEndpoint($projectId, $deploymentId);
|
||||
$response = $this->call($endpoint, self::METHOD_DELETE, $route, [
|
||||
$response = $this->call(self::METHOD_DELETE, $route, [
|
||||
'x-opr-addressing-method' => 'broadcast'
|
||||
], [], true, 30);
|
||||
|
||||
@@ -232,8 +227,7 @@ class Executor
|
||||
$requestTimeout = $timeout + 15;
|
||||
}
|
||||
|
||||
$endpoint = $this->selectEndpoint($projectId, $deploymentId);
|
||||
$response = $this->call($endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId, 'content-type' => 'multipart/form-data', 'accept' => 'multipart/form-data' ], $params, true, $requestTimeout);
|
||||
$response = $this->call(self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId, 'content-type' => 'multipart/form-data', 'accept' => 'multipart/form-data' ], $params, true, $requestTimeout);
|
||||
|
||||
$status = $response['headers']['status-code'];
|
||||
if ($status >= 400) {
|
||||
@@ -241,11 +235,7 @@ class Executor
|
||||
throw new \Exception($message, $status);
|
||||
}
|
||||
|
||||
$headers = $response['body']['headers'] ?? [];
|
||||
if (is_string($headers)) {
|
||||
$headers = \json_decode($headers, true);
|
||||
}
|
||||
$response['body']['headers'] = $headers;
|
||||
$response['body']['headers'] = \json_decode($response['body']['headers'] ?? '{}', true);
|
||||
$response['body']['statusCode'] = \intval($response['body']['statusCode'] ?? 500);
|
||||
$response['body']['duration'] = \floatval($response['body']['duration'] ?? 0);
|
||||
$response['body']['startTime'] = \floatval($response['body']['startTime'] ?? \microtime(true));
|
||||
@@ -266,10 +256,10 @@ class Executor
|
||||
* @return array|string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function call(string $endpoint, string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true, int $timeout = 15, callable $callback = null)
|
||||
public function call(string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true, int $timeout = 15, callable $callback = null)
|
||||
{
|
||||
$headers = array_merge($this->headers, $headers);
|
||||
$ch = curl_init($endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : ''));
|
||||
$ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : ''));
|
||||
$responseHeaders = [];
|
||||
$responseStatus = -1;
|
||||
$responseType = '';
|
||||
@@ -432,9 +422,4 @@ class Executor
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function selectEndpoint(string $projectId, string $deploymentId): string
|
||||
{
|
||||
return call_user_func($this->endpointSelector, $projectId, $deploymentId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Tests\E2E\Scopes;
|
||||
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\System\System;
|
||||
|
||||
trait ProjectCustom
|
||||
{
|
||||
@@ -43,7 +42,7 @@ trait ProjectCustom
|
||||
'x-appwrite-project' => 'console',
|
||||
], [
|
||||
'projectId' => ID::unique(),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'region' => 'default',
|
||||
'name' => 'Demo Project',
|
||||
'teamId' => $team['body']['$id'],
|
||||
'description' => 'Demo Project Description',
|
||||
|
||||
@@ -8,7 +8,6 @@ use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideClient;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\System\System;
|
||||
|
||||
class FunctionsCustomClientTest extends Scope
|
||||
{
|
||||
@@ -112,7 +111,7 @@ class FunctionsCustomClientTest extends Scope
|
||||
$this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']);
|
||||
$this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']);
|
||||
$this->assertEquals(APP_VERSION_STABLE, $output['APPWRITE_VERSION']);
|
||||
$this->assertEquals(System::getEnv('_APP_REGION', 'default'), $output['APPWRITE_REGION']);
|
||||
$this->assertEquals('default', $output['APPWRITE_REGION']);
|
||||
$this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']);
|
||||
$this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']);
|
||||
$this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']);
|
||||
@@ -222,7 +221,7 @@ class FunctionsCustomClientTest extends Scope
|
||||
$this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']);
|
||||
$this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']);
|
||||
$this->assertEquals(APP_VERSION_STABLE, $output['APPWRITE_VERSION']);
|
||||
$this->assertEquals(System::getEnv('_APP_REGION', 'default'), $output['APPWRITE_REGION']);
|
||||
$this->assertEquals('default', $output['APPWRITE_REGION']);
|
||||
$this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']);
|
||||
$this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']);
|
||||
$this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']);
|
||||
|
||||
@@ -14,7 +14,6 @@ use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\System\System;
|
||||
|
||||
class ProjectsConsoleClientTest extends Scope
|
||||
{
|
||||
@@ -50,7 +49,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Project Test',
|
||||
'teamId' => $team['body']['$id'],
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
@@ -90,7 +89,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => '',
|
||||
'teamId' => $team['body']['$id'],
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
@@ -101,7 +100,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
], $this->getHeaders()), [
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Project Test',
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
@@ -130,7 +129,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => $projectId,
|
||||
'name' => 'Project Duplicate',
|
||||
'teamId' => $teamId,
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(409, $response['headers']['status-code']);
|
||||
@@ -179,7 +178,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Team 1 Project',
|
||||
'teamId' => $team1,
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
'region' => 'default',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
@@ -278,7 +277,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Project Test 2',
|
||||
'teamId' => $team['body']['$id'],
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
@@ -2043,7 +2042,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Project Test',
|
||||
'teamId' => $team['body']['$id'],
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $project['headers']['status-code']);
|
||||
@@ -2136,7 +2135,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Project Test',
|
||||
'teamId' => $team['body']['$id'],
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $project['headers']['status-code']);
|
||||
@@ -3750,7 +3749,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Amazing Project',
|
||||
'teamId' => $teamId,
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $project['headers']['status-code']);
|
||||
@@ -3821,7 +3820,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Amazing Project 1',
|
||||
'teamId' => $teamId,
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$project2 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
|
||||
@@ -3831,7 +3830,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Amazing Project 2',
|
||||
'teamId' => $teamId,
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$project1Id = $project1['body']['$id'];
|
||||
|
||||
@@ -37,37 +37,6 @@ trait TeamsBase
|
||||
$teamUid = $response1['body']['$id'];
|
||||
$teamName = $response1['body']['name'];
|
||||
|
||||
/**
|
||||
* Test: Attempt to downgrade the only OWNER in an organization (should fail)
|
||||
*/
|
||||
if ($this->getProject()['$id'] === 'console') {
|
||||
// Step 1: Fetch all team memberships — only one exists at this point
|
||||
$response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
// Step 2: Extract the membership ID of the only member (also the only OWNER)
|
||||
$membershipID = $response['body']['memberships'][0]['$id'];
|
||||
|
||||
// Step 3: Attempt to downgrade the member's role to 'developer'
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipID, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'roles' => ['developer']
|
||||
]);
|
||||
|
||||
// Step 4: Assert failure — cannot remove the only OWNER from a team
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
$this->assertEquals('general_argument_invalid', $response['body']['type']);
|
||||
$this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']);
|
||||
}
|
||||
|
||||
$teamId = ID::unique();
|
||||
$response2 = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
||||
Reference in New Issue
Block a user