mirror of
https://github.com/appwrite/appwrite
synced 2026-05-22 00:18:25 +00:00
commit
a8dcd9efe3
1258 changed files with 26952 additions and 6639 deletions
8
.env
8
.env
|
|
@ -1,5 +1,9 @@
|
|||
_APP_ENV=production
|
||||
_APP_ENV=development
|
||||
_APP_LOCALE=en
|
||||
_APP_CONSOLE_WHITELIST_ROOT=disabled
|
||||
_APP_CONSOLE_WHITELIST_EMAILS=
|
||||
_APP_CONSOLE_WHITELIST_IPS=
|
||||
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
||||
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
|
||||
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io
|
||||
|
|
@ -16,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
|
||||
|
|
@ -24,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=
|
||||
|
|
|
|||
|
|
@ -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,9 @@ before_install:
|
|||
- docker --version
|
||||
- docker buildx create --use
|
||||
- chmod -R u+x ./.travis-ci
|
||||
- export COMPOSE_INTERACTIVE_NO_CLI=1
|
||||
# Only pass a single runtime for CI stability
|
||||
- echo "_APP_FUNCTIONS_RUNTIMES=php-8.0" >> .env
|
||||
|
||||
install:
|
||||
- docker-compose up -d
|
||||
|
|
|
|||
52
CHANGES.md
52
CHANGES.md
|
|
@ -1,6 +1,53 @@
|
|||
# Version 0.8.0 (Not Released Yet)
|
||||
# Version 0.8.0
|
||||
|
||||
- Anonymous login
|
||||
## Features
|
||||
- Refactoring SSL generation to work on every request so no domain environment variable is required for SSL generation (#1133)
|
||||
- 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 (#784)
|
||||
- Added ARM support (#726)
|
||||
- New awesome image preview features, supports borderRadius, borderColor, borderWidth
|
||||
- Split 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 (#947)
|
||||
- Added option to disable anonymous login (need to merge and apply changed) (#947)
|
||||
- Added option to disable JWT auth (#947)
|
||||
- Added option to disable team invites (#947)
|
||||
- Option to limit number of users (good for app launches + root account PR) (#947)
|
||||
- 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 (#1044)
|
||||
- Added Deno 1.8 as a new Cloud Functions runtime (#989)
|
||||
- Upgraded to PHP 8.0 (#713)
|
||||
- ClamAV is now disabled by default to allow lower min requirements 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)
|
||||
- Added Response Models for Documents and Preferences (#1075, #1102)
|
||||
- Added new endpoint to update team membership roles (#1142)
|
||||
- Removed DB connection from webhooks worker for improved performance (#1150)
|
||||
|
||||
## Bugs
|
||||
|
||||
- Fixed default value for HTTPS force option
|
||||
- Fixed form array casting in dashboard (#1070)
|
||||
- Fixed collection document rule form in dashboard (#1069)
|
||||
- Bugs in the Teams API:
|
||||
- Fixed incorrect audit worker event names (#1143)
|
||||
- Increased limit of memberships fetched in `createTeamMembership` to 2000 (#1143)
|
||||
- Fixed exception thrown when SSL certificate is already stored in the database (#1151)
|
||||
|
||||
## Breaking Changes (Read before upgrading!)
|
||||
|
||||
- Rename `deleteuser` to `delete` on Users Api (#1089)
|
||||
- Environment variable `_APP_FUNCTIONS_ENVS` renamed to `_APP_FUNCTIONS_RUNTIMES` (#1101)
|
||||
- Only logged in users can execute functions (for guests, use anonymous login) (#976)
|
||||
- Only the user who has triggered the execution get access to the relevant execution logs (#1045)
|
||||
- Function execution environment variable `APPWRITE_FUNCTION_EVENT_PAYLOAD` renamed to `APPWRITE_FUNCTION_EVENT_DATA` (#1045)
|
||||
- Function execution environment variable `APPWRITE_FUNCTION_ENV_NAME` renamed to `APPWRITE_FUNCTION_RUNTIME_NAME` (#1101)
|
||||
- Function execution environment variable `APPWRITE_FUNCTION_ENV_VERSION` renamed to `APPWRITE_FUNCTION_RUNTIME_VERSION` (#1101)
|
||||
- Introduces rate limits for:
|
||||
- Team invite (10 requests in every 60 minutes per IP address) (#1088)
|
||||
- Rename param `inviteId` to the more accurate `membershipId` in the Teams API (#1129)
|
||||
|
||||
# Version 0.7.2
|
||||
|
||||
|
|
@ -31,6 +78,7 @@
|
|||
- Force adding a security email on setup
|
||||
- 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
|
||||
|
||||
|
|
|
|||
|
|
@ -278,13 +278,9 @@ Before running the command, make sure you have proper write permissions to the A
|
|||
```bash
|
||||
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -t appwrite/appwrite:dev --push .
|
||||
```
|
||||
**Build Functions Envs**
|
||||
**Build Functions Runtimes**
|
||||
|
||||
Build envs for all supported cloud functions (multicore builds)
|
||||
|
||||
```bash
|
||||
bash ./docker/environments/build.sh
|
||||
```
|
||||
The Runtimes for all supported cloud functions (multicore builds) can be found at the [appwrite/php-runtimes](https://github.com/appwrite/php-runtimes) repository.
|
||||
|
||||
## Tests
|
||||
|
||||
|
|
|
|||
69
Dockerfile
69
Dockerfile
|
|
@ -12,12 +12,13 @@ RUN composer update --ignore-platform-reqs --optimize-autoloader \
|
|||
--no-plugins --no-scripts --prefer-dist \
|
||||
`if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi`
|
||||
|
||||
FROM php:7.4-cli-alpine as step1
|
||||
FROM php:8.0-cli-alpine as step1
|
||||
|
||||
ENV PHP_REDIS_VERSION=5.3.3 \
|
||||
PHP_SWOOLE_VERSION=v4.5.8 \
|
||||
PHP_MAXMINDDB_VERSION=v1.10.0 \
|
||||
PHP_XDEBUG_VERSION=sdebug_2_9-beta
|
||||
ENV PHP_REDIS_VERSION=5.3.4 \
|
||||
PHP_SWOOLE_VERSION=v4.6.6 \
|
||||
PHP_IMAGICK_VERSION=master \
|
||||
PHP_YAML_VERSION=2.2.1 \
|
||||
PHP_MAXMINDDB_VERSION=v1.10.1
|
||||
|
||||
RUN \
|
||||
apk add --no-cache --virtual .deps \
|
||||
|
|
@ -29,38 +30,52 @@ RUN \
|
|||
git \
|
||||
zlib-dev \
|
||||
brotli-dev \
|
||||
yaml-dev \
|
||||
imagemagick \
|
||||
imagemagick-dev \
|
||||
libmaxminddb-dev
|
||||
|
||||
RUN docker-php-ext-install sockets
|
||||
|
||||
RUN \
|
||||
# Redis Extension
|
||||
git clone https://github.com/phpredis/phpredis.git && \
|
||||
git clone --depth 1 --branch $PHP_REDIS_VERSION https://github.com/phpredis/phpredis.git && \
|
||||
cd phpredis && \
|
||||
git checkout $PHP_REDIS_VERSION && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install && \
|
||||
cd .. && \
|
||||
## Swoole Extension
|
||||
git clone https://github.com/swoole/swoole-src.git && \
|
||||
git clone --depth 1 --branch $PHP_SWOOLE_VERSION https://github.com/swoole/swoole-src.git && \
|
||||
cd swoole-src && \
|
||||
git checkout $PHP_SWOOLE_VERSION && \
|
||||
phpize && \
|
||||
./configure --enable-sockets --enable-http2 && \
|
||||
./configure --enable-http2 && \
|
||||
make && make install && \
|
||||
cd .. && \
|
||||
## Imagick Extension
|
||||
git clone --depth 1 --branch $PHP_IMAGICK_VERSION https://github.com/Imagick/imagick && \
|
||||
cd imagick && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install && \
|
||||
cd .. && \
|
||||
## YAML Extension
|
||||
git clone --depth 1 --branch $PHP_YAML_VERSION https://github.com/php/pecl-file_formats-yaml && \
|
||||
cd pecl-file_formats-yaml && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install && \
|
||||
cd .. && \
|
||||
## Maxminddb extension
|
||||
git clone https://github.com/maxmind/MaxMind-DB-Reader-php.git && \
|
||||
git clone --depth 1 --branch $PHP_MAXMINDDB_VERSION https://github.com/maxmind/MaxMind-DB-Reader-php.git && \
|
||||
cd MaxMind-DB-Reader-php && \
|
||||
git checkout $PHP_MAXMINDDB_VERSION && \
|
||||
cd ext && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install && \
|
||||
cd ../..
|
||||
|
||||
FROM php:7.4-cli-alpine as final
|
||||
FROM php:8.0-cli-alpine as final
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
|
|
@ -68,10 +83,18 @@ 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 \
|
||||
_APP_EDITION=community \
|
||||
_APP_CONSOLE_WHITELIST_ROOT=enabled \
|
||||
_APP_CONSOLE_WHITELIST_EMAILS= \
|
||||
_APP_CONSOLE_WHITELIST_IPS= \
|
||||
_APP_SYSTEM_EMAIL_NAME= \
|
||||
_APP_SYSTEM_EMAIL_ADDRESS= \
|
||||
_APP_SYSTEM_RESPONSE_FORMAT= \
|
||||
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS= \
|
||||
_APP_OPTIONS_ABUSE=enabled \
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled \
|
||||
_APP_OPENSSL_KEY_V1=your-secret-key \
|
||||
|
|
@ -123,16 +146,14 @@ RUN \
|
|||
curl-dev \
|
||||
&& apk add --no-cache \
|
||||
libstdc++ \
|
||||
certbot \
|
||||
brotli-dev \
|
||||
yaml-dev \
|
||||
imagemagick \
|
||||
imagemagick-dev \
|
||||
libmaxminddb-dev \
|
||||
certbot \
|
||||
docker-cli \
|
||||
docker-compose \
|
||||
libmaxminddb \
|
||||
libmaxminddb-dev \
|
||||
&& pecl install imagick yaml \
|
||||
&& docker-php-ext-enable imagick yaml \
|
||||
&& docker-php-ext-install sockets opcache pdo_mysql \
|
||||
&& apk del .deps \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
|
@ -140,9 +161,11 @@ RUN \
|
|||
WORKDIR /usr/src/code
|
||||
|
||||
COPY --from=step0 /usr/local/src/vendor /usr/src/code/vendor
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20190902/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20190902/
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20190902/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20190902/
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20190902/maxminddb.so /usr/local/lib/php/extensions/no-debug-non-zts-20190902/
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/imagick.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yaml.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=step1 /usr/local/lib/php/extensions/no-debug-non-zts-20200930/maxminddb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
|
||||
# Add Source Code
|
||||
COPY ./app /usr/src/code/app
|
||||
|
|
@ -190,11 +213,15 @@ RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
|
|||
# Enable Extensions
|
||||
RUN echo extension=swoole.so >> /usr/local/etc/php/conf.d/swoole.ini
|
||||
RUN echo extension=redis.so >> /usr/local/etc/php/conf.d/redis.ini
|
||||
RUN echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini
|
||||
RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini
|
||||
RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini
|
||||
|
||||
RUN echo "opcache.preload_user=www-data" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.preload=/usr/src/code/app/preload.php" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.jit_buffer_size=100M" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.jit=1235" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,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.2
|
||||
appwrite/appwrite:0.8.0
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
|
@ -66,7 +66,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.2
|
||||
appwrite/appwrite:0.8.0
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
|
|
@ -76,7 +76,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.2
|
||||
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.
|
||||
|
|
|
|||
42
app/config/auth.php
Normal file
42
app/config/auth.php
Normal file
|
|
@ -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,
|
||||
],
|
||||
];
|
||||
|
|
@ -5,6 +5,7 @@ use Utopia\Config\Config;
|
|||
use Appwrite\Database\Database;
|
||||
|
||||
$providers = Config::getParam('providers', []);
|
||||
$auth = Config::getParam('auth', []);
|
||||
|
||||
$collections = [
|
||||
'console' => [
|
||||
|
|
@ -45,7 +46,7 @@ $collections = [
|
|||
'legalTaxId' => '',
|
||||
'authWhitelistEmails' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [],
|
||||
'authWhitelistIPs' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [],
|
||||
'authWhitelistDomains' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null)) : [],
|
||||
'usersAuthLimit' => (App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user
|
||||
],
|
||||
Database::SYSTEM_COLLECTION_COLLECTIONS => [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS,
|
||||
|
|
@ -204,7 +205,7 @@ $collections = [
|
|||
'key' => 'email',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_EMAIL,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
|
|
@ -222,7 +223,7 @@ $collections = [
|
|||
'key' => 'password',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_TEXT,
|
||||
'default' => '',
|
||||
'required' => true,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
|
|
@ -271,6 +272,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',
|
||||
|
|
@ -293,11 +304,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' => [
|
||||
[
|
||||
|
|
@ -306,16 +317,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,
|
||||
],
|
||||
[
|
||||
|
|
@ -473,6 +502,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,
|
||||
|
|
@ -679,6 +771,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',
|
||||
|
|
@ -1172,6 +1272,24 @@ $collections = [
|
|||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Updated Date',
|
||||
'key' => 'updated',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_NUMERIC,
|
||||
'default' => 0,
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RULES,
|
||||
'label' => 'Certificate ID',
|
||||
'key' => 'certificateId',
|
||||
'type' => Database::SYSTEM_VAR_TYPE_KEY,
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
'array' => false,
|
||||
],
|
||||
],
|
||||
],
|
||||
Database::SYSTEM_COLLECTION_FILES => [
|
||||
|
|
@ -1617,25 +1735,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,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,138 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Utopia\App;
|
||||
use Utopia\System\System;
|
||||
|
||||
/**
|
||||
* List of Appwrite Cloud Functions supported environments
|
||||
*/
|
||||
$environments = [
|
||||
'node-14.5' => [
|
||||
'name' => 'Node.js',
|
||||
'version' => '14.5',
|
||||
'base' => 'node:14.5-alpine',
|
||||
'image' => 'appwrite/env-node-14.5:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/node-14.5',
|
||||
'logo' => 'node.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'node-15.5' => [
|
||||
'name' => 'Node.js',
|
||||
'version' => '15.5',
|
||||
'base' => 'node:15.5-alpine',
|
||||
'image' => 'appwrite/env-node-15.5:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/node-15.5',
|
||||
'logo' => 'node.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'php-7.4' => [
|
||||
'name' => 'PHP',
|
||||
'version' => '7.4',
|
||||
'base' => 'php:7.4-cli-alpine',
|
||||
'image' => 'appwrite/env-php-7.4:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/php-7.4',
|
||||
'logo' => 'php.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'php-8.0' => [
|
||||
'name' => 'PHP',
|
||||
'version' => '8.0',
|
||||
'base' => 'php:8.0-cli-alpine',
|
||||
'image' => 'appwrite/env-php-8.0:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/php-8.0',
|
||||
'logo' => 'php.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'ruby-2.7' => [
|
||||
'name' => 'Ruby',
|
||||
'version' => '2.7',
|
||||
'base' => 'ruby:2.7-alpine',
|
||||
'image' => 'appwrite/env-ruby-2.7:1.0.2',
|
||||
'build' => '/usr/src/code/docker/environments/ruby-2.7',
|
||||
'logo' => 'ruby.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'ruby-3.0' => [
|
||||
'name' => 'Ruby',
|
||||
'version' => '3.0',
|
||||
'base' => 'ruby:3.0-alpine',
|
||||
'image' => 'appwrite/env-ruby-3.0:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/ruby-3.0',
|
||||
'logo' => 'ruby.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'python-3.8' => [
|
||||
'name' => 'Python',
|
||||
'version' => '3.8',
|
||||
'base' => 'python:3.8-alpine',
|
||||
'image' => 'appwrite/env-python-3.8:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/python-3.8',
|
||||
'logo' => 'python.png',
|
||||
'supports' => [System::X86, System::PPC, System::ARM],
|
||||
],
|
||||
'deno-1.2' => [
|
||||
'name' => 'Deno',
|
||||
'version' => '1.2',
|
||||
'base' => 'hayd/deno:alpine-1.2.0',
|
||||
'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],
|
||||
],
|
||||
'deno-1.5' => [
|
||||
'name' => 'Deno',
|
||||
'version' => '1.5',
|
||||
'base' => 'hayd/deno:alpine-1.5.0',
|
||||
'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],
|
||||
],
|
||||
'deno-1.6' => [
|
||||
'name' => 'Deno',
|
||||
'version' => '1.6',
|
||||
'base' => 'hayd/deno:alpine-1.6.0',
|
||||
'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],
|
||||
],
|
||||
'dart-2.10' => [
|
||||
'name' => 'Dart',
|
||||
'version' => '2.10',
|
||||
'base' => 'google/dart:2.10',
|
||||
'image' => 'appwrite/env-dart-2.10:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/dart-2.10',
|
||||
'logo' => 'dart.png',
|
||||
'supports' => [System::X86],
|
||||
],
|
||||
'dotnet-3.1' => [
|
||||
'name' => '.NET',
|
||||
'version' => '3.1',
|
||||
'base' => 'mcr.microsoft.com/dotnet/runtime:3.1-alpine',
|
||||
'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],
|
||||
],
|
||||
'dotnet-5.0' => [
|
||||
'name' => '.NET',
|
||||
'version' => '5.0',
|
||||
'base' => 'mcr.microsoft.com/dotnet/runtime:5.0-alpine',
|
||||
'image' => 'appwrite/env-dotnet-5.0:1.0.0',
|
||||
'build' => '/usr/src/code/docker/environments/dotnet-5.0',
|
||||
'logo' => 'dotnet.png',
|
||||
'supports' => [System::X86, System::ARM],
|
||||
],
|
||||
];
|
||||
|
||||
$allowList = empty(App::getEnv('_APP_FUNCTIONS_ENVS', null)) ? false : \explode(',', App::getEnv('_APP_FUNCTIONS_ENVS', null));
|
||||
|
||||
$environments = array_filter($environments, function ($environment, $key) use ($allowList) {
|
||||
$isAllowed = $allowList && in_array($key, $allowList);
|
||||
$isSupported = in_array(System::getArchEnum(), $environment["supports"]);
|
||||
|
||||
return $allowList ? ($isAllowed && $isSupported) : $isSupported;
|
||||
}, ARRAY_FILTER_USE_BOTH);
|
||||
|
||||
return $environments;
|
||||
|
|
@ -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,
|
||||
|
|
@ -157,6 +197,11 @@ return [
|
|||
'model' => Response::MODEL_MEMBERSHIP,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
'teams.memberships.update' => [
|
||||
'description' => 'This event triggers when a team membership is updated.',
|
||||
'model' => Response::MODEL_MEMBERSHIP,
|
||||
'note' => 'version >= 0.8',
|
||||
],
|
||||
'teams.memberships.update.status' => [
|
||||
'description' => 'This event triggers when a team memberships status is updated.',
|
||||
'model' => Response::MODEL_MEMBERSHIP,
|
||||
|
|
@ -167,4 +212,4 @@ return [
|
|||
'model' => Response::MODEL_MEMBERSHIP,
|
||||
'note' => 'version >= 0.7',
|
||||
],
|
||||
];
|
||||
];
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ return [
|
|||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Web',
|
||||
'version' => '2.0.0',
|
||||
'version' => '3.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-web',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -62,7 +62,7 @@ return [
|
|||
[
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'version' => '0.5.0-dev.1',
|
||||
'version' => '0.6.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-flutter',
|
||||
'package' => 'https://pub.dev/packages/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -151,7 +151,7 @@ return [
|
|||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Console',
|
||||
'version' => '1.0.0',
|
||||
'version' => '2.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-console',
|
||||
'package' => '',
|
||||
'enabled' => true,
|
||||
|
|
@ -178,7 +178,7 @@ return [
|
|||
[
|
||||
'key' => 'nodejs',
|
||||
'name' => 'Node.js',
|
||||
'version' => '2.1.0',
|
||||
'version' => '2.2.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-node',
|
||||
'package' => 'https://www.npmjs.com/package/node-appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -195,7 +195,7 @@ return [
|
|||
[
|
||||
'key' => 'deno',
|
||||
'name' => 'Deno',
|
||||
'version' => '0.1.1',
|
||||
'version' => '0.2.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-deno',
|
||||
'package' => 'https://deno.land/x/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -212,7 +212,7 @@ return [
|
|||
[
|
||||
'key' => 'php',
|
||||
'name' => 'PHP',
|
||||
'version' => '2.0.0',
|
||||
'version' => '2.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-php',
|
||||
'package' => 'https://packagist.org/packages/appwrite/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -229,7 +229,7 @@ return [
|
|||
[
|
||||
'key' => 'python',
|
||||
'name' => 'Python',
|
||||
'version' => '0.1.1',
|
||||
'version' => '0.2.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-python',
|
||||
'package' => 'https://pypi.org/project/appwrite/',
|
||||
'enabled' => true,
|
||||
|
|
@ -246,7 +246,7 @@ return [
|
|||
[
|
||||
'key' => 'ruby',
|
||||
'name' => 'Ruby',
|
||||
'version' => '2.0.2',
|
||||
'version' => '2.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-ruby',
|
||||
'package' => 'https://rubygems.org/gems/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -297,7 +297,7 @@ return [
|
|||
[
|
||||
'key' => 'dotnet',
|
||||
'name' => '.NET',
|
||||
'version' => '0.2.0',
|
||||
'version' => '0.3.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
|
||||
'package' => 'https://www.nuget.org/packages/Appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -314,7 +314,7 @@ return [
|
|||
[
|
||||
'key' => 'dart',
|
||||
'name' => 'Dart',
|
||||
'version' => '0.5.0-dev.1',
|
||||
'version' => '0.6.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dart',
|
||||
'package' => 'https://pub.dev/packages/dart_appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -331,7 +331,7 @@ return [
|
|||
[
|
||||
'key' => 'cli',
|
||||
'name' => 'Command Line',
|
||||
'version' => '0.8.0',
|
||||
'version' => '0.9.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 => [
|
||||
|
|
|
|||
15
app/config/runtimes.php
Normal file
15
app/config/runtimes.php
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
use Utopia\App;
|
||||
use Appwrite\Runtimes\Runtimes;
|
||||
|
||||
/**
|
||||
* List of Appwrite Cloud Functions supported runtimes
|
||||
*/
|
||||
$runtimes = new Runtimes();
|
||||
|
||||
$allowList = empty(App::getEnv('_APP_FUNCTIONS_RUNTIMES')) ? [] : \explode(',', App::getEnv('_APP_FUNCTIONS_RUNTIMES'));
|
||||
|
||||
$runtimes = $runtimes->getAll(true, $allowList);
|
||||
|
||||
return $runtimes;
|
||||
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
2
app/config/specs/0.8.x.client.json
Normal file
2
app/config/specs/0.8.x.client.json
Normal file
File diff suppressed because one or more lines are too long
2
app/config/specs/0.8.x.console.json
Normal file
2
app/config/specs/0.8.x.console.json
Normal file
File diff suppressed because one or more lines are too long
2
app/config/specs/0.8.x.server.json
Normal file
2
app/config/specs/0.8.x.server.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -14,6 +14,16 @@ return [
|
|||
'default' => 'production',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_LOCALE',
|
||||
'description' => 'Set your Appwrite\'s locale. By default, the locale is set to \'en\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'en',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_OPTIONS_ABUSE',
|
||||
|
|
@ -22,14 +32,16 @@ return [
|
|||
'default' => 'enabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'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' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_OPENSSL_KEY_V1',
|
||||
|
|
@ -38,6 +50,7 @@ return [
|
|||
'default' => 'your-secret-key',
|
||||
'required' => true,
|
||||
'question' => 'Choose a secret API key, make sure to make a backup of your key in a secure location',
|
||||
'filter' => 'token'
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN',
|
||||
|
|
@ -46,6 +59,7 @@ return [
|
|||
'default' => 'localhost',
|
||||
'required' => true,
|
||||
'question' => 'Enter your Appwrite hostname',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN_TARGET',
|
||||
|
|
@ -54,14 +68,25 @@ return [
|
|||
'default' => 'localhost',
|
||||
'required' => true,
|
||||
'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.\nYou can use the same value as used for the Appwrite hostname.',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_CONSOLE_WHITELIST_ROOT',
|
||||
'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by invting them to your project. By default this option is enabled.',
|
||||
'introduction' => '0.8.0',
|
||||
'default' => 'enabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_CONSOLE_WHITELIST_EMAILS',
|
||||
'description' => 'This option allows you to limit creation of users to Appwrite console. This option is very useful for small teams or sole developers. To enable it, pass a list of allowed email addresses separated by a comma.',
|
||||
'description' => 'This option allows you to limit creation of new users on the Appwrite console. This option is very useful for small teams or sole developers. To enable it, pass a list of allowed email addresses separated by a comma.',
|
||||
'introduction' => '',
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
// [
|
||||
// 'name' => '_APP_CONSOLE_WHITELIST_DOMAINS',
|
||||
|
|
@ -78,6 +103,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SYSTEM_EMAIL_NAME',
|
||||
|
|
@ -86,6 +112,7 @@ return [
|
|||
'default' => 'Appwrite',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SYSTEM_EMAIL_ADDRESS',
|
||||
|
|
@ -94,6 +121,7 @@ return [
|
|||
'default' => 'team@appwrite.io',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SYSTEM_RESPONSE_FORMAT',
|
||||
|
|
@ -102,6 +130,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SYSTEM_SECURITY_EMAIL_ADDRESS',
|
||||
|
|
@ -110,6 +139,7 @@ return [
|
|||
'default' => 'certs@appwrite.io',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_USAGE_STATS',
|
||||
|
|
@ -118,7 +148,8 @@ return [
|
|||
'default' => 'enabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
'filter' => ''
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
|
|
@ -132,6 +163,7 @@ return [
|
|||
'default' => 'redis',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_REDIS_PORT',
|
||||
|
|
@ -140,6 +172,7 @@ return [
|
|||
'default' => '6379',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_REDIS_USER',
|
||||
|
|
@ -148,6 +181,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_REDIS_PASS',
|
||||
|
|
@ -156,6 +190,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
@ -170,6 +205,7 @@ return [
|
|||
'default' => 'mariadb',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_PORT',
|
||||
|
|
@ -178,6 +214,7 @@ return [
|
|||
'default' => '3306',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_SCHEMA',
|
||||
|
|
@ -186,6 +223,7 @@ return [
|
|||
'default' => 'appwrite',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_USER',
|
||||
|
|
@ -194,6 +232,7 @@ return [
|
|||
'default' => 'user',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_PASS',
|
||||
|
|
@ -202,6 +241,16 @@ return [
|
|||
'default' => 'password',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => 'password'
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_ROOT_PASS',
|
||||
'description' => 'MariaDB server root password. Default value is: \'rootsecretpassword\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'rootsecretpassword',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => 'password'
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
@ -216,6 +265,7 @@ return [
|
|||
'default' => 'influxdb',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_INFLUXDB_PORT',
|
||||
|
|
@ -224,6 +274,7 @@ return [
|
|||
'default' => '8086',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
@ -238,6 +289,7 @@ return [
|
|||
'default' => 'telegraf',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_STATSD_PORT',
|
||||
|
|
@ -246,6 +298,7 @@ return [
|
|||
'default' => '8125',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
@ -260,6 +313,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SMTP_PORT',
|
||||
|
|
@ -268,6 +322,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SMTP_SECURE',
|
||||
|
|
@ -276,6 +331,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SMTP_USERNAME',
|
||||
|
|
@ -284,6 +340,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SMTP_PASSWORD',
|
||||
|
|
@ -292,6 +349,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
@ -306,14 +364,16 @@ return [
|
|||
'default' => '10000000',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'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' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_STORAGE_ANTIVIRUS_HOST',
|
||||
|
|
@ -322,6 +382,7 @@ return [
|
|||
'default' => 'clamav',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_STORAGE_ANTIVIRUS_PORT',
|
||||
|
|
@ -330,6 +391,7 @@ return [
|
|||
'default' => '3310',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
@ -344,6 +406,7 @@ return [
|
|||
'default' => '900',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_CONTAINERS',
|
||||
|
|
@ -352,6 +415,7 @@ return [
|
|||
'default' => '10',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_CPUS',
|
||||
|
|
@ -360,6 +424,7 @@ return [
|
|||
'default' => '',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_MEMORY',
|
||||
|
|
@ -368,6 +433,7 @@ return [
|
|||
'default' => '256',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_MEMORY_SWAP',
|
||||
|
|
@ -376,14 +442,25 @@ return [
|
|||
'default' => '256',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_RUNTIMES',
|
||||
'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('runtimes'))),
|
||||
'introduction' => '0.8.0',
|
||||
'default' => 'node-15.5,deno-1.8,php-8.0,python-3.9,ruby-3.0,dotnet-5.0',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'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'))),
|
||||
'description' => 'Deprectated with 0.8.0, use \'_APP_FUNCTIONS_RUNTIMES\' instead!',
|
||||
'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' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
[
|
||||
|
|
@ -397,6 +474,7 @@ return [
|
|||
'default' => '86400',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_EXECUTION',
|
||||
|
|
@ -405,6 +483,7 @@ return [
|
|||
'default' => '1209600',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_AUDIT',
|
||||
|
|
@ -413,6 +492,7 @@ return [
|
|||
'default' => '1209600',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_ABUSE',
|
||||
|
|
@ -421,6 +501,7 @@ return [
|
|||
'default' => '86400',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
]
|
||||
],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
@ -60,7 +61,6 @@ App::post('/v1/account')
|
|||
if ('console' === $project->getId()) {
|
||||
$whitlistEmails = $project->getAttribute('authWhitelistEmails');
|
||||
$whitlistIPs = $project->getAttribute('authWhitelistIPs');
|
||||
$whitlistDomains = $project->getAttribute('authWhitelistDomains');
|
||||
|
||||
if (!empty($whitlistEmails) && !\in_array($email, $whitlistEmails)) {
|
||||
throw new Exception('Console registration is restricted to specific emails. Contact your administrator for more information.', 401);
|
||||
|
|
@ -69,9 +69,21 @@ App::post('/v1/account')
|
|||
if (!empty($whitlistIPs) && !\in_array($request->getIP(), $whitlistIPs)) {
|
||||
throw new Exception('Console registration is restricted to specific IPs. Contact your administrator for more information.', 401);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($whitlistDomains) && !\in_array(\substr(\strrchr($email, '@'), 1), $whitlistDomains)) {
|
||||
throw new Exception('Console registration is restricted to specific domains. Contact your administrator for more information.', 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +121,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());
|
||||
|
|
@ -133,10 +145,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')
|
||||
|
|
@ -190,10 +203,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'),
|
||||
|
|
@ -210,7 +224,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,7 +265,7 @@ 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')
|
||||
|
|
@ -441,7 +455,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);
|
||||
|
|
@ -451,7 +465,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;
|
||||
|
||||
|
|
@ -467,7 +482,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 {
|
||||
|
|
@ -478,7 +509,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
'emailVerification' => true,
|
||||
'status' => Auth::USER_STATUS_ACTIVATED, // Email should already be authenticated by OAuth2 provider
|
||||
'password' => Auth::passwordHash(Auth::passwordGenerator()),
|
||||
'passwordUpdate' => \time(),
|
||||
'passwordUpdate' => 0,
|
||||
'registration' => \time(),
|
||||
'reset' => false,
|
||||
'name' => $name,
|
||||
|
|
@ -487,7 +518,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);
|
||||
|
|
@ -506,10 +537,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'),
|
||||
|
|
@ -517,11 +550,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());
|
||||
|
|
@ -566,12 +606,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')
|
||||
|
|
@ -583,16 +767,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);
|
||||
}
|
||||
|
||||
|
|
@ -606,7 +792,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);
|
||||
});
|
||||
|
||||
|
|
@ -614,7 +800,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')
|
||||
|
|
@ -634,13 +820,13 @@ 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')
|
||||
->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_PREFERENCES)
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->action(function ($response, $user) {
|
||||
|
|
@ -649,14 +835,14 @@ App::get('/v1/account/prefs')
|
|||
|
||||
$prefs = $user->getAttribute('prefs', new \stdClass());
|
||||
|
||||
$response->dynamic(new Document($prefs), Response::MODEL_ANY);
|
||||
$response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES);
|
||||
});
|
||||
|
||||
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')
|
||||
|
|
@ -671,22 +857,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[strtoupper($token->getAttribute('countryCode'))]))
|
||||
? $countries[strtoupper($token->getAttribute('countryCode'))]
|
||||
$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([
|
||||
|
|
@ -699,7 +882,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')
|
||||
|
|
@ -776,7 +959,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')
|
||||
|
|
@ -816,7 +999,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')
|
||||
|
|
@ -824,7 +1007,7 @@ App::patch('/v1/account/password')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_USER)
|
||||
->param('password', '', new Password(), 'New user password. Must be between 6 to 32 chars.')
|
||||
->param('oldPassword', '', new Password(), 'Old user password. Must be between 6 to 32 chars.')
|
||||
->param('oldPassword', '', new Password(), 'Old user password. Must be between 6 to 32 chars.', true)
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('projectDB')
|
||||
|
|
@ -835,12 +1018,14 @@ App::patch('/v1/account/password')
|
|||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
if (!Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password
|
||||
// Check old password only if its an existing user.
|
||||
if ($user->getAttribute('passwordUpdate') !== 0 && !Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password
|
||||
throw new Exception('Invalid credentials', 401);
|
||||
}
|
||||
|
||||
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
|
||||
'password' => Auth::passwordHash($password),
|
||||
'passwordUpdate' => \time(),
|
||||
]));
|
||||
|
||||
if (false === $user) {
|
||||
|
|
@ -861,7 +1046,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')
|
||||
|
|
@ -880,7 +1065,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);
|
||||
}
|
||||
|
||||
|
|
@ -898,10 +1088,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);
|
||||
|
|
@ -921,13 +1115,13 @@ 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')
|
||||
->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_USER)
|
||||
->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
|
|
@ -960,7 +1154,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')
|
||||
|
|
@ -1005,7 +1199,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')) {
|
||||
|
|
@ -1026,7 +1220,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')
|
||||
|
|
@ -1050,14 +1244,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);
|
||||
}
|
||||
|
||||
|
|
@ -1073,10 +1269,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)
|
||||
|
|
@ -1085,7 +1281,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();
|
||||
|
|
@ -1100,7 +1296,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')
|
||||
|
|
@ -1122,10 +1318,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);
|
||||
}
|
||||
|
||||
|
|
@ -1141,10 +1339,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'))
|
||||
|
|
@ -1153,9 +1351,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))
|
||||
;
|
||||
|
||||
|
|
@ -1167,7 +1365,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')
|
||||
|
|
@ -1196,7 +1394,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
|
||||
|
|
@ -1278,7 +1476,7 @@ App::post('/v1/account/recovery')
|
|||
;
|
||||
|
||||
$events
|
||||
->setParam('payload',
|
||||
->setParam('eventData',
|
||||
$response->output($recovery->setAttribute('secret', $secret),
|
||||
Response::MODEL_TOKEN
|
||||
))
|
||||
|
|
@ -1286,7 +1484,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())
|
||||
|
|
@ -1305,7 +1503,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')
|
||||
|
|
@ -1384,7 +1582,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')
|
||||
|
|
@ -1414,7 +1612,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();
|
||||
|
|
@ -1481,7 +1679,7 @@ App::post('/v1/account/verification')
|
|||
;
|
||||
|
||||
$events
|
||||
->setParam('payload',
|
||||
->setParam('eventData',
|
||||
$response->output($verification->setAttribute('secret', $verificationSecret),
|
||||
Response::MODEL_TOKEN
|
||||
))
|
||||
|
|
@ -1489,7 +1687,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())
|
||||
|
|
@ -1508,7 +1706,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')
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use Utopia\Validator\Boolean;
|
|||
use Utopia\Validator\HexColor;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\URL;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
$avatarCallback = function ($type, $code, $width, $height, $quality, $response) {
|
||||
|
|
@ -38,7 +38,7 @@ $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);
|
||||
$key = \md5('/v1/avatars/'.$type.'/:code-' . $code . $width . $height . $quality . $output);
|
||||
$path = $set[$code];
|
||||
$type = 'png';
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ 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')
|
||||
|
|
@ -103,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')
|
||||
|
|
@ -123,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')
|
||||
|
|
@ -143,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')
|
||||
|
|
@ -212,7 +212,7 @@ 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')
|
||||
|
|
@ -365,7 +365,7 @@ 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')
|
||||
|
|
@ -408,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')
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -238,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)
|
||||
|
|
@ -271,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
|
||||
|
|
@ -289,12 +289,12 @@ 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', 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)
|
||||
|
|
@ -401,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)
|
||||
;
|
||||
});
|
||||
|
||||
|
|
@ -410,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)
|
||||
|
|
@ -473,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')
|
||||
|
|
@ -494,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')
|
||||
|
|
@ -503,12 +503,12 @@ 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.')
|
||||
|
|
@ -566,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')
|
||||
|
|
@ -575,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)
|
||||
|
|
@ -614,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')
|
||||
|
|
@ -36,7 +39,7 @@ App::post('/v1/functions')
|
|||
->label('sdk.response.model', Response::MODEL_FUNCTION)
|
||||
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
|
||||
->param('execute', [], new ArrayList(new Text(64)), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('env', '', new WhiteList(array_keys(Config::getParam('environments')), true), 'Execution enviornment.')
|
||||
->param('env', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution enviornment.')
|
||||
->param('vars', [], new Assoc(), 'Key-value JSON object.', true)
|
||||
->param('events', [], new ArrayList(new WhiteList(array_keys(Config::getParam('events')), true)), 'Events list.', true)
|
||||
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
|
||||
|
|
@ -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')
|
||||
|
|
@ -317,6 +321,7 @@ App::put('/v1/functions/:functionId')
|
|||
if ($next && $schedule !== $original) {
|
||||
ResqueScheduler::enqueueAt($next, 'v1-functions', 'FunctionsV1', [
|
||||
'projectId' => $project->getId(),
|
||||
'webhooks' => $project->getAttribute('webhooks', []),
|
||||
'functionId' => $function->getId(),
|
||||
'executionId' => null,
|
||||
'trigger' => 'schedule',
|
||||
|
|
@ -330,7 +335,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')
|
||||
|
|
@ -370,6 +376,7 @@ App::patch('/v1/functions/:functionId/tag')
|
|||
if ($next) { // Init first schedule
|
||||
ResqueScheduler::enqueueAt($next, 'v1-functions', 'FunctionsV1', [
|
||||
'projectId' => $project->getId(),
|
||||
'webhooks' => $project->getAttribute('webhooks', []),
|
||||
'functionId' => $function->getId(),
|
||||
'executionId' => null,
|
||||
'trigger' => 'schedule',
|
||||
|
|
@ -387,7 +394,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 +432,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')
|
||||
|
|
@ -518,7 +527,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 +572,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 +610,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 +672,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 +683,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 +726,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 +744,37 @@ 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(),
|
||||
'webhooks' => $project->getAttribute('webhooks', []),
|
||||
'functionId' => $function->getId(),
|
||||
'executionId' => $execution->getId(),
|
||||
'trigger' => 'http',
|
||||
'data' => $data,
|
||||
'userId' => $user->getId(),
|
||||
'jwt' => $jwt,
|
||||
]);
|
||||
|
||||
$response
|
||||
|
|
@ -748,7 +787,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')
|
||||
|
|
@ -766,7 +805,9 @@ App::get('/v1/functions/:functionId/executions')
|
|||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
|
||||
Authorization::disable();
|
||||
$function = $projectDB->getDocument($functionId);
|
||||
Authorization::reset();
|
||||
|
||||
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
||||
throw new Exception('Function not found', 404);
|
||||
|
|
@ -793,7 +834,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')
|
||||
|
|
@ -808,7 +849,9 @@ App::get('/v1/functions/:functionId/executions/:executionId')
|
|||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
|
||||
Authorization::disable();
|
||||
$function = $projectDB->getDocument($functionId);
|
||||
Authorization::reset();
|
||||
|
||||
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
||||
throw new Exception('Function not found', 404);
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
@ -272,8 +272,8 @@ App::get('/v1/health/anti-virus')
|
|||
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('scope', 'root')
|
||||
// ->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)
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
@ -115,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);
|
||||
}
|
||||
|
||||
|
|
@ -167,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')
|
||||
|
|
@ -204,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')
|
||||
|
|
@ -231,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')
|
||||
|
|
@ -242,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 */
|
||||
|
|
@ -273,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);
|
||||
|
||||
|
|
@ -293,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();
|
||||
|
|
@ -337,11 +342,28 @@ App::get('/v1/storage/files/:fileId/preview')
|
|||
$image = new Image($source);
|
||||
|
||||
$image->crop((int) $width, (int) $height);
|
||||
|
||||
if (!empty($opacity) || $opacity==0) {
|
||||
$image->setOpacity($opacity);
|
||||
}
|
||||
|
||||
if (!empty($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 = $image->output($output, $quality);
|
||||
|
|
@ -362,7 +384,7 @@ 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')
|
||||
|
|
@ -420,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')
|
||||
|
|
@ -489,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')
|
||||
|
|
@ -538,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')
|
||||
|
|
@ -581,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();
|
||||
|
|
@ -590,8 +612,8 @@ App::delete('/v1/storage/files/:fileId')
|
|||
// App::get('/v1/storage/files/:fileId/scan')
|
||||
// ->desc('Scan Storage')
|
||||
// ->groups(['api', 'storage'])
|
||||
// ->label('scope', 'god')
|
||||
// ->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
// ->label('scope', 'root')
|
||||
// ->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;
|
||||
|
|
@ -292,7 +294,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
}
|
||||
|
||||
$memberships = $projectDB->getCollection([
|
||||
'limit' => 50,
|
||||
'limit' => 2000,
|
||||
'offset' => 0,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_MEMBERSHIPS,
|
||||
|
|
@ -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 {
|
||||
|
|
@ -323,10 +341,16 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
'emailVerification' => false,
|
||||
'status' => Auth::USER_STATUS_UNACTIVATED,
|
||||
'password' => Auth::passwordHash(Auth::passwordGenerator()),
|
||||
'passwordUpdate' => \time(),
|
||||
/**
|
||||
* Set the password update time to 0 for users created using
|
||||
* team invite and OAuth to allow password updates without an
|
||||
* old password
|
||||
*/
|
||||
'passwordUpdate' => 0,
|
||||
'registration' => \time(),
|
||||
'reset' => false,
|
||||
'name' => $name,
|
||||
'sessions' => [],
|
||||
'tokens' => [],
|
||||
], ['email' => $email]);
|
||||
} catch (Duplicate $th) {
|
||||
|
|
@ -352,7 +376,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 +392,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());
|
||||
|
||||
|
|
@ -400,7 +424,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
}
|
||||
|
||||
$url = Template::parseURL($url);
|
||||
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['inviteId' => $membership->getId(), 'teamId' => $team->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]);
|
||||
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'teamId' => $team->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]);
|
||||
$url = Template::unParseURL($url);
|
||||
|
||||
$body = new Template(__DIR__.'/../../config/locale/templates/email-base.tpl');
|
||||
|
|
@ -425,9 +449,9 @@ 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 of confirmation when in admin or app mode
|
||||
$mails
|
||||
->setParam('event', 'teams.membership.create')
|
||||
->setParam('event', 'teams.memberships.create')
|
||||
->setParam('from', ($project->getId() === 'console') ? '' : \sprintf($locale->getText('account.emails.team'), $project->getAttribute('name')))
|
||||
->setParam('recipient', $email)
|
||||
->setParam('name', $name)
|
||||
|
|
@ -439,7 +463,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
|
||||
$audits
|
||||
->setParam('userId', $invitee->getId())
|
||||
->setParam('event', 'teams.membership.create')
|
||||
->setParam('event', 'teams.memberships.create')
|
||||
->setParam('resource', 'teams/'.$teamId)
|
||||
;
|
||||
|
||||
|
|
@ -452,11 +476,74 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
;
|
||||
});
|
||||
|
||||
App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->desc('Update Membership Roles')
|
||||
->groups(['api', 'teams'])
|
||||
->label('event', 'teams.memberships.update')
|
||||
->label('scope', 'teams.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'teams')
|
||||
->label('sdk.method', 'updateMembershipRoles')
|
||||
->label('sdk.description', '/docs/references/teams/update-team-membership-roles.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
|
||||
->param('teamId', '', new UID(), 'Team unique ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('roles', [], new ArrayList(new Key()), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('projectDB')
|
||||
->inject('audits')
|
||||
->action(function ($teamId, $membershipId, $roles, $request, $response, $user, $projectDB,$audits) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$team = $projectDB->getDocument($teamId);
|
||||
if (empty($team->getId()) || Database::SYSTEM_COLLECTION_TEAMS != $team->getCollection()) {
|
||||
throw new Exception('Team not found', 404);
|
||||
}
|
||||
|
||||
$membership = $projectDB->getDocument($membershipId);
|
||||
if (empty($membership->getId()) || Database::SYSTEM_COLLECTION_MEMBERSHIPS != $membership->getCollection()) {
|
||||
throw new Exception('Membership not found', 404);
|
||||
}
|
||||
|
||||
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
$isOwner = Authorization::isRole('team:'.$team->getId().'/owner');;
|
||||
|
||||
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
throw new Exception('User is not allowed to modify roles', 401);
|
||||
}
|
||||
|
||||
// Update the roles
|
||||
$membership->setAttribute('roles', $roles);
|
||||
$membership = $projectDB->updateDocument($membership->getArrayCopy());
|
||||
|
||||
if (false === $membership) {
|
||||
throw new Exception('Failed updating membership', 500);
|
||||
}
|
||||
|
||||
$audits
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', 'teams.memberships.update')
|
||||
->setParam('resource', 'teams/'.$teamId)
|
||||
;
|
||||
|
||||
$response->dynamic(new Document($membership->getArrayCopy()), Response::MODEL_MEMBERSHIP);
|
||||
});
|
||||
|
||||
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')
|
||||
|
|
@ -505,12 +592,12 @@ App::get('/v1/teams/:teamId/memberships')
|
|||
$response->dynamic(new Document(['sum' => $projectDB->getSum(), 'memberships' => $users]), Response::MODEL_MEMBERSHIP_LIST);
|
||||
});
|
||||
|
||||
App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||
App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
->desc('Update Team Membership 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')
|
||||
|
|
@ -518,7 +605,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
|
||||
->param('teamId', '', new UID(), 'Team unique ID.')
|
||||
->param('inviteId', '', new UID(), 'Invite unique ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('userId', '', new UID(), 'User unique ID.')
|
||||
->param('secret', '', new Text(256), 'Secret key.')
|
||||
->inject('request')
|
||||
|
|
@ -527,7 +614,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
->inject('projectDB')
|
||||
->inject('geodb')
|
||||
->inject('audits')
|
||||
->action(function ($teamId, $inviteId, $userId, $secret, $request, $response, $user, $projectDB, $geodb, $audits) {
|
||||
->action(function ($teamId, $membershipId, $userId, $secret, $request, $response, $user, $projectDB, $geodb, $audits) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
|
|
@ -536,7 +623,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
/** @var Appwrite\Event\Event $audits */
|
||||
|
||||
$protocol = $request->getProtocol();
|
||||
$membership = $projectDB->getDocument($inviteId);
|
||||
$membership = $projectDB->getDocument($membershipId);
|
||||
|
||||
if (empty($membership->getId()) || Database::SYSTEM_COLLECTION_MEMBERSHIPS != $membership->getCollection()) {
|
||||
throw new Exception('Invite not found', 404);
|
||||
|
|
@ -561,7 +648,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
}
|
||||
|
||||
if ($userId != $membership->getAttribute('userId')) {
|
||||
throw new Exception('Invite not belong to current user ('.$user->getAttribute('email').')', 401);
|
||||
throw new Exception('Invite does not belong to current user ('.$user->getAttribute('email').')', 401);
|
||||
}
|
||||
|
||||
if (empty($user->getId())) {
|
||||
|
|
@ -575,7 +662,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
}
|
||||
|
||||
if ($membership->getAttribute('userId') !== $user->getId()) {
|
||||
throw new Exception('Invite not belong to current user ('.$user->getAttribute('email').')', 401);
|
||||
throw new Exception('Invite does not belong to current user ('.$user->getAttribute('email').')', 401);
|
||||
}
|
||||
|
||||
$membership // Attach user to team
|
||||
|
|
@ -595,10 +682,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 +694,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);
|
||||
|
||||
|
|
@ -630,7 +718,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
|
||||
$audits
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', 'teams.membership.update')
|
||||
->setParam('event', 'teams.memberships.update.status')
|
||||
->setParam('resource', 'teams/'.$teamId)
|
||||
;
|
||||
|
||||
|
|
@ -651,30 +739,30 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
])), Response::MODEL_MEMBERSHIP);
|
||||
});
|
||||
|
||||
App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
||||
App::delete('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->desc('Delete Team Membership')
|
||||
->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')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('teamId', '', new UID(), 'Team unique ID.')
|
||||
->param('inviteId', '', new UID(), 'Invite unique ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
->inject('audits')
|
||||
->inject('events')
|
||||
->action(function ($teamId, $inviteId, $response, $projectDB, $audits, $events) {
|
||||
->action(function ($teamId, $membershipId, $response, $projectDB, $audits, $events) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $audits */
|
||||
/** @var Appwrite\Event\Event $events */
|
||||
|
||||
$membership = $projectDB->getDocument($inviteId);
|
||||
$membership = $projectDB->getDocument($membershipId);
|
||||
|
||||
if (empty($membership->getId()) || Database::SYSTEM_COLLECTION_MEMBERSHIPS != $membership->getCollection()) {
|
||||
throw new Exception('Invite not found', 404);
|
||||
|
|
@ -706,12 +794,12 @@ App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
|||
|
||||
$audits
|
||||
->setParam('userId', $membership->getAttribute('userId'))
|
||||
->setParam('event', 'teams.membership.delete')
|
||||
->setParam('event', 'teams.memberships.delete')
|
||||
->setParam('resource', 'teams/'.$teamId)
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('payload', $response->output($membership, Response::MODEL_MEMBERSHIP))
|
||||
->setParam('eventData', $response->output($membership, Response::MODEL_MEMBERSHIP))
|
||||
;
|
||||
|
||||
$response->noContent();
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator;
|
||||
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 +24,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 +82,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 +119,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,13 +146,13 @@ 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')
|
||||
->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_PREFERENCES)
|
||||
->param('userId', '', new UID(), 'User unique ID.')
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
|
|
@ -167,14 +168,14 @@ App::get('/v1/users/:userId/prefs')
|
|||
|
||||
$prefs = $user->getAttribute('prefs', new \stdClass());
|
||||
|
||||
$response->dynamic(new Document($prefs), Response::MODEL_ANY);
|
||||
$response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES);
|
||||
});
|
||||
|
||||
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 +197,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[strtoupper($token->getAttribute('countryCode'))]))
|
||||
? $countries[strtoupper($token->getAttribute('countryCode'))]
|
||||
$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 +221,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 +336,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')
|
||||
|
|
@ -346,7 +344,7 @@ App::patch('/v1/users/:userId/status')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_USER)
|
||||
->param('userId', '', new UID(), 'User unique ID.')
|
||||
->param('status', '', new WhiteList([Auth::USER_STATUS_ACTIVATED, Auth::USER_STATUS_BLOCKED, Auth::USER_STATUS_UNACTIVATED], true), 'User Status code. To activate the user pass '.Auth::USER_STATUS_ACTIVATED.', to block the user pass '.Auth::USER_STATUS_BLOCKED.' and for disabling the user pass '.Auth::USER_STATUS_UNACTIVATED)
|
||||
->param('status', '', new WhiteList([Auth::USER_STATUS_ACTIVATED, Auth::USER_STATUS_BLOCKED, Auth::USER_STATUS_UNACTIVATED], true, Validator::TYPE_INTEGER), 'User Status code. To activate the user pass '.Auth::USER_STATUS_ACTIVATED.', to block the user pass '.Auth::USER_STATUS_BLOCKED.' and for disabling the user pass '.Auth::USER_STATUS_UNACTIVATED)
|
||||
->inject('response')
|
||||
->inject('projectDB')
|
||||
->action(function ($userId, $status, $response, $projectDB) {
|
||||
|
|
@ -375,13 +373,13 @@ App::patch('/v1/users/:userId/prefs')
|
|||
->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')
|
||||
->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_PREFERENCES)
|
||||
->param('userId', '', new UID(), 'User unique ID.')
|
||||
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
|
||||
->inject('response')
|
||||
|
|
@ -404,7 +402,7 @@ App::patch('/v1/users/:userId/prefs')
|
|||
throw new Exception('Failed saving user to DB', 500);
|
||||
}
|
||||
|
||||
$response->dynamic(new Document($prefs), Response::MODEL_ANY);
|
||||
$response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES);
|
||||
});
|
||||
|
||||
App::delete('/v1/users/:userId/sessions/:sessionId')
|
||||
|
|
@ -412,7 +410,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')
|
||||
|
|
@ -434,16 +432,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))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -457,7 +457,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')
|
||||
|
|
@ -478,16 +478,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
|
||||
|
|
@ -499,10 +501,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.')
|
||||
|
|
@ -547,7 +549,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
|
||||
|
|
|
|||
|
|
@ -14,24 +14,69 @@ use Appwrite\Database\Database;
|
|||
use Appwrite\Database\Document;
|
||||
use Appwrite\Database\Validator\Authorization;
|
||||
use Appwrite\Network\Validator\Origin;
|
||||
use Utopia\Storage\Device\Local;
|
||||
use Utopia\Storage\Storage;
|
||||
use Appwrite\Utopia\Response\Filters\V06;
|
||||
use Appwrite\Utopia\Response\Filters\V07;
|
||||
use Utopia\CLI\Console;
|
||||
|
||||
Config::setParam('domainVerification', false);
|
||||
Config::setParam('cookieDomain', 'localhost');
|
||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||
|
||||
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $clients) {
|
||||
App::init(function ($utopia, $request, $response, $console, $project, $consoleDB, $user, $locale, $clients) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $consoleDB */
|
||||
/** @var Appwrite\Database\Document $console */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Database\Document $user */
|
||||
/** @var Utopia\Locale\Locale $locale */
|
||||
/** @var bool $mode */
|
||||
/** @var array $clients */
|
||||
|
||||
$domain = $request->getHostname();
|
||||
$domains = Config::getParam('domains', []);
|
||||
if (!array_key_exists($domain, $domains)) {
|
||||
$domain = new Domain(!empty($domain) ? $domain : '');
|
||||
|
||||
if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) {
|
||||
$domains[$domain->get()] = false;
|
||||
Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.');
|
||||
} else {
|
||||
Authorization::disable();
|
||||
$dbDomain = $consoleDB->getCollectionFirst([
|
||||
'limit' => 1,
|
||||
'offset' => 0,
|
||||
'filters' => [
|
||||
'$collection=' . Database::SYSTEM_COLLECTION_CERTIFICATES,
|
||||
'domain=' . $domain->get(),
|
||||
],
|
||||
]);
|
||||
|
||||
if (empty($dbDomain)) {
|
||||
$dbDomain = [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_CERTIFICATES,
|
||||
'$permissions' => [
|
||||
'read' => [],
|
||||
'write' => [],
|
||||
],
|
||||
'domain' => $domain->get(),
|
||||
];
|
||||
$dbDomain = $consoleDB->createDocument($dbDomain);
|
||||
Authorization::enable();
|
||||
|
||||
Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in a few seconds...'); // TODO move this to installation script
|
||||
|
||||
Resque::enqueue('v1-certificates', 'CertificatesV1', [
|
||||
'document' => $dbDomain,
|
||||
'domain' => $domain->get(),
|
||||
'validateTarget' => false,
|
||||
'validateCNAME' => false,
|
||||
]);
|
||||
}
|
||||
$domains[$domain->get()] = true;
|
||||
}
|
||||
Config::setParam('domains', $domains);
|
||||
}
|
||||
|
||||
$localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''));
|
||||
|
||||
|
|
@ -41,7 +86,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);
|
||||
}
|
||||
|
||||
|
|
@ -92,6 +137,9 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
case version_compare ($responseFormat , '0.6.2', '<=') :
|
||||
Response::setFilter(new V06());
|
||||
break;
|
||||
case version_compare ($responseFormat , '0.7.2', '<=') :
|
||||
Response::setFilter(new V07());
|
||||
break;
|
||||
default:
|
||||
Response::setFilter(null);
|
||||
}
|
||||
|
|
@ -208,7 +256,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
}
|
||||
}, $user->getAttribute('memberships', []));
|
||||
|
||||
// TDOO Check if user is god
|
||||
// TDOO Check if user is root
|
||||
|
||||
if (!\in_array($scope, $scopes)) {
|
||||
if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS !== $project->getCollection()) { // Check if permission is denied because project is missing
|
||||
|
|
@ -226,7 +274,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
|||
throw new Exception('Password reset is required', 412);
|
||||
}
|
||||
|
||||
}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'clients']);
|
||||
}, ['utopia', 'request', 'response', 'console', 'project', 'consoleDB', 'user', 'locale', 'clients']);
|
||||
|
||||
App::options(function ($request, $response) {
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
|
|
@ -271,7 +319,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
|
||||
|
|
@ -280,6 +328,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;
|
||||
|
|
@ -423,4 +472,4 @@ include_once __DIR__ . '/shared/web.php';
|
|||
|
||||
foreach (Config::getParam('services', []) as $service) {
|
||||
include_once $service['controller'];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@
|
|||
global $utopia, $request, $response;
|
||||
|
||||
use Appwrite\Database\Document;
|
||||
use Appwrite\Network\Validator\Host;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\App;
|
||||
use Utopia\Validator\Numeric;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Host;
|
||||
use Utopia\Storage\Validator\File;
|
||||
|
||||
App::get('/v1/mock/tests/foo')
|
||||
->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.')
|
||||
|
|
@ -33,7 +33,7 @@ App::post('/v1/mock/tests/foo')
|
|||
->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.')
|
||||
|
|
@ -51,7 +51,7 @@ App::patch('/v1/mock/tests/foo')
|
|||
->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 patch request.')
|
||||
|
|
@ -69,7 +69,7 @@ App::put('/v1/mock/tests/foo')
|
|||
->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.')
|
||||
|
|
@ -87,7 +87,7 @@ App::delete('/v1/mock/tests/foo')
|
|||
->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.')
|
||||
|
|
@ -105,7 +105,7 @@ App::get('/v1/mock/tests/bar')
|
|||
->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.')
|
||||
|
|
@ -123,7 +123,7 @@ App::post('/v1/mock/tests/bar')
|
|||
->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.')
|
||||
|
|
@ -141,7 +141,7 @@ App::patch('/v1/mock/tests/bar')
|
|||
->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 patch request.')
|
||||
|
|
@ -159,7 +159,7 @@ App::put('/v1/mock/tests/bar')
|
|||
->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.')
|
||||
|
|
@ -177,7 +177,7 @@ App::delete('/v1/mock/tests/bar')
|
|||
->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.')
|
||||
|
|
@ -195,7 +195,7 @@ App::post('/v1/mock/tests/general/upload')
|
|||
->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 file upload request.')
|
||||
|
|
@ -240,7 +240,7 @@ App::get('/v1/mock/tests/general/redirect')
|
|||
->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.')
|
||||
|
|
@ -258,7 +258,7 @@ App::get('/v1/mock/tests/general/redirect/done')
|
|||
->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.')
|
||||
|
|
@ -273,7 +273,7 @@ App::get('/v1/mock/tests/general/set-cookie')
|
|||
->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.')
|
||||
|
|
@ -292,7 +292,7 @@ App::get('/v1/mock/tests/general/get-cookie')
|
|||
->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 cookie response.')
|
||||
|
|
@ -313,7 +313,7 @@ App::get('/v1/mock/tests/general/empty')
|
|||
->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 an empty response.')
|
||||
|
|
@ -331,7 +331,7 @@ App::get('/v1/mock/tests/general/400-error')
|
|||
->desc('400 Error')
|
||||
->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', 'error400')
|
||||
->label('sdk.description', 'Mock a 400 failed request.')
|
||||
|
|
@ -347,7 +347,7 @@ App::get('/v1/mock/tests/general/500-error')
|
|||
->desc('500 Error')
|
||||
->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', 'error500')
|
||||
->label('sdk.description', 'Mock a 500 failed request.')
|
||||
|
|
@ -391,7 +391,7 @@ App::get('/v1/mock/tests/general/oauth2')
|
|||
->param('scope', '', new Text(100), 'OAuth2 scope list.')
|
||||
->param('state', '', new Text(1024), 'OAuth2 state.')
|
||||
->inject('response')
|
||||
->action(function ($clientId, $redirectURI, $scope, $state, $response) {
|
||||
->action(function ($client_id, $redirectURI, $scope, $state, $response) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
|
||||
$response->redirect($redirectURI.'?'.\http_build_query(['code' => 'abcdef', 'state' => $state]));
|
||||
|
|
@ -408,14 +408,14 @@ App::get('/v1/mock/tests/general/oauth2/token')
|
|||
->param('client_secret', '', new Text(100), 'OAuth2 scope list.')
|
||||
->param('code', '', new Text(100), 'OAuth2 state.')
|
||||
->inject('response')
|
||||
->action(function ($clientId, $redirectURI, $clientSecret, $code, $response) {
|
||||
->action(function ($client_id, $redirectURI, $client_secret, $code, $response) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
|
||||
if ($clientId != '1') {
|
||||
if ($client_id != '1') {
|
||||
throw new Exception('Invalid client ID');
|
||||
}
|
||||
|
||||
if ($clientSecret != '123456') {
|
||||
if ($client_secret != '123456') {
|
||||
throw new Exception('Invalid client secret');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -76,9 +76,10 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
|
|||
*/
|
||||
$events
|
||||
->setParam('projectId', $project->getId())
|
||||
->setParam('webhooks', $project->getAttribute('webhooks', []))
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('event', $route->getLabel('event', ''))
|
||||
->setParam('payload', [])
|
||||
->setParam('eventData', [])
|
||||
->setParam('functionId', null)
|
||||
->setParam('executionId', null)
|
||||
->setParam('trigger', 'event')
|
||||
|
|
@ -110,6 +111,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 +179,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;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ App::init(function ($utopia, $request, $response, $layout) {
|
|||
['type' => 'developer', 'label' => 'Developer'],
|
||||
['type' => 'admin', 'label' => 'Admin'],
|
||||
])
|
||||
->setParam('environments', Config::getParam('environments'))
|
||||
->setParam('runtimes', Config::getParam('runtimes'))
|
||||
->setParam('mode', App::getMode())
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
@ -370,7 +373,7 @@ App::get('/console/functions')
|
|||
$page = new View(__DIR__.'/../../views/console/functions/index.phtml');
|
||||
|
||||
$page
|
||||
->setParam('environments', Config::getParam('environments'))
|
||||
->setParam('runtimes', Config::getParam('runtimes'))
|
||||
;
|
||||
|
||||
$layout
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Database\Database;
|
||||
use Appwrite\Specification\Format\OpenAPI3;
|
||||
use Appwrite\Specification\Format\Swagger2;
|
||||
use Appwrite\Specification\Specification;
|
||||
|
|
@ -42,10 +43,38 @@ App::get('/')
|
|||
->label('permission', 'public')
|
||||
->label('scope', 'home')
|
||||
->inject('response')
|
||||
->action(function ($response) {
|
||||
->inject('consoleDB')
|
||||
->inject('project')
|
||||
->action(function ($response, $consoleDB, $project) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $consoleDB */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
|
||||
$response->redirect('/auth/signin');
|
||||
$response
|
||||
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
|
||||
->addHeader('Expires', 0)
|
||||
->addHeader('Pragma', 'no-cache')
|
||||
;
|
||||
|
||||
if ('console' === $project->getId() || $project->isEmpty()) {
|
||||
$whitlistRoot = App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled');
|
||||
|
||||
if($whitlistRoot !== 'disabled') {
|
||||
$consoleDB->getCollection([ // Count users
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
],
|
||||
]);
|
||||
|
||||
$sum = $consoleDB->getSum();
|
||||
|
||||
if($sum !== 0) {
|
||||
return $response->redirect('/auth/signin');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response->redirect('/auth/signup');
|
||||
});
|
||||
|
||||
App::get('/auth/signin')
|
||||
|
|
@ -58,6 +87,10 @@ App::get('/auth/signin')
|
|||
|
||||
$page = new View(__DIR__.'/../../views/home/auth/signin.phtml');
|
||||
|
||||
$page
|
||||
->setParam('root', App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled'))
|
||||
;
|
||||
|
||||
$layout
|
||||
->setParam('title', 'Sign In - '.APP_NAME)
|
||||
->setParam('body', $page);
|
||||
|
|
@ -72,6 +105,10 @@ App::get('/auth/signup')
|
|||
/** @var Utopia\View $layout */
|
||||
$page = new View(__DIR__.'/../../views/home/auth/signup.phtml');
|
||||
|
||||
$page
|
||||
->setParam('root', App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled'))
|
||||
;
|
||||
|
||||
$layout
|
||||
->setParam('title', 'Sign Up - '.APP_NAME)
|
||||
->setParam('body', $page);
|
||||
|
|
@ -87,6 +124,10 @@ App::get('/auth/recovery')
|
|||
|
||||
$page = new View(__DIR__.'/../../views/home/auth/recovery.phtml');
|
||||
|
||||
$page
|
||||
->setParam('smtpEnabled', (!empty(App::getEnv('_APP_SMTP_HOST'))))
|
||||
;
|
||||
|
||||
$layout
|
||||
->setParam('title', 'Password Recovery - '.APP_NAME)
|
||||
->setParam('body', $page);
|
||||
|
|
@ -214,6 +255,12 @@ App::get('/specs/:format')
|
|||
'console' => APP_PLATFORM_CONSOLE,
|
||||
];
|
||||
|
||||
$authCounts = [
|
||||
'client' => 1,
|
||||
'server' => 2,
|
||||
'console' => 1,
|
||||
];
|
||||
|
||||
$routes = [];
|
||||
$models = [];
|
||||
$services = [];
|
||||
|
|
@ -226,6 +273,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',
|
||||
|
|
@ -246,6 +299,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',
|
||||
|
|
@ -266,6 +325,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',
|
||||
|
|
@ -281,14 +346,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;
|
||||
}
|
||||
|
|
@ -305,7 +388,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;
|
||||
}
|
||||
|
||||
|
|
@ -342,11 +425,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], $authCounts[$platform] ?? 0);
|
||||
break;
|
||||
|
||||
case 'open-api3':
|
||||
$format = new OpenAPI3($utopia, $services, $routes, $models, $keys[$platform], $security[$platform]);
|
||||
$format = new OpenAPI3($utopia, $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
14
app/http.php
14
app/http.php
|
|
@ -12,6 +12,8 @@ use Swoole\Http\Request as SwooleRequest;
|
|||
use Swoole\Http\Response as SwooleResponse;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Domains\Domain;
|
||||
|
||||
// xdebug_start_trace('/tmp/trace');
|
||||
|
||||
|
|
@ -65,18 +67,6 @@ Files::load(__DIR__ . '/../public');
|
|||
|
||||
include __DIR__ . '/controllers/general.php';
|
||||
|
||||
$domain = App::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
Console::info('Issuing a TLS certificate for the master domain ('.$domain.') in 30 seconds.
|
||||
Make sure your domain points to your server IP or restart your Appwrite server to try again.'); // TODO move this to installation script
|
||||
|
||||
ResqueScheduler::enqueueAt(\time() + 30, 'v1-certificates', 'CertificatesV1', [
|
||||
'document' => [],
|
||||
'domain' => $domain,
|
||||
'validateTarget' => false,
|
||||
'validateCNAME' => false,
|
||||
]);
|
||||
|
||||
$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) {
|
||||
$request = new Request($swooleRequest);
|
||||
$response = new Response($swooleResponse);
|
||||
|
|
|
|||
19
app/init.php
19
app/init.php
|
|
@ -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 = 145;
|
||||
const APP_VERSION_STABLE = '0.7.2';
|
||||
const APP_CACHE_BUSTER = 146;
|
||||
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';
|
||||
|
|
@ -62,6 +62,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();
|
||||
|
||||
|
|
@ -71,10 +76,11 @@ 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');
|
||||
Config::load('environments', __DIR__.'/config/environments.php');
|
||||
Config::load('runtimes', __DIR__.'/config/runtimes.php');
|
||||
Config::load('roles', __DIR__.'/config/roles.php'); // User roles and scopes
|
||||
Config::load('scopes', __DIR__.'/config/scopes.php'); // User roles and scopes
|
||||
Config::load('services', __DIR__.'/config/services.php'); // List of services
|
||||
|
|
@ -164,8 +170,9 @@ $register->set('influxdb', function () { // Register DB connection
|
|||
if (empty($host) || empty($port)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$driver = new InfluxDB\Driver\Curl("http://{$host}:{$port}");
|
||||
$client = new InfluxDB\Client($host, $port, '', '', false, false, 5);
|
||||
$client->setDriver($driver);
|
||||
|
||||
return $client;
|
||||
});
|
||||
|
|
@ -314,7 +321,7 @@ App::setResource('layout', function($locale) {
|
|||
}, ['locale']);
|
||||
|
||||
App::setResource('locale', function() {
|
||||
return new Locale('en');
|
||||
return new Locale(App::getEnv('_APP_LOCALE', 'en'));
|
||||
});
|
||||
|
||||
// Queues
|
||||
|
|
@ -420,7 +427,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]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,12 +61,12 @@ $cli
|
|||
Console::log('🟢 Abuse protection is enabled');
|
||||
}
|
||||
|
||||
$authWhitelistRoot = App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', null);
|
||||
$authWhitelistEmails = App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null);
|
||||
$authWhitelistIPs = App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null);
|
||||
$authWhitelistDomains = App::getEnv('_APP_CONSOLE_WHITELIST_DOMAINS', null);
|
||||
|
||||
if(empty($authWhitelistEmails)
|
||||
&& empty($authWhitelistDomains)
|
||||
if(empty($authWhitelistRoot)
|
||||
&& empty($authWhitelistEmails)
|
||||
&& empty($authWhitelistIPs)
|
||||
) {
|
||||
Console::log('🔴 Console access limits are disabled');
|
||||
|
|
|
|||
|
|
@ -2,17 +2,24 @@
|
|||
|
||||
global $cli;
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Docker\Compose;
|
||||
use Appwrite\Docker\Env;
|
||||
use Utopia\Analytics\GoogleAnalytics;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\View;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
$cli
|
||||
->task('install')
|
||||
->desc('Install Appwrite')
|
||||
->action(function () {
|
||||
->param('httpPort', '', new Text(4), 'Server HTTP port', true)
|
||||
->param('httpsPort', '', new Text(4), 'Server HTTPS port', true)
|
||||
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
|
||||
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
|
||||
->param('interactive','Y', new Text(1), 'Run an interactive session', true)
|
||||
->action(function ($httpPort, $httpsPort, $organization, $image, $interactive) {
|
||||
/**
|
||||
* 1. Start - DONE
|
||||
* 2. Check for older setup and get older version - DONE
|
||||
|
|
@ -60,6 +67,9 @@ $cli
|
|||
$data = @file_get_contents($path.'/docker-compose.yml');
|
||||
|
||||
if($data !== false) {
|
||||
$time = \time();
|
||||
Console::info('Compose file found, creating backup: docker-compose.yml.'.$time.'.backup');
|
||||
file_put_contents($path.'/docker-compose.yml.'.$time.'.backup',$data);
|
||||
$compose = new Compose($data);
|
||||
$appwrite = $compose->getService('appwrite');
|
||||
$oldVersion = ($appwrite) ? $appwrite->getImageVersion() : null;
|
||||
|
|
@ -85,6 +95,8 @@ $cli
|
|||
$data = @file_get_contents($path.'/.env');
|
||||
|
||||
if($data !== false) { // Fetch all env vars from previous .env file
|
||||
Console::info('Env file found, creating backup: .env.'.$time.'.backup');
|
||||
file_put_contents($path.'/.env.'.$time.'.backup',$data);
|
||||
$env = new Env($data);
|
||||
|
||||
foreach ($env->list() as $key => $value) {
|
||||
|
|
@ -108,16 +120,36 @@ $cli
|
|||
}
|
||||
}
|
||||
|
||||
$httpPort = Console::confirm('Choose your server HTTP port: (default: '.$defaultHTTPPort.')');
|
||||
$httpPort = ($httpPort) ? $httpPort : $defaultHTTPPort;
|
||||
if(empty($httpPort)) {
|
||||
$httpPort = Console::confirm('Choose your server HTTP port: (default: '.$defaultHTTPPort.')');
|
||||
$httpPort = ($httpPort) ? $httpPort : $defaultHTTPPort;
|
||||
}
|
||||
|
||||
$httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')');
|
||||
$httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPSPort;
|
||||
if(empty($httpsPort)) {
|
||||
$httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')');
|
||||
$httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPSPort;
|
||||
}
|
||||
|
||||
$input = [];
|
||||
|
||||
foreach($vars as $key => $var) {
|
||||
if(!$var['required']) {
|
||||
if(!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) {
|
||||
if($data && $var['default'] !== null) {
|
||||
$input[$var['name']] = $var['default'];
|
||||
continue;
|
||||
}
|
||||
|
||||
if($var['filter'] === 'token') {
|
||||
$input[$var['name']] = Auth::tokenGenerator();
|
||||
continue;
|
||||
}
|
||||
|
||||
if($var['filter'] === 'password') {
|
||||
$input[$var['name']] = Auth::passwordGenerator();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(!$var['required'] || !Console::isInteractive() || $interactive !== 'Y') {
|
||||
$input[$var['name']] = $var['default'];
|
||||
continue;
|
||||
}
|
||||
|
|
@ -136,6 +168,8 @@ $cli
|
|||
->setParam('httpPort', $httpPort)
|
||||
->setParam('httpsPort', $httpsPort)
|
||||
->setParam('version', APP_VERSION_STABLE)
|
||||
->setParam('organization', $organization)
|
||||
->setParam('image', $image)
|
||||
;
|
||||
|
||||
$templateForEnv
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -21,20 +21,6 @@ use Appwrite\SDK\Language\Swift;
|
|||
$cli
|
||||
->task('sdks')
|
||||
->action(function () {
|
||||
function getSSLPage($url)
|
||||
{
|
||||
$ch = \curl_init();
|
||||
\curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
\curl_setopt($ch, CURLOPT_URL, $url);
|
||||
\curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
\curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$result = \curl_exec($ch);
|
||||
\curl_close($ch);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$platforms = Config::getParam('platforms');
|
||||
$selected = \strtolower(Console::confirm('Choose SDK ("*" for all):'));
|
||||
$version = Console::confirm('Choose an Appwrite version');
|
||||
|
|
@ -42,7 +28,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.x', '0.7.x'])) {
|
||||
if(!in_array($version, ['0.6.x', '0.7.x', '0.8.x'])) {
|
||||
throw new Exception('Unknown version given');
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +179,9 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
->setExamples($examples)
|
||||
->setTwitter(APP_SOCIAL_TWITTER_HANDLE)
|
||||
->setDiscord(APP_SOCIAL_DISCORD_CHANNEL, APP_SOCIAL_DISCORD)
|
||||
->setDefaultHeaders([
|
||||
'X-Appwrite-Response-Format' => '0.8.0',
|
||||
])
|
||||
;
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
$home = $this->getParam('home', '');
|
||||
$version = $this->getParam('version', '').'.'.APP_CACHE_BUSTER;
|
||||
$version = $this->getParam('version', '') . '.' . APP_CACHE_BUSTER;
|
||||
?>
|
||||
<footer class="clear margin-top-large">
|
||||
<ul class="copyright pull-start">
|
||||
|
|
@ -12,6 +12,14 @@ $version = $this->getParam('version', '').'.'.APP_CACHE_BUSTER;
|
|||
data-analytics-label="GitHub Link"
|
||||
href="https://github.com/appwrite/appwrite" target="_blank" rel="noopener"><i class="icon-github-circled"></i> GitHub</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="link-animation-enabled"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/footer"
|
||||
data-analytics-label="Discord Link"
|
||||
href="https://appwrite.io/discord" target="_blank" rel="noopener"><i class="icon-discord"></i> Discord</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="link-animation-enabled"
|
||||
data-analytics
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -46,28 +46,13 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
|||
|
||||
<div class="box margin-bottom-large">
|
||||
<div class="text-align-center">
|
||||
<img src="" data-ls-attrs="src=/images/environments/{{project-function.env|envLogo}}" alt="Function Env." class="avatar huge margin-top-negative-xxl" />
|
||||
<img src="" data-ls-attrs="src=/images/runtimes/{{project-function.env|envLogo}}" alt="Function Env." class="avatar huge margin-top-negative-xxl" />
|
||||
|
||||
<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>
|
||||
|
||||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
$environments = $this->getParam('environments', []);
|
||||
$runtimes = $this->getParam('runtimes', []);
|
||||
?>
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
|
|
@ -40,7 +40,7 @@ $environments = $this->getParam('environments', []);
|
|||
<ul data-ls-loop="project-functions.functions" data-ls-as="function" class="list">
|
||||
<li class="clear">
|
||||
<div class="pull-start margin-end avatar-container">
|
||||
<img src="" data-ls-attrs="src=/images/environments/{{function.env|envLogo}}?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Function Env." class="avatar" loading="lazy" width="60" height="60" />
|
||||
<img src="" data-ls-attrs="src=/images/runtimes/{{function.env|envLogo}}?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Function Env." class="avatar" loading="lazy" width="60" height="60" />
|
||||
</div>
|
||||
|
||||
<a data-ls-attrs="href=/console/functions/function?id={{function.$id}}&project={{router.params.project}}" class="button pull-end">Settings</a>
|
||||
|
|
@ -109,10 +109,10 @@ $environments = $this->getParam('environments', []);
|
|||
<label for="name">Name</label>
|
||||
<input type="text" id="name" name="name" required autocomplete="off" class="margin-bottom" maxlength="128" />
|
||||
|
||||
<label for="env">Environment</label>
|
||||
<label for="env">Runtimes</label>
|
||||
<select name="env" id="env" required class="margin-bottom-xl">
|
||||
<?php foreach($environments as $key => $environment): ?>
|
||||
<option value="<?php echo $this->escape($key); ?>"><?php echo $this->escape($environment['name']); ?> <?php echo $this->escape($environment['version']); ?></option>
|
||||
<?php foreach($runtimes as $key => $runtime): ?>
|
||||
<option value="<?php echo $this->escape($key); ?>"><?php echo $this->escape($runtime['name']); ?> <?php echo $this->escape($runtime['version']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
|||
|
||||
<div class="chart-metric">
|
||||
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.requests.total|statsTotal}}">N/A</span></div>
|
||||
<div class="metric margin-bottom-small">Requests <span class="tooltip" data-tooltip="Total number of API requests last 30 days"><i class="icon-info-circled"></i></span></div>
|
||||
<div class="metric margin-bottom-small">Requests <span class="tooltip" data-tooltip="Total number of API requests"><i class="icon-info-circled"></i></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col span-3">
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
|
|||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input name="teamId" data-ls-attrs="id=leave-teamId-{{member.$id}}" type="hidden" data-ls-bind="{{console-project.teamId}}">
|
||||
<input name="inviteId" data-ls-attrs="id=leave-inviteId-{{member.$id}}" type="hidden" data-ls-bind="{{member.$id}}">
|
||||
<input name="membershipId" data-ls-attrs="id=leave-membershipId-{{member.$id}}" type="hidden" data-ls-bind="{{member.$id}}">
|
||||
|
||||
<button class="danger">Leave</button>
|
||||
</form>
|
||||
|
|
@ -437,7 +437,7 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
|
|||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input name="teamId" data-ls-attrs="id=resend-teamId-{{member.$id}}" type="hidden" data-ls-bind="{{console-project.teamId}}">
|
||||
<input name="inviteId" data-ls-attrs="id=resend-inviteId-{{member.$id}}" type="hidden" data-ls-bind="{{member.$id}}">
|
||||
<input name="membershipId" data-ls-attrs="id=resend-membershipId-{{member.$id}}" type="hidden" data-ls-bind="{{member.$id}}">
|
||||
|
||||
<button class="reverse">Resend</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -215,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"
|
||||
|
|
@ -244,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"
|
||||
|
|
@ -111,7 +77,7 @@ $providers = $this->getParam('providers', []);
|
|||
<td data-title="Name: ">
|
||||
<a data-ls-attrs="href=/console/users/user?id={{user.$id}}&project={{router.params.project}}">
|
||||
<span data-ls-bind="{{user.name}}"></span>
|
||||
<span data-ls-if="{{user.name}} === ''">-----</span>
|
||||
<span data-ls-if="{{user.name|escape}} === ''">-----</span>
|
||||
</a>
|
||||
</td>
|
||||
<td data-title="Email: ">
|
||||
|
|
@ -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,9 +411,10 @@ $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
|
||||
autocomplete="off"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
|
|
@ -338,6 +430,10 @@ $providers = $this->getParam('providers', []);
|
|||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to update project OAuth2 settings"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input style="display: none" type="text" /> <?php /** Disabling Chrone Autofill @see https://stackoverflow.com/a/15917221/2299554 */ ?>
|
||||
<input style="display: none" type="password" /> <?php /** Disabling Chrone Autofill @see https://stackoverflow.com/a/15917221/2299554 */ ?>
|
||||
|
||||
<input name="provider" id="provider<?php echo $this->escape(ucfirst($provider)); ?>" type="hidden" autocomplete="off" value="<?php echo $this->escape($provider); ?>">
|
||||
|
||||
<?php if(!$form): ?>
|
||||
|
|
@ -383,10 +479,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">
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@
|
|||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input name="teamId" data-ls-attrs="id={{member.$id}}" type="hidden" data-ls-bind="{{router.params.id}}">
|
||||
<input name="inviteId" data-ls-attrs="id=leave-inviteId-{{member.$id}}" type="hidden" data-ls-bind="{{member.$id}}">
|
||||
<input name="membershipId" data-ls-attrs="id=leave-membershipId-{{member.$id}}" type="hidden" data-ls-bind="{{member.$id}}">
|
||||
|
||||
<button class="danger">Remove</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
data-scope="console"
|
||||
data-event="submit"
|
||||
data-param-team-id="{{router.params.teamId}}"
|
||||
data-param-invite-id="{{router.params.inviteId}}"
|
||||
data-param-invite-id="{{router.params.membershipId}}"
|
||||
data-param-user-id="{{router.params.userId}}"
|
||||
data-param-secret="{{router.params.secret}}"
|
||||
data-success="redirect,alert,trigger"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
<?php
|
||||
$smtpEnabled = $this->getParam('smtpEnabled', false);
|
||||
?>
|
||||
<div class="zone medium">
|
||||
<h1 class="zone xl margin-bottom-large margin-top">
|
||||
Password Recovery
|
||||
|
|
@ -25,7 +28,13 @@
|
|||
|
||||
<input name="url" type="hidden" data-ls-bind="{{env.ENDPOINT}}/auth/recovery/reset" />
|
||||
|
||||
<button type="submit" class="btn btn-primary"><i class="fa fa-sign-in"></i> Recover</button>
|
||||
<?php if(!$smtpEnabled): ?>
|
||||
<div class="box note padding-tiny warning margin-bottom text-align-center">
|
||||
<i class="icon-warning"></i> SMTP connection is disabled. <a href="https://appwrite.io/docs/email-delivery" target="_blank" rel="noopener">Learn more <i class="icon-link-ext"></i></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<button type="submit" class="btn btn-primary"<?php if(!$smtpEnabled): ?> disabled<?php endif; ?>><i class="fa fa-sign-in"></i> Recover</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
<?php
|
||||
$root = ($this->getParam('root') !== 'disabled');
|
||||
?>
|
||||
<div class="zone medium"
|
||||
data-service="account.get"
|
||||
data-name="account"
|
||||
|
|
@ -43,7 +46,7 @@
|
|||
<br />
|
||||
|
||||
<div class="text-line-high-large text-align-center">
|
||||
<a href="/auth/recovery">Forgot password?</a> or don't have an account? <b><a href="/auth/signup">Sign up now</a></b>
|
||||
<a href="/auth/recovery">Forgot password?</a><?php if(!$root): ?> or don't have an account? <b><a href="/auth/signup">Sign up now</a></b><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
<div class="zone medium signup">
|
||||
<?php
|
||||
$root = ($this->getParam('root') !== 'disabled');
|
||||
?>
|
||||
<div class="zone medium signup"
|
||||
data-service="account.get"
|
||||
data-name="account"
|
||||
data-scope="console"
|
||||
data-event="load"
|
||||
data-success="redirect"
|
||||
data-success-param-redirect-url="/console"
|
||||
data-success-param-trigger-events="account.get">
|
||||
<h1 class="zone xl margin-bottom-large margin-top">
|
||||
Sign Up
|
||||
</h1>
|
||||
|
|
@ -9,6 +19,7 @@
|
|||
|
||||
<form name="account.create"
|
||||
data-analytics
|
||||
data-newsletter
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="home"
|
||||
|
|
@ -23,6 +34,10 @@
|
|||
data-failure-param-alert-text="Registration Failed. Please try again later"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<?php if($root): ?>
|
||||
<p>Please create your root account</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<label>Name</label>
|
||||
<input name="name" type="text" autocomplete="name" placeholder="" required maxlength="128">
|
||||
|
||||
|
|
@ -39,11 +54,20 @@
|
|||
By signing up, you agree to the <a data-ls-attrs="href={{env.HOME}}/policy/terms" tabindex="-1" target="_blank" rel="noopener">Terms and Conditions</a> and <a data-ls-attrs="href={{env.HOME}}/policy/privacy" target="_blank" tabindex="-1" rel="noopener">Privacy Policy</a>
|
||||
</div>
|
||||
|
||||
<div class="newsletter margin-top margin-bottom-large">
|
||||
<div class="pull-start margin-end-small margin-bottom">
|
||||
<input id="newsletter" type="checkbox" />
|
||||
</div>
|
||||
Sign up for our <a data-ls-attrs="href={{env.HOME}}/updates" tabindex="-1" target="_blank" rel="noopener">monthly newsletter</a> <span class="text-fade">(optional)</span>.
|
||||
</div>
|
||||
|
||||
<button type="submit">Sign Up</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<?php if(!$root): ?>
|
||||
<div class="zone medium text-align-center">
|
||||
<a href="/auth/signin">Already have an account?</a>
|
||||
</div>
|
||||
</div>
|
||||
<?PHP endif; ?>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
$httpPort = $this->getParam('httpPort', '');
|
||||
$httpsPort = $this->getParam('httpsPort', '');
|
||||
$version = $this->getParam('version', '');
|
||||
$organization = $this->getParam('organization', '');
|
||||
$image = $this->getParam('image', '');
|
||||
?>version: '3'
|
||||
|
||||
services:
|
||||
|
|
@ -32,7 +34,7 @@ services:
|
|||
- appwrite
|
||||
|
||||
appwrite:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
container_name: appwrite
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
|
@ -52,10 +54,12 @@ services:
|
|||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
- clamav
|
||||
# - clamav
|
||||
- influxdb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_LOCALE
|
||||
- _APP_CONSOLE_WHITELIST_ROOT
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||
- _APP_CONSOLE_WHITELIST_IPS
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
|
|
@ -93,10 +97,10 @@ services:
|
|||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_MEMORY_SWAP
|
||||
- _APP_FUNCTIONS_ENVS
|
||||
- _APP_FUNCTIONS_RUNTIMES
|
||||
|
||||
appwrite-worker-usage:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-usage
|
||||
container_name: appwrite-worker-usage
|
||||
restart: unless-stopped
|
||||
|
|
@ -115,7 +119,7 @@ services:
|
|||
- _APP_STATSD_PORT
|
||||
|
||||
appwrite-worker-audits:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-audits
|
||||
container_name: appwrite-worker-audits
|
||||
restart: unless-stopped
|
||||
|
|
@ -137,7 +141,7 @@ services:
|
|||
- _APP_DB_PASS
|
||||
|
||||
appwrite-worker-webhooks:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-webhooks
|
||||
container_name: appwrite-worker-webhooks
|
||||
restart: unless-stopped
|
||||
|
|
@ -153,14 +157,9 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
|
||||
appwrite-worker-tasks:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-tasks
|
||||
container_name: appwrite-worker-tasks
|
||||
restart: unless-stopped
|
||||
|
|
@ -171,6 +170,7 @@ services:
|
|||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -183,7 +183,7 @@ services:
|
|||
- _APP_DB_PASS
|
||||
|
||||
appwrite-worker-deletes:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-deletes
|
||||
container_name: appwrite-worker-deletes
|
||||
restart: unless-stopped
|
||||
|
|
@ -209,7 +209,7 @@ services:
|
|||
- _APP_DB_PASS
|
||||
|
||||
appwrite-worker-certificates:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-certificates
|
||||
container_name: appwrite-worker-certificates
|
||||
restart: unless-stopped
|
||||
|
|
@ -236,7 +236,7 @@ services:
|
|||
- _APP_DB_PASS
|
||||
|
||||
appwrite-worker-functions:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-functions
|
||||
container_name: appwrite-worker-functions
|
||||
restart: unless-stopped
|
||||
|
|
@ -251,6 +251,7 @@ services:
|
|||
- /tmp:/tmp:rw
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -265,10 +266,11 @@ services:
|
|||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_MEMORY_SWAP
|
||||
- _APP_FUNCTIONS_RUNTIMES
|
||||
- _APP_USAGE_STATS
|
||||
|
||||
appwrite-worker-mails:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-mails
|
||||
container_name: appwrite-worker-mails
|
||||
restart: unless-stopped
|
||||
|
|
@ -291,7 +293,7 @@ services:
|
|||
- _APP_SMTP_PASSWORD
|
||||
|
||||
appwrite-maintenance:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: maintenance
|
||||
container_name: appwrite-maintenance
|
||||
restart: unless-stopped
|
||||
|
|
@ -312,7 +314,7 @@ services:
|
|||
|
||||
|
||||
appwrite-schedule:
|
||||
image: appwrite/appwrite:<?php echo $version."\n"; ?>
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: schedule
|
||||
container_name: appwrite-schedule
|
||||
restart: unless-stopped
|
||||
|
|
@ -336,7 +338,7 @@ services:
|
|||
volumes:
|
||||
- appwrite-mariadb:/var/lib/mysql:rw
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=rootsecretpassword
|
||||
- MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
|
||||
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
|
||||
- MYSQL_USER=${_APP_DB_USER}
|
||||
- MYSQL_PASSWORD=${_APP_DB_PASS}
|
||||
|
|
@ -351,17 +353,17 @@ 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
|
||||
image: appwrite/influxdb:1.0.0
|
||||
container_name: appwrite-influxdb
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ $analytics = $this->getParam('analytics', 'UA-26264668-9');
|
|||
$mode = $this->getParam('mode', '');
|
||||
$canonical = $this->getParam('canonical', '');
|
||||
$locale = $this->getParam('locale', null);
|
||||
$environments = $this->getParam('environments', null);
|
||||
$runtimes = $this->getParam('runtimes', null);
|
||||
|
||||
if(!empty($platforms)) {
|
||||
$platforms = array_map(function($platform) {
|
||||
|
|
@ -78,7 +78,7 @@ if(!empty($platforms)) {
|
|||
SETUP: '<?php echo $this->escape($this->getParam('setup')); ?>',
|
||||
API: '/v1',
|
||||
PROJECT: 'console',
|
||||
ENVIRONMENTS: <?php echo json_encode($environments); ?>,
|
||||
RUNTIMES: <?php echo json_encode($runtimes); ?>,
|
||||
PLATFORMS: <?php echo json_encode($platforms); ?>,
|
||||
LOCALE: '<?php echo $this->escape($locale->getText('settings.locale')); ?>',
|
||||
PREFIX: '<?php echo $this->escape($this->getParam('prefix')); ?>',
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -14,21 +14,19 @@ use Utopia\Config\Config;
|
|||
|
||||
require_once __DIR__.'/../init.php';
|
||||
|
||||
Runtime::enableCoroutine(0);
|
||||
|
||||
Console::title('Functions V1 Worker');
|
||||
|
||||
Runtime::setHookFlags(SWOOLE_HOOK_ALL);
|
||||
|
||||
Console::success(APP_NAME.' functions worker v1 has started');
|
||||
|
||||
$environments = Config::getParam('environments');
|
||||
$runtimes = Config::getParam('runtimes');
|
||||
|
||||
/**
|
||||
* Warmup Docker Images
|
||||
*/
|
||||
$warmupStart = \microtime(true);
|
||||
|
||||
Co\run(function() use ($environments) { // Warmup: make sure images are ready to run fast 🚀
|
||||
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
||||
Co\run(function() use ($runtimes) { // Warmup: make sure images are ready to run fast 🚀
|
||||
|
||||
$dockerUser = App::getEnv('DOCKERHUB_PULL_USERNAME', null);
|
||||
$dockerPass = App::getEnv('DOCKERHUB_PULL_PASSWORD', null);
|
||||
|
|
@ -41,14 +39,14 @@ Co\run(function() use ($environments) { // Warmup: make sure images are ready t
|
|||
Console::log('Docker Login'. $stdout.$stderr);
|
||||
}
|
||||
|
||||
foreach($environments as $environment) {
|
||||
go(function() use ($environment) {
|
||||
foreach($runtimes as $runtime) {
|
||||
go(function() use ($runtime) {
|
||||
$stdout = '';
|
||||
$stderr = '';
|
||||
|
||||
Console::info('Warming up '.$environment['name'].' '.$environment['version'].' environment...');
|
||||
Console::info('Warming up '.$runtime['name'].' '.$runtime['version'].' environment...');
|
||||
|
||||
Console::execute('docker pull '.$environment['image'], '', $stdout, $stderr);
|
||||
Console::execute('docker pull '.$runtime['image'], '', $stdout, $stderr);
|
||||
|
||||
if(!empty($stdout)) {
|
||||
Console::log($stdout);
|
||||
|
|
@ -143,11 +141,15 @@ class FunctionsV1
|
|||
|
||||
$projectId = $this->args['projectId'] ?? '';
|
||||
$functionId = $this->args['functionId'] ?? '';
|
||||
$webhooks = $this->args['webhooks'] ?? [];
|
||||
$executionId = $this->args['executionId'] ?? '';
|
||||
$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 +197,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, $webhooks, $userId, $jwt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -245,14 +247,14 @@ class FunctionsV1
|
|||
|
||||
ResqueScheduler::enqueueAt($next, 'v1-functions', 'FunctionsV1', [
|
||||
'projectId' => $projectId,
|
||||
'webhooks' => $webhooks,
|
||||
'functionId' => $function->getId(),
|
||||
'executionId' => null,
|
||||
'trigger' => 'schedule',
|
||||
'scheduleOriginal' => $function->getAttribute('schedule', ''),
|
||||
]); // Async task rescheduale
|
||||
|
||||
$this->execute($trigger, $projectId, $executionId, $database, $function);
|
||||
|
||||
$this->execute($trigger, $projectId, $executionId, $database, $function, /*$event*/'', /*$eventData*/'', $data, $webhooks, $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, $webhooks, $userId, $jwt);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -282,15 +284,19 @@ class FunctionsV1
|
|||
* @param Database $database
|
||||
* @param Database $function
|
||||
* @param string $event
|
||||
* @param string $payload
|
||||
* @param string $eventData
|
||||
* @param string $data
|
||||
* @param array $webhooks
|
||||
* @param string $userId
|
||||
* @param string $jwt
|
||||
*
|
||||
* @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 = '', array $webhooks = [], string $userId = '', string $jwt = ''): void
|
||||
{
|
||||
global $list;
|
||||
|
||||
$environments = Config::getParam('environments');
|
||||
$runtimes = Config::getParam('runtimes');
|
||||
|
||||
Authorization::disable();
|
||||
$tag = $database->getDocument($function->getAttribute('tag', ''));
|
||||
|
|
@ -324,11 +330,11 @@ class FunctionsV1
|
|||
|
||||
Authorization::reset();
|
||||
|
||||
$environment = (isset($environments[$function->getAttribute('env', '')]))
|
||||
? $environments[$function->getAttribute('env', '')]
|
||||
$runtime = (isset($runtimes[$function->getAttribute('env', '')]))
|
||||
? $runtimes[$function->getAttribute('env', '')]
|
||||
: null;
|
||||
|
||||
if(\is_null($environment)) {
|
||||
if(\is_null($runtime)) {
|
||||
throw new Exception('Environment "'.$function->getAttribute('env', '').' is not supported');
|
||||
}
|
||||
|
||||
|
|
@ -337,10 +343,14 @@ class FunctionsV1
|
|||
'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name', ''),
|
||||
'APPWRITE_FUNCTION_TAG' => $tag->getId(),
|
||||
'APPWRITE_FUNCTION_TRIGGER' => $trigger,
|
||||
'APPWRITE_FUNCTION_ENV_NAME' => $environment['name'],
|
||||
'APPWRITE_FUNCTION_ENV_VERSION' => $environment['version'],
|
||||
'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'],
|
||||
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['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) {
|
||||
|
|
@ -412,7 +422,7 @@ class FunctionsV1
|
|||
" --volume {$tagPathTargetDir}:/tmp:rw".
|
||||
" --workdir /usr/local/src".
|
||||
" ".\implode(" ", $vars).
|
||||
" {$environment['image']}".
|
||||
" {$runtime['image']}".
|
||||
" sh -c 'mv /tmp/code.tar.gz /usr/local/src/code.tar.gz && tar -zxf /usr/local/src/code.tar.gz --strip 1 && rm /usr/local/src/code.tar.gz && tail -f /dev/null'"
|
||||
, '', $stdout, $stderr, 30);
|
||||
|
||||
|
|
@ -469,6 +479,27 @@ 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('webhooks', $webhooks)
|
||||
->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
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ class MailsV1
|
|||
return;
|
||||
}
|
||||
|
||||
$event = $this->args['event'];
|
||||
$from = $this->args['from'];
|
||||
$recipient = $this->args['recipient'];
|
||||
$name = $this->args['name'];
|
||||
|
|
|
|||
|
|
@ -26,20 +26,20 @@ class UsageV1
|
|||
|
||||
$statsd = $register->get('statsd', true);
|
||||
|
||||
$projectId = $this->args['projectId'];
|
||||
$projectId = $this->args['projectId'] ?? '';
|
||||
|
||||
$storage = $this->args['storage'];
|
||||
$storage = $this->args['storage'] ?? 0;
|
||||
|
||||
$networkRequestSize = $this->args['networkRequestSize'];
|
||||
$networkResponseSize = $this->args['networkResponseSize'];
|
||||
$networkRequestSize = $this->args['networkRequestSize'] ?? 0;
|
||||
$networkResponseSize = $this->args['networkResponseSize'] ?? 0;
|
||||
|
||||
$httpMethod = $this->args['httpMethod'];
|
||||
$httpRequest = $this->args['httpRequest'];
|
||||
$httpMethod = $this->args['httpMethod'] ?? '';
|
||||
$httpRequest = $this->args['httpRequest'] ?? 0;
|
||||
|
||||
$functionId = $this->args['functionId'];
|
||||
$functionExecution = $this->args['functionExecution'];
|
||||
$functionExecutionTime = $this->args['functionExecutionTime'];
|
||||
$functionStatus = $this->args['functionStatus'];
|
||||
$functionExecution = $this->args['functionExecution'] ?? 0;
|
||||
$functionExecutionTime = $this->args['functionExecutionTime'] ?? 0;
|
||||
$functionStatus = $this->args['functionStatus'] ?? '';
|
||||
|
||||
$tags = ",project={$projectId},version=".App::getEnv('_APP_VERSION', 'UNKNOWN').'';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,6 @@
|
|||
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Appwrite\Database\Database;
|
||||
use Appwrite\Database\Adapter\MySQL as MySQLAdapter;
|
||||
use Appwrite\Database\Adapter\Redis as RedisAdapter;
|
||||
use Appwrite\Database\Validator\Authorization;
|
||||
|
||||
require_once __DIR__.'/../init.php';
|
||||
|
||||
|
|
@ -24,34 +19,16 @@ class WebhooksV1
|
|||
|
||||
public function perform()
|
||||
{
|
||||
global $register;
|
||||
|
||||
$consoleDB = new Database();
|
||||
$consoleDB->setAdapter(new RedisAdapter(new MySQLAdapter($register), $register));
|
||||
$consoleDB->setNamespace('app_console'); // Main DB
|
||||
$consoleDB->setMocks(Config::getParam('collections', []));
|
||||
|
||||
$errors = [];
|
||||
|
||||
// Event
|
||||
$projectId = $this->args['projectId'] ?? '';
|
||||
$webhooks = $this->args['webhooks'] ?? [];
|
||||
$userId = $this->args['userId'] ?? '';
|
||||
$event = $this->args['event'] ?? '';
|
||||
$payload = \json_encode($this->args['payload']);
|
||||
$eventData = \json_encode($this->args['eventData']);
|
||||
|
||||
// Webhook
|
||||
|
||||
Authorization::disable();
|
||||
|
||||
$project = $consoleDB->getDocument($projectId);
|
||||
|
||||
Authorization::reset();
|
||||
|
||||
if (\is_null($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS !== $project->getCollection()) {
|
||||
throw new Exception('Project Not Found');
|
||||
}
|
||||
|
||||
foreach ($project->getAttribute('webhooks', []) as $webhook) {
|
||||
foreach ($webhooks as $webhook) {
|
||||
if (!(isset($webhook['events']) && \is_array($webhook['events']) && \in_array($event, $webhook['events']))) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -67,7 +44,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 +56,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,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4.0",
|
||||
"php": ">=8.0.0",
|
||||
"ext-curl": "*",
|
||||
"ext-imagick": "*",
|
||||
"ext-mbstring": "*",
|
||||
|
|
@ -35,52 +35,44 @@
|
|||
"ext-zlib": "*",
|
||||
"ext-sockets": "*",
|
||||
|
||||
"appwrite/php-clamav": "1.0.*",
|
||||
"appwrite/php-clamav": "1.1.*",
|
||||
"appwrite/php-runtimes": "0.2.*",
|
||||
|
||||
"utopia-php/framework": "0.12.*",
|
||||
"utopia-php/framework": "0.14.*",
|
||||
"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",
|
||||
"utopia-php/cli": "0.11.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/locale": "0.3.*",
|
||||
"utopia-php/registry": "0.2.*",
|
||||
"utopia-php/registry": "0.4.*",
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
"utopia-php/domains": "0.2.*",
|
||||
"utopia-php/domains": "1.1.*",
|
||||
"utopia-php/swoole": "0.2.*",
|
||||
"utopia-php/system": "0.4.*",
|
||||
"utopia-php/storage": "0.4.*",
|
||||
"utopia-php/image": "0.1.*",
|
||||
|
||||
"utopia-php/storage": "0.5.*",
|
||||
"utopia-php/image": "0.2.*",
|
||||
"resque/php-resque": "1.3.6",
|
||||
"matomo/device-detector": "4.1.0",
|
||||
"matomo/device-detector": "4.2.2",
|
||||
"dragonmantank/cron-expression": "3.1.0",
|
||||
"influxdb/influxdb-php": "1.15.2",
|
||||
"phpmailer/phpmailer": "6.4.1",
|
||||
"chillerlan/php-qrcode": "4.3.0",
|
||||
"adhocore/jwt": "1.1.2",
|
||||
"slickdeals/statsd": "~3.0"
|
||||
"slickdeals/statsd": "3.0.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"appwrite/sdk-generator": "0.9.0",
|
||||
"phpunit/phpunit": "9.4.2",
|
||||
"swoole/ide-helper": "4.5.5",
|
||||
"vimeo/psalm": "4.1.1"
|
||||
"appwrite/sdk-generator": "0.10.1",
|
||||
"swoole/ide-helper": "4.6.6",
|
||||
"phpunit/phpunit": "9.5.4",
|
||||
"vimeo/psalm": "4.7.2"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator"
|
||||
}
|
||||
],
|
||||
"provide": {
|
||||
"ext-phpiredis": "*"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.4"
|
||||
"php": "8.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
993
composer.lock
generated
993
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -71,10 +71,14 @@ services:
|
|||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
- clamav
|
||||
# - clamav
|
||||
- influxdb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_LOCALE
|
||||
- _APP_CONSOLE_WHITELIST_ROOT
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||
- _APP_CONSOLE_WHITELIST_IPS
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
|
|
@ -110,7 +114,7 @@ services:
|
|||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_MEMORY_SWAP
|
||||
- _APP_FUNCTIONS_ENVS
|
||||
- _APP_FUNCTIONS_RUNTIMES
|
||||
|
||||
appwrite-worker-usage:
|
||||
entrypoint: worker-usage
|
||||
|
|
@ -180,11 +184,6 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
|
||||
appwrite-worker-tasks:
|
||||
entrypoint: worker-tasks
|
||||
|
|
@ -201,6 +200,7 @@ services:
|
|||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -282,12 +282,12 @@ services:
|
|||
- /tmp:/tmp:rw
|
||||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
- ./docker:/usr/src/code/docker
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -299,6 +299,7 @@ services:
|
|||
- _APP_DB_PASS
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_CONTAINERS
|
||||
- _APP_FUNCTIONS_RUNTIMES
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_MEMORY_SWAP
|
||||
|
|
@ -413,16 +414,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
|
||||
|
|
@ -430,7 +431,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
|
||||
|
|
@ -449,16 +450,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:
|
||||
|
|
@ -466,6 +467,7 @@ services:
|
|||
|
||||
adminer:
|
||||
image: adminer
|
||||
container_name: appwrite-adminer
|
||||
restart: always
|
||||
ports:
|
||||
- 9505:8080
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
# Appwrite Functions Environments
|
||||
|
||||
Docker based enviornments for Appwrite Functions. You can use this Docker images to locally tests your functions by executing them on your local desktop or server.
|
||||
|
||||
All the supported enviornments are based on Docker Alpine images.
|
||||
|
||||
## Build
|
||||
|
||||
Build envs for all supported cloud functions (multicore builds)
|
||||
|
||||
```bash
|
||||
bash ./docker/environments/build.sh
|
||||
```
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
echo 'Starting build...'
|
||||
|
||||
echo 'Deno 1.2...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-deno-1.2:1.0.0 ./docker/environments/deno-1.2/ --push
|
||||
|
||||
echo 'Deno 1.5...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-deno-1.5:1.0.0 ./docker/environments/deno-1.5/ --push
|
||||
|
||||
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 '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
|
||||
|
||||
echo 'Node 15.5...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le -t appwrite/env-node-15.5:1.0.0 ./docker/environments/node-15.5/ --push
|
||||
|
||||
echo 'PHP 7.4...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-php-7.4:1.0.0 ./docker/environments/php-7.4/ --push
|
||||
|
||||
echo 'PHP 8.0...'
|
||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-php-8.0:1.0.0 ./docker/environments/php-8.0/ --push
|
||||
|
||||
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 '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
|
||||
|
||||
echo 'Ruby 3.0...'
|
||||
docker buildx build --platform linux/amd64,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-ruby-3.0:1.0.0 ./docker/environments/ruby-3.0/ --push
|
||||
|
||||
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 '.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
|
||||
|
||||
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
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
FROM google/dart:2.10
|
||||
|
||||
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
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
FROM hayd/deno:alpine-1.2.0
|
||||
|
||||
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
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
FROM hayd/deno:alpine-1.5.0
|
||||
|
||||
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
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
FROM hayd/deno:alpine-1.6.2
|
||||
|
||||
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
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
FROM mcr.microsoft.com/dotnet/runtime:3.1-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
FROM mcr.microsoft.com/dotnet/runtime:5.0-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
FROM node:14.5-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
FROM node:15.5-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
FROM php:7.4-cli-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
FROM php:8.0-cli-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
FROM python:3.8-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"
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
FROM ruby:2.7-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
||||
ENV GEM_PATH=/usr/local/src/.appwrite
|
||||
ENV GEM_SPEC_CACHE=/usr/local/src/.appwrite/specs
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
FROM ruby:3.0-alpine
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
RUN apk add tar
|
||||
|
||||
RUN mkdir /usr/local/src
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
||||
ENV GEM_PATH=/usr/local/src/.appwrite
|
||||
ENV GEM_SPEC_CACHE=/usr/local/src/.appwrite/specs
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
let sdk = new Appwrite();
|
||||
|
||||
sdk
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||
;
|
||||
|
||||
let promise = sdk.projects.updateAuthLimit('[PROJECT_ID]', '');
|
||||
|
||||
promise.then(function (response) {
|
||||
console.log(response); // Success
|
||||
}, function (error) {
|
||||
console.log(error); // Failure
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
let sdk = new Appwrite();
|
||||
|
||||
sdk
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||
;
|
||||
|
||||
let promise = sdk.projects.updateAuthStatus('[PROJECT_ID]', 'email-password', false);
|
||||
|
||||
promise.then(function (response) {
|
||||
console.log(response); // Success
|
||||
}, function (error) {
|
||||
console.log(error); // Failure
|
||||
});
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.createAnonymousSession();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.createJWT();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.createOAuth2Session(
|
||||
provider: 'amazon',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.createRecovery(
|
||||
email: 'email@example.com',
|
||||
url: 'https://example.com',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.createSession(
|
||||
email: 'email@example.com',
|
||||
password: 'password',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.createVerification(
|
||||
url: 'https://example.com',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.create(
|
||||
email: 'email@example.com',
|
||||
password: 'password',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.deleteSession(
|
||||
sessionId: '[SESSION_ID]',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.deleteSessions();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.delete();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.getLogs();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.getPrefs();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.getSessions();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
19
docs/examples/0.8.x/client-flutter/examples/account/get.md
Normal file
19
docs/examples/0.8.x/client-flutter/examples/account/get.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.get();
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.updateEmail(
|
||||
email: 'email@example.com',
|
||||
password: 'password',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import 'package:appwrite/appwrite.dart';
|
||||
|
||||
void main() { // Init SDK
|
||||
Client client = Client();
|
||||
Account account = Account(client);
|
||||
|
||||
client
|
||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||
.setProject('5df5acd0d48c2') // Your project ID
|
||||
;
|
||||
Future result = account.updateName(
|
||||
name: '[NAME]',
|
||||
);
|
||||
|
||||
result
|
||||
.then((response) {
|
||||
print(response);
|
||||
}).catchError((error) {
|
||||
print(error.response);
|
||||
});
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue