mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '0.8.x' of github.com:appwrite/appwrite into feat-god-user
This commit is contained in:
@@ -3,6 +3,7 @@ _APP_ENV=development
|
||||
_APP_CONSOLE_WHITELIST_GOD=disabled
|
||||
_APP_CONSOLE_WHITELIST_EMAILS=
|
||||
_APP_CONSOLE_WHITELIST_IPS=
|
||||
_APP_LOCALE=en
|
||||
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
||||
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
|
||||
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io
|
||||
@@ -19,7 +20,7 @@ _APP_DB_PORT=3306
|
||||
_APP_DB_SCHEMA=appwrite
|
||||
_APP_DB_USER=user
|
||||
_APP_DB_PASS=password
|
||||
_APP_STORAGE_ANTIVIRUS=enabled
|
||||
_APP_STORAGE_ANTIVIRUS=disabled
|
||||
_APP_STORAGE_ANTIVIRUS_HOST=clamav
|
||||
_APP_STORAGE_ANTIVIRUS_PORT=3310
|
||||
_APP_INFLUXDB_HOST=influxdb
|
||||
@@ -27,7 +28,7 @@ _APP_INFLUXDB_PORT=8086
|
||||
_APP_STATSD_HOST=telegraf
|
||||
_APP_STATSD_PORT=8125
|
||||
_APP_SMTP_HOST=maildev
|
||||
_APP_SMTP_PORT=25
|
||||
_APP_SMTP_PORT=1025
|
||||
_APP_SMTP_SECURE=
|
||||
_APP_SMTP_USERNAME=
|
||||
_APP_SMTP_PASSWORD=
|
||||
|
||||
+1
-6
@@ -15,12 +15,7 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating git repository $1 / $2"
|
||||
|
||||
git fetch origin
|
||||
git reset --hard origin/master
|
||||
|
||||
if test $(find "./app/db/DBIP/dbip-country-lite-2020-01.mmdb" -mmin +259200)
|
||||
if test $(find "./app/db/DBIP/dbip-country-lite-2021-02.mmdb" -mmin +259200)
|
||||
then
|
||||
printf "${RED}GEO country DB has not been updated for more than 6 months. Go to https://db-ip.com/db/download/ip-to-country-lite to download a newer version${NC}\n"
|
||||
fi
|
||||
|
||||
+3
-4
@@ -2,6 +2,7 @@ dist: xenial
|
||||
|
||||
arch:
|
||||
- amd64
|
||||
- arm64
|
||||
|
||||
os: linux
|
||||
|
||||
@@ -10,9 +11,6 @@ language: shell
|
||||
notifications:
|
||||
email:
|
||||
- team@appwrite.io
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
before_install:
|
||||
- curl -fsSL https://get.docker.com | sh
|
||||
@@ -27,6 +25,7 @@ before_install:
|
||||
- docker --version
|
||||
- docker buildx create --use
|
||||
- chmod -R u+x ./.travis-ci
|
||||
- export COMPOSE_INTERACTIVE_NO_CLI=1
|
||||
|
||||
install:
|
||||
- docker-compose up -d
|
||||
@@ -38,7 +37,7 @@ script:
|
||||
- docker-compose logs appwrite-worker-functions
|
||||
- docker-compose exec appwrite doctor
|
||||
- docker-compose exec appwrite vars
|
||||
- docker-compose exec appwrite test
|
||||
- docker-compose exec appwrite test --debug
|
||||
|
||||
deploy:
|
||||
- provider: script
|
||||
|
||||
+71
-5
@@ -1,15 +1,71 @@
|
||||
# Version 0.8.0 (Not Released Yet)
|
||||
|
||||
- Anonymous login
|
||||
|
||||
# Version 0.7.1 (Not Released Yet)
|
||||
|
||||
## Features
|
||||
|
||||
- Added Anonymous Login ([RFC-010](https://github.com/appwrite/rfc/blob/main/010-anonymous-login.md), #914)
|
||||
- Added events for functions and executions (#971)
|
||||
- Added JWT support
|
||||
- Added ARM support
|
||||
- Splited token & session models to become 2 different internal entities (#922)
|
||||
- Added Dart 2.12 as a new Cloud Functions runtime (#989)
|
||||
- Added option to disable email/password
|
||||
- Added option to disable anonymous login (need to merge and apply changed)
|
||||
- Added option to disable JWT auth
|
||||
- Added option to disable team invites
|
||||
- Option to limit number of users (good for app launches + god account PR)
|
||||
- Added 2 new endpoints to the projects API to allow new settings
|
||||
- Enabled 501 errors (Not Implemented) from the error handler
|
||||
- Added Python 3.9 as a new Cloud Functions runtime
|
||||
- Added Deno 1.8 as a new Cloud Functions runtime (#989)
|
||||
- ClamAV is now disabled by default to allow lower min requirments for Appwrite (#1064)
|
||||
- Added a new env var named `_APP_LOCALE` that allow to change the default `en` locale value (#1056)
|
||||
- Updated all the console bottom control to be consistent. Dropped the `+` icon (#1062)
|
||||
|
||||
## Bugs
|
||||
|
||||
- Fixed default value for HTTPS force option
|
||||
- Fixed form array casting in dashboard
|
||||
- Fixed collection document rule form in dashboard
|
||||
|
||||
## Breaking Changes (Read before upgrading!)
|
||||
|
||||
- Rename `deleteuser` to `delete` on Users Api
|
||||
- Only logged in users can execute functions (for guests, use anonymous login)
|
||||
- Only the user who has triggered the execution get access to the relevant execution logs
|
||||
- Function execution env `APPWRITE_FUNCTION_EVENT_PAYLOAD` renamed to `APPWRITE_FUNCTION_EVENT_DATA`
|
||||
- Introdcues rate limits for:
|
||||
- Team invite (10 requests in every 60 minutes per IP address)
|
||||
|
||||
# Version 0.7.2
|
||||
|
||||
## Features
|
||||
|
||||
- When creating new resources from the client API, the current user gets both read & write permissions by default. (#1007)
|
||||
- Added timestamp to errors logs on the HTTP API container (#1002)
|
||||
- Added verbose tests output on the terminal and CI (#1006)
|
||||
|
||||
## Upgrades
|
||||
|
||||
- Upgraded utopia-php/abuse to version 0.4.0
|
||||
- Upgraded utopia-php/analytics to version 0.2.0
|
||||
|
||||
## Bugs
|
||||
|
||||
- Fixed certificates worker error on successful operations (#1010)
|
||||
- Fixed head requests not responding (#998)
|
||||
- Fixed bug when using auth credential for the Redis container (#993)
|
||||
- Fixed server warning logs on 3** redirect endpoints (#1013)
|
||||
|
||||
# Version 0.7.1
|
||||
|
||||
## Features
|
||||
|
||||
- Better error logs on appwrite certificates worker
|
||||
- Added option for Redis authentication
|
||||
- Force adding a security email on setup
|
||||
- Better error logs on appwrite cretificates worker## Upgrades
|
||||
- SMTP is now disabled by default, no dummy SMTP is included in setup
|
||||
- Added a new endpoint that returns the server and SDKs latest versions numbers #941
|
||||
- Custom data strings, userId, and JWT available for cloud functions #967
|
||||
|
||||
## Upgrades
|
||||
|
||||
@@ -21,10 +77,20 @@
|
||||
- Upgraded influxdb/influxdb-php lib to version 1.15.2
|
||||
- Upgraded phpmailer/phpmailer lib to version 6.3.0
|
||||
- Upgraded adhocore/jwt lib to version 1.1.2
|
||||
- Upgraded domnikl/statsd to slickdeals/statsd version 3.0
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Updated missing storage env vars
|
||||
- Fixed a bug, that added a wrong timzone offset to user log timestamps
|
||||
- Fixed a bug, that Response format header was not added in the access-control-allow-header list.
|
||||
- Fixed a bug where countryName is unknown on sessions (#933)
|
||||
- Added missing event users.update.prefs (#952)
|
||||
- Fixed bug not allowing to reset document permissions (#977)
|
||||
|
||||
## Security
|
||||
|
||||
- Fixed an XSS vulnerability in the Appwrite console
|
||||
|
||||
# Version 0.7.0
|
||||
|
||||
|
||||
+33
-4
@@ -90,6 +90,35 @@ Appwrite uses an internal micro-framework called Litespeed.js to build simple UI
|
||||
|
||||
After finishing the installation process, you can start writing and editing code.
|
||||
|
||||
|
||||
#### Advanced Topics
|
||||
We love to create issues that are good for beginners and label them as `good first issue` or `hacktoberfest`, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn more about some of the more advance topics that will help you master the Appwrite codebase.
|
||||
|
||||
##### Tools and Libs
|
||||
- [Docker](https://www.docker.com/get-started)
|
||||
- [PHP FIG](https://www.php-fig.org/) - [PSR-1](https://www.php-fig.org/psr/psr-1/) and [PSR-4](https://www.php-fig.org/psr/psr-4/)
|
||||
- [PHP Swoole](https://www.swoole.co.uk/)
|
||||
|
||||
Learn more at our [Technology Stack](## Technology Stack) section.
|
||||
|
||||
##### Network and Protocols
|
||||
- [OSI Model](https://en.wikipedia.org/wiki/OSI_model)
|
||||
- [TCP vs UDP](https://www.guru99.com/tcp-vs-udp-understanding-the-difference.html#:~:text=TCP%20is%20a%20connection%2Doriented,speed%20of%20UDP%20is%20faster&text=TCP%20does%20error%20checking%20and,but%20it%20discards%20erroneous%20packets.)
|
||||
- [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol)
|
||||
- [REST API](https://en.wikipedia.org/wiki/Representational_state_transfer)
|
||||
- [GraphQL](https://en.wikipedia.org/wiki/GraphQL)
|
||||
- [gRPC](https://en.wikipedia.org/wiki/GRPC)
|
||||
|
||||
##### Architecture
|
||||
- [Microservices vs Monolithic](https://www.mulesoft.com/resources/api/microservices-vs-monolithic#:~:text=Microservices%20architecture%20vs%20monolithic%20architecture&text=A%20monolithic%20application%20is%20built%20as%20a%20single%20unit.&text=To%20make%20any%20alterations%20to,formally%20with%20business%2Doriented%20APIs.)
|
||||
- [MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel) - Appwrite console architecture
|
||||
|
||||
##### Security
|
||||
- [Appwrite Auth and ACL](https://github.com/appwrite/appwrite/blob/0.7.x/docs/specs/authentication.drawio.svg)
|
||||
- [OAuth](https://en.wikipedia.org/wiki/OAuth)
|
||||
- [Encryption](https://medium.com/searchencrypt/what-is-encryption-how-does-it-work-e8f20e340537#:~:text=Encryption%20is%20a%20process%20that,%2C%20or%20decrypt%2C%20the%20information.)
|
||||
- [Hashing](https://searchsqlserver.techtarget.com/definition/hashing#:~:text=Hashing%20is%20the%20transformation%20of,it%20using%20the%20original%20value.)
|
||||
|
||||
## Architecture
|
||||
|
||||
Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures, but our final goal, as we grow, is to be using only microservices.
|
||||
@@ -114,7 +143,6 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
|
||||
├── docs # Docs and tutorials
|
||||
│ ├── examples
|
||||
│ ├── references
|
||||
│ ├── sdks
|
||||
│ ├── services
|
||||
│ ├── specs
|
||||
│ └── tutorials
|
||||
@@ -128,13 +156,14 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
|
||||
│ └── Appwrite
|
||||
│ ├── Auth
|
||||
│ ├── Database
|
||||
│ ├── Detector
|
||||
│ ├── Docker
|
||||
│ ├── Event
|
||||
│ ├── Extend
|
||||
│ ├── Migration
|
||||
│ ├── Network
|
||||
│ ├── OpenSSL
|
||||
│ ├── Resize
|
||||
│ ├── Storage
|
||||
│ ├── Specification
|
||||
│ ├── Task
|
||||
│ ├── Template
|
||||
│ ├── URL
|
||||
@@ -336,7 +365,7 @@ From time to time, our team will add tutorials that will help contributors find
|
||||
* [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
|
||||
* [Appwrite Environment Variables](./docs/tutorials/environment-variables.md)
|
||||
* [Running in Production](./docs/tutorials/running-in-production.md)
|
||||
|
||||
* [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
|
||||
|
||||
## Other Ways to Help
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ ARG VERSION=dev
|
||||
|
||||
ENV _APP_SERVER=swoole \
|
||||
_APP_ENV=production \
|
||||
_APP_LOCALE=en \
|
||||
_APP_DOMAIN=localhost \
|
||||
_APP_DOMAIN_TARGET=localhost \
|
||||
_APP_HOME=https://appwrite.io \
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker<nobr> microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.
|
||||
|
||||
Using Appwrite, you can easily integrate your app with user authentication & multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, schedule CRON tasks, and [more services](https://appwrite.io/docs).
|
||||
Using Appwrite, you can easily integrate your app with user authentication & multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, and [more services](https://appwrite.io/docs).
|
||||
|
||||

|
||||
|
||||
@@ -53,7 +53,7 @@ docker run -it --rm \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||
--entrypoint="install" \
|
||||
appwrite/appwrite:0.7.0
|
||||
appwrite/appwrite:0.8.0
|
||||
```
|
||||
|
||||
### Windows
|
||||
@@ -65,7 +65,7 @@ docker run -it --rm ^
|
||||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||
--entrypoint="install" ^
|
||||
appwrite/appwrite:0.7.0
|
||||
appwrite/appwrite:0.8.0
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
@@ -75,13 +75,13 @@ docker run -it --rm ,
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock ,
|
||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ,
|
||||
--entrypoint="install" ,
|
||||
appwrite/appwrite:0.7.0
|
||||
appwrite/appwrite:0.8.0
|
||||
```
|
||||
|
||||
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-linux native hosts, the server might take a few minutes to start after installation completes.
|
||||
|
||||
|
||||
For advanced production and custom installation, check out our Docker [environment variables](docs/tutorials/environment-variables.md) docs. You can also use our public [docker-compose.yml](https://appwrite.io/docker-compose.yml) file to manually set up and environment.
|
||||
For advanced production and custom installation, check out our Docker [environment variables](https://appwrite.io/docs/environment-variables) docs. You can also use our public [docker-compose.yml](https://gist.github.com/eldadfux/977869ff6bdd7312adfd4e629ee15cc5#file-docker-compose-yml) file to manually set up an environment.
|
||||
|
||||
### Upgrade from an Older Version
|
||||
|
||||
@@ -94,6 +94,7 @@ Getting started with Appwrite is as easy as creating a new project, choosing you
|
||||
* [Getting Started for Web](https://appwrite.io/docs/getting-started-for-web)
|
||||
* [Getting Started for Flutter](https://appwrite.io/docs/getting-started-for-flutter)
|
||||
* [Getting Started for Server](https://appwrite.io/docs/getting-started-for-server)
|
||||
* [Getting Started for CLI](https://appwrite.io/docs/command-line)
|
||||
* Getting Started for Android (Coming soon...)
|
||||
* Getting Started for iOS (Coming soon...)
|
||||
|
||||
@@ -132,13 +133,13 @@ Looking for more SDKs? - Help us by contributing a pull request to our [SDK Gene
|
||||
|
||||
## Contributing
|
||||
|
||||
All code contributions - including those of people having commit access - must go through a pull request and approved by a core developer before being merged. This is to ensure proper review of all the code.
|
||||
All code contributions - including those of people having commit access - must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
|
||||
|
||||
We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](CONTRIBUTING.md).
|
||||
|
||||
## Security
|
||||
|
||||
For security issues, kindly email us at [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue in GitHub.
|
||||
For security issues, kindly email us at [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue on GitHub.
|
||||
|
||||
## Follow Us
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
// Auth methods
|
||||
|
||||
return [
|
||||
'email-password' => [
|
||||
'name' => 'Email/Password',
|
||||
'key' => 'usersAuthEmailPassword',
|
||||
'icon' => '/images/users/email-password.png',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateSession',
|
||||
'enabled' => true,
|
||||
],
|
||||
'anonymous' => [
|
||||
'name' => 'Anonymous',
|
||||
'key' => 'usersAuthAnonymous',
|
||||
'icon' => '/images/users/anonymous.png',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateAnonymousSession',
|
||||
'enabled' => true,
|
||||
],
|
||||
'invites' => [
|
||||
'name' => 'Invites',
|
||||
'key' => 'usersAuthInvites',
|
||||
'icon' => '/images/users/invites.png',
|
||||
'docs' => 'https://appwrite.io/docs/client/teams?sdk=web#teamsCreateMembership',
|
||||
'enabled' => true,
|
||||
],
|
||||
'jwt' => [
|
||||
'name' => 'JWT',
|
||||
'key' => 'usersAuthJWT',
|
||||
'icon' => '/images/users/jwt.png',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateJWT',
|
||||
'enabled' => true,
|
||||
],
|
||||
'phone' => [
|
||||
'name' => 'Phone',
|
||||
'key' => 'usersAuthPhone',
|
||||
'icon' => '/images/users/phone.png',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreatePhoneSession',
|
||||
'docs' => '',
|
||||
'enabled' => false,
|
||||
],
|
||||
];
|
||||
+117
-26
@@ -5,6 +5,7 @@ use Utopia\Config\Config;
|
||||
use Appwrite\Database\Database;
|
||||
|
||||
$providers = Config::getParam('providers', []);
|
||||
$auth = Config::getParam('auth', []);
|
||||
|
||||
$collections = [
|
||||
'console' => [
|
||||
@@ -205,7 +206,7 @@ $collections = [
|
||||
'key' => 'email',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_EMAIL,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
@@ -223,7 +224,7 @@ $collections = [
|
||||
'key' => 'password',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
@@ -272,6 +273,16 @@ $collections = [
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Sessions',
|
||||
'key' => 'sessions',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_DOCUMENT,
|
||||
'default' => [],
|
||||
'required' => false,
|
||||
'array' => true,
|
||||
'list' => [Database::SYSTEM_COLLECTION_SESSIONS],
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Tokens',
|
||||
@@ -294,11 +305,11 @@ $collections = [
|
||||
],
|
||||
],
|
||||
],
|
||||
Database::SYSTEM_COLLECTION_TOKENS => [
|
||||
Database::SYSTEM_COLLECTION_SESSIONS => [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS,
|
||||
'$id' => Database::SYSTEM_COLLECTION_TOKENS,
|
||||
'$id' => Database::SYSTEM_COLLECTION_SESSIONS,
|
||||
'$permissions' => ['read' => ['*']],
|
||||
'name' => 'Token',
|
||||
'name' => 'Session',
|
||||
'structure' => true,
|
||||
'rules' => [
|
||||
[
|
||||
@@ -307,16 +318,34 @@ $collections = [
|
||||
'key' => 'userId',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => null,
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Provider',
|
||||
'key' => 'provider',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Provider User Identifier',
|
||||
'key' => 'providerUid',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Type',
|
||||
'key' => 'type',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_NUMERIC,
|
||||
'default' => null,
|
||||
'required' => true,
|
||||
'label' => 'Provider Token',
|
||||
'key' => 'providerToken',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
@@ -474,6 +503,69 @@ $collections = [
|
||||
],
|
||||
],
|
||||
],
|
||||
Database::SYSTEM_COLLECTION_TOKENS => [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS,
|
||||
'$id' => Database::SYSTEM_COLLECTION_TOKENS,
|
||||
'$permissions' => ['read' => ['*']],
|
||||
'name' => 'Token',
|
||||
'structure' => true,
|
||||
'rules' => [
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'User ID',
|
||||
'key' => 'userId',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => null,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Type',
|
||||
'key' => 'type',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_NUMERIC,
|
||||
'default' => null,
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Secret',
|
||||
'key' => 'secret',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Expire',
|
||||
'key' => 'expire',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_NUMERIC,
|
||||
'default' => 0,
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'User Agent',
|
||||
'key' => 'userAgent',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'IP',
|
||||
'key' => 'ip',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_IP,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
],
|
||||
],
|
||||
],
|
||||
Database::SYSTEM_COLLECTION_MEMBERSHIPS => [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS,
|
||||
'$id' => Database::SYSTEM_COLLECTION_MEMBERSHIPS,
|
||||
@@ -680,6 +772,14 @@ $collections = [
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Max users allowed',
|
||||
'key' => 'usersAuthLimit',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_NUMERIC,
|
||||
'default' => 0,
|
||||
'required' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Webhooks',
|
||||
@@ -1618,25 +1718,16 @@ foreach ($providers as $index => $provider) {
|
||||
'array' => false,
|
||||
'filter' => ['encrypt'],
|
||||
];
|
||||
}
|
||||
|
||||
$collections[Database::SYSTEM_COLLECTION_USERS]['rules'][] = [
|
||||
foreach ($auth as $index => $method) {
|
||||
$collections[Database::SYSTEM_COLLECTION_PROJECTS]['rules'][] = [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'OAuth2 '.\ucfirst($index).' ID',
|
||||
'key' => 'oauth2'.\ucfirst($index),
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'label' => $method['name'] || '',
|
||||
'key' => $method['key'] || '',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_BOOLEAN,
|
||||
'default' => true,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
];
|
||||
|
||||
$collections[Database::SYSTEM_COLLECTION_USERS]['rules'][] = [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'OAuth2 '.\ucfirst($index).' Access Token',
|
||||
'key' => 'oauth2'.\ucfirst($index).'AccessToken',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,15 @@ $environments = [
|
||||
'logo' => 'python.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'python-3.9' => [
|
||||
'name' => 'Python',
|
||||
'version' => '3.9',
|
||||
'base' => 'python:3.9-alpine',
|
||||
'image' => 'appwrite/env-python-3.9:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/python-3.9',
|
||||
'logo' => 'python.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'deno-1.2' => [
|
||||
'name' => 'Deno',
|
||||
'version' => '1.2',
|
||||
@@ -77,7 +86,7 @@ $environments = [
|
||||
'image' => 'appwrite/env-deno-1.2:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/deno-1.2',
|
||||
'logo' => 'deno.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'deno-1.5' => [
|
||||
'name' => 'Deno',
|
||||
@@ -86,7 +95,7 @@ $environments = [
|
||||
'image' => 'appwrite/env-deno-1.5:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/deno-1.5',
|
||||
'logo' => 'deno.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'deno-1.6' => [
|
||||
'name' => 'Deno',
|
||||
@@ -95,7 +104,16 @@ $environments = [
|
||||
'image' => 'appwrite/env-deno-1.6:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/deno-1.6',
|
||||
'logo' => 'deno.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'deno-1.8' => [
|
||||
'name' => 'Deno',
|
||||
'version' => '1.8',
|
||||
'base' => 'hayd/deno:alpine-1.8.2',
|
||||
'image' => 'appwrite/env-deno-1.8:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/deno-1.8',
|
||||
'logo' => 'deno.png',
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'dart-2.10' => [
|
||||
'name' => 'Dart',
|
||||
@@ -106,6 +124,15 @@ $environments = [
|
||||
'logo' => 'dart.png',
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'dart-2.12' => [
|
||||
'name' => 'Dart',
|
||||
'version' => '2.12',
|
||||
'base' => 'google/dart:2.12',
|
||||
'image' => 'appwrite/env-dart-2.12:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/dart-2.12',
|
||||
'logo' => 'dart.png',
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'dotnet-3.1' => [
|
||||
'name' => '.NET',
|
||||
'version' => '3.1',
|
||||
@@ -113,7 +140,7 @@ $environments = [
|
||||
'image' => 'appwrite/env-dotnet-3.1:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/dotnet-3.1',
|
||||
'logo' => 'dotnet.png',
|
||||
'supports' => [System::X86, System::ARM],
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'dotnet-5.0' => [
|
||||
'name' => '.NET',
|
||||
|
||||
+49
-4
@@ -84,19 +84,59 @@ return [
|
||||
],
|
||||
'database.documents.create' => [
|
||||
'description' => 'This event triggers when a database document is created.',
|
||||
'model' => Response::MODEL_ANY,
|
||||
'model' => Response::MODEL_DOCUMENT,
|
||||
'note' => '',
|
||||
],
|
||||
'database.documents.update' => [
|
||||
'description' => 'This event triggers when a database document is updated.',
|
||||
'model' => Response::MODEL_ANY,
|
||||
'model' => Response::MODEL_DOCUMENT,
|
||||
'note' => '',
|
||||
],
|
||||
'database.documents.delete' => [
|
||||
'description' => 'This event triggers when a database document is deleted.',
|
||||
'model' => Response::MODEL_ANY,
|
||||
'model' => Response::MODEL_DOCUMENT,
|
||||
'note' => '',
|
||||
],
|
||||
'functions.create' => [
|
||||
'description' => 'This event triggers when a function is created.',
|
||||
'model' => Response::MODEL_FUNCTION,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'functions.update' => [
|
||||
'description' => 'This event triggers when a function is updated.',
|
||||
'model' => Response::MODEL_FUNCTION,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'functions.delete' => [
|
||||
'description' => 'This event triggers when a function is deleted.',
|
||||
'model' => Response::MODEL_ANY,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'functions.tags.create' => [
|
||||
'description' => 'This event triggers when a function tag is created.',
|
||||
'model' => Response::MODEL_TAG,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'functions.tags.update' => [
|
||||
'description' => 'This event triggers when a function tag is updated.',
|
||||
'model' => Response::MODEL_FUNCTION,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'functions.tags.delete' => [
|
||||
'description' => 'This event triggers when a function tag is deleted.',
|
||||
'model' => Response::MODEL_ANY,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'functions.executions.create' => [
|
||||
'description' => 'This event triggers when a function execution is created.',
|
||||
'model' => Response::MODEL_EXECUTION,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'functions.executions.update' => [
|
||||
'description' => 'This event triggers when a function execution is updated.',
|
||||
'model' => Response::MODEL_EXECUTION,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'storage.files.create' => [
|
||||
'description' => 'This event triggers when a storage file is created.',
|
||||
'model' => Response::MODEL_FILE,
|
||||
@@ -117,6 +157,11 @@ return [
|
||||
'model' => Response::MODEL_USER,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'users.update.prefs' => [
|
||||
'description' => 'This event triggers when a user preference is updated from the users API.',
|
||||
'model' => Response::MODEL_ANY,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'users.update.status' => [
|
||||
'description' => 'This event triggers when a user status is updated from the users API.',
|
||||
'model' => Response::MODEL_USER,
|
||||
@@ -162,4 +207,4 @@ return [
|
||||
'model' => Response::MODEL_MEMBERSHIP,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
];
|
||||
];
|
||||
|
||||
@@ -32,7 +32,7 @@ return [
|
||||
[
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'version' => '0.3.0',
|
||||
'version' => '0.4.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-flutter',
|
||||
'package' => 'https://pub.dev/packages/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -165,7 +165,7 @@ return [
|
||||
[
|
||||
'key' => 'deno',
|
||||
'name' => 'Deno',
|
||||
'version' => '0.1.0',
|
||||
'version' => '0.1.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-deno',
|
||||
'package' => 'https://deno.land/x/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -199,7 +199,7 @@ return [
|
||||
[
|
||||
'key' => 'python',
|
||||
'name' => 'Python',
|
||||
'version' => '0.1.0',
|
||||
'version' => '0.1.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-python',
|
||||
'package' => 'https://pypi.org/project/appwrite/',
|
||||
'enabled' => true,
|
||||
@@ -216,7 +216,7 @@ return [
|
||||
[
|
||||
'key' => 'ruby',
|
||||
'name' => 'Ruby',
|
||||
'version' => '2.0.0',
|
||||
'version' => '2.0.2',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-ruby',
|
||||
'package' => 'https://rubygems.org/gems/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -284,12 +284,12 @@ return [
|
||||
[
|
||||
'key' => 'dart',
|
||||
'name' => 'Dart',
|
||||
'version' => '0.2.0',
|
||||
'version' => '0.4.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dart',
|
||||
'package' => 'https://pub.dev/packages/dart_appwrite',
|
||||
'enabled' => true,
|
||||
'beta' => true,
|
||||
'dev' => true,
|
||||
'dev' => false,
|
||||
'hidden' => false,
|
||||
'family' => APP_PLATFORM_SERVER,
|
||||
'prism' => 'dart',
|
||||
@@ -301,7 +301,7 @@ return [
|
||||
[
|
||||
'key' => 'cli',
|
||||
'name' => 'Command Line',
|
||||
'version' => '0.5.0',
|
||||
'version' => '0.6.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-cli',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-cli',
|
||||
'enabled' => true,
|
||||
|
||||
@@ -6,6 +6,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.amazon.com/apps-and-games/services-and-apis',
|
||||
'icon' => 'icon-amazon',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -15,6 +16,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.apple.com/',
|
||||
'icon' => 'icon-apple',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => 'apple.phtml', // Perperation for adding ability to customized OAuth UI forms, currently handled hardcoded.
|
||||
'beta' => true,
|
||||
'mock' => false,
|
||||
@@ -24,6 +26,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.atlassian.com/bitbucket',
|
||||
'icon' => 'icon-bitbucket',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -33,6 +36,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://dev.bitly.com/v4_documentation.html',
|
||||
'icon' => 'icon-bitly',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
@@ -42,6 +46,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.box.com/reference/',
|
||||
'icon' => 'icon-box',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
@@ -51,6 +56,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://discordapp.com/developers/docs/topics/oauth2',
|
||||
'icon' => 'icon-discord',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -60,6 +66,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://www.dropbox.com/developers/documentation',
|
||||
'icon' => 'icon-dropbox',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -69,6 +76,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developers.facebook.com/',
|
||||
'icon' => 'icon-facebook',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -78,6 +86,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.github.com/',
|
||||
'icon' => 'icon-github-circled',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -87,6 +96,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://docs.gitlab.com/ee/api/',
|
||||
'icon' => 'icon-gitlab',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -96,6 +106,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://support.google.com/googleapi/answer/6158849',
|
||||
'icon' => 'icon-google',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -105,6 +116,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.linkedin.com/',
|
||||
'icon' => 'icon-linkedin',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -114,6 +126,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.microsoft.com/en-us/',
|
||||
'icon' => 'icon-windows',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -123,15 +136,17 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.paypal.com/docs/api/overview/',
|
||||
'icon' => 'icon-paypal',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
'paypalSandbox' => [
|
||||
'name' => 'PayPal (Sandbox)',
|
||||
'name' => 'PayPal',
|
||||
'developers' => 'https://developer.paypal.com/docs/api/overview/',
|
||||
'icon' => 'icon-paypal',
|
||||
'enabled' => true,
|
||||
'sandbox' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
@@ -141,6 +156,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.salesforce.com/docs/',
|
||||
'icon' => 'icon-salesforce',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -150,6 +166,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://api.slack.com/',
|
||||
'icon' => 'icon-slack',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -159,6 +176,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.spotify.com/documentation/general/guides/authorization-guide/',
|
||||
'icon' => 'icon-spotify',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -168,15 +186,17 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developers.tradeshift.com/docs/api',
|
||||
'icon' => 'icon-tradeshift',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'tradeshiftBox' => [
|
||||
'name' => 'Tradeshift Sandbox',
|
||||
'name' => 'Tradeshift',
|
||||
'developers' => 'https://developers.tradeshift.com/docs/api',
|
||||
'icon' => 'icon-tradeshiftbox',
|
||||
'enabled' => true,
|
||||
'sandbox' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -186,6 +206,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://dev.twitch.tv/docs/authentication',
|
||||
'icon' => 'icon-twitch',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -195,6 +216,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://vk.com/dev',
|
||||
'icon' => 'icon-vk',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -204,6 +226,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.yahoo.com/oauth2/guide/flows_authcode/',
|
||||
'icon' => 'icon-yahoo',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -213,6 +236,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://tech.yandex.com/oauth/',
|
||||
'icon' => 'icon-yandex',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
@@ -238,6 +262,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://developer.wordpress.com/docs/oauth2/',
|
||||
'icon' => 'icon-wordpress',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
@@ -248,6 +273,7 @@ return [ // Ordered by ABC.
|
||||
'developers' => 'https://appwrite.io',
|
||||
'icon' => 'icon-appwrite',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => true,
|
||||
|
||||
@@ -60,8 +60,6 @@ return [
|
||||
'files.read',
|
||||
'locale.read',
|
||||
'avatars.read',
|
||||
'execution.read',
|
||||
'execution.write',
|
||||
],
|
||||
],
|
||||
Auth::USER_ROLE_MEMBER => [
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+18
-10
@@ -15,6 +15,14 @@ return [
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
[
|
||||
'name' => '_APP_LOCALE',
|
||||
'description' => 'Set your Appwrite\'s locale. By default, the locale is set to \'en\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'en',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
[
|
||||
'name' => '_APP_OPTIONS_ABUSE',
|
||||
'description' => 'Allows you to disable abuse checks and API rate limiting. By default, set to \'enabled\'. To cancel the abuse checking, set to \'disabled\'. It is not recommended to disable this check-in a production environment.',
|
||||
@@ -25,9 +33,9 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_OPTIONS_FORCE_HTTPS',
|
||||
'description' => 'Allows you to force HTTPS connection to your API. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'disabled\'. To enable, set to \'enabled\'. This feature will work only when your ports are set to default 80 and 443.',
|
||||
'description' => 'Allows you to force HTTPS connection to your API. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.',
|
||||
'introduction' => '',
|
||||
'default' => 'enabled',
|
||||
'default' => 'disabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
@@ -115,8 +123,8 @@ return [
|
||||
'name' => '_APP_SYSTEM_SECURITY_EMAIL_ADDRESS',
|
||||
'description' => 'This is the email address used to issue SSL certificates for custom domains or the user agent in your webhooks payload.',
|
||||
'introduction' => '0.7.0',
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'default' => 'certs@appwrite.io',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
[
|
||||
@@ -126,7 +134,7 @@ return [
|
||||
'default' => 'enabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
@@ -151,7 +159,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_REDIS_USER',
|
||||
'description' => 'Redis server user.',
|
||||
'description' => 'Redis server user. This is an optional variable. Default value is an empty string.',
|
||||
'introduction' => '0.7',
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
@@ -159,7 +167,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_REDIS_PASS',
|
||||
'description' => 'Redis server password.',
|
||||
'description' => 'Redis server password. This is an optional variable. Default value is an empty string.',
|
||||
'introduction' => '0.7',
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
@@ -317,9 +325,9 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_STORAGE_ANTIVIRUS',
|
||||
'description' => 'This variable allows you to disable the internal anti-virus scans. This value is set to \'enabled\' by default, to cancel the scans set the value to \'disabled\'. When disabled, it\'s recommended to turn off the ClamAV container for better resource usage.',
|
||||
'description' => 'This variable allows you to disable the internal anti-virus scans. This value is set to \'disabled\' by default, to enable the scans set the value to \'enabled\'. Before enabling, you must add the ClamAV service and depend on it on main Appwrite service.',
|
||||
'introduction' => '',
|
||||
'default' => 'enabled',
|
||||
'default' => 'disabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
@@ -389,7 +397,7 @@ return [
|
||||
'name' => '_APP_FUNCTIONS_ENVS',
|
||||
'description' => 'This option allows you to limit the available environments for cloud functions. This option is very useful for low-cost servers to safe disk space.\n\nTo enable/activate this option, pass a list of allowed environments separated by a comma.\n\nCurrently, supported environments are: ' . \implode(', ', \array_keys(Config::getParam('providers'))),
|
||||
'introduction' => '0.7.0',
|
||||
'default' => 'node-14.5,deno-1.6,php-7.4,python-3.8,ruby-3.0,dotnet-5.0',
|
||||
'default' => 'node-14.5,deno-1.8,php-7.4,python-3.9,ruby-3.0,dotnet-5.0',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
|
||||
+293
-90
@@ -6,10 +6,10 @@ use Utopia\Exception;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Validator\Assoc;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\Email;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Host;
|
||||
use Utopia\Validator\URL;
|
||||
use Appwrite\Network\Validator\Host;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Appwrite\Auth\Auth;
|
||||
@@ -31,10 +31,11 @@ $oauthDefaultFailure = App::getEnv('_APP_HOME').'/auth/oauth2/failure';
|
||||
|
||||
App::post('/v1/account')
|
||||
->desc('Create Account')
|
||||
->groups(['api', 'account'])
|
||||
->groups(['api', 'account', 'auth'])
|
||||
->label('event', 'account.create')
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('auth.type', 'emailPassword')
|
||||
->label('sdk.auth', [])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'create')
|
||||
->label('sdk.description', '/docs/references/account/create.md')
|
||||
@@ -90,6 +91,22 @@ App::post('/v1/account')
|
||||
}
|
||||
}
|
||||
|
||||
$limit = $project->getAttribute('usersAuthLimit', 0);
|
||||
|
||||
if ($limit !== 0) {
|
||||
$projectDB->getCollection([ // Count users
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
],
|
||||
]);
|
||||
|
||||
$sum = $projectDB->getSum();
|
||||
|
||||
if($sum >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
|
||||
}
|
||||
}
|
||||
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'filters' => [
|
||||
@@ -124,7 +141,7 @@ App::post('/v1/account')
|
||||
throw new Exception('Account already exists', 409);
|
||||
}
|
||||
|
||||
Authorization::enable();
|
||||
Authorization::reset();
|
||||
|
||||
Authorization::unsetRole('role:'.Auth::USER_ROLE_GUEST);
|
||||
Authorization::setRole('user:'.$user->getId());
|
||||
@@ -148,10 +165,11 @@ App::post('/v1/account')
|
||||
|
||||
App::post('/v1/account/sessions')
|
||||
->desc('Create Account Session')
|
||||
->groups(['api', 'account'])
|
||||
->groups(['api', 'account', 'auth'])
|
||||
->label('event', 'account.sessions.create')
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('auth.type', 'emailPassword')
|
||||
->label('sdk.auth', [])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'createSession')
|
||||
->label('sdk.description', '/docs/references/account/create-session.md')
|
||||
@@ -205,10 +223,11 @@ App::post('/v1/account/sessions')
|
||||
$secret = Auth::tokenGenerator();
|
||||
$session = new Document(array_merge(
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_TOKENS,
|
||||
'$collection' => Database::SYSTEM_COLLECTION_SESSIONS,
|
||||
'$permissions' => ['read' => ['user:'.$profile->getId()], 'write' => ['user:'.$profile->getId()]],
|
||||
'userId' => $profile->getId(),
|
||||
'type' => Auth::TOKEN_TYPE_LOGIN,
|
||||
'provider' => Auth::SESSION_PROVIDER_EMAIL,
|
||||
'providerUid' => $email,
|
||||
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
|
||||
'expire' => $expiry,
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
@@ -225,7 +244,7 @@ App::post('/v1/account/sessions')
|
||||
throw new Exception('Failed saving session to DB', 500);
|
||||
}
|
||||
|
||||
$profile->setAttribute('tokens', $session, Document::SET_TYPE_APPEND);
|
||||
$profile->setAttribute('sessions', $session, Document::SET_TYPE_APPEND);
|
||||
|
||||
$profile = $projectDB->updateDocument($profile->getArrayCopy());
|
||||
|
||||
@@ -251,9 +270,11 @@ App::post('/v1/account/sessions')
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
;
|
||||
|
||||
$countries = $locale->getText('countries');
|
||||
|
||||
$session
|
||||
->setAttribute('current', true)
|
||||
->setAttribute('countryName', (isset($countries[$session->getAttribute('countryCode')])) ? $countries[$session->getAttribute('countryCode')] : $locale->getText('locale.country.unknown'))
|
||||
->setAttribute('countryName', (isset($countries[strtoupper($session->getAttribute('countryCode'))])) ? $countries[strtoupper($session->getAttribute('countryCode'))] : $locale->getText('locale.country.unknown'))
|
||||
;
|
||||
|
||||
$response->dynamic($session, Response::MODEL_SESSION);
|
||||
@@ -264,12 +285,12 @@ App::get('/v1/account/sessions/oauth2/:provider')
|
||||
->groups(['api', 'account'])
|
||||
->label('error', __DIR__.'/../../views/general/error.phtml')
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'createOAuth2Session')
|
||||
->label('sdk.description', '/docs/references/account/create-session-oauth2.md')
|
||||
->label('sdk.response.code', 301)
|
||||
->label('sdk.response.type', 'text/html')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_HTML)
|
||||
->label('sdk.methodType', 'webAuth')
|
||||
->label('abuse-limit', 50)
|
||||
->label('abuse-key', 'ip:{ip}')
|
||||
@@ -454,7 +475,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
throw new Exception('Missing ID from OAuth2 provider', 400);
|
||||
}
|
||||
|
||||
$current = Auth::tokenVerify($user->getAttribute('tokens', []), Auth::TOKEN_TYPE_LOGIN, Auth::$secret);
|
||||
$current = Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret);
|
||||
|
||||
if ($current) {
|
||||
$projectDB->deleteDocument($current); //throw new Exception('User already logged in', 401);
|
||||
@@ -464,7 +485,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
'limit' => 1,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'oauth2'.\ucfirst($provider).'='.$oauth2ID,
|
||||
'sessions.provider='.$provider,
|
||||
'sessions.providerUid='.$oauth2ID
|
||||
],
|
||||
]) : $user;
|
||||
|
||||
@@ -480,7 +502,23 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
],
|
||||
]);
|
||||
|
||||
if (!$user || empty($user->getId())) { // Last option -> create user alone, generate random password
|
||||
if (!$user || empty($user->getId())) { // Last option -> create the user, generate random password
|
||||
$limit = $project->getAttribute('usersAuthLimit', 0);
|
||||
|
||||
if ($limit !== 0) {
|
||||
$projectDB->getCollection([ // Count users
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
],
|
||||
]);
|
||||
|
||||
$sum = $projectDB->getSum();
|
||||
|
||||
if($sum >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
|
||||
}
|
||||
}
|
||||
|
||||
Authorization::disable();
|
||||
|
||||
try {
|
||||
@@ -500,7 +538,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
throw new Exception('Account already exists', 409);
|
||||
}
|
||||
|
||||
Authorization::enable();
|
||||
Authorization::reset();
|
||||
|
||||
if (false === $user) {
|
||||
throw new Exception('Failed saving user to DB', 500);
|
||||
@@ -519,10 +557,12 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
$secret = Auth::tokenGenerator();
|
||||
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$session = new Document(array_merge([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_TOKENS,
|
||||
'$collection' => Database::SYSTEM_COLLECTION_SESSIONS,
|
||||
'$permissions' => ['read' => ['user:'.$user['$id']], 'write' => ['user:'.$user['$id']]],
|
||||
'userId' => $user->getId(),
|
||||
'type' => Auth::TOKEN_TYPE_LOGIN,
|
||||
'provider' => $provider,
|
||||
'providerUid' => $oauth2ID,
|
||||
'providerToken' => $accessToken,
|
||||
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
|
||||
'expire' => $expiry,
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
@@ -530,11 +570,18 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
], $detector->getOS(), $detector->getClient(), $detector->getDevice()));
|
||||
|
||||
$isAnonymousUser = is_null($user->getAttribute('email')) && is_null($user->getAttribute('password'));
|
||||
|
||||
if ($isAnonymousUser) {
|
||||
$user
|
||||
->setAttribute('name', $oauth2->getUserName($accessToken))
|
||||
->setAttribute('email', $oauth2->getUserEmail($accessToken))
|
||||
;
|
||||
}
|
||||
|
||||
$user
|
||||
->setAttribute('oauth2'.\ucfirst($provider), $oauth2ID)
|
||||
->setAttribute('oauth2'.\ucfirst($provider).'AccessToken', $accessToken)
|
||||
->setAttribute('status', Auth::USER_STATUS_ACTIVATED)
|
||||
->setAttribute('tokens', $session, Document::SET_TYPE_APPEND)
|
||||
->setAttribute('sessions', $session, Document::SET_TYPE_APPEND)
|
||||
;
|
||||
|
||||
Authorization::setRole('user:'.$user->getId());
|
||||
@@ -579,12 +626,156 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
;
|
||||
});
|
||||
|
||||
App::post('/v1/account/sessions/anonymous')
|
||||
->desc('Create Anonymous Session')
|
||||
->groups(['api', 'account', 'auth'])
|
||||
->label('event', 'account.sessions.create')
|
||||
->label('scope', 'public')
|
||||
->label('auth.type', 'anonymous')
|
||||
->label('sdk.auth', [])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'createAnonymousSession')
|
||||
->label('sdk.description', '/docs/references/account/create-session-anonymous.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_SESSION)
|
||||
->label('abuse-limit', 50)
|
||||
->label('abuse-key', 'ip:{ip}')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('locale')
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->inject('projectDB')
|
||||
->inject('geodb')
|
||||
->inject('audits')
|
||||
->action(function ($request, $response, $locale, $user, $project, $projectDB, $geodb, $audits) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Utopia\Locale\Locale $locale */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var MaxMind\Db\Reader $geodb */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$protocol = $request->getProtocol();
|
||||
|
||||
if ('console' === $project->getId()) {
|
||||
throw new Exception('Failed to create anonymous user.', 401);
|
||||
}
|
||||
|
||||
if ($user->getId()) {
|
||||
throw new Exception('Cannot create an anonymous user when logged in.', 401);
|
||||
}
|
||||
|
||||
$limit = $project->getAttribute('usersAuthLimit', 0);
|
||||
|
||||
if ($limit !== 0) {
|
||||
$projectDB->getCollection([ // Count users
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
],
|
||||
]);
|
||||
|
||||
$sum = $projectDB->getSum();
|
||||
|
||||
if($sum >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
|
||||
}
|
||||
}
|
||||
|
||||
Authorization::disable();
|
||||
try {
|
||||
$user = $projectDB->createDocument([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_USERS,
|
||||
'$permissions' => [
|
||||
'read' => ['*'],
|
||||
'write' => ['user:{self}']
|
||||
],
|
||||
'email' => null,
|
||||
'emailVerification' => false,
|
||||
'status' => Auth::USER_STATUS_UNACTIVATED,
|
||||
'password' => null,
|
||||
'passwordUpdate' => \time(),
|
||||
'registration' => \time(),
|
||||
'reset' => false,
|
||||
'name' => null
|
||||
]);
|
||||
} catch (Exception $th) {
|
||||
throw new Exception('Failed saving user to DB', 500);
|
||||
}
|
||||
Authorization::reset();
|
||||
|
||||
if (false === $user) {
|
||||
throw new Exception('Failed saving user to DB', 500);
|
||||
}
|
||||
|
||||
// Create session token
|
||||
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
$secret = Auth::tokenGenerator();
|
||||
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$session = new Document(array_merge(
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_SESSIONS,
|
||||
'$permissions' => ['read' => ['user:' . $user['$id']], 'write' => ['user:' . $user['$id']]],
|
||||
'userId' => $user->getId(),
|
||||
'provider' => Auth::SESSION_PROVIDER_ANONYMOUS,
|
||||
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
|
||||
'expire' => $expiry,
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'ip' => $request->getIP(),
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
],
|
||||
$detector->getOS(),
|
||||
$detector->getClient(),
|
||||
$detector->getDevice()
|
||||
));
|
||||
|
||||
$user->setAttribute('sessions', $session, Document::SET_TYPE_APPEND);
|
||||
|
||||
Authorization::setRole('user:'.$user->getId());
|
||||
|
||||
$user = $projectDB->updateDocument($user->getArrayCopy());
|
||||
|
||||
if (false === $user) {
|
||||
throw new Exception('Failed saving user to DB', 500);
|
||||
}
|
||||
|
||||
$audits
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', 'account.sessions.create')
|
||||
->setParam('resource', 'users/'.$user->getId())
|
||||
;
|
||||
|
||||
if (!Config::getParam('domainVerification')) {
|
||||
$response
|
||||
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)]))
|
||||
;
|
||||
}
|
||||
|
||||
$response
|
||||
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
|
||||
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
;
|
||||
|
||||
$session
|
||||
->setAttribute('current', true)
|
||||
->setAttribute('countryName', (isset($countries[$session->getAttribute('countryCode')])) ? $countries[$session->getAttribute('countryCode')] : $locale->getText('locale.country.unknown'))
|
||||
;
|
||||
|
||||
$response->dynamic($session, Response::MODEL_SESSION);
|
||||
});
|
||||
|
||||
App::post('/v1/account/jwt')
|
||||
->desc('Create Account JWT')
|
||||
->groups(['api', 'account'])
|
||||
->groups(['api', 'account', 'auth'])
|
||||
->label('scope', 'account')
|
||||
->label('docs', false) // Hidden for now - private beta
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('auth.type', 'jwt')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'createJWT')
|
||||
->label('sdk.description', '/docs/references/account/create-jwt.md')
|
||||
@@ -596,16 +787,18 @@ App::post('/v1/account/jwt')
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$session = new Document();
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$current = new Document();
|
||||
|
||||
foreach ($tokens as $token) { /** @var Appwrite\Database\Document $token */
|
||||
if ($token->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
$session = $token;
|
||||
foreach ($sessions as $session) {
|
||||
/** @var Appwrite\Database\Document $session */
|
||||
|
||||
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
$current = $session;
|
||||
}
|
||||
}
|
||||
|
||||
if($session->isEmpty()) {
|
||||
if($current->isEmpty()) {
|
||||
throw new Exception('No valid session found', 401);
|
||||
}
|
||||
|
||||
@@ -619,7 +812,7 @@ App::post('/v1/account/jwt')
|
||||
// 'scopes' => ['user'],
|
||||
// 'iss' => 'http://api.mysite.com',
|
||||
'userId' => $user->getId(),
|
||||
'sessionId' => $session->getId(),
|
||||
'sessionId' => $current->getId(),
|
||||
])]), Response::MODEL_JWT);
|
||||
});
|
||||
|
||||
@@ -627,7 +820,7 @@ App::get('/v1/account')
|
||||
->desc('Get Account')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', '/docs/references/account/get.md')
|
||||
@@ -647,7 +840,7 @@ App::get('/v1/account/prefs')
|
||||
->desc('Get Account Preferences')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'getPrefs')
|
||||
->label('sdk.description', '/docs/references/account/get-prefs.md')
|
||||
@@ -669,7 +862,7 @@ App::get('/v1/account/sessions')
|
||||
->desc('Get Account Sessions')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'getSessions')
|
||||
->label('sdk.description', '/docs/references/account/get-sessions.md')
|
||||
@@ -684,22 +877,19 @@ App::get('/v1/account/sessions')
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Utopia\Locale\Locale $locale */
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$sessions = [];
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$countries = $locale->getText('countries');
|
||||
$current = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_LOGIN, Auth::$secret);
|
||||
$current = Auth::sessionVerify($sessions, Auth::$secret);
|
||||
|
||||
foreach ($tokens as $token) { /* @var $token Document */
|
||||
if (Auth::TOKEN_TYPE_LOGIN != $token->getAttribute('type')) {
|
||||
continue;
|
||||
}
|
||||
foreach ($sessions as $key => $session) {
|
||||
/** @var Document $session */
|
||||
|
||||
$token->setAttribute('countryName', (isset($countries[$token->getAttribute('contryCode')]))
|
||||
? $countries[$token->getAttribute('contryCode')]
|
||||
$session->setAttribute('countryName', (isset($countries[strtoupper($session->getAttribute('countryCode'))]))
|
||||
? $countries[strtoupper($session->getAttribute('countryCode'))]
|
||||
: $locale->getText('locale.country.unknown'));
|
||||
$token->setAttribute('current', ($current == $token->getId()) ? true : false);
|
||||
$session->setAttribute('current', ($current == $session->getId()) ? true : false);
|
||||
|
||||
$sessions[] = $token;
|
||||
$sessions[$key] = $session;
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -712,7 +902,7 @@ App::get('/v1/account/logs')
|
||||
->desc('Get Account Logs')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'getLogs')
|
||||
->label('sdk.description', '/docs/references/account/get-logs.md')
|
||||
@@ -789,7 +979,7 @@ App::patch('/v1/account/name')
|
||||
->groups(['api', 'account'])
|
||||
->label('event', 'account.update.name')
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'updateName')
|
||||
->label('sdk.description', '/docs/references/account/update-name.md')
|
||||
@@ -829,7 +1019,7 @@ App::patch('/v1/account/password')
|
||||
->groups(['api', 'account'])
|
||||
->label('event', 'account.update.password')
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'updatePassword')
|
||||
->label('sdk.description', '/docs/references/account/update-password.md')
|
||||
@@ -874,7 +1064,7 @@ App::patch('/v1/account/email')
|
||||
->groups(['api', 'account'])
|
||||
->label('event', 'account.update.email')
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'updateEmail')
|
||||
->label('sdk.description', '/docs/references/account/update-email.md')
|
||||
@@ -893,7 +1083,12 @@ App::patch('/v1/account/email')
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password
|
||||
$isAnonymousUser = is_null($user->getAttribute('email')) && is_null($user->getAttribute('password')); // Check if request is from an anonymous account for converting
|
||||
|
||||
if (
|
||||
!$isAnonymousUser &&
|
||||
!Auth::passwordVerify($password, $user->getAttribute('password'))
|
||||
) { // Double check user password
|
||||
throw new Exception('Invalid credentials', 401);
|
||||
}
|
||||
|
||||
@@ -911,10 +1106,14 @@ App::patch('/v1/account/email')
|
||||
|
||||
// TODO after this user needs to confirm mail again
|
||||
|
||||
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
|
||||
'email' => $email,
|
||||
'emailVerification' => false,
|
||||
]));
|
||||
$user = $projectDB->updateDocument(\array_merge(
|
||||
$user->getArrayCopy(),
|
||||
($isAnonymousUser ? [ 'password' => Auth::passwordHash($password) ] : []),
|
||||
[
|
||||
'email' => $email,
|
||||
'emailVerification' => false,
|
||||
]
|
||||
));
|
||||
|
||||
if (false === $user) {
|
||||
throw new Exception('Failed saving user to DB', 500);
|
||||
@@ -934,7 +1133,7 @@ App::patch('/v1/account/prefs')
|
||||
->groups(['api', 'account'])
|
||||
->label('event', 'account.update.prefs')
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'updatePrefs')
|
||||
->label('sdk.description', '/docs/references/account/update-prefs.md')
|
||||
@@ -973,7 +1172,7 @@ App::delete('/v1/account')
|
||||
->groups(['api', 'account'])
|
||||
->label('event', 'account.delete')
|
||||
->label('scope', 'account')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.description', '/docs/references/account/delete.md')
|
||||
@@ -1018,7 +1217,7 @@ App::delete('/v1/account')
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||
->setParam('eventData', $response->output($user, Response::MODEL_USER))
|
||||
;
|
||||
|
||||
if (!Config::getParam('domainVerification')) {
|
||||
@@ -1039,7 +1238,7 @@ App::delete('/v1/account/sessions/:sessionId')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'account')
|
||||
->label('event', 'account.sessions.delete')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'deleteSession')
|
||||
->label('sdk.description', '/docs/references/account/delete-session.md')
|
||||
@@ -1063,14 +1262,16 @@ App::delete('/v1/account/sessions/:sessionId')
|
||||
|
||||
$protocol = $request->getProtocol();
|
||||
$sessionId = ($sessionId === 'current')
|
||||
? Auth::tokenVerify($user->getAttribute('tokens'), Auth::TOKEN_TYPE_LOGIN, Auth::$secret)
|
||||
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
|
||||
: $sessionId;
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
||||
foreach ($tokens as $token) { /* @var $token Document */
|
||||
if (($sessionId == $token->getId()) && Auth::TOKEN_TYPE_LOGIN == $token->getAttribute('type')) {
|
||||
if (!$projectDB->deleteDocument($token->getId())) {
|
||||
foreach ($sessions as $session) {
|
||||
/** @var Document $session */
|
||||
|
||||
if (($sessionId == $session->getId())) {
|
||||
if (!$projectDB->deleteDocument($session->getId())) {
|
||||
throw new Exception('Failed to remove token from DB', 500);
|
||||
}
|
||||
|
||||
@@ -1086,10 +1287,10 @@ App::delete('/v1/account/sessions/:sessionId')
|
||||
;
|
||||
}
|
||||
|
||||
$token->setAttribute('current', false);
|
||||
$session->setAttribute('current', false);
|
||||
|
||||
if ($token->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
$token->setAttribute('current', true);
|
||||
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
$session->setAttribute('current', true);
|
||||
|
||||
$response
|
||||
->addCookie(Auth::$cookieName.'_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
|
||||
@@ -1098,7 +1299,7 @@ App::delete('/v1/account/sessions/:sessionId')
|
||||
}
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($token, Response::MODEL_SESSION))
|
||||
->setParam('eventData', $response->output($session, Response::MODEL_SESSION))
|
||||
;
|
||||
|
||||
return $response->noContent();
|
||||
@@ -1113,7 +1314,7 @@ App::delete('/v1/account/sessions')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'account')
|
||||
->label('event', 'account.sessions.delete')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'deleteSessions')
|
||||
->label('sdk.description', '/docs/references/account/delete-sessions.md')
|
||||
@@ -1135,10 +1336,12 @@ App::delete('/v1/account/sessions')
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
|
||||
$protocol = $request->getProtocol();
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
||||
foreach ($tokens as $token) { /* @var $token Document */
|
||||
if (!$projectDB->deleteDocument($token->getId())) {
|
||||
foreach ($sessions as $session) {
|
||||
/** @var Document $session */
|
||||
|
||||
if (!$projectDB->deleteDocument($session->getId())) {
|
||||
throw new Exception('Failed to remove token from DB', 500);
|
||||
}
|
||||
|
||||
@@ -1154,10 +1357,10 @@ App::delete('/v1/account/sessions')
|
||||
;
|
||||
}
|
||||
|
||||
$token->setAttribute('current', false);
|
||||
$session->setAttribute('current', false);
|
||||
|
||||
if ($token->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
$token->setAttribute('current', true);
|
||||
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
$session->setAttribute('current', true);
|
||||
$response
|
||||
->addCookie(Auth::$cookieName.'_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
|
||||
->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
||||
@@ -1166,9 +1369,9 @@ App::delete('/v1/account/sessions')
|
||||
}
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output(new Document([
|
||||
'sum' => count($tokens),
|
||||
'sessions' => $tokens
|
||||
->setParam('eventData', $response->output(new Document([
|
||||
'sum' => count($sessions),
|
||||
'sessions' => $sessions
|
||||
]), Response::MODEL_SESSION_LIST))
|
||||
;
|
||||
|
||||
@@ -1180,7 +1383,7 @@ App::post('/v1/account/recovery')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'public')
|
||||
->label('event', 'account.recovery.create')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'createRecovery')
|
||||
->label('sdk.description', '/docs/references/account/create-recovery.md')
|
||||
@@ -1209,7 +1412,7 @@ App::post('/v1/account/recovery')
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
|
||||
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
@@ -1291,7 +1494,7 @@ App::post('/v1/account/recovery')
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload',
|
||||
->setParam('eventData',
|
||||
$response->output($recovery->setAttribute('secret', $secret),
|
||||
Response::MODEL_TOKEN
|
||||
))
|
||||
@@ -1299,7 +1502,7 @@ App::post('/v1/account/recovery')
|
||||
|
||||
$recovery // Hide secret for clients, sp
|
||||
->setAttribute('secret',
|
||||
($isPreviliggedUser || $isAppUser) ? $secret : '');
|
||||
($isPrivilegedUser || $isAppUser) ? $secret : '');
|
||||
|
||||
$audits
|
||||
->setParam('userId', $profile->getId())
|
||||
@@ -1318,7 +1521,7 @@ App::put('/v1/account/recovery')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'public')
|
||||
->label('event', 'account.recovery.update')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'updateRecovery')
|
||||
->label('sdk.description', '/docs/references/account/update-recovery.md')
|
||||
@@ -1397,7 +1600,7 @@ App::post('/v1/account/verification')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'account')
|
||||
->label('event', 'account.verification.create')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'createVerification')
|
||||
->label('sdk.description', '/docs/references/account/create-verification.md')
|
||||
@@ -1427,7 +1630,7 @@ App::post('/v1/account/verification')
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
/** @var Appwrite\Event\Event $mails */
|
||||
|
||||
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
$verificationSecret = Auth::tokenGenerator();
|
||||
@@ -1494,7 +1697,7 @@ App::post('/v1/account/verification')
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload',
|
||||
->setParam('eventData',
|
||||
$response->output($verification->setAttribute('secret', $verificationSecret),
|
||||
Response::MODEL_TOKEN
|
||||
))
|
||||
@@ -1502,7 +1705,7 @@ App::post('/v1/account/verification')
|
||||
|
||||
$verification // Hide secret for clients, sp
|
||||
->setAttribute('secret',
|
||||
($isPreviliggedUser || $isAppUser) ? $verificationSecret : '');
|
||||
($isPrivilegedUser || $isAppUser) ? $verificationSecret : '');
|
||||
|
||||
$audits
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -1521,7 +1724,7 @@ App::put('/v1/account/verification')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'public')
|
||||
->label('event', 'account.verification.update')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'updateVerification')
|
||||
->label('sdk.description', '/docs/references/account/update-verification.md')
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\URL;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\Cache\Adapter\Filesystem;
|
||||
use Appwrite\Resize\Resize;
|
||||
use Appwrite\URL\URL as URLParse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Validator\HexColor;
|
||||
use chillerlan\QRCode\QRCode;
|
||||
use chillerlan\QRCode\QROptions;
|
||||
use Utopia\App;
|
||||
use Utopia\Cache\Adapter\Filesystem;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Image\Image;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\HexColor;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Text;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
$avatarCallback = function ($type, $code, $width, $height, $quality, $response) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
|
||||
$code = \strtolower($code);
|
||||
$type = \strtolower($type);
|
||||
$set = Config::getParam('avatar-'.$type, []);
|
||||
$set = Config::getParam('avatar-' . $type, []);
|
||||
|
||||
if (empty($set)) {
|
||||
throw new Exception('Avatar set not found', 404);
|
||||
@@ -37,17 +37,17 @@ $avatarCallback = function ($type, $code, $width, $height, $quality, $response)
|
||||
}
|
||||
|
||||
$output = 'png';
|
||||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
|
||||
$key = \md5('/v1/avatars/:type/:code-'.$code.$width.$height.$quality.$output);
|
||||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
|
||||
$key = \md5('/v1/avatars/'.$type.'/:code-' . $code . $width . $height . $quality . $output);
|
||||
$path = $set[$code];
|
||||
$type = 'png';
|
||||
|
||||
if (!\is_readable($path)) {
|
||||
throw new Exception('File not readable in '.$path, 500);
|
||||
throw new Exception('File not readable in ' . $path, 500);
|
||||
}
|
||||
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
|
||||
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */);
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
|
||||
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */);
|
||||
|
||||
if ($data) {
|
||||
//$output = (empty($output)) ? $type : $output;
|
||||
@@ -60,38 +60,37 @@ $avatarCallback = function ($type, $code, $width, $height, $quality, $response)
|
||||
;
|
||||
}
|
||||
|
||||
$resize = new Resize(\file_get_contents($path));
|
||||
$image = new Image(\file_get_contents($path));
|
||||
|
||||
$resize->crop((int) $width, (int) $height);
|
||||
$image->crop((int) $width, (int) $height);
|
||||
|
||||
$output = (empty($output)) ? $type : $output;
|
||||
|
||||
$data = $resize->output($output, $quality);
|
||||
|
||||
$data = $image->output($output, $quality);
|
||||
|
||||
$cache->save($key, $data);
|
||||
|
||||
|
||||
$response
|
||||
->setContentType('image/png')
|
||||
->addHeader('Expires', $date)
|
||||
->addHeader('X-Appwrite-Cache', 'miss')
|
||||
->send($data, null);
|
||||
;
|
||||
|
||||
unset($resize);
|
||||
unset($image);
|
||||
};
|
||||
|
||||
App::get('/v1/avatars/credit-cards/:code')
|
||||
->desc('Get Credit Card Icon')
|
||||
->groups(['api', 'avatars'])
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getCreditCard')
|
||||
->label('sdk.methodType', 'location')
|
||||
->label('sdk.description', '/docs/references/avatars/get-credit-card.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
|
||||
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.')
|
||||
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.')
|
||||
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
|
||||
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
|
||||
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
|
||||
@@ -104,7 +103,7 @@ App::get('/v1/avatars/browsers/:code')
|
||||
->desc('Get Browser Icon')
|
||||
->groups(['api', 'avatars'])
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getBrowser')
|
||||
->label('sdk.methodType', 'location')
|
||||
@@ -124,7 +123,7 @@ App::get('/v1/avatars/flags/:code')
|
||||
->desc('Get Country Flag')
|
||||
->groups(['api', 'avatars'])
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getFlag')
|
||||
->label('sdk.methodType', 'location')
|
||||
@@ -144,7 +143,7 @@ App::get('/v1/avatars/image')
|
||||
->desc('Get Image from URL')
|
||||
->groups(['api', 'avatars'])
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getImage')
|
||||
->label('sdk.methodType', 'location')
|
||||
@@ -160,11 +159,11 @@ App::get('/v1/avatars/image')
|
||||
|
||||
$quality = 80;
|
||||
$output = 'png';
|
||||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
|
||||
$key = \md5('/v2/avatars/images-'.$url.'-'.$width.'/'.$height.'/'.$quality);
|
||||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
|
||||
$key = \md5('/v2/avatars/images-' . $url . '-' . $width . '/' . $height . '/' . $quality);
|
||||
$type = 'png';
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
|
||||
$data = $cache->load($key, 60 * 60 * 24 * 7 /* 1 week */);
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
|
||||
$data = $cache->load($key, 60 * 60 * 24 * 7/* 1 week */);
|
||||
|
||||
if ($data) {
|
||||
return $response
|
||||
@@ -186,17 +185,17 @@ App::get('/v1/avatars/image')
|
||||
}
|
||||
|
||||
try {
|
||||
$resize = new Resize($fetch);
|
||||
} catch (\Exception $exception) {
|
||||
$image = new Image($fetch);
|
||||
} catch (\Exception$exception) {
|
||||
throw new Exception('Unable to parse image', 500);
|
||||
}
|
||||
|
||||
$resize->crop((int) $width, (int) $height);
|
||||
$image->crop((int) $width, (int) $height);
|
||||
|
||||
$output = (empty($output)) ? $type : $output;
|
||||
|
||||
$data = $resize->output($output, $quality);
|
||||
|
||||
|
||||
$data = $image->output($output, $quality);
|
||||
|
||||
$cache->save($key, $data);
|
||||
|
||||
$response
|
||||
@@ -206,14 +205,14 @@ App::get('/v1/avatars/image')
|
||||
->send($data);
|
||||
;
|
||||
|
||||
unset($resize);
|
||||
unset($image);
|
||||
});
|
||||
|
||||
App::get('/v1/avatars/favicon')
|
||||
->desc('Get Favicon')
|
||||
->groups(['api', 'avatars'])
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getFavicon')
|
||||
->label('sdk.methodType', 'location')
|
||||
@@ -229,11 +228,11 @@ App::get('/v1/avatars/favicon')
|
||||
$height = 56;
|
||||
$quality = 80;
|
||||
$output = 'png';
|
||||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
|
||||
$key = \md5('/v2/avatars/favicon-'.$url);
|
||||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
|
||||
$key = \md5('/v2/avatars/favicon-' . $url);
|
||||
$type = 'png';
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
|
||||
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */);
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
|
||||
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */);
|
||||
|
||||
if ($data) {
|
||||
return $response
|
||||
@@ -316,7 +315,7 @@ App::get('/v1/avatars/favicon')
|
||||
if (empty($outputHref) || empty($outputExt)) {
|
||||
$default = \parse_url($url);
|
||||
|
||||
$outputHref = $default['scheme'].'://'.$default['host'].'/favicon.ico';
|
||||
$outputHref = $default['scheme'] . '://' . $default['host'] . '/favicon.ico';
|
||||
$outputExt = 'ico';
|
||||
}
|
||||
|
||||
@@ -343,13 +342,13 @@ App::get('/v1/avatars/favicon')
|
||||
throw new Exception('Icon not found', 404);
|
||||
}
|
||||
|
||||
$resize = new Resize($fetch);
|
||||
$image = new Image($fetch);
|
||||
|
||||
$resize->crop((int) $width, (int) $height);
|
||||
$image->crop((int) $width, (int) $height);
|
||||
|
||||
$output = (empty($output)) ? $type : $output;
|
||||
|
||||
$data = $resize->output($output, $quality);
|
||||
$data = $image->output($output, $quality);
|
||||
|
||||
$cache->save($key, $data);
|
||||
|
||||
@@ -359,14 +358,14 @@ App::get('/v1/avatars/favicon')
|
||||
->addHeader('X-Appwrite-Cache', 'miss')
|
||||
->send($data);
|
||||
|
||||
unset($resize);
|
||||
unset($image);
|
||||
});
|
||||
|
||||
App::get('/v1/avatars/qr')
|
||||
->desc('Get QR Code')
|
||||
->groups(['api', 'avatars'])
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getQR')
|
||||
->label('sdk.methodType', 'location')
|
||||
@@ -394,14 +393,14 @@ App::get('/v1/avatars/qr')
|
||||
$response->addHeader('Content-Disposition', 'attachment; filename="qr.png"');
|
||||
}
|
||||
|
||||
$resize = new Resize($qrcode->render($text));
|
||||
$image = new Image($qrcode->render($text));
|
||||
|
||||
$resize->crop((int) $size, (int) $size);
|
||||
$image->crop((int) $size, (int) $size);
|
||||
|
||||
$response
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
|
||||
->setContentType('image/png')
|
||||
->send($resize->output('png', 9))
|
||||
->send($image->output('png', 9))
|
||||
;
|
||||
});
|
||||
|
||||
@@ -409,7 +408,7 @@ App::get('/v1/avatars/initials')
|
||||
->desc('Get User Initials')
|
||||
->groups(['api', 'avatars'])
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getInitials')
|
||||
->label('sdk.methodType', 'location')
|
||||
@@ -437,10 +436,10 @@ App::get('/v1/avatars/initials')
|
||||
['color' => '#610038', 'background' => '#f5d1e6'], // PINK
|
||||
['color' => '#386100', 'background' => '#dcf1bd'], // LIME
|
||||
['color' => '#615800', 'background' => '#f1ecba'], // YELLOW
|
||||
['color' => '#610008', 'background' => '#f6d2d5'] // RED
|
||||
['color' => '#610008', 'background' => '#f6d2d5'], // RED
|
||||
];
|
||||
|
||||
$rand = \rand(0, \count($themes)-1);
|
||||
$rand = \rand(0, \count($themes) - 1);
|
||||
|
||||
$name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', ''));
|
||||
$words = \explode(' ', \strtoupper($name));
|
||||
@@ -457,23 +456,23 @@ App::get('/v1/avatars/initials')
|
||||
}
|
||||
|
||||
$length = \count($words);
|
||||
$rand = \substr($code,-1);
|
||||
$background = (!empty($background)) ? '#'.$background : $themes[$rand]['background'];
|
||||
$color = (!empty($color)) ? '#'.$color : $themes[$rand]['color'];
|
||||
$rand = \substr($code, -1);
|
||||
$background = (!empty($background)) ? '#' . $background : $themes[$rand]['background'];
|
||||
$color = (!empty($color)) ? '#' . $color : $themes[$rand]['color'];
|
||||
|
||||
$image = new \Imagick();
|
||||
$draw = new \ImagickDraw();
|
||||
$fontSize = \min($width, $height) / 2;
|
||||
|
||||
$draw->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf");
|
||||
$image->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf");
|
||||
|
||||
$draw->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
|
||||
$image->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
|
||||
|
||||
$draw->setFillColor(new \ImagickPixel($color));
|
||||
$draw->setFontSize($fontSize);
|
||||
|
||||
|
||||
$draw->setTextAlignment(\Imagick::ALIGN_CENTER);
|
||||
$draw->annotation($width / 1.97, ($height / 2) + ($fontSize / 3), $initials);
|
||||
|
||||
|
||||
$image->newImage($width, $height, $background);
|
||||
$image->setImageFormat("png");
|
||||
$image->drawImage($draw);
|
||||
@@ -481,7 +480,7 @@ App::get('/v1/avatars/initials')
|
||||
//$image->setImageCompressionQuality(9 - round(($quality / 100) * 9));
|
||||
|
||||
$response
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
|
||||
->setContentType('image/png')
|
||||
->send($image->getImageBlob())
|
||||
;
|
||||
|
||||
@@ -24,7 +24,7 @@ App::post('/v1/database/collections')
|
||||
->label('event', 'database.collections.create')
|
||||
->label('scope', 'collections.write')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.method', 'createCollection')
|
||||
->label('sdk.description', '/docs/references/database/create-collection.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
@@ -96,7 +96,7 @@ App::get('/v1/database/collections')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'collections.read')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.method', 'listCollections')
|
||||
->label('sdk.description', '/docs/references/database/list-collections.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -133,7 +133,7 @@ App::get('/v1/database/collections/:collectionId')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'collections.read')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.method', 'getCollection')
|
||||
->label('sdk.description', '/docs/references/database/get-collection.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -161,7 +161,7 @@ App::put('/v1/database/collections/:collectionId')
|
||||
->label('scope', 'collections.write')
|
||||
->label('event', 'database.collections.update')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.method', 'updateCollection')
|
||||
->label('sdk.description', '/docs/references/database/update-collection.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -169,8 +169,8 @@ App::put('/v1/database/collections/:collectionId')
|
||||
->label('sdk.response.model', Response::MODEL_COLLECTION)
|
||||
->param('collectionId', '', new UID(), 'Collection unique ID.')
|
||||
->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.')
|
||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions(/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', true, ['projectDB'])
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
@@ -187,6 +187,8 @@ App::put('/v1/database/collections/:collectionId')
|
||||
}
|
||||
|
||||
$parsedRules = [];
|
||||
$read = (is_null($read)) ? ($collection->getPermissions()['read'] ?? []) : $read; // By default inherit read permissions
|
||||
$write = (is_null($write)) ? ($collection->getPermissions()['write'] ?? []) : $write; // By default inherit write permissions
|
||||
|
||||
foreach ($rules as &$rule) {
|
||||
$parsedRules[] = \array_merge([
|
||||
@@ -236,7 +238,7 @@ App::delete('/v1/database/collections/:collectionId')
|
||||
->label('scope', 'collections.write')
|
||||
->label('event', 'database.collections.delete')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.method', 'deleteCollection')
|
||||
->label('sdk.description', '/docs/references/database/delete-collection.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
@@ -269,7 +271,7 @@ App::delete('/v1/database/collections/:collectionId')
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($collection, Response::MODEL_COLLECTION))
|
||||
->setParam('eventData', $response->output($collection, Response::MODEL_COLLECTION))
|
||||
;
|
||||
|
||||
$audits
|
||||
@@ -287,25 +289,27 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||
->label('event', 'database.documents.create')
|
||||
->label('scope', 'documents.write')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.method', 'createDocument')
|
||||
->label('sdk.description', '/docs/references/database/create-document.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_ANY)
|
||||
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
||||
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('parentDocument', '', new UID(), 'Parent document unique ID. Use when you want your new document to be a child of a parent document.', true)
|
||||
->param('parentProperty', '', new Key(), 'Parent document property name. Use when you want your new document to be a child of a parent document.', true)
|
||||
->param('parentPropertyType', Document::SET_TYPE_ASSIGN, new WhiteList([Document::SET_TYPE_ASSIGN, Document::SET_TYPE_APPEND, Document::SET_TYPE_PREPEND], true), 'Parent document property connection type. You can set this value to **assign**, **append** or **prepend**, default value is assign. Use when you want your new document to be a child of a parent document.', true)
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
->inject('user')
|
||||
->inject('audits')
|
||||
->action(function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType, $response, $projectDB, $audits) {
|
||||
->action(function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType, $response, $projectDB, $user, $audits) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
@@ -326,8 +330,8 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||
|
||||
$data['$collection'] = $collectionId; // Adding this param to make API easier for developers
|
||||
$data['$permissions'] = [
|
||||
'read' => $read,
|
||||
'write' => $write,
|
||||
'read' => (is_null($read) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $read ?? [], // By default set read permissions for user
|
||||
'write' => (is_null($write) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $write ?? [], // By default set write permissions for user
|
||||
];
|
||||
|
||||
// Read parent document + validate not 404 + validate read / write permission like patch method
|
||||
@@ -397,7 +401,7 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($data, Response::MODEL_ANY)
|
||||
->dynamic($data, Response::MODEL_DOCUMENT)
|
||||
;
|
||||
});
|
||||
|
||||
@@ -406,7 +410,7 @@ App::get('/v1/database/collections/:collectionId/documents')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'documents.read')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.method', 'listDocuments')
|
||||
->label('sdk.description', '/docs/references/database/list-documents.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -469,12 +473,12 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'documents.read')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.method', 'getDocument')
|
||||
->label('sdk.description', '/docs/references/database/get-document.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_ANY)
|
||||
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
||||
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
||||
->param('documentId', null, new UID(), 'Document unique ID.')
|
||||
->inject('response')
|
||||
@@ -490,7 +494,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
throw new Exception('No document found', 404);
|
||||
}
|
||||
|
||||
$response->dynamic($document, Response::MODEL_ANY);
|
||||
$response->dynamic($document, Response::MODEL_DOCUMENT);
|
||||
});
|
||||
|
||||
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
@@ -499,17 +503,17 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
->label('event', 'database.documents.update')
|
||||
->label('scope', 'documents.write')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.method', 'updateDocument')
|
||||
->label('sdk.description', '/docs/references/database/update-document.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_ANY)
|
||||
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
||||
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
||||
->param('documentId', null, new UID(), 'Document unique ID.')
|
||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
->inject('audits')
|
||||
@@ -522,7 +526,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
$document = $projectDB->getDocument($documentId, false);
|
||||
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
|
||||
if (!\is_array($data)) {
|
||||
throw new Exception('Data param should be a valid JSON object', 400);
|
||||
}
|
||||
@@ -535,20 +539,12 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
throw new Exception('No document found', 404);
|
||||
}
|
||||
|
||||
//TODO check merge read write permissions
|
||||
|
||||
if (!empty($read)) { // Overwrite permissions only when passed
|
||||
$data['$permissions']['read'] = $read;
|
||||
}
|
||||
|
||||
if (!empty($write)) { // Overwrite permissions only when passed
|
||||
$data['$permissions']['write'] = $write;
|
||||
}
|
||||
|
||||
$data = \array_merge($document->getArrayCopy(), $data);
|
||||
|
||||
$data['$collection'] = $collection->getId(); // Make sure user don't switch collectionID
|
||||
$data['$id'] = $document->getId(); // Make sure user don't switch document unique ID
|
||||
$data['$permissions']['read'] = (is_null($read)) ? ($document->getPermissions()['read'] ?? []) : $read; // By default inherit read permissions
|
||||
$data['$permissions']['write'] = (is_null($write)) ? ($document->getPermissions()['write'] ?? []) : $write; // By default inherit write permissions
|
||||
|
||||
if (empty($data)) {
|
||||
throw new Exception('Missing payload', 400);
|
||||
@@ -570,7 +566,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
->setParam('data', $data->getArrayCopy())
|
||||
;
|
||||
|
||||
$response->dynamic($data, Response::MODEL_ANY);
|
||||
$response->dynamic($data, Response::MODEL_DOCUMENT);
|
||||
});
|
||||
|
||||
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
@@ -579,7 +575,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
->label('scope', 'documents.write')
|
||||
->label('event', 'database.documents.delete')
|
||||
->label('sdk.namespace', 'database')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.method', 'deleteDocument')
|
||||
->label('sdk.description', '/docs/references/database/delete-document.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
@@ -618,9 +614,9 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||
}
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($document, Response::MODEL_ANY))
|
||||
->setParam('eventData', $response->output($document, Response::MODEL_DOCUMENT))
|
||||
;
|
||||
|
||||
|
||||
$audits
|
||||
->setParam('event', 'database.documents.delete')
|
||||
->setParam('resource', 'database/document/'.$document->getId())
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Ahc\Jwt\JWT;
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Database\Database;
|
||||
use Appwrite\Database\Document;
|
||||
use Appwrite\Database\Validator\Authorization;
|
||||
@@ -27,7 +29,8 @@ App::post('/v1/functions')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Create Function')
|
||||
->label('scope', 'functions.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('event', 'functions.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'create')
|
||||
->label('sdk.description', '/docs/references/functions/create-function.md')
|
||||
@@ -80,7 +83,7 @@ App::get('/v1/functions')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('List Functions')
|
||||
->label('scope', 'functions.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'list')
|
||||
->label('sdk.description', '/docs/references/functions/list-functions.md')
|
||||
@@ -117,7 +120,7 @@ App::get('/v1/functions/:functionId')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Get Function')
|
||||
->label('scope', 'functions.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', '/docs/references/functions/get-function.md')
|
||||
@@ -144,7 +147,7 @@ App::get('/v1/functions/:functionId/usage')
|
||||
->desc('Get Function Usage')
|
||||
->groups(['api', 'functions'])
|
||||
->label('scope', 'functions.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CONSOLE])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'getUsage')
|
||||
->param('functionId', '', new UID(), 'Function unique ID.')
|
||||
@@ -265,7 +268,8 @@ App::put('/v1/functions/:functionId')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Update Function')
|
||||
->label('scope', 'functions.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('event', 'functions.update')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'update')
|
||||
->label('sdk.description', '/docs/references/functions/update-function.md')
|
||||
@@ -330,7 +334,8 @@ App::patch('/v1/functions/:functionId/tag')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Update Function Tag')
|
||||
->label('scope', 'functions.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('event', 'functions.tags.update')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'updateTag')
|
||||
->label('sdk.description', '/docs/references/functions/update-function-tag.md')
|
||||
@@ -387,7 +392,8 @@ App::delete('/v1/functions/:functionId')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Delete Function')
|
||||
->label('scope', 'functions.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('event', 'functions.delete')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.description', '/docs/references/functions/delete-function.md')
|
||||
@@ -424,7 +430,8 @@ App::post('/v1/functions/:functionId/tags')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Create Tag')
|
||||
->label('scope', 'functions.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('event', 'functions.tags.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'createTag')
|
||||
->label('sdk.description', '/docs/references/functions/create-tag.md')
|
||||
@@ -435,7 +442,7 @@ App::post('/v1/functions/:functionId/tags')
|
||||
->label('sdk.response.model', Response::MODEL_TAG)
|
||||
->param('functionId', '', new UID(), 'Function unique ID.')
|
||||
->param('command', '', new Text('1028'), 'Code execution command.')
|
||||
->param('code', null, new File(), 'Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.', false)
|
||||
->param('code', [], new File(), 'Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.', false)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
@@ -518,7 +525,7 @@ App::get('/v1/functions/:functionId/tags')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('List Tags')
|
||||
->label('scope', 'functions.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'listTags')
|
||||
->label('sdk.description', '/docs/references/functions/list-tags.md')
|
||||
@@ -563,7 +570,7 @@ App::get('/v1/functions/:functionId/tags/:tagId')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Get Tag')
|
||||
->label('scope', 'functions.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'getTag')
|
||||
->label('sdk.description', '/docs/references/functions/get-tag.md')
|
||||
@@ -601,7 +608,8 @@ App::delete('/v1/functions/:functionId/tags/:tagId')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Delete Tag')
|
||||
->label('scope', 'functions.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('event', 'functions.tags.delete')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'deleteTag')
|
||||
->label('sdk.description', '/docs/references/functions/delete-tag.md')
|
||||
@@ -662,7 +670,8 @@ App::post('/v1/functions/:functionId/executions')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Create Execution')
|
||||
->label('scope', 'execution.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('event', 'functions.executions.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'createExecution')
|
||||
->label('sdk.description', '/docs/references/functions/create-execution.md')
|
||||
@@ -672,14 +681,17 @@ App::post('/v1/functions/:functionId/executions')
|
||||
->label('abuse-limit', 60)
|
||||
->label('abuse-time', 60)
|
||||
->param('functionId', '', new UID(), 'Function unique ID.')
|
||||
->param('data', '', new Text(8192), 'String of custom data to send to function.', true)
|
||||
// ->param('async', 1, new Range(0, 1), 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true)
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('projectDB')
|
||||
->action(function ($functionId, /*$async,*/ $response, $project, $projectDB) {
|
||||
->inject('user')
|
||||
->action(function ($functionId, $data, /*$async,*/ $response, $project, $projectDB, $user) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
|
||||
Authorization::disable();
|
||||
|
||||
@@ -712,7 +724,7 @@ App::post('/v1/functions/:functionId/executions')
|
||||
$execution = $projectDB->createDocument([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_EXECUTIONS,
|
||||
'$permissions' => [
|
||||
'read' => $function->getPermissions()['execute'] ?? [],
|
||||
'read' => (!empty($user->getId())) ? ['user:' . $user->getId()] : [],
|
||||
'write' => [],
|
||||
],
|
||||
'dateCreated' => time(),
|
||||
@@ -730,12 +742,36 @@ App::post('/v1/functions/:functionId/executions')
|
||||
if (false === $execution) {
|
||||
throw new Exception('Failed saving execution to DB', 500);
|
||||
}
|
||||
|
||||
|
||||
$jwt = ''; // initialize
|
||||
if (!empty($user->getId())) { // If userId exists, generate a JWT for function
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$session = new Document();
|
||||
|
||||
foreach ($tokens as $token) { /** @var Appwrite\Database\Document $token */
|
||||
if ($token->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
$session = $token;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$session->isEmpty()) {
|
||||
$jwtObj = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
|
||||
$jwt = $jwtObj->encode([
|
||||
'userId' => $user->getId(),
|
||||
'sessionId' => $session->getId(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Resque::enqueue('v1-functions', 'FunctionsV1', [
|
||||
'projectId' => $project->getId(),
|
||||
'functionId' => $function->getId(),
|
||||
'executionId' => $execution->getId(),
|
||||
'trigger' => 'http',
|
||||
'data' => $data,
|
||||
'userId' => $user->getId(),
|
||||
'jwt' => $jwt,
|
||||
]);
|
||||
|
||||
$response
|
||||
@@ -748,7 +784,7 @@ App::get('/v1/functions/:functionId/executions')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('List Executions')
|
||||
->label('scope', 'execution.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'listExecutions')
|
||||
->label('sdk.description', '/docs/references/functions/list-executions.md')
|
||||
@@ -793,7 +829,7 @@ App::get('/v1/functions/:functionId/executions/:executionId')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Get Execution')
|
||||
->label('scope', 'execution.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'getExecution')
|
||||
->label('sdk.description', '/docs/references/functions/get-execution.md')
|
||||
|
||||
@@ -11,7 +11,7 @@ App::get('/v1/health')
|
||||
->desc('Get HTTP')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', '/docs/references/health/get.md')
|
||||
@@ -37,7 +37,7 @@ App::get('/v1/health/db')
|
||||
->desc('Get DB')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getDB')
|
||||
->label('sdk.description', '/docs/references/health/get-db.md')
|
||||
@@ -56,7 +56,7 @@ App::get('/v1/health/cache')
|
||||
->desc('Get Cache')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getCache')
|
||||
->label('sdk.description', '/docs/references/health/get-cache.md')
|
||||
@@ -74,7 +74,7 @@ App::get('/v1/health/time')
|
||||
->desc('Get Time')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getTime')
|
||||
->label('sdk.description', '/docs/references/health/get-time.md')
|
||||
@@ -123,7 +123,7 @@ App::get('/v1/health/queue/webhooks')
|
||||
->desc('Get Webhooks Queue')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getQueueWebhooks')
|
||||
->label('sdk.description', '/docs/references/health/get-queue-webhooks.md')
|
||||
@@ -138,7 +138,7 @@ App::get('/v1/health/queue/tasks')
|
||||
->desc('Get Tasks Queue')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getQueueTasks')
|
||||
->label('sdk.description', '/docs/references/health/get-queue-tasks.md')
|
||||
@@ -153,7 +153,7 @@ App::get('/v1/health/queue/logs')
|
||||
->desc('Get Logs Queue')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getQueueLogs')
|
||||
->label('sdk.description', '/docs/references/health/get-queue-logs.md')
|
||||
@@ -168,7 +168,7 @@ App::get('/v1/health/queue/usage')
|
||||
->desc('Get Usage Queue')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getQueueUsage')
|
||||
->label('sdk.description', '/docs/references/health/get-queue-usage.md')
|
||||
@@ -183,7 +183,7 @@ App::get('/v1/health/queue/certificates')
|
||||
->desc('Get Certificate Queue')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getQueueCertificates')
|
||||
->label('sdk.description', '/docs/references/health/get-queue-certificates.md')
|
||||
@@ -198,7 +198,7 @@ App::get('/v1/health/queue/functions')
|
||||
->desc('Get Functions Queue')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getQueueFunctions')
|
||||
->label('sdk.description', '/docs/references/health/get-queue-functions.md')
|
||||
@@ -213,7 +213,7 @@ App::get('/v1/health/storage/local')
|
||||
->desc('Get Local Storage')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getStorageLocal')
|
||||
->label('sdk.description', '/docs/references/health/get-storage-local.md')
|
||||
@@ -245,7 +245,7 @@ App::get('/v1/health/anti-virus')
|
||||
->desc('Get Anti virus')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'health.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'health')
|
||||
->label('sdk.method', 'getAntiVirus')
|
||||
->label('sdk.description', '/docs/references/health/get-storage-anti-virus.md')
|
||||
@@ -254,7 +254,10 @@ App::get('/v1/health/anti-virus')
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
|
||||
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'disabled') { // Check if scans are enabled
|
||||
throw new Exception('Anitvirus is disabled');
|
||||
return $response->json([
|
||||
'status' => 'disabled',
|
||||
'version' => '',
|
||||
]);
|
||||
}
|
||||
|
||||
$antiVirus = new Network(App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'),
|
||||
@@ -270,7 +273,7 @@ App::get('/v1/health/stats') // Currently only used internally
|
||||
->desc('Get System Stats')
|
||||
->groups(['api', 'health'])
|
||||
->label('scope', 'god')
|
||||
// ->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
// ->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
// ->label('sdk.namespace', 'health')
|
||||
// ->label('sdk.method', 'getStats')
|
||||
->label('docs', false)
|
||||
|
||||
@@ -9,7 +9,7 @@ App::get('/v1/locale')
|
||||
->desc('Get User Locale')
|
||||
->groups(['api', 'locale'])
|
||||
->label('scope', 'locale.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'locale')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', '/docs/references/locale/get-locale.md')
|
||||
@@ -74,7 +74,7 @@ App::get('/v1/locale/countries')
|
||||
->desc('List Countries')
|
||||
->groups(['api', 'locale'])
|
||||
->label('scope', 'locale.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'locale')
|
||||
->label('sdk.method', 'getCountries')
|
||||
->label('sdk.description', '/docs/references/locale/get-countries.md')
|
||||
@@ -106,7 +106,7 @@ App::get('/v1/locale/countries/eu')
|
||||
->desc('List EU Countries')
|
||||
->groups(['api', 'locale'])
|
||||
->label('scope', 'locale.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'locale')
|
||||
->label('sdk.method', 'getCountriesEU')
|
||||
->label('sdk.description', '/docs/references/locale/get-countries-eu.md')
|
||||
@@ -141,7 +141,7 @@ App::get('/v1/locale/countries/phones')
|
||||
->desc('List Countries Phone Codes')
|
||||
->groups(['api', 'locale'])
|
||||
->label('scope', 'locale.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'locale')
|
||||
->label('sdk.method', 'getCountriesPhones')
|
||||
->label('sdk.description', '/docs/references/locale/get-countries-phones.md')
|
||||
@@ -177,7 +177,7 @@ App::get('/v1/locale/continents')
|
||||
->desc('List Continents')
|
||||
->groups(['api', 'locale'])
|
||||
->label('scope', 'locale.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'locale')
|
||||
->label('sdk.method', 'getContinents')
|
||||
->label('sdk.description', '/docs/references/locale/get-continents.md')
|
||||
@@ -208,7 +208,7 @@ App::get('/v1/locale/currencies')
|
||||
->desc('List Currencies')
|
||||
->groups(['api', 'locale'])
|
||||
->label('scope', 'locale.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'locale')
|
||||
->label('sdk.method', 'getCurrencies')
|
||||
->label('sdk.description', '/docs/references/locale/get-currencies.md')
|
||||
@@ -233,7 +233,7 @@ App::get('/v1/locale/languages')
|
||||
->desc('List Languages')
|
||||
->groups(['api', 'locale'])
|
||||
->label('scope', 'locale.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'locale')
|
||||
->label('sdk.method', 'getLanguages')
|
||||
->label('sdk.description', '/docs/references/locale/get-languages.md')
|
||||
|
||||
@@ -6,8 +6,9 @@ use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\URL;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Integer;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Domains\Domain;
|
||||
use Appwrite\Auth\Auth;
|
||||
@@ -24,6 +25,7 @@ App::post('/v1/projects')
|
||||
->desc('Create Project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'create')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
@@ -96,6 +98,7 @@ App::get('/v1/projects')
|
||||
->desc('List Projects')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'list')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -131,6 +134,7 @@ App::get('/v1/projects/:projectId')
|
||||
->desc('Get Project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -156,6 +160,7 @@ App::get('/v1/projects/:projectId/usage')
|
||||
->desc('Get Project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getUsage')
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
@@ -356,6 +361,7 @@ App::patch('/v1/projects/:projectId')
|
||||
->desc('Update Project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'update')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -408,6 +414,7 @@ App::patch('/v1/projects/:projectId/oauth2')
|
||||
->desc('Update Project OAuth2')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateOAuth2')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -441,10 +448,85 @@ App::patch('/v1/projects/:projectId/oauth2')
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
App::patch('/v1/projects/:projectId/auth/limit')
|
||||
->desc('Update Project users limit')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateAuthLimit')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PROJECT)
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('limit', false, new Integer(true), 'Set the max number of users allowed in this project. Use 0 for unlimited.')
|
||||
->inject('response')
|
||||
->inject('consoleDB')
|
||||
->action(function ($projectId, $limit, $response, $consoleDB) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $consoleDB */
|
||||
|
||||
$project = $consoleDB->getDocument($projectId);
|
||||
|
||||
if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) {
|
||||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
if (false === $consoleDB->updateDocument(
|
||||
\array_merge($project->getArrayCopy(), [
|
||||
'usersAuthLimit' => $limit,
|
||||
]))
|
||||
) {
|
||||
throw new Exception('Failed saving project to DB', 500);
|
||||
};
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
App::patch('/v1/projects/:projectId/auth/:method')
|
||||
->desc('Update Project auth method status. Use this endpoint to enable or disable a given auth method for this project.')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateAuthStatus')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PROJECT)
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: '.implode(',', \array_keys(Config::getParam('auth'))), false)
|
||||
->param('status', false, new Boolean(true), 'Set the status of this auth method.')
|
||||
->inject('response')
|
||||
->inject('consoleDB')
|
||||
->action(function ($projectId, $method, $status, $response, $consoleDB) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $consoleDB */
|
||||
|
||||
$project = $consoleDB->getDocument($projectId);
|
||||
$auth = Config::getParam('auth')[$method] ?? [];
|
||||
$authKey = $auth['key'] ?? '';
|
||||
$status = ($status === '1' || $status === 'true' || $status === 1 || $status === true);
|
||||
|
||||
if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) {
|
||||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
if (false === $consoleDB->updateDocument(
|
||||
\array_merge($project->getArrayCopy(), [
|
||||
$authKey => $status,
|
||||
]))
|
||||
) {
|
||||
throw new Exception('Failed saving project to DB', 500);
|
||||
};
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
App::delete('/v1/projects/:projectId')
|
||||
->desc('Delete Project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
@@ -510,6 +592,7 @@ App::post('/v1/projects/:projectId/webhooks')
|
||||
->desc('Create Webhook')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'createWebhook')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
@@ -572,6 +655,7 @@ App::get('/v1/projects/:projectId/webhooks')
|
||||
->desc('List Webhooks')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'listWebhooks')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -602,6 +686,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
->desc('Get Webhook')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getWebhook')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -634,6 +719,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
->desc('Update Webhook')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateWebhook')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -687,6 +773,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
->desc('Delete Webhook')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'deleteWebhook')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
@@ -724,6 +811,7 @@ App::post('/v1/projects/:projectId/keys')
|
||||
->desc('Create Key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'createKey')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
@@ -777,6 +865,7 @@ App::get('/v1/projects/:projectId/keys')
|
||||
->desc('List Keys')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'listKeys')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -807,6 +896,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
|
||||
->desc('Get Key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getKey')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -836,6 +926,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
||||
->desc('Update Key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateKey')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -879,6 +970,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
|
||||
->desc('Delete Key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'deleteKey')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
@@ -916,6 +1008,7 @@ App::post('/v1/projects/:projectId/tasks')
|
||||
->desc('Create Task')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'createTask')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
@@ -996,6 +1089,7 @@ App::get('/v1/projects/:projectId/tasks')
|
||||
->desc('List Tasks')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'listTasks')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1027,6 +1121,7 @@ App::get('/v1/projects/:projectId/tasks/:taskId')
|
||||
->desc('Get Task')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getTask')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1059,6 +1154,7 @@ App::put('/v1/projects/:projectId/tasks/:taskId')
|
||||
->desc('Update Task')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateTask')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1127,6 +1223,7 @@ App::delete('/v1/projects/:projectId/tasks/:taskId')
|
||||
->desc('Delete Task')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'deleteTask')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
@@ -1164,6 +1261,7 @@ App::post('/v1/projects/:projectId/platforms')
|
||||
->desc('Create Platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'createPlatform')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
@@ -1224,6 +1322,7 @@ App::get('/v1/projects/:projectId/platforms')
|
||||
->desc('List Platforms')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'listPlatforms')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1254,6 +1353,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
|
||||
->desc('Get Platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getPlatform')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1286,6 +1386,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
||||
->desc('Update Platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updatePlatform')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1334,6 +1435,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
|
||||
->desc('Delete Platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'deletePlatform')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
@@ -1371,6 +1473,7 @@ App::post('/v1/projects/:projectId/domains')
|
||||
->desc('Create Domain')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'createDomain')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
@@ -1440,6 +1543,7 @@ App::get('/v1/projects/:projectId/domains')
|
||||
->desc('List Domains')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'listDomains')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1470,6 +1574,7 @@ App::get('/v1/projects/:projectId/domains/:domainId')
|
||||
->desc('Get Domain')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getDomain')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1502,6 +1607,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
||||
->desc('Update Domain Verification Status')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateDomainVerification')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
@@ -1565,6 +1671,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId')
|
||||
->desc('Delete Domain')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'deleteDomain')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
|
||||
@@ -18,7 +18,7 @@ use Utopia\Storage\Validator\File;
|
||||
use Utopia\Storage\Validator\FileSize;
|
||||
use Utopia\Storage\Validator\Upload;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Appwrite\Resize\Resize;
|
||||
use Utopia\Image\Image;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
@@ -28,7 +28,7 @@ App::post('/v1/storage/files')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.write')
|
||||
->label('event', 'storage.files.create')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'createFile')
|
||||
->label('sdk.description', '/docs/references/storage/create-file.md')
|
||||
@@ -38,17 +38,19 @@ App::post('/v1/storage/files')
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_FILE)
|
||||
->param('file', [], new File(), 'Binary file.', false)
|
||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
->inject('user')
|
||||
->inject('audits')
|
||||
->inject('usage')
|
||||
->action(function ($file, $read, $write, $request, $response, $projectDB, $audits, $usage) {
|
||||
->action(function ($file, $read, $write, $request, $response, $projectDB, $user, $audits, $usage) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $usage */
|
||||
|
||||
@@ -113,7 +115,7 @@ App::post('/v1/storage/files')
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$data = OpenSSL::encrypt($data, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag);
|
||||
|
||||
if (!$device->write($path, $data)) {
|
||||
if (!$device->write($path, $data, $mimeType)) {
|
||||
throw new Exception('Failed to save file', 500);
|
||||
}
|
||||
|
||||
@@ -122,8 +124,8 @@ App::post('/v1/storage/files')
|
||||
$file = $projectDB->createDocument([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_FILES,
|
||||
'$permissions' => [
|
||||
'read' => $read,
|
||||
'write' => $write,
|
||||
'read' => (is_null($read) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $read ?? [], // By default set read permissions for user
|
||||
'write' => (is_null($write) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $write ?? [], // By default set write permissions for user
|
||||
],
|
||||
'dateCreated' => \time(),
|
||||
'folderId' => '',
|
||||
@@ -165,7 +167,7 @@ App::get('/v1/storage/files')
|
||||
->desc('List Files')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'listFiles')
|
||||
->label('sdk.description', '/docs/references/storage/list-files.md')
|
||||
@@ -202,7 +204,7 @@ App::get('/v1/storage/files/:fileId')
|
||||
->desc('Get File')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'getFile')
|
||||
->label('sdk.description', '/docs/references/storage/get-file.md')
|
||||
@@ -229,7 +231,7 @@ App::get('/v1/storage/files/:fileId/preview')
|
||||
->desc('Get File Preview')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'getFilePreview')
|
||||
->label('sdk.description', '/docs/references/storage/get-file-preview.md')
|
||||
@@ -240,13 +242,18 @@ App::get('/v1/storage/files/:fileId/preview')
|
||||
->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true)
|
||||
->param('height', 0, new Range(0, 4000), 'Resize preview image height, Pass an integer between 0 to 4000.', true)
|
||||
->param('quality', 100, new Range(0, 100), 'Preview image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
|
||||
->param('borderWidth', 0, new Range(0, 100), 'Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.', true)
|
||||
->param('borderColor', '', new HexColor(), 'Preview image border color. Use a valid HEX color, no # is needed for prefix.', true)
|
||||
->param('borderRadius', 0, new Range(0, 4000), 'Preview image border radius in pixels. Pass an integer between 0 to 4000.', true)
|
||||
->param('opacity', 1, new Range(0,1), 'Preview image opacity. Only works with images having an alpha channel (like png). Pass a number between 0 to 1.', true)
|
||||
->param('rotation', 0, new Range(0,360), 'Preview image rotation in degrees. Pass an integer between 0 and 360.', true)
|
||||
->param('background', '', new HexColor(), 'Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.', true)
|
||||
->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('projectDB')
|
||||
->action(function ($fileId, $width, $height, $quality, $background, $output, $request, $response, $project, $projectDB) {
|
||||
->action(function ($fileId, $width, $height, $quality, $borderWidth, $borderColor, $borderRadius, $opacity, $rotation, $background, $output, $request, $response, $project, $projectDB) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
@@ -271,7 +278,7 @@ App::get('/v1/storage/files/:fileId/preview')
|
||||
$fileLogos = Config::getParam('storage-logos');
|
||||
|
||||
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
|
||||
$key = \md5($fileId.$width.$height.$quality.$background.$storage.$output);
|
||||
$key = \md5($fileId.$width.$height.$quality.$borderWidth.$borderColor.$borderRadius.$opacity.$rotation.$background.$storage.$output);
|
||||
|
||||
$file = $projectDB->getDocument($fileId);
|
||||
|
||||
@@ -291,7 +298,7 @@ App::get('/v1/storage/files/:fileId/preview')
|
||||
$cipher = null;
|
||||
$background = (empty($background)) ? 'eceff1' : $background;
|
||||
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
|
||||
$key = \md5($path.$width.$height.$quality.$background.$storage.$output);
|
||||
$key = \md5($path.$width.$height.$quality.$borderWidth.$borderColor.$borderRadius.$opacity.$rotation.$background.$storage.$output);
|
||||
}
|
||||
|
||||
$compressor = new GZIP();
|
||||
@@ -332,17 +339,34 @@ App::get('/v1/storage/files/:fileId/preview')
|
||||
$source = $compressor->decompress($source);
|
||||
}
|
||||
|
||||
$resize = new Resize($source);
|
||||
$image = new Image($source);
|
||||
|
||||
$resize->crop((int) $width, (int) $height);
|
||||
$image->crop((int) $width, (int) $height);
|
||||
|
||||
if (!empty($opacity) || $opacity==0) {
|
||||
$image->setOpacity($opacity);
|
||||
}
|
||||
|
||||
if (!empty($background)) {
|
||||
$resize->setBackground('#'.$background);
|
||||
$image->setBackground('#'.$background);
|
||||
}
|
||||
|
||||
|
||||
if (!empty($borderWidth) ) {
|
||||
$image->setBorder($borderWidth, '#'.$borderColor);
|
||||
}
|
||||
|
||||
if (!empty($borderRadius)) {
|
||||
$image->setBorderRadius($borderRadius);
|
||||
}
|
||||
|
||||
if (!empty($rotation)) {
|
||||
$image->setRotation($rotation);
|
||||
}
|
||||
|
||||
$output = (empty($output)) ? $type : $output;
|
||||
|
||||
$data = $resize->output($output, $quality);
|
||||
$data = $image->output($output, $quality);
|
||||
|
||||
$cache->save($key, $data);
|
||||
|
||||
@@ -353,14 +377,14 @@ App::get('/v1/storage/files/:fileId/preview')
|
||||
->send($data)
|
||||
;
|
||||
|
||||
unset($resize);
|
||||
unset($image);
|
||||
});
|
||||
|
||||
App::get('/v1/storage/files/:fileId/download')
|
||||
->desc('Get File for Download')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'getFileDownload')
|
||||
->label('sdk.description', '/docs/references/storage/get-file-download.md')
|
||||
@@ -418,7 +442,7 @@ App::get('/v1/storage/files/:fileId/view')
|
||||
->desc('Get File for View')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'getFileView')
|
||||
->label('sdk.description', '/docs/references/storage/get-file-view.md')
|
||||
@@ -487,7 +511,7 @@ App::put('/v1/storage/files/:fileId')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.write')
|
||||
->label('event', 'storage.files.update')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'updateFile')
|
||||
->label('sdk.description', '/docs/references/storage/update-file.md')
|
||||
@@ -536,7 +560,7 @@ App::delete('/v1/storage/files/:fileId')
|
||||
->groups(['api', 'storage'])
|
||||
->label('scope', 'files.write')
|
||||
->label('event', 'storage.files.delete')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'storage')
|
||||
->label('sdk.method', 'deleteFile')
|
||||
->label('sdk.description', '/docs/references/storage/delete-file.md')
|
||||
@@ -579,7 +603,7 @@ App::delete('/v1/storage/files/:fileId')
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($file, Response::MODEL_FILE))
|
||||
->setParam('eventData', $response->output($file, Response::MODEL_FILE))
|
||||
;
|
||||
|
||||
$response->noContent();
|
||||
@@ -589,7 +613,7 @@ App::delete('/v1/storage/files/:fileId')
|
||||
// ->desc('Scan Storage')
|
||||
// ->groups(['api', 'storage'])
|
||||
// ->label('scope', 'god')
|
||||
// ->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
// ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
// ->label('sdk.namespace', 'storage')
|
||||
// ->label('sdk.method', 'getFileScan')
|
||||
// ->label('sdk.hide', true)
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Validator\Email;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\Host;
|
||||
use Appwrite\Network\Validator\Host;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\WhiteList;
|
||||
@@ -25,7 +25,7 @@ App::post('/v1/teams')
|
||||
->groups(['api', 'teams'])
|
||||
->label('event', 'teams.create')
|
||||
->label('scope', 'teams.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'create')
|
||||
->label('sdk.description', '/docs/references/teams/create-team.md')
|
||||
@@ -44,7 +44,7 @@ App::post('/v1/teams')
|
||||
|
||||
Authorization::disable();
|
||||
|
||||
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
$team = $projectDB->createDocument([
|
||||
@@ -54,7 +54,7 @@ App::post('/v1/teams')
|
||||
'write' => ['team:{self}/owner'],
|
||||
],
|
||||
'name' => $name,
|
||||
'sum' => ($isPreviliggedUser || $isAppUser) ? 0 : 1,
|
||||
'sum' => ($isPrivilegedUser || $isAppUser) ? 0 : 1,
|
||||
'dateCreated' => \time(),
|
||||
]);
|
||||
|
||||
@@ -64,7 +64,7 @@ App::post('/v1/teams')
|
||||
throw new Exception('Failed saving team to DB', 500);
|
||||
}
|
||||
|
||||
if (!$isPreviliggedUser && !$isAppUser) { // Don't add user on server mode
|
||||
if (!$isPrivilegedUser && !$isAppUser) { // Don't add user on server mode
|
||||
$membership = new Document([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_MEMBERSHIPS,
|
||||
'$permissions' => [
|
||||
@@ -100,7 +100,7 @@ App::get('/v1/teams')
|
||||
->desc('List Teams')
|
||||
->groups(['api', 'teams'])
|
||||
->label('scope', 'teams.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'list')
|
||||
->label('sdk.description', '/docs/references/teams/list-teams.md')
|
||||
@@ -137,7 +137,7 @@ App::get('/v1/teams/:teamId')
|
||||
->desc('Get Team')
|
||||
->groups(['api', 'teams'])
|
||||
->label('scope', 'teams.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', '/docs/references/teams/get-team.md')
|
||||
@@ -165,7 +165,7 @@ App::put('/v1/teams/:teamId')
|
||||
->groups(['api', 'teams'])
|
||||
->label('event', 'teams.update')
|
||||
->label('scope', 'teams.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'update')
|
||||
->label('sdk.description', '/docs/references/teams/update-team.md')
|
||||
@@ -202,7 +202,7 @@ App::delete('/v1/teams/:teamId')
|
||||
->groups(['api', 'teams'])
|
||||
->label('event', 'teams.delete')
|
||||
->label('scope', 'teams.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.description', '/docs/references/teams/delete-team.md')
|
||||
@@ -243,7 +243,7 @@ App::delete('/v1/teams/:teamId')
|
||||
}
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($team, Response::MODEL_TEAM))
|
||||
->setParam('eventData', $response->output($team, Response::MODEL_TEAM))
|
||||
;
|
||||
|
||||
$response->noContent();
|
||||
@@ -251,16 +251,18 @@ App::delete('/v1/teams/:teamId')
|
||||
|
||||
App::post('/v1/teams/:teamId/memberships')
|
||||
->desc('Create Team Membership')
|
||||
->groups(['api', 'teams'])
|
||||
->groups(['api', 'teams', 'auth'])
|
||||
->label('event', 'teams.memberships.create')
|
||||
->label('scope', 'teams.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('auth.type', 'invites')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'createMembership')
|
||||
->label('sdk.description', '/docs/references/teams/create-team-membership.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
|
||||
->label('abuse-limit', 10)
|
||||
->param('teamId', '', new UID(), 'Team unique ID.')
|
||||
->param('email', '', new Email(), 'New team member email.')
|
||||
->param('name', '', new Text(128), 'New team member name. Max length: 128 chars.', true)
|
||||
@@ -281,7 +283,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $mails */
|
||||
|
||||
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
$name = (empty($name)) ? $email : $name;
|
||||
@@ -310,6 +312,22 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
|
||||
if (empty($invitee)) { // Create new user if no user with same email found
|
||||
|
||||
$limit = $project->getAttribute('usersAuthLimit', 0);
|
||||
|
||||
if ($limit !== 0 && $project->getId() !== 'console') { // check users limit, console invites are allways allowed.
|
||||
$projectDB->getCollection([ // Count users
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
],
|
||||
]);
|
||||
|
||||
$sum = $projectDB->getSum();
|
||||
|
||||
if($sum >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
|
||||
}
|
||||
}
|
||||
|
||||
Authorization::disable();
|
||||
|
||||
try {
|
||||
@@ -327,6 +345,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
'registration' => \time(),
|
||||
'reset' => false,
|
||||
'name' => $name,
|
||||
'sessions' => [],
|
||||
'tokens' => [],
|
||||
], ['email' => $email]);
|
||||
} catch (Duplicate $th) {
|
||||
@@ -352,7 +371,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isOwner && !$isPreviliggedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
throw new Exception('User is not allowed to send invitations for this team', 401);
|
||||
}
|
||||
|
||||
@@ -368,12 +387,12 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
'teamId' => $team->getId(),
|
||||
'roles' => $roles,
|
||||
'invited' => \time(),
|
||||
'joined' => ($isPreviliggedUser || $isAppUser) ? \time() : 0,
|
||||
'confirm' => ($isPreviliggedUser || $isAppUser),
|
||||
'joined' => ($isPrivilegedUser || $isAppUser) ? \time() : 0,
|
||||
'confirm' => ($isPrivilegedUser || $isAppUser),
|
||||
'secret' => Auth::hash($secret),
|
||||
]);
|
||||
|
||||
if ($isPreviliggedUser || $isAppUser) { // Allow admin to create membership
|
||||
if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership
|
||||
Authorization::disable();
|
||||
$membership = $projectDB->createDocument($membership->getArrayCopy());
|
||||
|
||||
@@ -425,7 +444,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
->setParam('{{text-cta}}', '#ffffff')
|
||||
;
|
||||
|
||||
if (!$isPreviliggedUser && !$isAppUser) { // No need in comfirmation when in admin or app mode
|
||||
if (!$isPrivilegedUser && !$isAppUser) { // No need in comfirmation when in admin or app mode
|
||||
$mails
|
||||
->setParam('event', 'teams.membership.create')
|
||||
->setParam('from', ($project->getId() === 'console') ? '' : \sprintf($locale->getText('account.emails.team'), $project->getAttribute('name')))
|
||||
@@ -456,7 +475,7 @@ App::get('/v1/teams/:teamId/memberships')
|
||||
->desc('Get Team Memberships')
|
||||
->groups(['api', 'teams'])
|
||||
->label('scope', 'teams.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'getMemberships')
|
||||
->label('sdk.description', '/docs/references/teams/get-team-members.md')
|
||||
@@ -510,7 +529,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||
->groups(['api', 'teams'])
|
||||
->label('event', 'teams.memberships.update.status')
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'updateMembershipStatus')
|
||||
->label('sdk.description', '/docs/references/teams/update-team-membership-status.md')
|
||||
@@ -595,10 +614,11 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$secret = Auth::tokenGenerator();
|
||||
$session = new Document(array_merge([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_TOKENS,
|
||||
'$collection' => Database::SYSTEM_COLLECTION_SESSIONS,
|
||||
'$permissions' => ['read' => ['user:'.$user->getId()], 'write' => ['user:'.$user->getId()]],
|
||||
'userId' => $user->getId(),
|
||||
'type' => Auth::TOKEN_TYPE_LOGIN,
|
||||
'provider' => Auth::SESSION_PROVIDER_EMAIL,
|
||||
'providerUid' => $user->getAttribute('email'),
|
||||
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
|
||||
'expire' => $expiry,
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
@@ -606,7 +626,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
], $detector->getOS(), $detector->getClient(), $detector->getDevice()));
|
||||
|
||||
$user->setAttribute('tokens', $session, Document::SET_TYPE_APPEND);
|
||||
$user->setAttribute('sessions', $session, Document::SET_TYPE_APPEND);
|
||||
|
||||
Authorization::setRole('user:'.$userId);
|
||||
|
||||
@@ -656,7 +676,7 @@ App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
||||
->groups(['api', 'teams'])
|
||||
->label('event', 'teams.memberships.delete')
|
||||
->label('scope', 'teams.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'deleteMembership')
|
||||
->label('sdk.description', '/docs/references/teams/delete-team-membership.md')
|
||||
@@ -711,7 +731,7 @@ App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($membership, Response::MODEL_MEMBERSHIP))
|
||||
->setParam('eventData', $response->output($membership, Response::MODEL_MEMBERSHIP))
|
||||
;
|
||||
|
||||
$response->noContent();
|
||||
|
||||
@@ -4,7 +4,7 @@ use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator\Assoc;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Email;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Audit\Audit;
|
||||
@@ -23,7 +23,7 @@ App::post('/v1/users')
|
||||
->groups(['api', 'users'])
|
||||
->label('event', 'users.create')
|
||||
->label('scope', 'users.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'create')
|
||||
->label('sdk.description', '/docs/references/users/create-user.md')
|
||||
@@ -81,7 +81,7 @@ App::get('/v1/users')
|
||||
->desc('List Users')
|
||||
->groups(['api', 'users'])
|
||||
->label('scope', 'users.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'list')
|
||||
->label('sdk.description', '/docs/references/users/list-users.md')
|
||||
@@ -118,7 +118,7 @@ App::get('/v1/users/:userId')
|
||||
->desc('Get User')
|
||||
->groups(['api', 'users'])
|
||||
->label('scope', 'users.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', '/docs/references/users/get-user.md')
|
||||
@@ -145,7 +145,7 @@ App::get('/v1/users/:userId/prefs')
|
||||
->desc('Get User Preferences')
|
||||
->groups(['api', 'users'])
|
||||
->label('scope', 'users.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'getPrefs')
|
||||
->label('sdk.description', '/docs/references/users/get-user-prefs.md')
|
||||
@@ -174,7 +174,7 @@ App::get('/v1/users/:userId/sessions')
|
||||
->desc('Get User Sessions')
|
||||
->groups(['api', 'users'])
|
||||
->label('scope', 'users.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'getSessions')
|
||||
->label('sdk.description', '/docs/references/users/get-user-sessions.md')
|
||||
@@ -196,21 +196,18 @@ App::get('/v1/users/:userId/sessions')
|
||||
throw new Exception('User not found', 404);
|
||||
}
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$sessions = [];
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$countries = $locale->getText('countries');
|
||||
|
||||
foreach ($tokens as $token) { /* @var $token Document */
|
||||
if (Auth::TOKEN_TYPE_LOGIN != $token->getAttribute('type')) {
|
||||
continue;
|
||||
}
|
||||
foreach ($sessions as $key => $session) {
|
||||
/** @var Document $session */
|
||||
|
||||
$token->setAttribute('countryName', (isset($countries[$token->getAttribute('contryCode')]))
|
||||
? $countries[$token->getAttribute('contryCode')]
|
||||
$session->setAttribute('countryName', (isset($countries[strtoupper($session->getAttribute('countryCode'))]))
|
||||
? $countries[strtoupper($session->getAttribute('countryCode'))]
|
||||
: $locale->getText('locale.country.unknown'));
|
||||
$token->setAttribute('current', false);
|
||||
$session->setAttribute('current', false);
|
||||
|
||||
$sessions[] = $token;
|
||||
$sessions[$key] = $session;
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -223,7 +220,7 @@ App::get('/v1/users/:userId/logs')
|
||||
->desc('Get User Logs')
|
||||
->groups(['api', 'users'])
|
||||
->label('scope', 'users.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'getLogs')
|
||||
->label('sdk.description', '/docs/references/users/get-user-logs.md')
|
||||
@@ -338,7 +335,7 @@ App::patch('/v1/users/:userId/status')
|
||||
->groups(['api', 'users'])
|
||||
->label('event', 'users.update.status')
|
||||
->label('scope', 'users.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'updateStatus')
|
||||
->label('sdk.description', '/docs/references/users/update-user-status.md')
|
||||
@@ -373,8 +370,9 @@ App::patch('/v1/users/:userId/status')
|
||||
App::patch('/v1/users/:userId/prefs')
|
||||
->desc('Update User Preferences')
|
||||
->groups(['api', 'users'])
|
||||
->label('event', 'users.update.prefs')
|
||||
->label('scope', 'users.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'updatePrefs')
|
||||
->label('sdk.description', '/docs/references/users/update-user-prefs.md')
|
||||
@@ -411,7 +409,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
|
||||
->groups(['api', 'users'])
|
||||
->label('event', 'users.sessions.delete')
|
||||
->label('scope', 'users.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'deleteSession')
|
||||
->label('sdk.description', '/docs/references/users/delete-user-session.md')
|
||||
@@ -433,16 +431,18 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
|
||||
throw new Exception('User not found', 404);
|
||||
}
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
||||
foreach ($tokens as $token) { /* @var $token Document */
|
||||
if ($sessionId == $token->getId()) {
|
||||
if (!$projectDB->deleteDocument($token->getId())) {
|
||||
foreach ($sessions as $session) {
|
||||
/** @var Document $session */
|
||||
|
||||
if ($sessionId == $session->getId()) {
|
||||
if (!$projectDB->deleteDocument($session->getId())) {
|
||||
throw new Exception('Failed to remove token from DB', 500);
|
||||
}
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||
->setParam('eventData', $response->output($user, Response::MODEL_USER))
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -456,7 +456,7 @@ App::delete('/v1/users/:userId/sessions')
|
||||
->groups(['api', 'users'])
|
||||
->label('event', 'users.sessions.delete')
|
||||
->label('scope', 'users.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'deleteSessions')
|
||||
->label('sdk.description', '/docs/references/users/delete-user-sessions.md')
|
||||
@@ -477,16 +477,18 @@ App::delete('/v1/users/:userId/sessions')
|
||||
throw new Exception('User not found', 404);
|
||||
}
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
||||
foreach ($tokens as $token) { /* @var $token Document */
|
||||
if (!$projectDB->deleteDocument($token->getId())) {
|
||||
foreach ($sessions as $session) {
|
||||
/** @var Document $session */
|
||||
|
||||
if (!$projectDB->deleteDocument($session->getId())) {
|
||||
throw new Exception('Failed to remove token from DB', 500);
|
||||
}
|
||||
}
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||
->setParam('eventData', $response->output($user, Response::MODEL_USER))
|
||||
;
|
||||
|
||||
// TODO : Response filter implementation
|
||||
@@ -498,10 +500,10 @@ App::delete('/v1/users/:userId')
|
||||
->groups(['api', 'users'])
|
||||
->label('event', 'users.delete')
|
||||
->label('scope', 'users.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'deleteUser')
|
||||
->label('sdk.description', '/docs/references/users/delete-user.md')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.description', '/docs/references/users/delete.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('userId', '', function () {return new UID();}, 'User unique ID.')
|
||||
@@ -546,7 +548,7 @@ App::delete('/v1/users/:userId')
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||
->setParam('eventData', $response->output($user, Response::MODEL_USER))
|
||||
;
|
||||
|
||||
// TODO : Response filter implementation
|
||||
|
||||
@@ -41,7 +41,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
if (!empty($route->getLabel('sdk.platform', [])) && empty($project->getId()) && ($route->getLabel('scope', '') !== 'public')) {
|
||||
if (!empty($route->getLabel('sdk.auth', [])) && empty($project->getId()) && ($route->getLabel('scope', '') !== 'public')) {
|
||||
throw new Exception('Missing or unknown project ID', 400);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||
->addHeader('Server', 'Appwrite')
|
||||
->addHeader('X-Content-Type-Options', 'nosniff')
|
||||
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
|
||||
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-SDK-Version, Cache-Control, Expires, Pragma')
|
||||
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, Cache-Control, Expires, Pragma')
|
||||
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
|
||||
->addHeader('Access-Control-Allow-Origin', $refDomain)
|
||||
->addHeader('Access-Control-Allow-Credentials', 'true')
|
||||
@@ -237,7 +237,7 @@ App::options(function ($request, $response) {
|
||||
$response
|
||||
->addHeader('Server', 'Appwrite')
|
||||
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
|
||||
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-SDK-Version, Cache-Control, Expires, Pragma, X-Fallback-Cookies')
|
||||
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, Cache-Control, Expires, Pragma, X-Fallback-Cookies')
|
||||
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
|
||||
->addHeader('Access-Control-Allow-Origin', $origin)
|
||||
->addHeader('Access-Control-Allow-Credentials', 'true')
|
||||
@@ -256,6 +256,8 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project) {
|
||||
$template = ($route) ? $route->getLabel('error', null) : null;
|
||||
|
||||
if (php_sapi_name() === 'cli') {
|
||||
Console::error('[Error] Timestamp: '.date('c', time()));
|
||||
|
||||
if($route) {
|
||||
Console::error('[Error] Method: '.$route->getMethod());
|
||||
Console::error('[Error] URL: '.$route->getURL());
|
||||
@@ -269,7 +271,7 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project) {
|
||||
|
||||
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
|
||||
|
||||
switch ($error->getCode()) {
|
||||
switch ($error->getCode()) { // Don't show 500 errors!
|
||||
case 400: // Error allowed publicly
|
||||
case 401: // Error allowed publicly
|
||||
case 402: // Error allowed publicly
|
||||
@@ -278,6 +280,7 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project) {
|
||||
case 409: // Error allowed publicly
|
||||
case 412: // Error allowed publicly
|
||||
case 429: // Error allowed publicly
|
||||
case 501: // Error allowed publicly
|
||||
$code = $error->getCode();
|
||||
$message = $error->getMessage();
|
||||
break;
|
||||
|
||||
+135
-54
@@ -2,8 +2,9 @@
|
||||
|
||||
global $utopia, $request, $response;
|
||||
|
||||
use Appwrite\Database\Document;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\App;
|
||||
use Utopia\Response;
|
||||
use Utopia\Validator\Numeric;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\ArrayList;
|
||||
@@ -11,13 +12,16 @@ use Utopia\Validator\Host;
|
||||
use Utopia\Storage\Validator\File;
|
||||
|
||||
App::get('/v1/mock/tests/foo')
|
||||
->desc('Mock a get request for SDK tests')
|
||||
->desc('Get Foo')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'foo')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', 'Mock a get request for SDK tests')
|
||||
->label('sdk.description', 'Mock a get request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -26,13 +30,16 @@ App::get('/v1/mock/tests/foo')
|
||||
});
|
||||
|
||||
App::post('/v1/mock/tests/foo')
|
||||
->desc('Mock a post request for SDK tests')
|
||||
->desc('Post Foo')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'foo')
|
||||
->label('sdk.method', 'post')
|
||||
->label('sdk.description', 'Mock a post request for SDK tests')
|
||||
->label('sdk.description', 'Mock a post request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -41,13 +48,16 @@ App::post('/v1/mock/tests/foo')
|
||||
});
|
||||
|
||||
App::patch('/v1/mock/tests/foo')
|
||||
->desc('Mock a patch request for SDK tests')
|
||||
->desc('Patch Foo')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'foo')
|
||||
->label('sdk.method', 'patch')
|
||||
->label('sdk.description', 'Mock a get request for SDK tests')
|
||||
->label('sdk.description', 'Mock a patch request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -56,13 +66,16 @@ App::patch('/v1/mock/tests/foo')
|
||||
});
|
||||
|
||||
App::put('/v1/mock/tests/foo')
|
||||
->desc('Mock a put request for SDK tests')
|
||||
->desc('Put Foo')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'foo')
|
||||
->label('sdk.method', 'put')
|
||||
->label('sdk.description', 'Mock a put request for SDK tests')
|
||||
->label('sdk.description', 'Mock a put request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -71,13 +84,16 @@ App::put('/v1/mock/tests/foo')
|
||||
});
|
||||
|
||||
App::delete('/v1/mock/tests/foo')
|
||||
->desc('Mock a delete request for SDK tests')
|
||||
->desc('Delete Foo')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'foo')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.description', 'Mock a delete request for SDK tests')
|
||||
->label('sdk.description', 'Mock a delete request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -86,13 +102,16 @@ App::delete('/v1/mock/tests/foo')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/bar')
|
||||
->desc('Mock a get request for SDK tests')
|
||||
->desc('Get Bar')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'bar')
|
||||
->label('sdk.method', 'get')
|
||||
->label('sdk.description', 'Mock a get request for SDK tests')
|
||||
->label('sdk.description', 'Mock a get request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -101,13 +120,16 @@ App::get('/v1/mock/tests/bar')
|
||||
});
|
||||
|
||||
App::post('/v1/mock/tests/bar')
|
||||
->desc('Mock a post request for SDK tests')
|
||||
->desc('Post Bar')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'bar')
|
||||
->label('sdk.method', 'post')
|
||||
->label('sdk.description', 'Mock a post request for SDK tests')
|
||||
->label('sdk.description', 'Mock a post request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -116,13 +138,16 @@ App::post('/v1/mock/tests/bar')
|
||||
});
|
||||
|
||||
App::patch('/v1/mock/tests/bar')
|
||||
->desc('Mock a patch request for SDK tests')
|
||||
->desc('Patch Bar')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'bar')
|
||||
->label('sdk.method', 'patch')
|
||||
->label('sdk.description', 'Mock a get request for SDK tests')
|
||||
->label('sdk.description', 'Mock a patch request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -131,13 +156,16 @@ App::patch('/v1/mock/tests/bar')
|
||||
});
|
||||
|
||||
App::put('/v1/mock/tests/bar')
|
||||
->desc('Mock a put request for SDK tests')
|
||||
->desc('Put Bar')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'bar')
|
||||
->label('sdk.method', 'put')
|
||||
->label('sdk.description', 'Mock a put request for SDK tests')
|
||||
->label('sdk.description', 'Mock a put request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -146,13 +174,16 @@ App::put('/v1/mock/tests/bar')
|
||||
});
|
||||
|
||||
App::delete('/v1/mock/tests/bar')
|
||||
->desc('Mock a delete request for SDK tests')
|
||||
->desc('Delete Bar')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'bar')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.description', 'Mock a delete request for SDK tests')
|
||||
->label('sdk.description', 'Mock a delete request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -161,14 +192,17 @@ App::delete('/v1/mock/tests/bar')
|
||||
});
|
||||
|
||||
App::post('/v1/mock/tests/general/upload')
|
||||
->desc('Mock a post request for SDK tests')
|
||||
->desc('Upload File')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'upload')
|
||||
->label('sdk.description', 'Mock a delete request for SDK tests')
|
||||
->label('sdk.description', 'Mock a file upload request.')
|
||||
->label('sdk.request.type', 'multipart/form-data')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->param('x', '', new Text(100), 'Sample string param')
|
||||
->param('y', '', new Numeric(), 'Sample numeric param')
|
||||
@@ -203,13 +237,15 @@ App::post('/v1/mock/tests/general/upload')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/redirect')
|
||||
->desc('Mock a post request for SDK tests')
|
||||
->desc('Redirect')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'redirect')
|
||||
->label('sdk.description', 'Mock a redirect request for SDK tests')
|
||||
->label('sdk.description', 'Mock a redirect request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_HTML)
|
||||
->label('sdk.mock', true)
|
||||
->inject('response')
|
||||
->action(function ($response) {
|
||||
@@ -219,25 +255,31 @@ App::get('/v1/mock/tests/general/redirect')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/redirect/done')
|
||||
->desc('Mock a post request for SDK tests')
|
||||
->desc('Redirected')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'redirected')
|
||||
->label('sdk.description', 'Mock a redirected request for SDK tests')
|
||||
->label('sdk.description', 'Mock a redirected request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->action(function () {
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/set-cookie')
|
||||
->desc('Mock a cookie request for SDK tests')
|
||||
->desc('Set Cookie')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'setCookie')
|
||||
->label('sdk.description', 'Mock a set cookie request for SDK tests')
|
||||
->label('sdk.description', 'Mock a set cookie request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->inject('response')
|
||||
->action(function ($response) {
|
||||
@@ -247,13 +289,16 @@ App::get('/v1/mock/tests/general/set-cookie')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/get-cookie')
|
||||
->desc('Mock a cookie request for SDK tests')
|
||||
->desc('Get Cookie')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'getCookie')
|
||||
->label('sdk.description', 'Mock a get cookie request for SDK tests')
|
||||
->label('sdk.description', 'Mock a cookie response.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MOCK)
|
||||
->label('sdk.mock', true)
|
||||
->inject('request')
|
||||
->action(function ($request) {
|
||||
@@ -265,13 +310,15 @@ App::get('/v1/mock/tests/general/get-cookie')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/empty')
|
||||
->desc('Mock a post request for SDK tests')
|
||||
->desc('Empty Response')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'empty')
|
||||
->label('sdk.description', 'Mock a redirected request for SDK tests')
|
||||
->label('sdk.description', 'Mock a an empty response.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->label('sdk.mock', true)
|
||||
->inject('response')
|
||||
->action(function ($response) {
|
||||
@@ -280,8 +327,40 @@ App::get('/v1/mock/tests/general/empty')
|
||||
$response->noContent();
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/400-error')
|
||||
->desc('400 Error')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'error400')
|
||||
->label('sdk.description', 'Mock a an 400 failed request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_BAD_REQUEST)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_ERROR)
|
||||
->label('sdk.mock', true)
|
||||
->action(function () {
|
||||
throw new Exception('Mock 400 error', 400);
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/500-error')
|
||||
->desc('500 Error')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'general')
|
||||
->label('sdk.method', 'error500')
|
||||
->label('sdk.description', 'Mock a an 500 failed request.')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_INTERNAL_SERVER_ERROR)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_ERROR)
|
||||
->label('sdk.mock', true)
|
||||
->action(function () {
|
||||
throw new Exception('Mock 500 error', 500);
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/oauth2')
|
||||
->desc('Mock an OAuth2 login route')
|
||||
->desc('OAuth Login')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('docs', false)
|
||||
@@ -298,7 +377,7 @@ App::get('/v1/mock/tests/general/oauth2')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/oauth2/token')
|
||||
->desc('Mock an OAuth2 login route')
|
||||
->desc('OAuth2 Token')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('docs', false)
|
||||
@@ -327,7 +406,7 @@ App::get('/v1/mock/tests/general/oauth2/token')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/oauth2/user')
|
||||
->desc('Mock an OAuth2 user route')
|
||||
->desc('OAuth2 User')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('docs', false)
|
||||
@@ -348,8 +427,9 @@ App::get('/v1/mock/tests/general/oauth2/user')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/oauth2/success')
|
||||
->label('scope', 'public')
|
||||
->desc('OAuth2 Success')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('docs', false)
|
||||
->inject('response')
|
||||
->action(function ($response) {
|
||||
@@ -361,6 +441,7 @@ App::get('/v1/mock/tests/general/oauth2/success')
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/oauth2/failure')
|
||||
->desc('OAuth2 Failure')
|
||||
->groups(['mock'])
|
||||
->label('scope', 'public')
|
||||
->label('docs', false)
|
||||
@@ -397,5 +478,5 @@ App::shutdown(function($utopia, $response, $request) {
|
||||
throw new Exception('Failed to save resutls', 500);
|
||||
}
|
||||
|
||||
$response->json(['result' => $route->getMethod() . ':' . $route->getURL() . ':passed']);
|
||||
$response->dynamic(new Document(['result' => $route->getMethod() . ':' . $route->getURL() . ':passed']), Response::MODEL_MOCK);
|
||||
}, ['utopia', 'response', 'request'], 'mock');
|
||||
@@ -61,12 +61,12 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
|
||||
;
|
||||
}
|
||||
|
||||
$isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles);
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
if (($abuse->check() // Route is rate-limited
|
||||
&& App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') // Abuse is not diabled
|
||||
&& (!$isAppUser && !$isPreviliggedUser)) // User is not an admin or API key
|
||||
&& (!$isAppUser && !$isPrivilegedUser)) // User is not an admin or API key
|
||||
{
|
||||
throw new Exception('Too many requests', 429);
|
||||
}
|
||||
@@ -78,7 +78,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', $route->getLabel('event', ''))
|
||||
->setParam('payload', [])
|
||||
->setParam('eventData', [])
|
||||
->setParam('functionId', null)
|
||||
->setParam('executionId', null)
|
||||
->setParam('trigger', 'event')
|
||||
@@ -110,6 +110,61 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
|
||||
|
||||
}, ['utopia', 'request', 'response', 'project', 'user', 'register', 'events', 'audits', 'usage', 'deletes'], 'api');
|
||||
|
||||
|
||||
App::init(function ($utopia, $request, $response, $project, $user) {
|
||||
/** @var Utopia\App $utopia */
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Utopia\Registry\Registry $register */
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $usage */
|
||||
/** @var Appwrite\Event\Event $deletes */
|
||||
/** @var Appwrite\Event\Event $functions */
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
if($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($route->getLabel('auth.type', '')) {
|
||||
case 'emailPassword':
|
||||
if($project->getAttribute('usersAuthEmailPassword', true) === false) {
|
||||
throw new Exception('Email / Password authentication is disabled for this project', 501);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'anonymous':
|
||||
if($project->getAttribute('usersAuthAnonymous', true) === false) {
|
||||
throw new Exception('Anonymous authentication is disabled for this project', 501);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'invites':
|
||||
if($project->getAttribute('usersAuthInvites', true) === false) {
|
||||
throw new Exception('Invites authentication is disabled for this project', 501);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'jwt':
|
||||
if($project->getAttribute('usersAuthJWT', true) === false) {
|
||||
throw new Exception('JWT authentication is disabled for this project', 501);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Unsupported authentication route');
|
||||
break;
|
||||
}
|
||||
|
||||
}, ['utopia', 'request', 'response', 'project', 'user'], 'auth');
|
||||
|
||||
App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $mode) {
|
||||
/** @var Utopia\App $utopia */
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
@@ -123,8 +178,8 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits
|
||||
/** @var bool $mode */
|
||||
|
||||
if (!empty($events->getParam('event'))) {
|
||||
if(empty($events->getParam('payload'))) {
|
||||
$events->setParam('payload', $response->getPayload());
|
||||
if(empty($events->getParam('eventData'))) {
|
||||
$events->setParam('eventData', $response->getPayload());
|
||||
}
|
||||
|
||||
$webhooks = clone $events;
|
||||
|
||||
@@ -323,7 +323,10 @@ App::get('/console/users')
|
||||
|
||||
$page = new View(__DIR__.'/../../views/console/users/index.phtml');
|
||||
|
||||
$page->setParam('providers', Config::getParam('providers'));
|
||||
$page
|
||||
->setParam('auth', Config::getParam('auth'))
|
||||
->setParam('providers', Config::getParam('providers'))
|
||||
;
|
||||
|
||||
$layout
|
||||
->setParam('title', APP_NAME.' - Users')
|
||||
|
||||
@@ -267,6 +267,12 @@ App::get('/specs/:format')
|
||||
'description' => 'Your project ID',
|
||||
'in' => 'header',
|
||||
],
|
||||
'JWT' => [
|
||||
'type' => 'apiKey',
|
||||
'name' => 'X-Appwrite-JWT',
|
||||
'description' => 'Your secret JSON Web Token',
|
||||
'in' => 'header',
|
||||
],
|
||||
'Locale' => [
|
||||
'type' => 'apiKey',
|
||||
'name' => 'X-Appwrite-Locale',
|
||||
@@ -287,6 +293,12 @@ App::get('/specs/:format')
|
||||
'description' => 'Your secret API key',
|
||||
'in' => 'header',
|
||||
],
|
||||
'JWT' => [
|
||||
'type' => 'apiKey',
|
||||
'name' => 'X-Appwrite-JWT',
|
||||
'description' => 'Your secret JSON Web Token',
|
||||
'in' => 'header',
|
||||
],
|
||||
'Locale' => [
|
||||
'type' => 'apiKey',
|
||||
'name' => 'X-Appwrite-Locale',
|
||||
@@ -307,6 +319,12 @@ App::get('/specs/:format')
|
||||
'description' => 'Your secret API key',
|
||||
'in' => 'header',
|
||||
],
|
||||
'JWT' => [
|
||||
'type' => 'apiKey',
|
||||
'name' => 'X-Appwrite-JWT',
|
||||
'description' => 'Your secret JSON Web Token',
|
||||
'in' => 'header',
|
||||
],
|
||||
'Locale' => [
|
||||
'type' => 'apiKey',
|
||||
'name' => 'X-Appwrite-Locale',
|
||||
@@ -322,14 +340,32 @@ App::get('/specs/:format')
|
||||
],
|
||||
];
|
||||
|
||||
$security = [
|
||||
APP_PLATFORM_CLIENT => ['Project' => []],
|
||||
APP_PLATFORM_SERVER => ['Project' => [], 'Key' => []],
|
||||
APP_PLATFORM_CONSOLE => ['Project' => [], 'Key' => []],
|
||||
];
|
||||
|
||||
foreach ($utopia->getRoutes() as $key => $method) {
|
||||
foreach ($method as $route) { /** @var \Utopia\Route $route */
|
||||
$routeSecurity = $route->getLabel('sdk.auth', []);
|
||||
$sdkPlatofrms = [];
|
||||
|
||||
foreach ($routeSecurity as $value) {
|
||||
switch ($value) {
|
||||
case APP_AUTH_TYPE_SESSION:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
||||
break;
|
||||
case APP_AUTH_TYPE_KEY:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
||||
break;
|
||||
case APP_AUTH_TYPE_JWT:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
||||
break;
|
||||
case APP_AUTH_TYPE_ADMIN:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_CONSOLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($routeSecurity)) {
|
||||
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
||||
}
|
||||
|
||||
if (!$route->getLabel('docs', true)) {
|
||||
continue;
|
||||
}
|
||||
@@ -346,7 +382,7 @@ App::get('/specs/:format')
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $route->getLabel('sdk.platform', []))) {
|
||||
if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatofrms)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -383,11 +419,11 @@ App::get('/specs/:format')
|
||||
|
||||
switch ($format) {
|
||||
case 'swagger2':
|
||||
$format = new Swagger2($utopia, $services, $routes, $models, $keys[$platform], $security[$platform]);
|
||||
$format = new Swagger2($utopia, $services, $routes, $models, $keys[$platform]);
|
||||
break;
|
||||
|
||||
case 'open-api3':
|
||||
$format = new OpenAPI3($utopia, $services, $routes, $models, $keys[$platform], $security[$platform]);
|
||||
$format = new OpenAPI3($utopia, $services, $routes, $models, $keys[$platform]);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -416,4 +452,40 @@ App::get('/specs/:format')
|
||||
|
||||
$response
|
||||
->json($specs->parse());
|
||||
});
|
||||
|
||||
App::get('/versions')
|
||||
->desc('Get Version')
|
||||
->groups(['web', 'home'])
|
||||
->label('scope', 'public')
|
||||
->inject('response')
|
||||
->action(function ($response) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
|
||||
$platforms = Config::getParam('platforms');
|
||||
|
||||
$versions = [
|
||||
'server' => APP_VERSION_STABLE,
|
||||
];
|
||||
|
||||
foreach($platforms as $platform) {
|
||||
$languages = $platform['languages'] ?? [];
|
||||
|
||||
foreach ($languages as $key => $language) {
|
||||
if(isset($language['dev']) && $language['dev']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isset($language['enabled']) && !$language['enabled']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$platformKey = $platform['key'] ?? '';
|
||||
$languageKey = $language['key'] ?? '';
|
||||
$version = $language['version'] ?? '';
|
||||
$versions[$platformKey . '-' . $languageKey] = $version;
|
||||
}
|
||||
}
|
||||
|
||||
$response->json($versions);
|
||||
});
|
||||
+1
-1
@@ -94,7 +94,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo
|
||||
return;
|
||||
}
|
||||
|
||||
$app = new App('America/New_York');
|
||||
$app = new App('UTC');
|
||||
|
||||
try {
|
||||
Authorization::cleanRoles();
|
||||
|
||||
+10
-4
@@ -39,8 +39,8 @@ const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s';
|
||||
const APP_MODE_DEFAULT = 'default';
|
||||
const APP_MODE_ADMIN = 'admin';
|
||||
const APP_PAGING_LIMIT = 12;
|
||||
const APP_CACHE_BUSTER = 144;
|
||||
const APP_VERSION_STABLE = '0.7.0';
|
||||
const APP_CACHE_BUSTER = 145;
|
||||
const APP_VERSION_STABLE = '0.8.0';
|
||||
const APP_STORAGE_UPLOADS = '/storage/uploads';
|
||||
const APP_STORAGE_FUNCTIONS = '/storage/functions';
|
||||
const APP_STORAGE_CACHE = '/storage/cache';
|
||||
@@ -61,6 +61,11 @@ const DELETE_TYPE_EXECUTIONS = 'executions';
|
||||
const DELETE_TYPE_AUDIT = 'audit';
|
||||
const DELETE_TYPE_ABUSE = 'abuse';
|
||||
const DELETE_TYPE_CERTIFICATES = 'certificates';
|
||||
// Auth Types
|
||||
const APP_AUTH_TYPE_SESSION = 'Session';
|
||||
const APP_AUTH_TYPE_JWT = 'JWT';
|
||||
const APP_AUTH_TYPE_KEY = 'Key';
|
||||
const APP_AUTH_TYPE_ADMIN = 'Admin';
|
||||
|
||||
$register = new Registry();
|
||||
|
||||
@@ -70,6 +75,7 @@ App::setMode(App::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION));
|
||||
* ENV vars
|
||||
*/
|
||||
Config::load('events', __DIR__.'/config/events.php');
|
||||
Config::load('auth', __DIR__.'/config/auth.php');
|
||||
Config::load('providers', __DIR__.'/config/providers.php');
|
||||
Config::load('platforms', __DIR__.'/config/platforms.php');
|
||||
Config::load('collections', __DIR__.'/config/collections.php');
|
||||
@@ -313,7 +319,7 @@ App::setResource('layout', function($locale) {
|
||||
}, ['locale']);
|
||||
|
||||
App::setResource('locale', function() {
|
||||
return new Locale('en');
|
||||
return new Locale(App::getEnv('_APP_LOCALE', 'en'));
|
||||
});
|
||||
|
||||
// Queues
|
||||
@@ -419,7 +425,7 @@ App::setResource('user', function($mode, $project, $console, $request, $response
|
||||
|
||||
if (empty($user->getId()) // Check a document has been found in the DB
|
||||
|| Database::SYSTEM_COLLECTION_USERS !== $user->getCollection() // Validate returned document is really a user document
|
||||
|| !Auth::tokenVerify($user->getAttribute('tokens', []), Auth::TOKEN_TYPE_LOGIN, Auth::$secret)) { // Validate user has valid login token
|
||||
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret)) { // Validate user has valid login token
|
||||
$user = new Document(['$id' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -28,10 +28,9 @@ foreach ([
|
||||
realpath(__DIR__ . '/../vendor/felixfbecker'),
|
||||
realpath(__DIR__ . '/../vendor/twig/twig'),
|
||||
realpath(__DIR__ . '/../vendor/guzzlehttp/guzzle'),
|
||||
realpath(__DIR__ . '/../vendor/domnikl'),
|
||||
realpath(__DIR__ . '/../vendor/domnikl'),
|
||||
realpath(__DIR__ . '/../vendor/slickdeals'),
|
||||
realpath(__DIR__ . '/../vendor/psr/log'),
|
||||
realpath(__DIR__ . '/../vendor/piwik'),
|
||||
realpath(__DIR__ . '/../vendor/matomo'),
|
||||
realpath(__DIR__ . '/../vendor/symfony'),
|
||||
] as $key => $value) {
|
||||
if($value !== false) {
|
||||
|
||||
@@ -141,7 +141,6 @@ $cli
|
||||
Console::success('SMTP................connected 👍');
|
||||
} catch (\Throwable $th) {
|
||||
Console::error('SMTP.............disconnected 👎');
|
||||
var_dump($th);
|
||||
}
|
||||
|
||||
$host = App::getEnv('_APP_STATSD_HOST', 'telegraf');
|
||||
|
||||
@@ -124,7 +124,7 @@ $cli
|
||||
|
||||
$input[$var['name']] = Console::confirm($var['question'].' (default: \''.$var['default'].'\')');
|
||||
|
||||
if(empty($input[$key])) {
|
||||
if(empty($input[$var['name']])) {
|
||||
$input[$var['name']] = $var['default'];
|
||||
}
|
||||
}
|
||||
@@ -181,4 +181,4 @@ $cli
|
||||
$analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message);
|
||||
Console::success($message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ $cli
|
||||
$projects = [$console];
|
||||
$count = 0;
|
||||
|
||||
$migration = new Version\V06($register->get('db')); //TODO: remove hardcoded version and move to dynamic migration
|
||||
$migration = new Version\V07($register->get('db')); //TODO: remove hardcoded version and move to dynamic migration
|
||||
|
||||
while ($sum > 0) {
|
||||
foreach ($projects as $project) {
|
||||
|
||||
+13
-1
@@ -42,7 +42,7 @@ $cli
|
||||
$production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false;
|
||||
$message = ($git) ? Console::confirm('Please enter your commit message:') : '';
|
||||
|
||||
if(!in_array($version, ['0.6.2', '0.7.0'])) {
|
||||
if(!in_array($version, ['0.6.x', '0.7.x', '0.8.x'])) {
|
||||
throw new Exception('Unknown version given');
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ $cli
|
||||
$target = \realpath(__DIR__.'/..').'/sdks/git/'.$language['key'].'/';
|
||||
$readme = \realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/README.md');
|
||||
$readme = ($readme) ? \file_get_contents($readme) : '';
|
||||
$gettingStarted = \realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/GETTING_STARTED.md');
|
||||
$gettingStarted = ($gettingStarted) ? \file_get_contents($gettingStarted) : '';
|
||||
$examples = \realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/EXAMPLES.md');
|
||||
$examples = ($examples) ? \file_get_contents($examples) : '';
|
||||
$changelog = \realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/CHANGELOG.md');
|
||||
@@ -96,6 +98,15 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
$config = new CLI();
|
||||
$config->setComposerVendor('appwrite');
|
||||
$config->setComposerPackage('cli');
|
||||
$config->setExecutableName('appwrite');
|
||||
$config->setLogo("
|
||||
_ _ _ ___ __ _____
|
||||
/_\ _ __ _ ____ ___ __(_) |_ ___ / __\ / / \_ \
|
||||
//_\\| '_ \| '_ \ \ /\ / / '__| | __/ _ \ / / / / / /\/
|
||||
/ _ \ |_) | |_) \ V V /| | | | || __/ / /___/ /___/\/ /_
|
||||
\_/ \_/ .__/| .__/ \_/\_/ |_| |_|\__\___| \____/\____/\____/
|
||||
|_| |_|
|
||||
");
|
||||
break;
|
||||
case 'php':
|
||||
$config = new PHP();
|
||||
@@ -178,6 +189,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
->setShareVia('appwrite_io')
|
||||
->setWarning($warning)
|
||||
->setReadme($readme)
|
||||
->setGettingStarted($gettingStarted)
|
||||
->setChangelog($changelog)
|
||||
->setExamples($examples)
|
||||
;
|
||||
|
||||
@@ -36,9 +36,6 @@ $maxCells = 10;
|
||||
<div class="zone xl">
|
||||
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
|
||||
<li data-state="/console/database/collection?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<a data-ls-if="{{project-collection.rules.length}} > 0" data-ls-attrs="href=/console/database/document?collection={{router.params.id}}&project={{router.params.project}}&buster={{project-collection.dateUpdated}}" class="button fly round text-align-center">
|
||||
<i class="icon-plus"></i>
|
||||
</a>
|
||||
|
||||
<h2>Documents</h2>
|
||||
|
||||
@@ -135,7 +132,7 @@ $maxCells = 10;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clear text-align-center paging">
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="database.listDocuments"
|
||||
data-event="submit"
|
||||
@@ -166,6 +163,10 @@ $maxCells = 10;
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-documents.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<a data-ls-if="{{project-collection.rules.length}} > 0" data-ls-attrs="href=/console/database/document?collection={{router.params.id}}&project={{router.params.project}}&buster={{project-collection.dateUpdated}}" class="button">
|
||||
Add Document
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li data-state="/console/database/collection/settings?id={{router.params.id}}&project={{router.params.project}}">
|
||||
@@ -520,7 +521,7 @@ $maxCells = 10;
|
||||
|
||||
<div data-ls-loop="project-collections.collections" data-ls-as="project" data-ls-key="$index2" class="tiles cell-3 margin-bottom-negative">
|
||||
<div class="margin-bottom" data-ls-if="{{project.$id}} != {{router.params.id}}">
|
||||
<input type="radio" name="list" data-ls-attrs="value={{project.$id}},id={{project.$id}}" data-ls-bind="{{rule.list|firstElement}}" data-cast-to="array" required />
|
||||
<input type="radio" data-ls-attrs="value={{project.$id}},id=[{{rule.$id}}].{{project.$id}},name=[{{rule.$id}}].list" data-ls-bind="{{rule.list|firstElement}}" data-cast-to="array" required />
|
||||
<label data-ls-attrs="for={{project.$id}}"data-ls-bind="{{project.name}}"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,40 +12,6 @@
|
||||
<li data-state="/console/database?project={{router.params.project}}">
|
||||
<h2>Collections</h2>
|
||||
|
||||
<div data-ui-modal class="box modal close" data-button-text="" data-button-class="fly round" data-button-icon="icon-plus">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>New Collection</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Database Collection"
|
||||
data-service="database.createCollection"
|
||||
data-event="submit"
|
||||
data-scope="sdk"
|
||||
data-success="alert,reset,redirect,trigger"
|
||||
data-success-param-alert-text="Collection created successfully"
|
||||
data-success-param-redirect-url="/console/database/collection/settings?id={{serviceData.$id}}&project={{router.params.project}}"
|
||||
data-success-param-trigger-events="database.createCollection"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create collection"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="user-name">Name</label>
|
||||
<input type="text" class="full-width" id="collection-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<input type="hidden" id="collection-read" name="read" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
<input type="hidden" id="collection-write" name="write" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="margin-top"
|
||||
data-service="database.listCollections"
|
||||
data-event="load,database.createCollection,database.updateCollection,database.deleteCollection"
|
||||
@@ -76,7 +42,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="clear text-align-center paging">
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="database.listCollections"
|
||||
data-event="submit"
|
||||
@@ -105,6 +71,41 @@
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-collections.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="modal close box sticky-footer" data-button-text="Add Collection">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>New Collection</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Database Collection"
|
||||
data-service="database.createCollection"
|
||||
data-event="submit"
|
||||
data-scope="sdk"
|
||||
data-success="alert,reset,redirect,trigger"
|
||||
data-success-param-alert-text="Collection created successfully"
|
||||
data-success-param-redirect-url="/console/database/collection/settings?id={{serviceData.$id}}&project={{router.params.project}}"
|
||||
data-success-param-trigger-events="database.createCollection"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create collection"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="user-name">Name</label>
|
||||
<input type="text" class="full-width" id="collection-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<input type="hidden" id="collection-read" name="read" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
<input type="hidden" id="collection-write" name="write" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
<!-- <li data-state="/console/database/usage?project={{router.params.project}}">
|
||||
<h2>Usage</h2>
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
</td>
|
||||
<td data-title="Size: ">
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
|
||||
</td>
|
||||
<td data-title="Created: ">
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.dateCreated|dateText}}"></span>
|
||||
|
||||
@@ -50,24 +50,9 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||
|
||||
<p class="text-fade margin-bottom-small" data-ls-bind="{{project-function.env|envName}} {{project-function.env|envVersion}}">
|
||||
</p>
|
||||
|
||||
<form data-ls-if="{{project-function.tag}} !== ''" name="functions.createExecution" class="margin-top"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Function Execution"
|
||||
data-service="functions.createExecution"
|
||||
data-event="submit"
|
||||
data-param-function-id="{{router.params.id}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Function executed successfully"
|
||||
data-success-param-trigger-events="functions.createExecution"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to execute function"
|
||||
data-failure-param-alert-classname="error">
|
||||
<button style="vertical-align: top;">Execute Now</button> <a data-ls-attrs="href=/console/functions/function/logs?id={{router.params.id}}&project={{router.params.project}}" class="button reverse" style="vertical-align: top;">View Logs</a>
|
||||
</form>
|
||||
<div data-ls-if="{{project-function.tag}} !== ''" class="margin-top">
|
||||
<button data-ls-ui-trigger="execute-now">Execute Now</button> <a data-ls-attrs="href=/console/functions/function/logs?id={{router.params.id}}&project={{router.params.project}}" class="button reverse" style="vertical-align: top;">View Logs</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -117,7 +102,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||
<b data-ls-bind="{{tag.$id}}"></b>
|
||||
<span class="text-fade" data-ls-bind="{{tag.command}}"></span>
|
||||
<div class="text-size-small margin-top-small clear">
|
||||
<span class="pull-start" data-ls-bind="Created {{tag.dateCreated|timeSince}} | {{tag.size|humanFileSize}}"></span>
|
||||
<span class="pull-start" data-ls-bind="Created {{tag.dateCreated|timeSince}} | {{tag.size|humanFileSize}}{{tag.size|humanFileUnit}}"></span>
|
||||
|
||||
<form data-ls-if="{{tag.$id}} !== {{project-function.tag}}" name="functions.deleteTag" class="pull-start"
|
||||
data-analytics
|
||||
@@ -575,6 +560,31 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="modal close box sticky-footer" data-button-hide="on" data-open-event="execute-now">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
<h1 class="margin-bottom">Execute Function</h1>
|
||||
<form data-ls-if="{{project-function.tag}} !== ''" name="functions.createExecution" class="margin-top"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Function Execution"
|
||||
data-service="functions.createExecution"
|
||||
data-event="submit"
|
||||
data-param-function-id="{{router.params.id}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Function executed successfully"
|
||||
data-success-param-trigger-events="functions.createExecution"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to execute function"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="execution-data">Custom Data</label>
|
||||
<textarea id="execution-data" name="data" autocomplete="off" class="margin-bottom" placeholder="Data string (optional)"></textarea>
|
||||
|
||||
<button type="submit" style="vertical-align: top;">Execute Now</button>
|
||||
</form>
|
||||
</div>
|
||||
<div data-ui-modal class="modal close box sticky-footer" data-button-hide="on" data-open-event="deploy-tag">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
|
||||
@@ -97,7 +97,10 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||
</div>
|
||||
</div>
|
||||
<div class="col span-3">
|
||||
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.network.total|humanFileSize}}" data-default="0">0</span></div>
|
||||
<div class="value margin-bottom-small">
|
||||
<span class="sum" data-ls-bind="{{usage.network.total|humanFileSize}}" data-default="0">0</span>
|
||||
<span data-ls-bind="{{usage.network.total|humanFileUnit}}" class="text-size-small unit"></span>
|
||||
</div>
|
||||
<div class="metric margin-bottom-small">Bandwidth</div>
|
||||
|
||||
<div class="margin-top-large value small">
|
||||
@@ -117,7 +120,10 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||
<div class="margin-top-small"><b class="text-size-small unit">Documents</b></div>
|
||||
</div>
|
||||
<div class="col span-3">
|
||||
<div class="value"><span class="sum" data-ls-bind="{{usage.storage.total|humanFileSize}}" data-default="0">0</span></div>
|
||||
<div class="value">
|
||||
<span class="sum" data-ls-bind="{{usage.storage.total|humanFileSize}}" data-default="0">0</span>
|
||||
<span data-ls-bind="{{usage.storage.total|humanFileUnit}}" class="text-size-small unit"></span>
|
||||
</div>
|
||||
<div class="margin-top-small"><b class="text-size-small unit">Storage</b></div>
|
||||
</div>
|
||||
<div class="col span-3">
|
||||
|
||||
@@ -17,48 +17,6 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||
<li data-state="/console/database?project={{router.params.project}}">
|
||||
<h2 class="margin-bottom">Files</h2>
|
||||
|
||||
<div data-ui-modal class="box modal sticky-footer close" data-button-text="" data-button-class="fly round" data-button-icon="icon-plus">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>Upload File</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Storage File"
|
||||
data-service="storage.createFile"
|
||||
data-event="submit"
|
||||
data-scope="sdk"
|
||||
data-loading="Uploading File..."
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="File uploaded successfully"
|
||||
data-success-param-trigger-events="storage.createFile"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to upload file"
|
||||
data-failure-param-alert-classname="error">
|
||||
<input type="hidden" name="folderId" id="files-folderId" data-cast-to="integer" value="1">
|
||||
|
||||
<label for="file-read">File</label>
|
||||
<input type="file" name="file" id="file-file" size="1" required>
|
||||
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
|
||||
|
||||
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="file-read" name="read" data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['*'])); ?>" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="file-write" name="write" data-forms-tags data-cast-to="json" value="" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<footer>
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form class="box padding-small margin-bottom search"
|
||||
data-service="storage.listFiles"
|
||||
data-event="submit"
|
||||
@@ -204,6 +162,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||
</td>
|
||||
<td data-title="Size: ">
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
|
||||
</td>
|
||||
<td data-title="Created: ">
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.dateCreated|dateText}}"></span>
|
||||
@@ -214,7 +173,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clear text-align-center paging">
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="storage.listFiles"
|
||||
data-event="submit"
|
||||
@@ -243,6 +202,48 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-files.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="box modal sticky-footer close" data-button-text="Add File">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>Upload File</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Storage File"
|
||||
data-service="storage.createFile"
|
||||
data-event="submit"
|
||||
data-scope="sdk"
|
||||
data-loading="Uploading File..."
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="File uploaded successfully"
|
||||
data-success-param-trigger-events="storage.createFile"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to upload file"
|
||||
data-failure-param-alert-classname="error">
|
||||
<input type="hidden" name="folderId" id="files-folderId" data-cast-to="integer" value="1">
|
||||
|
||||
<label for="file-read">File</label>
|
||||
<input type="file" name="file" id="file-file" size="1" required>
|
||||
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
|
||||
|
||||
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="file-read" name="read" data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['*'])); ?>" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="file-write" name="write" data-forms-tags data-cast-to="json" value="" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<footer>
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
$providers = $this->getParam('providers', []);
|
||||
$auth = $this->getParam('auth', []);
|
||||
?>
|
||||
|
||||
<div class="cover">
|
||||
@@ -17,41 +18,6 @@ $providers = $this->getParam('providers', []);
|
||||
|
||||
<h2>Users</h2>
|
||||
|
||||
<div data-ui-modal class="box modal close" data-button-text="" data-button-class="fly round" data-button-icon="icon-plus">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>Create User</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create User"
|
||||
data-service="users.create"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created user successfully"
|
||||
data-success-param-trigger-events="users.create"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create user"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="user-name">Name</label>
|
||||
<input type="text" class="full-width" id="user-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<label for="user-email">Email</label>
|
||||
<input type="email" class="full-width" id="user-email" name="email" required autocomplete="off" />
|
||||
|
||||
<label for="user-password">Password</label>
|
||||
<input type="password" class="full-width" id="user-password" name="password" required pattern=".{6,}" title="Six or more characters" autocomplete="off" />
|
||||
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form class="box padding-small margin-bottom search"
|
||||
data-service="users.list"
|
||||
data-event="submit"
|
||||
@@ -137,7 +103,7 @@ $providers = $this->getParam('providers', []);
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clear text-align-center paging">
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="users.list"
|
||||
data-event="submit"
|
||||
@@ -166,41 +132,47 @@ $providers = $this->getParam('providers', []);
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-users.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="box modal close" data-button-text="Add User">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>Create User</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create User"
|
||||
data-service="users.create"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created user successfully"
|
||||
data-success-param-trigger-events="users.create"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create user"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="user-name">Name</label>
|
||||
<input type="text" class="full-width" id="user-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<label for="user-email">Email</label>
|
||||
<input type="email" class="full-width" id="user-email" name="email" required autocomplete="off" />
|
||||
|
||||
<label for="user-password">Password</label>
|
||||
<input type="password" class="full-width" id="user-password" name="password" required pattern=".{6,}" title="Six or more characters" autocomplete="off" />
|
||||
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li data-state="/console/users/teams?project={{router.params.project}}">
|
||||
<h2>Teams</h2>
|
||||
|
||||
<div data-ui-modal class="box modal close" data-button-text="" data-button-class="fly round" data-button-icon="icon-plus">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>Create Team</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Team"
|
||||
data-service="teams.create"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created team successfully"
|
||||
data-success-param-trigger-events="filter-teams-changed,teams.create"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create team"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="team-name">Name</label>
|
||||
<input type="text" class="full-width" id="team-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form class="box padding-small margin-bottom search"
|
||||
data-service="teams.list"
|
||||
data-event="submit"
|
||||
@@ -239,7 +211,7 @@ $providers = $this->getParam('providers', []);
|
||||
</div>
|
||||
|
||||
<div data-ls-if="0 != {{project-teams.sum}}">
|
||||
<div class="margin-bottom-small margin-end-small text-align-end text-size-small"><span data-ls-bind="{{project-teams.sum}}"></span> results found</div>
|
||||
<div class="margin-bottom-small margin-end-small text-align-end text-size-small"><span data-ls-bind="{{project-teams.sum}}"></span> results found</div>
|
||||
|
||||
<div class="box margin-bottom">
|
||||
<table class="vertical">
|
||||
@@ -267,7 +239,7 @@ $providers = $this->getParam('providers', []);
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clear text-align-center paging">
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="teams.list"
|
||||
data-event="submit"
|
||||
@@ -296,13 +268,131 @@ $providers = $this->getParam('providers', []);
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-teams.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="box modal close" data-button-text="Add Team">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>Create Team</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Team"
|
||||
data-service="teams.create"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created team successfully"
|
||||
data-success-param-trigger-events="filter-teams-changed,teams.create"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create team"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="team-name">Name</label>
|
||||
<input type="text" class="full-width" id="team-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li data-state="/console/users/providers?project={{router.params.project}}">
|
||||
<h2>OAuth2 Providers</h2>
|
||||
<p data-ls-if="{{console-project.usersAuthLimit}} == 0" class="text-fade text-size-small margin-bottom pull-end">Unlimited Users <span class="link" data-ls-ui-trigger="project-update-auth-users-limit">Set Limit</a></p>
|
||||
<p data-ls-if="{{console-project.usersAuthLimit}} != 0" class="text-fade text-size-small margin-bottom pull-end"><span data-ls-bind="{{console-project.usersAuthLimit|statsTotal}}"></span> Users allowed <span class="link" data-ls-ui-trigger="project-update-auth-users-limit">Change Limit</a></p>
|
||||
|
||||
<h2>Settings</h2>
|
||||
|
||||
<div class="margin-bottom margin-top-large"
|
||||
<div data-ui-modal class="modal close" data-button-alias="none" data-open-event="project-update-auth-users-limit">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>Max Allowed Users</h1>
|
||||
|
||||
<form data-debug="1"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Update Project Users Limit"
|
||||
data-service="projects.updateAuthLimit"
|
||||
data-scope="console"
|
||||
data-event="submit"
|
||||
data-param-project-id="{{router.params.project}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Updated project users limit successfully"
|
||||
data-success-param-trigger-events="projects.update"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to update project users limit"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input name="limit" id="users-limit" type="number" data-ls-bind="{{console-project.usersAuthLimit}}" data-cast-to="numeric" min="0" />
|
||||
|
||||
<div class="info row thin margin-bottom margin-top">
|
||||
<div class="col span-1">
|
||||
<i class="icon-info-circled text-sign"></i>
|
||||
</div>
|
||||
<div class="col span-11">This limit will prevent new users from signing up for your project, no matter what auth method has been used. You will still be able to create users and team memberships from your Appwrite console. For an unlimited amount of users, set the limit to 0.</div>
|
||||
</div>
|
||||
|
||||
<button>Update</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p class="text-fade margin-bottom">Choose auth methods you wish to use.</p>
|
||||
|
||||
<ul class="tiles cell-3 margin-bottom-small">
|
||||
<?php foreach($auth as $index => $method):
|
||||
$key = $method['key'] ?? '';
|
||||
$name = $method['name'] ?? '';
|
||||
$icon = $method['icon'] ?? '';
|
||||
$docs = $method['docs'] ?? '';
|
||||
$enabled = $method['enabled'] ?? false;
|
||||
?>
|
||||
<li class="">
|
||||
<div class="box padding-small margin-bottom clear">
|
||||
<?php if($enabled): ?>
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Update Project Auth Status (<?php echo $this->escape($name); ?>)"
|
||||
data-service="projects.updateAuthStatus"
|
||||
data-scope="console"
|
||||
data-event="change"
|
||||
data-param-project-id="{{router.params.project}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Updated project auth status successfully"
|
||||
data-success-param-trigger-events="projects.update"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to update project auth status settings"
|
||||
data-failure-param-alert-classname="error">
|
||||
<input name="method" id="<?php echo $this->escape($key); ?>" type="hidden" autocomplete="off" value="<?php echo $this->escape($index); ?>">
|
||||
|
||||
<input name="status" type="hidden" data-forms-switch data-ls-bind="{{console-project.<?php echo $this->escape($key); ?>}}" data-cast-to="boolean" class="pull-end" />
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<img src="<?php echo $this->escape($icon); ?>?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="Email/Password Logo" class="pull-start provider margin-end" />
|
||||
|
||||
<span class="text-size-small"><?php echo $this->escape($name); ?><?php if(!$enabled): ?> <spann class="text-fade text-size-xs">soon</span><?php endif; ?></span>
|
||||
|
||||
<?php if($docs): ?>
|
||||
<p class="margin-bottom-no text-one-liner text-size-small">
|
||||
<a href="<?php echo $this->escape($docs); ?>" target="_blank" rel="noopener">Docs<i class="icon-link-ext"></i></a>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<h3>OAuth2 Providers</h3>
|
||||
|
||||
<div class="margin-bottom margin-top"
|
||||
data-service="projects.get"
|
||||
data-event="load,projects.create,projects.update,projects.deleteProject"
|
||||
data-name="console-project"
|
||||
@@ -312,6 +402,7 @@ $providers = $this->getParam('providers', []);
|
||||
<?php foreach ($providers as $provider => $data):
|
||||
if (isset($data['enabled']) && !$data['enabled']) { continue; }
|
||||
if (isset($data['mock']) && $data['mock']) { continue; }
|
||||
$sandbox = $data['sandbox'] ?? false;
|
||||
$form = $data['form'] ?? false;
|
||||
$name = $data['name'] ?? 'Unknown';
|
||||
$beta = $data['beta'] ?? false;
|
||||
@@ -320,7 +411,7 @@ $providers = $this->getParam('providers', []);
|
||||
<div data-ui-modal class="modal close" data-button-alias="none" data-open-event="provider-update-<?php echo $provider; ?>">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1><?php echo $this->escape($name); ?> OAuth2 Settings</h1>
|
||||
<h1><?php echo $this->escape($name); ?> <?php if($sandbox): ?>Sandbox<?php endif; ?> OAuth2 Settings</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
@@ -383,10 +474,10 @@ $providers = $this->getParam('providers', []);
|
||||
<button class="switch pull-end" data-ls-ui-trigger="provider-update-<?php echo $this->escape($provider); ?>"></button>
|
||||
</span>
|
||||
|
||||
<img src="/images/oauth2/<?php echo $this->escape(strtolower($provider)); ?>.png?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="<?php echo $this->escape(ucfirst($provider)); ?> Logo" class="pull-start provider margin-end" />
|
||||
<img src="/images/users/oauth2/<?php echo $this->escape(strtolower($provider)); ?>.png?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="<?php echo $this->escape(ucfirst($provider)); ?> Logo" class="pull-start provider margin-end" />
|
||||
|
||||
<span class="text-size-small">
|
||||
<?php echo $this->escape($name); ?> <?php if($beta): ?>(beta)<?php endif; ?>
|
||||
<?php echo $this->escape($name); ?> <?php if($sandbox): ?><span class="text-size-xs text-fade">sandbox</span><?php endif; ?> <?php if($beta): ?><span class="text-size-xs text-fade">beta</span><?php endif; ?>
|
||||
</span>
|
||||
|
||||
<p class="margin-bottom-no text-one-liner text-size-small">
|
||||
|
||||
@@ -52,10 +52,11 @@ services:
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
- clamav
|
||||
# - clamav
|
||||
- influxdb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_LOCALE
|
||||
- _APP_CONSOLE_WHITELIST_GOD
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||
- _APP_CONSOLE_WHITELIST_IPS
|
||||
@@ -352,14 +353,14 @@ services:
|
||||
volumes:
|
||||
- appwrite-redis:/data:rw
|
||||
|
||||
clamav:
|
||||
image: appwrite/clamav:1.2.0
|
||||
container_name: appwrite-clamav
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads
|
||||
# clamav:
|
||||
# image: appwrite/clamav:1.2.0
|
||||
# container_name: appwrite-clamav
|
||||
# restart: unless-stopped
|
||||
# networks:
|
||||
# - appwrite
|
||||
# volumes:
|
||||
# - appwrite-uploads:/storage/uploads
|
||||
|
||||
influxdb:
|
||||
image: influxdb:1.8-alpine
|
||||
|
||||
@@ -124,7 +124,7 @@ class CertificatesV1
|
||||
." -w ".APP_STORAGE_CERTIFICATES
|
||||
." -d {$domain->get()}", '', $stdout, $stderr);
|
||||
|
||||
if($stderr || $exit !== 0) {
|
||||
if($exit !== 0) {
|
||||
throw new Exception('Failed to issue a certificate with message: '.$stderr);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,13 +112,21 @@ class DeletesV1
|
||||
protected function deleteUser(Document $document, $projectId)
|
||||
{
|
||||
$tokens = $document->getAttribute('tokens', []);
|
||||
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
if (!$this->getProjectDB($projectId)->deleteDocument($token->getId())) {
|
||||
throw new Exception('Failed to remove token from DB');
|
||||
}
|
||||
}
|
||||
|
||||
$sessions = $document->getAttribute('sessions', []);
|
||||
|
||||
foreach ($sessions as $session) {
|
||||
if (!$this->getProjectDB($projectId)->deleteDocument($session->getId())) {
|
||||
throw new Exception('Failed to remove session from DB');
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Memberships
|
||||
$this->deleteByGroup([
|
||||
'$collection='.Database::SYSTEM_COLLECTION_MEMBERSHIPS,
|
||||
|
||||
@@ -147,7 +147,10 @@ class FunctionsV1
|
||||
$trigger = $this->args['trigger'] ?? '';
|
||||
$event = $this->args['event'] ?? '';
|
||||
$scheduleOriginal = $this->args['scheduleOriginal'] ?? '';
|
||||
$payload = (!empty($this->args['payload'])) ? json_encode($this->args['payload']) : '';
|
||||
$eventData = (!empty($this->args['eventData'])) ? json_encode($this->args['eventData']) : '';
|
||||
$data = $this->args['data'] ?? '';
|
||||
$userId = $this->args['userId'] ?? '';
|
||||
$jwt = $this->args['jwt'] ?? '';
|
||||
|
||||
$database = new Database();
|
||||
$database->setAdapter(new RedisAdapter(new MySQLAdapter($register), $register));
|
||||
@@ -195,7 +198,7 @@ class FunctionsV1
|
||||
|
||||
Console::success('Triggered function: '.$event);
|
||||
|
||||
$this->execute('event', $projectId, '', $database, $function, $event, $payload);
|
||||
$this->execute('event', $projectId, '', $database, $function, $event, $eventData, $data, $userId, $jwt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -251,8 +254,7 @@ class FunctionsV1
|
||||
'scheduleOriginal' => $function->getAttribute('schedule', ''),
|
||||
]); // Async task rescheduale
|
||||
|
||||
$this->execute($trigger, $projectId, $executionId, $database, $function);
|
||||
|
||||
$this->execute($trigger, $projectId, $executionId, $database, $function, /*$event*/'', /*$eventData*/'', $data, $userId, $jwt);
|
||||
break;
|
||||
|
||||
case 'http':
|
||||
@@ -264,7 +266,7 @@ class FunctionsV1
|
||||
throw new Exception('Function not found ('.$functionId.')');
|
||||
}
|
||||
|
||||
$this->execute($trigger, $projectId, $executionId, $database, $function);
|
||||
$this->execute($trigger, $projectId, $executionId, $database, $function, /*$event*/'', /*$eventData*/'', $data, $userId, $jwt);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -282,11 +284,12 @@ class FunctionsV1
|
||||
* @param Database $database
|
||||
* @param Database $function
|
||||
* @param string $event
|
||||
* @param string $payload
|
||||
* @param string $eventData
|
||||
* @param string $data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute(string $trigger, string $projectId, string $executionId, Database $database, Document $function, string $event = '', string $payload = ''): void
|
||||
public function execute(string $trigger, string $projectId, string $executionId, Database $database, Document $function, string $event = '', string $eventData = '', string $data = '', string $userId = '', string $jwt = ''): void
|
||||
{
|
||||
global $list;
|
||||
|
||||
@@ -340,7 +343,11 @@ class FunctionsV1
|
||||
'APPWRITE_FUNCTION_ENV_NAME' => $environment['name'],
|
||||
'APPWRITE_FUNCTION_ENV_VERSION' => $environment['version'],
|
||||
'APPWRITE_FUNCTION_EVENT' => $event,
|
||||
'APPWRITE_FUNCTION_EVENT_PAYLOAD' => $payload,
|
||||
'APPWRITE_FUNCTION_EVENT_DATA' => $eventData,
|
||||
'APPWRITE_FUNCTION_DATA' => $data,
|
||||
'APPWRITE_FUNCTION_USER_ID' => $userId,
|
||||
'APPWRITE_FUNCTION_JWT' => $jwt,
|
||||
'APPWRITE_FUNCTION_PROJECT_ID' => $projectId,
|
||||
]);
|
||||
|
||||
\array_walk($vars, function (&$value, $key) {
|
||||
@@ -469,6 +476,26 @@ class FunctionsV1
|
||||
throw new Exception('Failed saving execution to DB', 500);
|
||||
}
|
||||
|
||||
$executionUpdate = new Event('v1-webhooks', 'WebhooksV1');
|
||||
|
||||
$executionUpdate
|
||||
->setParam('projectId', $projectId)
|
||||
->setParam('userId', $userId)
|
||||
->setParam('event', 'functions.executions.update')
|
||||
->setParam('eventData', [
|
||||
'$id' => $execution['$id'],
|
||||
'functionId' => $execution['functionId'],
|
||||
'dateCreated' => $execution['dateCreated'],
|
||||
'trigger' => $execution['trigger'],
|
||||
'status' => $execution['status'],
|
||||
'exitCode' => $execution['exitCode'],
|
||||
'stdout' => $execution['stdout'],
|
||||
'stderr' => $execution['stderr'],
|
||||
'time' => $execution['time']
|
||||
]);
|
||||
|
||||
$executionUpdate->trigger();
|
||||
|
||||
$usage = new Event('v1-usage', 'UsageV1');
|
||||
|
||||
$usage
|
||||
|
||||
@@ -37,7 +37,7 @@ class WebhooksV1
|
||||
$projectId = $this->args['projectId'] ?? '';
|
||||
$userId = $this->args['userId'] ?? '';
|
||||
$event = $this->args['event'] ?? '';
|
||||
$payload = \json_encode($this->args['payload']);
|
||||
$eventData = \json_encode($this->args['eventData']);
|
||||
|
||||
// Webhook
|
||||
|
||||
@@ -67,7 +67,7 @@ class WebhooksV1
|
||||
$ch = \curl_init($url);
|
||||
|
||||
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
|
||||
\curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
||||
\curl_setopt($ch, CURLOPT_POSTFIELDS, $eventData);
|
||||
\curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
\curl_setopt($ch, CURLOPT_USERAGENT, \sprintf(APP_USERAGENT,
|
||||
@@ -79,7 +79,7 @@ class WebhooksV1
|
||||
CURLOPT_HTTPHEADER,
|
||||
[
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: '.\strlen($payload),
|
||||
'Content-Length: '.\strlen($eventData),
|
||||
'X-'.APP_NAME.'-Webhook-Id: '.$id,
|
||||
'X-'.APP_NAME.'-Webhook-Event: '.$event,
|
||||
'X-'.APP_NAME.'-Webhook-Name: '.$name,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/src/code/vendor/bin/phpunit --verbose --configuration /usr/src/code/phpunit.xml $@
|
||||
/usr/src/code/vendor/bin/phpunit --configuration /usr/src/code/phpunit.xml $@
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
|
||||
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
|
||||
then
|
||||
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
else
|
||||
|
||||
+12
-9
@@ -15,7 +15,10 @@
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {"Tests\\E2E\\": "tests/e2e"}
|
||||
"psr-4": {
|
||||
"Tests\\E2E\\": "tests/e2e",
|
||||
"Appwrite\\Tests\\": "tests/extensions"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4.0",
|
||||
@@ -34,9 +37,9 @@
|
||||
|
||||
"appwrite/php-clamav": "1.0.*",
|
||||
|
||||
"utopia-php/framework": "0.10.0",
|
||||
"utopia-php/abuse": "0.3.*",
|
||||
"utopia-php/analytics": "0.1.*",
|
||||
"utopia-php/framework": "0.12.*",
|
||||
"utopia-php/abuse": "0.4.*",
|
||||
"utopia-php/analytics": "0.2.*",
|
||||
"utopia-php/audit": "0.5.*",
|
||||
"utopia-php/cache": "0.2.*",
|
||||
"utopia-php/cli": "0.10.0",
|
||||
@@ -47,19 +50,19 @@
|
||||
"utopia-php/domains": "0.2.*",
|
||||
"utopia-php/swoole": "0.2.*",
|
||||
"utopia-php/system": "0.4.*",
|
||||
"utopia-php/storage": "0.2.*",
|
||||
|
||||
"utopia-php/storage": "0.4.3",
|
||||
"utopia-php/image": "0.2.*",
|
||||
"resque/php-resque": "1.3.6",
|
||||
"matomo/device-detector": "4.1.0",
|
||||
"dragonmantank/cron-expression": "3.1.0",
|
||||
"domnikl/statsd": "3.0.2",
|
||||
"influxdb/influxdb-php": "1.15.2",
|
||||
"phpmailer/phpmailer": "6.3.0",
|
||||
"chillerlan/php-qrcode": "4.3.0",
|
||||
"adhocore/jwt": "1.1.2"
|
||||
"adhocore/jwt": "1.1.2",
|
||||
"slickdeals/statsd": "~3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"appwrite/sdk-generator": "0.5.5",
|
||||
"appwrite/sdk-generator": "dev-feat-preps-for-0.8",
|
||||
"phpunit/phpunit": "9.4.2",
|
||||
"swoole/ide-helper": "4.5.5",
|
||||
"vimeo/psalm": "4.1.1"
|
||||
|
||||
Generated
+480
-305
File diff suppressed because it is too large
Load Diff
+16
-15
@@ -71,10 +71,11 @@ services:
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
- clamav
|
||||
# - clamav
|
||||
- influxdb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_LOCALE
|
||||
- _APP_CONSOLE_WHITELIST_GOD
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||
- _APP_CONSOLE_WHITELIST_IPS
|
||||
@@ -416,16 +417,16 @@ services:
|
||||
volumes:
|
||||
- appwrite-redis:/data:rw
|
||||
|
||||
clamav:
|
||||
image: appwrite/clamav:1.2.0
|
||||
container_name: appwrite-clamav
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads
|
||||
# clamav:
|
||||
# image: appwrite/clamav:1.2.0
|
||||
# container_name: appwrite-clamav
|
||||
# networks:
|
||||
# - appwrite
|
||||
# volumes:
|
||||
# - appwrite-uploads:/storage/uploads
|
||||
|
||||
influxdb:
|
||||
image: influxdb:1.8-alpine
|
||||
image: appwrite/influxdb:1.0.0
|
||||
container_name: appwrite-influxdb
|
||||
networks:
|
||||
- appwrite
|
||||
@@ -433,7 +434,7 @@ services:
|
||||
- appwrite-influxdb:/var/lib/influxdb:rw
|
||||
|
||||
telegraf:
|
||||
image: appwrite/telegraf:1.0.0
|
||||
image: appwrite/telegraf:1.1.0
|
||||
container_name: appwrite-telegraf
|
||||
networks:
|
||||
- appwrite
|
||||
@@ -452,16 +453,16 @@ services:
|
||||
# Webgrind - A nice UI for exploring and debugging code-level stuff
|
||||
|
||||
maildev: # used mainly for dev tests
|
||||
image: djfarrelly/maildev
|
||||
container_name: appwrite-maildev
|
||||
image: appwrite/mailcatcher:1.0.0
|
||||
container_name: appwrite-mailcatcher
|
||||
ports:
|
||||
- '9503:80'
|
||||
- '9503:1080'
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
request-catcher: # used mainly for dev tests
|
||||
image: smarterdm/http-request-catcher
|
||||
container_name: appwrite-request-catcher
|
||||
image: appwrite/requestcatcher:1.0.0
|
||||
container_name: appwrite-requestcatcher
|
||||
ports:
|
||||
- '9504:5000'
|
||||
networks:
|
||||
|
||||
@@ -9,6 +9,9 @@ docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||
echo 'Deno 1.6...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-deno-1.6:1.0.0 ./docker/environments/deno-1.6/ --push
|
||||
|
||||
echo 'Deno 1.8...'
|
||||
docker buildx build --platform linux/amd64,linux/386 -t appwrite/env-deno-1.8:1.0.0 ./docker/environments/deno-1.8/ --push
|
||||
|
||||
echo 'Node 14.5...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le -t appwrite/env-node-14.5:1.0.0 ./docker/environments/node-14.5/ --push
|
||||
|
||||
@@ -24,6 +27,9 @@ docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||
echo 'Python 3.8...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-python-3.8:1.0.0 ./docker/environments/python-3.8/ --push
|
||||
|
||||
echo 'Python 3.9...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-python-3.9:1.0.0 ./docker/environments/python-3.9/ --push
|
||||
|
||||
echo 'Ruby 2.7...'
|
||||
docker buildx build --platform linux/amd64,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-ruby-2.7:1.0.2 ./docker/environments/ruby-2.7/ --push
|
||||
|
||||
@@ -33,8 +39,11 @@ docker buildx build --platform linux/amd64,linux/arm64,linux/386,linux/ppc64le -
|
||||
echo 'Dart 2.10...'
|
||||
docker buildx build --platform linux/amd64 -t appwrite/env-dart-2.10:1.0.0 ./docker/environments/dart-2.10/ --push
|
||||
|
||||
echo 'Dart 2.12...'
|
||||
docker buildx build --platform linux/amd64 -t appwrite/env-dart-2.12:1.0.0 ./docker/environments/dart-2.12/ --push
|
||||
|
||||
echo '.NET 3.1...'
|
||||
docker buildx build --platform linux/amd64,linux/arm64 -t appwrite/env-dotnet-3.1:1.0.0 ./docker/environments/dotnet-3.1/ --push
|
||||
docker buildx build --platform linux/amd64 -t appwrite/env-dotnet-3.1:1.0.0 ./docker/environments/dotnet-3.1/ --push
|
||||
|
||||
echo '.NET 5.0...'
|
||||
docker buildx build --platform linux/amd64,linux/arm64 -t appwrite/env-dotnet-5.0:1.0.0 ./docker/environments/dotnet-5.0/ --push
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
FROM google/dart:2.12
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apt-get update -y && apt-get install -y tar
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
||||
ENV PUB_CACHE=/usr/local/src/.appwrite
|
||||
@@ -0,0 +1,11 @@
|
||||
FROM hayd/deno:alpine-1.8.3
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
||||
ENV DENO_DIR=/usr/local/src/.appwrite
|
||||
@@ -0,0 +1,11 @@
|
||||
FROM python:3.9-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
||||
ENV PYTHONPATH "${PYTHONPATH}:/usr/local/src/.appwrite"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user