From 6472787cc04f6211daa0b5d96b557f943126b6c9 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Mon, 21 Aug 2023 13:53:12 +0200 Subject: [PATCH 01/10] feat: mail templates --- .../reference/engine/tenant/mail-templates.md | 99 +++++++++++++++++++ sidebars.js | 1 + 2 files changed, 100 insertions(+) create mode 100644 docs/reference/engine/tenant/mail-templates.md diff --git a/docs/reference/engine/tenant/mail-templates.md b/docs/reference/engine/tenant/mail-templates.md new file mode 100644 index 00000000..0a01f842 --- /dev/null +++ b/docs/reference/engine/tenant/mail-templates.md @@ -0,0 +1,99 @@ +--- +title: Mail templates +--- + +Mail templates in Contember enable tailored communication for emails dispatched by the Tenant API. Via the `/tenant` path and with either the `SUPER_ADMIN` or `PROJECT_ADMIN` global roles, users can create and manage these templates seamlessly. + +## Mail Types +Contember provides three primary mail types, each serving specific communication needs: + +- **NEW_USER_INVITED**: This mail type welcomes newly invited users. Often, it's the first touchpoint a new user has with the platform, typically containing details for setting up their account or accessing the platform's resources. + +- **EXISTING_USER_INVITED**: Deployed when inviting an already registered user to a new project. It's a notification template, guiding users to the new project or functionalities they've been given access to. + +- **RESET_PASSWORD_REQUEST**: For situations when a user forgets their password. This email directs users to reset their password, ensuring they regain access to their account. + +Each of these mail types comes with a straightforward default template. Additionally, in Contember Cloud setups, enhanced custom templates are present, which users can modify or overwrite based on their preferences. +Of course! I'll include more detailed information about the GraphQL mutations by elaborating on the structure of the input. + +## Managing Templates via GraphQL + +### Adding a Mail Template + Utilize the `addMailTemplate` mutation to introduce a new email template. Below is a comprehensive example, showcasing all possible fields: + + ```graphql + mutation { + addMailTemplate(template: { + type: NEW_USER_INVITED, + subject: "Welcome to Our Platform", + content: "Hello {{email}}, get started with our platform!", + projectSlug: "YourProjectSlug", # Optional: for project-specific templates + variant: "en-US", # Optional: for different variants like locales + useLayout: true # Optional: set to false for custom designs + }) { + ok, + error { + code, + developerMessage + } + } + } + ``` + Input breakdown: +- `type`: The type of the mail, i.e., `NEW_USER_INVITED`, `EXISTING_USER_INVITED`, or `RESET_PASSWORD_REQUEST`. +- `subject`: The email's subject. +- `content`: The email's main content, with Mustache variables for dynamic information. +- `projectSlug`: To specify a particular project. +- `variant`: For different template variants, such as language or design. +- `useLayout`: A flag to determine whether to use the default layout. + +- **Removing a Mail Template**: +To delete a custom template, use the `removeMailTemplate` mutation. When removed, the system defaults back to the original template. + + ```graphql + mutation { + removeMailTemplate(templateIdentifier: { + type: NEW_USER_INVITED, + projectSlug: "YourProjectSlug", # Optional: for project-specific templates + variant: "en-US" # Optional: for different variants like locales + }) { + ok, + error { + code, + developerMessage + } + } + } + ``` +Input breakdown: +- `type`: The type of the mail to remove. +- `projectSlug`: To specify a particular project. +- `variant`: To specify which variant to remove, if any. + +## Key Details + +- **Global vs. Project-specific Templates**: By default, templates are global. To create a project-specific template, include the `projectSlug`. Such project-specific templates will always have precedence over global ones. + +- **Template Variants**: Especially relevant for projects serving diverse audiences, Contember supports the creation of variant templates. Whether for different languages or thematic designs, variants ensure your emails are contextually apt. To use a variant, include the `variant` parameter in a mutaiton. + +- **Custom Layout**: For those seeking granular control over design, use the `useLayout: false` flag. This means your template won't inherit the standard layout (white centered box on light gray background), granting you carte blanche on the HTML structure. + +## Mustache Variables in Templates + +Contember uses Mustache for dynamic content in templates. Here are the variables available for each mail type: + +- **NEW_USER_INVITED**: + - `{{email}}`: Recipient's email. + - `{{password}}`: Password (if available). + - `{{token}}`: Token for account validation (if available). + - `{{project}}`: Project name or identifier. + - availability of `password` and `token` variable depends on [invitation method](./users.md#password-handling) + +- **EXISTING_USER_INVITED**: + - `{{email}}`: Recipient's email. + - `{{project}}`: New project they've been invited to. + +- **RESET_PASSWORD_REQUEST**: + - `{{email}}`: Recipient's email. + - `{{token}}`: Token for password reset. + - `{{project}}`: Project name or identifier (if relevant). diff --git a/sidebars.js b/sidebars.js index 9de3ffa1..67ce0757 100644 --- a/sidebars.js +++ b/sidebars.js @@ -198,6 +198,7 @@ module.exports = { "reference/engine/tenant/memberships", "reference/engine/tenant/api-keys", "reference/engine/tenant/idp", + "reference/engine/tenant/mail-templates", ], }, { From 372df40294abb5ab6be7f183f53224a941967a2d Mon Sep 17 00:00:00 2001 From: David Matejka Date: Wed, 30 Aug 2023 15:25:13 +0200 Subject: [PATCH 02/10] feat: improve user invite section --- docs/reference/engine/tenant/users.md | 30 ++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/reference/engine/tenant/users.md b/docs/reference/engine/tenant/users.md index 5c084136..d29b3b1f 100644 --- a/docs/reference/engine/tenant/users.md +++ b/docs/reference/engine/tenant/users.md @@ -54,9 +54,15 @@ mutation { Only persons are allowed to sign out. It cannot be called with a permanent API key. :::: -## Invite +## Inviting Users to a Project -Superadmin or a project admin can invite other person to a project. You can also setup [Tenant ACL permissions](/reference/engine/schema/acl.md#tenant-permissions) for other user roles. +The `invite` mutation provides a way to add a new member to a specified project within the system. + +### Invite permissions + +By default, users with the global roles `super_admin` and `project_admin`, along with project-level `admin`, are authorized to issue invitations. However, you can extend this capability to other user roles by configuring [Tenant ACL permissions](/reference/engine/schema/acl.md#tenant-permissions). + +#### Example: sending and invitation ```graphql mutation { @@ -66,9 +72,13 @@ mutation { memberships: [ { role: "editor", - variables: [{name: "language", values: ["cs"]}] + variables: [{name: "language", values: ["en}] } - ] + ], + options: { + mailVariant: "en_us", # Optional + method: RESET_PASSWORD # Recommended + } ) { ok error { @@ -78,4 +88,14 @@ mutation { } ``` -When a user with given email already exists in a system, he is just added to a project, otherwise a new user is created and login instructions are sent to given e-mail. +### Existing vs new users + +If the specified email address already corresponds to a user in the system, that user will simply be added to the designated project. If the user does not yet exist, a new account will be created, and login instructions will be sent to the provided email address. + +### Password handling + +By default, the invitation process auto-generates a password and sends it via email. However, it's recommended to set the invite method to `RESET_PASSWORD`. This way, a reset token is sent instead of a generated password. Ensure your [mail templates](./mail-templates.md) are appropriately configured to include the password setup link. Note that the default method will transition to `RESET_PASSWORD` in future updates. + +### Customizing Email Templates + +You can specify a preferred email template variant by setting the `mailVariant` option, as outlined in the [mail templates](./mail-templates.md) section. From d8f60d74676da7201c38abdf85aff9c9d8723962 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Wed, 30 Aug 2023 15:39:14 +0200 Subject: [PATCH 03/10] improve tenant api overview --- docs/reference/engine/tenant/overview.md | 46 ++++++++++++------------ static/assets/tenant-api.drawio | 1 - static/assets/tenant-api.svg | 3 -- 3 files changed, 24 insertions(+), 26 deletions(-) delete mode 100644 static/assets/tenant-api.drawio delete mode 100644 static/assets/tenant-api.svg diff --git a/docs/reference/engine/tenant/overview.md b/docs/reference/engine/tenant/overview.md index e80d92f0..d472f616 100644 --- a/docs/reference/engine/tenant/overview.md +++ b/docs/reference/engine/tenant/overview.md @@ -1,39 +1,41 @@ --- -title: Tenant API overview +title: Overview of Tenant API --- -Contember Tenant API is a GraphQL API allowing you to manage **projects**, **tokens**, **users** and their **roles**. Unlike [Content API](../content/overview.md), this API is shared for all projects. It is available on URL `https://engine-hostname/tenant` and to access it you need to provide `Bearer` token in `Authorization` header. +The Contember Tenant API is a specialized GraphQL API designed for the centralized management of **projects**, **tokens**, **users**, and their respective **roles**. Unlike the [Content API](../content/overview.md), the Tenant API is shared across all projects and is accessible via the URL `https://engine-hostname/tenant`. To interact with this API, a `Bearer` token must be supplied in the `Authorization` header. +## Key Concepts -## Terms +- **Identity**: Contains information regarding roles and project memberships. +- **Person**: Associated with an identity and possesses credentials (email and password) for authentication. +- **Authorization Key/Token**: Serves as either a permanent (for applications) or session-based (for users) authorization token tied to a specific identity. This token is verified using a Bearer token. -- Identity - Holds information about roles and project memberships. -- Person - Has assigned some identity and has credentials (email and password), using which he is authenticated to claim his identity. -- Authorization key/token - Represents permanent (for applications) or session (for users) authorization of particular identity. It is verified using a Bearer token. +## Authorization Mechanisms +Much like the Content API, the Tenant API requires an authorization token for every request, including login operations. -## Authorization tokens +The default keys for the `login` and `super_admin` roles are configured via the environment variables `CONTEMBER_LOGIN_TOKEN` and `CONTEMBER_ROOT_TOKEN`. For local development setups, these keys can be found in the `docker-compose.yaml` file. -Like a Content API, Tenant API also needs an authorization token for each request - even for a login. +The login token can be employed for various sign-in methods, including email/password-based and Identity Provider (IdP) authentication, as well as for password reset operations. -The key is defined using `CONTEMBER_LOGIN_TOKEN` env variable. For local development, you can find this key in `docker-compose.yaml` +There are primarily two types of authorization tokens: -You use this token for sign in (using both email/password or IdP) and password reset mutations. +- **Permanent API Token**: Generally used in application settings where user authentication is not required. [This token can be generated through Tenant API mutations](api-keys.md). -Besides special tokens like the login token, there are two basic kinds of authorization tokens: -- permanent API token for e.g. applications, where you don't authenticate users. You can [generate it using Tenant API mutations](api-keys.md) -- session token, which user obtain after he signs in. You use it e.g. in administration for each action that given user makes. +- **Session Token**: Obtained when a user successfully signs in and is typically used for tracking individual user actions within administrative interfaces. +## Choosing the Right Token -## Which token should I use? +Choosing the appropriate token for specific actions can sometimes be confusing. Here's a step-by-step example to clarify how to generate an API token for an application to read data from the Content API: -It is sometimes a bit confusing which token should be used for an action. So lets show it on an example - you as a project administrator want to create a API token for application, so application can read a data from Content API. +1. **Locate the Login Token**: Retrieve your default login token, usually found in your environment configuration. -1. Find the login token. -2. Use this token as a Bearer token and run `signIn` mutation against Tenant API. -3. You will receive another token, this is your session token with limited validity. -4. Run `createApiKey` mutation against Tenant API but now with your personal session token. -5. The mutation returns a new permanent token with permissions you have set. -6. Now you can use this permanent API token and run some queries against Content API. +2. **Sign In**: Use the retrieved login token as a Bearer token and execute the `signIn` mutation against the Tenant API. -![tenant API diagram](/assets/tenant-api.svg) +3. **Session Token**: Upon successful sign-in, you'll receive another token—this is your session token, which has a limited validity period. + +4. **Create API Key**: Execute the `createApiKey` mutation against the Tenant API, this time using your newly acquired session token. + +5. **Retrieve Permanent API Token**: The mutation will return a new, permanent API token configured with the permissions you have set. + +6. **Interact with Content API**: You can now use this permanent API token to execute queries against the Content API. diff --git a/static/assets/tenant-api.drawio b/static/assets/tenant-api.drawio deleted file mode 100644 index 8a088732..00000000 --- a/static/assets/tenant-api.drawio +++ /dev/null @@ -1 +0,0 @@ -5VrbcuI4EP0aHnFZkq+PCZlLqmZrs5Wp2tmnlGILo42xWFkEyNevLEsY4TGwA5hkyUusttSSu/scd7cZoNF0+YXj2eQ3lpJ8AN10OUB3AwgB8KH8V0lWtST0US3IOE31pEbwSN+IFrpaOqcpKa2JgrFc0JktTFhRkERYMsw5W9jTxiy3d53hjLQEjwnO29I/aSomtTSCYSP/Smg2MTuDIK7vTLGZrJ+knOCULTZE6NMAjThjor6aLkckr4xn7FKv+9xxd30wTgpxyIJRFnKQTr9zuPj6dH//9Db//WmoH6MUK/PAnM2LlFRr3AG6ZVxMWMYKnH9jbCaFQAr/JkKstKvwXDApmohpru+SJRU/5PXQdVwXasFflT4HIjO+W+oN1GBlBoXgqx9qahxDI6jXBnFoBM1iNbJWPxBOp0QQvqF/W1Y/M0lbnm9MqUUlm/OE7LCfCUnMMyJ2zENrh0ukECZPw1dyHSc5FvTVPgfWIZut5zVelRfasf/ByToiX3E+1zvlLKOFgtILKVohIMhS2D7FOc0KeZ1IA1VmvH0lXFCJkht9Y0rTtFp+y0lJ3/CzUlXZesZoIdQD+bcD/05KcvxM8lucvGQq1EYsZ1zti8bqb+2gag+yHPwE5Vp/g61N13XHedv+WruMTC/UW2ie0ix1sIO07ofqcRvFMLCU+o4X2irYeFzKwNn28PqIv+50AFt+rSL+UQ8LVih3HY12A1lgwzX096FV00TFEshiCT/0drPE+4A0cH8eU/1gGvgtUM9LaQ75gKQsKbsqdNex3glv+SaSeUh8HKI1hAFyoqg3DMcfBsPAgnAUfQwIB5eEsAnvDQjPCJ/igqiAux70xnvR6wXhGd7OQ88x5YlBN3A82Bu6W+7/TgqsDnjzcL8nMV9MqCCPM6xwsJC1lx0UY5rnm96LEpIkUl4KLsNq485z5Hu+u8uvLQB2esqLXduagR4vmsoJmLCYbFRN61g5OcaCPWY8hi2rzCWyGRPsZcyuGsVUPZHFoyhCl+RRdCiPXpJGozaLcpKSMS2kl6t0SMxnDZ0GeUWfzzJRCjKhAqDSX5QCF5UpbtTchE0lDafXQL4db8CGe1G8VcSAk3Avgo5rc/oQek7g90W+qBU1Y8pL9d6VaGri5hgSPgGlQneLUsMDKTU4F6MC0DLKOXLSU2aD7kegMdCOyKvr0oDdYKgywSiyM7bhaegIeltatzScMQtsVwFl5a3qrfTu6Ad6F6efdsf6rCWxKW2bHC+S9covJHmnJLTgQxBaOzG7xtbU7s6zpDQYGEudNMGCttJh7Pj99Z6DlusTTrCo8qqNFsd2Lq6qXveFrN4d7yFwad6Dft+81/oCF3noqOrW7hB6F61s19+S91Eo7Ggt99QibANJfWf/45s6QjljRUmugUbr8N/xAQ+4pkV4JG8Cz7GZM+6xJWiOu+HvEZMu+x81BT334lSKeqHSU7IVPJStLprxmSKqg63+mRPVYFlQ6ffWy/8qP33Ajt+FNLQGzHfL09a7Rs2699ZbvWtiuZvi3CSnavjOksBzMpccNr8Eq03d/J4OffoX \ No newline at end of file diff --git a/static/assets/tenant-api.svg b/static/assets/tenant-api.svg deleted file mode 100644 index 61566b51..00000000 --- a/static/assets/tenant-api.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -
login token
login token
user session token
user session token
permanent token
permanent token
Tenant API
Tenant API
predefined setup token
or instance:up command
predefined setup token...
first time setup
first time setup
login token
login token
sign in
sign in
session token
session token
create permanent
API key
create permanent...
GraphQL response
GraphQL response
Content API
Content API
GraphQL request with
permanent token
GraphQL request with...
Content API client
Content API client
\ No newline at end of file From 84c63810ce6ea8a68e7797273960704d66455969 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Wed, 30 Aug 2023 15:40:53 +0200 Subject: [PATCH 04/10] typo --- docs/reference/engine/tenant/users.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/engine/tenant/users.md b/docs/reference/engine/tenant/users.md index d29b3b1f..ffd2e0c8 100644 --- a/docs/reference/engine/tenant/users.md +++ b/docs/reference/engine/tenant/users.md @@ -52,7 +52,7 @@ mutation { ``` :::note Only persons are allowed to sign out. It cannot be called with a permanent API key. -:::: +::: ## Inviting Users to a Project From 1b4e47c0d4c2ef17bceef4347201340b51a65b16 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Wed, 30 Aug 2023 16:29:38 +0200 Subject: [PATCH 05/10] split invite and user session management, add createSessionToken docs --- .../engine/tenant/{users.md => invites.md} | 64 ++------------ .../reference/engine/tenant/mail-templates.md | 2 +- docs/reference/engine/tenant/memberships.md | 2 +- docs/reference/engine/tenant/sessions.md | 83 +++++++++++++++++++ sidebars.js | 3 +- 5 files changed, 92 insertions(+), 62 deletions(-) rename docs/reference/engine/tenant/{users.md => invites.md} (64%) create mode 100644 docs/reference/engine/tenant/sessions.md diff --git a/docs/reference/engine/tenant/users.md b/docs/reference/engine/tenant/invites.md similarity index 64% rename from docs/reference/engine/tenant/users.md rename to docs/reference/engine/tenant/invites.md index ffd2e0c8..d1d45085 100644 --- a/docs/reference/engine/tenant/users.md +++ b/docs/reference/engine/tenant/invites.md @@ -1,67 +1,9 @@ --- -title: User management +title: User invitations --- -## Sign in - -For sign in, you need a [login token](overview.md#authorization-tokens). After successful login, you receive a session token for subsequent requests. - - -#### Example: sign in -```graphql -mutation { - signIn(email: "admin@example.com", password: "123456", expiration: 3600) { - ok - result { - token - } - error { - code - } - } -} -``` - -:::note -Expiration is automatically extended after each request. -::: - -## Sign out - -By calling `signOut` mutation, you can invalidate a token associated with current request - - -#### Example: sign out current session -```graphql -mutation { - signOut { - ok - } -} -``` - -By setting a parameter `all` to `true`, you invalidate all tokens associated with a current identity. - -#### Example: sign out all sessions -```graphql -mutation { - signOut(all: true) { - ok - } -} -``` -:::note -Only persons are allowed to sign out. It cannot be called with a permanent API key. -::: - -## Inviting Users to a Project - The `invite` mutation provides a way to add a new member to a specified project within the system. -### Invite permissions - -By default, users with the global roles `super_admin` and `project_admin`, along with project-level `admin`, are authorized to issue invitations. However, you can extend this capability to other user roles by configuring [Tenant ACL permissions](/reference/engine/schema/acl.md#tenant-permissions). - #### Example: sending and invitation ```graphql @@ -88,6 +30,10 @@ mutation { } ``` +### Invite permissions + +By default, users with the global roles `super_admin` and `project_admin`, along with project-level `admin`, are authorized to issue invitations. However, you can extend this capability to other user roles by configuring [Tenant ACL permissions](/reference/engine/schema/acl.md#tenant-permissions). + ### Existing vs new users If the specified email address already corresponds to a user in the system, that user will simply be added to the designated project. If the user does not yet exist, a new account will be created, and login instructions will be sent to the provided email address. diff --git a/docs/reference/engine/tenant/mail-templates.md b/docs/reference/engine/tenant/mail-templates.md index 0a01f842..8c29271a 100644 --- a/docs/reference/engine/tenant/mail-templates.md +++ b/docs/reference/engine/tenant/mail-templates.md @@ -87,7 +87,7 @@ Contember uses Mustache for dynamic content in templates. Here are the variables - `{{password}}`: Password (if available). - `{{token}}`: Token for account validation (if available). - `{{project}}`: Project name or identifier. - - availability of `password` and `token` variable depends on [invitation method](./users.md#password-handling) + - availability of `password` and `token` variable depends on [invitation method](./invites.md#password-handling) - **EXISTING_USER_INVITED**: - `{{email}}`: Recipient's email. diff --git a/docs/reference/engine/tenant/memberships.md b/docs/reference/engine/tenant/memberships.md index 09fa64e4..8cb12804 100644 --- a/docs/reference/engine/tenant/memberships.md +++ b/docs/reference/engine/tenant/memberships.md @@ -6,7 +6,7 @@ An identity can be a member of any project with some role and optionally variabl ## Creating a project membership -Add an existing identity to a project. For this operation you need to know an identity ID. If you want to add a user by an email check [invite mutation](users.md#invite) +Add an existing identity to a project. For this operation you need to know an identity ID. If you want to add a user by an email check [invite mutation](./invites.md) ```graphql mutation { diff --git a/docs/reference/engine/tenant/sessions.md b/docs/reference/engine/tenant/sessions.md new file mode 100644 index 00000000..ec299889 --- /dev/null +++ b/docs/reference/engine/tenant/sessions.md @@ -0,0 +1,83 @@ +--- +title: User Sessions +--- + +User session management is a crucial aspect of maintaining secure and efficient interactions within your application. This guide elaborates on how to manage user sessions through sign-ins and sign-outs using Contember's Tenant API. + +## Sign In to Your Account + +To sign in, you need a [login token](overview.md#authorization-tokens). Once you've successfully signed in, a session token will be issued, which is necessary for making subsequent authenticated requests. + +#### Example: How to Sign In + +```graphql +mutation { + signIn(email: "admin@example.com", password: "123456", expiration: 3600) { + ok + result { + token + } + error { + code + } + } +} +``` + +:::note +The session token's expiration time will be automatically extended with each subsequent request you make, so you don't need to worry about frequent re-logins. +::: + +## Sign Out of Your Account + +Signing out is straightforward: all you need to do is call the `signOut` mutation. This invalidates the session token associated with the current request, effectively logging you out. + +#### Example: How to Sign Out from the Current Session + +```graphql +mutation { + signOut { + ok + } +} +``` + +### Signing Out of All Sessions + +If you want to take an extra step in security or think your credentials have been compromised, you can invalidate all session tokens associated with your current identity by setting the `all` parameter to `true`. + +#### Example: How to Sign Out from All Sessions + +```graphql +mutation { + signOut(all: true) { + ok + } +} +``` + +:::note +Keep in mind that the `signOut` mutation is only applicable for persons (users with a set of credentials). It cannot be called using a permanent API key. This design choice ensures that application-level permissions remain secure. +::: + +## Advanced: Create session token manually + +For users with `super_admin` or `project_admin` roles, the `createSessionToken` mutation provides a way to generate session tokens for other users. This functionality enables administrators to act as a specific user. + +### Example: Create session token for given user + +```graphql +mutation { + createSessionToken(email: "example@email.com", expiration: 3600) { + ok + result { + token + } + error { + code + } + } +} +``` + +You must supply either an `email` or a `personId`, along with an optional expiration time for the token. diff --git a/sidebars.js b/sidebars.js index 67ce0757..e82ae524 100644 --- a/sidebars.js +++ b/sidebars.js @@ -194,7 +194,8 @@ module.exports = { label: "Tenant API", items: [ "reference/engine/tenant/overview", - "reference/engine/tenant/users", + "reference/engine/tenant/sessions", + "reference/engine/tenant/invites", "reference/engine/tenant/memberships", "reference/engine/tenant/api-keys", "reference/engine/tenant/idp", From 00fe94869fdfbea4ac8221c185c0839bd49f9af9 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Wed, 30 Aug 2023 16:49:53 +0200 Subject: [PATCH 06/10] extract tenant acl to its own chapter --- docs/intro/graphql.mdx | 4 +- docs/reference/engine/schema/acl.md | 106 +-------------------- docs/reference/engine/schema/tenant-acl.md | 83 ++++++++++++++++ sidebars.js | 1 + 4 files changed, 87 insertions(+), 107 deletions(-) create mode 100644 docs/reference/engine/schema/tenant-acl.md diff --git a/docs/intro/graphql.mdx b/docs/intro/graphql.mdx index b9fed39f..795410a1 100644 --- a/docs/intro/graphql.mdx +++ b/docs/intro/graphql.mdx @@ -164,8 +164,8 @@ The Tenant API facilitates user logins and registrations, membership management,

Basic explanation of Tenant API functionality.

- -

Manage users in your project over Tenant API.

+ +

Invite users to your projects.

Explaining relationship between users and projects.

diff --git a/docs/reference/engine/schema/acl.md b/docs/reference/engine/schema/acl.md index 5778bc37..25b7b2d8 100644 --- a/docs/reference/engine/schema/acl.md +++ b/docs/reference/engine/schema/acl.md @@ -151,112 +151,8 @@ Each variable must be exported from schema definition using `export const ...` ## Tenant permissions -Here, you can also setup [Tenant API] permissions for a role. It is done under the `tenant` field of the role. +See [tenant permissions](./tenant-acl.md) -### Invite permissions - -By setting `invite` to `true` you can allow a user to invite other users. Keep in mind, you also need to set appropriate [manage permissions](#manage-permissions) for the role. - -There is also `unmanagedInvite` flag, which allows you to invite users using `unmanagedInvite` mutation. - -#### Example: enabling invite - -```typescript -const editorRole = { - // ... - tenant: { - invite: true, - }, -} -``` - -### Manage permissions - -Defines which other roles and their variables a user can manage. First you define a role, which you want to manage as a object key: - -```typescript -const editorRole = { - // ... - tenant: { - manage: { - editor: { - // ... - }, - }, - }, -} -``` - -With this, you would be able to manage users with the role `editor`, but not their variables. - -To allow managing all variable, just pass `variables: true`, - -```typescript -const editorRole = { - // ... - tenant: { - manage: { - editor: { - variables: true, - }, - }, - }, -} -``` - -To granularly define which variables a user can manage, you can pass an object with variable names as keys and either `true` or source variable name as a value. - -```typescript -const editorRole = { - // ... - tenant: { - manage: { - editor: { - variables: { - language: true, - site: 'assignable_site', - }, - }, - }, - }, -} -``` - -This would allow a user manage `editor` role and assign any value to `language` variable. For `site` variable, user can only assign values from his own `assignable_site` source variable. - - -## System API permissions - -You can also set some flags affecting system API. - -### [History API](/reference/engine/content/event-log.md) - -By setting `history` flag under `system` section to `true` you can allow a user to access the history API. - -```typescript -const editorRole = { - // ... - system: { - history: true, - } -} -``` -:::caution -Allowing history API access will allow user to access all the data in history API, ignoring entity rules. -::: - -### Migrations - -Allow a role to run [migrations](migrations.md). Project admin (and superadmin) can always run migrations. Also, there is a default `deployer` role with this and only permission. - -```typescript -const editorRole = { - // ... - system: { - migrations: true, - } -} -``` ### Assume identity diff --git a/docs/reference/engine/schema/tenant-acl.md b/docs/reference/engine/schema/tenant-acl.md new file mode 100644 index 00000000..aa025cb6 --- /dev/null +++ b/docs/reference/engine/schema/tenant-acl.md @@ -0,0 +1,83 @@ +--- +title: Tenant Permissions +--- + +The Tenant permissions feature in Contember allows you to fine-tune control over various actions and roles. These permissions are specified under the `tenant` field when you define a role. + +## Invite Permissions + +The `invite` permission controls the ability to invite other users to a project. You can use either a simple boolean value or a more advanced [membership match rule](#understanding-membership-match-rules) object. If `invite` is set to `true`, the existing rules under `manage` will apply. + +#### Example: Simple Invite Permission + +```typescript +export const editorRole = acl.createRole('editor', { + tenant: { + invite: true, + }, +}); +``` + +### Unmanaged Invite Permissions + +Similar to `invite`, the `unmanagedInvite` field can accept a boolean value or a [membership match rule](#understanding-membership-match-rules) object. This permission allows you to use the `unmanagedInvite` mutation. + +### View Permissions + +The `view` field enables you to specify which roles and their associated variables a user can view. + +#### Example: View Permissions + +```typescript +export const editorRole = acl.createRole('editor', { + tenant: { + view: { + editor: { + variables: { + language: true, + }, + }, + }, + }, +}); +``` + +### Manage Permissions + +The `manage` field helps you specify the roles and their variables that a user can manage. + +#### Example: Manage Permissions + +```typescript +export const editorRole = acl.createRole('editor', { + tenant: { + manage: { + editor: { + variables: true, + }, + }, + }, +}); +``` + +## Understanding membership match rules + +The membership match rules is an object that enables you to define more granular rules for managing memberships, roles, and variables. It comes into play when you set values for `invite`, `unmanagedInvite`, `view`, and `manage` fields in the `tenant` permissions. + +This rule allows you to: + +- Define which roles can be managed +- Specify what variables within those roles can be managed + +For example, if you only want to allow a user to manage the `editor` role and assign any value to the `language` variable but restrict values for the `site` variable, your rule would look like this: + +```typescript +{ + editor: { + variables: { + language: true, + site: 'assignable_site', + }, + }, +} +``` diff --git a/sidebars.js b/sidebars.js index e82ae524..ff2ce87a 100644 --- a/sidebars.js +++ b/sidebars.js @@ -164,6 +164,7 @@ module.exports = { "reference/engine/schema/views", "reference/engine/schema/migrations", "reference/engine/schema/acl", + "reference/engine/schema/tenant-acl", "reference/engine/schema/validations", ], }, From 0221388870bd5427775dd48314715b5e38c17341 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Thu, 31 Aug 2023 10:50:37 +0200 Subject: [PATCH 07/10] add version notes --- docs/reference/engine/schema/tenant-acl.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/reference/engine/schema/tenant-acl.md b/docs/reference/engine/schema/tenant-acl.md index aa025cb6..d30fa3b0 100644 --- a/docs/reference/engine/schema/tenant-acl.md +++ b/docs/reference/engine/schema/tenant-acl.md @@ -4,7 +4,7 @@ title: Tenant Permissions The Tenant permissions feature in Contember allows you to fine-tune control over various actions and roles. These permissions are specified under the `tenant` field when you define a role. -## Invite Permissions +## Engine 1.3+ Invite Permissions The `invite` permission controls the ability to invite other users to a project. You can use either a simple boolean value or a more advanced [membership match rule](#understanding-membership-match-rules) object. If `invite` is set to `true`, the existing rules under `manage` will apply. @@ -18,11 +18,15 @@ export const editorRole = acl.createRole('editor', { }); ``` -### Unmanaged Invite Permissions +:::note +Before Engine 1.3, the `invite` and `unmanagedInvite` allowed only a boolean value. +::: + +### Engine 1.3+ Unmanaged Invite Permissions Similar to `invite`, the `unmanagedInvite` field can accept a boolean value or a [membership match rule](#understanding-membership-match-rules) object. This permission allows you to use the `unmanagedInvite` mutation. -### View Permissions +### Engine 1.3+ View Permissions The `view` field enables you to specify which roles and their associated variables a user can view. From 16d1ff67c6b1294e479c38a474d0fe8bec561d15 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Thu, 31 Aug 2023 12:39:53 +0200 Subject: [PATCH 08/10] improve api keys chapter --- docs/reference/engine/tenant/api-keys.md | 96 +++++++++++++++++++----- 1 file changed, 79 insertions(+), 17 deletions(-) diff --git a/docs/reference/engine/tenant/api-keys.md b/docs/reference/engine/tenant/api-keys.md index 97d33bdb..22e37f0c 100644 --- a/docs/reference/engine/tenant/api-keys.md +++ b/docs/reference/engine/tenant/api-keys.md @@ -2,23 +2,58 @@ title: API keys management --- -For applications, where you don't identify and authenticate individual users, you can use an API key. These API keys are in fact an identity (without a person) with permanent access token. So you can later manage memberships of users and API keys using the same API. +# API Keys Management -## Create API key +API keys serve as a way to authenticate applications where individual user identification and authentication are not required. They function as permanent access tokens. + +## Create an API Key for a Project + +You can create a project-specific API key using the GraphQL API: -### Using GraphQL API ```graphql mutation { createApiKey( projectSlug: "my-blog", - description: "Some user friendly description of the key" + description: "User-friendly description of the key", memberships: [{role: "editor", variables: [{name: "language", values: ["cs"]}]}] ) { ok error { code } - result { + result { + apiKey { + id + token + identity { + id + } + } + } + } +} +``` + +This returns three identifiers: + +- **API Key ID**: Used for disabling this API key later. +- **Identity ID**: Used to modify the API key's memberships and permissions. +- **Token**: A bearer token used for authenticating your GraphQL requests. + + +## Create Global API Key + +```graphql +mutation { + createGlobalApiKey( + description: "Global API key description", + roles: ["super_admin", "monitor"] + ) { + ok + error { + code + } + result { apiKey { id token @@ -31,27 +66,54 @@ mutation { } ``` -This mutations returns 3 identifiers, which might be relevant for you: -- API key ID: using this ID you can later call a `disableApiKey` and invalidate this API key -- identity ID: which you use to modify API key [memberships and permissions](memberships.md) -- token: which is a bearer token, which you use to authenticate all GraphQL requests +This also returns three identifiers similar to creating a project-specific API key. -### Using CLI +### Custom Token Generation -There is also an interactive CLI command for creating an API key. Run +Both `createApiKey` and `createGlobalApiKey` support the optional `tokenHash` parameter. If you provide a SHA-256 hash of the token you wish to use, the API will not generate a new token, and the `token` field in the response will be empty. This allows you more control over token management but requires you to securely generate and store the original token yourself. + +## Add Global Roles to an Identity + +```graphql +mutation { + addGlobalIdentityRoles( + identityId: "some-identity-id", + roles: ["super_admin", "monitor"] + ) { + ok + error { + code + } + } +} ``` -npm run contember tenant:create-api-key -``` -and follow the instructions -## Disable API key +## Remove Global Roles from an Identity + +```graphql +mutation { + removeGlobalIdentityRoles( + identityId: "some-identity-id", + roles: ["monitor"] + ) { + ok + error { + code + } + } +} +``` -You need an API key ID to disable it. Do not confuse this id with identity id! + + +## Disable API Key ```graphql mutation { - disableApiKey(id: "fb6658f3-a000-4448-ac9e-0688f1afa3d7") { + disableApiKey(id: "some-api-key-id") { ok } } ``` + +Use the API Key ID to disable the API key. Do not confuse this with the Identity ID. From 9ebfd867618540c6f3ca86075075ff5b5596702a Mon Sep 17 00:00:00 2001 From: David Matejka Date: Thu, 31 Aug 2023 12:49:42 +0200 Subject: [PATCH 09/10] mail templates: add projectSlug --- docs/reference/engine/tenant/mail-templates.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/reference/engine/tenant/mail-templates.md b/docs/reference/engine/tenant/mail-templates.md index 8c29271a..4fe5a87f 100644 --- a/docs/reference/engine/tenant/mail-templates.md +++ b/docs/reference/engine/tenant/mail-templates.md @@ -86,14 +86,21 @@ Contember uses Mustache for dynamic content in templates. Here are the variables - `{{email}}`: Recipient's email. - `{{password}}`: Password (if available). - `{{token}}`: Token for account validation (if available). - - `{{project}}`: Project name or identifier. + - `{{project}}`: Project name. + - `{{projectSlug}}`: Project identifier. - availability of `password` and `token` variable depends on [invitation method](./invites.md#password-handling) - **EXISTING_USER_INVITED**: - `{{email}}`: Recipient's email. - - `{{project}}`: New project they've been invited to. + - `{{project}}`: New project's name they've been invited to. + - `{{projectSlug}}`: Project identifier. - **RESET_PASSWORD_REQUEST**: - `{{email}}`: Recipient's email. - `{{token}}`: Token for password reset. - - `{{project}}`: Project name or identifier (if relevant). + - `{{project}}`: Project name (if available). + - `{{projectSlug}}`: Project identifier (if available). + +:::note +`projectSlug` is available since Engine 1.3+ +::: From 5dcd6a883c6f91bb90782472cbafab487caead1f Mon Sep 17 00:00:00 2001 From: David Matejka Date: Thu, 31 Aug 2023 12:49:56 +0200 Subject: [PATCH 10/10] typo --- docs/reference/engine/tenant/api-keys.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/reference/engine/tenant/api-keys.md b/docs/reference/engine/tenant/api-keys.md index 22e37f0c..7f7eb6ae 100644 --- a/docs/reference/engine/tenant/api-keys.md +++ b/docs/reference/engine/tenant/api-keys.md @@ -2,8 +2,6 @@ title: API keys management --- -# API Keys Management - API keys serve as a way to authenticate applications where individual user identification and authentication are not required. They function as permanent access tokens. ## Create an API Key for a Project