Merge pull request #5142 from appwrite/feat-13x-master-sync
Feat 13x master sync
This commit is contained in:
commit
f1fd44cee3
129 changed files with 1267 additions and 1420 deletions
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -11,21 +11,17 @@ Happy contributing!
|
||||||
|
|
||||||
## What does this PR do?
|
## What does this PR do?
|
||||||
|
|
||||||
(Provide a description of what this PR does.)
|
(Provide a description of what this PR does and why it's needed.)
|
||||||
|
|
||||||
## Test Plan
|
## Test Plan
|
||||||
|
|
||||||
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)
|
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)
|
||||||
|
|
||||||
## Related PRs and Issues
|
## Related PRs and Issues
|
||||||
|
|
||||||
(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)
|
- (Related PR or issue)
|
||||||
|
|
||||||
### Have you added your change to the [Changelog](https://github.com/appwrite/appwrite/blob/master/CHANGES.md)?
|
## Checklist
|
||||||
|
|
||||||
(The CHANGES.md file tracks all the changes that make it to the `main` branch. Add your change to this file in the following format)
|
- [ ] Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
||||||
- One line description of your PR [#pr_number](Link to your PR)
|
- [ ] If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?
|
||||||
|
|
||||||
### Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
|
||||||
|
|
||||||
(Write your answer here.)
|
|
||||||
|
|
27
.github/workflows/tests.yml
vendored
27
.github/workflows/tests.yml
vendored
|
@ -21,18 +21,29 @@ jobs:
|
||||||
- run: git checkout HEAD^2
|
- run: git checkout HEAD^2
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
|
# This is a separate action that sets up buildx runner
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Build Appwrite
|
- name: Build Appwrite
|
||||||
# Upstream bug causes buildkit pulls to fail so prefetch base images
|
uses: docker/build-push-action@v3
|
||||||
# https://github.com/moby/moby/issues/41864
|
with:
|
||||||
|
context: .
|
||||||
|
push: false
|
||||||
|
tags: appwrite-dev
|
||||||
|
load: true
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
build-args: |
|
||||||
|
DEBUG=false
|
||||||
|
TESTING=true
|
||||||
|
VERSION=dev
|
||||||
|
|
||||||
|
- name: Start Appwrite
|
||||||
run: |
|
run: |
|
||||||
export COMPOSE_INTERACTIVE_NO_CLI
|
|
||||||
export DOCKER_BUILDKIT=1
|
|
||||||
export COMPOSE_DOCKER_CLI_BUILD=1
|
|
||||||
export BUILDKIT_PROGRESS=plain
|
|
||||||
docker pull composer:2.0
|
|
||||||
docker compose build appwrite
|
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
sleep 30
|
sleep 30
|
||||||
|
|
||||||
- name: Doctor
|
- name: Doctor
|
||||||
run: docker compose exec -T appwrite doctor
|
run: docker compose exec -T appwrite doctor
|
||||||
|
|
||||||
|
|
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -1,4 +1,4 @@
|
||||||
[submodule "app/console"]
|
[submodule "app/console"]
|
||||||
path = app/console
|
path = app/console
|
||||||
url = https://github.com/appwrite/console
|
url = https://github.com/appwrite/console
|
||||||
branch = 2.1.1
|
branch = 2.2.0
|
||||||
|
|
21
CHANGES.md
21
CHANGES.md
|
@ -1,9 +1,28 @@
|
||||||
## Version 1.3.0
|
# Version TBD
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Password dictionary setting allows to compare user's password against command password database [4906](https://github.com/appwrite/appwrite/pull/4906)
|
- Password dictionary setting allows to compare user's password against command password database [4906](https://github.com/appwrite/appwrite/pull/4906)
|
||||||
- Password history setting allows to save user's last used password so that it may not be used again. Maximum number of history saved is 20, which can be configured. Minimum is 0 which means disabled. [#4866](https://github.com/appwrite/appwrite/pull/4866)
|
- Password history setting allows to save user's last used password so that it may not be used again. Maximum number of history saved is 20, which can be configured. Minimum is 0 which means disabled. [#4866](https://github.com/appwrite/appwrite/pull/4866)
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
|
||||||
|
- Fix not storing function's response on response codes 5xx [#4610](https://github.com/appwrite/appwrite/pull/4610)
|
||||||
|
|
||||||
|
# Version 1.2.1
|
||||||
|
## Changes
|
||||||
|
- Upgrade Console to [2.2.0](https://github.com/appwrite/console/releases/tag/2.2.0)
|
||||||
|
- Update DBIP Database [#5049](https://github.com/appwrite/appwrite/pull/5049)
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
- Fix a few null safety warnings [#4654](https://github.com/appwrite/appwrite/pull/4654)
|
||||||
|
- Fix timestamp format in Realtime response [#4515](https://github.com/appwrite/appwrite/pull/4515)
|
||||||
|
- Add flutter-web as a platform type [#4992](https://github.com/appwrite/appwrite/pull/4992)
|
||||||
|
- Fix typo in Model/Locale.php [#4669](https://github.com/appwrite/appwrite/pull/4669)
|
||||||
|
- Fix deletes worker not deleting project database tables [#4984](https://github.com/appwrite/appwrite/pull/4984)
|
||||||
|
- Fix deletes worker not deleting database collections [#4983](https://github.com/appwrite/appwrite/pull/4983)
|
||||||
|
- Fix restart policy for worker-messaging container [#4994](https://github.com/appwrite/appwrite/pull/4994)
|
||||||
|
- Fix validating origin for apple platforms [#5089](https://github.com/appwrite/appwrite/pull/5089)
|
||||||
|
|
||||||
# Version 1.2.0
|
# Version 1.2.0
|
||||||
## Features
|
## Features
|
||||||
- Added GraphQL API [#974](https://github.com/appwrite/appwrite/pull/974)
|
- Added GraphQL API [#974](https://github.com/appwrite/appwrite/pull/974)
|
||||||
|
|
|
@ -441,8 +441,8 @@ composer lint <your file path>
|
||||||
From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials:
|
From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials:
|
||||||
|
|
||||||
- [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
|
- [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
|
||||||
- [Appwrite Environment Variables](./docs/tutorials/environment-variables.md)
|
- [Appwrite Environment Variables](./docs/tutorials/add-environment-variable.md)
|
||||||
- [Running in Production](./docs/tutorials/running-in-production.md)
|
- [Running in Production](https://appwrite.io/docs/production)
|
||||||
- [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
|
- [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
|
||||||
|
|
||||||
## Other Ways to Help
|
## Other Ways to Help
|
||||||
|
|
189
Dockerfile
189
Dockerfile
|
@ -20,152 +20,16 @@ WORKDIR /usr/local/src/console
|
||||||
|
|
||||||
ARG VITE_GA_PROJECT
|
ARG VITE_GA_PROJECT
|
||||||
ARG VITE_CONSOLE_MODE
|
ARG VITE_CONSOLE_MODE
|
||||||
|
ARG VITE_APPWRITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1
|
||||||
|
|
||||||
ENV VITE_GA_PROJECT=$VITE_GA_PROJECT
|
ENV VITE_GA_PROJECT=$VITE_GA_PROJECT
|
||||||
ENV VITE_CONSOLE_MODE=$VITE_CONSOLE_MODE
|
ENV VITE_CONSOLE_MODE=$VITE_CONSOLE_MODE
|
||||||
|
ENV VITE_APPWRITE_GROWTH_ENDPOINT=$VITE_APPWRITE_GROWTH_ENDPOINT
|
||||||
|
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
FROM php:8.0.18-cli-alpine3.15 as compile
|
FROM appwrite/base:0.1.0 as final
|
||||||
|
|
||||||
ARG DEBUG=false
|
|
||||||
ENV DEBUG=$DEBUG
|
|
||||||
|
|
||||||
ENV PHP_REDIS_VERSION=5.3.7 \
|
|
||||||
PHP_MONGODB_VERSION=1.13.0 \
|
|
||||||
PHP_SWOOLE_VERSION=v4.8.10 \
|
|
||||||
PHP_IMAGICK_VERSION=3.7.0 \
|
|
||||||
PHP_YAML_VERSION=2.2.2 \
|
|
||||||
PHP_MAXMINDDB_VERSION=v1.11.0 \
|
|
||||||
PHP_ZSTD_VERSION="4504e4186e79b197cfcb75d4d09aa47ef7d92fe9"
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
apk add --no-cache --virtual .deps \
|
|
||||||
make \
|
|
||||||
automake \
|
|
||||||
autoconf \
|
|
||||||
gcc \
|
|
||||||
g++ \
|
|
||||||
git \
|
|
||||||
zlib-dev \
|
|
||||||
brotli-dev \
|
|
||||||
openssl-dev \
|
|
||||||
yaml-dev \
|
|
||||||
imagemagick \
|
|
||||||
imagemagick-dev \
|
|
||||||
libmaxminddb-dev \
|
|
||||||
zstd-dev
|
|
||||||
|
|
||||||
RUN docker-php-ext-install sockets
|
|
||||||
|
|
||||||
FROM compile AS redis
|
|
||||||
RUN \
|
|
||||||
# Redis Extension
|
|
||||||
git clone --depth 1 --branch $PHP_REDIS_VERSION https://github.com/phpredis/phpredis.git && \
|
|
||||||
cd phpredis && \
|
|
||||||
phpize && \
|
|
||||||
./configure && \
|
|
||||||
make && make install
|
|
||||||
|
|
||||||
## Swoole Extension
|
|
||||||
FROM compile AS swoole
|
|
||||||
RUN \
|
|
||||||
git clone --depth 1 --branch $PHP_SWOOLE_VERSION https://github.com/swoole/swoole-src.git && \
|
|
||||||
cd swoole-src && \
|
|
||||||
phpize && \
|
|
||||||
./configure --enable-sockets --enable-http2 --enable-openssl && \
|
|
||||||
make && make install && \
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
## Swoole Debugger setup
|
|
||||||
RUN if [ "$DEBUG" == "true" ]; then \
|
|
||||||
cd /tmp && \
|
|
||||||
apk add boost-dev && \
|
|
||||||
git clone --depth 1 https://github.com/swoole/yasd && \
|
|
||||||
cd yasd && \
|
|
||||||
phpize && \
|
|
||||||
./configure && \
|
|
||||||
make && make install && \
|
|
||||||
cd ..;\
|
|
||||||
fi
|
|
||||||
|
|
||||||
## Imagick Extension
|
|
||||||
FROM compile AS imagick
|
|
||||||
RUN \
|
|
||||||
git clone --depth 1 --branch $PHP_IMAGICK_VERSION https://github.com/imagick/imagick && \
|
|
||||||
cd imagick && \
|
|
||||||
phpize && \
|
|
||||||
./configure && \
|
|
||||||
make && make install
|
|
||||||
|
|
||||||
## YAML Extension
|
|
||||||
FROM compile AS yaml
|
|
||||||
RUN \
|
|
||||||
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
|
|
||||||
|
|
||||||
## Maxminddb extension
|
|
||||||
FROM compile AS maxmind
|
|
||||||
RUN \
|
|
||||||
git clone --depth 1 --branch $PHP_MAXMINDDB_VERSION https://github.com/maxmind/MaxMind-DB-Reader-php.git && \
|
|
||||||
cd MaxMind-DB-Reader-php && \
|
|
||||||
cd ext && \
|
|
||||||
phpize && \
|
|
||||||
./configure && \
|
|
||||||
make && make install
|
|
||||||
|
|
||||||
# Mongodb Extension
|
|
||||||
FROM compile as mongodb
|
|
||||||
RUN \
|
|
||||||
git clone --depth 1 --branch $PHP_MONGODB_VERSION https://github.com/mongodb/mongo-php-driver.git && \
|
|
||||||
cd mongo-php-driver && \
|
|
||||||
git submodule update --init && \
|
|
||||||
phpize && \
|
|
||||||
./configure && \
|
|
||||||
make && make install
|
|
||||||
|
|
||||||
# Zstd Compression
|
|
||||||
FROM compile as zstd
|
|
||||||
RUN git clone --recursive -n https://github.com/kjdev/php-ext-zstd.git \
|
|
||||||
&& cd php-ext-zstd \
|
|
||||||
&& git checkout $PHP_ZSTD_VERSION \
|
|
||||||
&& phpize \
|
|
||||||
&& ./configure --with-libzstd \
|
|
||||||
&& make && make install
|
|
||||||
|
|
||||||
|
|
||||||
# Rust Extensions Compile Image
|
|
||||||
FROM php:8.0.18-cli as rust_compile
|
|
||||||
|
|
||||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
|
||||||
|
|
||||||
ENV PATH=/root/.cargo/bin:$PATH
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install musl-tools build-essential clang-11 git -y
|
|
||||||
RUN rustup target add $(uname -m)-unknown-linux-musl
|
|
||||||
|
|
||||||
# Install ZigBuild for easier cross-compilation
|
|
||||||
RUN curl https://ziglang.org/builds/zig-linux-$(uname -m)-0.10.0-dev.2674+d980c6a38.tar.xz --output /tmp/zig.tar.xz
|
|
||||||
RUN tar -xf /tmp/zig.tar.xz -C /tmp/ && cp -r /tmp/zig-linux-$(uname -m)-0.10.0-dev.2674+d980c6a38 /tmp/zig/
|
|
||||||
ENV PATH=/tmp/zig:$PATH
|
|
||||||
RUN cargo install cargo-zigbuild
|
|
||||||
ENV RUSTFLAGS="-C target-feature=-crt-static"
|
|
||||||
|
|
||||||
FROM rust_compile as scrypt
|
|
||||||
|
|
||||||
WORKDIR /usr/local/lib/php/extensions/
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
git clone --depth 1 https://github.com/appwrite/php-scrypt.git && \
|
|
||||||
cd php-scrypt && \
|
|
||||||
cargo zigbuild --workspace --all-targets --target $(uname -m)-unknown-linux-musl --release && \
|
|
||||||
mv target/$(uname -m)-unknown-linux-musl/release/libphp_scrypt.so target/libphp_scrypt.so
|
|
||||||
|
|
||||||
FROM php:8.0.18-cli-alpine3.15 as final
|
|
||||||
|
|
||||||
LABEL maintainer="team@appwrite.io"
|
LABEL maintainer="team@appwrite.io"
|
||||||
|
|
||||||
|
@ -260,38 +124,6 @@ ENV _APP_SERVER=swoole \
|
||||||
_APP_LOGGING_PROVIDER= \
|
_APP_LOGGING_PROVIDER= \
|
||||||
_APP_LOGGING_CONFIG=
|
_APP_LOGGING_CONFIG=
|
||||||
|
|
||||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
apk update \
|
|
||||||
&& apk add --no-cache --virtual .deps \
|
|
||||||
make \
|
|
||||||
automake \
|
|
||||||
autoconf \
|
|
||||||
gcc \
|
|
||||||
g++ \
|
|
||||||
curl-dev \
|
|
||||||
&& apk add --no-cache \
|
|
||||||
libstdc++ \
|
|
||||||
certbot \
|
|
||||||
brotli-dev \
|
|
||||||
yaml-dev \
|
|
||||||
imagemagick \
|
|
||||||
imagemagick-dev \
|
|
||||||
libmaxminddb-dev \
|
|
||||||
certbot \
|
|
||||||
docker-cli \
|
|
||||||
libgomp \
|
|
||||||
&& docker-php-ext-install sockets opcache pdo_mysql \
|
|
||||||
&& apk del .deps \
|
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
mkdir -p $DOCKER_CONFIG/cli-plugins \
|
|
||||||
&& ARCH=$(uname -m) && if [ $ARCH == "armv7l" ]; then ARCH="armv7"; fi \
|
|
||||||
&& curl -SL https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-linux-$ARCH -o $DOCKER_CONFIG/cli-plugins/docker-compose \
|
|
||||||
&& chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
|
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
if [ "$DEBUG" == "true" ]; then \
|
if [ "$DEBUG" == "true" ]; then \
|
||||||
apk add boost boost-dev; \
|
apk add boost boost-dev; \
|
||||||
|
@ -301,14 +133,6 @@ WORKDIR /usr/src/code
|
||||||
|
|
||||||
COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor
|
COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor
|
||||||
COPY --from=node /usr/local/src/console/build /usr/src/code/console
|
COPY --from=node /usr/local/src/console/build /usr/src/code/console
|
||||||
COPY --from=swoole /usr/local/lib/php/extensions/no-debug-non-zts-20200930/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yasd.so* /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
COPY --from=redis /usr/local/lib/php/extensions/no-debug-non-zts-20200930/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
COPY --from=imagick /usr/local/lib/php/extensions/no-debug-non-zts-20200930/imagick.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
COPY --from=yaml /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yaml.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
COPY --from=maxmind /usr/local/lib/php/extensions/no-debug-non-zts-20200930/maxminddb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
COPY --from=mongodb /usr/local/lib/php/extensions/no-debug-non-zts-20200930/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
COPY --from=scrypt /usr/local/lib/php/extensions/php-scrypt/target/libphp_scrypt.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
COPY --from=zstd /usr/local/lib/php/extensions/no-debug-non-zts-20200930/zstd.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
|
||||||
|
|
||||||
# Add Source Code
|
# Add Source Code
|
||||||
COPY ./app /usr/src/code/app
|
COPY ./app /usr/src/code/app
|
||||||
|
@ -358,13 +182,6 @@ RUN chmod +x /usr/local/bin/doctor && \
|
||||||
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
|
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
|
||||||
|
|
||||||
# Enable Extensions
|
# 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 extension=libphp_scrypt.so >> /usr/local/etc/php/conf.d/libphp_scrypt.ini
|
|
||||||
RUN echo extension=zstd.so >> /usr/local/etc/php/conf.d/zstd.ini
|
|
||||||
RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
|
RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
|
||||||
|
|
||||||
RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi
|
RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi
|
||||||
|
|
17
README-CN.md
17
README-CN.md
|
@ -1,3 +1,6 @@
|
||||||
|
> 准备好迎接狂风暴'云'了吗? 🌩 ☂️
|
||||||
|
> Appwrite Cloud即将到来!你能够通过https://appwrite.io/cloud了解更多的资讯, 注册即可领取试用额度哦
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://appwrite.io" target="_blank"><img width="260" height="39" src="https://appwrite.io/images/appwrite.svg" alt="Appwrite Logo"></a>
|
<a href="https://appwrite.io" target="_blank"><img width="260" height="39" src="https://appwrite.io/images/appwrite.svg" alt="Appwrite Logo"></a>
|
||||||
|
@ -12,7 +15,7 @@
|
||||||
|
|
||||||
[![Hacktoberfest](https://img.shields.io/static/v1?label=hacktoberfest&message=friendly&color=191120&style=flat-square)](https://hacktoberfest.appwrite.io)
|
[![Hacktoberfest](https://img.shields.io/static/v1?label=hacktoberfest&message=friendly&color=191120&style=flat-square)](https://hacktoberfest.appwrite.io)
|
||||||
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord?r=Github)
|
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord?r=Github)
|
||||||
[![Build Status](https://img.shields.io/github/workflow/status/appwrite/appwrite/Tests?label=tests&style=flat-square)](https://github.com/appwrite/appwrite/actions)
|
[![Build Status](https://img.shields.io/github/actions/workflow/status/appwrite/appwrite/tests.yml?branch=master&label=tests&style=flat-square)](https://github.com/appwrite/appwrite/actions)
|
||||||
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite)
|
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite)
|
||||||
|
|
||||||
<!-- [![Docker Pulls](https://img.shields.io/docker/pulls/appwrite/appwrite?color=f02e65&style=flat-square)](https://hub.docker.com/r/appwrite/appwrite) -->
|
<!-- [![Docker Pulls](https://img.shields.io/docker/pulls/appwrite/appwrite?color=f02e65&style=flat-square)](https://hub.docker.com/r/appwrite/appwrite) -->
|
||||||
|
@ -23,7 +26,7 @@
|
||||||
|
|
||||||
[**我们发布了 Appwrite Console 2.0 版本,点击这里了解更多!**](https://medium.com/appwrite-io/announcing-console-2-0-2e0e96891cb0?source=friends_link&sk=7a82b4069778e3adc165dc026e960fe1)
|
[**我们发布了 Appwrite Console 2.0 版本,点击这里了解更多!**](https://medium.com/appwrite-io/announcing-console-2-0-2e0e96891cb0?source=friends_link&sk=7a82b4069778e3adc165dc026e960fe1)
|
||||||
|
|
||||||
Appwrite是一个基于Docker的端到端开发者平台,其容器化的微服务库可应用于网页端,移动端,以及后端。Appwrite 通过视觉化界面极简了从零编写 API 的繁琐过程,在保证软件安全的前提下为开发者创造了一个高效的开发环境。
|
Appwrite是一个基于Docker的端到端开发者平台,其容器化的微服务库可应用于网页端,移动端,以及后端。Appwrite 通过视觉化界面简化了从零开始编写 API 的繁琐过程,在保证软件安全的前提下为开发者创造了一个高效的开发环境。
|
||||||
|
|
||||||
Appwrite 可以提供给开发者用户验证,外部授权,用户数据读写检索,文件储存,图像处理,云函数计算,[等多种服务](https://appwrite.io/docs).
|
Appwrite 可以提供给开发者用户验证,外部授权,用户数据读写检索,文件储存,图像处理,云函数计算,[等多种服务](https://appwrite.io/docs).
|
||||||
|
|
||||||
|
@ -55,7 +58,7 @@ Appwrite 可以提供给开发者用户验证,外部授权,用户数据读
|
||||||
|
|
||||||
Appwrite 的容器化服务器只需要一行指令就可以运行。您可以使用 docker-compose 在本地主机上运行 Appwrite,也可以在任何其他容器化工具(如 Kubernetes、Docker Swarm 或 Rancher)上运行 Appwrite。
|
Appwrite 的容器化服务器只需要一行指令就可以运行。您可以使用 docker-compose 在本地主机上运行 Appwrite,也可以在任何其他容器化工具(如 Kubernetes、Docker Swarm 或 Rancher)上运行 Appwrite。
|
||||||
|
|
||||||
开始运行 Appwrite 服务器的最简单方法是运行我们的 docker-compose 文件。在运行安装命令之前,请确保您的机器上安装了 [Docker](https://dockerdocs.cn/get-docker/index.html):
|
启动 Appwrite 服务器的最简单方法是运行我们的 docker-compose 文件。在运行安装命令之前,请确保您的机器上安装了 [Docker](https://dockerdocs.cn/get-docker/index.html):
|
||||||
|
|
||||||
### Unix
|
### Unix
|
||||||
|
|
||||||
|
@ -64,7 +67,7 @@ docker run -it --rm \
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||||
--entrypoint="install" \
|
--entrypoint="install" \
|
||||||
appwrite/appwrite:1.2.0
|
appwrite/appwrite:1.2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
@ -76,7 +79,7 @@ docker run -it --rm ^
|
||||||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||||
--entrypoint="install" ^
|
--entrypoint="install" ^
|
||||||
appwrite/appwrite:1.2.0
|
appwrite/appwrite:1.2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
#### PowerShell
|
#### PowerShell
|
||||||
|
@ -86,7 +89,7 @@ docker run -it --rm `
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||||
--entrypoint="install" `
|
--entrypoint="install" `
|
||||||
appwrite/appwrite:1.2.0
|
appwrite/appwrite:1.2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
|
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
|
||||||
|
@ -159,7 +162,7 @@ Appwrite API 界面层利用后台缓存和任务委派来提供极速的响应
|
||||||
|
|
||||||
## 贡献代码
|
## 贡献代码
|
||||||
|
|
||||||
所有代码贡献 - 包括来自具有直接提交更改权限的贡献者 - 都必须提交PR请求并在合并分支之前得到核心开发人员的批准。这是为了确保正确审查所有代码。
|
为了确保正确审查,所有代码贡献 - 包括来自具有直接提交更改权限的贡献者 - 都必须提交PR请求并在合并分支之前得到核心开发人员的批准。
|
||||||
|
|
||||||
我们欢迎所有人提交PR!如果您愿意提供帮助,可以在 [贡献指南](CONTRIBUTING.md) 中了解有关如何为项目做出贡献的更多信息。
|
我们欢迎所有人提交PR!如果您愿意提供帮助,可以在 [贡献指南](CONTRIBUTING.md) 中了解有关如何为项目做出贡献的更多信息。
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
[![Hacktoberfest](https://img.shields.io/static/v1?label=hacktoberfest&message=ready&color=191120&style=flat-square)](https://hacktoberfest.appwrite.io)
|
[![Hacktoberfest](https://img.shields.io/static/v1?label=hacktoberfest&message=ready&color=191120&style=flat-square)](https://hacktoberfest.appwrite.io)
|
||||||
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord?r=Github)
|
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord?r=Github)
|
||||||
[![Build Status](https://img.shields.io/github/workflow/status/appwrite/appwrite/Tests?label=tests&style=flat-square)](https://github.com/appwrite/appwrite/actions)
|
[![Build Status](https://img.shields.io/github/actions/workflow/status/appwrite/appwrite/tests.yml?branch=master&label=tests&style=flat-square)](https://github.com/appwrite/appwrite/actions)
|
||||||
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite)
|
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite)
|
||||||
|
|
||||||
<!-- [![Docker Pulls](https://img.shields.io/docker/pulls/appwrite/appwrite?color=f02e65&style=flat-square)](https://hub.docker.com/r/appwrite/appwrite) -->
|
<!-- [![Docker Pulls](https://img.shields.io/docker/pulls/appwrite/appwrite?color=f02e65&style=flat-square)](https://hub.docker.com/r/appwrite/appwrite) -->
|
||||||
|
@ -75,7 +75,7 @@ docker run -it --rm \
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||||
--entrypoint="install" \
|
--entrypoint="install" \
|
||||||
appwrite/appwrite:1.2.0
|
appwrite/appwrite:1.2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
@ -87,7 +87,7 @@ docker run -it --rm ^
|
||||||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||||
--entrypoint="install" ^
|
--entrypoint="install" ^
|
||||||
appwrite/appwrite:1.2.0
|
appwrite/appwrite:1.2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
#### PowerShell
|
#### PowerShell
|
||||||
|
@ -97,7 +97,7 @@ docker run -it --rm `
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||||
--entrypoint="install" `
|
--entrypoint="install" `
|
||||||
appwrite/appwrite:1.2.0
|
appwrite/appwrite:1.2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
Once the Docker installation is complete, 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 completing the installation.
|
Once the Docker installation is complete, 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 completing the installation.
|
||||||
|
|
14
SECURITY.md
14
SECURITY.md
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| --------- | ------------------ |
|
||||||
| <= 0.14 | :x: |
|
| <= 0.14.x | :x: |
|
||||||
| 1.15.x | :white_check_mark: |
|
| 0.15.x | :white_check_mark: |
|
||||||
| 1.0.x | :white_check_mark: |
|
| 1.0.x | :white_check_mark: |
|
||||||
| 1.1.x | :white_check_mark: |
|
| 1.1.x | :white_check_mark: |
|
||||||
| 1.2.x | :white_check_mark: |
|
| 1.2.x | :white_check_mark: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
|
Binary file not shown.
BIN
app/assets/dbip/dbip-country-lite-2023-01.mmdb
Normal file
BIN
app/assets/dbip/dbip-country-lite-2023-01.mmdb
Normal file
Binary file not shown.
|
@ -3,7 +3,7 @@
|
||||||
use Appwrite\Auth\Auth;
|
use Appwrite\Auth\Auth;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
$providers = Config::getParam('providers', []);
|
$providers = Config::getParam('providers', []);
|
||||||
$auth = Config::getParam('auth', []);
|
$auth = Config::getParam('auth', []);
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -482,9 +482,9 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => '_APP_STORAGE_DEVICE',
|
'name' => '_APP_STORAGE_DEVICE',
|
||||||
'description' => 'Select default storage device. The default value is \'Local\'. List of supported adapters are \'Local\', \'S3\', \'DOSpaces\', \'Backblaze\', \'Linode\' and \'Wasabi\'.',
|
'description' => 'Select default storage device. The default value is \'local\'. List of supported adapters are \'local\', \'s3\', \'dospaces\', \'backblaze\', \'linode\' and \'wasabi\'.',
|
||||||
'introduction' => '0.13.0',
|
'introduction' => '0.13.0',
|
||||||
'default' => 'Local',
|
'default' => 'local',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'question' => '',
|
'question' => '',
|
||||||
],
|
],
|
||||||
|
|
|
@ -10,8 +10,8 @@ use Appwrite\Event\Mail;
|
||||||
use Appwrite\Event\Phone as EventPhone;
|
use Appwrite\Event\Phone as EventPhone;
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\Host;
|
use Utopia\Validator\Host;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\OpenSSL\OpenSSL;
|
use Appwrite\OpenSSL\OpenSSL;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
use Appwrite\URL\URL as URLParser;
|
use Appwrite\URL\URL as URLParser;
|
||||||
|
@ -29,10 +29,10 @@ use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Exception\Duplicate;
|
use Utopia\Database\Exception\Duplicate;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Database\Validator\UID;
|
use Utopia\Database\Validator\UID;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
|
@ -64,7 +64,7 @@ App::post('/v1/account')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_ACCOUNT)
|
->label('sdk.response.model', Response::MODEL_ACCOUNT)
|
||||||
->label('abuse-limit', 10)
|
->label('abuse-limit', 10)
|
||||||
->param('userId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary'])
|
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary'])
|
||||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||||
|
@ -284,6 +284,12 @@ App::get('/v1/account/sessions/oauth2/:provider')
|
||||||
|
|
||||||
$protocol = $request->getProtocol();
|
$protocol = $request->getProtocol();
|
||||||
$callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
|
$callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
|
||||||
|
$providerEnabled = $project->getAttribute('authProviders', [])[$provider . 'Enabled'] ?? false;
|
||||||
|
|
||||||
|
if (!$providerEnabled) {
|
||||||
|
throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your ' . APP_NAME . ' console to continue.');
|
||||||
|
}
|
||||||
|
|
||||||
$appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? '';
|
$appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? '';
|
||||||
$appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}';
|
$appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}';
|
||||||
|
|
||||||
|
@ -398,6 +404,11 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||||
$validateURL = new URL();
|
$validateURL = new URL();
|
||||||
$appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? '';
|
$appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? '';
|
||||||
$appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}';
|
$appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}';
|
||||||
|
$providerEnabled = $project->getAttribute('authProviders', [])[$provider . 'Enabled'] ?? false;
|
||||||
|
|
||||||
|
if (!$providerEnabled) {
|
||||||
|
throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please enable the provider from your ' . APP_NAME . ' console to continue.');
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($appSecret) && isset($appSecret['version'])) {
|
if (!empty($appSecret) && isset($appSecret['version'])) {
|
||||||
$key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']);
|
$key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']);
|
||||||
|
@ -629,7 +640,7 @@ App::post('/v1/account/sessions/magic-url')
|
||||||
->label('sdk.response.model', Response::MODEL_TOKEN)
|
->label('sdk.response.model', Response::MODEL_TOKEN)
|
||||||
->label('abuse-limit', 10)
|
->label('abuse-limit', 10)
|
||||||
->label('abuse-key', 'url:{url},email:{param-email}')
|
->label('abuse-key', 'url:{url},email:{param-email}')
|
||||||
->param('userId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
|
->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
|
||||||
->inject('request')
|
->inject('request')
|
||||||
|
@ -906,7 +917,7 @@ App::post('/v1/account/sessions/phone')
|
||||||
->label('sdk.response.model', Response::MODEL_TOKEN)
|
->label('sdk.response.model', Response::MODEL_TOKEN)
|
||||||
->label('abuse-limit', 10)
|
->label('abuse-limit', 10)
|
||||||
->label('abuse-key', 'url:{url},email:{param-email}')
|
->label('abuse-key', 'url:{url},email:{param-email}')
|
||||||
->param('userId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.')
|
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.')
|
||||||
->inject('request')
|
->inject('request')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\URL\URL as URLParse;
|
use Appwrite\URL\URL as URLParse;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use chillerlan\QRCode\QRCode;
|
use chillerlan\QRCode\QRCode;
|
||||||
|
@ -242,8 +242,8 @@ App::get('/v1/avatars/favicon')
|
||||||
case 'jpeg':
|
case 'jpeg':
|
||||||
$size = \explode('x', \strtolower($sizes));
|
$size = \explode('x', \strtolower($sizes));
|
||||||
|
|
||||||
$sizeWidth = (int) $size[0] ?? 0;
|
$sizeWidth = (int) ($size[0] ?? 0);
|
||||||
$sizeHeight = (int) $size[1] ?? 0;
|
$sizeHeight = (int) ($size[1] ?? 0);
|
||||||
|
|
||||||
if (($sizeWidth * $sizeHeight) >= $space) {
|
if (($sizeWidth * $sizeHeight) >= $space) {
|
||||||
$space = $sizeWidth * $sizeHeight;
|
$space = $sizeWidth * $sizeHeight;
|
||||||
|
|
|
@ -4,10 +4,10 @@ use Utopia\App;
|
||||||
use Appwrite\Event\Delete;
|
use Appwrite\Event\Delete;
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Utopia\Audit\Audit;
|
use Utopia\Audit\Audit;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\DatetimeValidator;
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Validator\Boolean;
|
use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\FloatValidator;
|
use Utopia\Validator\FloatValidator;
|
||||||
use Utopia\Validator\Integer;
|
use Utopia\Validator\Integer;
|
||||||
|
@ -33,8 +33,8 @@ use Utopia\Database\Exception\Structure as StructureException;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
use Appwrite\Auth\Auth;
|
use Appwrite\Auth\Auth;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\IP;
|
use Utopia\Validator\IP;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Appwrite\Utopia\Database\Validator\Query\Limit;
|
use Appwrite\Utopia\Database\Validator\Query\Limit;
|
||||||
use Appwrite\Utopia\Database\Validator\Query\Offset;
|
use Appwrite\Utopia\Database\Validator\Query\Offset;
|
||||||
|
@ -162,7 +162,7 @@ App::post('/v1/databases')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_DATABASE) // Model for database needs to be created
|
->label('sdk.response.model', Response::MODEL_DATABASE) // Model for database needs to be created
|
||||||
->param('databaseId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('databaseId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
|
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
|
@ -488,9 +488,9 @@ App::post('/v1/databases/:databaseId/collections')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_COLLECTION)
|
->label('sdk.response.model', Response::MODEL_COLLECTION)
|
||||||
->param('databaseId', '', new UID(), 'Database ID.')
|
->param('databaseId', '', new UID(), 'Database ID.')
|
||||||
->param('collectionId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('collectionId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
|
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default no user is granted with any permissions. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](/docs/permissions).', true)
|
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
|
@ -745,7 +745,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
|
||||||
->param('databaseId', '', new UID(), 'Database ID.')
|
->param('databaseId', '', new UID(), 'Database ID.')
|
||||||
->param('collectionId', '', new UID(), 'Collection ID.')
|
->param('collectionId', '', new UID(), 'Collection ID.')
|
||||||
->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.')
|
->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.')
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default the current permission are inherited. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](/docs/permissions).', true)
|
->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->param('enabled', true, new Boolean(), 'Is collection enabled?', true)
|
->param('enabled', true, new Boolean(), 'Is collection enabled?', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
@ -1853,10 +1853,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
||||||
->param('databaseId', '', new UID(), 'Database ID.')
|
->param('databaseId', '', new UID(), 'Database ID.')
|
||||||
->param('documentId', '', new CustomId(), 'Document ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.')
|
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.')
|
||||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default the current user is granted with all permissions. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('user')
|
->inject('user')
|
||||||
|
@ -2244,7 +2244,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
||||||
->param('collectionId', '', new UID(), 'Collection ID.')
|
->param('collectionId', '', new UID(), 'Collection ID.')
|
||||||
->param('documentId', '', new UID(), 'Document ID.')
|
->param('documentId', '', new UID(), 'Document ID.')
|
||||||
->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true)
|
->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true)
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('events')
|
->inject('events')
|
||||||
|
|
|
@ -9,9 +9,9 @@ use Appwrite\Event\Func;
|
||||||
use Appwrite\Event\Validator\Event as ValidatorEvent;
|
use Appwrite\Event\Validator\Event as ValidatorEvent;
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\UID;
|
use Utopia\Database\Validator\UID;
|
||||||
use Appwrite\Usage\Stats;
|
use Appwrite\Usage\Stats;
|
||||||
use Utopia\Storage\Device;
|
use Utopia\Storage\Device;
|
||||||
|
@ -61,7 +61,7 @@ App::post('/v1/functions')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_FUNCTION)
|
->label('sdk.response.model', Response::MODEL_FUNCTION)
|
||||||
->param('functionId', '', new CustomId(), 'Function ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('functionId', '', new CustomId(), 'Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
|
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
|
||||||
->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.')
|
->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution roles. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.')
|
||||||
->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.')
|
->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.')
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Appwrite\Event\Certificate;
|
||||||
use Appwrite\Event\Delete;
|
use Appwrite\Event\Delete;
|
||||||
use Appwrite\Event\Validator\Event;
|
use Appwrite\Event\Validator\Event;
|
||||||
use Appwrite\Network\Validator\CNAME;
|
use Appwrite\Network\Validator\CNAME;
|
||||||
use Appwrite\Network\Validator\Domain as DomainValidator;
|
use Utopia\Validator\Domain as DomainValidator;
|
||||||
use Appwrite\Network\Validator\Origin;
|
use Appwrite\Network\Validator\Origin;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Utopia\Abuse\Adapters\TimeLimit;
|
use Utopia\Abuse\Adapters\TimeLimit;
|
||||||
|
@ -17,11 +17,11 @@ use Utopia\Audit\Audit;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Database\Validator\DatetimeValidator;
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
use Utopia\Database\Validator\UID;
|
use Utopia\Database\Validator\UID;
|
||||||
|
@ -32,7 +32,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects;
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\Boolean;
|
use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\Hostname;
|
use Utopia\Validator\Hostname;
|
||||||
use Utopia\Validator\Integer;
|
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
|
@ -56,7 +55,7 @@ App::post('/v1/projects')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_PROJECT)
|
->label('sdk.response.model', Response::MODEL_PROJECT)
|
||||||
->param('projectId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('projectId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
|
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
|
||||||
->param('teamId', '', new UID(), 'Team unique ID.')
|
->param('teamId', '', new UID(), 'Team unique ID.')
|
||||||
->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn($config) => !$config['disabled']))), 'Project Region.', true)
|
->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn($config) => !$config['disabled']))), 'Project Region.', true)
|
||||||
|
@ -1177,7 +1176,7 @@ App::post('/v1/projects/:projectId/platforms')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_PLATFORM)
|
->label('sdk.response.model', Response::MODEL_PLATFORM)
|
||||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||||
->param('type', null, new WhiteList([Origin::CLIENT_TYPE_WEB, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_LINUX, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_APPLE_IOS, Origin::CLIENT_TYPE_APPLE_MACOS, Origin::CLIENT_TYPE_APPLE_WATCHOS, Origin::CLIENT_TYPE_APPLE_TVOS, Origin::CLIENT_TYPE_ANDROID, Origin::CLIENT_TYPE_UNITY], true), 'Platform type.')
|
->param('type', null, new WhiteList([Origin::CLIENT_TYPE_WEB, Origin::CLIENT_TYPE_FLUTTER_WEB, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_LINUX, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_APPLE_IOS, Origin::CLIENT_TYPE_APPLE_MACOS, Origin::CLIENT_TYPE_APPLE_WATCHOS, Origin::CLIENT_TYPE_APPLE_TVOS, Origin::CLIENT_TYPE_ANDROID, Origin::CLIENT_TYPE_UNITY], true), 'Platform type.')
|
||||||
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
|
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
|
||||||
->param('key', '', new Text(256), 'Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.', true)
|
->param('key', '', new Text(256), 'Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.', true)
|
||||||
->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true)
|
->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true)
|
||||||
|
|
|
@ -16,10 +16,10 @@ use Utopia\Database\Exception\Duplicate;
|
||||||
use Utopia\Database\Exception\Authorization as AuthorizationException;
|
use Utopia\Database\Exception\Authorization as AuthorizationException;
|
||||||
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||||
use Utopia\Database\Exception\Structure as StructureException;
|
use Utopia\Database\Exception\Structure as StructureException;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Database\Validator\Permissions;
|
use Utopia\Database\Validator\Permissions;
|
||||||
use Utopia\Database\Validator\UID;
|
use Utopia\Database\Validator\UID;
|
||||||
|
@ -58,14 +58,14 @@ App::post('/v1/storage/buckets')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_BUCKET)
|
->label('sdk.response.model', Response::MODEL_BUCKET)
|
||||||
->param('bucketId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('bucketId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('name', '', new Text(128), 'Bucket name')
|
->param('name', '', new Text(128), 'Bucket name')
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default no user is granted with any permissions. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true)
|
->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
||||||
->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
||||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||||
->param('compression', 'none', new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
||||||
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
||||||
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
@ -232,12 +232,12 @@ App::put('/v1/storage/buckets/:bucketId')
|
||||||
->label('sdk.response.model', Response::MODEL_BUCKET)
|
->label('sdk.response.model', Response::MODEL_BUCKET)
|
||||||
->param('bucketId', '', new UID(), 'Bucket unique ID.')
|
->param('bucketId', '', new UID(), 'Bucket unique ID.')
|
||||||
->param('name', null, new Text(128), 'Bucket name', false)
|
->param('name', null, new Text(128), 'Bucket name', false)
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true)
|
->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
||||||
->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
||||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||||
->param('compression', 'none', new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
||||||
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
||||||
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
@ -347,9 +347,9 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_FILE)
|
->label('sdk.response.model', Response::MODEL_FILE)
|
||||||
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
|
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
|
||||||
->param('fileId', '', new CustomId(), 'File ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('fileId', '', new CustomId(), 'File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('file', [], new File(), 'Binary file.', false)
|
->param('file', [], new File(), 'Binary file.', false)
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission strings. By default the current user is granted with all permissions. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->inject('request')
|
->inject('request')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
|
@ -501,7 +501,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($chunksUploaded === $chunks) {
|
if ($chunksUploaded === $chunks) {
|
||||||
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled' && $bucket->getAttribute('antivirus', true) && $fileSize <= APP_LIMIT_ANTIVIRUS && App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) === Storage::DEVICE_LOCAL) {
|
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled' && $bucket->getAttribute('antivirus', true) && $fileSize <= APP_LIMIT_ANTIVIRUS && strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) === Storage::DEVICE_LOCAL) {
|
||||||
$antivirus = new Network(
|
$antivirus = new Network(
|
||||||
App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'),
|
App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'),
|
||||||
(int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)
|
(int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)
|
||||||
|
@ -516,14 +516,14 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
$mimeType = $deviceFiles->getFileMimeType($path); // Get mime-type before compression and encryption
|
$mimeType = $deviceFiles->getFileMimeType($path); // Get mime-type before compression and encryption
|
||||||
$data = '';
|
$data = '';
|
||||||
// Compression
|
// Compression
|
||||||
$algorithm = $bucket->getAttribute('compression', 'none');
|
$algorithm = $bucket->getAttribute('compression', COMPRESSION_TYPE_NONE);
|
||||||
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != 'none') {
|
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != COMPRESSION_TYPE_NONE) {
|
||||||
$data = $deviceFiles->read($path);
|
$data = $deviceFiles->read($path);
|
||||||
switch ($algorithm) {
|
switch ($algorithm) {
|
||||||
case 'zstd':
|
case COMPRESSION_TYPE_ZSTD:
|
||||||
$compressor = new Zstd();
|
$compressor = new Zstd();
|
||||||
break;
|
break;
|
||||||
case 'gzip':
|
case COMPRESSION_TYPE_GZIP:
|
||||||
default:
|
default:
|
||||||
$compressor = new GZIP();
|
$compressor = new GZIP();
|
||||||
break;
|
break;
|
||||||
|
@ -549,6 +549,11 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
$sizeActual = $deviceFiles->getFileSize($path);
|
$sizeActual = $deviceFiles->getFileSize($path);
|
||||||
$fileHash = $deviceFiles->getFileHash($path);
|
$fileHash = $deviceFiles->getFileHash($path);
|
||||||
|
|
||||||
|
$openSSLVersion = null;
|
||||||
|
$openSSLCipher = null;
|
||||||
|
$openSSLTag = null;
|
||||||
|
$openSSLIV = null;
|
||||||
|
|
||||||
if ($bucket->getAttribute('encryption', true) && $fileSize <= APP_STORAGE_READ_BUFFER) {
|
if ($bucket->getAttribute('encryption', true) && $fileSize <= APP_STORAGE_READ_BUFFER) {
|
||||||
$openSSLVersion = '1';
|
$openSSLVersion = '1';
|
||||||
$openSSLCipher = OpenSSL::CIPHER_AES_128_GCM;
|
$openSSLCipher = OpenSSL::CIPHER_AES_128_GCM;
|
||||||
|
@ -1263,7 +1268,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
||||||
->label('sdk.response.model', Response::MODEL_FILE)
|
->label('sdk.response.model', Response::MODEL_FILE)
|
||||||
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
|
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
|
||||||
->param('fileId', '', new UID(), 'File unique ID.')
|
->param('fileId', '', new UID(), 'File unique ID.')
|
||||||
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission string. By default the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true)
|
->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](/docs/permissions).', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('user')
|
->inject('user')
|
||||||
|
|
|
@ -8,7 +8,7 @@ use Appwrite\Event\Event;
|
||||||
use Appwrite\Event\Mail;
|
use Appwrite\Event\Mail;
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\Host;
|
use Utopia\Validator\Host;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Appwrite\Utopia\Database\Validator\Queries;
|
use Appwrite\Utopia\Database\Validator\Queries;
|
||||||
|
@ -27,11 +27,11 @@ use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\Exception\Authorization as AuthorizationException;
|
use Utopia\Database\Exception\Authorization as AuthorizationException;
|
||||||
use Utopia\Database\Exception\Duplicate;
|
use Utopia\Database\Exception\Duplicate;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Database\Validator\Key;
|
use Utopia\Database\Validator\Key;
|
||||||
use Utopia\Database\Validator\UID;
|
use Utopia\Database\Validator\UID;
|
||||||
|
@ -56,7 +56,7 @@ App::post('/v1/teams')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_TEAM)
|
->label('sdk.response.model', Response::MODEL_TEAM)
|
||||||
->param('teamId', '', new CustomId(), 'Team ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('teamId', '', new CustomId(), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('name', null, new Text(128), 'Team name. Max length: 128 chars.')
|
->param('name', null, new Text(128), 'Team name. Max length: 128 chars.')
|
||||||
->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true)
|
->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
|
|
@ -16,9 +16,9 @@ use Appwrite\Utopia\Response;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Audit\Audit;
|
use Utopia\Audit\Audit;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
|
@ -103,7 +103,7 @@ App::post('/v1/users')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', null, new Email(), 'User email.', true)
|
->param('email', null, new Email(), 'User email.', true)
|
||||||
->param('phone', null, new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
->param('phone', null, new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'Plain text user password. Must be at least 8 chars.', true, ['project', 'passwordsDictionary'])
|
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'Plain text user password. Must be at least 8 chars.', true, ['project', 'passwordsDictionary'])
|
||||||
|
@ -136,7 +136,7 @@ App::post('/v1/users/bcrypt')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password hashed using Bcrypt.')
|
->param('password', '', new Password(), 'User password hashed using Bcrypt.')
|
||||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||||
|
@ -167,7 +167,7 @@ App::post('/v1/users/md5')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password hashed using MD5.')
|
->param('password', '', new Password(), 'User password hashed using MD5.')
|
||||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||||
|
@ -198,7 +198,7 @@ App::post('/v1/users/argon2')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password hashed using Argon2.')
|
->param('password', '', new Password(), 'User password hashed using Argon2.')
|
||||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||||
|
@ -229,7 +229,7 @@ App::post('/v1/users/sha')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password hashed using SHA.')
|
->param('password', '', new Password(), 'User password hashed using SHA.')
|
||||||
->param('passwordVersion', '', new WhiteList(['sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512']), "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", true)
|
->param('passwordVersion', '', new WhiteList(['sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512']), "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", true)
|
||||||
|
@ -267,7 +267,7 @@ App::post('/v1/users/phpass')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password hashed using PHPass.')
|
->param('password', '', new Password(), 'User password hashed using PHPass.')
|
||||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||||
|
@ -298,7 +298,7 @@ App::post('/v1/users/scrypt')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password hashed using Scrypt.')
|
->param('password', '', new Password(), 'User password hashed using Scrypt.')
|
||||||
->param('passwordSalt', '', new Text(128), 'Optional salt used to hash password.')
|
->param('passwordSalt', '', new Text(128), 'Optional salt used to hash password.')
|
||||||
|
@ -342,7 +342,7 @@ App::post('/v1/users/scrypt-modified')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_USER)
|
->label('sdk.response.model', Response::MODEL_USER)
|
||||||
->param('userId', '', new CustomId(), 'User ID. Choose your own unique ID or pass the string `ID.unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password hashed using Scrypt Modified.')
|
->param('password', '', new Password(), 'User password hashed using Scrypt Modified.')
|
||||||
->param('passwordSalt', '', new Text(128), 'Salt used to hash password.')
|
->param('passwordSalt', '', new Text(128), 'Salt used to hash password.')
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
require_once __DIR__ . '/../init.php';
|
require_once __DIR__ . '/../init.php';
|
||||||
|
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
use Utopia\Logger\Logger;
|
use Utopia\Logger\Logger;
|
||||||
use Utopia\Logger\Log;
|
use Utopia\Logger\Log;
|
||||||
|
|
|
@ -4,7 +4,7 @@ global $utopia, $request, $response;
|
||||||
|
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Appwrite\Network\Validator\Host;
|
use Utopia\Validator\Host;
|
||||||
use Appwrite\Utopia\Request;
|
use Appwrite\Utopia\Request;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Appwrite\Utopia\Response\Model;
|
use Appwrite\Utopia\Response\Model;
|
||||||
|
@ -14,7 +14,7 @@ use Utopia\Validator\Integer;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Storage\Validator\File;
|
use Utopia\Storage\Validator\File;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
App::get('/v1/mock/tests/foo')
|
App::get('/v1/mock/tests/foo')
|
||||||
->desc('Get Foo')
|
->desc('Get Foo')
|
||||||
|
|
|
@ -119,7 +119,7 @@ function logError(Throwable $error, string $action, Utopia\Route $route = null)
|
||||||
|
|
||||||
function getStorageDevice($root): Device
|
function getStorageDevice($root): Device
|
||||||
{
|
{
|
||||||
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
|
switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL))) {
|
||||||
case Storage::DEVICE_LOCAL:
|
case Storage::DEVICE_LOCAL:
|
||||||
default:
|
default:
|
||||||
return new Local($root);
|
return new Local($root);
|
||||||
|
@ -548,6 +548,10 @@ App::post('/v1/execution')
|
||||||
case $statusCode >= 500:
|
case $statusCode >= 500:
|
||||||
$stderr = ($executorResponse ?? [])['stderr'] ?? 'Internal Runtime error.';
|
$stderr = ($executorResponse ?? [])['stderr'] ?? 'Internal Runtime error.';
|
||||||
$stdout = ($executorResponse ?? [])['stdout'] ?? 'Internal Runtime error.';
|
$stdout = ($executorResponse ?? [])['stdout'] ?? 'Internal Runtime error.';
|
||||||
|
$res = ($executorResponse ?? [])['response'] ?? '';
|
||||||
|
if (is_array($res)) {
|
||||||
|
$res = json_encode($res, JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case $statusCode >= 100:
|
case $statusCode >= 100:
|
||||||
$stdout = $executorResponse['stdout'];
|
$stdout = $executorResponse['stdout'];
|
||||||
|
|
|
@ -10,9 +10,9 @@ use Swoole\Http\Response as SwooleResponse;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Audit\Audit;
|
use Utopia\Audit\Audit;
|
||||||
use Utopia\Abuse\Adapters\TimeLimit;
|
use Utopia\Abuse\Adapters\TimeLimit;
|
||||||
|
|
23
app/init.php
23
app/init.php
|
@ -33,8 +33,7 @@ use Appwrite\Extend\PDO;
|
||||||
use Appwrite\GraphQL\Promises\Adapter\Swoole;
|
use Appwrite\GraphQL\Promises\Adapter\Swoole;
|
||||||
use Appwrite\GraphQL\Schema;
|
use Appwrite\GraphQL\Schema;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\IP;
|
use Appwrite\Network\Validator\Origin;
|
||||||
use Appwrite\Network\Validator\URL;
|
|
||||||
use Appwrite\OpenSSL\OpenSSL;
|
use Appwrite\OpenSSL\OpenSSL;
|
||||||
use Appwrite\Usage\Stats;
|
use Appwrite\Usage\Stats;
|
||||||
use MaxMind\Db\Reader;
|
use MaxMind\Db\Reader;
|
||||||
|
@ -44,19 +43,19 @@ use Swoole\Database\PDOPool;
|
||||||
use Swoole\Database\RedisConfig;
|
use Swoole\Database\RedisConfig;
|
||||||
use Swoole\Database\RedisPool;
|
use Swoole\Database\RedisPool;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
|
use Utopia\Database\Helpers\ID;
|
||||||
|
use Utopia\Logger\Logger;
|
||||||
use Utopia\Cache\Adapter\Redis as RedisCache;
|
use Utopia\Cache\Adapter\Redis as RedisCache;
|
||||||
use Utopia\Cache\Cache;
|
use Utopia\Cache\Cache;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Database\Adapter\MariaDB;
|
use Utopia\Database\Adapter\MariaDB;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\ID;
|
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Database\Validator\DatetimeValidator;
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
use Utopia\Database\Validator\Structure;
|
use Utopia\Database\Validator\Structure;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
use Utopia\Logger\Logger;
|
|
||||||
use Utopia\Messaging\Adapters\SMS\Mock;
|
use Utopia\Messaging\Adapters\SMS\Mock;
|
||||||
use Utopia\Messaging\Adapters\SMS\Msg91;
|
use Utopia\Messaging\Adapters\SMS\Msg91;
|
||||||
use Utopia\Messaging\Adapters\SMS\Telesign;
|
use Utopia\Messaging\Adapters\SMS\Telesign;
|
||||||
|
@ -73,6 +72,8 @@ use Utopia\Storage\Device\S3;
|
||||||
use Utopia\Storage\Device\Wasabi;
|
use Utopia\Storage\Device\Wasabi;
|
||||||
use Utopia\Storage\Storage;
|
use Utopia\Storage\Storage;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
|
use Utopia\Validator\IP;
|
||||||
|
use Utopia\Validator\URL;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
|
|
||||||
const APP_NAME = 'Appwrite';
|
const APP_NAME = 'Appwrite';
|
||||||
|
@ -100,7 +101,7 @@ const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return
|
||||||
const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours
|
const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours
|
||||||
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
|
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
|
||||||
const APP_CACHE_BUSTER = 501;
|
const APP_CACHE_BUSTER = 501;
|
||||||
const APP_VERSION_STABLE = '1.2.0';
|
const APP_VERSION_STABLE = '1.2.1';
|
||||||
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
|
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
|
||||||
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
|
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
|
||||||
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
|
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
|
||||||
|
@ -605,7 +606,7 @@ $register->set('smtp', function () {
|
||||||
return $mail;
|
return $mail;
|
||||||
});
|
});
|
||||||
$register->set('geodb', function () {
|
$register->set('geodb', function () {
|
||||||
return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2022-06.mmdb');
|
return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2023-01.mmdb');
|
||||||
});
|
});
|
||||||
$register->set('passwordsDictionary', function () {
|
$register->set('passwordsDictionary', function () {
|
||||||
$content = \file_get_contents(__DIR__ . '/assets/security/10k-common-passwords');
|
$content = \file_get_contents(__DIR__ . '/assets/security/10k-common-passwords');
|
||||||
|
@ -761,7 +762,7 @@ App::setResource('clients', function ($request, $console, $project) {
|
||||||
$console->setAttribute('platforms', [ // Always allow current host
|
$console->setAttribute('platforms', [ // Always allow current host
|
||||||
'$collection' => ID::custom('platforms'),
|
'$collection' => ID::custom('platforms'),
|
||||||
'name' => 'Current Host',
|
'name' => 'Current Host',
|
||||||
'type' => 'web',
|
'type' => Origin::CLIENT_TYPE_WEB,
|
||||||
'hostname' => $request->getHostname(),
|
'hostname' => $request->getHostname(),
|
||||||
], Document::SET_TYPE_APPEND);
|
], Document::SET_TYPE_APPEND);
|
||||||
|
|
||||||
|
@ -773,7 +774,7 @@ App::setResource('clients', function ($request, $console, $project) {
|
||||||
fn ($node) => $node['hostname'],
|
fn ($node) => $node['hostname'],
|
||||||
\array_filter(
|
\array_filter(
|
||||||
$console->getAttribute('platforms', []),
|
$console->getAttribute('platforms', []),
|
||||||
fn ($node) => (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname']))
|
fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && isset($node['hostname']) && !empty($node['hostname']))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -784,7 +785,7 @@ App::setResource('clients', function ($request, $console, $project) {
|
||||||
fn ($node) => $node['hostname'],
|
fn ($node) => $node['hostname'],
|
||||||
\array_filter(
|
\array_filter(
|
||||||
$project->getAttribute('platforms', []),
|
$project->getAttribute('platforms', []),
|
||||||
fn ($node) => (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname']))
|
fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB || $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && isset($node['hostname']) && !empty($node['hostname']))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -917,7 +918,7 @@ App::setResource('console', function () {
|
||||||
[
|
[
|
||||||
'$collection' => ID::custom('platforms'),
|
'$collection' => ID::custom('platforms'),
|
||||||
'name' => 'Localhost',
|
'name' => 'Localhost',
|
||||||
'type' => 'web',
|
'type' => Origin::CLIENT_TYPE_WEB,
|
||||||
'hostname' => 'localhost',
|
'hostname' => 'localhost',
|
||||||
], // Current host is added on app init
|
], // Current host is added on app init
|
||||||
],
|
],
|
||||||
|
@ -975,7 +976,7 @@ App::setResource('deviceBuilds', function ($project) {
|
||||||
|
|
||||||
function getDevice($root): Device
|
function getDevice($root): Device
|
||||||
{
|
{
|
||||||
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
|
switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL))) {
|
||||||
case Storage::DEVICE_LOCAL:
|
case Storage::DEVICE_LOCAL:
|
||||||
default:
|
default:
|
||||||
return new Local($root);
|
return new Local($root);
|
||||||
|
|
|
@ -13,8 +13,8 @@ use Utopia\Abuse\Abuse;
|
||||||
use Utopia\Abuse\Adapters\TimeLimit;
|
use Utopia\Abuse\Adapters\TimeLimit;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Logger\Log;
|
use Utopia\Logger\Log;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
|
@ -237,7 +237,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
||||||
'data' => [
|
'data' => [
|
||||||
'events' => ['stats.connections'],
|
'events' => ['stats.connections'],
|
||||||
'channels' => ['project'],
|
'channels' => ['project'],
|
||||||
'timestamp' => DateTime::now(),
|
'timestamp' => DateTime::formatTz(DateTime::now()),
|
||||||
'payload' => [
|
'payload' => [
|
||||||
$projectId => $payload[$projectId]
|
$projectId => $payload[$projectId]
|
||||||
]
|
]
|
||||||
|
@ -264,7 +264,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
||||||
'data' => [
|
'data' => [
|
||||||
'events' => ['test.event'],
|
'events' => ['test.event'],
|
||||||
'channels' => ['tests'],
|
'channels' => ['tests'],
|
||||||
'timestamp' => DateTime::now(),
|
'timestamp' => DateTime::formatTz(DateTime::now()),
|
||||||
'payload' => $payload
|
'payload' => $payload
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
|
@ -509,6 +509,7 @@ services:
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-messaging
|
container_name: appwrite-worker-messaging
|
||||||
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
@ -40,6 +40,7 @@ class AuditsV1 extends Worker
|
||||||
$dbForProject = $this->getProjectDB($project->getId());
|
$dbForProject = $this->getProjectDB($project->getId());
|
||||||
$audit = new Audit($dbForProject);
|
$audit = new Audit($dbForProject);
|
||||||
$audit->log(
|
$audit->log(
|
||||||
|
userInternalId: $user->getInternalId(),
|
||||||
userId: $user->getId(),
|
userId: $user->getId(),
|
||||||
// Pass first, most verbose event pattern
|
// Pass first, most verbose event pattern
|
||||||
event: $event,
|
event: $event,
|
||||||
|
|
|
@ -11,7 +11,7 @@ use Utopia\Database\Database;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Storage\Storage;
|
use Utopia\Storage\Storage;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
|
@ -91,7 +91,7 @@ class BuildsV1 extends Worker
|
||||||
'outputPath' => '',
|
'outputPath' => '',
|
||||||
'runtime' => $function->getAttribute('runtime'),
|
'runtime' => $function->getAttribute('runtime'),
|
||||||
'source' => $deployment->getAttribute('path'),
|
'source' => $deployment->getAttribute('path'),
|
||||||
'sourceType' => App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL),
|
'sourceType' => strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)),
|
||||||
'stdout' => '',
|
'stdout' => '',
|
||||||
'stderr' => '',
|
'stderr' => '',
|
||||||
'endTime' => null,
|
'endTime' => null,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Utopia\CLI\Console;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Domains\Domain;
|
use Utopia\Domains\Domain;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
|
|
|
@ -44,9 +44,6 @@ class DeletesV1 extends Worker
|
||||||
case DELETE_TYPE_DATABASES:
|
case DELETE_TYPE_DATABASES:
|
||||||
$this->deleteDatabase($document, $project->getId());
|
$this->deleteDatabase($document, $project->getId());
|
||||||
break;
|
break;
|
||||||
case DELETE_TYPE_COLLECTIONS:
|
|
||||||
$this->deleteCollection($document, $project->getId());
|
|
||||||
break;
|
|
||||||
case DELETE_TYPE_PROJECTS:
|
case DELETE_TYPE_PROJECTS:
|
||||||
$this->deleteProject($document);
|
$this->deleteProject($document);
|
||||||
break;
|
break;
|
||||||
|
@ -66,6 +63,10 @@ class DeletesV1 extends Worker
|
||||||
$this->deleteBucket($document, $project->getId());
|
$this->deleteBucket($document, $project->getId());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (\str_starts_with($document->getCollection(), 'database_')) {
|
||||||
|
$this->deleteCollection($document, $project->getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
Console::error('No lazy delete operation available for document of type: ' . $document->getCollection());
|
Console::error('No lazy delete operation available for document of type: ' . $document->getCollection());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +173,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document database document
|
* @param Document $document database document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteDatabase(Document $document, string $projectId): void
|
protected function deleteDatabase(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -191,6 +193,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document teams document
|
* @param Document $document teams document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteCollection(Document $document, string $projectId): void
|
protected function deleteCollection(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -217,6 +220,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $hourlyUsageRetentionDatetime
|
* @param string $hourlyUsageRetentionDatetime
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteUsageStats(string $hourlyUsageRetentionDatetime)
|
protected function deleteUsageStats(string $hourlyUsageRetentionDatetime)
|
||||||
{
|
{
|
||||||
|
@ -232,6 +236,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document teams document
|
* @param Document $document teams document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteMemberships(Document $document, string $projectId): void
|
protected function deleteMemberships(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -245,25 +250,62 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Document $document project document
|
* @param Document $document project document
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteProject(Document $document): void
|
protected function deleteProject(Document $document): void
|
||||||
{
|
{
|
||||||
$projectId = $document->getId();
|
$projectId = $document->getId();
|
||||||
|
|
||||||
// Delete all DBs
|
// Delete project domains and certificates
|
||||||
$this->getProjectDB($projectId)->delete($projectId);
|
$dbForConsole = $this->getConsoleDB();
|
||||||
|
|
||||||
|
$domains = $dbForConsole->find('domains', [
|
||||||
|
Query::equal('projectInternalId', [$document->getInternalId()])
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($domains as $domain) {
|
||||||
|
$this->deleteCertificates($domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete project tables
|
||||||
|
$dbForProject = $this->getProjectDB($projectId, $document);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
$collections = $dbForProject->listCollections();
|
||||||
|
|
||||||
|
if (empty($collections)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($collections as $collection) {
|
||||||
|
$dbForProject->deleteCollection($collection->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete metadata tables
|
||||||
|
try {
|
||||||
|
$dbForProject->deleteCollection('_metadata');
|
||||||
|
} catch (Exception) {
|
||||||
|
// Ignore: deleteCollection tries to delete a metadata entry after the collection is deleted,
|
||||||
|
// which will throw an exception here because the metadata collection is already deleted.
|
||||||
|
}
|
||||||
|
|
||||||
// Delete all storage directories
|
// Delete all storage directories
|
||||||
$uploads = $this->getFilesDevice($document->getId());
|
$uploads = $this->getFilesDevice($projectId);
|
||||||
$cache = new Local(APP_STORAGE_CACHE . '/app-' . $document->getId());
|
$functions = $this->getFunctionsDevice($projectId);
|
||||||
|
$builds = $this->getBuildsDevice($projectId);
|
||||||
|
$cache = $this->getCacheDevice($projectId);
|
||||||
|
|
||||||
$uploads->delete($uploads->getRoot(), true);
|
$uploads->delete($uploads->getRoot(), true);
|
||||||
|
$functions->delete($functions->getRoot(), true);
|
||||||
|
$builds->delete($builds->getRoot(), true);
|
||||||
$cache->delete($cache->getRoot(), true);
|
$cache->delete($cache->getRoot(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Document $document user document
|
* @param Document $document user document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteUser(Document $document, string $projectId): void
|
protected function deleteUser(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -305,6 +347,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $datetime
|
* @param string $datetime
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteExecutionLogs(string $datetime): void
|
protected function deleteExecutionLogs(string $datetime): void
|
||||||
{
|
{
|
||||||
|
@ -337,6 +380,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $datetime
|
* @param string $datetime
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteRealtimeUsage(string $datetime): void
|
protected function deleteRealtimeUsage(string $datetime): void
|
||||||
{
|
{
|
||||||
|
@ -393,6 +437,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param string $resource
|
* @param string $resource
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteAuditLogsByResource(string $resource, string $projectId): void
|
protected function deleteAuditLogsByResource(string $resource, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -406,6 +451,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document function document
|
* @param Document $document function document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteFunction(Document $document, string $projectId): void
|
protected function deleteFunction(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -479,6 +525,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document deployment document
|
* @param Document $document deployment document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteDeployment(Document $document, string $projectId): void
|
protected function deleteDeployment(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -528,9 +575,10 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document to be deleted
|
* @param Document $document to be deleted
|
||||||
* @param Database $database to delete it from
|
* @param Database $database to delete it from
|
||||||
* @param callable $callback to perform after document is deleted
|
* @param callable|null $callback to perform after document is deleted
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @throws \Utopia\Database\Exception\Authorization
|
||||||
*/
|
*/
|
||||||
protected function deleteById(Document $document, Database $database, callable $callback = null): bool
|
protected function deleteById(Document $document, Database $database, callable $callback = null): bool
|
||||||
{
|
{
|
||||||
|
@ -550,6 +598,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable $callback
|
* @param callable $callback
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteForProjectIds(callable $callback): void
|
protected function deleteForProjectIds(callable $callback): void
|
||||||
{
|
{
|
||||||
|
@ -584,9 +633,10 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $collection collectionID
|
* @param string $collection collectionID
|
||||||
* @param Query[] $queries
|
* @param array $queries
|
||||||
* @param Database $database
|
* @param Database $database
|
||||||
* @param callable $callback
|
* @param callable|null $callback
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
|
protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
|
||||||
{
|
{
|
||||||
|
@ -620,6 +670,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Document $document certificates document
|
* @param Document $document certificates document
|
||||||
|
* @throws \Utopia\Database\Exception\Authorization
|
||||||
*/
|
*/
|
||||||
protected function deleteCertificates(Document $document): void
|
protected function deleteCertificates(Document $document): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,10 @@ use Utopia\Config\Config;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
require_once __DIR__ . '/../init.php';
|
require_once __DIR__ . '/../init.php';
|
||||||
|
|
||||||
|
|
|
@ -43,21 +43,21 @@
|
||||||
"ext-sockets": "*",
|
"ext-sockets": "*",
|
||||||
"appwrite/php-clamav": "1.1.*",
|
"appwrite/php-clamav": "1.1.*",
|
||||||
"appwrite/php-runtimes": "0.11.*",
|
"appwrite/php-runtimes": "0.11.*",
|
||||||
"utopia-php/abuse": "0.16.*",
|
"utopia-php/abuse": "0.18.*",
|
||||||
"utopia-php/analytics": "0.2.*",
|
"utopia-php/analytics": "0.2.*",
|
||||||
"utopia-php/audit": "0.17.*",
|
"utopia-php/audit": "0.20.*",
|
||||||
"utopia-php/cache": "0.8.*",
|
"utopia-php/cache": "0.8.*",
|
||||||
"utopia-php/cli": "0.13.*",
|
"utopia-php/cli": "0.13.*",
|
||||||
"utopia-php/config": "0.2.*",
|
"utopia-php/config": "0.2.*",
|
||||||
"utopia-php/database": "0.28.*",
|
"utopia-php/database": "0.30.*",
|
||||||
|
"utopia-php/preloader": "0.2.*",
|
||||||
"utopia-php/domains": "1.1.*",
|
"utopia-php/domains": "1.1.*",
|
||||||
"utopia-php/framework": "0.25.*",
|
"utopia-php/framework": "0.26.*",
|
||||||
"utopia-php/image": "0.5.*",
|
"utopia-php/image": "0.5.*",
|
||||||
"utopia-php/locale": "0.4.*",
|
"utopia-php/locale": "0.4.*",
|
||||||
"utopia-php/logger": "0.3.*",
|
"utopia-php/logger": "0.3.*",
|
||||||
"utopia-php/messaging": "0.1.*",
|
"utopia-php/messaging": "0.1.*",
|
||||||
"utopia-php/orchestration": "0.6.*",
|
"utopia-php/orchestration": "0.6.*",
|
||||||
"utopia-php/preloader": "0.2.*",
|
|
||||||
"utopia-php/registry": "0.5.*",
|
"utopia-php/registry": "0.5.*",
|
||||||
"utopia-php/storage": "0.13.*",
|
"utopia-php/storage": "0.13.*",
|
||||||
"utopia-php/swoole": "0.5.*",
|
"utopia-php/swoole": "0.5.*",
|
||||||
|
|
591
composer.lock
generated
591
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -554,6 +554,7 @@ services:
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-messaging
|
container_name: appwrite-worker-messaging
|
||||||
|
restart: unless-stopped
|
||||||
image: appwrite-dev
|
image: appwrite-dev
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
|
|
|
@ -41,11 +41,10 @@ App::init()
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. The Labels Mechanism
|
### 4. The Labels Mechanism
|
||||||
|
Labels are very straightforward and easy to use and understand, but at the same time are very robust.
|
||||||
Labels are very strait forward and easy to use and understand, but in the same time are very robust.
|
|
||||||
Labels are passed from the controllers route and used to pick up key-value pairs to be handled in a centralized place
|
Labels are passed from the controllers route and used to pick up key-value pairs to be handled in a centralized place
|
||||||
along the road.
|
along the road.
|
||||||
Labels can be used to pass a pattern in order to be replaced in the other end.
|
Labels can be used to pass a pattern in order to be replaced on the other end.
|
||||||
Appwrite uses different labels to achieve different things, for example:
|
Appwrite uses different labels to achieve different things, for example:
|
||||||
|
|
||||||
#### Scope
|
#### Scope
|
||||||
|
@ -58,6 +57,9 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Audit
|
#### Audit
|
||||||
|
* audits.event - Identify the log in human-readable text.
|
||||||
|
* audits.userId - Signals the extraction of userId in places that it's not available natively.
|
||||||
|
* audits.resource - Signals the extraction part of the resource.
|
||||||
|
|
||||||
- audits.event - Identify the log in human-readable text.
|
- audits.event - Identify the log in human-readable text.
|
||||||
- audits.userId - Signals the extraction of $userId in places that it's not available natively.
|
- audits.userId - Signals the extraction of $userId in places that it's not available natively.
|
||||||
|
@ -71,13 +73,12 @@ App::post('/v1/account/create')
|
||||||
```
|
```
|
||||||
|
|
||||||
#### SDK
|
#### SDK
|
||||||
|
* sdk.auth - Array of authentication types is passed in order to impose different authentication methods in different situations.
|
||||||
- sdk.auth - Array of authentication types is passed in order to impose different authentication methods in different situations.
|
* sdk.namespace - Refers to the route namespace.
|
||||||
- sdk.namespace - Refers to the route namespace.
|
* sdk.method - Refers to the sdk method that needs to called.
|
||||||
- sdk.method - Refers to the sdk method that needs to called.
|
* sdk.description - Description of the route, using markdown format.
|
||||||
- sdk.description - Description of the route,using markdown format.
|
* sdk.sdk.response.code - Refers to the route http response status code expected.
|
||||||
- sdk.sdk.response.code - Refers to the route http response status code expected.
|
* sdk.auth.response.model - Refers the route http response expected.
|
||||||
- sdk.auth.response.model - Refers the route http response expected.
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
App::post('/v1/account/jwt')
|
App::post('/v1/account/jwt')
|
||||||
|
@ -174,8 +175,7 @@ some code...
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Action
|
### 6. Action
|
||||||
|
Action populates the actual route code and has to be very clear and understandable. A good route stays simple and doesn't contain complex logic. An action is where we describe our business needs in code, and combine different libraries to work together and tell our story.
|
||||||
Action populates the actual routes code and has to be very clear and understandable. A good route stay simple and doesn't contain complex logic. An action is where we describe our business need in code, and combine different libraries to work together and tell our story.
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
App::post('/v1/account/sessions/anonymous')
|
App::post('/v1/account/sessions/anonymous')
|
||||||
|
|
|
@ -73,8 +73,7 @@ Internally the runtime can be anything you like as long as it follows the standa
|
||||||
|
|
||||||
The best way to go about writing a runtime is like so:
|
The best way to go about writing a runtime is like so:
|
||||||
Initialize a web server that runs on port 3000 and uses any IP Address (0.0.0.0) and on each `POST` request do the following:
|
Initialize a web server that runs on port 3000 and uses any IP Address (0.0.0.0) and on each `POST` request do the following:
|
||||||
|
1. Check that the `x-internal-challenge` header matches the `INTERNAL_RUNTIME_KEY` environment variable. If not, return an error with a `401` status code and an `unauthorized` error message.
|
||||||
1. Check that the `x-internal-challenge` header matches the `INTERNAL_RUNTIME_KEY` environment variable. If not return an error with a `401` status code and an `unauthorized` error message.
|
|
||||||
2. Decode the executor's JSON POST request. This normally looks like so:
|
2. Decode the executor's JSON POST request. This normally looks like so:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -112,8 +111,8 @@ All errors that occur during the execution of a user's function **MUST** be retu
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"code": 500, // (Int) Use 404 if function not found or use 401 if the x-internal-challenge check failed.
|
"code": 500, // (Int) Use 404 if function not found or use 401 if the x-internal-challenge check fails.
|
||||||
"message": "Error: Tried to divide by 0 \n /usr/code/index.js:80:7" // (String) Try to return a stacktrace and detailed error message if possible. This is shown to the user.
|
"message": "Error: Tried to divide by 0 \n /usr/code/index.js:80:7", // (String) Try to return a stacktrace and detailed error message if possible. This is shown to the user.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -154,8 +153,7 @@ WORKDIR /usr/local/src
|
||||||
COPY . /usr/local/src
|
COPY . /usr/local/src
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, you want to make sure you are adding execute permissions to any scripts you may run, the main ones are `build.sh` and `launch.sh`. You can run commands in Dockerfile's using the `RUN` prefix like so:
|
Next, you want to make sure you are adding execute permissions to any scripts you may run, the main ones are `build.sh` and `launch.sh`. You can run commands in Dockerfile using the `RUN` prefix like so:
|
||||||
|
|
||||||
```
|
```
|
||||||
RUN chmod +x ./build.sh
|
RUN chmod +x ./build.sh
|
||||||
RUN chmod +x ./launch.sh
|
RUN chmod +x ./launch.sh
|
||||||
|
@ -220,7 +218,7 @@ $this->runtimes['dart'] = $dart;
|
||||||
|
|
||||||
This is an example of what you would do for a compiled language such as dart.
|
This is an example of what you would do for a compiled language such as dart.
|
||||||
|
|
||||||
The first line is creating a new language entry, The first parameter is the internal name and the second one is the external one which is what the user will see in Appwrite.
|
The first line is creating a new language entry. The first parameter is the internal name and the second one is the external one which is what the user will see in Appwrite.
|
||||||
|
|
||||||
The second line adds a new version to the language entry, I'll break down the parameters:
|
The second line adds a new version to the language entry, I'll break down the parameters:
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,14 @@ This document is part of the Appwrite contributors' guide. Before you continue r
|
||||||
|
|
||||||
Storage providers help us use various storage services to store our Appwrite data. As of the writing of these lines we already support Local storage, [AWS S3](https://aws.amazon.com/s3/) storage and [Digitalocean Spaces](https://www.digitalocean.com/products/spaces/) storage.
|
Storage providers help us use various storage services to store our Appwrite data. As of the writing of these lines we already support Local storage, [AWS S3](https://aws.amazon.com/s3/) storage and [Digitalocean Spaces](https://www.digitalocean.com/products/spaces/) storage.
|
||||||
|
|
||||||
As the storage library is separated into [utopia-php/storage](https://github.com/utopia-php/storage), adding new storage adapter will consist of two phases. First adding and implementing the new adapter in the [utopia-php/storage](https://github.com/utopia-php/storage) and then adding support to the new storage adapter in Appwrite.
|
As the storage library is separated into [utopia-php/storage](https://github.com/utopia-php/storage), adding a new storage adapter will consist of two phases. First adding and implementing the new adapter in the [utopia-php/storage](https://github.com/utopia-php/storage) and then adding support to the new storage adapter in Appwrite.
|
||||||
|
|
||||||
### Phase 1
|
### Phase 1
|
||||||
|
|
||||||
In phase 1, we will introduce and implement the new device adapter in [utopia-php/storage](https://github.com/utopia-php/storage) library.
|
In phase 1, we will introduce and implement the new device adapter in [utopia-php/storage](https://github.com/utopia-php/storage) library.
|
||||||
|
|
||||||
### Add new adapter
|
### Add new adapter
|
||||||
|
Add a new storage adapter inside the `src/Storage/Device/` folder. Use one of the existing ones as a reference. The new adapter class should extend `Device` class and implement all the required methods.
|
||||||
Add a new storage adapter inside `src/Storage/Device/` folder. Use one of the existing ones as a reference. The new adapter class should extend `Device` class and implement all the required methods.
|
|
||||||
|
|
||||||
Note that the class name should start with a capital letter as PHP FIG standards suggest.
|
Note that the class name should start with a capital letter as PHP FIG standards suggest.
|
||||||
|
|
||||||
|
@ -40,22 +39,19 @@ If everything goes well, create a new pull request in [utopia-php/storage](https
|
||||||
|
|
||||||
In this phase we will add support to the new storage adapter in Appwrite.
|
In this phase we will add support to the new storage adapter in Appwrite.
|
||||||
|
|
||||||
- Note for this to happen, your PR in the first phase should have been merged and new version of [utopia-php/storage](https://github.com/utopia-php/storage) library released.
|
* Note for this to happen, your PR in the first phase should have been merged and a new version of [utopia-php/storage](https://github.com/utopia-php/storage) library released.
|
||||||
|
|
||||||
### Upgrade the utopia-php/storage dependency
|
### Upgrade the utopia-php/storage dependency
|
||||||
|
|
||||||
Upgrade the utopia-php/storage dependency in `composer.json` file.
|
Upgrade the utopia-php/storage dependency in `composer.json` file.
|
||||||
|
|
||||||
### Introduce new environment variables
|
### Introduce new environment variables
|
||||||
|
Introduce new environment variables if the adapter requires new configuration information or to pass in credentials. The storage environment variables are prefixed as `_APP_STORAGE_DEVICE`. Please read [Adding Environment Variables](https://github.com/appwrite/appwrite/blob/master/docs/tutorials/add-environment-variable.md) guidelines in order to properly introduce new environment variables.
|
||||||
If required for the new adapter, may be for credentials, introduce new environment variables. The storage environment variables are prefixed as `_APP_STORAGE_DEVICE`. Please read [Adding Environment Variables]() guidelines in order to properly introduce new environment variables.
|
|
||||||
|
|
||||||
### Implement the device case
|
### Implement the device case
|
||||||
|
In `app/controllers/shared/api.php` inside init function, there are `switch/case` statements for each supported storage device. Implement the instantiation of your device type for your device case. The device cases are the device constants listed in the `uptopa-php/storage/Storage` class.
|
||||||
In `app/controllers/shared/api.php` inside init function, there is a `switch/case` statements for each supported storage device. Implement the instantiation of your device type for your device case. The device cases are the devices constants listed in the `uptopa-php/storage/Storage` class.
|
|
||||||
|
|
||||||
### Test and verify everything works
|
### Test and verify everything works
|
||||||
|
To test you can switch to your newly added device using `_APP_STORAGE_DEVICE` environment variable. Then run `docker compose build && docker compose up -d` in order to build the containers with updated changes. Once the containers are running, login to Appwrite console and create a project. Then in the storage section, try to upload, preview, delete files.
|
||||||
To test you can switch to your newly added device using `_APP_STORAGE_DEVICE` environment variable. Then run `docker compose build && docker compose up -d` in order to build the containers with updated changes. Once the containers are running, login to Appwrite console and create a project. Then in storage section, try to upload, preview, delete files.
|
|
||||||
|
|
||||||
If everything goes well, initiate a pull request to appwrite repository.
|
If everything goes well, initiate a pull request to appwrite repository.
|
||||||
|
|
|
@ -12,7 +12,7 @@ use Appwrite\Auth\Hash\Sha;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Database\Validator\Roles;
|
use Utopia\Database\Validator\Roles;
|
||||||
|
|
||||||
|
|
|
@ -228,18 +228,18 @@ class Mapper
|
||||||
case 'Appwrite\Network\Validator\CNAME':
|
case 'Appwrite\Network\Validator\CNAME':
|
||||||
case 'Appwrite\Task\Validator\Cron':
|
case 'Appwrite\Task\Validator\Cron':
|
||||||
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
||||||
case 'Appwrite\Network\Validator\Domain':
|
case 'Utopia\Validator\Domain':
|
||||||
case 'Appwrite\Network\Validator\Email':
|
case 'Appwrite\Network\Validator\Email':
|
||||||
case 'Appwrite\Event\Validator\Event':
|
case 'Appwrite\Event\Validator\Event':
|
||||||
case 'Utopia\Validator\HexColor':
|
case 'Utopia\Validator\HexColor':
|
||||||
case 'Appwrite\Network\Validator\Host':
|
case 'Utopia\Validator\Host':
|
||||||
case 'Appwrite\Network\Validator\IP':
|
case 'Utopia\Validator\IP':
|
||||||
case 'Utopia\Database\Validator\Key':
|
case 'Utopia\Database\Validator\Key':
|
||||||
case 'Appwrite\Network\Validator\Origin':
|
case 'Utopia\Validator\Origin':
|
||||||
case 'Appwrite\Auth\Validator\Password':
|
case 'Appwrite\Auth\Validator\Password':
|
||||||
case 'Utopia\Validator\Text':
|
case 'Utopia\Validator\Text':
|
||||||
case 'Utopia\Database\Validator\UID':
|
case 'Utopia\Database\Validator\UID':
|
||||||
case 'Appwrite\Network\Validator\URL':
|
case 'Utopia\Validator\URL':
|
||||||
case 'Utopia\Validator\WhiteList':
|
case 'Utopia\Validator\WhiteList':
|
||||||
default:
|
default:
|
||||||
$type = Type::string();
|
$type = Type::string();
|
||||||
|
|
|
@ -6,8 +6,8 @@ use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Appwrite\Messaging\Adapter;
|
use Appwrite\Messaging\Adapter;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class Realtime extends Adapter
|
class Realtime extends Adapter
|
||||||
{
|
{
|
||||||
|
@ -149,7 +149,7 @@ class Realtime extends Adapter
|
||||||
'data' => [
|
'data' => [
|
||||||
'events' => $events,
|
'events' => $events,
|
||||||
'channels' => $channels,
|
'channels' => $channels,
|
||||||
'timestamp' => DateTime::now(),
|
'timestamp' => DateTime::formatTz(DateTime::now()),
|
||||||
'payload' => $payload
|
'payload' => $payload
|
||||||
]
|
]
|
||||||
]));
|
]));
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Utopia\CLI\Console;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
|
|
||||||
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
||||||
|
@ -49,6 +49,7 @@ abstract class Migration
|
||||||
'1.1.1' => 'V16',
|
'1.1.1' => 'V16',
|
||||||
'1.1.2' => 'V16',
|
'1.1.2' => 'V16',
|
||||||
'1.2.0' => 'V17',
|
'1.2.0' => 'V17',
|
||||||
|
'1.2.1' => 'V17',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,9 +11,9 @@ use Utopia\CLI\Console;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class V15 extends Migration
|
class V15 extends Migration
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,10 @@ class CNAME extends Validator
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$records) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
if (isset($record['target']) && $record['target'] === $this->target) {
|
if (isset($record['target']) && $record['target'] === $this->target) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain
|
|
||||||
*
|
|
||||||
* Validate that an variable is a valid domain address
|
|
||||||
*
|
|
||||||
* @package Utopia\Validator
|
|
||||||
*/
|
|
||||||
class Domain extends Validator
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return 'Value must be a valid domain';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value is valid domain.
|
|
||||||
*
|
|
||||||
* Validates domain names against RFC 1034, RFC 1035, RFC 952, RFC 1123, RFC 2732, RFC 2181, and RFC 1123.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
if (empty($value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_string($value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_DOMAIN) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Utopia\Validator\Hostname;
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Host
|
|
||||||
*
|
|
||||||
* Validate that a host is allowed from given whitelisted hosts list
|
|
||||||
*
|
|
||||||
* @package Utopia\Validator
|
|
||||||
*/
|
|
||||||
class Host extends Validator
|
|
||||||
{
|
|
||||||
protected $whitelist = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $whitelist
|
|
||||||
*/
|
|
||||||
public function __construct(array $whitelist)
|
|
||||||
{
|
|
||||||
$this->whitelist = $whitelist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return 'URL host must be one of: ' . \implode(', ', $this->whitelist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value starts with one of the given hosts
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
// Check if value is valid URL
|
|
||||||
$urlValidator = new URL();
|
|
||||||
|
|
||||||
if (!$urlValidator->isValid($value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$hostname = \parse_url($value, PHP_URL_HOST);
|
|
||||||
$hostnameValidator = new Hostname($this->whitelist);
|
|
||||||
return $hostnameValidator->isValid($hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,114 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IP
|
|
||||||
*
|
|
||||||
* Validate that an variable is a valid IP address
|
|
||||||
*
|
|
||||||
* @package Utopia\Validator
|
|
||||||
*/
|
|
||||||
class IP extends Validator
|
|
||||||
{
|
|
||||||
public const ALL = 'all';
|
|
||||||
public const V4 = 'ipv4';
|
|
||||||
public const V6 = 'ipv6';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $type = self::ALL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* Set a the type of IP check.
|
|
||||||
*
|
|
||||||
* @param string $type
|
|
||||||
*/
|
|
||||||
public function __construct(string $type = self::ALL)
|
|
||||||
{
|
|
||||||
if (!in_array($type, [self::ALL, self::V4, self::V6])) {
|
|
||||||
throw new Exception('Unsupported IP type');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->type = $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return 'Value must be a valid IP address';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value is valid IP address.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
switch ($this->type) {
|
|
||||||
case self::ALL:
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_IP)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case self::V4:
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case self::V6:
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,6 +14,7 @@ class Origin extends Validator
|
||||||
public const CLIENT_TYPE_FLUTTER_MACOS = 'flutter-macos';
|
public const CLIENT_TYPE_FLUTTER_MACOS = 'flutter-macos';
|
||||||
public const CLIENT_TYPE_FLUTTER_WINDOWS = 'flutter-windows';
|
public const CLIENT_TYPE_FLUTTER_WINDOWS = 'flutter-windows';
|
||||||
public const CLIENT_TYPE_FLUTTER_LINUX = 'flutter-linux';
|
public const CLIENT_TYPE_FLUTTER_LINUX = 'flutter-linux';
|
||||||
|
public const CLIENT_TYPE_FLUTTER_WEB = 'flutter-web';
|
||||||
public const CLIENT_TYPE_APPLE_IOS = 'apple-ios';
|
public const CLIENT_TYPE_APPLE_IOS = 'apple-ios';
|
||||||
public const CLIENT_TYPE_APPLE_MACOS = 'apple-macos';
|
public const CLIENT_TYPE_APPLE_MACOS = 'apple-macos';
|
||||||
public const CLIENT_TYPE_APPLE_WATCHOS = 'apple-watchos';
|
public const CLIENT_TYPE_APPLE_WATCHOS = 'apple-watchos';
|
||||||
|
@ -25,8 +26,10 @@ class Origin extends Validator
|
||||||
public const SCHEME_TYPE_HTTP = 'http';
|
public const SCHEME_TYPE_HTTP = 'http';
|
||||||
public const SCHEME_TYPE_HTTPS = 'https';
|
public const SCHEME_TYPE_HTTPS = 'https';
|
||||||
public const SCHEME_TYPE_IOS = 'appwrite-ios';
|
public const SCHEME_TYPE_IOS = 'appwrite-ios';
|
||||||
public const SCHEME_TYPE_ANDROID = 'appwrite-android';
|
|
||||||
public const SCHEME_TYPE_MACOS = 'appwrite-macos';
|
public const SCHEME_TYPE_MACOS = 'appwrite-macos';
|
||||||
|
public const SCHEME_TYPE_WATCHOS = 'appwrite-watchos';
|
||||||
|
public const SCHEME_TYPE_TVOS = 'appwrite-tvos';
|
||||||
|
public const SCHEME_TYPE_ANDROID = 'appwrite-android';
|
||||||
public const SCHEME_TYPE_WINDOWS = 'appwrite-windows';
|
public const SCHEME_TYPE_WINDOWS = 'appwrite-windows';
|
||||||
public const SCHEME_TYPE_LINUX = 'appwrite-linux';
|
public const SCHEME_TYPE_LINUX = 'appwrite-linux';
|
||||||
|
|
||||||
|
@ -37,8 +40,10 @@ class Origin extends Validator
|
||||||
self::SCHEME_TYPE_HTTP => 'Web',
|
self::SCHEME_TYPE_HTTP => 'Web',
|
||||||
self::SCHEME_TYPE_HTTPS => 'Web',
|
self::SCHEME_TYPE_HTTPS => 'Web',
|
||||||
self::SCHEME_TYPE_IOS => 'iOS',
|
self::SCHEME_TYPE_IOS => 'iOS',
|
||||||
self::SCHEME_TYPE_ANDROID => 'Android',
|
|
||||||
self::SCHEME_TYPE_MACOS => 'macOS',
|
self::SCHEME_TYPE_MACOS => 'macOS',
|
||||||
|
self::SCHEME_TYPE_WATCHOS => 'watchOS',
|
||||||
|
self::SCHEME_TYPE_TVOS => 'tvOS',
|
||||||
|
self::SCHEME_TYPE_ANDROID => 'Android',
|
||||||
self::SCHEME_TYPE_WINDOWS => 'Windows',
|
self::SCHEME_TYPE_WINDOWS => 'Windows',
|
||||||
self::SCHEME_TYPE_LINUX => 'Linux',
|
self::SCHEME_TYPE_LINUX => 'Linux',
|
||||||
];
|
];
|
||||||
|
@ -69,6 +74,7 @@ class Origin extends Validator
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case self::CLIENT_TYPE_WEB:
|
case self::CLIENT_TYPE_WEB:
|
||||||
|
case self::CLIENT_TYPE_FLUTTER_WEB:
|
||||||
$this->clients[] = (isset($platform['hostname'])) ? $platform['hostname'] : '';
|
$this->clients[] = (isset($platform['hostname'])) ? $platform['hostname'] : '';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -79,6 +85,9 @@ class Origin extends Validator
|
||||||
case self::CLIENT_TYPE_FLUTTER_LINUX:
|
case self::CLIENT_TYPE_FLUTTER_LINUX:
|
||||||
case self::CLIENT_TYPE_ANDROID:
|
case self::CLIENT_TYPE_ANDROID:
|
||||||
case self::CLIENT_TYPE_APPLE_IOS:
|
case self::CLIENT_TYPE_APPLE_IOS:
|
||||||
|
case self::CLIENT_TYPE_APPLE_MACOS:
|
||||||
|
case self::CLIENT_TYPE_APPLE_WATCHOS:
|
||||||
|
case self::CLIENT_TYPE_APPLE_TVOS:
|
||||||
$this->clients[] = (isset($platform['key'])) ? $platform['key'] : '';
|
$this->clients[] = (isset($platform['key'])) ? $platform['key'] : '';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL
|
|
||||||
*
|
|
||||||
* Validate that an variable is a valid URL
|
|
||||||
*
|
|
||||||
* @package Appwrite\Network\Validator
|
|
||||||
*/
|
|
||||||
class URL extends Validator
|
|
||||||
{
|
|
||||||
protected array $allowedSchemes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $allowedSchemes
|
|
||||||
*/
|
|
||||||
public function __construct(array $allowedSchemes = [])
|
|
||||||
{
|
|
||||||
$this->allowedSchemes = $allowedSchemes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
if (!empty($this->allowedSchemes)) {
|
|
||||||
return 'Value must be a valid URL with following schemes (' . \implode(', ', $this->allowedSchemes) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'Value must be a valid URL';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value is valid URL.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
$sanitizedURL = '';
|
|
||||||
|
|
||||||
foreach (str_split($value) as $character) {
|
|
||||||
$sanitizedURL .= (ord($character) > 127) ? rawurlencode($character) : $character;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (\filter_var($sanitizedURL, FILTER_VALIDATE_URL) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->allowedSchemes) && !\in_array(\parse_url($sanitizedURL, PHP_URL_SCHEME), $this->allowedSchemes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,22 +2,23 @@
|
||||||
|
|
||||||
namespace Appwrite\Resque;
|
namespace Appwrite\Resque;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Cache\Cache;
|
|
||||||
use Utopia\Cache\Adapter\Redis as RedisCache;
|
use Utopia\Cache\Adapter\Redis as RedisCache;
|
||||||
|
use Utopia\Cache\Cache;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
use Utopia\Database\Database;
|
|
||||||
use Utopia\Database\Adapter\MariaDB;
|
use Utopia\Database\Adapter\MariaDB;
|
||||||
|
use Utopia\Database\Database;
|
||||||
|
use Utopia\Database\Document;
|
||||||
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Storage\Device;
|
use Utopia\Storage\Device;
|
||||||
use Utopia\Storage\Storage;
|
use Utopia\Storage\Device\Backblaze;
|
||||||
use Utopia\Storage\Device\Local;
|
|
||||||
use Utopia\Storage\Device\DOSpaces;
|
use Utopia\Storage\Device\DOSpaces;
|
||||||
use Utopia\Storage\Device\Linode;
|
use Utopia\Storage\Device\Linode;
|
||||||
use Utopia\Storage\Device\Wasabi;
|
use Utopia\Storage\Device\Local;
|
||||||
use Utopia\Storage\Device\Backblaze;
|
|
||||||
use Utopia\Storage\Device\S3;
|
use Utopia\Storage\Device\S3;
|
||||||
use Exception;
|
use Utopia\Storage\Device\Wasabi;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Storage\Storage;
|
||||||
|
|
||||||
abstract class Worker
|
abstract class Worker
|
||||||
{
|
{
|
||||||
|
@ -53,7 +54,7 @@ abstract class Worker
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception|\Throwable
|
* @throws \Exception|\Throwable
|
||||||
*/
|
*/
|
||||||
public function init()
|
public function init(): void
|
||||||
{
|
{
|
||||||
throw new Exception("Please implement init method in worker");
|
throw new Exception("Please implement init method in worker");
|
||||||
}
|
}
|
||||||
|
@ -65,7 +66,7 @@ abstract class Worker
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception|\Throwable
|
* @throws \Exception|\Throwable
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run(): void
|
||||||
{
|
{
|
||||||
throw new Exception("Please implement run method in worker");
|
throw new Exception("Please implement run method in worker");
|
||||||
}
|
}
|
||||||
|
@ -77,7 +78,7 @@ abstract class Worker
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception|\Throwable
|
* @throws \Exception|\Throwable
|
||||||
*/
|
*/
|
||||||
public function shutdown()
|
public function shutdown(): void
|
||||||
{
|
{
|
||||||
throw new Exception("Please implement shutdown method in worker");
|
throw new Exception("Please implement shutdown method in worker");
|
||||||
}
|
}
|
||||||
|
@ -151,35 +152,39 @@ abstract class Worker
|
||||||
/**
|
/**
|
||||||
* Register callback. Will be executed when error occurs.
|
* Register callback. Will be executed when error occurs.
|
||||||
* @param callable $callback
|
* @param callable $callback
|
||||||
* @param Throwable $error
|
* @return void
|
||||||
* @return self
|
|
||||||
*/
|
*/
|
||||||
public static function error(callable $callback): void
|
public static function error(callable $callback): void
|
||||||
{
|
{
|
||||||
\array_push(self::$errorCallbacks, $callback);
|
self::$errorCallbacks[] = $callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get internal project database
|
* Get internal project database
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
* @return Database
|
* @return Database
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function getProjectDB(string $projectId): Database
|
protected function getProjectDB(string $projectId, ?Document $project = null): Database
|
||||||
{
|
{
|
||||||
$consoleDB = $this->getConsoleDB();
|
if ($project === null) {
|
||||||
|
$consoleDB = $this->getConsoleDB();
|
||||||
|
|
||||||
if ($projectId === 'console') {
|
if ($projectId === 'console') {
|
||||||
return $consoleDB;
|
return $consoleDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Document $project */
|
||||||
|
$project = Authorization::skip(fn() => $consoleDB->getDocument('projects', $projectId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Document $project */
|
return $this->getDB(self::DATABASE_PROJECT, $projectId, $project->getInternalId(), $project);
|
||||||
$project = Authorization::skip(fn() => $consoleDB->getDocument('projects', $projectId));
|
|
||||||
|
|
||||||
return $this->getDB(self::DATABASE_PROJECT, $projectId, $project->getInternalId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get console database
|
* Get console database
|
||||||
* @return Database
|
* @return Database
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function getConsoleDB(): Database
|
protected function getConsoleDB(): Database
|
||||||
{
|
{
|
||||||
|
@ -187,24 +192,35 @@ abstract class Worker
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get console database
|
* Get database
|
||||||
* @param string $type One of (internal, external, console)
|
* @param string $type One of (project, console)
|
||||||
* @param string $projectId of internal or external DB
|
* @param string $projectId of project or console DB
|
||||||
|
* @param string $projectInternalId
|
||||||
|
* @param Document|null $project
|
||||||
* @return Database
|
* @return Database
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function getDB(string $type, string $projectId = '', string $projectInternalId = ''): Database
|
private function getDB(
|
||||||
{
|
string $type,
|
||||||
|
string $projectId = '',
|
||||||
|
string $projectInternalId = '',
|
||||||
|
?Document $project = null
|
||||||
|
): Database {
|
||||||
global $register;
|
global $register;
|
||||||
|
|
||||||
$namespace = '';
|
|
||||||
$sleep = DATABASE_RECONNECT_SLEEP; // overwritten when necessary
|
$sleep = DATABASE_RECONNECT_SLEEP; // overwritten when necessary
|
||||||
|
|
||||||
|
if ($project !== null) {
|
||||||
|
$projectId = $project->getId();
|
||||||
|
$projectInternalId = $project->getInternalId();
|
||||||
|
}
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case self::DATABASE_PROJECT:
|
case self::DATABASE_PROJECT:
|
||||||
if (!$projectId) {
|
if (!$projectId) {
|
||||||
throw new \Exception('ProjectID not provided - cannot get database');
|
throw new \Exception('ProjectID not provided - cannot get database');
|
||||||
}
|
}
|
||||||
$namespace = "_{$projectInternalId}";
|
$namespace = "_$projectInternalId";
|
||||||
break;
|
break;
|
||||||
case self::DATABASE_CONSOLE:
|
case self::DATABASE_CONSOLE:
|
||||||
$namespace = "_console";
|
$namespace = "_console";
|
||||||
|
@ -212,12 +228,11 @@ abstract class Worker
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \Exception('Unknown database type: ' . $type);
|
throw new \Exception('Unknown database type: ' . $type);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
|
|
||||||
do {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
$attempts++;
|
$attempts++;
|
||||||
$cache = new Cache(new RedisCache($register->get('cache')));
|
$cache = new Cache(new RedisCache($register->get('cache')));
|
||||||
|
@ -225,8 +240,12 @@ abstract class Worker
|
||||||
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
||||||
$database->setNamespace($namespace); // Main DB
|
$database->setNamespace($namespace); // Main DB
|
||||||
|
|
||||||
if (!empty($projectId) && !$database->getDocument('projects', $projectId)->isEmpty()) {
|
if (
|
||||||
throw new \Exception("Project does not exist: {$projectId}");
|
$project === null
|
||||||
|
&& !empty($projectId)
|
||||||
|
&& !$database->getDocument('projects', $projectId)->isEmpty()
|
||||||
|
) {
|
||||||
|
throw new \Exception("Project does not exist: $projectId");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), Database::METADATA)) {
|
if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), Database::METADATA)) {
|
||||||
|
@ -235,13 +254,13 @@ abstract class Worker
|
||||||
|
|
||||||
break; // leave loop if successful
|
break; // leave loop if successful
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Console::warning("Database not ready. Retrying connection ({$attempts})...");
|
Console::warning("Database not ready. Retrying connection ($attempts)...");
|
||||||
if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) {
|
if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) {
|
||||||
throw new \Exception('Failed to connect to database: ' . $e->getMessage());
|
throw new \Exception('Failed to connect to database: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
sleep($sleep);
|
sleep($sleep);
|
||||||
}
|
}
|
||||||
} while ($attempts < DATABASE_RECONNECT_MAX_ATTEMPTS);
|
}
|
||||||
|
|
||||||
return $database;
|
return $database;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +270,7 @@ abstract class Worker
|
||||||
* @param string $projectId of the project
|
* @param string $projectId of the project
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
protected function getFunctionsDevice($projectId): Device
|
protected function getFunctionsDevice(string $projectId): Device
|
||||||
{
|
{
|
||||||
return $this->getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
|
return $this->getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +280,7 @@ abstract class Worker
|
||||||
* @param string $projectId of the project
|
* @param string $projectId of the project
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
protected function getFilesDevice($projectId): Device
|
protected function getFilesDevice(string $projectId): Device
|
||||||
{
|
{
|
||||||
return $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId);
|
return $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId);
|
||||||
}
|
}
|
||||||
|
@ -272,19 +291,24 @@ abstract class Worker
|
||||||
* @param string $projectId of the project
|
* @param string $projectId of the project
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
protected function getBuildsDevice($projectId): Device
|
protected function getBuildsDevice(string $projectId): Device
|
||||||
{
|
{
|
||||||
return $this->getDevice(APP_STORAGE_BUILDS . '/app-' . $projectId);
|
return $this->getDevice(APP_STORAGE_BUILDS . '/app-' . $projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getCacheDevice(string $projectId): Device
|
||||||
|
{
|
||||||
|
return $this->getDevice(APP_STORAGE_CACHE . '/app-' . $projectId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Device based on selected storage environment
|
* Get Device based on selected storage environment
|
||||||
* @param string $root path of the device
|
* @param string $root path of the device
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
public function getDevice($root): Device
|
public function getDevice(string $root): Device
|
||||||
{
|
{
|
||||||
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
|
switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL))) {
|
||||||
case Storage::DEVICE_LOCAL:
|
case Storage::DEVICE_LOCAL:
|
||||||
default:
|
default:
|
||||||
return new Local($root);
|
return new Local($root);
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace Appwrite\Specification\Format;
|
||||||
use Appwrite\Specification\Format;
|
use Appwrite\Specification\Format;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
use Appwrite\Utopia\Response\Model;
|
use Appwrite\Utopia\Response\Model;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Validator;
|
use Utopia\Validator;
|
||||||
|
|
||||||
class OpenAPI3 extends Format
|
class OpenAPI3 extends Format
|
||||||
|
@ -311,7 +311,7 @@ class OpenAPI3 extends Format
|
||||||
$node['schema']['format'] = 'email';
|
$node['schema']['format'] = 'email';
|
||||||
$node['schema']['x-example'] = 'email@example.com';
|
$node['schema']['x-example'] = 'email@example.com';
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\URL':
|
case 'Utopia\Validator\URL':
|
||||||
$node['schema']['type'] = $validator->getType();
|
$node['schema']['type'] = $validator->getType();
|
||||||
$node['schema']['format'] = 'url';
|
$node['schema']['format'] = 'url';
|
||||||
$node['schema']['x-example'] = 'https://example.com';
|
$node['schema']['x-example'] = 'https://example.com';
|
||||||
|
@ -391,7 +391,7 @@ class OpenAPI3 extends Format
|
||||||
case 'Utopia\Validator\Length':
|
case 'Utopia\Validator\Length':
|
||||||
$node['schema']['type'] = $validator->getType();
|
$node['schema']['type'] = $validator->getType();
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\Host':
|
case 'Utopia\Validator\Host':
|
||||||
$node['schema']['type'] = $validator->getType();
|
$node['schema']['type'] = $validator->getType();
|
||||||
$node['schema']['format'] = 'url';
|
$node['schema']['format'] = 'url';
|
||||||
$node['schema']['x-example'] = 'https://example.com';
|
$node['schema']['x-example'] = 'https://example.com';
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace Appwrite\Specification\Format;
|
||||||
use Appwrite\Specification\Format;
|
use Appwrite\Specification\Format;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
use Appwrite\Utopia\Response\Model;
|
use Appwrite\Utopia\Response\Model;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Validator;
|
use Utopia\Validator;
|
||||||
|
|
||||||
class Swagger2 extends Format
|
class Swagger2 extends Format
|
||||||
|
@ -312,7 +312,7 @@ class Swagger2 extends Format
|
||||||
$node['format'] = 'email';
|
$node['format'] = 'email';
|
||||||
$node['x-example'] = 'email@example.com';
|
$node['x-example'] = 'email@example.com';
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\URL':
|
case 'Utopia\Validator\URL':
|
||||||
$node['type'] = $validator->getType();
|
$node['type'] = $validator->getType();
|
||||||
$node['format'] = 'url';
|
$node['format'] = 'url';
|
||||||
$node['x-example'] = 'https://example.com';
|
$node['x-example'] = 'https://example.com';
|
||||||
|
@ -393,7 +393,7 @@ class Swagger2 extends Format
|
||||||
case 'Utopia\Validator\Length':
|
case 'Utopia\Validator\Length':
|
||||||
$node['type'] = $validator->getType();
|
$node['type'] = $validator->getType();
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\Host':
|
case 'Utopia\Validator\Host':
|
||||||
$node['type'] = $validator->getType();
|
$node['type'] = $validator->getType();
|
||||||
$node['format'] = 'url';
|
$node['format'] = 'url';
|
||||||
$node['x-example'] = 'https://example.com';
|
$node['x-example'] = 'https://example.com';
|
||||||
|
|
|
@ -4,9 +4,9 @@ namespace Appwrite\Utopia\Request\Filters;
|
||||||
|
|
||||||
use Appwrite\Utopia\Request\Filter;
|
use Appwrite\Utopia\Request\Filter;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class V15 extends Filter
|
class V15 extends Filter
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace Appwrite\Utopia\Response\Filters;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Appwrite\Utopia\Response\Filter;
|
use Appwrite\Utopia\Response\Filter;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class V15 extends Filter
|
class V15 extends Filter
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model;
|
||||||
|
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Appwrite\Utopia\Response\Model;
|
use Appwrite\Utopia\Response\Model;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class Execution extends Model
|
class Execution extends Model
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Locale extends Model
|
||||||
])
|
])
|
||||||
->addRule('eu', [
|
->addRule('eu', [
|
||||||
'type' => self::TYPE_BOOLEAN,
|
'type' => self::TYPE_BOOLEAN,
|
||||||
'description' => 'True if country is part of the Europian Union.',
|
'description' => 'True if country is part of the European Union.',
|
||||||
'default' => false,
|
'default' => false,
|
||||||
'example' => false,
|
'example' => false,
|
||||||
])
|
])
|
||||||
|
|
|
@ -41,9 +41,9 @@ class Platform extends Model
|
||||||
])
|
])
|
||||||
->addRule('type', [
|
->addRule('type', [
|
||||||
'type' => self::TYPE_STRING,
|
'type' => self::TYPE_STRING,
|
||||||
'description' => 'Platform type. Possible values are: web, flutter-ios, flutter-android, ios, android, and unity.',
|
'description' => 'Platform type. Possible values are: web, flutter-web, flutter-ios, flutter-android, ios, android, and unity.',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'example' => 'My Web App',
|
'example' => 'web',
|
||||||
])
|
])
|
||||||
->addRule('key', [
|
->addRule('key', [
|
||||||
'type' => self::TYPE_STRING,
|
'type' => self::TYPE_STRING,
|
||||||
|
|
|
@ -8,9 +8,9 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideNone;
|
use Tests\E2E\Scopes\SideNone;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class AbuseTest extends Scope
|
class AbuseTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,9 +9,9 @@ use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use CURLFile;
|
use CURLFile;
|
||||||
use Tests\E2E\Services\Functions\FunctionsBase;
|
use Tests\E2E\Services\Functions\FunctionsBase;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
|
|
||||||
class UsageTest extends Scope
|
class UsageTest extends Scope
|
||||||
{
|
{
|
||||||
|
@ -601,6 +601,7 @@ class UsageTest extends Scope
|
||||||
/** @depends testDatabaseStats */
|
/** @depends testDatabaseStats */
|
||||||
public function testPrepareFunctionsStats(array $data): array
|
public function testPrepareFunctionsStats(array $data): array
|
||||||
{
|
{
|
||||||
|
$dateValidator = new DatetimeValidator();
|
||||||
$headers = $data['headers'];
|
$headers = $data['headers'];
|
||||||
$functionId = '';
|
$functionId = '';
|
||||||
$executionTime = 0;
|
$executionTime = 0;
|
||||||
|
@ -642,7 +643,7 @@ class UsageTest extends Scope
|
||||||
|
|
||||||
$this->assertEquals(202, $deployment['headers']['status-code']);
|
$this->assertEquals(202, $deployment['headers']['status-code']);
|
||||||
$this->assertNotEmpty($deployment['body']['$id']);
|
$this->assertNotEmpty($deployment['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($deployment['body']['$createdAt']));
|
$this->assertEquals(true, $dateValidator->isValid($deployment['body']['$createdAt']));
|
||||||
$this->assertEquals('index.php', $deployment['body']['entrypoint']);
|
$this->assertEquals('index.php', $deployment['body']['entrypoint']);
|
||||||
|
|
||||||
// Wait for deployment to build.
|
// Wait for deployment to build.
|
||||||
|
@ -652,8 +653,8 @@ class UsageTest extends Scope
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['$createdAt']));
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['$createdAt']));
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['$updatedAt']));
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['$updatedAt']));
|
||||||
$this->assertEquals($deploymentId, $response['body']['deployment']);
|
$this->assertEquals($deploymentId, $response['body']['deployment']);
|
||||||
|
|
||||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', $headers, [
|
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', $headers, [
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Tests\E2E\Scopes;
|
namespace Tests\E2E\Scopes;
|
||||||
|
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
trait ProjectConsole
|
trait ProjectConsole
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace Tests\E2E\Scopes;
|
namespace Tests\E2E\Scopes;
|
||||||
|
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
trait ProjectCustom
|
trait ProjectCustom
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,21 +5,14 @@ namespace Tests\E2E\Scopes;
|
||||||
use Appwrite\Tests\Retryable;
|
use Appwrite\Tests\Retryable;
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
abstract class Scope extends TestCase
|
abstract class Scope extends TestCase
|
||||||
{
|
{
|
||||||
use Retryable;
|
use Retryable;
|
||||||
|
|
||||||
/**
|
protected ?Client $client = null;
|
||||||
* @var Client
|
protected string $endpoint = 'http://localhost/v1';
|
||||||
*/
|
|
||||||
protected $client = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $endpoint = 'http://localhost/v1';
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,8 +4,9 @@ namespace Tests\E2E\Services\Account;
|
||||||
|
|
||||||
use Appwrite\Tests\Retry;
|
use Appwrite\Tests\Retry;
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
|
|
||||||
trait AccountBase
|
trait AccountBase
|
||||||
{
|
{
|
||||||
|
@ -34,7 +35,8 @@ trait AccountBase
|
||||||
$this->assertEquals($response['headers']['status-code'], 201);
|
$this->assertEquals($response['headers']['status-code'], 201);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
$this->assertEquals($response['body']['name'], $name);
|
$this->assertEquals($response['body']['name'], $name);
|
||||||
|
|
||||||
|
@ -198,7 +200,8 @@ trait AccountBase
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
$this->assertEquals($response['body']['name'], $name);
|
$this->assertEquals($response['body']['name'], $name);
|
||||||
|
|
||||||
|
@ -343,7 +346,8 @@ trait AccountBase
|
||||||
$this->assertIsNumeric($response['body']['total']);
|
$this->assertIsNumeric($response['body']['total']);
|
||||||
$this->assertContains($response['body']['logs'][1]['event'], ["session.create"]);
|
$this->assertContains($response['body']['logs'][1]['event'], ["session.create"]);
|
||||||
$this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP));
|
$this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP));
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['logs'][1]['time']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['logs'][1]['time']));
|
||||||
|
|
||||||
$this->assertEquals('Windows', $response['body']['logs'][1]['osName']);
|
$this->assertEquals('Windows', $response['body']['logs'][1]['osName']);
|
||||||
$this->assertEquals('WIN', $response['body']['logs'][1]['osCode']);
|
$this->assertEquals('WIN', $response['body']['logs'][1]['osCode']);
|
||||||
|
@ -365,7 +369,7 @@ trait AccountBase
|
||||||
|
|
||||||
$this->assertContains($response['body']['logs'][2]['event'], ["user.create"]);
|
$this->assertContains($response['body']['logs'][2]['event'], ["user.create"]);
|
||||||
$this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP));
|
$this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP));
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['logs'][2]['time']));
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['logs'][2]['time']));
|
||||||
|
|
||||||
$this->assertEquals('Windows', $response['body']['logs'][2]['osName']);
|
$this->assertEquals('Windows', $response['body']['logs'][2]['osName']);
|
||||||
$this->assertEquals('WIN', $response['body']['logs'][2]['osCode']);
|
$this->assertEquals('WIN', $response['body']['logs'][2]['osCode']);
|
||||||
|
@ -476,7 +480,8 @@ trait AccountBase
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
$this->assertEquals($response['body']['name'], $newName);
|
$this->assertEquals($response['body']['name'], $newName);
|
||||||
|
|
||||||
|
@ -543,7 +548,8 @@ trait AccountBase
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
|
|
||||||
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
||||||
|
@ -633,7 +639,8 @@ trait AccountBase
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $newEmail);
|
$this->assertEquals($response['body']['email'], $newEmail);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -675,7 +682,7 @@ trait AccountBase
|
||||||
$this->assertEquals($response['headers']['status-code'], 201);
|
$this->assertEquals($response['headers']['status-code'], 201);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $data['email']);
|
$this->assertEquals($response['body']['email'], $data['email']);
|
||||||
$this->assertEquals($response['body']['name'], $data['name']);
|
$this->assertEquals($response['body']['name'], $data['name']);
|
||||||
|
|
||||||
|
@ -817,7 +824,8 @@ trait AccountBase
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEmpty($response['body']['secret']);
|
$this->assertEmpty($response['body']['secret']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['expire']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['expire']));
|
||||||
|
|
||||||
$lastEmail = $this->getLastEmail();
|
$lastEmail = $this->getLastEmail();
|
||||||
|
|
||||||
|
@ -1119,7 +1127,8 @@ trait AccountBase
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEmpty($response['body']['secret']);
|
$this->assertEmpty($response['body']['secret']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['expire']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['expire']));
|
||||||
|
|
||||||
$lastEmail = $this->getLastEmail();
|
$lastEmail = $this->getLastEmail();
|
||||||
|
|
||||||
|
@ -1273,7 +1282,8 @@ trait AccountBase
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEmpty($response['body']['secret']);
|
$this->assertEmpty($response['body']['secret']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['expire']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['expire']));
|
||||||
|
|
||||||
$userId = $response['body']['userId'];
|
$userId = $response['body']['userId'];
|
||||||
|
|
||||||
|
@ -1379,7 +1389,8 @@ trait AccountBase
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
$this->assertTrue($response['body']['emailVerification']);
|
$this->assertTrue($response['body']['emailVerification']);
|
||||||
|
|
||||||
|
@ -1439,7 +1450,8 @@ trait AccountBase
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
|
|
||||||
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
||||||
|
|
|
@ -9,7 +9,8 @@ use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
|
|
||||||
use function sleep;
|
use function sleep;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ class AccountCustomClientTest extends Scope
|
||||||
'provider' => $provider,
|
'provider' => $provider,
|
||||||
'appId' => $appId,
|
'appId' => $appId,
|
||||||
'secret' => $secret,
|
'secret' => $secret,
|
||||||
|
'enabled' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
|
@ -56,6 +58,34 @@ class AccountCustomClientTest extends Scope
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertEquals('success', $response['body']['result']);
|
$this->assertEquals('success', $response['body']['result']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Failure when disabled
|
||||||
|
*/
|
||||||
|
$response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/oauth2', array_merge([
|
||||||
|
'origin' => 'http://localhost',
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => 'console',
|
||||||
|
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
|
||||||
|
]), [
|
||||||
|
'provider' => $provider,
|
||||||
|
'appId' => $appId,
|
||||||
|
'secret' => $secret,
|
||||||
|
'enabled' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
|
|
||||||
|
$response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, array_merge([
|
||||||
|
'origin' => 'http://localhost',
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
]), [
|
||||||
|
'success' => 'http://localhost/v1/mock/tests/general/oauth2/success',
|
||||||
|
'failure' => 'http://localhost/v1/mock/tests/general/oauth2/failure',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(412, $response['headers']['status-code']);
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +479,8 @@ class AccountCustomClientTest extends Scope
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
|
|
||||||
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
||||||
|
@ -496,6 +527,7 @@ class AccountCustomClientTest extends Scope
|
||||||
'provider' => $provider,
|
'provider' => $provider,
|
||||||
'appId' => $appId,
|
'appId' => $appId,
|
||||||
'secret' => $secret,
|
'secret' => $secret,
|
||||||
|
'enabled' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
|
@ -700,7 +732,8 @@ class AccountCustomClientTest extends Scope
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEmpty($response['body']['secret']);
|
$this->assertEmpty($response['body']['secret']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['expire']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['expire']));
|
||||||
|
|
||||||
$userId = $response['body']['userId'];
|
$userId = $response['body']['userId'];
|
||||||
|
|
||||||
|
@ -800,7 +833,8 @@ class AccountCustomClientTest extends Scope
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['phone'], $number);
|
$this->assertEquals($response['body']['phone'], $number);
|
||||||
$this->assertTrue($response['body']['phoneVerification']);
|
$this->assertTrue($response['body']['phoneVerification']);
|
||||||
|
|
||||||
|
@ -851,7 +885,8 @@ class AccountCustomClientTest extends Scope
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['email'], $email);
|
$this->assertEquals($response['body']['email'], $email);
|
||||||
|
|
||||||
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([
|
||||||
|
@ -893,7 +928,8 @@ class AccountCustomClientTest extends Scope
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['registration']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['registration']));
|
||||||
$this->assertEquals($response['body']['phone'], $newPhone);
|
$this->assertEquals($response['body']['phone'], $newPhone);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -943,7 +979,8 @@ class AccountCustomClientTest extends Scope
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEmpty($response['body']['secret']);
|
$this->assertEmpty($response['body']['secret']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['expire']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['expire']));
|
||||||
|
|
||||||
\sleep(2);
|
\sleep(2);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
class AccountCustomServerTest extends Scope
|
class AccountCustomServerTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
namespace Tests\E2E\Services\Databases;
|
namespace Tests\E2E\Services\Databases;
|
||||||
|
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
use Utopia\Database\Role;
|
|
||||||
|
|
||||||
trait DatabasesBase
|
trait DatabasesBase
|
||||||
{
|
{
|
||||||
|
@ -1532,8 +1531,9 @@ trait DatabasesBase
|
||||||
$this->assertEquals($databaseId, $document['body']['$databaseId']);
|
$this->assertEquals($databaseId, $document['body']['$databaseId']);
|
||||||
$this->assertEquals($document['body']['title'], 'Thor: Ragnaroc');
|
$this->assertEquals($document['body']['title'], 'Thor: Ragnaroc');
|
||||||
$this->assertEquals($document['body']['releaseYear'], 2017);
|
$this->assertEquals($document['body']['releaseYear'], 2017);
|
||||||
$this->assertEquals(true, DateTime::isValid($document['body']['$createdAt']));
|
$dateValidator = new DatetimeValidator();
|
||||||
$this->assertEquals(true, DateTime::isValid($document['body']['birthDay']));
|
$this->assertEquals(true, $dateValidator->isValid($document['body']['$createdAt']));
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($document['body']['birthDay']));
|
||||||
$this->assertContains(Permission::read(Role::user($this->getUser()['$id'])), $document['body']['$permissions']);
|
$this->assertContains(Permission::read(Role::user($this->getUser()['$id'])), $document['body']['$permissions']);
|
||||||
$this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $document['body']['$permissions']);
|
$this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $document['body']['$permissions']);
|
||||||
$this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $document['body']['$permissions']);
|
$this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $document['body']['$permissions']);
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\SideConsole;
|
use Tests\E2E\Scopes\SideConsole;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class DatabasesConsoleClientTest extends Scope
|
class DatabasesConsoleClientTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class DatabasesCustomClientTest extends Scope
|
class DatabasesCustomClientTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,9 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Role;
|
|
||||||
|
|
||||||
class DatabasesCustomServerTest extends Scope
|
class DatabasesCustomServerTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
|
|
||||||
class DatabasesPermissionsGuestTest extends Scope
|
class DatabasesPermissionsGuestTest extends Scope
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class DatabasesPermissionsMemberTest extends Scope
|
class DatabasesPermissionsMemberTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class DatabasesPermissionsTeamTest extends Scope
|
class DatabasesPermissionsTeamTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,8 +6,8 @@ use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\SideConsole;
|
use Tests\E2E\Scopes\SideConsole;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class FunctionsConsoleClientTest extends Scope
|
class FunctionsConsoleClientTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,8 +9,8 @@ use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Database;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class FunctionsCustomClientTest extends Scope
|
class FunctionsCustomClientTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,10 +8,8 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Database;
|
use Utopia\Database\Validator\DatetimeValidator;
|
||||||
use Utopia\Database\DateTime;
|
|
||||||
use Utopia\Database\ID;
|
|
||||||
|
|
||||||
class FunctionsCustomServerTest extends Scope
|
class FunctionsCustomServerTest extends Scope
|
||||||
{
|
{
|
||||||
|
@ -45,8 +43,9 @@ class FunctionsCustomServerTest extends Scope
|
||||||
$this->assertNotEmpty($response1['body']['$id']);
|
$this->assertNotEmpty($response1['body']['$id']);
|
||||||
$this->assertEquals('Test', $response1['body']['name']);
|
$this->assertEquals('Test', $response1['body']['name']);
|
||||||
$this->assertEquals('php-8.0', $response1['body']['runtime']);
|
$this->assertEquals('php-8.0', $response1['body']['runtime']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response1['body']['$createdAt']));
|
$dateValidator = new DatetimeValidator();
|
||||||
$this->assertEquals(true, DateTime::isValid($response1['body']['$updatedAt']));
|
$this->assertEquals(true, $dateValidator->isValid($response1['body']['$createdAt']));
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response1['body']['$updatedAt']));
|
||||||
$this->assertEquals('', $response1['body']['deployment']);
|
$this->assertEquals('', $response1['body']['deployment']);
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'users.*.create',
|
'users.*.create',
|
||||||
|
@ -328,8 +327,9 @@ class FunctionsCustomServerTest extends Scope
|
||||||
$this->assertEquals(200, $response1['headers']['status-code']);
|
$this->assertEquals(200, $response1['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response1['body']['$id']);
|
$this->assertNotEmpty($response1['body']['$id']);
|
||||||
$this->assertEquals('Test1', $response1['body']['name']);
|
$this->assertEquals('Test1', $response1['body']['name']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response1['body']['$createdAt']));
|
$dateValidator = new DatetimeValidator();
|
||||||
$this->assertEquals(true, DateTime::isValid($response1['body']['$updatedAt']));
|
$this->assertEquals(true, $dateValidator->isValid($response1['body']['$createdAt']));
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response1['body']['$updatedAt']));
|
||||||
$this->assertEquals('', $response1['body']['deployment']);
|
$this->assertEquals('', $response1['body']['deployment']);
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'users.*.update.name',
|
'users.*.update.name',
|
||||||
|
@ -369,7 +369,8 @@ class FunctionsCustomServerTest extends Scope
|
||||||
|
|
||||||
$this->assertEquals(202, $deployment['headers']['status-code']);
|
$this->assertEquals(202, $deployment['headers']['status-code']);
|
||||||
$this->assertNotEmpty($deployment['body']['$id']);
|
$this->assertNotEmpty($deployment['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($deployment['body']['$createdAt']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($deployment['body']['$createdAt']));
|
||||||
$this->assertEquals('index.php', $deployment['body']['entrypoint']);
|
$this->assertEquals('index.php', $deployment['body']['entrypoint']);
|
||||||
|
|
||||||
// Wait for deployment to build.
|
// Wait for deployment to build.
|
||||||
|
@ -418,7 +419,8 @@ class FunctionsCustomServerTest extends Scope
|
||||||
|
|
||||||
$this->assertEquals(202, $largeTag['headers']['status-code']);
|
$this->assertEquals(202, $largeTag['headers']['status-code']);
|
||||||
$this->assertNotEmpty($largeTag['body']['$id']);
|
$this->assertNotEmpty($largeTag['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($largeTag['body']['$createdAt']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($largeTag['body']['$createdAt']));
|
||||||
$this->assertEquals('index.php', $largeTag['body']['entrypoint']);
|
$this->assertEquals('index.php', $largeTag['body']['entrypoint']);
|
||||||
$this->assertGreaterThan(10000, $largeTag['body']['size']);
|
$this->assertGreaterThan(10000, $largeTag['body']['size']);
|
||||||
|
|
||||||
|
@ -440,8 +442,9 @@ class FunctionsCustomServerTest extends Scope
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['$createdAt']));
|
$dateValidator = new DatetimeValidator();
|
||||||
$this->assertEquals(true, DateTime::isValid($response['body']['$updatedAt']));
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['$createdAt']));
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($response['body']['$updatedAt']));
|
||||||
$this->assertEquals($data['deploymentId'], $response['body']['deployment']);
|
$this->assertEquals($data['deploymentId'], $response['body']['deployment']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -606,7 +609,8 @@ class FunctionsCustomServerTest extends Scope
|
||||||
$this->assertEquals(202, $execution['headers']['status-code']);
|
$this->assertEquals(202, $execution['headers']['status-code']);
|
||||||
$this->assertNotEmpty($execution['body']['$id']);
|
$this->assertNotEmpty($execution['body']['$id']);
|
||||||
$this->assertNotEmpty($execution['body']['functionId']);
|
$this->assertNotEmpty($execution['body']['functionId']);
|
||||||
$this->assertEquals(true, DateTime::isValid($execution['body']['$createdAt']));
|
$dateValidator = new DatetimeValidator();
|
||||||
|
$this->assertEquals(true, $dateValidator->isValid($execution['body']['$createdAt']));
|
||||||
$this->assertEquals($data['functionId'], $execution['body']['functionId']);
|
$this->assertEquals($data['functionId'], $execution['body']['functionId']);
|
||||||
$this->assertEquals('waiting', $execution['body']['status']);
|
$this->assertEquals('waiting', $execution['body']['status']);
|
||||||
$this->assertEquals(0, $execution['body']['statusCode']);
|
$this->assertEquals(0, $execution['body']['statusCode']);
|
||||||
|
@ -623,7 +627,7 @@ class FunctionsCustomServerTest extends Scope
|
||||||
|
|
||||||
$this->assertNotEmpty($execution['body']['$id']);
|
$this->assertNotEmpty($execution['body']['$id']);
|
||||||
$this->assertNotEmpty($execution['body']['functionId']);
|
$this->assertNotEmpty($execution['body']['functionId']);
|
||||||
$this->assertEquals(true, DateTime::isValid($execution['body']['$createdAt']));
|
$this->assertEquals(true, $dateValidator->isValid($execution['body']['$createdAt']));
|
||||||
$this->assertEquals($data['functionId'], $execution['body']['functionId']);
|
$this->assertEquals($data['functionId'], $execution['body']['functionId']);
|
||||||
$this->assertEquals('completed', $execution['body']['status']);
|
$this->assertEquals('completed', $execution['body']['status']);
|
||||||
$this->assertEquals(200, $execution['body']['statusCode']);
|
$this->assertEquals(200, $execution['body']['statusCode']);
|
||||||
|
|
|
@ -7,9 +7,9 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class AbuseTest extends Scope
|
class AbuseTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
class AccountTest extends Scope
|
class AccountTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
|
|
||||||
class AuthTest extends Scope
|
class AuthTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
class BatchTest extends Scope
|
class BatchTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,9 +7,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class ContentTypeTest extends Scope
|
class ContentTypeTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class DatabaseClientTest extends Scope
|
class DatabaseClientTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,9 +7,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class DatabaseServerTest extends Scope
|
class DatabaseServerTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,8 +7,8 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class FunctionsClientTest extends Scope
|
class FunctionsClientTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,8 +7,8 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class FunctionsServerTest extends Scope
|
class FunctionsServerTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
|
||||||
class ScopeTest extends Scope
|
class ScopeTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,9 +7,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideClient;
|
use Tests\E2E\Scopes\SideClient;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class StorageClientTest extends Scope
|
class StorageClientTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,9 +7,9 @@ use Tests\E2E\Client;
|
||||||
use Tests\E2E\Scopes\ProjectCustom;
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
use Tests\E2E\Scopes\Scope;
|
use Tests\E2E\Scopes\Scope;
|
||||||
use Tests\E2E\Scopes\SideServer;
|
use Tests\E2E\Scopes\SideServer;
|
||||||
use Utopia\Database\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
use Utopia\Database\Permission;
|
use Utopia\Database\Helpers\Permission;
|
||||||
use Utopia\Database\Role;
|
use Utopia\Database\Helpers\Role;
|
||||||
|
|
||||||
class StorageServerTest extends Scope
|
class StorageServerTest extends Scope
|
||||||
{
|
{
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue