From b8a1b3174aef0c040f0a20ffb2cc0e5e152dddf1 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:29:33 +0100 Subject: [PATCH 01/13] feat: svelte tutorial --- .../docs/tutorials/svelte/+page.markdoc | 343 ++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 src/routes/docs/tutorials/svelte/+page.markdoc diff --git a/src/routes/docs/tutorials/svelte/+page.markdoc b/src/routes/docs/tutorials/svelte/+page.markdoc new file mode 100644 index 0000000000..d7ce7563d0 --- /dev/null +++ b/src/routes/docs/tutorials/svelte/+page.markdoc @@ -0,0 +1,343 @@ +--- +layout: article +title: Svelte Tutorial +description: This is the description used for SEO. +--- +Build an app to track all the side projects you've been meaning to start. + +{% section #step-1 step=1 title="Getting started" %} +Head to the [Appwrite Console](https://cloud.appwrite.io/console). + +![Create project screen](/images/docs/databases/quick-start/create-project.png) + +If this is your first time using Appwrite, create an accout and create your first project. + +Then, under **Add a platform**, add a **Web app**. The **Hostname** should be localhost. + +![Add a platform](/images/docs/databases/quick-start/add-platform.png) + +You can skip optional steps. + +{% /section %} + +{% section #step-2 step=2 title="Create SvelteKit app" %} +Create a SvelteKit app with the `npm create` command and select `Skeleton project` + +```sh +npm create svelte@latest ideas-tracker && cd ideas-tracker +``` +{% /section %} + +{% section #step-3 step=3 title="Install dependencies" %} + +Install the JavaScript Appwrite SDK. + +```sh +npm install appwrite +``` + +We recommend starting the development server to watch your app update in the browser as you make changes. + +```sh +npm run dev -- --open +``` +{% /section %} + +{% section #step-4 step=4 title="Setting up Appwrite" %} +To use Appwrite in our Svelte app, we'll need to find our project ID. Find your project's ID in the **Settings** page. + +![Settings page in Appwrite Console.](/images/docs/databases/quick-start/project-id.png) + +Create a new file `src/lib/appwrite.js` to hold our Appwrite related code. +Add the following code to it, replacing `` with your project ID. + +```js +import { Client } from "appwrite"; + +const client = new Client(); +client + .setEndpoint("https://cloud.appwrite.io/v1") + .setProject(""); // Replace with your project IDxw + +export const account = new Account(client); +export const database = new Database(client); +``` +{% /section %} + +{% section #step-5 step=5 title="Using Appwrite Authentication" %} +In Svelte, [stores](https://svelte.dev/docs/svelte-store) are a way to share state between components. We'll use a store to keep track of our user's data. + +Create a new file `src/lib/stores/user.js` and add the following code to it. + +```js +import { writable } from "svelte/store"; +import { ID } from "appwrite"; +import { goto } from "$app/navigation"; +import { account } from "$lib/appwrite"; + +const store = writable(null); + +async function init() { + try { + store.set(await account.get()); + } catch (e) { + store.set(null); + } +} + +async function register(email, password) { + await account.create(ID.unique(), email, password); + await login(email, password); +} + +async function login(email, password) { + await account.createEmailSession(email, password); + await init(); + goto("/"); // Redirect to home page after login +} + +async function logout() { + await account.deleteSession("current"); + store.set(null); +} + +export const user = { + subscribe: store.subscribe, // Expose the store's value with $user + register, + login, + logout, + init, +}; +``` +{% /section %} + +{% section #step-6 step=6 title="Building a login page" %} + +Using this store, we can build a login page. + +Create a new file `src/routes/login/+page.svelte` and add the following code to it. + +```html + + +

Login or register

+
+ + + + +
+ + +``` +{% /section %} + +{% section #step-7 step=7 title="Building a navbar" %} +Create a layout component, used by all pages, to display a navbar. The navbar will show a login button if the user is not logged in, and a logout button if the user is logged in. + +In this component, we can call our `user.init()` function to check if the user is logged in when the page loads. + +Create a new file `src/routes/+layout.svelte` and add the following code to it. + +```html + + + + + + + +``` +{% /section %} + +{% section #step-8 step=8 title="Using Appwrite Databases" %} +Create a collection in the Appwrite console to store our ideas. + +![Create collection screen](#TODO update me) + +Create a new collection with the following attributes: +- userId: String (required) +- title: String (required) +- description: String + +Create a new file `src/lib/stores/ideas.js` and add the following code to it. + +```js +import { writable } from "svelte/store"; +import { ID, Query } from "appwrite"; +import { databases } from "$lib/appwrite"; + +export const IDEAS_DATABASE_ID = "6508783c5dc784d544dd"; // Replace with your database ID +export const IDEAS_COLLECTION_ID = "65087840ab307cb06883"; // Replace with your collection ID + +const databases = new Databases(client); + +const store = writable([]); + +async function init() { + const response = await databases.listDocuments( + IDEAS_DATABASE_ID, + IDEAS_COLLECTION_ID, + // Use a query to how the latest ideas first + [Query.orderDesc("$createdAt")] + ); + store.set(response.documents); +} + +async function add(userId, title, description) { + const response = await databases.createDocument( + IDEAS_DATABASE_ID, + IDEAS_COLLECTION_ID, + ID.unique(), + { + userId, + title, + description, + } + ); + store.update((ideas) => [response, ...ideas]); +} + +async function remove(id) { + await databases.deleteDocument(IDEAS_DATABASE_ID, IDEAS_COLLECTION_ID, id); + store.update((ideas) => ideas.filter((idea) => idea.$id !== id)); +} + +export const ideas = { + subscribe: store.subscribe, // Expose the store's value with $ideas + init, + add, + remove, +}; +``` +{% /section %} + +{% section #step-9 step=9 title="Creating the ideas page" %} + +Using this store, we can build a page to submit and view ideas. + +Overwrite the contents of `src/routes/+page.svelte` with the following code. + +```html + + +{#if $user} +
+

Submit Idea

+
+ + + +
+
+

Please login to submit an idea.

+ +
+

Latest Ideas

+
    +
  • + {{ idea.title }} +

    {{ idea.description }}

    + +
  • +
+
+ +``` \ No newline at end of file diff --git a/src/routes/docs/tutorials/vue/step-8/+page.markdoc b/src/routes/docs/tutorials/vue/step-8/+page.markdoc new file mode 100644 index 0000000000..9c5af3c44c --- /dev/null +++ b/src/routes/docs/tutorials/vue/step-8/+page.markdoc @@ -0,0 +1,14 @@ +--- +layout: tutorial +title: Next steps +description: This is the description used for SEO. +step: 8 +difficulty: easy +readtime: 10 +--- + +## Test your project {% #test-project %} +Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser. + +## Add style {% #add-style %} +If you want to see a version of this project, complete with CSS styles, clone [this GitHub repository](). \ No newline at end of file From a8c09f1b9b6c20c4395a8f8e8157ed96ba304658 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Thu, 21 Sep 2023 18:45:15 +0000 Subject: [PATCH 12/13] Redo auth sidebar? --- .../advanced/platform/webhooks/+page.markdoc | 11 - .../self-hosting/functions/+page.markdoc | 2 - src/routes/docs/apis/graphql/+page.markdoc | 4 +- src/routes/docs/products/auth/+layout.svelte | 22 +- .../auth/account-vs-users-api/+page.markdoc | 26 ++ .../docs/products/auth/accounts/+page.markdoc | 183 +++++++++ .../docs/products/auth/labels/+page.markdoc | 186 +++++++++ .../products/auth/magic-url/+page.markdoc | 1 - .../products/auth/quick-start/+page.markdoc | 27 +- .../docs/products/auth/teams/+page.markdoc | 198 ++++++++++ .../auth/user-management/+page.markdoc | 357 ------------------ 11 files changed, 620 insertions(+), 397 deletions(-) create mode 100644 src/routes/docs/products/auth/account-vs-users-api/+page.markdoc create mode 100644 src/routes/docs/products/auth/accounts/+page.markdoc create mode 100644 src/routes/docs/products/auth/labels/+page.markdoc create mode 100644 src/routes/docs/products/auth/teams/+page.markdoc delete mode 100644 src/routes/docs/products/auth/user-management/+page.markdoc diff --git a/src/routes/docs/advanced/platform/webhooks/+page.markdoc b/src/routes/docs/advanced/platform/webhooks/+page.markdoc index 8551cbddec..56bed361da 100644 --- a/src/routes/docs/advanced/platform/webhooks/+page.markdoc +++ b/src/routes/docs/advanced/platform/webhooks/+page.markdoc @@ -4,17 +4,6 @@ title: Webhooks description: Placeholder SEO. --- -Certainly! Below is the content converted to Markdown format: - -```markdown -```php -getParam('events', []); - -?> -``` - Webhooks allow you to build or set up integrations which subscribe to certain events on Appwrite. When one of those events is triggered, we'll send an HTTP POST payload to the webhook's configured URL. Webhooks can be used to purge cache from CDN, calculate data or send a Slack notification. You're only limited by your imagination. ## Add your webhook {% #addWebhook %} diff --git a/src/routes/docs/advanced/self-hosting/functions/+page.markdoc b/src/routes/docs/advanced/self-hosting/functions/+page.markdoc index 94de2be9ec..4dd9324697 100644 --- a/src/routes/docs/advanced/self-hosting/functions/+page.markdoc +++ b/src/routes/docs/advanced/self-hosting/functions/+page.markdoc @@ -79,8 +79,6 @@ Check the **Any account** box under **Where can this GitHub App be installed?** After creating your app, you'll have to configure the following environment variables. -Markdown doesn't natively support tables with complex markup like HTML does. However, you can create simple tables with Markdown. Here's a basic conversion of your table to Markdown: - | Variable | Description | |------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `_APP_DOMAIN` | Your main Appwrite domain used to access the Appwrite Console. When setting a public suffix domain, Appwrite will attempt to issue a valid SSL certificate automatically. When used with a dev domain, Appwrite will assign a self-signed SSL certificate. If you're using a proxy for **localhost development**, such as [ngrok](https://ngrok.com/), this will be the domain of your localhost proxy. | diff --git a/src/routes/docs/apis/graphql/+page.markdoc b/src/routes/docs/apis/graphql/+page.markdoc index 32333e9831..555deff73c 100644 --- a/src/routes/docs/apis/graphql/+page.markdoc +++ b/src/routes/docs/apis/graphql/+page.markdoc @@ -1,9 +1,7 @@ --- layout: article title: GraphQL -description: -difficulty: beginner -readtime: 10 +description: Description used for SEO --- Appwrite supports multiple protocols for accessing the server, including [REST](/docs/rest), [GraphQL](/docs/graphql), and [Realtime](/docs/realtime). diff --git a/src/routes/docs/products/auth/+layout.svelte b/src/routes/docs/products/auth/+layout.svelte index 3fd9558d63..4e87fb8a3a 100644 --- a/src/routes/docs/products/auth/+layout.svelte +++ b/src/routes/docs/products/auth/+layout.svelte @@ -43,19 +43,31 @@ { label: 'Anonymous', href: '/docs/products/auth/anonymous' - } + }, + { + label: 'Server integrations', + href: '/docs/products/auth/server-integrations' + }, ] }, { label: 'Concepts', items: [ { - label: 'User management', - href: '/docs/products/auth/user-management' + label: 'Account vs. Users API', + href: '/docs/products/auth/account-vs-users-api' }, { - label: 'Server integrations', - href: '/docs/products/auth/server-integrations' + label: 'Accounts', + href: '/docs/products/auth/accounts' + }, + { + label: 'Teams', + href: '/docs/products/auth/teams' + }, + { + label: 'Labels', + href: '/docs/products/auth/labels' }, { label: 'Security', diff --git a/src/routes/docs/products/auth/account-vs-users-api/+page.markdoc b/src/routes/docs/products/auth/account-vs-users-api/+page.markdoc new file mode 100644 index 0000000000..077a51e653 --- /dev/null +++ b/src/routes/docs/products/auth/account-vs-users-api/+page.markdoc @@ -0,0 +1,26 @@ +--- +layout: article +title: Account vs. Users API +description: This is the description used for SEO. +--- + +Appwrite provides two APIs to manager user accounts. + +## Account API {% #account-api %} +The Account API is the API you should use in your **client applications** like web, Flutter, mobile, and native apps. +Account API creates sessions, which represent an authenticated user and is attached to a user's [account](/docs/products/auth/account). +Sessions respect [permissions](/docs/advanced/platform/permissions), which means users can only access resources if they have been granted the correct permissions. + +You'll notice that the Account API doesn't allow you to view or make changes to other users. +This is by design and for **security reasons**. + +[Account API references](#) + +## Users API {% #users-api %} +The Users API is a dedicated API for managing users from an admin's perspective. **Do not use the Users API on client applications**. +It should be used with backend or server-side applications with the [Server SDK](#). + +Users API uses API keys instead of sessions. +This means they're not resticted by permissions, but by the scopes granted to the API key used. + +[Users API references](#) \ No newline at end of file diff --git a/src/routes/docs/products/auth/accounts/+page.markdoc b/src/routes/docs/products/auth/accounts/+page.markdoc new file mode 100644 index 0000000000..4e71ef0025 --- /dev/null +++ b/src/routes/docs/products/auth/accounts/+page.markdoc @@ -0,0 +1,183 @@ +--- +layout: article +title: Accounts +description: This is the description used for SEO. +--- + +Appwrite allows users to create accounts. +Users can be organized into teams and be given labels, so they can be given different permissions and access different resources. +Each user's account can also have their own preference object, which you can use to save preferences such as theme, language, and notification settings. + +## Signup and login {% signup-login %} +You can signup and login a user with an account create through +[email password](/docs/products/auth/email-password), +[phone (SMS)](/docs/products/auth/phone-sms), +[Anonymous](/docs/products/auth/anonymous) +[magic URL](/docs/products/auth/magic-url), and +[OAuth 2](/docs/products/auth/oauth2) +authentication. + +## Preferences {% #preferences %} + +You can store user preferences on a user's account using Appwrite's [Update Preferences](#) endpoint. You can store preferences such as theme, notification settings, or preferred language so they can be synced across multiple devices. + +Preferences are stored as a key-value JSON object. The maximum allowed size for preferences is 64kB, and an error will be thrown if this limit is exceeded. + +{% multicode %} +```js +import { Client, Account } from "appwrite"; + +const client = new Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const promise = account.updatePrefs({darkTheme: true, language: 'en'}); + +promise.then(function (response) { + console.log(response); // Success +}, function (error) { + console.log(error); // Failure +}); +``` +```dart +import 'package:appwrite/appwrite.dart'; + +final client = Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +final account = Account(client); + +final user = await account.updatePrefs( + prefs: { + "darkTheme": true, + "language": "en", + } +); +``` +```kotlin +import io.appwrite.Client +import io.appwrite.services.Account + +val client = Client() + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val account = Account(client) + +val user = account.updatePrefs( + prefs = mapOf( + "darkTheme" to true, + "language" to "en" + ) +) +``` +```swift +import Appwrite + +let client = Client() + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let account = Account(client) + +let user = try await account.updatePrefs( + prefs: [ + "darkTheme": true, + "language": "en" + ] +) +``` +```graphql +mutation { + accountUpdatePrefs( + prefs: "{\"darkTheme\": true, \"language\": \"en\"}" + ) { + _id + name + prefs { + data + } + } +} +``` +{% /multicode %} + +After a user's preferences are updated, they can be retrieved using the [Get Preferences](#) endpoint. + +{% multicode %} +```js +import { Client, Account } from "appwrite"; + +const client = new Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const promise = account.getPrefs(); + +promise.then(function (response) { + console.log(response); // Success +}, function (error) { + console.log(error); // Failure +}); +``` +```dart +import 'package:appwrite/appwrite.dart'; + +final client = Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +final account = Account(client); + +final prefs = await account.getPrefs(); +``` +```kotlin +import io.appwrite.Client +import io.appwrite.services.Account + +val client = Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val account = Account(client) + +val prefs = account.getPrefs() +``` +```swift +import Appwrite + +let client = Client() + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let account = Account(client) + +let prefs = try await account.getPrefs() +``` +```graphql +query { + accountGetPrefs { + data + } +} +``` +{% /multicode %} + +## Permissions {% #permissions %} + +You can grant permissions to all users using the `Role.users()` role or +individual users using the `Role.user(, )` role. + +| Description | Role | +| ------------------------------------------- | ------------------------------------------- | +| Verified users | `Role.users('verified')`| +| Unverified users | `Role.users('unverified')` | +| Verified user | `Role.user(, 'verified')`| +| Unverified user | `Role.user(, 'unverified')` | + +[Learn more about permissions](/docs/advanced/platform/permissions) \ No newline at end of file diff --git a/src/routes/docs/products/auth/labels/+page.markdoc b/src/routes/docs/products/auth/labels/+page.markdoc new file mode 100644 index 0000000000..e3c4c916fa --- /dev/null +++ b/src/routes/docs/products/auth/labels/+page.markdoc @@ -0,0 +1,186 @@ +--- +layout: article +title: Labels +description: This is the description used for SEO. +--- + +Labels are a good way to categorize a user to grant them access to resources. For example, a `subscriber` label can be added to a user once they've purchased a subscription. + +{% multicode %} +```js +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + .setKey('98fd4...a2ad2'); // Your secret API key + +const users = new sdk.Users(client); + +const promise = users.updateLabels( + '[USER_ID]', + [ 'subscriber' ] +); + +promise.then(function (response) { + console.log(response); // Success +}, function (error) { + console.log(error); // Failure +}); +``` + +```php +use Appwrite\Client; +use Appwrite\Services\Users; +use Appwrite\Role; + +$client = new Client(); + +$client + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + .setKey('98fd4...a2ad2'); // Your secret API key + +$users = new Users($client); + +$result = $users->updateLabels( + '[USER_ID]', + [ 'subscriber' ] +); +``` + +```python +from appwrite.client import Client +from appwrite.services.users import Users +from appwrite.role import Role + +client = Client() + +(client + .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint + .set_project('5df5acd0d48c2') # Your project ID + .set_key('98fd4...a2ad2') # Your secret API key +) + +users = Users(client) + +result = users.update_labels( + '[USER_ID]', + [ 'subscriber' ] +); +``` +```ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint + .set_project('5df5acd0d48c2') # Your project ID + .set_key('98fd4...a2ad2') # Your secret API key + +users = Users.new(client) + +response = users.update_labels( + user_id: '[USER_ID]', + labels: [ 'subscriber' ] +); +``` + +```deno +import * as sdk from "https://deno.land/x/appwrite/mod.ts"; + +let client = new sdk.Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + .setKey('98fd4...a2ad2'); // Your secret API key + +let users = new sdk.Users(client); + +const promise = users.updateLabels( + '[USER_ID]', + [ 'subscriber' ] +); + +promise.then(function (response) { + console.log(response); // Success +}, function (error) { + console.log(error); // Failure +}); +``` +```dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +final client = Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + .setKey('98fd4...a2ad2'); // Your secret API key + +final users = Users(client); + +final result = await users.updateLabels( + userId: '[USER_ID]', + labels: [ 'subscriber' ], +); +``` +```kotlin +import io.appwrite.Client +import io.appwrite.Role +import io.appwrite.services.Users + +val client = Client() + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + .setKey("98fd4...a2ad2") // Your secret API key + +val users = Users(client) + +val response = users.updateLabels( + userId = "[USER_ID]", + labels = [ 'subscriber' ] +); +``` + +```swift +import Appwrite + +let client = Client() + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + .setKey("98fd4...a2ad2") // Your secret API key + +let users = Users(client) + +let response = try await users.updateLabels( + userId: "[USER_ID]", + labels: [ 'subscriber' ] +); +``` + +```csharp +using Appwrite; + +var client = new Client() + .SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("5df5acd0d48c2") // Your project ID + .SetKey("98fd4...a2ad2"); // Your secret API key + +var users = new Users(client); + +var response = await users.UpdateLabels( + userId: "[USER_ID]", + labels: [ 'subscriber' ] +); +``` +{% /multicode %} + +This would correspond with the permissions below. + +| Description | Code Snippet | +| ------------------------------------------- | ------------------------------------------- | +| Read | `Permissions.read(Role.label('subscriber'))`| +| Update | `Permissions.update(Role.label('subscriber'))` | +| Delete | `Permissions.delete(Role.label('subscriber'))` | +| Create | `Permissions.create(Role.label('subscriber'))` | + +[Learn more about permissions](/docs/advanced/platform/permissions) diff --git a/src/routes/docs/products/auth/magic-url/+page.markdoc b/src/routes/docs/products/auth/magic-url/+page.markdoc index 492b4f288b..f316c4bd5c 100644 --- a/src/routes/docs/products/auth/magic-url/+page.markdoc +++ b/src/routes/docs/products/auth/magic-url/+page.markdoc @@ -3,7 +3,6 @@ layout: article title: Magic URL description: This is the description used for SEO. --- -Certainly, here's the HTML content converted into Markdown format: Magic URL is a password-less way to authenticate users. When a user logs in by providing their email, they will receive an email with a "magic" link that contains a secret used to log in the user. The user can simply click the link to be logged in. diff --git a/src/routes/docs/products/auth/quick-start/+page.markdoc b/src/routes/docs/products/auth/quick-start/+page.markdoc index 9a16808b7c..1f6a2f1810 100644 --- a/src/routes/docs/products/auth/quick-start/+page.markdoc +++ b/src/routes/docs/products/auth/quick-start/+page.markdoc @@ -93,8 +93,6 @@ mutation { After you've created your account, users can be logged in using the Create Email Session route. -Converting your HTML code into your custom Markdown with the multi-select code feature can be done like this. - {% multicode %} ```js import { Client, Account } from "appwrite"; @@ -172,19 +170,12 @@ mutation { ``` {% /multicode %} -## Explore -Appwrite's feature rich Authentication service has much more to offer. -Explore the features below. - -| Explore | | -|-------------------------------------------------------------------------|----------------------------------------------------| -| [Email and password](/docs/products/auth/email-password) | Authenticate your users using email and passwords. | -| [Account verification](/docs/products/auth/email-password#verification) | Verify the email of registered users. | -| [Phone (SMS)](/docs/products/auth/phone-sms) | Authenticate users with their phone number using SMS messages. | -| [Magic URL](/docs/products/auth/magic-url) | Authenticate users through a magic link sent to their email, without needing a password. | -| [OAuth 2](/docs/products/auth/oauth2) | Authenticate users by connecting to existing accounts from an OAuth provider. | -| [Anonymous](/docs/products/auth/anonymous) | Create guest user sessions that can be convered to full accounts later. | -| [User preferences](/docs/products/auth/user-management#preferences) | Store and manage user preferences, like notification settings and themes. | -| [Organize users](/docs/products/auth/user-management#labels) | Organize users by adding labels or creating teams. | -| [Server integration](/docs/products/auth/server-integrations) | Authenticate users in backend code or act on behalf of users using the [Appwrite Server SDKs](#). | -| [Security](/docs/products/auth/security) | Learn about Appwrite's session persistence and enhanced security features. | \ No newline at end of file +## More ways to Authenticate +You can signup and login a user with an account create through +[email password](/docs/products/auth/email-password), +[phone (SMS)](/docs/products/auth/phone-sms), +[Anonymous](/docs/products/auth/anonymous) +[magic URL](/docs/products/auth/magic-url), and +[OAuth 2](/docs/products/auth/oauth2) +authentication. + diff --git a/src/routes/docs/products/auth/teams/+page.markdoc b/src/routes/docs/products/auth/teams/+page.markdoc new file mode 100644 index 0000000000..2ccffd89ad --- /dev/null +++ b/src/routes/docs/products/auth/teams/+page.markdoc @@ -0,0 +1,198 @@ +--- +layout: article +title: User Managements +description: This is the description used for SEO. +--- + +Teams are a good way to allow users to share access to resources. +For example, in a todo app, a user can [create a team](#) for one of their todo lists and [invite another user](#) to the team to grant the other user access. +You can further give special rights to parts of a team using team roles. + +The invited user can [accept the invitation](#) to gain access. If the user's ever removed from the team, they'll lose access again. + +## Create team {% #create %} +For example, we can create a team called `teachers` with roles `maths`, `sciences`, `arts`, and `literature`. + +The creator of the team is also granted the `owner` role. **Only those with the `owner` role can invite and remove members**. + +{% multicode %} +```js +import { Client, Teams } from "appwrite"; + +const client = new Client(); + +const teams = new Teams(client); + +client + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID +; + +const promise = teams.create( + 'teachers', + 'Teachers', + ['maths', 'sciences', 'arts', 'literature'] +); + +promise.then(function (response) { + console.log(response); // Success +}, function (error) { + console.log(error); // Failure +}); +``` +```dart +import 'package:appwrite/appwrite.dart'; + +void main() { // Init SDK + Client client = Client(); + Teams teams = Teams(client); + + client + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + ; + Future result = teams.create( + teamId: 'teachers', + name: 'Teachers', + roles: ['maths', 'sciences', 'arts', 'literature'] + ); + + result + .then((response) { + print(response); + }).catchError((error) { + print(error.response); + }); +} +``` +```swift +import Appwrite + +let client = Client() + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + +let teams = Teams(client) + +let team = try await teams.create( + teamId: "teachers", + name: "Teachers", + roles: ["maths", "sciences", "arts", "literature"] +) +``` +```kotlin +import io.appwrite.Client +import io.appwrite.services.Teams + +val client = Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + +val teams = Teams(client) + +val response = teams.create( + teamId = "teachers", + name = "Teachers", + roles = listOf("maths", "sciences", "arts", "literature") +) +``` + +{% /multicode %} + +## Invite a member {% #create-membership %} + +You can invite members to a team by creating team memberships. For example, inviting "David" a math teacher, to the teachers team. + +{% multicode %} +```js +import { Client, Teams } from "appwrite"; + +const client = new Client(); + +const teams = new Teams(client); + +client + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID +; + +const promise = teams.createMembership( + 'teachers', + ["maths"], + "david@example.com" + ); + +promise.then(function (response) { + console.log(response); // Success +}, function (error) { + console.log(error); // Failure +}); +``` +```dart +import 'package:appwrite/appwrite.dart'; + +void main() { // Init SDK + Client client = Client(); + Teams teams = Teams(client); + + client + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + ; + Future result = teams.createMembership( + teamId: 'teachers', + roles: ['maths'], + email: 'david@example.com' + ); + + result + .then((response) { + print(response); + }).catchError((error) { + print(error.response); + }); +} +``` +```swift +import Appwrite + +let client = Client() + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + +let teams = Teams(client) + +let membership = try await teams.createMembership( + teamId: "teachers", + roles: ["maths"], + email: "david@example.com" +) +``` +```kotlin +import io.appwrite.Client +import io.appwrite.services.Teams + +val client = Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + +val teams = Teams(client) + +val response = teams.createMembership( + teamId = "teachers", + roles = listOf("maths"), + email = "david@example.com" +) +``` + +{% /multicode %} + +## Permissions {% #permissions %} + +You can grant permissions to all members of a team using the `Role.team()` role or +individual roles in the team using the `Role.team(, [, , ...])` role. + +| Description | Role | +| ------------------------------------------- | ------------------------------------------- | +| All members | `Role.team()`| +| Select roles | `Role.team(, [, , ...])`| \ No newline at end of file diff --git a/src/routes/docs/products/auth/user-management/+page.markdoc b/src/routes/docs/products/auth/user-management/+page.markdoc deleted file mode 100644 index fdd25fde4f..0000000000 --- a/src/routes/docs/products/auth/user-management/+page.markdoc +++ /dev/null @@ -1,357 +0,0 @@ ---- -layout: article -title: User Managements -description: This is the description used for SEO. ---- - -Appwrite has built-in features to help manage user accounts. Users can be organized into teams and be given labels, so they can be given different permissions and access different resources. Each user can also have their own preference object, which you can use to save preferences such as theme, language, and notification settings. - -## User preferences {% #preferences %} - -You can store user preferences on a user's account using Appwrite's [Update Preferences](#) endpoint. You can store user preferences such as theme, notification settings, or preferred language so they can be synced across multiple devices. - -Preferences are stored as a key-value JSON object. The maximum allowed size for preferences is 64kB, and an error will be thrown if this limit is exceeded. - -{% multicode %} -```js -import { Client, Account } from "appwrite"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject(''); // Your project ID - -const account = new Account(client); - -const promise = account.updatePrefs({darkTheme: true, language: 'en'}); - -promise.then(function (response) { - console.log(response); // Success -}, function (error) { - console.log(error); // Failure -}); -``` -```dart -import 'package:appwrite/appwrite.dart'; - -final client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject(''); // Your project ID - -final account = Account(client); - -final user = await account.updatePrefs( - prefs: { - "darkTheme": true, - "language": "en", - } -); -``` -```kotlin -import io.appwrite.Client -import io.appwrite.services.Account - -val client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -val account = Account(client) - -val user = account.updatePrefs( - prefs = mapOf( - "darkTheme" to true, - "language" to "en" - ) -) -``` -```swift -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -let account = Account(client) - -let user = try await account.updatePrefs( - prefs: [ - "darkTheme": true, - "language": "en" - ] -) -``` -```graphql -mutation { - accountUpdatePrefs( - prefs: "{\"darkTheme\": true, \"language\": \"en\"}" - ) { - _id - name - prefs { - data - } - } -} -``` -{% /multicode %} - -After a user's preferences are updated, they can be retrieved using the [Get Preferences](#) endpoint. - -{% multicode %} -```js -import { Client, Account } from "appwrite"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject(''); // Your project ID - -const account = new Account(client); - -const promise = account.getPrefs(); - -promise.then(function (response) { - console.log(response); // Success -}, function (error) { - console.log(error); // Failure -}); -``` -```dart -import 'package:appwrite/appwrite.dart'; - -final client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject(''); // Your project ID - -final account = Account(client); - -final prefs = await account.getPrefs(); -``` -```kotlin -import io.appwrite.Client -import io.appwrite.services.Account - -val client = Client(context) - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -val account = Account(client) - -val prefs = account.getPrefs() -``` -```swift -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -let account = Account(client) - -let prefs = try await account.getPrefs() -``` -```graphql -query { - accountGetPrefs { - data - } -} -``` -{% /multicode %} - -## Users API {% #users-api %} - -The Users API is a dedicated API for managing users from an admin's perspective. You'll notice that the Account API doesn't allow you to view or make changes to other users. This is by design and for **security reasons**. - -You can use the Users API with an API key authenticated [Server SDK](#) to manage users. If you must expose parts of the Users API to normal users, we suggest doing so through an Appwrite Function. Exposing API keys to users is **dangerous and a security risk**, by using an Appwrite Function, you can add your own validation to prevent malicious behavior. - -[Learn more about the Users API](#) - -## Labels {% #labels %} - -Labels are a good way to categorize a user to grant them access to resources. For example, a `subscriber` label can be added to a user once they've purchased a subscription. - -Using your extended markdown with the `{% multicode %}` syntax, the HTML content can be converted to the following markdown: - -{% multicode %} -```js -const sdk = require('node-appwrite'); - -const client = new sdk.Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('5df5acd0d48c2') // Your project ID - .setKey('98fd4...a2ad2'); // Your secret API key - -const users = new sdk.Users(client); - -const promise = users.updateLabels( - '[USER_ID]', - [ 'subscriber' ] -); - -promise.then(function (response) { - console.log(response); // Success -}, function (error) { - console.log(error); // Failure -}); -``` - -```php -use Appwrite\Client; -use Appwrite\Services\Users; -use Appwrite\Role; - -$client = new Client(); - -$client - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('5df5acd0d48c2') // Your project ID - .setKey('98fd4...a2ad2'); // Your secret API key - -$users = new Users($client); - -$result = $users->updateLabels( - '[USER_ID]', - [ 'subscriber' ] -); -``` - -```python -from appwrite.client import Client -from appwrite.services.users import Users -from appwrite.role import Role - -client = Client() - -(client - .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint - .set_project('5df5acd0d48c2') # Your project ID - .set_key('98fd4...a2ad2') # Your secret API key -) - -users = Users(client) - -result = users.update_labels( - '[USER_ID]', - [ 'subscriber' ] -); -``` -```ruby -require 'appwrite' - -include Appwrite - -client = Client.new - .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint - .set_project('5df5acd0d48c2') # Your project ID - .set_key('98fd4...a2ad2') # Your secret API key - -users = Users.new(client) - -response = users.update_labels( - user_id: '[USER_ID]', - labels: [ 'subscriber' ] -); -``` - -```deno -import * as sdk from "https://deno.land/x/appwrite/mod.ts"; - -let client = new sdk.Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('5df5acd0d48c2') // Your project ID - .setKey('98fd4...a2ad2'); // Your secret API key - -let users = new sdk.Users(client); - -const promise = users.updateLabels( - '[USER_ID]', - [ 'subscriber' ] -); - -promise.then(function (response) { - console.log(response); // Success -}, function (error) { - console.log(error); // Failure -}); -``` -```dart -import 'package:dart_appwrite/dart_appwrite.dart'; - -final client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('5df5acd0d48c2') // Your project ID - .setKey('98fd4...a2ad2'); // Your secret API key - -final users = Users(client); - -final result = await users.updateLabels( - userId: '[USER_ID]', - labels: [ 'subscriber' ], -); -``` -```kotlin -import io.appwrite.Client -import io.appwrite.Role -import io.appwrite.services.Users - -val client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("5df5acd0d48c2") // Your project ID - .setKey("98fd4...a2ad2") // Your secret API key - -val users = Users(client) - -val response = users.updateLabels( - userId = "[USER_ID]", - labels = [ 'subscriber' ] -); -``` - -```swift -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("5df5acd0d48c2") // Your project ID - .setKey("98fd4...a2ad2") // Your secret API key - -let users = Users(client) - -let response = try await users.updateLabels( - userId: "[USER_ID]", - labels: [ 'subscriber' ] -); -``` - -```csharp -using Appwrite; - -var client = new Client() - .SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .SetProject("5df5acd0d48c2") // Your project ID - .SetKey("98fd4...a2ad2"); // Your secret API key - -var users = new Users(client); - -var response = await users.UpdateLabels( - userId: "[USER_ID]", - labels: [ 'subscriber' ] -); -``` -{% /multicode %} - -This would correspond with the permissions below. - -| Description | Code Snippet | -| ------------------------------------------- | ------------------------------------------- | -| Read | `Permissions.read(Role.label('subscriber'))`| -| Update | `Permissions.update(Role.label('subscriber'))` | -| Delete | `Permissions.delete(Role.label('subscriber'))` | -| Create | `Permissions.create(Role.label('subscriber'))` | - -[Learn more about permissions](/docs/advanced/platform/permissions) - -## Teams {% #teams %} - -Teams are a good way to allow users to share access to resources. - -For example, in a todo app, a user can [create a team](#) for one of their todo lists and [invite another user](#) to the team to grant the other user access. The invited user can [accept the invitation](#) to gain access. If the user's ever removed from the team, they'll lose access again. From 10132b15c251f29430107dea00eb008405974c81 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Thu, 21 Sep 2023 20:01:32 +0000 Subject: [PATCH 13/13] Split account vs user into separate page --- .../account-vs-user.md} | 13 +++----- src/routes/docs/products/auth/+layout.svelte | 33 +++++++++++++------ .../docs/products/auth/accounts/+page.markdoc | 2 ++ 3 files changed, 29 insertions(+), 19 deletions(-) rename src/{routes/docs/products/auth/account-vs-users-api/+page.markdoc => partials/account-vs-user.md} (81%) diff --git a/src/routes/docs/products/auth/account-vs-users-api/+page.markdoc b/src/partials/account-vs-user.md similarity index 81% rename from src/routes/docs/products/auth/account-vs-users-api/+page.markdoc rename to src/partials/account-vs-user.md index 077a51e653..638d806300 100644 --- a/src/routes/docs/products/auth/account-vs-users-api/+page.markdoc +++ b/src/partials/account-vs-user.md @@ -1,12 +1,7 @@ ---- -layout: article -title: Account vs. Users API -description: This is the description used for SEO. ---- +{% info title="Account vs Users API" %} Appwrite provides two APIs to manager user accounts. -## Account API {% #account-api %} The Account API is the API you should use in your **client applications** like web, Flutter, mobile, and native apps. Account API creates sessions, which represent an authenticated user and is attached to a user's [account](/docs/products/auth/account). Sessions respect [permissions](/docs/advanced/platform/permissions), which means users can only access resources if they have been granted the correct permissions. @@ -14,13 +9,13 @@ Sessions respect [permissions](/docs/advanced/platform/permissions), which means You'll notice that the Account API doesn't allow you to view or make changes to other users. This is by design and for **security reasons**. -[Account API references](#) +[Account API references](/docs/references/cloud/client-web/account) -## Users API {% #users-api %} The Users API is a dedicated API for managing users from an admin's perspective. **Do not use the Users API on client applications**. It should be used with backend or server-side applications with the [Server SDK](#). Users API uses API keys instead of sessions. This means they're not resticted by permissions, but by the scopes granted to the API key used. -[Users API references](#) \ No newline at end of file +[Users API references](/docs/references/cloud/server-nodejs/users) +{% /info %} \ No newline at end of file diff --git a/src/routes/docs/products/auth/+layout.svelte b/src/routes/docs/products/auth/+layout.svelte index 4e87fb8a3a..9cd071a117 100644 --- a/src/routes/docs/products/auth/+layout.svelte +++ b/src/routes/docs/products/auth/+layout.svelte @@ -25,27 +25,27 @@ label: 'Journeys', items: [ { - label: 'Email and password', + label: 'Email and password login', href: '/docs/products/auth/email-password' }, { - label: 'Phone (SMS)', + label: 'Phone (SMS) login', href: '/docs/products/auth/phone-sms' }, { - label: 'Magic URL', + label: 'Magic URL login', href: '/docs/products/auth/magic-url' }, { - label: 'OAuth 2', + label: 'OAuth 2 login', href: '/docs/products/auth/oauth2' }, { - label: 'Anonymous', + label: 'Anonymous login', href: '/docs/products/auth/anonymous' }, { - label: 'Server integrations', + label: 'JWT login', href: '/docs/products/auth/server-integrations' }, ] @@ -53,10 +53,6 @@ { label: 'Concepts', items: [ - { - label: 'Account vs. Users API', - href: '/docs/products/auth/account-vs-users-api' - }, { label: 'Accounts', href: '/docs/products/auth/accounts' @@ -75,6 +71,23 @@ } ] }, + { + label: 'References', + items: [ + { + label: 'Account API', + href: '/docs/references/cloud/client-web/account' + }, + { + label: 'Users API', + href: '/docs/references/cloud/server-nodejs/users' + }, + { + label: 'Users API', + href: '/docs/references/cloud/client-web/teams' + } + ] + }, ]; diff --git a/src/routes/docs/products/auth/accounts/+page.markdoc b/src/routes/docs/products/auth/accounts/+page.markdoc index 4e71ef0025..a4f1559da8 100644 --- a/src/routes/docs/products/auth/accounts/+page.markdoc +++ b/src/routes/docs/products/auth/accounts/+page.markdoc @@ -8,6 +8,8 @@ Appwrite allows users to create accounts. Users can be organized into teams and be given labels, so they can be given different permissions and access different resources. Each user's account can also have their own preference object, which you can use to save preferences such as theme, language, and notification settings. +{% partial file="account-vs-user.md" /%} + ## Signup and login {% signup-login %} You can signup and login a user with an account create through [email password](/docs/products/auth/email-password),