mirror of
https://github.com/appwrite/appwrite
synced 2026-05-22 00:18:25 +00:00
Merge branch 'master' into release-1.2.1
This commit is contained in:
commit
e90e007da1
197 changed files with 1581 additions and 1498 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?
|
||||
|
||||
(Provide a description of what this PR does.)
|
||||
(Provide a description of what this PR does and why it's needed.)
|
||||
|
||||
## 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
|
||||
|
||||
(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)
|
||||
- One line description of your PR [#pr_number](Link to your PR)
|
||||
|
||||
### Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
||||
|
||||
(Write your answer here.)
|
||||
- [ ] Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
||||
- [ ] 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?
|
||||
|
|
|
|||
10
CHANGES.md
10
CHANGES.md
|
|
@ -1,3 +1,13 @@
|
|||
# Version 1.2.1
|
||||
## Features
|
||||
|
||||
## Changes
|
||||
|
||||
## 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)
|
||||
|
||||
# Version 1.2.0
|
||||
## Features
|
||||
- Added GraphQL API [#974](https://github.com/appwrite/appwrite/pull/974)
|
||||
|
|
|
|||
137
CONTRIBUTING.md
137
CONTRIBUTING.md
|
|
@ -1,14 +1,14 @@
|
|||
# Contributing
|
||||
|
||||
We would ❤️ for you to contribute to Appwrite and help make it better! We want contributing to Appwrite to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, new docs as well as updates and tweaks, blog posts, workshops, and more.
|
||||
We would ❤️ you to contribute to Appwrite and help make it better! We want contributing to Appwrite to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, and new docs, as well as updates and tweaks, blog posts, workshops, and more.
|
||||
|
||||
## How to Start?
|
||||
|
||||
If you are worried or don’t know where to start, check out our next section explaining what kind of help we could use and where can you get involved. You can reach out with questions to [Eldad Fux (@eldadfux)](https://twitter.com/eldadfux) or [@appwrite](https://twitter.com/appwrite) on Twitter, and anyone from the [Appwrite team on Discord](https://discord.gg/GSeTUeA). You can also submit an issue, and a maintainer can guide you!
|
||||
If you are worried or don’t know where to start, check out the next section that explains what kind of help we could use and where you can get involved. You can send your questions to [@appwrite](https://twitter.com/appwrite) on Twitter or to anyone from the [Appwrite team on Discord](https://appwrite.io/discord). You can also submit an issue, and a maintainer can guide you!
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
Help us keep Appwrite open and inclusive. Please read and follow our [Code of Conduct](/https://github.com/appwrite/.github/blob/main/CODE_OF_CONDUCT.md).
|
||||
Help us keep Appwrite open and inclusive. Please read and follow our [Code of Conduct](https://github.com/appwrite/.github/blob/main/CODE_OF_CONDUCT.md).
|
||||
|
||||
## Submit a Pull Request 🚀
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ doc-548-submit-a-pull-request-section-to-contribution-guide
|
|||
|
||||
When `TYPE` can be:
|
||||
|
||||
- **feat** - is a new feature
|
||||
- **feat** - a new feature
|
||||
- **doc** - documentation only changes
|
||||
- **cicd** - changes related to CI/CD system
|
||||
- **fix** - a bug fix
|
||||
|
|
@ -40,33 +40,33 @@ For the initial start, fork the project and use git clone command to do
|
|||
$ git pull
|
||||
```
|
||||
|
||||
2. Create new branch from `master` like: `doc-548-submit-a-pull-request-section-to-contribution-guide`<br/>
|
||||
2. Create a new branch from `master` like: `doc-548-submit-a-pull-request-section-to-contribution-guide`.<br/>
|
||||
|
||||
```
|
||||
$ git checkout -b [name_of_your_new_branch]
|
||||
```
|
||||
|
||||
3. Work - commit - repeat ( be sure to be in your branch )
|
||||
3. Work - commit - repeat (make sure you're on the correct branch!)
|
||||
|
||||
4. Before you push your changes, make sure your code follows the `PSR12` coding standards, which is the standard Appwrite follows currently. You can easily do this by running the formatter.
|
||||
4. Before you push your changes, make sure your code follows the `PSR12` coding standards, which is the standard that Appwrite currently follows. You can easily do this by running the formatter.
|
||||
|
||||
```bash
|
||||
composer format <your file path>
|
||||
```
|
||||
|
||||
Now, go a step further by running the linter by the following command to manually fix the issues the formatter wasn't able to fix.
|
||||
Now, go a step further by running the linter using the following command to manually fix the issues the formatter wasn't able to.
|
||||
|
||||
```bash
|
||||
composer lint <your file path>
|
||||
```
|
||||
|
||||
This will give you a list of errors for you to rectify, if there is an instance you need more information on the errors being displayed you can pass in additional command line arguments. More list of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues.
|
||||
This will give you a list of errors to rectify. If you need more information on the errors, you can pass in additional command line arguments to get more verbose information. More lists of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues.
|
||||
|
||||
```bash
|
||||
composer lint --report=diff <your file path>
|
||||
```
|
||||
|
||||
5. Push changes to GitHub
|
||||
5. Push changes to GitHub.
|
||||
|
||||
```
|
||||
$ git push origin [name_of_your_new_branch]
|
||||
|
|
@ -76,23 +76,23 @@ $ git push origin [name_of_your_new_branch]
|
|||
If you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button.
|
||||
7. Start a Pull Request
|
||||
Now submit the pull request and click on `Create pull request`.
|
||||
8. Get a code review approval/reject
|
||||
9. After approval, merge your PR
|
||||
8. Get a code review approval/reject.
|
||||
9. After approval, merge your PR.
|
||||
10. GitHub will automatically delete the branch after the merge is done. (they can still be restored).
|
||||
|
||||
## Setup From Source
|
||||
|
||||
To set up a working **development environment**, just fork the project git repository and install the backend and frontend dependencies using the proper package manager and create run the docker-compose stack.
|
||||
|
||||
> If you just want to install Appwrite for day-to-day usage and not as a code maintainer use this [installation guide](https://github.com/appwrite/appwrite#installation).
|
||||
|
||||
Please note that these instructions are for setting a functional dev environment. If you want to set up an Appwrite instance to integrate into your app, you should probably try and install Appwrite by using the instructions in the [getting started guide](https://appwrite.io/docs/getting-started-for-web) or in the main [README](README.md) file.
|
||||
> If you just want to install Appwrite for day-to-day use and not as a contributor, you can reference the [installation guide](https://github.com/appwrite/appwrite#installation), the [getting started guide](https://appwrite.io/docs/getting-started-for-web), or the main [README](README.md) file.
|
||||
|
||||
```bash
|
||||
git clone git@github.com:[YOUR_FORK_HERE]/appwrite.git
|
||||
|
||||
cd appwrite
|
||||
|
||||
git submodule update --init
|
||||
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
|
|
@ -117,7 +117,7 @@ After finishing the installation process, you can start writing and editing code
|
|||
|
||||
#### Advanced Topics
|
||||
|
||||
We love to create issues that are good for beginners and label them as `good first issue` or `hacktoberfest`, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn more about some of the more advanced topics that will help you master the Appwrite codebase.
|
||||
We love to create issues that are good for beginners and label them as `good first issue` or `hacktoberfest`, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn about the more advanced topics that will help you master the Appwrite codebase.
|
||||
|
||||
##### Tools and Libs
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ Learn more at our [Technology Stack](#technology-stack) section.
|
|||
|
||||
## Architecture
|
||||
|
||||
Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures, but our final goal, as we grow, is to be using only microservices.
|
||||
Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -216,13 +216,13 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
|
|||
|
||||
Appwrite's main API container is designed as a monolithic app. This is a decision we made to allow us to develop the project faster while still being a very small team.
|
||||
|
||||
Although the Appwrite API is a monolithic app, it has a very clear separation of concern as each internal service or worker is separated by its container, which will allow us as we grow to start breaking services for better maintenance and scalability.
|
||||
Although the Appwrite API is a monolithic app, it has a very clear separation of concern as each internal service or worker is separated by its container, which allows us to start breaking services for better maintenance and scalability as we grow.
|
||||
|
||||
### The Microservice Part
|
||||
|
||||
Each container in Appwrite is a microservice on its own. Each service is an independent process that can scale without regard to any of the other services.
|
||||
|
||||
Currently, all of the Appwrite microservices are intended to communicate using the TCP protocol over a private network. You should be aware to not expose any of the services to the public-facing network, besides the public port 80 and 443, who, by default, are used to expose the Appwrite HTTP API.
|
||||
Currently, all the Appwrite microservices are intended to communicate using the TCP protocol over a private network. With the exception of the public-facing port 80 and 443, which by default are used to expose the Appwrite HTTP API, you should **avoid exposing any other services' ports**.
|
||||
|
||||
## Ports
|
||||
|
||||
|
|
@ -230,43 +230,43 @@ Appwrite dev version uses ports 80 and 443 as an entry point to the Appwrite API
|
|||
|
||||
## Technology Stack
|
||||
|
||||
To start helping us to improve the Appwrite server by submitting code, prior knowledge of Appwrite's technology stack can help you with getting started.
|
||||
To start helping us to improve the Appwrite server by submitting code, prior knowledge of Appwrite's technology stack can help you get started.
|
||||
|
||||
Appwrite stack is combined from a variety of open-source technologies and tools. Appwrite backend API is written primarily with PHP version 7 and above on top of the [Utopia PHP framework](https://github.com/utopia-php/framework). The Appwrite frontend is built with tools like gulp, less, and [litespeed.js](https://github.com/litespeed-js). We use Docker as the container technology to package the Appwrite server for easy integration on-cloud, on-premise, or on-localhosts.
|
||||
Appwrite stack is a combination of a variety of open-source technologies and tools. Appwrite backend API is written primarily with PHP version 7 and above, on top of the [Utopia PHP framework](https://github.com/utopia-php/framework). The Appwrite frontend is built with tools like gulp, less, and [litespeed.js](https://github.com/litespeed-js). We use Docker as the container technology to package the Appwrite server for easy on-cloud, on-premise, or on-localhost integration.
|
||||
|
||||
### Other Technologies
|
||||
|
||||
- Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data)
|
||||
- MariaDB - for database storage and queries
|
||||
- InfluxDB - for managing stats and time-series based data
|
||||
- Statsd - for sending data over UDP protocol (using Telegraf)
|
||||
- ClamAV - for validating and scanning storage files
|
||||
- Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data).
|
||||
- MariaDB - for database storage and queries.
|
||||
- InfluxDB - for managing stats and time-series based data.
|
||||
- Statsd - for sending data over UDP protocol (using Telegraf).
|
||||
- ClamAV - for validating and scanning storage files.
|
||||
- Imagemagick - for manipulating and managing image media files.
|
||||
- Webp - for better compression of images on supporting clients
|
||||
- SMTP - for sending email messages and alerts
|
||||
- Resque - for managing data queues and scheduled tasks over a Redis server
|
||||
- Webp - for better compression of images on supporting clients.
|
||||
- SMTP - for sending email messages and alerts.
|
||||
- Resque - for managing data queues and scheduled tasks over a Redis server.
|
||||
|
||||
## Package Managers
|
||||
|
||||
Appwrite uses a package manager for managing code dependencies for both backend and frontend development. We try our best to avoid creating any unnecessary, and any new dependency to the project is subjected to a lead developer review and approval.
|
||||
Appwrite uses a package manager for managing code dependencies for both backend and frontend development. We try our best to avoid creating any unnecessary dependencies. New dependency to the project is subjected to a lead developer's review and approval.
|
||||
|
||||
Many of Appwrite's internal modules are also used as dependencies to allow other Appwrite's projects to reuse them and as a way to contribute them back to the community.
|
||||
Many of Appwrite's internal modules are also used as dependencies to allow other Appwrite projects to reuse them and as a way to contribute back to the community.
|
||||
|
||||
Appwrite uses [PHP's Composer](https://getcomposer.org/) for managing dependencies on the server-side and [JS NPM](https://www.npmjs.com/) for managing dependencies on the frontend side.
|
||||
|
||||
## Coding Standards
|
||||
|
||||
Appwrite is following the [PHP-FIG standards](https://www.php-fig.org/). Currently, we are using both PSR-0 and PSR-12 for coding standards and autoloading standards.
|
||||
Appwrite follows the [PHP-FIG standards](https://www.php-fig.org/). Currently, we use both PSR-0 and PSR-12 for coding standards and autoloading standards.
|
||||
|
||||
We use prettier for our JS coding standards and auto-formatting our code.
|
||||
We use prettier for our JS coding standards and auto-formatting for our code.
|
||||
|
||||
## Scalability, Speed, and Performance
|
||||
|
||||
Appwrite is built to scale. Please keep in mind that the Appwrite stack can run in different environments and different scales.
|
||||
|
||||
We wish Appwrite will be as easy to set up and in a single, localhost, and easy to grow to a large environment with dozens and even hundreds of instances.
|
||||
We intend Appwrite to be as easy to set up as possible in a single localhost, and to grow easily into a large environment with dozens and even hundreds of instances.
|
||||
|
||||
When contributing code, please take into account the following considerations:
|
||||
When contributing code, please take into account the following:
|
||||
|
||||
- Response Time
|
||||
- Throughput
|
||||
|
|
@ -277,25 +277,25 @@ When contributing code, please take into account the following considerations:
|
|||
- Background Jobs
|
||||
- Task Execution Time
|
||||
|
||||
## Security & Privacy
|
||||
## Security and Privacy
|
||||
|
||||
Security and privacy are extremely important to Appwrite, developers, and users alike. Make sure to follow the best industry standards and practices.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Please avoid introducing new dependencies to Appwrite without consulting the team. New dependencies can be very helpful but also introduce new security and privacy issues, complexity, and impact total docker image size.
|
||||
Please avoid introducing new dependencies to Appwrite without consulting the team. New dependencies can be very helpful, but they also introduce new security and privacy risks, add complexity, and impact the total docker image size.
|
||||
|
||||
Adding a new dependency should have vital value on the product with minimum possible risk.
|
||||
Adding a new dependency should have vital value for the product with minimum possible risk.
|
||||
|
||||
## Introducing New Features
|
||||
|
||||
We would 💖 you to contribute to Appwrite, but we would also like to make sure Appwrite is as great as possible and loyal to its vision and mission statement 🙏.
|
||||
We would 💖 you to contribute to Appwrite, but we also want to ensure Appwrite is loyal to its vision and mission statement 🙏.
|
||||
|
||||
For us to find the right balance, please open an issue explaining your ideas before introducing a new pull request.
|
||||
|
||||
This will allow the Appwrite community to have sufficient discussion about the new feature value and how it fits in the product roadmap and vision.
|
||||
This will allow the Appwrite community to sufficiently discuss the new feature value and how it fits within the product roadmap and vision.
|
||||
|
||||
This is also important for the Appwrite lead developers to be able to give technical input and different emphasis regarding the feature design and architecture. Some bigger features might need to go through our [RFC process](https://github.com/appwrite/rfc).
|
||||
This is also important for the Appwrite lead developers to be able to provide technical input and potentially a different emphasis regarding the feature design and architecture. Some bigger features might need to go through our [RFC process](https://github.com/appwrite/rfc).
|
||||
|
||||
## Build
|
||||
|
||||
|
|
@ -319,30 +319,35 @@ The Runtimes for all supported cloud functions (multicore builds) can be found a
|
|||
|
||||
## Generate SDK
|
||||
|
||||
For generating a new console SDK follow the next steps:
|
||||
The following steps are used to generate a new console SDK:
|
||||
|
||||
1. Update the console spec file located at `app/config/specs/swagger2-<version-number>.console.json` using Appwrite Tasks. Run the `php app/cli.php specs <version-number> normal` command in a running `appwrite/appwrite` container.
|
||||
2. Generate a new SDK using the command `php app/cli.php sdks`
|
||||
3. Change your working dir using `cd app/sdks/console-web`
|
||||
4. Build the new SDK `npm run build`
|
||||
5. Copy `iife/sdk.js` to `appwrite.js`
|
||||
6. Go back to the root of the project `run npm run build`
|
||||
2. Generate a new SDK using the command `php app/cli.php sdks`.
|
||||
3. Change your working dir using `cd app/sdks/console-web`.
|
||||
4. Build the new SDK `npm run build`.
|
||||
5. Copy `iife/sdk.js` to `appwrite.js`.
|
||||
6. Go back to the root of the project `run npm run build`.
|
||||
|
||||
## Checklist for Releasing SDKs
|
||||
|
||||
Things to remember when releasing SDKs
|
||||
Things to remember when releasing SDKs:
|
||||
|
||||
- Update the Changelogs in **docs/sdks** (right now only Dart and Flutter are using these)
|
||||
- Update **GETTING_STARTED.md** in **docs/sdks** for each SDKs if any changes in the related APIs in there
|
||||
- Update SDK versions as required on **app/config/platforms.php**
|
||||
- Generate SDKs using the command `php app/cli.php sdks` and follow the instructions
|
||||
- Release new tags on GitHub repository for each SDKs
|
||||
- Update the Changelogs in **docs/sdks** (right now only Dart and Flutter are using these).
|
||||
- Update **GETTING_STARTED.md** in **docs/sdks** for each SDKs if any changes in the related APIs are in there.
|
||||
- Update SDK versions as required on **app/config/platforms.php**.
|
||||
- Generate SDKs using the command `php app/cli.php sdks` and follow the instructions.
|
||||
- Release new tags on GitHub repository for each SDK.
|
||||
|
||||
## Debug
|
||||
|
||||
Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection.
|
||||
Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code's [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension.
|
||||
|
||||
First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and then change the IP address to your development machine's IP. Without the proper IP address debugger won't connect. And you also need to set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
|
||||
If you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection:
|
||||
|
||||
1. Create an init file.
|
||||
2. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php**.
|
||||
3. Change the IP address to your development machine's IP. Without the proper IP address, the debugger won't connect.
|
||||
4. Set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
|
||||
|
||||
### VS Code Launch Configuration
|
||||
|
||||
|
|
@ -360,7 +365,7 @@ First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** fil
|
|||
|
||||
### PHPStorm Setup
|
||||
|
||||
In settings, go to **Languages & Frameworks** > **PHP** > **Debug**, there under **Xdebug** set the debug port to **9005** and enable **can accept external connections** checkbox.
|
||||
In settings, go to **Languages & Frameworks** > **PHP** > **Debug**, under **Xdebug** set the debug port to **9005** and enable the **can accept external connections** checkbox.
|
||||
|
||||
## Tests
|
||||
|
||||
|
|
@ -436,34 +441,34 @@ 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:
|
||||
|
||||
- [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
|
||||
- [Appwrite Environment Variables](./docs/tutorials/environment-variables.md)
|
||||
- [Running in Production](./docs/tutorials/running-in-production.md)
|
||||
- [Appwrite Environment Variables](./docs/tutorials/add-environment-variable.md)
|
||||
- [Running in Production](https://appwrite.io/docs/production)
|
||||
- [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
|
||||
|
||||
## Other Ways to Help
|
||||
|
||||
Pull requests are great, but there are many other areas where you can help Appwrite.
|
||||
Pull requests are great, but there are many other ways you can help Appwrite.
|
||||
|
||||
### Blogging & Speaking
|
||||
|
||||
Blogging, speaking about, or creating tutorials about one of Appwrite’s many features. Mention [@appwrite](https://twitter.com/appwrite) on Twitter and/or [email team@appwrite.io](mailto:team@appwrite.io) so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub.
|
||||
Blogging, speaking about, or creating tutorials about one of Appwrite’s many features are great ways to get the word out about Appwrite. Mention [@appwrite](https://twitter.com/appwrite) on Twitter and/or [email team@appwrite.io](mailto:team@appwrite.io) so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub.
|
||||
|
||||
### Presenting at Meetups
|
||||
|
||||
Presenting at meetups and conferences about your Appwrite projects. Your unique challenges and successes in building things with Appwrite can provide great speaking material. We’d love to review your talk abstract/CFP, so get in touch with us if you’d like some help!
|
||||
We encourage our contributors to present at meetups and conferences about your Appwrite projects. Your unique challenges and successes in building things with Appwrite can provide great speaking material. We’d love to review your talk abstract/CFP, so get in touch with us if you’d like some help!
|
||||
|
||||
### Sending Feedbacks & Reporting Bugs
|
||||
### Sending Feedbacks and Reporting Bugs
|
||||
|
||||
Sending feedback is a great way for us to understand your different use cases of Appwrite better. If you had any issues, bugs, or want to share about your experience, feel free to do so on our GitHub issues page or at our [Discord channel](https://discord.gg/GSeTUeA).
|
||||
Sending feedback is a great way for us to understand your different use cases of Appwrite better. If you had any issues, bugs, or want to share your experience, feel free to do so on our GitHub issues page or at our [Discord channel](https://discord.gg/GSeTUeA).
|
||||
|
||||
### Submitting New Ideas
|
||||
|
||||
If you think Appwrite could use a new feature, please open an issue on our GitHub repository, stating as much information as you can think about your new idea and it's implications. We would also use this issue to gather more information, get more feedback from the community, and have a proper discussion about the new feature.
|
||||
If you think Appwrite could use a new feature, please open an issue on our GitHub repository, stating as much information as you have about your new idea and its implications. We would also use this issue to gather more information, get more feedback from the community, and have a proper discussion about the new feature.
|
||||
|
||||
### Improving Documentation
|
||||
|
||||
Submitting documentation updates, enhancements, designs, or bug fixes. Spelling or grammar fixes will be very much appreciated.
|
||||
Submitting documentation updates, enhancements, designs, or bug fixes, as well as spelling or grammar fixes is much appreciated.
|
||||
|
||||
### Helping Someone
|
||||
|
||||
Searching for Appwrite on Discord, GitHub, or StackOverflow and helping someone else who needs help. You can also help by teaching others how to contribute to Appwrite's repo!
|
||||
Consider searching for Appwrite on Discord, GitHub, or StackOverflow to help someone who needs help. You can also help by teaching others how to contribute to Appwrite's repo!
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@ WORKDIR /usr/local/src/console
|
|||
|
||||
ARG VITE_GA_PROJECT
|
||||
ARG VITE_CONSOLE_MODE
|
||||
ARG VITE_APPWRITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1
|
||||
|
||||
ENV VITE_GA_PROJECT=$VITE_GA_PROJECT
|
||||
ENV VITE_CONSOLE_MODE=$VITE_CONSOLE_MODE
|
||||
ENV VITE_APPWRITE_GROWTH_ENDPOINT=$VITE_APPWRITE_GROWTH_ENDPOINT
|
||||
|
||||
RUN npm ci
|
||||
RUN npm run build
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[](https://hacktoberfest.appwrite.io)
|
||||
[](https://appwrite.io/discord?r=Github)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://twitter.com/appwrite)
|
||||
|
||||
<!-- [](https://hub.docker.com/r/appwrite/appwrite) -->
|
||||
|
|
|
|||
32
README.md
32
README.md
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
[](https://hacktoberfest.appwrite.io)
|
||||
[](https://appwrite.io/discord?r=Github)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://twitter.com/appwrite)
|
||||
|
||||
<!-- [](https://hub.docker.com/r/appwrite/appwrite) -->
|
||||
|
|
@ -25,11 +25,11 @@
|
|||
|
||||
English | [简体中文](README-CN.md)
|
||||
|
||||
[**Appwrite Console 2.0 has been released! Learn what's new!**](https://medium.com/appwrite-io/announcing-console-2-0-2e0e96891cb0?source=friends_link&sk=7a82b4069778e3adc165dc026e960fe1)
|
||||
[**Announcing Appwrite 1.2 with GraphQL support! Learn what's new!**](https://appwrite.io/graphql)
|
||||
|
||||
Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker<nobr> microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.
|
||||
|
||||
Using Appwrite, you can easily integrate your app with user authentication & multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, and [more services](https://appwrite.io/docs).
|
||||
Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, and [more services](https://appwrite.io/docs).
|
||||
|
||||
<p align="center">
|
||||
<br />
|
||||
|
|
@ -64,7 +64,7 @@ Table of Contents:
|
|||
|
||||
## Installation
|
||||
|
||||
Appwrite backend server is designed to run in a container environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool like Kubernetes, Docker Swarm, or Rancher.
|
||||
Appwrite is designed to run in a containerized environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool, such as Kubernetes, Docker Swarm, or Rancher.
|
||||
|
||||
The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine:
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ docker run -it --rm `
|
|||
appwrite/appwrite:1.2.0
|
||||
```
|
||||
|
||||
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after installation completes.
|
||||
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.
|
||||
|
||||
For advanced production and custom installation, check out our Docker [environment variables](https://appwrite.io/docs/environment-variables) docs. You can also use our public [docker-compose.yml](https://appwrite.io/install/compose) and [.env](https://appwrite.io/install/env) files to manually set up an environment.
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ If you are upgrading your Appwrite server from an older version, you should use
|
|||
|
||||
## One-Click Setups
|
||||
|
||||
In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running with Appwrite quickly without installing Docker on your local machine.
|
||||
In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running quickly with Appwrite without installing Docker on your local machine.
|
||||
|
||||
Choose from one of the providers below:
|
||||
|
||||
|
|
@ -147,18 +147,18 @@ Getting started with Appwrite is as easy as creating a new project, choosing you
|
|||
- [**Account**](https://appwrite.io/docs/client/account) - Manage current user authentication and account. Track and manage the user sessions, devices, sign-in methods, and security logs.
|
||||
- [**Users**](https://appwrite.io/docs/server/users) - Manage and list all project users when building backend integrations with Server SDKs.
|
||||
- [**Teams**](https://appwrite.io/docs/client/teams) - Manage and group users in teams. Manage memberships, invites, and user roles within a team.
|
||||
- [**Databases**](https://appwrite.io/docs/client/databases) - Manage databases, collections and documents. Read, create, update, and delete documents and filter lists of document collections using advanced filters.
|
||||
- [**Storage**](https://appwrite.io/docs/client/storage) - Manage storage files. Read, create, delete, and preview files. Manipulate the preview of your files to fit your app perfectly. All files are scanned by ClamAV and stored in a secure and encrypted way.
|
||||
- [**Functions**](https://appwrite.io/docs/server/functions) - Customize your Appwrite server by executing your custom code in a secure, isolated environment. You can trigger your code on any Appwrite system event, manually or using a CRON schedule.
|
||||
- [**Realtime**](https://appwrite.io/docs/realtime) - Listen to real-time events for any of your Appwrite services including users, storage, functions, databases and more.
|
||||
- [**Locale**](https://appwrite.io/docs/client/locale) - Track your user's location, and manage your app locale-based data.
|
||||
- [**Avatars**](https://appwrite.io/docs/client/avatars) - Manage your users' avatars, countries' flags, browser icons, credit card symbols, and generate QR codes.
|
||||
- [**Databases**](https://appwrite.io/docs/client/databases) - Manage databases, collections, and documents. Read, create, update, and delete documents and filter lists of document collections using advanced filters.
|
||||
- [**Storage**](https://appwrite.io/docs/client/storage) - Manage storage files. Read, create, delete, and preview files. Manipulate the preview of your files to perfectly fit your app. All files are scanned by ClamAV and stored in a secure and encrypted way.
|
||||
- [**Functions**](https://appwrite.io/docs/server/functions) - Customize your Appwrite server by executing your custom code in a secure, isolated environment. You can trigger your code on any Appwrite system event either manually or using a CRON schedule.
|
||||
- [**Realtime**](https://appwrite.io/docs/realtime) - Listen to real-time events for any of your Appwrite services including users, storage, functions, databases, and more.
|
||||
- [**Locale**](https://appwrite.io/docs/client/locale) - Track your user's location and manage your app locale-based data.
|
||||
- [**Avatars**](https://appwrite.io/docs/client/avatars) - Manage your users' avatars, countries' flags, browser icons, and credit card symbols. Generate QR codes from links or plaintext strings.
|
||||
|
||||
For the complete API documentation, visit [https://appwrite.io/docs](https://appwrite.io/docs). For more tutorials, news and announcements check out our [blog](https://medium.com/appwrite-io) and [Discord Server](https://discord.gg/GSeTUeA).
|
||||
|
||||
### SDKs
|
||||
|
||||
Below is a list of currently supported platforms and languages. If you wish to help us add support to your platform of choice, you can go over to our [SDK Generator](https://github.com/appwrite/sdk-generator) project and view our [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md).
|
||||
Below is a list of currently supported platforms and languages. If you would like to help us add support to your platform of choice, you can go over to our [SDK Generator](https://github.com/appwrite/sdk-generator) project and view our [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md).
|
||||
|
||||
#### Client
|
||||
|
||||
|
|
@ -190,13 +190,13 @@ Looking for more SDKs? - Help us by contributing a pull request to our [SDK Gene
|
|||
|
||||

|
||||
|
||||
Appwrite uses a microservices architecture that was designed for easy scaling and delegation of responsibilities. In addition, Appwrite supports multiple APIs (REST, WebSocket, and GraphQL-soon) to allow you to interact with your resources by leveraging your existing knowledge and protocols of choice.
|
||||
Appwrite uses a microservices architecture that was designed for easy scaling and delegation of responsibilities. In addition, Appwrite supports multiple APIs, such as REST, WebSocket, and GraphQL to allow you to interact with your resources by leveraging your existing knowledge and protocols of choice.
|
||||
|
||||
The Appwrite API layer was designed to be extremely fast by leveraging in-memory caching and delegating any heavy-lifting tasks to the Appwrite background workers. The background workers also allow you to precisely control your compute capacity and costs using a message queue to handle the load. You can learn more about our architecture in the [contribution guide](CONTRIBUTING.md#architecture-1).
|
||||
|
||||
## Contributing
|
||||
|
||||
All code contributions - including those of people having commit access - must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
|
||||
All code contributions, including those of people having commit access, must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
|
||||
|
||||
We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](CONTRIBUTING.md).
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ For security issues, kindly email us at [security@appwrite.io](mailto:security@a
|
|||
|
||||
## Follow Us
|
||||
|
||||
Join our growing community around the world! See our official [Blog](https://medium.com/appwrite-io). Follow us on [Twitter](https://twitter.com/appwrite), [Facebook Page](https://www.facebook.com/appwrite.io), [Facebook Group](https://www.facebook.com/groups/appwrite.developers/), [Dev Community](https://dev.to/appwrite) or join our live [Discord server](https://discord.gg/GSeTUeA) for more help, ideas, and discussions.
|
||||
Join our growing community around the world! Check out our official [Blog](https://medium.com/appwrite-io). Follow us on [Twitter](https://twitter.com/appwrite), [Facebook Page](https://www.facebook.com/appwrite.io), [Facebook Group](https://www.facebook.com/groups/appwrite.developers/), [Dev Community](https://dev.to/appwrite) or join our live [Discord server](https://discord.gg/GSeTUeA) for more help, ideas, and discussions.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
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.
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',
|
||||
'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',
|
||||
'default' => 'Local',
|
||||
'default' => 'local',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
],
|
||||
|
|
@ -868,37 +868,37 @@ return [
|
|||
'filter' => ''
|
||||
],
|
||||
],
|
||||
[
|
||||
'category' => 'GraphQL',
|
||||
'description' => '',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_GRAPHQL_MAX_BATCH_SIZE',
|
||||
'description' => 'Maximum number of batched queries per request. The default value is 10.',
|
||||
'introduction' => '1.2.0',
|
||||
'default' => '10',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_GRAPHQL_MAX_COMPLEXITY',
|
||||
'description' => 'Maximum complexity of a GraphQL query. One field adds one to query complexity. Lists multiply the complexity by the number of items requested. The default value is 250.',
|
||||
'introduction' => '1.2.0',
|
||||
'default' => '250',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_GRAPHQL_MAX_DEPTH',
|
||||
'description' => 'Maximum depth of a GraphQL query. One nested field level adds one to query depth. The default value is 3.',
|
||||
'introduction' => '1.2.0',
|
||||
'default' => '3',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
[
|
||||
'category' => 'GraphQL',
|
||||
'description' => '',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_GRAPHQL_MAX_BATCH_SIZE',
|
||||
'description' => 'Maximum number of batched queries per request. The default value is 10.',
|
||||
'introduction' => '1.2.0',
|
||||
'default' => '10',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_GRAPHQL_MAX_COMPLEXITY',
|
||||
'description' => 'Maximum complexity of a GraphQL query. One field adds one to query complexity. Lists multiply the complexity by the number of items requested. The default value is 250.',
|
||||
'introduction' => '1.2.0',
|
||||
'default' => '250',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_GRAPHQL_MAX_DEPTH',
|
||||
'description' => 'Maximum depth of a GraphQL query. One nested field level adds one to query depth. The default value is 3.',
|
||||
'introduction' => '1.2.0',
|
||||
'default' => '3',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use Appwrite\Event\Mail;
|
|||
use Appwrite\Event\Phone as EventPhone;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Network\Validator\Host;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Validator\Host;
|
||||
use Utopia\Validator\URL;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\Template\Template;
|
||||
use Appwrite\URL\URL as URLParser;
|
||||
|
|
@ -62,7 +62,7 @@ App::post('/v1/account')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_ACCOUNT)
|
||||
->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('password', '', new Password(), 'User password. Must be at least 8 chars.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -621,7 +621,7 @@ App::post('/v1/account/sessions/magic-url')
|
|||
->label('sdk.response.model', Response::MODEL_TOKEN)
|
||||
->label('abuse-limit', 10)
|
||||
->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('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')
|
||||
|
|
@ -713,11 +713,33 @@ App::post('/v1/account/sessions/magic-url')
|
|||
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $loginSecret, 'expire' => $expire, 'project' => $project->getId()]);
|
||||
$url = Template::unParseURL($url);
|
||||
|
||||
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $project->getAttribute('name'));
|
||||
|
||||
$body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl');
|
||||
$subject = $locale->getText("emails.magicSession.subject");
|
||||
|
||||
$body
|
||||
->setParam('{{subject}}', $subject)
|
||||
->setParam('{{hello}}', $locale->getText("emails.magicSession.hello"))
|
||||
->setParam('{{name}}', '')
|
||||
->setParam('{{body}}', $locale->getText("emails.magicSession.body"))
|
||||
->setParam('{{redirect}}', $url)
|
||||
->setParam('{{footer}}', $locale->getText("emails.magicSession.footer"))
|
||||
->setParam('{{thanks}}', $locale->getText("emails.magicSession.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("emails.magicSession.signature"))
|
||||
->setParam('{{project}}', $project->getAttribute('name'))
|
||||
->setParam('{{direction}}', $locale->getText('settings.direction'))
|
||||
->setParam('{{bg-body}}', '#f7f7f7')
|
||||
->setParam('{{bg-content}}', '#ffffff')
|
||||
->setParam('{{text-content}}', '#000000');
|
||||
|
||||
$body = $body->render();
|
||||
|
||||
$mails
|
||||
->setType(MAIL_TYPE_MAGIC_SESSION)
|
||||
->setSubject($subject)
|
||||
->setBody($body)
|
||||
->setFrom($from)
|
||||
->setRecipient($user->getAttribute('email'))
|
||||
->setUrl($url)
|
||||
->setLocale($locale->default)
|
||||
->trigger()
|
||||
;
|
||||
|
||||
|
|
@ -876,7 +898,7 @@ App::post('/v1/account/sessions/phone')
|
|||
->label('sdk.response.model', Response::MODEL_TOKEN)
|
||||
->label('abuse-limit', 10)
|
||||
->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.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -1991,12 +2013,35 @@ App::post('/v1/account/recovery')
|
|||
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $profile->getId(), 'secret' => $secret, 'expire' => $expire]);
|
||||
$url = Template::unParseURL($url);
|
||||
|
||||
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
|
||||
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName);
|
||||
$body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl');
|
||||
$subject = $locale->getText("emails.recovery.subject");
|
||||
|
||||
$body
|
||||
->setParam('{{subject}}', $subject)
|
||||
->setParam('{{hello}}', $locale->getText("emails.recovery.hello"))
|
||||
->setParam('{{name}}', $profile->getAttribute('name'))
|
||||
->setParam('{{body}}', $locale->getText("emails.recovery.body"))
|
||||
->setParam('{{redirect}}', $url)
|
||||
->setParam('{{footer}}', $locale->getText("emails.recovery.footer"))
|
||||
->setParam('{{thanks}}', $locale->getText("emails.recovery.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("emails.recovery.signature"))
|
||||
->setParam('{{project}}', $projectName)
|
||||
->setParam('{{direction}}', $locale->getText('settings.direction'))
|
||||
->setParam('{{bg-body}}', '#f7f7f7')
|
||||
->setParam('{{bg-content}}', '#ffffff')
|
||||
->setParam('{{text-content}}', '#000000');
|
||||
|
||||
$body = $body->render();
|
||||
|
||||
|
||||
$mails
|
||||
->setType(MAIL_TYPE_RECOVERY)
|
||||
->setRecipient($profile->getAttribute('email', ''))
|
||||
->setUrl($url)
|
||||
->setLocale($locale->default)
|
||||
->setName($profile->getAttribute('name'))
|
||||
->setBody($body)
|
||||
->setFrom($from)
|
||||
->setSubject($subject)
|
||||
->trigger();
|
||||
;
|
||||
|
||||
|
|
@ -2151,11 +2196,32 @@ App::post('/v1/account/verification')
|
|||
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $verificationSecret, 'expire' => $expire]);
|
||||
$url = Template::unParseURL($url);
|
||||
|
||||
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
|
||||
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName);
|
||||
$body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl');
|
||||
$subject = $locale->getText("emails.verification.subject");
|
||||
$body
|
||||
->setParam('{{subject}}', $subject)
|
||||
->setParam('{{hello}}', $locale->getText("emails.verification.hello"))
|
||||
->setParam('{{name}}', $user->getAttribute('name'))
|
||||
->setParam('{{body}}', $locale->getText("emails.verification.body"))
|
||||
->setParam('{{redirect}}', $url)
|
||||
->setParam('{{footer}}', $locale->getText("emails.verification.footer"))
|
||||
->setParam('{{thanks}}', $locale->getText("emails.verification.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("emails.verification.signature"))
|
||||
->setParam('{{project}}', $projectName)
|
||||
->setParam('{{direction}}', $locale->getText('settings.direction'))
|
||||
->setParam('{{bg-body}}', '#f7f7f7')
|
||||
->setParam('{{bg-content}}', '#ffffff')
|
||||
->setParam('{{text-content}}', '#000000');
|
||||
|
||||
$body = $body->render();
|
||||
|
||||
$mails
|
||||
->setType(MAIL_TYPE_VERIFICATION)
|
||||
->setSubject($subject)
|
||||
->setBody($body)
|
||||
->setFrom($from)
|
||||
->setRecipient($user->getAttribute('email'))
|
||||
->setUrl($url)
|
||||
->setLocale($locale->default)
|
||||
->setName($user->getAttribute('name'))
|
||||
->trigger()
|
||||
;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Validator\URL;
|
||||
use Appwrite\URL\URL as URLParse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use chillerlan\QRCode\QRCode;
|
||||
|
|
@ -242,8 +242,8 @@ App::get('/v1/avatars/favicon')
|
|||
case 'jpeg':
|
||||
$size = \explode('x', \strtolower($sizes));
|
||||
|
||||
$sizeWidth = (int) $size[0] ?? 0;
|
||||
$sizeHeight = (int) $size[1] ?? 0;
|
||||
$sizeWidth = (int) ($size[0] ?? 0);
|
||||
$sizeHeight = (int) ($size[1] ?? 0);
|
||||
|
||||
if (($sizeWidth * $sizeHeight) >= $space) {
|
||||
$space = $sizeWidth * $sizeHeight;
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ use Utopia\Database\Exception\Structure as StructureException;
|
|||
use Utopia\Locale\Locale;
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Network\Validator\IP;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\URL;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Database\Validator\Query\Limit;
|
||||
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.type', Response::CONTENT_TYPE_JSON)
|
||||
->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.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -488,9 +488,9 @@ App::post('/v1/databases/:databaseId/collections')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_COLLECTION)
|
||||
->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('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)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -745,7 +745,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
|
|||
->param('databaseId', '', new UID(), 'Database ID.')
|
||||
->param('collectionId', '', new UID(), 'Collection ID.')
|
||||
->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('enabled', true, new Boolean(), 'Is collection enabled?', true)
|
||||
->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.model', Response::MODEL_DOCUMENT)
|
||||
->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('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('dbForProject')
|
||||
->inject('user')
|
||||
|
|
@ -2244,7 +2244,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
->param('collectionId', '', new UID(), 'Collection 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('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('dbForProject')
|
||||
->inject('events')
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ App::post('/v1/functions')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('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.')
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ use Appwrite\Event\Certificate;
|
|||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Validator\Event;
|
||||
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\URL;
|
||||
use Utopia\Validator\URL;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
|
|
@ -56,7 +56,7 @@ App::post('/v1/projects')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('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)
|
||||
|
|
@ -1115,7 +1115,7 @@ App::post('/v1/projects/:projectId/platforms')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PLATFORM)
|
||||
->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('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)
|
||||
|
|
|
|||
|
|
@ -58,14 +58,14 @@ App::post('/v1/storage/buckets')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('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('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('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('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')
|
||||
|
|
@ -232,12 +232,12 @@ App::put('/v1/storage/buckets/:bucketId')
|
|||
->label('sdk.response.model', Response::MODEL_BUCKET)
|
||||
->param('bucketId', '', new UID(), 'Bucket unique ID.')
|
||||
->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('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('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('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')
|
||||
|
|
@ -347,9 +347,9 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('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('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('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -501,7 +501,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
}
|
||||
|
||||
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(
|
||||
App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'),
|
||||
(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
|
||||
$data = '';
|
||||
// Compression
|
||||
$algorithm = $bucket->getAttribute('compression', 'none');
|
||||
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != 'none') {
|
||||
$algorithm = $bucket->getAttribute('compression', COMPRESSION_TYPE_NONE);
|
||||
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != COMPRESSION_TYPE_NONE) {
|
||||
$data = $deviceFiles->read($path);
|
||||
switch ($algorithm) {
|
||||
case 'zstd':
|
||||
case COMPRESSION_TYPE_ZSTD:
|
||||
$compressor = new Zstd();
|
||||
break;
|
||||
case 'gzip':
|
||||
case COMPRESSION_TYPE_GZIP:
|
||||
default:
|
||||
$compressor = new GZIP();
|
||||
break;
|
||||
|
|
@ -549,6 +549,11 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
$sizeActual = $deviceFiles->getFileSize($path);
|
||||
$fileHash = $deviceFiles->getFileHash($path);
|
||||
|
||||
$openSSLVersion = null;
|
||||
$openSSLCipher = null;
|
||||
$openSSLTag = null;
|
||||
$openSSLIV = null;
|
||||
|
||||
if ($bucket->getAttribute('encryption', true) && $fileSize <= APP_STORAGE_READ_BUFFER) {
|
||||
$openSSLVersion = '1';
|
||||
$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)
|
||||
->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('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('dbForProject')
|
||||
->inject('user')
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Appwrite\Event\Event;
|
|||
use Appwrite\Event\Mail;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Network\Validator\Host;
|
||||
use Utopia\Validator\Host;
|
||||
use Appwrite\Template\Template;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Database\Validator\Queries;
|
||||
|
|
@ -54,7 +54,7 @@ App::post('/v1/teams')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('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')
|
||||
|
|
@ -434,14 +434,37 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
$url = Template::unParseURL($url);
|
||||
|
||||
if (!$isPrivilegedUser && !$isAppUser) { // No need of confirmation when in admin or app mode
|
||||
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
|
||||
|
||||
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName);
|
||||
$body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl');
|
||||
$subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName);
|
||||
$body->setParam('{{owner}}', $user->getAttribute('name'));
|
||||
$body->setParam('{{team}}', $team->getAttribute('name'));
|
||||
|
||||
$body
|
||||
->setParam('{{subject}}', $subject)
|
||||
->setParam('{{hello}}', $locale->getText("emails.invitation.hello"))
|
||||
->setParam('{{name}}', $user->getAttribute('name'))
|
||||
->setParam('{{body}}', $locale->getText("emails.invitation.body"))
|
||||
->setParam('{{redirect}}', $url)
|
||||
->setParam('{{footer}}', $locale->getText("emails.invitation.footer"))
|
||||
->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("emails.invitation.signature"))
|
||||
->setParam('{{project}}', $projectName)
|
||||
->setParam('{{direction}}', $locale->getText('settings.direction'))
|
||||
->setParam('{{bg-body}}', '#f7f7f7')
|
||||
->setParam('{{bg-content}}', '#ffffff')
|
||||
->setParam('{{text-content}}', '#000000');
|
||||
|
||||
$body = $body->render();
|
||||
|
||||
$mails
|
||||
->setType(MAIL_TYPE_INVITATION)
|
||||
->setRecipient($email)
|
||||
->setUrl($url)
|
||||
->setName($name)
|
||||
->setLocale($locale->default)
|
||||
->setTeam($team)
|
||||
->setUser($user)
|
||||
->setSubject($subject)
|
||||
->setBody($body)
|
||||
->setFrom($from)
|
||||
->setRecipient($invitee->getAttribute('email'))
|
||||
->setName($invitee->getAttribute('name'))
|
||||
->trigger()
|
||||
;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ App::post('/v1/users')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('phone', null, new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('password', null, new Password(), 'Plain text user password. Must be at least 8 chars.', true)
|
||||
|
|
@ -129,7 +129,7 @@ App::post('/v1/users/bcrypt')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('password', '', new Password(), 'User password hashed using Bcrypt.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -159,7 +159,7 @@ App::post('/v1/users/md5')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('password', '', new Password(), 'User password hashed using MD5.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -189,7 +189,7 @@ App::post('/v1/users/argon2')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('password', '', new Password(), 'User password hashed using Argon2.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -219,7 +219,7 @@ App::post('/v1/users/sha')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('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)
|
||||
|
|
@ -256,7 +256,7 @@ App::post('/v1/users/phpass')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('password', '', new Password(), 'User password hashed using PHPass.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -286,7 +286,7 @@ App::post('/v1/users/scrypt')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('password', '', new Password(), 'User password hashed using Scrypt.')
|
||||
->param('passwordSalt', '', new Text(128), 'Optional salt used to hash password.')
|
||||
|
|
@ -329,7 +329,7 @@ App::post('/v1/users/scrypt-modified')
|
|||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->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('password', '', new Password(), 'User password hashed using Scrypt Modified.')
|
||||
->param('passwordSalt', '', new Text(128), 'Salt used to hash password.')
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ global $utopia, $request, $response;
|
|||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Utopia\Database\Document;
|
||||
use Appwrite\Network\Validator\Host;
|
||||
use Utopia\Validator\Host;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
|
|
|||
|
|
@ -98,13 +98,12 @@ App::init()
|
|||
->inject('user')
|
||||
->inject('events')
|
||||
->inject('audits')
|
||||
->inject('mails')
|
||||
->inject('usage')
|
||||
->inject('deletes')
|
||||
->inject('database')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Mail $mails, Stats $usage, Delete $deletes, EventDatabase $database, Database $dbForProject, string $mode) use ($databaseListener) {
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Stats $usage, Delete $deletes, EventDatabase $database, Database $dbForProject, string $mode) use ($databaseListener) {
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
|
|
@ -178,10 +177,6 @@ App::init()
|
|||
->setProject($project)
|
||||
->setUser($user);
|
||||
|
||||
$mails
|
||||
->setProject($project)
|
||||
->setUser($user);
|
||||
|
||||
$audits
|
||||
->setMode($mode)
|
||||
->setUserAgent($request->getUserAgent(''))
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ function logError(Throwable $error, string $action, Utopia\Route $route = null)
|
|||
|
||||
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:
|
||||
default:
|
||||
return new Local($root);
|
||||
|
|
|
|||
17
app/init.php
17
app/init.php
|
|
@ -33,8 +33,7 @@ use Appwrite\Extend\PDO;
|
|||
use Appwrite\GraphQL\Promises\Adapter\Swoole;
|
||||
use Appwrite\GraphQL\Schema;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Network\Validator\IP;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\Usage\Stats;
|
||||
use MaxMind\Db\Reader;
|
||||
|
|
@ -73,6 +72,8 @@ use Utopia\Storage\Device\S3;
|
|||
use Utopia\Storage\Device\Wasabi;
|
||||
use Utopia\Storage\Storage;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\URL;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
const APP_NAME = 'Appwrite';
|
||||
|
|
@ -604,7 +605,7 @@ $register->set('smtp', function () {
|
|||
return $mail;
|
||||
});
|
||||
$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('db', function () {
|
||||
// This is usually for our workers or CLI commands scope
|
||||
|
|
@ -754,7 +755,7 @@ App::setResource('clients', function ($request, $console, $project) {
|
|||
$console->setAttribute('platforms', [ // Always allow current host
|
||||
'$collection' => ID::custom('platforms'),
|
||||
'name' => 'Current Host',
|
||||
'type' => 'web',
|
||||
'type' => Origin::CLIENT_TYPE_WEB,
|
||||
'hostname' => $request->getHostname(),
|
||||
], Document::SET_TYPE_APPEND);
|
||||
|
||||
|
|
@ -766,7 +767,7 @@ App::setResource('clients', function ($request, $console, $project) {
|
|||
fn ($node) => $node['hostname'],
|
||||
\array_filter(
|
||||
$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']))
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -777,7 +778,7 @@ App::setResource('clients', function ($request, $console, $project) {
|
|||
fn ($node) => $node['hostname'],
|
||||
\array_filter(
|
||||
$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']))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -910,7 +911,7 @@ App::setResource('console', function () {
|
|||
[
|
||||
'$collection' => ID::custom('platforms'),
|
||||
'name' => 'Localhost',
|
||||
'type' => 'web',
|
||||
'type' => Origin::CLIENT_TYPE_WEB,
|
||||
'hostname' => 'localhost',
|
||||
], // Current host is added on app init
|
||||
],
|
||||
|
|
@ -968,7 +969,7 @@ App::setResource('deviceBuilds', function ($project) {
|
|||
|
||||
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:
|
||||
default:
|
||||
return new Local($root);
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
|||
'data' => [
|
||||
'events' => ['stats.connections'],
|
||||
'channels' => ['project'],
|
||||
'timestamp' => DateTime::now(),
|
||||
'timestamp' => DateTime::formatTz(DateTime::now()),
|
||||
'payload' => [
|
||||
$projectId => $payload[$projectId]
|
||||
]
|
||||
|
|
@ -264,7 +264,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
|||
'data' => [
|
||||
'events' => ['test.event'],
|
||||
'channels' => ['tests'],
|
||||
'timestamp' => DateTime::now(),
|
||||
'timestamp' => DateTime::formatTz(DateTime::now()),
|
||||
'payload' => $payload
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -509,6 +509,7 @@ services:
|
|||
entrypoint: worker-messaging
|
||||
<<: *x-logging
|
||||
container_name: appwrite-worker-messaging
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
depends_on:
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class BuildsV1 extends Worker
|
|||
'outputPath' => '',
|
||||
'runtime' => $function->getAttribute('runtime'),
|
||||
'source' => $deployment->getAttribute('path'),
|
||||
'sourceType' => App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL),
|
||||
'sourceType' => strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)),
|
||||
'stdout' => '',
|
||||
'stderr' => '',
|
||||
'endTime' => null,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use Appwrite\Event\Event;
|
|||
use Appwrite\Event\Mail;
|
||||
use Appwrite\Network\Validator\CNAME;
|
||||
use Appwrite\Resque\Worker;
|
||||
use Appwrite\Template\Template;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Database;
|
||||
|
|
@ -12,6 +13,7 @@ use Utopia\Database\DateTime;
|
|||
use Utopia\Database\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Locale\Locale;
|
||||
|
||||
require_once __DIR__ . '/../init.php';
|
||||
|
||||
|
|
@ -375,18 +377,38 @@ class CertificatesV1 extends Worker
|
|||
Console::warning('Cannot renew domain (' . $domain . ') on attempt no. ' . $attempt . ' certificate: ' . $errorMessage);
|
||||
|
||||
// Send mail to administratore mail
|
||||
|
||||
$locale = new Locale(App::getEnv('_APP_LOCALE', 'en'));
|
||||
if (!$locale->getText('emails.sender') || !$locale->getText("emails.certificate.hello") || !$locale->getText("emails.certificate.subject") || !$locale->getText("emails.certificate.body") || !$locale->getText("emails.certificate.footer") || !$locale->getText("emails.certificate.thanks") || !$locale->getText("emails.certificate.signature")) {
|
||||
$locale->setDefault('en');
|
||||
}
|
||||
|
||||
$body = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-base.tpl');
|
||||
|
||||
$subject = \sprintf($locale->getText("emails.certificate.subject"), $domain);
|
||||
$body->setParam('{{domain}}', $domain);
|
||||
$body->setParam('{{error}}', $errorMessage);
|
||||
$body->setParam('{{attempt}}', $attempt);
|
||||
|
||||
$body
|
||||
->setParam('{{subject}}', $subject)
|
||||
->setParam('{{hello}}', $locale->getText("emails.certificate.hello"))
|
||||
->setParam('{{body}}', $locale->getText("emails.certificate.body"))
|
||||
->setParam('{{redirect}}', 'https://' . $domain)
|
||||
->setParam('{{footer}}', $locale->getText("emails.certificate.footer"))
|
||||
->setParam('{{thanks}}', $locale->getText("emails.certificate.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("emails.certificate.signature"))
|
||||
->setParam('{{project}}', 'Console')
|
||||
->setParam('{{direction}}', $locale->getText('settings.direction'))
|
||||
->setParam('{{bg-body}}', '#f7f7f7')
|
||||
->setParam('{{bg-content}}', '#ffffff')
|
||||
->setParam('{{text-content}}', '#000000');
|
||||
|
||||
$body = $body->render();
|
||||
$mail = new Mail();
|
||||
$mail
|
||||
->setType(MAIL_TYPE_CERTIFICATE)
|
||||
->setRecipient(App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS'))
|
||||
->setUrl('https://' . $domain)
|
||||
->setLocale(App::getEnv('_APP_LOCALE', 'en'))
|
||||
->setName('Appwrite Administrator')
|
||||
->setPayload([
|
||||
'domain' => $domain,
|
||||
'error' => $errorMessage,
|
||||
'attempt' => $attempt
|
||||
])
|
||||
->trigger();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,9 +44,6 @@ class DeletesV1 extends Worker
|
|||
case DELETE_TYPE_DATABASES:
|
||||
$this->deleteDatabase($document, $project->getId());
|
||||
break;
|
||||
case DELETE_TYPE_COLLECTIONS:
|
||||
$this->deleteCollection($document, $project->getId());
|
||||
break;
|
||||
case DELETE_TYPE_PROJECTS:
|
||||
$this->deleteProject($document);
|
||||
break;
|
||||
|
|
@ -66,6 +63,10 @@ class DeletesV1 extends Worker
|
|||
$this->deleteBucket($document, $project->getId());
|
||||
break;
|
||||
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());
|
||||
break;
|
||||
}
|
||||
|
|
@ -172,6 +173,7 @@ class DeletesV1 extends Worker
|
|||
/**
|
||||
* @param Document $document database document
|
||||
* @param string $projectId
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteDatabase(Document $document, string $projectId): void
|
||||
{
|
||||
|
|
@ -191,6 +193,7 @@ class DeletesV1 extends Worker
|
|||
/**
|
||||
* @param Document $document teams document
|
||||
* @param string $projectId
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteCollection(Document $document, string $projectId): void
|
||||
{
|
||||
|
|
@ -217,6 +220,7 @@ class DeletesV1 extends Worker
|
|||
|
||||
/**
|
||||
* @param string $hourlyUsageRetentionDatetime
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteUsageStats(string $hourlyUsageRetentionDatetime)
|
||||
{
|
||||
|
|
@ -232,6 +236,7 @@ class DeletesV1 extends Worker
|
|||
/**
|
||||
* @param Document $document teams document
|
||||
* @param string $projectId
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteMemberships(Document $document, string $projectId): void
|
||||
{
|
||||
|
|
@ -245,25 +250,62 @@ class DeletesV1 extends Worker
|
|||
|
||||
/**
|
||||
* @param Document $document project document
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteProject(Document $document): void
|
||||
{
|
||||
$projectId = $document->getId();
|
||||
|
||||
// Delete all DBs
|
||||
$this->getProjectDB($projectId)->delete($projectId);
|
||||
// Delete project domains and certificates
|
||||
$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
|
||||
$uploads = $this->getFilesDevice($document->getId());
|
||||
$cache = new Local(APP_STORAGE_CACHE . '/app-' . $document->getId());
|
||||
$uploads = $this->getFilesDevice($projectId);
|
||||
$functions = $this->getFunctionsDevice($projectId);
|
||||
$builds = $this->getBuildsDevice($projectId);
|
||||
$cache = $this->getCacheDevice($projectId);
|
||||
|
||||
$uploads->delete($uploads->getRoot(), true);
|
||||
$functions->delete($functions->getRoot(), true);
|
||||
$builds->delete($builds->getRoot(), true);
|
||||
$cache->delete($cache->getRoot(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $document user document
|
||||
* @param string $projectId
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteUser(Document $document, string $projectId): void
|
||||
{
|
||||
|
|
@ -305,6 +347,7 @@ class DeletesV1 extends Worker
|
|||
|
||||
/**
|
||||
* @param string $datetime
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteExecutionLogs(string $datetime): void
|
||||
{
|
||||
|
|
@ -337,6 +380,7 @@ class DeletesV1 extends Worker
|
|||
|
||||
/**
|
||||
* @param string $datetime
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteRealtimeUsage(string $datetime): void
|
||||
{
|
||||
|
|
@ -393,6 +437,7 @@ class DeletesV1 extends Worker
|
|||
/**
|
||||
* @param string $resource
|
||||
* @param string $projectId
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteAuditLogsByResource(string $resource, string $projectId): void
|
||||
{
|
||||
|
|
@ -406,6 +451,7 @@ class DeletesV1 extends Worker
|
|||
/**
|
||||
* @param Document $document function document
|
||||
* @param string $projectId
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteFunction(Document $document, string $projectId): void
|
||||
{
|
||||
|
|
@ -479,6 +525,7 @@ class DeletesV1 extends Worker
|
|||
/**
|
||||
* @param Document $document deployment document
|
||||
* @param string $projectId
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteDeployment(Document $document, string $projectId): void
|
||||
{
|
||||
|
|
@ -528,9 +575,10 @@ class DeletesV1 extends Worker
|
|||
/**
|
||||
* @param Document $document to be deleted
|
||||
* @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
|
||||
* @throws \Utopia\Database\Exception\Authorization
|
||||
*/
|
||||
protected function deleteById(Document $document, Database $database, callable $callback = null): bool
|
||||
{
|
||||
|
|
@ -550,6 +598,7 @@ class DeletesV1 extends Worker
|
|||
|
||||
/**
|
||||
* @param callable $callback
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function deleteForProjectIds(callable $callback): void
|
||||
{
|
||||
|
|
@ -584,9 +633,10 @@ class DeletesV1 extends Worker
|
|||
|
||||
/**
|
||||
* @param string $collection collectionID
|
||||
* @param Query[] $queries
|
||||
* @param array $queries
|
||||
* @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
|
||||
{
|
||||
|
|
@ -620,6 +670,7 @@ class DeletesV1 extends Worker
|
|||
|
||||
/**
|
||||
* @param Document $document certificates document
|
||||
* @throws \Utopia\Database\Exception\Authorization
|
||||
*/
|
||||
protected function deleteCertificates(Document $document): void
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Resque\Worker;
|
||||
use Appwrite\Template\Template;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Locale\Locale;
|
||||
|
||||
require_once __DIR__ . '/../init.php';
|
||||
|
||||
|
|
@ -32,67 +29,12 @@ class MailsV1 extends Worker
|
|||
return;
|
||||
}
|
||||
|
||||
$project = new Document($this->args['project'] ?? []);
|
||||
$user = new Document($this->args['user'] ?? []);
|
||||
$team = new Document($this->args['team'] ?? []);
|
||||
$payload = $this->args['payload'] ?? [];
|
||||
|
||||
$recipient = $this->args['recipient'];
|
||||
$url = $this->args['url'];
|
||||
$subject = $this->args['subject'];
|
||||
$name = $this->args['name'];
|
||||
$type = $this->args['type'];
|
||||
$prefix = $this->getPrefix($type);
|
||||
$locale = new Locale($this->args['locale']);
|
||||
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
|
||||
|
||||
if (!$this->doesLocaleExist($locale, $prefix)) {
|
||||
$locale->setDefault('en');
|
||||
}
|
||||
|
||||
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName);
|
||||
$body = Template::fromFile(__DIR__ . '/../config/locale/templates/email-base.tpl');
|
||||
$subject = '';
|
||||
switch ($type) {
|
||||
case MAIL_TYPE_CERTIFICATE:
|
||||
$domain = $payload['domain'];
|
||||
$error = $payload['error'];
|
||||
$attempt = $payload['attempt'];
|
||||
|
||||
$subject = \sprintf($locale->getText("$prefix.subject"), $domain);
|
||||
$body->setParam('{{domain}}', $domain);
|
||||
$body->setParam('{{error}}', $error);
|
||||
$body->setParam('{{attempt}}', $attempt);
|
||||
break;
|
||||
case MAIL_TYPE_INVITATION:
|
||||
$subject = \sprintf($locale->getText("$prefix.subject"), $team->getAttribute('name'), $projectName);
|
||||
$body->setParam('{{owner}}', $user->getAttribute('name'));
|
||||
$body->setParam('{{team}}', $team->getAttribute('name'));
|
||||
break;
|
||||
case MAIL_TYPE_RECOVERY:
|
||||
case MAIL_TYPE_VERIFICATION:
|
||||
case MAIL_TYPE_MAGIC_SESSION:
|
||||
$subject = $locale->getText("$prefix.subject");
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Undefined Mail Type : ' . $type, 500);
|
||||
}
|
||||
|
||||
$body
|
||||
->setParam('{{subject}}', $subject)
|
||||
->setParam('{{hello}}', $locale->getText("$prefix.hello"))
|
||||
->setParam('{{name}}', $name)
|
||||
->setParam('{{body}}', $locale->getText("$prefix.body"))
|
||||
->setParam('{{redirect}}', $url)
|
||||
->setParam('{{footer}}', $locale->getText("$prefix.footer"))
|
||||
->setParam('{{thanks}}', $locale->getText("$prefix.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("$prefix.signature"))
|
||||
->setParam('{{project}}', $projectName)
|
||||
->setParam('{{direction}}', $locale->getText('settings.direction'))
|
||||
->setParam('{{bg-body}}', '#f7f7f7')
|
||||
->setParam('{{bg-content}}', '#ffffff')
|
||||
->setParam('{{text-content}}', '#000000');
|
||||
|
||||
$body = $body->render();
|
||||
$body = $this->args['body'];
|
||||
$from = $this->args['from'];
|
||||
|
||||
/** @var \PHPMailer\PHPMailer\PHPMailer $mail */
|
||||
$mail = $register->get('smtp');
|
||||
|
|
@ -130,47 +72,4 @@ class MailsV1 extends Worker
|
|||
public function shutdown(): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a prefix from a mail type
|
||||
*
|
||||
* @param $type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getPrefix(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case MAIL_TYPE_RECOVERY:
|
||||
return 'emails.recovery';
|
||||
case MAIL_TYPE_CERTIFICATE:
|
||||
return 'emails.certificate';
|
||||
case MAIL_TYPE_INVITATION:
|
||||
return 'emails.invitation';
|
||||
case MAIL_TYPE_VERIFICATION:
|
||||
return 'emails.verification';
|
||||
case MAIL_TYPE_MAGIC_SESSION:
|
||||
return 'emails.magicSession';
|
||||
default:
|
||||
throw new Exception('Undefined Mail Type : ' . $type, 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the required terms in a locale exist. False otherwise
|
||||
*
|
||||
* @param $locale
|
||||
* @param $prefix
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function doesLocaleExist(Locale $locale, string $prefix): bool
|
||||
{
|
||||
|
||||
if (!$locale->getText('emails.sender') || !$locale->getText("$prefix.hello") || !$locale->getText("$prefix.subject") || !$locale->getText("$prefix.body") || !$locale->getText("$prefix.footer") || !$locale->getText("$prefix.thanks") || !$locale->getText("$prefix.signature")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.28.*",
|
||||
"utopia-php/domains": "1.1.*",
|
||||
"utopia-php/framework": "0.25.*",
|
||||
"utopia-php/framework": "0.26.*",
|
||||
"utopia-php/image": "0.5.*",
|
||||
"utopia-php/locale": "0.4.*",
|
||||
"utopia-php/logger": "0.3.*",
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
"utopia-php/orchestration": "0.6.*",
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
"utopia-php/storage": "0.11.*",
|
||||
"utopia-php/storage": "0.13.*",
|
||||
"utopia-php/swoole": "0.5.*",
|
||||
"utopia-php/websocket": "0.1.*",
|
||||
"resque/php-resque": "1.3.6",
|
||||
|
|
|
|||
80
composer.lock
generated
80
composer.lock
generated
|
|
@ -1946,16 +1946,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/framework",
|
||||
"version": "0.25.1",
|
||||
"version": "0.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/framework.git",
|
||||
"reference": "2391b397135586b2100d39e338827bef8d2f4ad0"
|
||||
"reference": "e8da5576370366d3bf9c574ec855f8c96fe4f34e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/framework/zipball/2391b397135586b2100d39e338827bef8d2f4ad0",
|
||||
"reference": "2391b397135586b2100d39e338827bef8d2f4ad0",
|
||||
"url": "https://api.github.com/repos/utopia-php/framework/zipball/e8da5576370366d3bf9c574ec855f8c96fe4f34e",
|
||||
"reference": "e8da5576370366d3bf9c574ec855f8c96fe4f34e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1984,9 +1984,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/framework/issues",
|
||||
"source": "https://github.com/utopia-php/framework/tree/0.25.1"
|
||||
"source": "https://github.com/utopia-php/framework/tree/0.26.0"
|
||||
},
|
||||
"time": "2022-11-23T18:22:23+00:00"
|
||||
"time": "2023-01-13T08:14:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/image",
|
||||
|
|
@ -2367,16 +2367,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/storage",
|
||||
"version": "0.11.0",
|
||||
"version": "0.13.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/storage.git",
|
||||
"reference": "59802cf281d1976560cf6e353f250a9b870efddc"
|
||||
"reference": "ad1c00f24ca56e73888acc2af3deee4919b1194b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/59802cf281d1976560cf6e353f250a9b870efddc",
|
||||
"reference": "59802cf281d1976560cf6e353f250a9b870efddc",
|
||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/ad1c00f24ca56e73888acc2af3deee4919b1194b",
|
||||
"reference": "ad1c00f24ca56e73888acc2af3deee4919b1194b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2416,9 +2416,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/storage/issues",
|
||||
"source": "https://github.com/utopia-php/storage/tree/0.11.0"
|
||||
"source": "https://github.com/utopia-php/storage/tree/0.13.2"
|
||||
},
|
||||
"time": "2022-08-31T09:17:31+00:00"
|
||||
"time": "2022-12-20T11:11:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/swoole",
|
||||
|
|
@ -2646,16 +2646,16 @@
|
|||
},
|
||||
{
|
||||
"name": "webonyx/graphql-php",
|
||||
"version": "v14.11.8",
|
||||
"version": "v14.11.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webonyx/graphql-php.git",
|
||||
"reference": "04a48693acd785330eefd3b0e4fa67df8dfee7c3"
|
||||
"reference": "ff91c9f3cf241db702e30b2c42bcc0920e70ac70"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webonyx/graphql-php/zipball/04a48693acd785330eefd3b0e4fa67df8dfee7c3",
|
||||
"reference": "04a48693acd785330eefd3b0e4fa67df8dfee7c3",
|
||||
"url": "https://api.github.com/repos/webonyx/graphql-php/zipball/ff91c9f3cf241db702e30b2c42bcc0920e70ac70",
|
||||
"reference": "ff91c9f3cf241db702e30b2c42bcc0920e70ac70",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2700,7 +2700,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webonyx/graphql-php/issues",
|
||||
"source": "https://github.com/webonyx/graphql-php/tree/v14.11.8"
|
||||
"source": "https://github.com/webonyx/graphql-php/tree/v14.11.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -2708,7 +2708,7 @@
|
|||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2022-09-21T15:35:03+00:00"
|
||||
"time": "2023-01-06T12:12:50+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
|
@ -2765,30 +2765,30 @@
|
|||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.4.1",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/instantiator.git",
|
||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
|
||||
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
|
||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9",
|
||||
"doctrine/coding-standard": "^9 || ^11",
|
||||
"ext-pdo": "*",
|
||||
"ext-phar": "*",
|
||||
"phpbench/phpbench": "^0.16 || ^1",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpstan/phpstan-phpunit": "^1",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"vimeo/psalm": "^4.22"
|
||||
"vimeo/psalm": "^4.30 || ^5.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
|
@ -2815,7 +2815,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -2831,7 +2831,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-03T08:28:38+00:00"
|
||||
"time": "2022-12-30T00:15:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "matthiasmullie/minify",
|
||||
|
|
@ -3417,16 +3417,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "9.2.22",
|
||||
"version": "9.2.23",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "e4bf60d2220b4baaa0572986b5d69870226b06df"
|
||||
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e4bf60d2220b4baaa0572986b5d69870226b06df",
|
||||
"reference": "e4bf60d2220b4baaa0572986b5d69870226b06df",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
|
||||
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -3482,7 +3482,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.22"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -3490,7 +3490,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-12-18T16:40:55+00:00"
|
||||
"time": "2022-12-28T12:41:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
|
|
@ -5164,16 +5164,16 @@
|
|||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.4.3",
|
||||
"version": "v3.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
|
||||
"reference": "3ffcf4b7d890770466da3b2666f82ac054e7ec72"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3ffcf4b7d890770466da3b2666f82ac054e7ec72",
|
||||
"reference": "3ffcf4b7d890770466da3b2666f82ac054e7ec72",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -5188,7 +5188,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
"dev-master": "3.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
|
@ -5224,7 +5224,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.3"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -5236,7 +5236,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-09-28T08:42:51+00:00"
|
||||
"time": "2022-12-27T12:28:18+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
|
@ -5265,5 +5265,5 @@
|
|||
"platform-overrides": {
|
||||
"php": "8.0"
|
||||
},
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -554,6 +554,7 @@ services:
|
|||
entrypoint: worker-messaging
|
||||
<<: *x-logging
|
||||
container_name: appwrite-worker-messaging
|
||||
restart: unless-stopped
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
mutation {
|
||||
accountCreateAnonymousSession {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
email: "email@example.com",
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
email: "email@example.com"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
phone: "+12065550100"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
mutation {
|
||||
accountCreatePhoneVerification {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
email: "email@example.com",
|
||||
url: "https://example.com"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ mutation {
|
|||
accountCreateVerification(
|
||||
url: "https://example.com"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ mutation {
|
|||
email: "email@example.com",
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -15,6 +15,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ query {
|
|||
accountGetSession(
|
||||
sessionId: "[SESSION_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
query {
|
||||
accountGet {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -11,6 +11,8 @@ query {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,28 @@
|
|||
query {
|
||||
accountListLogs {
|
||||
total
|
||||
logs
|
||||
logs {
|
||||
event
|
||||
userId
|
||||
userEmail
|
||||
userName
|
||||
mode
|
||||
ip
|
||||
time
|
||||
osCode
|
||||
osName
|
||||
osVersion
|
||||
clientType
|
||||
clientCode
|
||||
clientName
|
||||
clientVersion
|
||||
clientEngine
|
||||
clientEngineVersion
|
||||
deviceName
|
||||
deviceBrand
|
||||
deviceModel
|
||||
countryCode
|
||||
countryName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,32 @@
|
|||
query {
|
||||
accountListSessions {
|
||||
total
|
||||
sessions
|
||||
sessions {
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
providerUid
|
||||
providerAccessToken
|
||||
providerAccessTokenExpiry
|
||||
providerRefreshToken
|
||||
ip
|
||||
osCode
|
||||
osName
|
||||
osVersion
|
||||
clientType
|
||||
clientCode
|
||||
clientName
|
||||
clientVersion
|
||||
clientEngine
|
||||
clientEngineVersion
|
||||
deviceName
|
||||
deviceBrand
|
||||
deviceModel
|
||||
countryCode
|
||||
countryName
|
||||
current
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ mutation {
|
|||
email: "email@example.com",
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -14,6 +14,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
secret: "[SECRET]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ mutation {
|
|||
accountUpdateName(
|
||||
name: "[NAME]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -13,6 +13,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ mutation {
|
|||
accountUpdatePassword(
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -13,6 +13,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
secret: "[SECRET]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
secret: "[SECRET]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ mutation {
|
|||
phone: "+12065550100",
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -14,6 +14,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ mutation {
|
|||
accountUpdatePrefs(
|
||||
prefs: "{}"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -13,6 +13,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ mutation {
|
|||
password: "password",
|
||||
passwordAgain: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ mutation {
|
|||
accountUpdateSession(
|
||||
sessionId: "[SESSION_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
mutation {
|
||||
accountUpdateStatus {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -11,6 +11,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
secret: "[SECRET]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ mutation {
|
|||
documentId: "[DOCUMENT_ID]",
|
||||
data: "{}"
|
||||
) {
|
||||
id
|
||||
collectionId
|
||||
databaseId
|
||||
createdAt
|
||||
updatedAt
|
||||
permissions
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ query {
|
|||
collectionId: "[COLLECTION_ID]",
|
||||
documentId: "[DOCUMENT_ID]"
|
||||
) {
|
||||
id
|
||||
collectionId
|
||||
databaseId
|
||||
createdAt
|
||||
updatedAt
|
||||
permissions
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,14 @@ query {
|
|||
collectionId: "[COLLECTION_ID]"
|
||||
) {
|
||||
total
|
||||
documents
|
||||
documents {
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ mutation {
|
|||
collectionId: "[COLLECTION_ID]",
|
||||
documentId: "[DOCUMENT_ID]"
|
||||
) {
|
||||
id
|
||||
collectionId
|
||||
databaseId
|
||||
createdAt
|
||||
updatedAt
|
||||
permissions
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ mutation {
|
|||
functionsCreateExecution(
|
||||
functionId: "[FUNCTION_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
permissions
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
functionId
|
||||
trigger
|
||||
status
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ query {
|
|||
functionId: "[FUNCTION_ID]",
|
||||
executionId: "[EXECUTION_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
permissions
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
functionId
|
||||
trigger
|
||||
status
|
||||
|
|
|
|||
|
|
@ -3,6 +3,19 @@ query {
|
|||
functionId: "[FUNCTION_ID]"
|
||||
) {
|
||||
total
|
||||
executions
|
||||
executions {
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
functionId
|
||||
trigger
|
||||
status
|
||||
statusCode
|
||||
response
|
||||
stdout
|
||||
stderr
|
||||
duration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
query {
|
||||
localeListContinents {
|
||||
total
|
||||
continents
|
||||
continents {
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
query {
|
||||
localeListCountriesEU {
|
||||
total
|
||||
countries
|
||||
countries {
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
query {
|
||||
localeListCountriesPhones {
|
||||
total
|
||||
phones
|
||||
phones {
|
||||
code
|
||||
countryCode
|
||||
countryName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
query {
|
||||
localeListCountries {
|
||||
total
|
||||
countries
|
||||
countries {
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
query {
|
||||
localeListCurrencies {
|
||||
total
|
||||
currencies
|
||||
currencies {
|
||||
symbol
|
||||
name
|
||||
symbolNative
|
||||
decimalDigits
|
||||
rounding
|
||||
code
|
||||
namePlural
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
query {
|
||||
localeListLanguages {
|
||||
total
|
||||
languages
|
||||
languages {
|
||||
name
|
||||
code
|
||||
nativeName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ query {
|
|||
bucketId: "[BUCKET_ID]",
|
||||
fileId: "[FILE_ID]"
|
||||
) {
|
||||
id
|
||||
_id
|
||||
bucketId
|
||||
createdAt
|
||||
updatedAt
|
||||
permissions
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
name
|
||||
signature
|
||||
mimeType
|
||||
|
|
|
|||
|
|
@ -3,6 +3,18 @@ query {
|
|||
bucketId: "[BUCKET_ID]"
|
||||
) {
|
||||
total
|
||||
files
|
||||
files {
|
||||
_id
|
||||
bucketId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
name
|
||||
signature
|
||||
mimeType
|
||||
sizeOriginal
|
||||
chunksTotal
|
||||
chunksUploaded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ mutation {
|
|||
bucketId: "[BUCKET_ID]",
|
||||
fileId: "[FILE_ID]"
|
||||
) {
|
||||
id
|
||||
_id
|
||||
bucketId
|
||||
createdAt
|
||||
updatedAt
|
||||
permissions
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
name
|
||||
signature
|
||||
mimeType
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ mutation {
|
|||
roles: [],
|
||||
url: "https://example.com"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
userId
|
||||
userName
|
||||
userEmail
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ mutation {
|
|||
teamId: "[TEAM_ID]",
|
||||
name: "[NAME]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
total
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ query {
|
|||
teamId: "[TEAM_ID]",
|
||||
membershipId: "[MEMBERSHIP_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
userId
|
||||
userName
|
||||
userEmail
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ query {
|
|||
teamsGet(
|
||||
teamId: "[TEAM_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
total
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,19 @@ query {
|
|||
teamId: "[TEAM_ID]"
|
||||
) {
|
||||
total
|
||||
memberships
|
||||
memberships {
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
userId
|
||||
userName
|
||||
userEmail
|
||||
teamId
|
||||
teamName
|
||||
invited
|
||||
joined
|
||||
confirm
|
||||
roles
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
query {
|
||||
teamsList {
|
||||
total
|
||||
teams
|
||||
teams {
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
total
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ mutation {
|
|||
membershipId: "[MEMBERSHIP_ID]",
|
||||
roles: []
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
userId
|
||||
userName
|
||||
userEmail
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
secret: "[SECRET]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
userId
|
||||
userName
|
||||
userEmail
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ mutation {
|
|||
teamId: "[TEAM_ID]",
|
||||
name: "[NAME]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
total
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
mutation {
|
||||
accountCreatePhoneVerification {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
email: "email@example.com",
|
||||
url: "https://example.com"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ mutation {
|
|||
accountCreateVerification(
|
||||
url: "https://example.com"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ query {
|
|||
accountGetSession(
|
||||
sessionId: "[SESSION_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
query {
|
||||
accountGet {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -11,6 +11,8 @@ query {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,28 @@
|
|||
query {
|
||||
accountListLogs {
|
||||
total
|
||||
logs
|
||||
logs {
|
||||
event
|
||||
userId
|
||||
userEmail
|
||||
userName
|
||||
mode
|
||||
ip
|
||||
time
|
||||
osCode
|
||||
osName
|
||||
osVersion
|
||||
clientType
|
||||
clientCode
|
||||
clientName
|
||||
clientVersion
|
||||
clientEngine
|
||||
clientEngineVersion
|
||||
deviceName
|
||||
deviceBrand
|
||||
deviceModel
|
||||
countryCode
|
||||
countryName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,32 @@
|
|||
query {
|
||||
accountListSessions {
|
||||
total
|
||||
sessions
|
||||
sessions {
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
providerUid
|
||||
providerAccessToken
|
||||
providerAccessTokenExpiry
|
||||
providerRefreshToken
|
||||
ip
|
||||
osCode
|
||||
osName
|
||||
osVersion
|
||||
clientType
|
||||
clientCode
|
||||
clientName
|
||||
clientVersion
|
||||
clientEngine
|
||||
clientEngineVersion
|
||||
deviceName
|
||||
deviceBrand
|
||||
deviceModel
|
||||
countryCode
|
||||
countryName
|
||||
current
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ mutation {
|
|||
email: "email@example.com",
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -14,6 +14,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ mutation {
|
|||
accountUpdateName(
|
||||
name: "[NAME]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -13,6 +13,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ mutation {
|
|||
accountUpdatePassword(
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -13,6 +13,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ mutation {
|
|||
userId: "[USER_ID]",
|
||||
secret: "[SECRET]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ mutation {
|
|||
phone: "+12065550100",
|
||||
password: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -14,6 +14,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ mutation {
|
|||
accountUpdatePrefs(
|
||||
prefs: "{}"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
_id
|
||||
_createdAt
|
||||
_updatedAt
|
||||
name
|
||||
registration
|
||||
status
|
||||
|
|
@ -13,6 +13,8 @@ mutation {
|
|||
phone
|
||||
emailVerification
|
||||
phoneVerification
|
||||
prefs
|
||||
prefs {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ mutation {
|
|||
password: "password",
|
||||
passwordAgain: "password"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
secret
|
||||
expire
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ mutation {
|
|||
accountUpdateSession(
|
||||
sessionId: "[SESSION_ID]"
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
_id
|
||||
_createdAt
|
||||
userId
|
||||
expire
|
||||
provider
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue