Merge remote-tracking branch 'origin/1.6.x' into feat-apns-content-available

# Conflicts:
#	composer.lock
This commit is contained in:
Jake Barnby
2025-01-15 15:01:55 +13:00
42 changed files with 6981 additions and 7145 deletions
+2
View File
@@ -175,6 +175,8 @@ jobs:
name: Benchmark
runs-on: ubuntu-latest
needs: setup
permissions:
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
+15 -6147
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+126
View File
@@ -0,0 +1,126 @@
<?php
use Utopia\Database\Database;
use Utopia\Database\Helpers\ID;
return [
'collections' => [
'$collection' => ID::custom('databases'),
'$id' => ID::custom('collections'),
'name' => 'Collections',
'attributes' => [
[
'$id' => ID::custom('databaseInternalId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('databaseId'),
'type' => Database::VAR_STRING,
'signed' => true,
'size' => Database::LENGTH_KEY,
'format' => '',
'filters' => [],
'required' => true,
'default' => null,
'array' => false,
],
[
'$id' => ID::custom('name'),
'type' => Database::VAR_STRING,
'size' => 256,
'required' => true,
'signed' => true,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('enabled'),
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'default' => null,
'array' => false,
],
[
'$id' => ID::custom('documentSecurity'),
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'default' => null,
'array' => false,
],
[
'$id' => ID::custom('attributes'),
'type' => Database::VAR_STRING,
'size' => 1000000,
'required' => false,
'signed' => true,
'array' => false,
'filters' => ['subQueryAttributes'],
],
[
'$id' => ID::custom('indexes'),
'type' => Database::VAR_STRING,
'size' => 1000000,
'required' => false,
'signed' => true,
'array' => false,
'filters' => ['subQueryIndexes'],
],
[
'$id' => ID::custom('search'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
'$id' => ID::custom('_fulltext_search'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['search'],
'lengths' => [],
'orders' => [],
],
[
'$id' => ID::custom('_key_name'),
'type' => Database::INDEX_KEY,
'attributes' => ['name'],
'lengths' => [256],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_enabled'),
'type' => Database::INDEX_KEY,
'attributes' => ['enabled'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_documentSecurity'),
'type' => Database::INDEX_KEY,
'attributes' => ['documentSecurity'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
],
]
];
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -1567,7 +1567,8 @@ return [
'required' => false,
'type' => 'number'
]
]
],
'scopes' => []
],
[
'icon' => 'icon-chip',
+1 -1
View File
@@ -6,7 +6,7 @@ return [
Specification::S_05VCPU_512MB => [
'slug' => Specification::S_05VCPU_512MB,
'memory' => 512,
'cpus' => 1 // TODO: revert this, it's a temporary change to test function performance.
'cpus' => 0.5
],
Specification::S_1VCPU_512MB => [
'slug' => Specification::S_1VCPU_512MB,
+2 -2
View File
@@ -5766,7 +5766,7 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 382,
"weight": 376,
"cookies": false,
"type": "",
"deprecated": false,
@@ -5851,7 +5851,7 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 386,
"weight": 380,
"cookies": false,
"type": "",
"deprecated": false,
+91 -350
View File
@@ -13675,7 +13675,7 @@
},
"x-appwrite": {
"method": "listMessages",
"weight": 390,
"weight": 384,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13753,7 +13753,7 @@
},
"x-appwrite": {
"method": "createEmail",
"weight": 387,
"weight": 381,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13899,7 +13899,7 @@
},
"x-appwrite": {
"method": "updateEmail",
"weight": 394,
"weight": 388,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14047,7 +14047,7 @@
},
"x-appwrite": {
"method": "createPush",
"weight": 389,
"weight": 383,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14223,7 +14223,7 @@
},
"x-appwrite": {
"method": "updatePush",
"weight": 396,
"weight": 390,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14403,7 +14403,7 @@
},
"x-appwrite": {
"method": "createSms",
"weight": 388,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14514,7 +14514,7 @@
},
"x-appwrite": {
"method": "updateSms",
"weight": 395,
"weight": 389,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14628,7 +14628,7 @@
},
"x-appwrite": {
"method": "getMessage",
"weight": 393,
"weight": 387,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14683,7 +14683,7 @@
},
"x-appwrite": {
"method": "delete",
"weight": 397,
"weight": 391,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14747,7 +14747,7 @@
},
"x-appwrite": {
"method": "listMessageLogs",
"weight": 391,
"weight": 385,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14824,7 +14824,7 @@
},
"x-appwrite": {
"method": "listTargets",
"weight": 392,
"weight": 386,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14901,7 +14901,7 @@
},
"x-appwrite": {
"method": "listProviders",
"weight": 362,
"weight": 356,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14979,7 +14979,7 @@
},
"x-appwrite": {
"method": "createApnsProvider",
"weight": 361,
"weight": 355,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15086,7 +15086,7 @@
},
"x-appwrite": {
"method": "updateApnsProvider",
"weight": 374,
"weight": 368,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15196,7 +15196,7 @@
},
"x-appwrite": {
"method": "createFcmProvider",
"weight": 360,
"weight": 354,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15283,7 +15283,7 @@
},
"x-appwrite": {
"method": "updateFcmProvider",
"weight": 373,
"weight": 367,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15373,7 +15373,7 @@
},
"x-appwrite": {
"method": "createMailgunProvider",
"weight": 352,
"weight": 346,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15490,7 +15490,7 @@
},
"x-appwrite": {
"method": "updateMailgunProvider",
"weight": 365,
"weight": 359,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15610,7 +15610,7 @@
},
"x-appwrite": {
"method": "createMsg91Provider",
"weight": 355,
"weight": 349,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15707,7 +15707,7 @@
},
"x-appwrite": {
"method": "updateMsg91Provider",
"weight": 368,
"weight": 362,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15807,7 +15807,7 @@
},
"x-appwrite": {
"method": "createSendgridProvider",
"weight": 353,
"weight": 347,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15914,7 +15914,7 @@
},
"x-appwrite": {
"method": "updateSendgridProvider",
"weight": 366,
"weight": 360,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16024,7 +16024,7 @@
},
"x-appwrite": {
"method": "createSmtpProvider",
"weight": 354,
"weight": 348,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16169,7 +16169,7 @@
},
"x-appwrite": {
"method": "updateSmtpProvider",
"weight": 367,
"weight": 361,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16316,7 +16316,7 @@
},
"x-appwrite": {
"method": "createTelesignProvider",
"weight": 356,
"weight": 350,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16413,7 +16413,7 @@
},
"x-appwrite": {
"method": "updateTelesignProvider",
"weight": 369,
"weight": 363,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16513,7 +16513,7 @@
},
"x-appwrite": {
"method": "createTextmagicProvider",
"weight": 357,
"weight": 351,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16610,7 +16610,7 @@
},
"x-appwrite": {
"method": "updateTextmagicProvider",
"weight": 370,
"weight": 364,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16710,7 +16710,7 @@
},
"x-appwrite": {
"method": "createTwilioProvider",
"weight": 358,
"weight": 352,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16807,7 +16807,7 @@
},
"x-appwrite": {
"method": "updateTwilioProvider",
"weight": 371,
"weight": 365,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16907,7 +16907,7 @@
},
"x-appwrite": {
"method": "createVonageProvider",
"weight": 359,
"weight": 353,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17004,7 +17004,7 @@
},
"x-appwrite": {
"method": "updateVonageProvider",
"weight": 372,
"weight": 366,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17104,7 +17104,7 @@
},
"x-appwrite": {
"method": "getProvider",
"weight": 364,
"weight": 358,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17159,7 +17159,7 @@
},
"x-appwrite": {
"method": "deleteProvider",
"weight": 375,
"weight": 369,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17223,7 +17223,7 @@
},
"x-appwrite": {
"method": "listProviderLogs",
"weight": 363,
"weight": 357,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17300,7 +17300,7 @@
},
"x-appwrite": {
"method": "listSubscriberLogs",
"weight": 384,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17377,7 +17377,7 @@
},
"x-appwrite": {
"method": "listTopics",
"weight": 377,
"weight": 371,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17453,7 +17453,7 @@
},
"x-appwrite": {
"method": "createTopic",
"weight": 376,
"weight": 370,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17538,7 +17538,7 @@
},
"x-appwrite": {
"method": "getTopic",
"weight": 379,
"weight": 373,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17600,7 +17600,7 @@
},
"x-appwrite": {
"method": "updateTopic",
"weight": 380,
"weight": 374,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17679,7 +17679,7 @@
},
"x-appwrite": {
"method": "deleteTopic",
"weight": 381,
"weight": 375,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17743,7 +17743,7 @@
},
"x-appwrite": {
"method": "listTopicLogs",
"weight": 378,
"weight": 372,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17820,7 +17820,7 @@
},
"x-appwrite": {
"method": "listSubscribers",
"weight": 383,
"weight": 377,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17906,7 +17906,7 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 382,
"weight": 376,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17998,7 +17998,7 @@
},
"x-appwrite": {
"method": "getSubscriber",
"weight": 385,
"weight": 379,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18063,7 +18063,7 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 386,
"weight": 380,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18140,7 +18140,7 @@
},
"x-appwrite": {
"method": "list",
"weight": 339,
"weight": 338,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18306,7 +18306,7 @@
},
"x-appwrite": {
"method": "getAppwriteReport",
"weight": 341,
"weight": 340,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18381,7 +18381,7 @@
},
"\/migrations\/firebase": {
"post": {
"summary": "Migrate Firebase data (Service Account)",
"summary": "Migrate Firebase data",
"operationId": "migrationsCreateFirebaseMigration",
"tags": [
"migrations"
@@ -18401,7 +18401,7 @@
},
"x-appwrite": {
"method": "createFirebaseMigration",
"weight": 336,
"weight": 335,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18457,177 +18457,6 @@
}
}
},
"\/migrations\/firebase\/deauthorize": {
"get": {
"summary": "Revoke Appwrite's authorization to access Firebase projects",
"operationId": "migrationsDeleteFirebaseAuth",
"tags": [
"migrations"
],
"description": "",
"responses": {
"200": {
"description": "File"
}
},
"x-appwrite": {
"method": "deleteFirebaseAuth",
"weight": 347,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/delete-firebase-auth.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.write",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
]
}
},
"\/migrations\/firebase\/oauth": {
"post": {
"summary": "Migrate Firebase data (OAuth)",
"operationId": "migrationsCreateFirebaseOAuthMigration",
"tags": [
"migrations"
],
"description": "",
"responses": {
"202": {
"description": "Migration",
"content": {
"application\/json": {
"schema": {
"$ref": "#\/components\/schemas\/migration"
}
}
}
}
},
"x-appwrite": {
"method": "createFirebaseOAuthMigration",
"weight": 335,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/create-firebase-o-auth-migration.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.write",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
],
"requestBody": {
"content": {
"application\/json": {
"schema": {
"type": "object",
"properties": {
"resources": {
"type": "array",
"description": "List of resources to migrate",
"x-example": null,
"items": {
"type": "string"
}
},
"projectId": {
"type": "string",
"description": "Project ID of the Firebase Project",
"x-example": "<PROJECT_ID>"
}
},
"required": [
"resources",
"projectId"
]
}
}
}
}
}
},
"\/migrations\/firebase\/projects": {
"get": {
"summary": "List Firebase projects",
"operationId": "migrationsListFirebaseProjects",
"tags": [
"migrations"
],
"description": "",
"responses": {
"200": {
"description": "Migrations Firebase Projects List",
"content": {
"application\/json": {
"schema": {
"$ref": "#\/components\/schemas\/firebaseProjectList"
}
}
}
}
},
"x-appwrite": {
"method": "listFirebaseProjects",
"weight": 346,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/list-firebase-projects.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.read",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
]
}
},
"\/migrations\/firebase\/report": {
"get": {
"summary": "Generate a report on Firebase data",
@@ -18650,7 +18479,7 @@
},
"x-appwrite": {
"method": "getFirebaseReport",
"weight": 342,
"weight": 341,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18702,80 +18531,6 @@
]
}
},
"\/migrations\/firebase\/report\/oauth": {
"get": {
"summary": "Generate a report on Firebase data using OAuth",
"operationId": "migrationsGetFirebaseReportOAuth",
"tags": [
"migrations"
],
"description": "",
"responses": {
"200": {
"description": "Migration Report",
"content": {
"application\/json": {
"schema": {
"$ref": "#\/components\/schemas\/migrationReport"
}
}
}
}
},
"x-appwrite": {
"method": "getFirebaseReportOAuth",
"weight": 343,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/get-firebase-report-o-auth.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.write",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
],
"parameters": [
{
"name": "resources",
"description": "List of resources to migrate",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
}
},
"in": "query"
},
{
"name": "projectId",
"description": "Project ID",
"required": true,
"schema": {
"type": "string",
"x-example": "<PROJECT_ID>"
},
"in": "query"
}
]
}
},
"\/migrations\/nhost": {
"post": {
"summary": "Migrate NHost data",
@@ -18798,7 +18553,7 @@
},
"x-appwrite": {
"method": "createNHostMigration",
"weight": 338,
"weight": 337,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18911,7 +18666,7 @@
},
"x-appwrite": {
"method": "getNHostReport",
"weight": 349,
"weight": 343,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19046,7 +18801,7 @@
},
"x-appwrite": {
"method": "createSupabaseMigration",
"weight": 337,
"weight": 336,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19153,7 +18908,7 @@
},
"x-appwrite": {
"method": "getSupabaseReport",
"weight": 348,
"weight": 342,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19279,7 +19034,7 @@
},
"x-appwrite": {
"method": "get",
"weight": 340,
"weight": 339,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19339,7 +19094,7 @@
},
"x-appwrite": {
"method": "retry",
"weight": 350,
"weight": 344,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19392,7 +19147,7 @@
},
"x-appwrite": {
"method": "delete",
"weight": 351,
"weight": 345,
"cookies": false,
"type": "",
"deprecated": false,
@@ -32791,30 +32546,6 @@
"migrations"
]
},
"firebaseProjectList": {
"description": "Migrations Firebase Projects List",
"type": "object",
"properties": {
"total": {
"type": "integer",
"description": "Total number of projects documents that matched your query.",
"x-example": 5,
"format": "int32"
},
"projects": {
"type": "array",
"description": "List of projects.",
"items": {
"$ref": "#\/components\/schemas\/firebaseProject"
},
"x-example": ""
}
},
"required": [
"total",
"projects"
]
},
"specificationList": {
"description": "Specifications List",
"type": "object",
@@ -37018,7 +36749,8 @@
"resourceId": {
"type": "string",
"description": "Resource ID.",
"x-example": "5e5ea5c16897e"
"x-example": "5e5ea5c16897e",
"nullable": true
},
"name": {
"type": "string",
@@ -37030,10 +36762,16 @@
"description": "The value of this metric at the timestamp.",
"x-example": 1,
"format": "int32"
},
"estimate": {
"type": "number",
"description": "The estimated value of this metric at the end of the period.",
"x-example": 1,
"format": "double",
"nullable": true
}
},
"required": [
"resourceId",
"name",
"value"
]
@@ -37849,6 +37587,26 @@
"$ref": "#\/components\/schemas\/metricBreakdown"
},
"x-example": []
},
"authPhoneTotal": {
"type": "integer",
"description": "Total aggregated number of phone auth.",
"x-example": 0,
"format": "int32"
},
"authPhoneEstimate": {
"type": "number",
"description": "Estimated total aggregated cost of phone auth.",
"x-example": 0,
"format": "double"
},
"authPhoneCountryBreakdown": {
"type": "array",
"description": "Aggregated breakdown in totals of phone auth by country.",
"items": {
"$ref": "#\/components\/schemas\/metricBreakdown"
},
"x-example": []
}
},
"required": [
@@ -37873,7 +37631,10 @@
"databasesStorageBreakdown",
"executionsMbSecondsBreakdown",
"buildsMbSecondsBreakdown",
"functionsStorageBreakdown"
"functionsStorageBreakdown",
"authPhoneTotal",
"authPhoneEstimate",
"authPhoneCountryBreakdown"
]
},
"headers": {
@@ -38749,26 +38510,6 @@
"size",
"version"
]
},
"firebaseProject": {
"description": "MigrationFirebaseProject",
"type": "object",
"properties": {
"projectId": {
"type": "string",
"description": "Project ID.",
"x-example": "my-project"
},
"displayName": {
"type": "string",
"description": "Project display name.",
"x-example": "My Project"
}
},
"required": [
"projectId",
"displayName"
]
}
},
"securitySchemes": {
+46 -46
View File
@@ -12529,7 +12529,7 @@
},
"x-appwrite": {
"method": "listMessages",
"weight": 390,
"weight": 384,
"cookies": false,
"type": "",
"deprecated": false,
@@ -12608,7 +12608,7 @@
},
"x-appwrite": {
"method": "createEmail",
"weight": 387,
"weight": 381,
"cookies": false,
"type": "",
"deprecated": false,
@@ -12755,7 +12755,7 @@
},
"x-appwrite": {
"method": "updateEmail",
"weight": 394,
"weight": 388,
"cookies": false,
"type": "",
"deprecated": false,
@@ -12904,7 +12904,7 @@
},
"x-appwrite": {
"method": "createPush",
"weight": 389,
"weight": 383,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13081,7 +13081,7 @@
},
"x-appwrite": {
"method": "updatePush",
"weight": 396,
"weight": 390,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13262,7 +13262,7 @@
},
"x-appwrite": {
"method": "createSms",
"weight": 388,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13374,7 +13374,7 @@
},
"x-appwrite": {
"method": "updateSms",
"weight": 395,
"weight": 389,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13489,7 +13489,7 @@
},
"x-appwrite": {
"method": "getMessage",
"weight": 393,
"weight": 387,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13545,7 +13545,7 @@
},
"x-appwrite": {
"method": "delete",
"weight": 397,
"weight": 391,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13610,7 +13610,7 @@
},
"x-appwrite": {
"method": "listMessageLogs",
"weight": 391,
"weight": 385,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13688,7 +13688,7 @@
},
"x-appwrite": {
"method": "listTargets",
"weight": 392,
"weight": 386,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13766,7 +13766,7 @@
},
"x-appwrite": {
"method": "listProviders",
"weight": 362,
"weight": 356,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13845,7 +13845,7 @@
},
"x-appwrite": {
"method": "createApnsProvider",
"weight": 361,
"weight": 355,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13953,7 +13953,7 @@
},
"x-appwrite": {
"method": "updateApnsProvider",
"weight": 374,
"weight": 368,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14064,7 +14064,7 @@
},
"x-appwrite": {
"method": "createFcmProvider",
"weight": 360,
"weight": 354,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14152,7 +14152,7 @@
},
"x-appwrite": {
"method": "updateFcmProvider",
"weight": 373,
"weight": 367,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14243,7 +14243,7 @@
},
"x-appwrite": {
"method": "createMailgunProvider",
"weight": 352,
"weight": 346,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14361,7 +14361,7 @@
},
"x-appwrite": {
"method": "updateMailgunProvider",
"weight": 365,
"weight": 359,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14482,7 +14482,7 @@
},
"x-appwrite": {
"method": "createMsg91Provider",
"weight": 355,
"weight": 349,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14580,7 +14580,7 @@
},
"x-appwrite": {
"method": "updateMsg91Provider",
"weight": 368,
"weight": 362,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14681,7 +14681,7 @@
},
"x-appwrite": {
"method": "createSendgridProvider",
"weight": 353,
"weight": 347,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14789,7 +14789,7 @@
},
"x-appwrite": {
"method": "updateSendgridProvider",
"weight": 366,
"weight": 360,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14900,7 +14900,7 @@
},
"x-appwrite": {
"method": "createSmtpProvider",
"weight": 354,
"weight": 348,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15046,7 +15046,7 @@
},
"x-appwrite": {
"method": "updateSmtpProvider",
"weight": 367,
"weight": 361,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15194,7 +15194,7 @@
},
"x-appwrite": {
"method": "createTelesignProvider",
"weight": 356,
"weight": 350,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15292,7 +15292,7 @@
},
"x-appwrite": {
"method": "updateTelesignProvider",
"weight": 369,
"weight": 363,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15393,7 +15393,7 @@
},
"x-appwrite": {
"method": "createTextmagicProvider",
"weight": 357,
"weight": 351,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15491,7 +15491,7 @@
},
"x-appwrite": {
"method": "updateTextmagicProvider",
"weight": 370,
"weight": 364,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15592,7 +15592,7 @@
},
"x-appwrite": {
"method": "createTwilioProvider",
"weight": 358,
"weight": 352,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15690,7 +15690,7 @@
},
"x-appwrite": {
"method": "updateTwilioProvider",
"weight": 371,
"weight": 365,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15791,7 +15791,7 @@
},
"x-appwrite": {
"method": "createVonageProvider",
"weight": 359,
"weight": 353,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15889,7 +15889,7 @@
},
"x-appwrite": {
"method": "updateVonageProvider",
"weight": 372,
"weight": 366,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15990,7 +15990,7 @@
},
"x-appwrite": {
"method": "getProvider",
"weight": 364,
"weight": 358,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16046,7 +16046,7 @@
},
"x-appwrite": {
"method": "deleteProvider",
"weight": 375,
"weight": 369,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16111,7 +16111,7 @@
},
"x-appwrite": {
"method": "listProviderLogs",
"weight": 363,
"weight": 357,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16189,7 +16189,7 @@
},
"x-appwrite": {
"method": "listSubscriberLogs",
"weight": 384,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16267,7 +16267,7 @@
},
"x-appwrite": {
"method": "listTopics",
"weight": 377,
"weight": 371,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16344,7 +16344,7 @@
},
"x-appwrite": {
"method": "createTopic",
"weight": 376,
"weight": 370,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16430,7 +16430,7 @@
},
"x-appwrite": {
"method": "getTopic",
"weight": 379,
"weight": 373,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16493,7 +16493,7 @@
},
"x-appwrite": {
"method": "updateTopic",
"weight": 380,
"weight": 374,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16573,7 +16573,7 @@
},
"x-appwrite": {
"method": "deleteTopic",
"weight": 381,
"weight": 375,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16638,7 +16638,7 @@
},
"x-appwrite": {
"method": "listTopicLogs",
"weight": 378,
"weight": 372,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16716,7 +16716,7 @@
},
"x-appwrite": {
"method": "listSubscribers",
"weight": 383,
"weight": 377,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16803,7 +16803,7 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 382,
"weight": 376,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16897,7 +16897,7 @@
},
"x-appwrite": {
"method": "getSubscriber",
"weight": 385,
"weight": 379,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16963,7 +16963,7 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 386,
"weight": 380,
"cookies": false,
"type": "",
"deprecated": false,
+33 -3
View File
@@ -36749,7 +36749,8 @@
"resourceId": {
"type": "string",
"description": "Resource ID.",
"x-example": "5e5ea5c16897e"
"x-example": "5e5ea5c16897e",
"nullable": true
},
"name": {
"type": "string",
@@ -36761,10 +36762,16 @@
"description": "The value of this metric at the timestamp.",
"x-example": 1,
"format": "int32"
},
"estimate": {
"type": "number",
"description": "The estimated value of this metric at the end of the period.",
"x-example": 1,
"format": "double",
"nullable": true
}
},
"required": [
"resourceId",
"name",
"value"
]
@@ -37580,6 +37587,26 @@
"$ref": "#\/components\/schemas\/metricBreakdown"
},
"x-example": []
},
"authPhoneTotal": {
"type": "integer",
"description": "Total aggregated number of phone auth.",
"x-example": 0,
"format": "int32"
},
"authPhoneEstimate": {
"type": "number",
"description": "Estimated total aggregated cost of phone auth.",
"x-example": 0,
"format": "double"
},
"authPhoneCountryBreakdown": {
"type": "array",
"description": "Aggregated breakdown in totals of phone auth by country.",
"items": {
"$ref": "#\/components\/schemas\/metricBreakdown"
},
"x-example": []
}
},
"required": [
@@ -37604,7 +37631,10 @@
"databasesStorageBreakdown",
"executionsMbSecondsBreakdown",
"buildsMbSecondsBreakdown",
"functionsStorageBreakdown"
"functionsStorageBreakdown",
"authPhoneTotal",
"authPhoneEstimate",
"authPhoneCountryBreakdown"
]
},
"headers": {
+2 -2
View File
@@ -5981,7 +5981,7 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 382,
"weight": 376,
"cookies": false,
"type": "",
"deprecated": false,
@@ -6070,7 +6070,7 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 386,
"weight": 380,
"cookies": false,
"type": "",
"deprecated": false,
+92 -365
View File
@@ -13892,7 +13892,7 @@
},
"x-appwrite": {
"method": "listMessages",
"weight": 390,
"weight": 384,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13969,7 +13969,7 @@
},
"x-appwrite": {
"method": "createEmail",
"weight": 387,
"weight": 381,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14129,7 +14129,7 @@
},
"x-appwrite": {
"method": "updateEmail",
"weight": 394,
"weight": 388,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14286,7 +14286,7 @@
},
"x-appwrite": {
"method": "createPush",
"weight": 389,
"weight": 383,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14483,7 +14483,7 @@
},
"x-appwrite": {
"method": "updatePush",
"weight": 396,
"weight": 390,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14679,7 +14679,7 @@
},
"x-appwrite": {
"method": "createSms",
"weight": 388,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14799,7 +14799,7 @@
},
"x-appwrite": {
"method": "updateSms",
"weight": 395,
"weight": 389,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14917,7 +14917,7 @@
},
"x-appwrite": {
"method": "getMessage",
"weight": 393,
"weight": 387,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14976,7 +14976,7 @@
},
"x-appwrite": {
"method": "delete",
"weight": 397,
"weight": 391,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15040,7 +15040,7 @@
},
"x-appwrite": {
"method": "listMessageLogs",
"weight": 391,
"weight": 385,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15116,7 +15116,7 @@
},
"x-appwrite": {
"method": "listTargets",
"weight": 392,
"weight": 386,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15192,7 +15192,7 @@
},
"x-appwrite": {
"method": "listProviders",
"weight": 362,
"weight": 356,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15269,7 +15269,7 @@
},
"x-appwrite": {
"method": "createApnsProvider",
"weight": 361,
"weight": 355,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15386,7 +15386,7 @@
},
"x-appwrite": {
"method": "updateApnsProvider",
"weight": 374,
"weight": 368,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15501,7 +15501,7 @@
},
"x-appwrite": {
"method": "createFcmProvider",
"weight": 360,
"weight": 354,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15594,7 +15594,7 @@
},
"x-appwrite": {
"method": "updateFcmProvider",
"weight": 373,
"weight": 367,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15685,7 +15685,7 @@
},
"x-appwrite": {
"method": "createMailgunProvider",
"weight": 352,
"weight": 346,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15814,7 +15814,7 @@
},
"x-appwrite": {
"method": "updateMailgunProvider",
"weight": 365,
"weight": 359,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15941,7 +15941,7 @@
},
"x-appwrite": {
"method": "createMsg91Provider",
"weight": 355,
"weight": 349,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16046,7 +16046,7 @@
},
"x-appwrite": {
"method": "updateMsg91Provider",
"weight": 368,
"weight": 362,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16149,7 +16149,7 @@
},
"x-appwrite": {
"method": "createSendgridProvider",
"weight": 353,
"weight": 347,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16266,7 +16266,7 @@
},
"x-appwrite": {
"method": "updateSendgridProvider",
"weight": 366,
"weight": 360,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16381,7 +16381,7 @@
},
"x-appwrite": {
"method": "createSmtpProvider",
"weight": 354,
"weight": 348,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16542,7 +16542,7 @@
},
"x-appwrite": {
"method": "updateSmtpProvider",
"weight": 367,
"weight": 361,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16700,7 +16700,7 @@
},
"x-appwrite": {
"method": "createTelesignProvider",
"weight": 356,
"weight": 350,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16805,7 +16805,7 @@
},
"x-appwrite": {
"method": "updateTelesignProvider",
"weight": 369,
"weight": 363,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16908,7 +16908,7 @@
},
"x-appwrite": {
"method": "createTextmagicProvider",
"weight": 357,
"weight": 351,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17013,7 +17013,7 @@
},
"x-appwrite": {
"method": "updateTextmagicProvider",
"weight": 370,
"weight": 364,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17116,7 +17116,7 @@
},
"x-appwrite": {
"method": "createTwilioProvider",
"weight": 358,
"weight": 352,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17221,7 +17221,7 @@
},
"x-appwrite": {
"method": "updateTwilioProvider",
"weight": 371,
"weight": 365,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17324,7 +17324,7 @@
},
"x-appwrite": {
"method": "createVonageProvider",
"weight": 359,
"weight": 353,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17429,7 +17429,7 @@
},
"x-appwrite": {
"method": "updateVonageProvider",
"weight": 372,
"weight": 366,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17532,7 +17532,7 @@
},
"x-appwrite": {
"method": "getProvider",
"weight": 364,
"weight": 358,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17591,7 +17591,7 @@
},
"x-appwrite": {
"method": "deleteProvider",
"weight": 375,
"weight": 369,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17655,7 +17655,7 @@
},
"x-appwrite": {
"method": "listProviderLogs",
"weight": 363,
"weight": 357,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17731,7 +17731,7 @@
},
"x-appwrite": {
"method": "listSubscriberLogs",
"weight": 384,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17807,7 +17807,7 @@
},
"x-appwrite": {
"method": "listTopics",
"weight": 377,
"weight": 371,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17882,7 +17882,7 @@
},
"x-appwrite": {
"method": "createTopic",
"weight": 376,
"weight": 370,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17974,7 +17974,7 @@
},
"x-appwrite": {
"method": "getTopic",
"weight": 379,
"weight": 373,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18036,7 +18036,7 @@
},
"x-appwrite": {
"method": "updateTopic",
"weight": 380,
"weight": 374,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18119,7 +18119,7 @@
},
"x-appwrite": {
"method": "deleteTopic",
"weight": 381,
"weight": 375,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18183,7 +18183,7 @@
},
"x-appwrite": {
"method": "listTopicLogs",
"weight": 378,
"weight": 372,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18259,7 +18259,7 @@
},
"x-appwrite": {
"method": "listSubscribers",
"weight": 383,
"weight": 377,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18342,7 +18342,7 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 382,
"weight": 376,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18434,7 +18434,7 @@
},
"x-appwrite": {
"method": "getSubscriber",
"weight": 385,
"weight": 379,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18501,7 +18501,7 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 386,
"weight": 380,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18576,7 +18576,7 @@
},
"x-appwrite": {
"method": "list",
"weight": 339,
"weight": 338,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18747,7 +18747,7 @@
},
"x-appwrite": {
"method": "getAppwriteReport",
"weight": 341,
"weight": 340,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18815,7 +18815,7 @@
},
"\/migrations\/firebase": {
"post": {
"summary": "Migrate Firebase data (Service Account)",
"summary": "Migrate Firebase data",
"operationId": "migrationsCreateFirebaseMigration",
"consumes": [
"application\/json"
@@ -18837,7 +18837,7 @@
},
"x-appwrite": {
"method": "createFirebaseMigration",
"weight": 336,
"weight": 335,
"cookies": false,
"type": "",
"deprecated": false,
@@ -18895,192 +18895,6 @@
]
}
},
"\/migrations\/firebase\/deauthorize": {
"get": {
"summary": "Revoke Appwrite's authorization to access Firebase projects",
"operationId": "migrationsDeleteFirebaseAuth",
"consumes": [
"application\/json"
],
"produces": [
"application\/json"
],
"tags": [
"migrations"
],
"description": "",
"responses": {
"200": {
"description": "File",
"schema": {
"type": "file"
}
}
},
"x-appwrite": {
"method": "deleteFirebaseAuth",
"weight": 347,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/delete-firebase-auth.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.write",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
]
}
},
"\/migrations\/firebase\/oauth": {
"post": {
"summary": "Migrate Firebase data (OAuth)",
"operationId": "migrationsCreateFirebaseOAuthMigration",
"consumes": [
"application\/json"
],
"produces": [
"application\/json"
],
"tags": [
"migrations"
],
"description": "",
"responses": {
"202": {
"description": "Migration",
"schema": {
"$ref": "#\/definitions\/migration"
}
}
},
"x-appwrite": {
"method": "createFirebaseOAuthMigration",
"weight": 335,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/create-firebase-o-auth-migration.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.write",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
],
"parameters": [
{
"name": "payload",
"in": "body",
"schema": {
"type": "object",
"properties": {
"resources": {
"type": "array",
"description": "List of resources to migrate",
"default": null,
"x-example": null,
"items": {
"type": "string"
}
},
"projectId": {
"type": "string",
"description": "Project ID of the Firebase Project",
"default": null,
"x-example": "<PROJECT_ID>"
}
},
"required": [
"resources",
"projectId"
]
}
}
]
}
},
"\/migrations\/firebase\/projects": {
"get": {
"summary": "List Firebase projects",
"operationId": "migrationsListFirebaseProjects",
"consumes": [
"application\/json"
],
"produces": [
"application\/json"
],
"tags": [
"migrations"
],
"description": "",
"responses": {
"200": {
"description": "Migrations Firebase Projects List",
"schema": {
"$ref": "#\/definitions\/firebaseProjectList"
}
}
},
"x-appwrite": {
"method": "listFirebaseProjects",
"weight": 346,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/list-firebase-projects.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.read",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
]
}
},
"\/migrations\/firebase\/report": {
"get": {
"summary": "Generate a report on Firebase data",
@@ -19105,7 +18919,7 @@
},
"x-appwrite": {
"method": "getFirebaseReport",
"weight": 342,
"weight": 341,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19154,79 +18968,6 @@
]
}
},
"\/migrations\/firebase\/report\/oauth": {
"get": {
"summary": "Generate a report on Firebase data using OAuth",
"operationId": "migrationsGetFirebaseReportOAuth",
"consumes": [
"application\/json"
],
"produces": [
"application\/json"
],
"tags": [
"migrations"
],
"description": "",
"responses": {
"200": {
"description": "Migration Report",
"schema": {
"$ref": "#\/definitions\/migrationReport"
}
}
},
"x-appwrite": {
"method": "getFirebaseReportOAuth",
"weight": 343,
"cookies": false,
"type": "",
"deprecated": false,
"demo": "migrations\/get-firebase-report-o-auth.md",
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md",
"rate-limit": 0,
"rate-time": 3600,
"rate-key": "url:{url},ip:{ip}",
"scope": "migrations.write",
"platforms": [
"console"
],
"packaging": false,
"offline-model": "",
"offline-key": "",
"offline-response-key": "$id",
"auth": {
"Project": []
}
},
"security": [
{
"Project": []
}
],
"parameters": [
{
"name": "resources",
"description": "List of resources to migrate",
"required": true,
"type": "array",
"collectionFormat": "multi",
"items": {
"type": "string"
},
"in": "query"
},
{
"name": "projectId",
"description": "Project ID",
"required": true,
"type": "string",
"x-example": "<PROJECT_ID>",
"in": "query"
}
]
}
},
"\/migrations\/nhost": {
"post": {
"summary": "Migrate NHost data",
@@ -19251,7 +18992,7 @@
},
"x-appwrite": {
"method": "createNHostMigration",
"weight": 338,
"weight": 337,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19374,7 +19115,7 @@
},
"x-appwrite": {
"method": "getNHostReport",
"weight": 349,
"weight": 343,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19496,7 +19237,7 @@
},
"x-appwrite": {
"method": "createSupabaseMigration",
"weight": 337,
"weight": 336,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19612,7 +19353,7 @@
},
"x-appwrite": {
"method": "getSupabaseReport",
"weight": 348,
"weight": 342,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19727,7 +19468,7 @@
},
"x-appwrite": {
"method": "get",
"weight": 340,
"weight": 339,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19787,7 +19528,7 @@
},
"x-appwrite": {
"method": "retry",
"weight": 350,
"weight": 344,
"cookies": false,
"type": "",
"deprecated": false,
@@ -19842,7 +19583,7 @@
},
"x-appwrite": {
"method": "delete",
"weight": 351,
"weight": 345,
"cookies": false,
"type": "",
"deprecated": false,
@@ -33298,31 +33039,6 @@
"migrations"
]
},
"firebaseProjectList": {
"description": "Migrations Firebase Projects List",
"type": "object",
"properties": {
"total": {
"type": "integer",
"description": "Total number of projects documents that matched your query.",
"x-example": 5,
"format": "int32"
},
"projects": {
"type": "array",
"description": "List of projects.",
"items": {
"type": "object",
"$ref": "#\/definitions\/firebaseProject"
},
"x-example": ""
}
},
"required": [
"total",
"projects"
]
},
"specificationList": {
"description": "Specifications List",
"type": "object",
@@ -37542,7 +37258,8 @@
"resourceId": {
"type": "string",
"description": "Resource ID.",
"x-example": "5e5ea5c16897e"
"x-example": "5e5ea5c16897e",
"x-nullable": true
},
"name": {
"type": "string",
@@ -37554,10 +37271,16 @@
"description": "The value of this metric at the timestamp.",
"x-example": 1,
"format": "int32"
},
"estimate": {
"type": "number",
"description": "The estimated value of this metric at the end of the period.",
"x-example": 1,
"format": "double",
"x-nullable": true
}
},
"required": [
"resourceId",
"name",
"value"
]
@@ -38417,6 +38140,27 @@
"$ref": "#\/definitions\/metricBreakdown"
},
"x-example": []
},
"authPhoneTotal": {
"type": "integer",
"description": "Total aggregated number of phone auth.",
"x-example": 0,
"format": "int32"
},
"authPhoneEstimate": {
"type": "number",
"description": "Estimated total aggregated cost of phone auth.",
"x-example": 0,
"format": "double"
},
"authPhoneCountryBreakdown": {
"type": "array",
"description": "Aggregated breakdown in totals of phone auth by country.",
"items": {
"type": "object",
"$ref": "#\/definitions\/metricBreakdown"
},
"x-example": []
}
},
"required": [
@@ -38441,7 +38185,10 @@
"databasesStorageBreakdown",
"executionsMbSecondsBreakdown",
"buildsMbSecondsBreakdown",
"functionsStorageBreakdown"
"functionsStorageBreakdown",
"authPhoneTotal",
"authPhoneEstimate",
"authPhoneCountryBreakdown"
]
},
"headers": {
@@ -39322,26 +39069,6 @@
"size",
"version"
]
},
"firebaseProject": {
"description": "MigrationFirebaseProject",
"type": "object",
"properties": {
"projectId": {
"type": "string",
"description": "Project ID.",
"x-example": "my-project"
},
"displayName": {
"type": "string",
"description": "Project display name.",
"x-example": "My Project"
}
},
"required": [
"projectId",
"displayName"
]
}
},
"externalDocs": {
+46 -46
View File
@@ -12754,7 +12754,7 @@
},
"x-appwrite": {
"method": "listMessages",
"weight": 390,
"weight": 384,
"cookies": false,
"type": "",
"deprecated": false,
@@ -12832,7 +12832,7 @@
},
"x-appwrite": {
"method": "createEmail",
"weight": 387,
"weight": 381,
"cookies": false,
"type": "",
"deprecated": false,
@@ -12993,7 +12993,7 @@
},
"x-appwrite": {
"method": "updateEmail",
"weight": 394,
"weight": 388,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13151,7 +13151,7 @@
},
"x-appwrite": {
"method": "createPush",
"weight": 389,
"weight": 383,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13349,7 +13349,7 @@
},
"x-appwrite": {
"method": "updatePush",
"weight": 396,
"weight": 390,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13546,7 +13546,7 @@
},
"x-appwrite": {
"method": "createSms",
"weight": 388,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13667,7 +13667,7 @@
},
"x-appwrite": {
"method": "updateSms",
"weight": 395,
"weight": 389,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13786,7 +13786,7 @@
},
"x-appwrite": {
"method": "getMessage",
"weight": 393,
"weight": 387,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13846,7 +13846,7 @@
},
"x-appwrite": {
"method": "delete",
"weight": 397,
"weight": 391,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13911,7 +13911,7 @@
},
"x-appwrite": {
"method": "listMessageLogs",
"weight": 391,
"weight": 385,
"cookies": false,
"type": "",
"deprecated": false,
@@ -13988,7 +13988,7 @@
},
"x-appwrite": {
"method": "listTargets",
"weight": 392,
"weight": 386,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14065,7 +14065,7 @@
},
"x-appwrite": {
"method": "listProviders",
"weight": 362,
"weight": 356,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14143,7 +14143,7 @@
},
"x-appwrite": {
"method": "createApnsProvider",
"weight": 361,
"weight": 355,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14261,7 +14261,7 @@
},
"x-appwrite": {
"method": "updateApnsProvider",
"weight": 374,
"weight": 368,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14377,7 +14377,7 @@
},
"x-appwrite": {
"method": "createFcmProvider",
"weight": 360,
"weight": 354,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14471,7 +14471,7 @@
},
"x-appwrite": {
"method": "updateFcmProvider",
"weight": 373,
"weight": 367,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14563,7 +14563,7 @@
},
"x-appwrite": {
"method": "createMailgunProvider",
"weight": 352,
"weight": 346,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14693,7 +14693,7 @@
},
"x-appwrite": {
"method": "updateMailgunProvider",
"weight": 365,
"weight": 359,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14821,7 +14821,7 @@
},
"x-appwrite": {
"method": "createMsg91Provider",
"weight": 355,
"weight": 349,
"cookies": false,
"type": "",
"deprecated": false,
@@ -14927,7 +14927,7 @@
},
"x-appwrite": {
"method": "updateMsg91Provider",
"weight": 368,
"weight": 362,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15031,7 +15031,7 @@
},
"x-appwrite": {
"method": "createSendgridProvider",
"weight": 353,
"weight": 347,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15149,7 +15149,7 @@
},
"x-appwrite": {
"method": "updateSendgridProvider",
"weight": 366,
"weight": 360,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15265,7 +15265,7 @@
},
"x-appwrite": {
"method": "createSmtpProvider",
"weight": 354,
"weight": 348,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15427,7 +15427,7 @@
},
"x-appwrite": {
"method": "updateSmtpProvider",
"weight": 367,
"weight": 361,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15586,7 +15586,7 @@
},
"x-appwrite": {
"method": "createTelesignProvider",
"weight": 356,
"weight": 350,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15692,7 +15692,7 @@
},
"x-appwrite": {
"method": "updateTelesignProvider",
"weight": 369,
"weight": 363,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15796,7 +15796,7 @@
},
"x-appwrite": {
"method": "createTextmagicProvider",
"weight": 357,
"weight": 351,
"cookies": false,
"type": "",
"deprecated": false,
@@ -15902,7 +15902,7 @@
},
"x-appwrite": {
"method": "updateTextmagicProvider",
"weight": 370,
"weight": 364,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16006,7 +16006,7 @@
},
"x-appwrite": {
"method": "createTwilioProvider",
"weight": 358,
"weight": 352,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16112,7 +16112,7 @@
},
"x-appwrite": {
"method": "updateTwilioProvider",
"weight": 371,
"weight": 365,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16216,7 +16216,7 @@
},
"x-appwrite": {
"method": "createVonageProvider",
"weight": 359,
"weight": 353,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16322,7 +16322,7 @@
},
"x-appwrite": {
"method": "updateVonageProvider",
"weight": 372,
"weight": 366,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16426,7 +16426,7 @@
},
"x-appwrite": {
"method": "getProvider",
"weight": 364,
"weight": 358,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16486,7 +16486,7 @@
},
"x-appwrite": {
"method": "deleteProvider",
"weight": 375,
"weight": 369,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16551,7 +16551,7 @@
},
"x-appwrite": {
"method": "listProviderLogs",
"weight": 363,
"weight": 357,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16628,7 +16628,7 @@
},
"x-appwrite": {
"method": "listSubscriberLogs",
"weight": 384,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16705,7 +16705,7 @@
},
"x-appwrite": {
"method": "listTopics",
"weight": 377,
"weight": 371,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16781,7 +16781,7 @@
},
"x-appwrite": {
"method": "createTopic",
"weight": 376,
"weight": 370,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16874,7 +16874,7 @@
},
"x-appwrite": {
"method": "getTopic",
"weight": 379,
"weight": 373,
"cookies": false,
"type": "",
"deprecated": false,
@@ -16937,7 +16937,7 @@
},
"x-appwrite": {
"method": "updateTopic",
"weight": 380,
"weight": 374,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17021,7 +17021,7 @@
},
"x-appwrite": {
"method": "deleteTopic",
"weight": 381,
"weight": 375,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17086,7 +17086,7 @@
},
"x-appwrite": {
"method": "listTopicLogs",
"weight": 378,
"weight": 372,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17163,7 +17163,7 @@
},
"x-appwrite": {
"method": "listSubscribers",
"weight": 383,
"weight": 377,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17247,7 +17247,7 @@
},
"x-appwrite": {
"method": "createSubscriber",
"weight": 382,
"weight": 376,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17341,7 +17341,7 @@
},
"x-appwrite": {
"method": "getSubscriber",
"weight": 385,
"weight": 379,
"cookies": false,
"type": "",
"deprecated": false,
@@ -17409,7 +17409,7 @@
},
"x-appwrite": {
"method": "deleteSubscriber",
"weight": 386,
"weight": 380,
"cookies": false,
"type": "",
"deprecated": false,
+34 -3
View File
@@ -37258,7 +37258,8 @@
"resourceId": {
"type": "string",
"description": "Resource ID.",
"x-example": "5e5ea5c16897e"
"x-example": "5e5ea5c16897e",
"x-nullable": true
},
"name": {
"type": "string",
@@ -37270,10 +37271,16 @@
"description": "The value of this metric at the timestamp.",
"x-example": 1,
"format": "int32"
},
"estimate": {
"type": "number",
"description": "The estimated value of this metric at the end of the period.",
"x-example": 1,
"format": "double",
"x-nullable": true
}
},
"required": [
"resourceId",
"name",
"value"
]
@@ -38133,6 +38140,27 @@
"$ref": "#\/definitions\/metricBreakdown"
},
"x-example": []
},
"authPhoneTotal": {
"type": "integer",
"description": "Total aggregated number of phone auth.",
"x-example": 0,
"format": "int32"
},
"authPhoneEstimate": {
"type": "number",
"description": "Estimated total aggregated cost of phone auth.",
"x-example": 0,
"format": "double"
},
"authPhoneCountryBreakdown": {
"type": "array",
"description": "Aggregated breakdown in totals of phone auth by country.",
"items": {
"type": "object",
"$ref": "#\/definitions\/metricBreakdown"
},
"x-example": []
}
},
"required": [
@@ -38157,7 +38185,10 @@
"databasesStorageBreakdown",
"executionsMbSecondsBreakdown",
"buildsMbSecondsBreakdown",
"functionsStorageBreakdown"
"functionsStorageBreakdown",
"authPhoneTotal",
"authPhoneEstimate",
"authPhoneCountryBreakdown"
]
},
"headers": {
+82 -6
View File
@@ -17,6 +17,7 @@ use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Mail;
use Appwrite\Event\Messaging;
use Appwrite\Event\Usage;
use Appwrite\Extend\Exception;
use Appwrite\Hooks\Hooks;
use Appwrite\Network\Validator\Email;
@@ -27,7 +28,9 @@ use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Identities;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use libphonenumber\PhoneNumberUtil;
use MaxMind\Db\Reader;
use Utopia\Abuse\Abuse;
use Utopia\App;
use Utopia\Audit\Audit as EventAudit;
use Utopia\Config\Config;
@@ -275,7 +278,7 @@ App::post('/v1/account')
->desc('Create account')
->groups(['api', 'account', 'auth'])
->label('scope', 'sessions.write')
->label('auth.type', 'emailPassword')
->label('auth.type', 'email-password')
->label('audits.event', 'user.create')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
@@ -796,7 +799,7 @@ App::post('/v1/account/sessions/email')
->groups(['api', 'account', 'auth', 'session'])
->label('event', 'users.[userId].sessions.[sessionId].create')
->label('scope', 'sessions.write')
->label('auth.type', 'emailPassword')
->label('auth.type', 'email-password')
->label('audits.event', 'session.create')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
@@ -2315,7 +2318,10 @@ App::post('/v1/account/tokens/phone')
->inject('queueForEvents')
->inject('queueForMessaging')
->inject('locale')
->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale) {
->inject('timelimit')
->inject('queueForUsage')
->inject('plan')
->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, Usage $queueForUsage, array $plan) {
if (empty(System::getEnv('_APP_SMS_PROVIDER'))) {
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
}
@@ -2452,6 +2458,27 @@ App::post('/v1/account/tokens/phone')
->setMessage($messageDoc)
->setRecipients([$phone])
->setProviderType(MESSAGE_TYPE_SMS);
if (isset($plan['authPhone'])) {
$timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days
$timelimit
->setParam('{organizationId}', $project->getAttribute('teamId'));
$abuse = new Abuse($timelimit);
if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
$helper = PhoneNumberUtil::getInstance();
$countryCode = $helper->parse($phone)->getCountryCode();
if (!empty($countryCode)) {
$queueForUsage
->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1);
}
}
$queueForUsage
->addMetric(METRIC_AUTH_METHOD_PHONE, 1)
->setProject($project)
->trigger();
}
}
// Set to unhashed secret for events and server responses
@@ -3465,7 +3492,10 @@ App::post('/v1/account/verification/phone')
->inject('queueForMessaging')
->inject('project')
->inject('locale')
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale) {
->inject('timelimit')
->inject('queueForUsage')
->inject('plan')
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, Usage $queueForUsage, array $plan) {
if (empty(System::getEnv('_APP_SMS_PROVIDER'))) {
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
}
@@ -3548,6 +3578,27 @@ App::post('/v1/account/verification/phone')
->setMessage($messageDoc)
->setRecipients([$user->getAttribute('phone')])
->setProviderType(MESSAGE_TYPE_SMS);
if (isset($plan['authPhone'])) {
$timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days
$timelimit
->setParam('{organizationId}', $project->getAttribute('teamId'));
$abuse = new Abuse($timelimit);
if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
$helper = PhoneNumberUtil::getInstance();
$countryCode = $helper->parse($phone)->getCountryCode();
if (!empty($countryCode)) {
$queueForUsage
->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1);
}
}
$queueForUsage
->addMetric(METRIC_AUTH_METHOD_PHONE, 1)
->setProject($project)
->trigger();
}
}
// Set to unhashed secret for events and server responses
@@ -4026,7 +4077,10 @@ App::post('/v1/account/mfa/challenge')
->inject('queueForEvents')
->inject('queueForMessaging')
->inject('queueForMails')
->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails) {
->inject('timelimit')
->inject('queueForUsage')
->inject('plan')
->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails, callable $timelimit, Usage $queueForUsage, array $plan) {
$expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM);
$code = Auth::codeGenerator();
@@ -4074,6 +4128,7 @@ App::post('/v1/account/mfa/challenge')
$message = $message->render();
$phone = $user->getAttribute('phone');
$queueForMessaging
->setType(MESSAGE_SEND_TYPE_INTERNAL)
->setMessage(new Document([
@@ -4082,8 +4137,29 @@ App::post('/v1/account/mfa/challenge')
'content' => $code,
],
]))
->setRecipients([$user->getAttribute('phone')])
->setRecipients([$phone])
->setProviderType(MESSAGE_TYPE_SMS);
if (isset($plan['authPhone'])) {
$timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days
$timelimit
->setParam('{organizationId}', $project->getAttribute('teamId'));
$abuse = new Abuse($timelimit);
if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
$helper = PhoneNumberUtil::getInstance();
$countryCode = $helper->parse($phone)->getCountryCode();
if (!empty($countryCode)) {
$queueForUsage
->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1);
}
}
$queueForUsage
->addMetric(METRIC_AUTH_METHOD_PHONE, 1)
->setProject($project)
->trigger();
}
break;
case Type::EMAIL:
if (empty(System::getEnv('_APP_SMTP_HOST'))) {
+75 -16
View File
@@ -2944,7 +2944,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
$data['$permissions'] = $permissions;
$document = new Document($data);
$checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database) {
$operations = 0;
$checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) {
$operations++;
$documentSecurity = $collection->getAttribute('documentSecurity', false);
$validator = new Authorization($permission);
@@ -3036,6 +3040,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$document->setAttribute('$databaseId', $database->getId());
@@ -3071,6 +3076,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
$processDocument($collection, $document);
$queueForUsage
->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
$response->addHeader('X-Debug-Operations', $operations);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($document, Response::MODEL_DOCUMENT);
@@ -3090,10 +3102,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->setContext('collection', $collection)
->setContext('database', $database)
->setPayload($response->getPayload(), sensitive: $relationships);
$queueForUsage
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection
});
App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
@@ -3116,7 +3124,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) {
->inject('queueForUsage')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
@@ -3152,7 +3161,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
}
$documentId = $cursor->getValue();
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId));
@@ -3167,12 +3175,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT);
$operations = 0;
// Add $collectionId and $databaseId for all documents
$processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool {
$processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool {
if ($document->isEmpty()) {
return false;
}
$operations++;
$document->removeAttribute('$collection');
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@@ -3186,8 +3198,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$related = $document->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
if (\in_array(\gettype($related), ['array', 'object'])) {
$operations++;
}
continue;
}
if (!\is_array($related)) {
$relations = [$related];
} else {
@@ -3195,6 +3212,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
}
$relatedCollectionId = $relationship->getAttribute('relatedCollection');
// todo: Use local cache for this getDocument
$relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId));
foreach ($relations as $index => $doc) {
@@ -3219,6 +3237,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$processDocument($collection, $document);
}
$queueForUsage
->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations)
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations)
;
$response->addHeader('X-Debug-Operations', $operations);
$select = \array_reduce($queries, function ($result, $query) {
return $result || ($query->getMethod() === Query::TYPE_SELECT);
}, false);
@@ -3274,9 +3299,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode) {
->inject('queueForUsage')
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode, Usage $queueForUsage) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
@@ -3303,12 +3328,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
}
$operations = 0;
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) {
if ($document->isEmpty()) {
return;
}
$operations++;
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@@ -3321,8 +3350,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$related = $document->getAttribute($relationship->getAttribute('key'));
if (empty($related)) {
if (\in_array(\gettype($related), ['array', 'object'])) {
$operations++;
}
continue;
}
if (!\is_array($related)) {
$related = [$related];
}
@@ -3342,6 +3376,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$processDocument($collection, $document);
$queueForUsage
->addMetric(METRIC_DATABASES_OPERATIONS_READS, $operations)
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations)
;
$response->addHeader('X-Debug-Operations', $operations);
$response->dynamic($document, Response::MODEL_DOCUMENT);
});
@@ -3444,6 +3485,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
}
}
$response->dynamic(new Document([
'total' => $audit->countLogsByResource($resource),
'logs' => $output,
@@ -3481,7 +3523,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
->inject('dbForProject')
->inject('queueForEvents')
->inject('mode')
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, string $mode) {
->inject('queueForUsage')
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Usage $queueForUsage) {
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
@@ -3548,7 +3591,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$data['$permissions'] = $permissions;
$newDocument = new Document($data);
$setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) {
$operations = 0;
$setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) {
$operations++;
$relationships = \array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
@@ -3616,6 +3664,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$setCollection($collection, $newDocument);
$queueForUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $operations)
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations)
;
$response->addHeader('X-Debug-Operations', $operations);
try {
$document = $dbForProject->withRequestTimestamp(
$requestTimestamp,
@@ -3787,6 +3842,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
$processDocument($collection, $document);
$queueForUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1)
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1)
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection
$response->addHeader('X-Debug-Operations', 1);
$relationships = \array_map(
fn ($document) => $document->getAttribute('key'),
\array_filter(
@@ -3803,9 +3865,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
->setContext('database', $database)
->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships);
$queueForUsage
->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection
$response->noContent();
});
+45 -1
View File
@@ -31,7 +31,8 @@ App::get('/v1/project/usage')
->param('period', '1d', new WhiteList(['1h', '1d']), 'Period used', true)
->inject('response')
->inject('dbForProject')
->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject) {
->inject('smsRates')
->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject, array $smsRates) {
$stats = $total = $usage = [];
$format = 'Y-m-d 00:00:00';
$firstDay = (new DateTime($startDate))->format($format);
@@ -257,6 +258,46 @@ App::get('/v1/project/usage')
];
}, $dbForProject->find('functions'));
// This total is includes free and paid SMS usage
$authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [
Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]),
Query::equal('period', ['1d']),
Query::greaterThanEqual('time', $firstDay),
Query::lessThan('time', $lastDay),
]));
// This estimate is only for paid SMS usage
$authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [
Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'),
Query::equal('period', ['1d']),
Query::greaterThanEqual('time', $firstDay),
Query::lessThan('time', $lastDay),
]));
$authPhoneEstimate = 0.0;
$authPhoneCountryBreakdown = [];
foreach ($authPhoneMetrics as $metric) {
$parts = explode('.', $metric->getAttribute('metric'));
$countryCode = $parts[3] ?? null;
if ($countryCode === null) {
continue;
}
$value = $metric->getAttribute('value', 0);
if (isset($smsRates[$countryCode])) {
$authPhoneEstimate += $value * $smsRates[$countryCode];
}
$authPhoneCountryBreakdown[] = [
'name' => $countryCode,
'value' => $value,
'estimate' => isset($smsRates[$countryCode])
? $value * $smsRates[$countryCode]
: 0.0,
];
}
// merge network inbound + outbound
$projectBandwidth = [];
foreach ($usage[METRIC_NETWORK_INBOUND] as $item) {
@@ -303,6 +344,9 @@ App::get('/v1/project/usage')
'executionsMbSecondsBreakdown' => $executionsMbSecondsBreakdown,
'buildsMbSecondsBreakdown' => $buildsMbSecondsBreakdown,
'functionsStorageBreakdown' => $functionsStorageBreakdown,
'authPhoneTotal' => $authPhoneTotal,
'authPhoneEstimate' => $authPhoneEstimate,
'authPhoneCountryBreakdown' => $authPhoneCountryBreakdown,
]), Response::MODEL_USAGE_PROJECT);
});
+6
View File
@@ -60,6 +60,7 @@ App::post('/v1/projects')
->desc('Create project')
->groups(['api', 'projects'])
->label('audits.event', 'projects.create')
->label('audits.resource', 'project/{response.$id}')
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
@@ -367,6 +368,8 @@ App::patch('/v1/projects/:projectId')
->desc('Update project')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('audits.event', 'projects.update')
->label('audits.resource', 'project/{request.projectId}')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
->label('sdk.method', 'update')
@@ -981,6 +984,7 @@ App::delete('/v1/projects/:projectId')
->desc('Delete project')
->groups(['api', 'projects'])
->label('audits.event', 'projects.delete')
->label('audits.resource', 'project/{request.projectId}')
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
@@ -1514,6 +1518,7 @@ App::post('/v1/projects/:projectId/platforms')
->desc('Create platform')
->groups(['api', 'projects'])
->label('audits.event', 'platforms.create')
->label('audits.resource', 'project/{request.projectId}')
->label('scope', 'platforms.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
@@ -1678,6 +1683,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
->desc('Delete platform')
->groups(['api', 'projects'])
->label('audits.event', 'platforms.delete')
->label('audits.resource', 'project/{request.projectId}/platform/${request.platformId}')
->label('scope', 'platforms.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
+8 -1
View File
@@ -6,6 +6,7 @@ use Appwrite\Auth\Auth;
use Appwrite\ClamAV\Network;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Usage;
use Appwrite\Extend\Exception;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Utopia\Database\Validator\CustomId;
@@ -886,7 +887,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
->inject('mode')
->inject('deviceForFiles')
->inject('deviceForLocal')
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal) {
->inject('queueForUsage')
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal, Usage $queueForUsage) {
if (!\extension_loaded('imagick')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
@@ -1014,6 +1016,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
$contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg'];
$queueForUsage
->addMetric(METRIC_FILES_TRANSFORMATIONS, 1)
->addMetric(str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_TRANSFORMATIONS), 1)
;
$response
->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days
->setContentType($contentType)
+28 -1
View File
@@ -8,6 +8,7 @@ use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Mail;
use Appwrite\Event\Messaging;
use Appwrite\Event\Usage;
use Appwrite\Extend\Exception;
use Appwrite\Network\Validator\Email;
use Appwrite\Platform\Workers\Deletes;
@@ -17,7 +18,9 @@ use Appwrite\Utopia\Database\Validator\Queries\Memberships;
use Appwrite\Utopia\Database\Validator\Queries\Teams;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use libphonenumber\PhoneNumberUtil;
use MaxMind\Db\Reader;
use Utopia\Abuse\Abuse;
use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Config\Config;
@@ -423,7 +426,10 @@ App::post('/v1/teams/:teamId/memberships')
->inject('queueForMails')
->inject('queueForMessaging')
->inject('queueForEvents')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents) {
->inject('timelimit')
->inject('queueForUsage')
->inject('plan')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, Usage $queueForUsage, array $plan) {
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
@@ -691,6 +697,27 @@ App::post('/v1/teams/:teamId/memberships')
->setMessage($messageDoc)
->setRecipients([$phone])
->setProviderType('SMS');
if (isset($plan['authPhone'])) {
$timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days
$timelimit
->setParam('{organizationId}', $project->getAttribute('teamId'));
$abuse = new Abuse($timelimit);
if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
$helper = PhoneNumberUtil::getInstance();
$countryCode = $helper->parse($phone)->getCountryCode();
if (!empty($countryCode)) {
$queueForUsage
->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1);
}
}
$queueForUsage
->addMetric(METRIC_AUTH_METHOD_PHONE, 1)
->setProject($project)
->trigger();
}
}
}
+6
View File
@@ -1814,6 +1814,12 @@ App::post('/v1/users/:userId/sessions')
$detector->getDevice()
));
$session->setAttribute('$permissions', [
Permission::read(Role::user($user->getId())),
Permission::update(Role::user($user->getId())),
Permission::delete(Role::user($user->getId())),
]);
$countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'));
$session = $dbForProject->createDocument('sessions', $session);
+45 -64
View File
@@ -355,53 +355,6 @@ App::get('/v1/vcs/github/callback')
throw new Exception(Exception::PROJECT_NOT_FOUND, $error);
}
$personalSlug = '';
// OAuth Authroization
if (!empty($code)) {
$oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), "");
$accessToken = $oauth2->getAccessToken($code) ?? '';
$refreshToken = $oauth2->getRefreshToken($code) ?? '';
$accessTokenExpiry = $oauth2->getAccessTokenExpiry($code) ?? '';
$personalSlug = $oauth2->getUserSlug($accessToken) ?? '';
$email = $oauth2->getUserEmail($accessToken);
$oauth2ID = $oauth2->getUserID($accessToken);
// Makes sure this email is not already used in another identity
$identity = $dbForPlatform->findOne('identities', [
Query::equal('providerEmail', [$email]),
]);
if (!$identity->isEmpty()) {
if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
}
$identity = $identity
->setAttribute('providerAccessToken', $accessToken)
->setAttribute('providerRefreshToken', $refreshToken)
->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry));
$dbForPlatform->updateDocument('identities', $identity->getId(), $identity);
} else {
$identity = $dbForPlatform->createDocument('identities', new Document([
'$id' => ID::unique(),
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::user($user->getId())),
Permission::delete(Role::user($user->getId())),
],
'userInternalId' => $user->getInternalId(),
'userId' => $user->getId(),
'provider' => 'github',
'providerUid' => $oauth2ID,
'providerEmail' => $email,
'providerAccessToken' => $accessToken,
'providerRefreshToken' => $refreshToken,
'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry),
]));
}
}
// Create / Update installation
if (!empty($providerInstallationId)) {
$privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY');
@@ -416,6 +369,22 @@ App::get('/v1/vcs/github/callback')
Query::equal('projectInternalId', [$projectInternalId])
]);
$personal = false;
$refreshToken = null;
$accessToken = null;
$accessTokenExpiry = null;
if (!empty($code)) {
$oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), "");
$accessToken = $oauth2->getAccessToken($code) ?? '';
$refreshToken = $oauth2->getRefreshToken($code) ?? '';
$accessTokenExpiry = DateTime::addSeconds(new \DateTime(), \intval($oauth2->getAccessTokenExpiry($code)));
$personalSlug = $oauth2->getUserSlug($accessToken) ?? '';
$personal = $personalSlug === $owner;
}
if ($installation->isEmpty()) {
$teamId = $project->getAttribute('teamId', '');
@@ -433,14 +402,20 @@ App::get('/v1/vcs/github/callback')
'projectInternalId' => $projectInternalId,
'provider' => 'github',
'organization' => $owner,
'personal' => $personalSlug === $owner
'personal' => $personal,
'personalRefreshToken' => $refreshToken,
'personalAccessToken' => $accessToken,
'personalAccessTokenExpiry' => $accessTokenExpiry,
]);
$installation = $dbForPlatform->createDocument('installations', $installation);
} else {
$installation = $installation
->setAttribute('organization', $owner)
->setAttribute('personal', $personalSlug === $owner);
->setAttribute('personal', $personal)
->setAttribute('personalRefreshToken', $refreshToken)
->setAttribute('personalAccessToken', $accessToken)
->setAttribute('personalAccessTokenExpiry', $accessTokenExpiry);
$installation = $dbForPlatform->updateDocument('installations', $installation->getId(), $installation);
}
} else {
@@ -720,17 +695,23 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories')
if ($installation->getAttribute('personal', false) === true) {
$oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), "");
$identity = $dbForPlatform->findOne('identities', [
Query::equal('provider', ['github']),
Query::equal('userInternalId', [$user->getInternalId()]),
]);
if ($identity->isEmpty()) {
throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
}
$accessToken = $installation->getAttribute('personalAccessToken');
$refreshToken = $installation->getAttribute('personalRefreshToken');
$accessTokenExpiry = $installation->getAttribute('personalAccessTokenExpiry');
$accessToken = $identity->getAttribute('providerAccessToken');
$refreshToken = $identity->getAttribute('providerRefreshToken');
$accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry');
if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) {
$identity = $dbForPlatform->findOne('identities', [
Query::equal('provider', ['github']),
Query::equal('userInternalId', [$user->getInternalId()]),
]);
if ($identity->isEmpty()) {
throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
}
$accessToken = $accessToken ?? $identity->getAttribute('providerAccessToken');
$refreshToken = $refreshToken ?? $identity->getAttribute('providerRefreshToken');
$accessTokenExpiry = $accessTokenExpiry ?? $identity->getAttribute('providerAccessTokenExpiry');
}
$isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now');
if ($isExpired) {
@@ -745,12 +726,12 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories')
throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, "Another request is currently refreshing OAuth token. Please try again.");
}
$identity = $identity
->setAttribute('providerAccessToken', $accessToken)
->setAttribute('providerRefreshToken', $refreshToken)
->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry('')));
$installation = $installation
->setAttribute('personalAccessToken', $accessToken)
->setAttribute('personalRefreshToken', $refreshToken)
->setAttribute('personalAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry('')));
$dbForPlatform->updateDocument('identities', $identity->getId(), $identity);
$dbForPlatform->updateDocument('installations', $installation->getId(), $installation);
}
try {
+2 -2
View File
@@ -835,7 +835,7 @@ App::error()
$adapter = new Sentry($projectId, $key, $host);
$logger = new Logger($adapter);
$logger->setSample(0.04);
$logger->setSample(0.01);
$publish = true;
} else {
throw new \Exception('Invalid experimental logging provider');
@@ -894,7 +894,7 @@ App::error()
$log->addTag('database', $dsn->getHost());
$log->addTag('method', $route->getMethod());
$log->addTag('url', $route->getPath());
$log->addTag('url', $request->getURI());
$log->addTag('verboseType', get_class($error));
$log->addTag('code', $error->getCode());
$log->addTag('projectId', $project->getId());
+1
View File
@@ -506,6 +506,7 @@ App::init()
->setMode($mode)
->setUserAgent($request->getUserAgent(''))
->setIP($request->getIP())
->setHostname($request->getHostname())
->setEvent($route->getLabel('audits.event', ''))
->setProject($project)
->setUser($user);
+9 -8
View File
@@ -5,6 +5,7 @@ use Appwrite\Extend\Exception;
use Appwrite\Utopia\Request;
use MaxMind\Db\Reader;
use Utopia\App;
use Utopia\Config\Config;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
@@ -57,44 +58,44 @@ App::init()
$auths = $project->getAttribute('auths', []);
switch ($route->getLabel('auth.type', '')) {
case 'emailPassword':
if (($auths['emailPassword'] ?? true) === false) {
case 'email-password':
if (($auths[Config::getParam('auth')['email-password']['key']] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email / Password authentication is disabled for this project');
}
break;
case 'magic-url':
if (($auths['usersAuthMagicURL'] ?? true) === false) {
if (($auths[Config::getParam('auth')['magic-url']['key']] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Magic URL authentication is disabled for this project');
}
break;
case 'anonymous':
if (($auths['anonymous'] ?? true) === false) {
if (($auths[Config::getParam('auth')['anonymous']['key']] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Anonymous authentication is disabled for this project');
}
break;
case 'phone':
if (($auths['phone'] ?? true) === false) {
if (($auths[Config::getParam('auth')['phone']['key']] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Phone authentication is disabled for this project');
}
break;
case 'invites':
if (($auths['invites'] ?? true) === false) {
if (($auths[Config::getParam('auth')['invites']['key']] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Invites authentication is disabled for this project');
}
break;
case 'jwt':
if (($auths['JWT'] ?? true) === false) {
if (($auths[Config::getParam('auth')['jwt']['key']] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'JWT authentication is disabled for this project');
}
break;
case 'email-otp':
if (($auths['emailOTP'] ?? true) === false) {
if (($auths[Config::getParam('auth')['email-otp']['key']] ?? true) === false) {
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email OTP authentication is disabled for this project');
}
break;
+1 -1
View File
@@ -42,7 +42,7 @@ $http = new Server(
);
$payloadSize = 12 * (1024 * 1024); // 12MB - adding slight buffer for headers and other data that might be sent with the payload - update later with valid testing
$totalWorkers = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
$totalWorkers = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
$http
->set([
+17 -1
View File
@@ -259,9 +259,15 @@ const METRIC_DOCUMENTS = 'documents';
const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents';
const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage';
const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads';
const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads';
const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes';
const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes';
const METRIC_BUCKETS = 'buckets';
const METRIC_FILES = 'files';
const METRIC_FILES_STORAGE = 'files.storage';
const METRIC_FILES_TRANSFORMATIONS = 'files.transformations';
const METRIC_BUCKET_ID_FILES_TRANSFORMATIONS = '{bucketInternalId}.files.transformations';
const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files';
const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage';
const METRIC_FUNCTIONS = 'functions';
@@ -876,6 +882,12 @@ $register->set('pools', function () {
'multiple' => true,
'schemes' => ['mariadb', 'mysql'],
],
'logs' => [
'type' => 'database',
'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB),
'multiple' => false,
'schemes' => ['mariadb', 'mysql'],
],
'queue' => [
'type' => 'queue',
'dsns' => $fallbackForRedis,
@@ -902,7 +914,7 @@ $register->set('pools', function () {
$multiprocessing = System::getEnv('_APP_SERVER_MULTIPROCESS', 'disabled') === 'enabled';
if ($multiprocessing) {
$workerCount = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
$workerCount = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
} else {
$workerCount = 1;
}
@@ -1830,6 +1842,10 @@ App::setResource('plan', function (array $plan = []) {
return [];
});
App::setResource('smsRates', function () {
return [];
});
App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) {
$teamInternalId = '';
if ($project->getId() !== 'console') {
+1 -1
View File
@@ -193,7 +193,7 @@ $stats->create();
$containerId = uniqid();
$statsDocument = null;
$workerNumber = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
$workerNumber = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6));
$adapter = new Adapter\Swoole(port: System::getEnv('PORT', 80));
$adapter
+2 -2
View File
@@ -47,11 +47,11 @@
"appwrite/php-clamav": "2.0.*",
"utopia-php/abuse": "0.46.*",
"utopia-php/analytics": "0.10.*",
"utopia-php/audit": "0.43.*",
"utopia-php/audit": "0.46.*",
"utopia-php/cache": "0.11.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.53.200",
"utopia-php/database": "0.53.32",
"utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
Generated
+47 -47
View File
@@ -709,16 +709,16 @@
},
{
"name": "google/protobuf",
"version": "v4.29.2",
"version": "v4.29.3",
"source": {
"type": "git",
"url": "https://github.com/protocolbuffers/protobuf-php.git",
"reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945"
"reference": "ab5077c2cfdd1f415f42d11fdbdf903ba8e3d9b7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/79aa5014efeeec3d137df5cdb0ae2fc163953945",
"reference": "79aa5014efeeec3d137df5cdb0ae2fc163953945",
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/ab5077c2cfdd1f415f42d11fdbdf903ba8e3d9b7",
"reference": "ab5077c2cfdd1f415f42d11fdbdf903ba8e3d9b7",
"shasum": ""
},
"require": {
@@ -747,9 +747,9 @@
"proto"
],
"support": {
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.2"
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.3"
},
"time": "2024-12-18T14:11:12+00:00"
"time": "2025-01-08T21:00:13+00:00"
},
{
"name": "jean85/pretty-package-versions",
@@ -1237,16 +1237,16 @@
},
{
"name": "open-telemetry/api",
"version": "1.1.2",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/api.git",
"reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed"
"reference": "351a30baa79699de3de3a814c8ccc7b52ccdfb1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/api/zipball/04c85a1e41a3d59fa9bdc801a5de1df6624b95ed",
"reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed",
"url": "https://api.github.com/repos/opentelemetry-php/api/zipball/351a30baa79699de3de3a814c8ccc7b52ccdfb1d",
"reference": "351a30baa79699de3de3a814c8ccc7b52ccdfb1d",
"shasum": ""
},
"require": {
@@ -1303,7 +1303,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2024-11-16T04:32:30+00:00"
"time": "2025-01-08T23:50:34+00:00"
},
{
"name": "open-telemetry/context",
@@ -1366,16 +1366,16 @@
},
{
"name": "open-telemetry/exporter-otlp",
"version": "1.1.0",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/exporter-otlp.git",
"reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18"
"reference": "243d9657c44a06f740cf384f486afe954c2b725f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/9b6de12204f25f8ab9540b46d6e7b5151897ce18",
"reference": "9b6de12204f25f8ab9540b46d6e7b5151897ce18",
"url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/243d9657c44a06f740cf384f486afe954c2b725f",
"reference": "243d9657c44a06f740cf384f486afe954c2b725f",
"shasum": ""
},
"require": {
@@ -1426,7 +1426,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2024-04-30T18:28:30+00:00"
"time": "2025-01-08T23:50:03+00:00"
},
{
"name": "open-telemetry/gen-otlp-protobuf",
@@ -1493,16 +1493,16 @@
},
{
"name": "open-telemetry/sdk",
"version": "1.1.2",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/sdk.git",
"reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b"
"reference": "9a1c3b866239dbff291e5cc555bb7793eab08127"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/fb0ff8d8279a3776bd604791e2531dd0cc147e8b",
"reference": "fb0ff8d8279a3776bd604791e2531dd0cc147e8b",
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/9a1c3b866239dbff291e5cc555bb7793eab08127",
"reference": "9a1c3b866239dbff291e5cc555bb7793eab08127",
"shasum": ""
},
"require": {
@@ -1579,7 +1579,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2024-10-18T21:01:35+00:00"
"time": "2025-01-08T23:50:34+00:00"
},
{
"name": "open-telemetry/sem-conv",
@@ -3136,16 +3136,16 @@
},
{
"name": "utopia-php/abuse",
"version": "0.46.0",
"version": "0.46.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "bef426a9a28b3e71b08216bcbe310455f588c11b"
"reference": "59749df988430b28953fb5cabfad88b0ff5b539b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/bef426a9a28b3e71b08216bcbe310455f588c11b",
"reference": "bef426a9a28b3e71b08216bcbe310455f588c11b",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/59749df988430b28953fb5cabfad88b0ff5b539b",
"reference": "59749df988430b28953fb5cabfad88b0ff5b539b",
"shasum": ""
},
"require": {
@@ -3153,7 +3153,7 @@
"ext-pdo": "*",
"ext-redis": "*",
"php": ">=8.0",
"utopia-php/database": "0.53.200"
"utopia-php/database": "0.53.32"
},
"require-dev": {
"laravel/pint": "1.5.*",
@@ -3181,9 +3181,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.46.0"
"source": "https://github.com/utopia-php/abuse/tree/0.46.2"
},
"time": "2024-12-27T17:46:08+00:00"
"time": "2025-01-13T02:09:43+00:00"
},
{
"name": "utopia-php/analytics",
@@ -3233,21 +3233,21 @@
},
{
"name": "utopia-php/audit",
"version": "0.43.1",
"version": "0.46.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277"
"reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/04a47dd1f5f92e2d50e971a06bcc9e759325d277",
"reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/21255fa1ce66433140a43d380b2859c7f0a0bb37",
"reference": "21255fa1ce66433140a43d380b2859c7f0a0bb37",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/database": "0.53.*"
"utopia-php/database": "0.53.32"
},
"require-dev": {
"laravel/pint": "1.5.*",
@@ -3274,9 +3274,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.43.1"
"source": "https://github.com/utopia-php/audit/tree/0.46.1"
},
"time": "2024-10-23T04:27:59+00:00"
"time": "2025-01-13T02:19:56+00:00"
},
{
"name": "utopia-php/cache",
@@ -3476,16 +3476,16 @@
},
{
"name": "utopia-php/database",
"version": "0.53.200",
"version": "0.53.32",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "570c63a3760d0e1404679ddfacd9484af40bd9fc"
"reference": "981a1241139b42dccd531511130b79137740b205"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/570c63a3760d0e1404679ddfacd9484af40bd9fc",
"reference": "570c63a3760d0e1404679ddfacd9484af40bd9fc",
"url": "https://api.github.com/repos/utopia-php/database/zipball/981a1241139b42dccd531511130b79137740b205",
"reference": "981a1241139b42dccd531511130b79137740b205",
"shasum": ""
},
"require": {
@@ -3526,9 +3526,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.53.200"
"source": "https://github.com/utopia-php/database/tree/0.53.32"
},
"time": "2024-12-01T07:59:15+00:00"
"time": "2025-01-10T08:53:47+00:00"
},
{
"name": "utopia-php/domains",
@@ -3929,16 +3929,16 @@
},
{
"name": "utopia-php/migration",
"version": "0.6.13",
"version": "0.6.14",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "68d9b0a9477755afcda607e7e8109785cae17a13"
"reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/68d9b0a9477755afcda607e7e8109785cae17a13",
"reference": "68d9b0a9477755afcda607e7e8109785cae17a13",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2",
"reference": "59a19f09ded0ccab4c8cca35b1242c01e2b9cfd2",
"shasum": ""
},
"require": {
@@ -3979,9 +3979,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/0.6.13"
"source": "https://github.com/utopia-php/migration/tree/0.6.14"
},
"time": "2024-11-26T13:57:53+00:00"
"time": "2025-01-08T01:07:25+00:00"
},
{
"name": "utopia-php/mongo",
+26
View File
@@ -11,6 +11,7 @@ class Audit extends Event
protected string $mode = '';
protected string $userAgent = '';
protected string $ip = '';
protected string $hostname = '';
public function __construct(protected Connection $connection)
{
@@ -113,6 +114,30 @@ class Audit extends Event
return $this->ip;
}
/**
* Set the hostname.
*
* @param string $hostname
*
* @return self
*/
public function setHostname(string $hostname): self
{
$this->hostname = $hostname;
return $this;
}
/**
* Get the hostname.
*
* @return string
*/
public function getHostname(): string
{
return $this->hostname;
}
/**
* Executes the event and sends it to the audit worker.
*
@@ -136,6 +161,7 @@ class Audit extends Event
'ip' => $this->ip,
'userAgent' => $this->userAgent,
'event' => $this->event,
'hostname' => $this->hostname
]);
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ class Messaging extends Event
/**
* Sets type for the build event.
*
* @param string $type Can be `MESSAGE_TYPE_INTERNAL` or `MESSAGE_TYPE_EXTERNAL`.
* @param string $type Can be `MESSAGE_SEND_TYPE_INTERNAL` or `MESSAGE_SEND_TYPE_EXTERNAL`.
* @return self
*/
public function setType(string $type): self
@@ -284,8 +284,6 @@ class Databases extends Action
$dbForProject->deleteDocument('attributes', $relatedAttribute->getId());
}
throw $e;
} catch (\Throwable $e) {
Console::error($e->getMessage());
+4 -14
View File
@@ -97,7 +97,7 @@ class Messaging extends Action
$message = new Document($payload['message'] ?? []);
$recipients = $payload['recipients'] ?? [];
$this->sendInternalSMSMessage($message, $project, $recipients, $queueForUsage, $log);
$this->sendInternalSMSMessage($message, $project, $recipients, $log);
break;
case MESSAGE_SEND_TYPE_EXTERNAL:
$message = $dbForProject->getDocument('messages', $payload['messageId']);
@@ -377,7 +377,7 @@ class Messaging extends Action
}
}
private function sendInternalSMSMessage(Document $message, Document $project, array $recipients, Usage $queueForUsage, Log $log): void
private function sendInternalSMSMessage(Document $message, Document $project, array $recipients, Log $log): void
{
if (empty(System::getEnv('_APP_SMS_PROVIDER')) || empty(System::getEnv('_APP_SMS_FROM'))) {
throw new \Exception('Skipped SMS processing. Missing "_APP_SMS_PROVIDER" or "_APP_SMS_FROM" environment variables.');
@@ -456,24 +456,14 @@ class Messaging extends Action
$adapter->getMaxMessagesPerRequest()
);
batch(\array_map(function ($batch) use ($message, $provider, $adapter, $project, $queueForUsage) {
return function () use ($batch, $message, $provider, $adapter, $project, $queueForUsage) {
batch(\array_map(function ($batch) use ($message, $provider, $adapter) {
return function () use ($batch, $message, $provider, $adapter) {
$message->setAttribute('to', $batch);
$data = $this->buildSmsMessage($message, $provider);
try {
$adapter->send($data);
$countryCode = $adapter->getCountryCode($message['to'][0] ?? '');
if (!empty($countryCode)) {
$queueForUsage
->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1);
}
$queueForUsage
->addMetric(METRIC_AUTH_METHOD_PHONE, 1)
->setProject($project)
->trigger();
} catch (\Throwable $th) {
throw new \Exception('Failed sending to targets with error: ' . $th->getMessage());
}
@@ -15,6 +15,7 @@ class MetricBreakdown extends Model
'description' => 'Resource ID.',
'default' => '',
'example' => '5e5ea5c16897e',
'required' => false,
])
->addRule('name', [
'type' => self::TYPE_STRING,
@@ -27,6 +28,13 @@ class MetricBreakdown extends Model
'description' => 'The value of this metric at the timestamp.',
'default' => 0,
'example' => 1,
])
->addRule('estimate', [
'type' => self::TYPE_FLOAT,
'description' => 'The estimated value of this metric at the end of the period.',
'default' => 0,
'example' => 1,
'required' => false,
]);
}
@@ -152,6 +152,25 @@ class UsageProject extends Model
'example' => [],
'array' => true
])
->addRule('authPhoneTotal', [
'type' => self::TYPE_INTEGER,
'description' => 'Total aggregated number of phone auth.',
'default' => 0,
'example' => 0,
])
->addRule('authPhoneEstimate', [
'type' => self::TYPE_FLOAT,
'description' => 'Estimated total aggregated cost of phone auth.',
'default' => 0,
'example' => 0,
])
->addRule('authPhoneCountryBreakdown', [
'type' => Response::MODEL_METRIC_BREAKDOWN,
'description' => 'Aggregated breakdown in totals of phone auth by country.',
'default' => [],
'example' => [],
'array' => true
])
;
}
+3 -3
View File
@@ -143,7 +143,7 @@ class UsageTest extends Scope
);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(22, count($response['body']));
$this->assertEquals(25, count($response['body']));
$this->validateDates($response['body']['network']);
$this->validateDates($response['body']['requests']);
$this->validateDates($response['body']['users']);
@@ -324,7 +324,7 @@ class UsageTest extends Scope
]
);
$this->assertEquals(22, count($response['body']));
$this->assertEquals(25, count($response['body']));
$this->assertEquals(1, count($response['body']['requests']));
$this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']);
$this->validateDates($response['body']['requests']);
@@ -545,7 +545,7 @@ class UsageTest extends Scope
]
);
$this->assertEquals(22, count($response['body']));
$this->assertEquals(25, count($response['body']));
$this->assertEquals(1, count($response['body']['requests']));
$this->assertEquals(1, count($response['body']['network']));
$this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']);
@@ -2,6 +2,7 @@
namespace Tests\E2E\Services\Messaging;
use Appwrite\Tests\Async;
use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
@@ -11,6 +12,8 @@ use Utopia\Database\Query;
class MessagingConsoleClientTest extends Scope
{
use Async;
use MessagingBase;
use ProjectCustom;
use SideConsole;
@@ -54,15 +57,18 @@ class MessagingConsoleClientTest extends Scope
$this->assertEquals(200, $response['headers']['status-code']);
$logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
// required for Cloud x Audits
$this->assertEventually(function () use ($provider) {
$logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertIsNumeric($logs['body']['total']);
$this->assertCount(2, $logs['body']['logs']);
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertIsNumeric($logs['body']['total']);
$this->assertCount(2, $logs['body']['logs']);
});
$logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([
'content-type' => 'application/json',
@@ -485,6 +485,8 @@ class ProjectsConsoleClientTest extends Scope
$this->assertIsNumeric($response['body']['usersTotal']);
$this->assertIsNumeric($response['body']['filesStorageTotal']);
$this->assertIsNumeric($response['body']['deploymentStorageTotal']);
$this->assertIsNumeric($response['body']['authPhoneTotal']);
$this->assertIsNumeric($response['body']['authPhoneEstimate']);
/**
+8
View File
@@ -318,6 +318,14 @@ trait UsersBase
]);
$this->assertEquals(200, $response['headers']['status-code']);
$response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/current', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-session' => $session['secret']
]);
$this->assertEquals(204, $response['headers']['status-code']);
}