From 332512644f0e23c92417edb0785788acf2d47b81 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Wed, 2 Oct 2024 13:54:16 +0200 Subject: [PATCH 01/31] add permissions outline --- docs/docs/user-guide/permissions.md | 106 ++++++++++++++++++++++++++++ docs/docs/user-guide/users.md | 103 +-------------------------- 2 files changed, 107 insertions(+), 102 deletions(-) create mode 100644 docs/docs/user-guide/permissions.md diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md new file mode 100644 index 0000000000..46d5ab990e --- /dev/null +++ b/docs/docs/user-guide/permissions.md @@ -0,0 +1,106 @@ +# Mathesar's Role-Based Permissions + +Mathesar uses PostgreSQL roles to manage permissions at the database, schema, and table levels. These roles define the actions users can perform, allowing fine-grained control over access. + +## Database Settings + +Mathesar provides three main sections for role management within the database settings: + +- **Role Configuration**: Used to manage credentials (passwords) for roles that exist on the server. These roles can then be assigned to collaborators. +- **Collaborators**: This section allows you to add users and assign them configured roles, dictating their access levels within the database. +- **Server Roles**: Here you can manage roles available on the server itself, defining inheritance, creating new roles, or deleting existing ones. + +> **Note:** Role Configuration is Mathesar-specific, managing credentials for existing roles within a connected database. Server Roles, however, exist on the PostgreSQL server itself and affect all databases. + +### Role Configuration + +In the **Role Configuration** section, all LOGIN roles that exist on the server are listed. These roles can then be assigned to collaborators once configured. A configured role has a password set. + +- **Password Management**: For each role, you can configure or change the password directly within Mathesar. +- **Remove Role Configuration**: Role configurations can be removed from the database as necessary. This only removes the credentials, not the role from the server. + +### Collaborators + +Collaborators are users who have been added to work on the database. Each collaborator is assigned a PostgreSQL LOGIN role that dictates their level of access to the database and its objects (schemas, tables, etc.). + +- **Add Collaborators**: In the **Collaborators** section, you can add new users as collaborators to the database. When adding a collaborator, you assign them one of the roles that have been configured in Mathesar. + +- **Remove Collaborators**: Collaborators can be removed if they no longer require access to the database. The Mathesar user will still exist and can be added back as a collaborator at a later time. + +### Server Roles + +The **Server Roles** section, found under the **Settings** tab, shows the roles available on the server for the current database. + +These roles will be displayed for all databases on the server. Also, any changes made to a server role will be reflected in all databases on the server. + +- **Create Roles**: New server-level roles can be created here. These roles can be configured in two ways: + 1. With login capability and a password, which can be assigned to collaborators. + 2. Without login capability, it is to be used as a parent role exclusively. These roles cannot be assigned to collaborators directly. +- **Define Child Roles**: For existing server-level roles, you can specify which other roles should be their child roles. This allows for creating hierarchies of roles where permissions can be inherited from parent to child roles. +- **Drop Roles**: Server-level roles that are no longer needed can be dropped. This action removes the role from the server and all databases where it has been assigned. Exercise caution when dropping roles, as it may affect existing permissions and user access across multiple databases. + +> **Note:** Server roles, once added, must be configured in Mathesar under the **Role Configuration** section before they can be assigned to collaborators. + +--- + +## Permissions Management at Different Levels + +Mathesar manages permissions at three levels: + +1. **Database** +2. **Schema** +3. **Table** + +Owners of each object (database, schema, or table) can set permissions for other users. Ownership is determined by the user's assigned collaborator role in the database. + +### Ownership of New Objects + +When a new object (database, schema, or table) is created, the owner of the object is the collaborator who created it. This automatic ownership assignment allows the creator to have immediate and full control over the objects they create, including the ability to manage permissions and transfer ownership if needed. + +You can find and manage permissions in the following sections: + +- **Database Permissions**: On the database settings page. +- **Schema Permissions**: On each schema's page. +- **Table Permissions**: In each table's inspector panel. + +### Database Permissions + +Database permissions control access and actions at the database level. + +- **Owner**: Each database has an owner who has full control over the database, including managing permissions and transferring ownership. +- **Granted Access**: Specific permissions can be granted to roles for various actions within the database. +- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them full administrative control. + +For each database, the following permission levels can be granted: + +- **Connect**: Allows the role to access and connect to the database. +- **Create**: Includes Connect permissions and allows the role to create new schemas within the database. +- **Custom**: Enables the granular setting of permissions beyond the predefined options. + +### Schema Permissions + +Schema permissions control access and actions at the schema level. + +- **Owner**: Each schema has an owner who has full control over the schema, including managing permissions and transferring ownership. +- **Granted Access**: Specific permissions can be granted to roles for various actions within the schema. +- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them full administrative control over the schema. + +For each schema, the following permission levels can be granted: + +- **Read**: Allows the role to access the schema and view its objects. +- **Create**: Includes Read permissions and allows the role to create new tables within the schema. +- **Custom**: Enables the granular setting of permissions beyond the predefined options. + +### Table Permissions + +Table permissions control access and actions at the table level. + +- **Owner**: Each table has an owner who has full control over the table, including managing permissions, transferring ownership, and modifying the table's structure (such as adding, removing, or altering columns). +- **Granted Access**: Specific permissions can be granted to roles for various actions on the table. +- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them full administrative control over the table. + +For each table, the following permission levels can be granted: + +- **Read**: Allows the role to access the table and read records. +- **Write**: Includes Read permissions and allows the role to insert, update, and delete records in the table. +- **Custom**: Enables the granular setting of permissions beyond the predefined options. diff --git a/docs/docs/user-guide/users.md b/docs/docs/user-guide/users.md index 7cef8d20f5..a3670df927 100644 --- a/docs/docs/user-guide/users.md +++ b/docs/docs/user-guide/users.md @@ -1,4 +1,4 @@ -# Users & Access Levels +# Users Mathesar allows you to set up users with different access levels. A user's access levels determine what they can do with the data managed in Mathesar. @@ -30,104 +30,3 @@ You cannot set granular permissions for an **Admin** user. ### Standard users By default, **Standard** users cannot see anything in Mathesar. They will need to be granted database or schema roles individually. - -## Database Roles - -There are three levels of database roles: - -- **Managers** own the database. They can edit all data in the database, as well as edit the structure of data (e.g. create tables, add and remove columns, etc.). They also manage access to the database. -- **Editors** can edit all data in the database, but cannot change the underlying data structures or manage access. -- **Viewers** have read-only access to all data in the database. They cannot make any changes. - -### Manager - -- Receives **Manager** permissions on all schemas in the database. -- Can view, add, and remove other users' access to the database. -- Can view, add, edit, and remove any schema in the database. -- Can view, add, edit, and remove any table in the database. -- Can view, add, edit, and remove any column in the database. -- Can view, add, edit, and remove any constraint in the database. -- Can view, add, edit, and remove any record in the database. -- Can view, add, edit, and remove any exploration in the database. -- Can perform "extract column" and "move column" actions - -### Editor - -- Receives **Editor** permissions on all schemas in the database. -- Can view any schema in the database. -- Can view any table in the database. -- Can view any column in the database. -- Can view any constraint in the database. -- Can view, add, edit, and remove any exploration in the database. -- Can view, add, edit, and remove any record in the database. - -### Viewer - -- Receives **Viewer** permissions on all schemas in the database. -- Can view any schema in the database. -- Can view any table in the database. -- Can view any column in the database. -- Can view any constraint in the database. -- Can view any exploration in the database. -- Can use the **Data Explorer** to create ad-hoc explorations using data in the database, but cannot save them. - -## Managing Database Roles - -!!! note - - Only **Admins** and **Database Managers** can manage access to a database. - -1. Click on the Mathesar logo on the top left of the application to go to the database page. -2. Click on the **Manage Access** button. - -## Schema Roles - -There are three levels of schema roles: - -- **Managers** own the schema. They can edit all data in the schema, as well as edit the structure of data (e.g. create tables, add and remove columns, etc.). They also manage access to the schema. -- **Editors** can edit all data in the schema, but cannot change the underlying data structures or manage access. -- **Viewers** have read-only access to all data in the schema. They cannot make any changes. - -### Manager - -- Can view, add, and remove other users' access to the schema. -- Can view, add, edit, and remove any schema in the schema. -- Can view, add, edit, and remove any table in the schema. -- Can view, add, edit, and remove any column in the schema. -- Can view, add, edit, and remove any constraint in the schema. -- Can view, add, edit, and remove any record in the schema. -- Can view, add, edit, and remove any exploration in the schema. -- Can perform "extract column" and "move column" actions - -### Editor - -- Can view any table in the schema. -- Can view any column in the schema. -- Can view any constraint in the schema. -- Can view, add, edit, and remove any record in the schema. -- Can view, add, edit, and remove any exploration in the schema. - -### Viewer - -- Can view any table in the schema. -- Can view any column in the schema. -- Can view any constraint in the schema. -- Can view any exploration in the schema. -- Can use the **Data Explorer** to create ad-hoc explorations using data in the schema, but cannot save them. - -## Managing Schema Roles - -!!! note - - Only **Admins**, **Database Managers**, and **Schema Managers** can manage access to a schema. - -1. Click on the Mathesar logo on the top left of the application to go to the database page. -2. Select the appropriate schema from the list to navigate to the schema's homepage. -3. Click on the **Manage Access** button. - -## Order of Precedence - -If a user has both a **Database Role** and a **Schema Role** for a schema within the same database, the **Schema Role** will only have an effect if it grants more permissions. - -Examples: - -- If a user is a **Database Manager** but has **Viewer** permissions on a given schema, the schema role has no effect. -- If a user is a **Database Editor** but has **Manager** permissions on a given schema, the schema role will take precedence. From 2e3b4c935c787913f3a03df36e879471ae84e82f Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Thu, 3 Oct 2024 17:46:14 +0200 Subject: [PATCH 02/31] fix structure --- docs/docs/user-guide/permissions.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index 46d5ab990e..a00369d836 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -47,22 +47,16 @@ These roles will be displayed for all databases on the server. Also, any changes Mathesar manages permissions at three levels: -1. **Database** -2. **Schema** -3. **Table** +1. **Database Level:** Manageable from the database page +2. **Schema Level:** Manageable from the schema page +3. **Table Level:** Manageable from the inspector panel for each table -Owners of each object (database, schema, or table) can set permissions for other users. Ownership is determined by the user's assigned collaborator role in the database. +### Ownership of Objects -### Ownership of New Objects +Owners of each object (database, schema, or table) can set permissions for other users. Ownership is determined by the user's assigned collaborator role in the database. When a new object (database, schema, or table) is created, the owner of the object is the collaborator who created it. This automatic ownership assignment allows the creator to have immediate and full control over the objects they create, including the ability to manage permissions and transfer ownership if needed. -You can find and manage permissions in the following sections: - -- **Database Permissions**: On the database settings page. -- **Schema Permissions**: On each schema's page. -- **Table Permissions**: In each table's inspector panel. - ### Database Permissions Database permissions control access and actions at the database level. From 4669c872ea7056b41c1373add307619551c380f4 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Thu, 3 Oct 2024 17:47:38 +0200 Subject: [PATCH 03/31] fix and add punctuation --- docs/docs/user-guide/permissions.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index a00369d836..d9c7679989 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -47,9 +47,9 @@ These roles will be displayed for all databases on the server. Also, any changes Mathesar manages permissions at three levels: -1. **Database Level:** Manageable from the database page -2. **Schema Level:** Manageable from the schema page -3. **Table Level:** Manageable from the inspector panel for each table +1. **Database Level:** Managed from the database page. +2. **Schema Level:** Managed from the schema page. +3. **Table Level:** Managed from the inspector panel for each table. ### Ownership of Objects From 9ed19a17621b7c16b33d8845a814e1b07de072d6 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Thu, 3 Oct 2024 17:56:17 +0200 Subject: [PATCH 04/31] use active voice --- docs/docs/user-guide/permissions.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index d9c7679989..f656cb8137 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -17,7 +17,7 @@ Mathesar provides three main sections for role management within the database se In the **Role Configuration** section, all LOGIN roles that exist on the server are listed. These roles can then be assigned to collaborators once configured. A configured role has a password set. - **Password Management**: For each role, you can configure or change the password directly within Mathesar. -- **Remove Role Configuration**: Role configurations can be removed from the database as necessary. This only removes the credentials, not the role from the server. +- **Remove Role Configuration**: You can remove role configurations from Mathesar as needed. This only removes the credentials, not the role from the server. ### Collaborators @@ -25,7 +25,7 @@ Collaborators are users who have been added to work on the database. Each collab - **Add Collaborators**: In the **Collaborators** section, you can add new users as collaborators to the database. When adding a collaborator, you assign them one of the roles that have been configured in Mathesar. -- **Remove Collaborators**: Collaborators can be removed if they no longer require access to the database. The Mathesar user will still exist and can be added back as a collaborator at a later time. +- **Remove Collaborators**: You can remove collaborators if they no longer require access to the database. The Mathesar user will still exist and you can add them back as a collaborator at a later time. ### Server Roles @@ -33,11 +33,11 @@ The **Server Roles** section, found under the **Settings** tab, shows the roles These roles will be displayed for all databases on the server. Also, any changes made to a server role will be reflected in all databases on the server. -- **Create Roles**: New server-level roles can be created here. These roles can be configured in two ways: - 1. With login capability and a password, which can be assigned to collaborators. - 2. Without login capability, it is to be used as a parent role exclusively. These roles cannot be assigned to collaborators directly. +- **Create Roles**: You can create new server-level roles from this section. You can configure these roles in two ways: + 1. With login capability and a password, which you can assign to collaborators. + 2. Without login capability, to be used as a parent role exclusively. You cannot assign these roles to collaborators directly. - **Define Child Roles**: For existing server-level roles, you can specify which other roles should be their child roles. This allows for creating hierarchies of roles where permissions can be inherited from parent to child roles. -- **Drop Roles**: Server-level roles that are no longer needed can be dropped. This action removes the role from the server and all databases where it has been assigned. Exercise caution when dropping roles, as it may affect existing permissions and user access across multiple databases. +- **Drop Roles**: You can drop server-level roles that are no longer needed. This action removes the role from the server and all databases where it has been assigned. Exercise caution when dropping roles, as it may affect existing permissions and user access across multiple databases. > **Note:** Server roles, once added, must be configured in Mathesar under the **Role Configuration** section before they can be assigned to collaborators. From 424421c7fed8f385e6c9747e7a150c553661a3e5 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 14:44:56 -0400 Subject: [PATCH 05/31] Update Users page title in nav --- docs/mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e2488e3424..4fe4dcd983 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -25,7 +25,7 @@ nav: - Introduction: user-guide/index.md - Importing data: user-guide/importing-data.md - Syncing database changes: user-guide/syncing-db.md - - Users & access levels: user-guide/users.md + - Users: user-guide/users.md - Glossary: user-guide/glossary.md - API: - REST: api/rest.md From e2d629edddc954fc5140799a2a559ad450636d23 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 14:45:16 -0400 Subject: [PATCH 06/31] Add Permissions page to nav --- docs/mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 4fe4dcd983..b6fd79956a 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -26,6 +26,7 @@ nav: - Importing data: user-guide/importing-data.md - Syncing database changes: user-guide/syncing-db.md - Users: user-guide/users.md + - Permissions: user-guide/permissions.md - Glossary: user-guide/glossary.md - API: - REST: api/rest.md From 2facda34e0028ad7910bc5fc042a51a0e43c98e6 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 14:46:49 -0400 Subject: [PATCH 07/31] Remove page on "Syncing database changes" --- docs/docs/index.md | 1 - docs/docs/user-guide/syncing-db.md | 7 ------- docs/mkdocs.yml | 2 -- 3 files changed, 10 deletions(-) delete mode 100644 docs/docs/user-guide/syncing-db.md diff --git a/docs/docs/index.md b/docs/docs/index.md index 9b77bf0621..6876a21f3a 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -51,7 +51,6 @@ You can self-host Mathesar by following one of the guides below: Mathesar should be pretty intuitive to use. More documentation is coming soon, but for now, we've written some documentation for some things that could be tricky. -- [Syncing database changes](./user-guide/syncing-db.md) if the database's structure is changed outside of Mathesar. - How to set up [users with different access levels](./user-guide/users.md) ## Contribute to Mathesar diff --git a/docs/docs/user-guide/syncing-db.md b/docs/docs/user-guide/syncing-db.md deleted file mode 100644 index e36f7bf89d..0000000000 --- a/docs/docs/user-guide/syncing-db.md +++ /dev/null @@ -1,7 +0,0 @@ -# Syncing Database Changes - -Mathesar is designed to be used in tandem with other database tools. This means that if you make changes to your database structure or data outside of Mathesar, those changes will be reflected in Mathesar's UI. - -If you make structural changes to the database outside Mathesar (e.g. using another tool to add a schema, table, or column), those changes will not be reflected in Mathesar until you manually sync them. You can sync them using the "Sync Database Changes" button in the database homepage. - -External changes to data (e.g. adding, editing, or deleting *records*) will be automatically reflected without clicking this button. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index b6fd79956a..b28ef23409 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -24,7 +24,6 @@ nav: - Using Mathesar: - Introduction: user-guide/index.md - Importing data: user-guide/importing-data.md - - Syncing database changes: user-guide/syncing-db.md - Users: user-guide/users.md - Permissions: user-guide/permissions.md - Glossary: user-guide/glossary.md @@ -48,7 +47,6 @@ plugins: redirect_maps: "installation-dc/ansible-setup.md": "installation/docker-compose/index.md" "product/intro.md": "user-guide/index.md" - "product/syncing-db.md": "user-guide/syncing-db.md" "product/users.md": "user-guide/users.md" "install/index.md": "index.md" "install/docker-compose/index.md": "installation/docker-compose/index.md" From d88deaeb6792cb24f2bcc312d93a696e45d949da Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 14:56:21 -0400 Subject: [PATCH 08/31] Improve flow towards user-focused docs --- docs/docs/index.md | 4 +--- docs/docs/user-guide/index.md | 5 +++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/docs/index.md b/docs/docs/index.md index 6876a21f3a..ea09a26144 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -49,9 +49,7 @@ You can self-host Mathesar by following one of the guides below: ## Use Mathesar -Mathesar should be pretty intuitive to use. More documentation is coming soon, but for now, we've written some documentation for some things that could be tricky. - -- How to set up [users with different access levels](./user-guide/users.md) +See our [Using Mathesar](user-guide/index.md) section for documentation on Mathesar's features. ## Contribute to Mathesar diff --git a/docs/docs/user-guide/index.md b/docs/docs/user-guide/index.md index 56e2e69edf..d82d5092a3 100644 --- a/docs/docs/user-guide/index.md +++ b/docs/docs/user-guide/index.md @@ -2,6 +2,7 @@ Welcome! At this point, we assume you've installed Mathesar successfully and have logged into the web UI. -If you've connected Mathesar to an existing database, you should see all your schemas once you log in, and you can work with them as you please. +If you've connected Mathesar to an existing database, you should see all your schemas and tables once you log in, and you can work with them as you please. -If you're starting from scratch, we recommend **creating a new schema**. +!!! tip "More..." + 👈 Browse the "Using Mathesar" navigation section to find more detailed documentation pages. From 2f92e0d6db3bf05ada4d7f1014276d4d2b81eed8 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 14:57:46 -0400 Subject: [PATCH 09/31] Fix indentation --- docs/docs/user-guide/permissions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index f656cb8137..92d5a6c792 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -34,8 +34,8 @@ The **Server Roles** section, found under the **Settings** tab, shows the roles These roles will be displayed for all databases on the server. Also, any changes made to a server role will be reflected in all databases on the server. - **Create Roles**: You can create new server-level roles from this section. You can configure these roles in two ways: - 1. With login capability and a password, which you can assign to collaborators. - 2. Without login capability, to be used as a parent role exclusively. You cannot assign these roles to collaborators directly. + 1. With login capability and a password, which you can assign to collaborators. + 2. Without login capability, to be used as a parent role exclusively. You cannot assign these roles to collaborators directly. - **Define Child Roles**: For existing server-level roles, you can specify which other roles should be their child roles. This allows for creating hierarchies of roles where permissions can be inherited from parent to child roles. - **Drop Roles**: You can drop server-level roles that are no longer needed. This action removes the role from the server and all databases where it has been assigned. Exercise caution when dropping roles, as it may affect existing permissions and user access across multiple databases. From 7c5da7558e510790ffad70a9668b1f16d032300c Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 15:39:50 -0400 Subject: [PATCH 10/31] Clean up RPC docs --- docs/docs/api/rpc.md | 355 +++++++++++++++++++++---------------------- 1 file changed, 177 insertions(+), 178 deletions(-) diff --git a/docs/docs/api/rpc.md b/docs/docs/api/rpc.md index 9f91c2f4b8..ab9021a2d8 100644 --- a/docs/docs/api/rpc.md +++ b/docs/docs/api/rpc.md @@ -2,16 +2,12 @@ Mathesar has an API available at `/api/rpc/v0/` which follows the [JSON-RPC](https://www.jsonrpc.org/specification) spec version 2.0. -## About +!!! caution "Not yet stable" + The RPC API is not yet stable and may change in the future. If you build logic that depends on this API, be mindful that it may change in the future without warning or notice. -### Status +## Usage -We are currently in the process of [transitioning](https://wiki.mathesar.org/projects/2024/architecture-transition/rpc/) our API architecture from a [RESTful](rest.md) API to this RPC-style API, and we hope to have all functionality available through the RPC API by Mathesar's beta release. - -!!! caution "Stability" - The RPC API is not yet stable and may change in the future, even after we've completed the transition to the RPC API architecture. If you build logic that depends on this API, be mindful that it may change in the future without warning or notice. - -### Usage +### Requests To use an RPC function: @@ -23,7 +19,7 @@ To use an RPC function: To call function `add_from_known_connection` from the `connections` section of this page, you'd send something like: - `POST /api/rpc/v0/` + `POST /api/rpc/v0/`b ```json { @@ -37,127 +33,63 @@ To use an RPC function: } ``` -## Collaborators - -::: collaborators - options: - members: - - list_ - - add - - delete - - set_role - - CollaboratorInfo - -## Connections - -::: connections - options: - members: - - add_from_known_connection - - add_from_scratch - - grant_access_to_user - - ConnectionReturn +### Responses -## Databases +#### Success -::: databases - options: - members: - - get - - delete - - DatabaseInfo +Upon a successful call to an RPC function, the API will return a success object. Such an object has the following form: -## Configured Databases +```json +{ + "jsonrpc": "2.0", + "id": 234, + "result": +} +``` -::: databases.configured - options: - members: - - list_ - - disconnect - - ConfiguredDatabaseInfo +The `result` is whatever was returned by the underlying function. -## Database Privileges +#### Errors -::: databases.privileges - options: - members: - - list_direct - - replace_for_roles - - transfer_ownership - - DBPrivileges +When an error is produced by a call to the RPC endpoint, we produce an error of the following form: -## Database Setup +```json +{ + "jsonrpc": "2.0", + "id": 234, + "error": { + "code": , + "message": + } +} +``` -::: databases.setup - options: - members: - - create_new - - connect_existing - - DatabaseConnectionResult +The `code` is a negative integer. Some codes are produced according to the [JSON-RPC spec](https://www.jsonrpc.org/specification#error_object). -## Schemas +Other error codes are grouped according to the library that produced the Exception: -::: schemas - options: - members: - - list_ - - get - - add - - delete - - patch - - SchemaInfo - - SchemaPatch +- `builtins`: -31xxx +- `psycopg` or `psycopg2`: -30xxx +- `django`: -29xxx +- `mathesar` (our code): -28xxx +- `db` (our code): -27xxx +- `sqlalchemy`: -26xxx +- other: -25xxx -## Schema Privileges +Unrecognized errors from a given library return a "round number" code, so an unknown `builtins` error gets the code -31000. -::: schemas.privileges - options: - members: - - list_direct - - replace_for_roles - - transfer_ownership - - SchemaPrivileges +--- -## Tables +## Collaborators -::: tables +::: collaborators options: members: - list_ - - get - add - delete - - patch - - import_ - - get_import_preview - - list_joinable - - list_with_metadata - - get_with_metadata - - TableInfo - - AddedTableInfo - - SettableTableInfo - - JoinableTableRecord - - JoinableTableInfo - -## Table Privileges - -::: tables.privileges - options: - members: - - list_direct - - replace_for_roles - - transfer_ownership - - TablePrivileges - -## Table Metadata - -::: tables.metadata - options: - members: - - list_ - - set_ - - TableMetaDataBlob - - TableMetaDataRecord + - set_role + - CollaboratorInfo ## Columns @@ -187,13 +119,25 @@ To use an RPC function: - ColumnMetaDataRecord - ColumnMetaDataBlob -## Types +## Configured Databases -::: types +::: databases.configured options: members: - list_ - - TypeInfo + - disconnect + - ConfiguredDatabaseInfo + + +## Connections + +::: connections + options: + members: + - add_from_known_connection + - add_from_scratch + - grant_access_to_user + - ConnectionReturn ## Constraints @@ -209,27 +153,46 @@ To use an RPC function: - UniqueConstraint - CreatableConstraintInfo -## Records +## Data Modeling -:::records +:::data_modeling + options: + members: + - add_foreign_key_column + - add_mapping_table + - suggest_types + - split_table + - move_columns + - MappingColumn + - SplitTableInfo + +## Databases + +::: databases options: members: - - list_ - get - - add - - patch - delete - - search - - RecordList - - RecordAdded - - OrderBy - - Filter - - FilterAttnum - - FilterLiteral - - Grouping - - Group - - GroupingResponse - - SearchParam + - DatabaseInfo + +## Database Privileges + +::: databases.privileges + options: + members: + - list_direct + - replace_for_roles + - transfer_ownership + - DBPrivileges + +## Database Setup + +::: databases.setup + options: + members: + - create_new + - connect_existing + - DatabaseConnectionResult ## Explorations @@ -247,6 +210,28 @@ To use an RPC function: - ExplorationDef - ExplorationResult +## Records + +:::records + options: + members: + - list_ + - get + - add + - patch + - delete + - search + - RecordList + - RecordAdded + - OrderBy + - Filter + - FilterAttnum + - FilterLiteral + - Grouping + - Group + - GroupingResponse + - SearchParam + ## Roles ::: roles @@ -260,7 +245,7 @@ To use an RPC function: - RoleInfo - RoleMember -## Configured Roles +## Roles Configured ::: roles.configured options: @@ -271,68 +256,82 @@ To use an RPC function: - set_password - ConfiguredRoleInfo -## Servers +## Schemas -::: servers +::: schemas options: members: - list_ - - ConfiguredServerInfo + - get + - add + - delete + - patch + - SchemaInfo + - SchemaPatch -## Data Modeling +## Schema Privileges -:::data_modeling +::: schemas.privileges options: members: - - add_foreign_key_column - - add_mapping_table - - suggest_types - - split_table - - move_columns - - MappingColumn - - SplitTableInfo - -## Responses - -### Success + - list_direct + - replace_for_roles + - transfer_ownership + - SchemaPrivileges -Upon a successful call to an RPC function, the API will return a success object. Such an object has the following form: +## Servers -```json -{ - "jsonrpc": "2.0", - "id": 234, - "result": -} -``` +::: servers + options: + members: + - list_ + - ConfiguredServerInfo -The `result` is whatever was returned by the underlying function. +## Tables -### Errors +::: tables + options: + members: + - list_ + - get + - add + - delete + - patch + - import_ + - get_import_preview + - list_joinable + - list_with_metadata + - get_with_metadata + - TableInfo + - AddedTableInfo + - SettableTableInfo + - JoinableTableRecord + - JoinableTableInfo -When an error is produced by a call to the RPC endpoint, we produce an error of the following form: +## Table Metadata -```json -{ - "jsonrpc": "2.0", - "id": 234, - "error": { - "code": , - "message": - } -} -``` +::: tables.metadata + options: + members: + - list_ + - set_ + - TableMetaDataBlob + - TableMetaDataRecord -The `code` is a negative integer. Some codes are produced according to the [JSON-RPC spec](https://www.jsonrpc.org/specification#error_object). +## Table Privileges -Other error codes are grouped according to the library that produced the Exception: +::: tables.privileges + options: + members: + - list_direct + - replace_for_roles + - transfer_ownership + - TablePrivileges -- `builtins`: -31xxx -- `psycopg` or `psycopg2`: -30xxx -- `django`: -29xxx -- `mathesar` (our code): -28xxx -- `db` (our code): -27xxx -- `sqlalchemy`: -26xxx -- other: -25xxx +## Types -Unrecognized errors from a given library return a "round number" code, so an unknown `builtins` error gets the code -31000. +::: types + options: + members: + - list_ + - TypeInfo From b3506faa03833d787f8ca4c9c298709fe7204cee Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 15:40:02 -0400 Subject: [PATCH 11/31] Add Databases page --- docs/docs/user-guide/databases.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/docs/user-guide/databases.md diff --git a/docs/docs/user-guide/databases.md b/docs/docs/user-guide/databases.md new file mode 100644 index 0000000000..d8695ea18d --- /dev/null +++ b/docs/docs/user-guide/databases.md @@ -0,0 +1,5 @@ +# Databases + +Each installation of Mathesar can connect to multiple Databases. + +TODO From dbbcfc4047d605daa0b62dc892f0b39dff13ec2a Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Thu, 3 Oct 2024 15:40:32 -0400 Subject: [PATCH 12/31] Re-order pages in nav --- docs/mkdocs.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index b28ef23409..bc61f19893 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -23,13 +23,14 @@ nav: - Debug Mathesar: administration/debug.md - Using Mathesar: - Introduction: user-guide/index.md - - Importing data: user-guide/importing-data.md + - Databases: user-guide/databases.md - Users: user-guide/users.md - Permissions: user-guide/permissions.md + - Importing data: user-guide/importing-data.md - Glossary: user-guide/glossary.md - API: - - REST: api/rest.md - RPC: api/rpc.md + - REST: api/rest.md - Releases: - '0.1.7': releases/0.1.7.md - '0.1.6': releases/0.1.6.md From dabefb9bfbd9bc2bfc2436d7cd4917a15f13f098 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Fri, 4 Oct 2024 07:00:10 -0400 Subject: [PATCH 13/31] Improve Users content --- docs/docs/user-guide/users.md | 54 ++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/docs/docs/user-guide/users.md b/docs/docs/user-guide/users.md index a3670df927..a813811dec 100644 --- a/docs/docs/user-guide/users.md +++ b/docs/docs/user-guide/users.md @@ -1,32 +1,52 @@ # Users -Mathesar allows you to set up users with different access levels. A user's access levels determine what they can do with the data managed in Mathesar. - -Mathesar's installation process includes setting up the first user. This user is an **Admin**. +Mathesar allows multiple users to collaborate on the same data using a [role-based permissioning](./permissions.md) system. ## Managing Users 1. Click on the gear icon on the top right of the application and select **Administration**. -2. In the left sidebar, click on **Users**. +1. In the left sidebar, click on **Users**. + +!!! info "Admin-assigned passwords" + Any user with an admin-assigned password (new or edited) will be prompted to change their password after logging in. + + +## Admin vs Standard users + +Each Mathesar user is either **Admin** or **Standard**. + +Admin users have the following capabilities which Standard users do not: + +- Admins can can manage other Mathesar users (view, add, edit, delete). +- Admins can add and remove [Databases](./databases.md). +- Admins can manage [Collaborators](./permissions.md#collaborators). This allows an Admin user to grant any Mathesar user access to a database through a PostgreSQL role that the Admin specifies. + +Upon installing Mathesar, your first user will be an Admin user. + +## Users vs Roles + +- A **"user"** is a Mathesar construct. Each Mathesar installation has multiple users. +- A **"role"** is a PostgreSQL construct ([docs](https://www.postgresql.org/docs/current/user-manag.html)). Each PostgreSQL server has multiple roles and multiple databases. -!!! note - - Only **Admins** can add new users. - - Mathesar does not send invitation emails to new users (yet). You'll need to send the user their username and password yourself. - - The user will be prompted to change the password when they log in for the first time. +!!! caution "Why this distinction is important" + Outside of Mathesar, it's not uncommon for people to say _user_ when referring to a PostgreSQL _role_. However, within the context of Mathesar users and roles are different things! Our documentation maintains this distinction pedantically. -## User Types +How users and roles work together: -Users can be either **Admin** or **Standard** users. +- To access a database, each Mathesar user must be assigned a PostgreSQL role to be used for that database. +- The user's permissions on anything _inside_ the database are determined by the corresponding role's permissions within PostgreSQL. -### Admin users + !!! info "Admin doesn't matter here" + The user's "admin" status with Mathesar _has no effect_ on the user's ability to do things within a database! It only affects operations outside the database. -Admin users: +- You can configure separate Mathesar users to share the same PostgreSQL role if you like. This is a good option if you want those users to have the same permissions on the data. +- Or you can use separate PostgreSQL roles for different users. This is necessary any time you want different users to have different permissions on the data. +- You cannot configure one Mathesar user with two PostgreSQL role simultaneously — though you can save multiple PostgreSQL roles in Mathesar and manually switch between them if necessary. -- can manage other users (view, add, edit, delete) -- have **Manager** permissions on all databases and schemas +See [Permissions](./permissions.md) for more information on managing roles. -You cannot set granular permissions for an **Admin** user. +## Limitations -### Standard users +- Mathesar does not send invitation emails to new users (yet). You'll need to send the user their username and password yourself. +- Nor is there yet an email-based password recovery mechanism. If you are locked out of your Mathesar installation's web interface, your system administrator can still [use the command line reset any user's password](https://stackoverflow.com/questions/6358030/how-to-reset-django-admin-password). -By default, **Standard** users cannot see anything in Mathesar. They will need to be granted database or schema roles individually. From aee4c2c09788cda1c637a76ee84d8313b0b73362 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Fri, 4 Oct 2024 07:02:09 -0400 Subject: [PATCH 14/31] Improve permissions content --- docs/docs/user-guide/permissions.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index 92d5a6c792..839a2ff3ce 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -1,6 +1,12 @@ # Mathesar's Role-Based Permissions -Mathesar uses PostgreSQL roles to manage permissions at the database, schema, and table levels. These roles define the actions users can perform, allowing fine-grained control over access. +Mathesar uses [PostgreSQL roles](https://www.postgresql.org/docs/current/user-manag.html) to manage permissions within a database. These roles define the actions users can perform, allowing fine-grained control over access. + +## Roles vs Users + +Each Mathesar user accesses a database through one PostgreSQL role — and the user's permissions are determined by the _role's_ permissions within PostgreSQL. + +You can read more about [how users and roles work together](./users.md#users-vs-roles). ## Database Settings @@ -10,18 +16,19 @@ Mathesar provides three main sections for role management within the database se - **Collaborators**: This section allows you to add users and assign them configured roles, dictating their access levels within the database. - **Server Roles**: Here you can manage roles available on the server itself, defining inheritance, creating new roles, or deleting existing ones. -> **Note:** Role Configuration is Mathesar-specific, managing credentials for existing roles within a connected database. Server Roles, however, exist on the PostgreSQL server itself and affect all databases. +!!! note + Role Configuration is Mathesar-specific, managing credentials for existing roles within a connected database. Server Roles, however, exist on the PostgreSQL server itself and affect all databases. ### Role Configuration -In the **Role Configuration** section, all LOGIN roles that exist on the server are listed. These roles can then be assigned to collaborators once configured. A configured role has a password set. +In the **Role Configuration** section, all [LOGIN roles](https://www.postgresql.org/docs/current/role-attributes.html#ROLE-ATTRIBUTES) that exist on the server are listed. These roles can then be assigned to collaborators once configured. A configured role has a password set. - **Password Management**: For each role, you can configure or change the password directly within Mathesar. - **Remove Role Configuration**: You can remove role configurations from Mathesar as needed. This only removes the credentials, not the role from the server. ### Collaborators -Collaborators are users who have been added to work on the database. Each collaborator is assigned a PostgreSQL LOGIN role that dictates their level of access to the database and its objects (schemas, tables, etc.). +Collaborators are users who have been added to work on a database. Each collaborator is assigned a PostgreSQL LOGIN role that dictates their level of access to the database and its objects (schemas, tables, etc.). - **Add Collaborators**: In the **Collaborators** section, you can add new users as collaborators to the database. When adding a collaborator, you assign them one of the roles that have been configured in Mathesar. @@ -36,10 +43,11 @@ These roles will be displayed for all databases on the server. Also, any changes - **Create Roles**: You can create new server-level roles from this section. You can configure these roles in two ways: 1. With login capability and a password, which you can assign to collaborators. 2. Without login capability, to be used as a parent role exclusively. You cannot assign these roles to collaborators directly. -- **Define Child Roles**: For existing server-level roles, you can specify which other roles should be their child roles. This allows for creating hierarchies of roles where permissions can be inherited from parent to child roles. +- **Define Child Roles**: PostgreSQL has a mechanism for [Role Membership](https://www.postgresql.org/docs/current/role-membership.html) wherein any role can be "granted" to any other role to form simple hierarchies or complex graph-based inheritance structures. For any role you've configured within Mathesar, you can use Mathesar to grant the role to other "child roles". - **Drop Roles**: You can drop server-level roles that are no longer needed. This action removes the role from the server and all databases where it has been assigned. Exercise caution when dropping roles, as it may affect existing permissions and user access across multiple databases. -> **Note:** Server roles, once added, must be configured in Mathesar under the **Role Configuration** section before they can be assigned to collaborators. +!!! note + Server roles, once added, must be configured in Mathesar under the **Role Configuration** section before they can be assigned to collaborators. --- From 992b5fae7748504fd795637989b8b25097543961 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Mon, 7 Oct 2024 09:24:15 +0200 Subject: [PATCH 15/31] add more detail to configurations --- docs/docs/user-guide/permissions.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index f656cb8137..97c548a8b2 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -6,11 +6,18 @@ Mathesar uses PostgreSQL roles to manage permissions at the database, schema, an Mathesar provides three main sections for role management within the database settings: +### In Mathesar + +These configurations specifically control how you interact with the database within the Mathesar interface. + - **Role Configuration**: Used to manage credentials (passwords) for roles that exist on the server. These roles can then be assigned to collaborators. - **Collaborators**: This section allows you to add users and assign them configured roles, dictating their access levels within the database. -- **Server Roles**: Here you can manage roles available on the server itself, defining inheritance, creating new roles, or deleting existing ones. -> **Note:** Role Configuration is Mathesar-specific, managing credentials for existing roles within a connected database. Server Roles, however, exist on the PostgreSQL server itself and affect all databases. +### On the Server + +These configurations affect the underlying PostgreSQL server where your database lives. Changes to these configurations will be reflected in all databases on the server. + +- **Roles**: Here you can manage roles available on the server, defining their inheritance, creating new roles, or deleting existing ones. ### Role Configuration From 3e70cd974d9a9147d4130c4662d436d75f624943 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Mon, 7 Oct 2024 09:29:23 +0200 Subject: [PATCH 16/31] clarify collaborators --- docs/docs/user-guide/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index 97c548a8b2..220c8537d5 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -11,7 +11,7 @@ Mathesar provides three main sections for role management within the database se These configurations specifically control how you interact with the database within the Mathesar interface. - **Role Configuration**: Used to manage credentials (passwords) for roles that exist on the server. These roles can then be assigned to collaborators. -- **Collaborators**: This section allows you to add users and assign them configured roles, dictating their access levels within the database. +- **Collaborators**: This section enables you to manage user access to the database. You can add existing Mathesar users as collaborators and assign them configured roles, which determine their specific access levels and permissions within the database. ### On the Server From 2125bc410a7c236c39f0386a97e5c81a6469c220 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Mon, 7 Oct 2024 11:44:43 +0200 Subject: [PATCH 17/31] update permissions documentation --- docs/docs/user-guide/permissions.md | 49 +++++++++++++++-------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index e9b6ad31e1..985d027533 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -21,36 +21,39 @@ These configurations specifically control how you interact with the database wit ### On the Server -These configurations affect the underlying PostgreSQL server where your database lives. Changes to these configurations will be reflected in all databases on the server. +These configurations affect the underlying PostgreSQL server where your database lives. - **Roles**: Here you can manage roles available on the server, defining their inheritance, creating new roles, or deleting existing ones. +!!! note + Changes to this configuration will be reflected in all databases on the server. + ### Role Configuration In the **Role Configuration** section, all [LOGIN roles](https://www.postgresql.org/docs/current/role-attributes.html#ROLE-ATTRIBUTES) that exist on the server are listed. These roles can then be assigned to collaborators once configured. A configured role has a password set. -- **Password Management**: For each role, you can configure or change the password directly within Mathesar. -- **Remove Role Configuration**: You can remove role configurations from Mathesar as needed. This only removes the credentials, not the role from the server. +- **Configure Password**: For each role, you can configure or change the password directly within Mathesar. +- **Remove Role**: You can remove role configurations from Mathesar as needed. This only removes the configured credentials (password), not the role from the server. ### Collaborators -Collaborators are users who have been added to work on a database. Each collaborator is assigned a PostgreSQL LOGIN role that dictates their level of access to the database and its objects (schemas, tables, etc.). +Collaborators are existing Mathesar users who have been added to work on a database. Each collaborator is assigned a PostgreSQL LOGIN role that dictates their level of access to the database and its objects (schemas, tables, etc.). -- **Add Collaborators**: In the **Collaborators** section, you can add new users as collaborators to the database. When adding a collaborator, you assign them one of the roles that have been configured in Mathesar. +- **Add Collaborators**: In the **Collaborators** section, you can add existing Mathesar users as collaborators to the database. When adding a collaborator, you assign them one of the roles that have been configured in Mathesar. -- **Remove Collaborators**: You can remove collaborators if they no longer require access to the database. The Mathesar user will still exist and you can add them back as a collaborator at a later time. +- **Remove Collaborator**: You can remove a collaborator if they no longer require access to the database. The Mathesar user will still exist, and you can add them back as a collaborator at a later time. ### Server Roles -The **Server Roles** section, found under the **Settings** tab, shows the roles available on the server for the current database. +The **Roles** section, found under the **Settings** tab, shows the roles available on the PostgreSQL server of the connected database. -These roles will be displayed for all databases on the server. Also, any changes made to a server role will be reflected in all databases on the server. +These roles are displayed for all databases on the server, and any changes made to a server role will be reflected across all databases on the server. - **Create Roles**: You can create new server-level roles from this section. You can configure these roles in two ways: 1. With login capability and a password, which you can assign to collaborators. - 2. Without login capability, to be used as a parent role exclusively. You cannot assign these roles to collaborators directly. + 2. Without login capability, to be used exclusively as a parent role to group permissions that can be inherited by other roles. You cannot assign these non-login roles to collaborators directly. - **Define Child Roles**: PostgreSQL has a mechanism for [Role Membership](https://www.postgresql.org/docs/current/role-membership.html) wherein any role can be "granted" to any other role to form simple hierarchies or complex graph-based inheritance structures. For any role you've configured within Mathesar, you can use Mathesar to grant the role to other "child roles". -- **Drop Roles**: You can drop server-level roles that are no longer needed. This action removes the role from the server and all databases where it has been assigned. Exercise caution when dropping roles, as it may affect existing permissions and user access across multiple databases. +- **Drop Roles**: You can drop server-level roles that are no longer needed. This action removes the role from the server, however if the role is configured in Mathesar, it will still be displayed. Exercise caution when dropping roles, as it may affect collaborators using the dropped role in Mathesar. !!! note Server roles, once added, must be configured in Mathesar under the **Role Configuration** section before they can be assigned to collaborators. @@ -59,25 +62,23 @@ These roles will be displayed for all databases on the server. Also, any changes ## Permissions Management at Different Levels -Mathesar manages permissions at three levels: +Mathesar provides an interface to manage permissions at different levels in the underlying PostgreSQL database: -1. **Database Level:** Managed from the database page. -2. **Schema Level:** Managed from the schema page. -3. **Table Level:** Managed from the inspector panel for each table. +1. **Database Level:** Accessible from the database page. +2. **Schema Level:** Accessible from the schema page. +3. **Table Level:** Accessible from the inspector panel for each table. ### Ownership of Objects -Owners of each object (database, schema, or table) can set permissions for other users. Ownership is determined by the user's assigned collaborator role in the database. - -When a new object (database, schema, or table) is created, the owner of the object is the collaborator who created it. This automatic ownership assignment allows the creator to have immediate and full control over the objects they create, including the ability to manage permissions and transfer ownership if needed. +When a new object (database, schema, or table) is created, the owner of the object is the configured role that the collaborator uses to create it. This automatic ownership assignment allows the role to have immediate and administrative control over the objects created under it, including the ability to manage permissions and transfer ownership if needed. ### Database Permissions Database permissions control access and actions at the database level. -- **Owner**: Each database has an owner who has full control over the database, including managing permissions and transferring ownership. +- **Owner**: Each database has an owner who has administrative control over the database itself, including managing database-level permissions and transferring ownership. Ownership does not automatically extend to the objects within the database (such as schemas and tables), which may have their own separate ownership and permission settings. - **Granted Access**: Specific permissions can be granted to roles for various actions within the database. -- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them full administrative control. +- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them administrative control. For each database, the following permission levels can be granted: @@ -89,9 +90,9 @@ For each database, the following permission levels can be granted: Schema permissions control access and actions at the schema level. -- **Owner**: Each schema has an owner who has full control over the schema, including managing permissions and transferring ownership. +- **Owner**: Each schema has an owner who has administrative control over the schema itself, including managing schema-level permissions and transferring ownership. Ownership does not automatically extend to the objects within the schema (such as tables), which may have their own separate ownership and permission settings. - **Granted Access**: Specific permissions can be granted to roles for various actions within the schema. -- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them full administrative control over the schema. +- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them administrative control over the schema. For each schema, the following permission levels can be granted: @@ -103,12 +104,14 @@ For each schema, the following permission levels can be granted: Table permissions control access and actions at the table level. -- **Owner**: Each table has an owner who has full control over the table, including managing permissions, transferring ownership, and modifying the table's structure (such as adding, removing, or altering columns). +- **Owner**: Each table has an owner who has administrative control over the table itself, including managing table-level permissions, transferring ownership, and modifying the table's structure (such as adding, removing, or altering columns). - **Granted Access**: Specific permissions can be granted to roles for various actions on the table. -- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them full administrative control over the table. +- **Transfer Ownership**: The current owner can transfer ownership to another role, granting them administrative control over the table. For each table, the following permission levels can be granted: - **Read**: Allows the role to access the table and read records. - **Write**: Includes Read permissions and allows the role to insert, update, and delete records in the table. - **Custom**: Enables the granular setting of permissions beyond the predefined options. + +You can read more on custom permissions and the specific privileges that can be granted on the [PostgreSQL GRANT documentation](https://www.postgresql.org/docs/current/sql-grant.html). From 03f9ba3f6f74f129f75bc61c6135cb78ab733a42 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Mon, 7 Oct 2024 13:02:49 +0200 Subject: [PATCH 18/31] Update label --- docs/docs/user-guide/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index 985d027533..0b0d178e9c 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -33,7 +33,7 @@ These configurations affect the underlying PostgreSQL server where your database In the **Role Configuration** section, all [LOGIN roles](https://www.postgresql.org/docs/current/role-attributes.html#ROLE-ATTRIBUTES) that exist on the server are listed. These roles can then be assigned to collaborators once configured. A configured role has a password set. - **Configure Password**: For each role, you can configure or change the password directly within Mathesar. -- **Remove Role**: You can remove role configurations from Mathesar as needed. This only removes the configured credentials (password), not the role from the server. +- **Remove**: You can remove role configurations from Mathesar as needed. This only removes the configured credentials (password), not the role from the server. ### Collaborators From 0425df7a3602c5ce798713bdcdd09cfaa4b5fbe5 Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Mon, 7 Oct 2024 13:07:22 +0200 Subject: [PATCH 19/31] update documentation link --- docs/docs/user-guide/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index 0b0d178e9c..a5bf47a7ff 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -114,4 +114,4 @@ For each table, the following permission levels can be granted: - **Write**: Includes Read permissions and allows the role to insert, update, and delete records in the table. - **Custom**: Enables the granular setting of permissions beyond the predefined options. -You can read more on custom permissions and the specific privileges that can be granted on the [PostgreSQL GRANT documentation](https://www.postgresql.org/docs/current/sql-grant.html). +You can read more about the specific privileges that can be granted in the [PostgreSQL documentation on Privileges](https://www.postgresql.org/docs/current/ddl-priv.html). From 491ec91b325848b8fdbf7cc5dfb2f66c9c7f7a3c Mon Sep 17 00:00:00 2001 From: Ghislaine Guerin Date: Mon, 7 Oct 2024 13:29:07 +0200 Subject: [PATCH 20/31] update users documentation --- docs/docs/user-guide/users.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/docs/user-guide/users.md b/docs/docs/user-guide/users.md index a813811dec..cf5c45eeed 100644 --- a/docs/docs/user-guide/users.md +++ b/docs/docs/user-guide/users.md @@ -10,7 +10,6 @@ Mathesar allows multiple users to collaborate on the same data using a [role-bas !!! info "Admin-assigned passwords" Any user with an admin-assigned password (new or edited) will be prompted to change their password after logging in. - ## Admin vs Standard users Each Mathesar user is either **Admin** or **Standard**. @@ -37,7 +36,7 @@ How users and roles work together: - The user's permissions on anything _inside_ the database are determined by the corresponding role's permissions within PostgreSQL. !!! info "Admin doesn't matter here" - The user's "admin" status with Mathesar _has no effect_ on the user's ability to do things within a database! It only affects operations outside the database. + The user's "admin" status with Mathesar _has no effect_ on the user's ability to do things within a database! It only affects operations outside the database. This includes configuring database roles and managing collaborators, even though those operations are presented within the Database section of the UI they are considered to be _outside_ the database. - You can configure separate Mathesar users to share the same PostgreSQL role if you like. This is a good option if you want those users to have the same permissions on the data. - Or you can use separate PostgreSQL roles for different users. This is necessary any time you want different users to have different permissions on the data. @@ -49,4 +48,3 @@ See [Permissions](./permissions.md) for more information on managing roles. - Mathesar does not send invitation emails to new users (yet). You'll need to send the user their username and password yourself. - Nor is there yet an email-based password recovery mechanism. If you are locked out of your Mathesar installation's web interface, your system administrator can still [use the command line reset any user's password](https://stackoverflow.com/questions/6358030/how-to-reset-django-admin-password). - From bffdb4bfa7cdd6fb7b714f4611e3b1c5e6310830 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Mon, 7 Oct 2024 09:56:35 -0400 Subject: [PATCH 21/31] Clarify language around admin status. --- docs/docs/user-guide/users.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/user-guide/users.md b/docs/docs/user-guide/users.md index cf5c45eeed..39d1f42330 100644 --- a/docs/docs/user-guide/users.md +++ b/docs/docs/user-guide/users.md @@ -33,10 +33,10 @@ Upon installing Mathesar, your first user will be an Admin user. How users and roles work together: - To access a database, each Mathesar user must be assigned a PostgreSQL role to be used for that database. -- The user's permissions on anything _inside_ the database are determined by the corresponding role's permissions within PostgreSQL. +- The user's permissions on actual data (in the [user database](./glossary.md#user-db)) are determined by the corresponding role's permissions within PostgreSQL. !!! info "Admin doesn't matter here" - The user's "admin" status with Mathesar _has no effect_ on the user's ability to do things within a database! It only affects operations outside the database. This includes configuring database roles and managing collaborators, even though those operations are presented within the Database section of the UI they are considered to be _outside_ the database. + The user's "admin" status with Mathesar _has no effect_ on the user's ability to do things with the _data_ in a database! The admin status only affects operations on Mathesar's [internal database](./glossary.md#internal-db) such as managing collaborators and their corresponding roles. - You can configure separate Mathesar users to share the same PostgreSQL role if you like. This is a good option if you want those users to have the same permissions on the data. - Or you can use separate PostgreSQL roles for different users. This is necessary any time you want different users to have different permissions on the data. From b2e805ef775bfa44f0a1ad2eb50c4ca5c15be63d Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Mon, 7 Oct 2024 12:54:49 -0400 Subject: [PATCH 22/31] Add more content to Databases page --- docs/docs/user-guide/databases.md | 32 +++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/docs/user-guide/databases.md b/docs/docs/user-guide/databases.md index d8695ea18d..f0068b88ae 100644 --- a/docs/docs/user-guide/databases.md +++ b/docs/docs/user-guide/databases.md @@ -1,5 +1,33 @@ # Databases -Each installation of Mathesar can connect to multiple Databases. +Each installation of Mathesar can connect to multiple PostgreSQL databases. Connecting your first database will likely be your first step in using Mathesar. + +## PostgreSQL servers + +Every PostgreSQL database lives within a PostgreSQL server. + +- **External servers:** Mathesar can connect to any Internet-exposed PostgreSQL server to access the databases within it. We'll refer to these PostgreSQL servers as "external servers". + +- The **Internal Server:** Most Mathesar installations have an internal PostgreSQL server which the Mathesar application controls and utilizes for storage of application-specific metadata. + + !!! info "Some Mathesar installations don't have an internal server" + It's possible (though not recommended) to configure Mathesar to store its internal metadata in SQLite, thereby circumventing the need for an internal server. + +## Creating a new database + +If you're starting your database from scratch with Mathesar you can either: + +- Use Mathesar to create a new database within Mathesar's internal server and connect to it. This is a good option to get up and running quickly, but it might require more work later should you decide to set up periodic backups or connect other tools to the same database. Also, this option won't be possible if Mathesar was installed without an internal server. + + _OR_ + +- Use another tool to create your database on an external server and then connect Mathesar to it. You can administer that external server yourself, or choose from a variety of hosted PostgreSQL solutions such as [Amazon RDS](https://aws.amazon.com/rds/postgresql/pricing/), [Google Cloud SQL](https://cloud.google.com/sql/postgresql), [Supabase](https://supabase.com/database), and others. + +## Connecting a database + +Click the **Connect Database** button from the home page of your Mathesar application and follow the prompts. + +Once you've connected a database, you can navigate to Mathesar's page for it where you can browse the database's schemas and configure various [permissions](./permissions.md) for it. + +Mathesar will remember the connection even after the application is shut down. Your Mathesar user will be added as a "collaborator" on the database (along with the PostgreSQL role you entered). And the password you entered for that role will be stored in Mathesar's internal database, encrypted using Mathesar's [SECRET_KEY](../configuration/env-variables.md#secret_key). -TODO From acd06b8fba0b368a19fb92615a15899df6cf7ed5 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Mon, 7 Oct 2024 14:35:39 -0400 Subject: [PATCH 23/31] Improve Permissions content --- docs/docs/user-guide/permissions.md | 76 ++++++++++++++++------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index a5bf47a7ff..8c3d4afcb4 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -1,6 +1,6 @@ # Mathesar's Role-Based Permissions -Mathesar uses [PostgreSQL roles](https://www.postgresql.org/docs/current/user-manag.html) to manage permissions within a database. These roles define the actions users can perform, allowing fine-grained control over access. +Mathesar uses [PostgreSQL roles](https://www.postgresql.org/docs/current/user-manag.html) to manage permissions on your data. These roles define the actions users can perform, allowing fine-grained control over access. ## Roles vs Users @@ -8,46 +8,41 @@ Each Mathesar user accesses a database through one PostgreSQL role — and the u You can read more about [how users and roles work together](./users.md#users-vs-roles). -## Database Settings +## The Database "Settings" tab {:#database_settings} -Mathesar provides three main sections for role management within the database settings: +Each database has its own page within Mathesar. And on that page you'll find a "Settings" tab where you can manage roles and collaborators. -### In Mathesar +### _In Mathesar:_ Role Configuration {:#role_configuration} -These configurations specifically control how you interact with the database within the Mathesar interface. +Use this section to manage the credentials (i.e. passwords) for roles that you'd like to assign to collaborators within Mathesar. Mathesar will display all [LOGIN roles](https://www.postgresql.org/docs/current/role-attributes.html#ROLE-ATTRIBUTES) that exist on the server. -- **Role Configuration**: Used to manage credentials (passwords) for roles that exist on the server. These roles can then be assigned to collaborators. -- **Collaborators**: This section enables you to manage user access to the database. You can add existing Mathesar users as collaborators and assign them configured roles, which determine their specific access levels and permissions within the database. +- Click **Configure in Mathesar** to store the role's password in Mathesar and allow the role to be associated with collaborators. -### On the Server +- Click **Configure Password** to update the password of an already configured role. -These configurations affect the underlying PostgreSQL server where your database lives. +- Click **Remove** to remove Mathesar's stored password for a role. The role will remain on the server. -- **Roles**: Here you can manage roles available on the server, defining their inheritance, creating new roles, or deleting existing ones. -!!! note - Changes to this configuration will be reflected in all databases on the server. - -### Role Configuration - -In the **Role Configuration** section, all [LOGIN roles](https://www.postgresql.org/docs/current/role-attributes.html#ROLE-ATTRIBUTES) that exist on the server are listed. These roles can then be assigned to collaborators once configured. A configured role has a password set. +### _In Mathesar:_ Collaborators {:#collaborators} -- **Configure Password**: For each role, you can configure or change the password directly within Mathesar. -- **Remove**: You can remove role configurations from Mathesar as needed. This only removes the configured credentials (password), not the role from the server. +A "collaborator" is a Mathesar users who has access to a database through a specific PostgreSQL sole. -### Collaborators +The Collaborators section allows you to add and remove collaborators and edit their corresponding PostgreSQL roles. -Collaborators are existing Mathesar users who have been added to work on a database. Each collaborator is assigned a PostgreSQL LOGIN role that dictates their level of access to the database and its objects (schemas, tables, etc.). +!!! tip "Keep in mind" -- **Add Collaborators**: In the **Collaborators** section, you can add existing Mathesar users as collaborators to the database. When adding a collaborator, you assign them one of the roles that have been configured in Mathesar. + - You'll only be able to choose roles that have been "configured" in the above section — roles for which Mathesar has passwords stored. -- **Remove Collaborator**: You can remove a collaborator if they no longer require access to the database. The Mathesar user will still exist, and you can add them back as a collaborator at a later time. + - Removing a collaborator revokes that user's access to the database _but_: -### Server Roles + - If the user is a Mathesar [admin](./users.md#admin-vs-standard-users), they'll be able to gain access again. + - The user will still remain in Mathesar, potentially with access to other Databases. + - The role (and it's corresponding password) will still remain configured in Mathesar. + - The role will still remain on the PostgreSQL server. -The **Roles** section, found under the **Settings** tab, shows the roles available on the PostgreSQL server of the connected database. +### _On the Server:_ Roles {:#roles} -These roles are displayed for all databases on the server, and any changes made to a server role will be reflected across all databases on the server. +Here you can manage roles available on the server, defining their inheritance, creating new roles, or deleting existing ones. Any changes here will be reflected for all connected databases which share this server. - **Create Roles**: You can create new server-level roles from this section. You can configure these roles in two ways: 1. With login capability and a password, which you can assign to collaborators. @@ -60,21 +55,32 @@ These roles are displayed for all databases on the server, and any changes made --- -## Permissions Management at Different Levels +## PostgreSQL objects {:#objects} + +In PostgreSQL, an "object" is a thing like: a database, a schema, a table, _(and some other things too, which we won't cover here)_. + +### Privileges and ownership + +- **Privileges:** Specific privileges on an object can be granted to specific roles. -Mathesar provides an interface to manage permissions at different levels in the underlying PostgreSQL database: + !!! example + A role can be granted the `CREATE` privilege on a schema. This allows the role to create new tables within the schema. -1. **Database Level:** Accessible from the database page. -2. **Schema Level:** Accessible from the schema page. -3. **Table Level:** Accessible from the inspector panel for each table. +- **Ownership**: Every PostgreSQL object has one and only one role said to be its "owner". The owner generally can do anything directly to the object, but not necessarily other objects contained within it. By default the owner is set to the role which created the object. -### Ownership of Objects +- **Shared ownership:** While PostgreSQL has a variety of granular privileges for different actions, there are still certain actions which remain restricted to object owners. For example only the owner of a table can add new columns to it. -When a new object (database, schema, or table) is created, the owner of the object is the configured role that the collaborator uses to create it. This automatic ownership assignment allows the role to have immediate and administrative control over the objects created under it, including the ability to manage permissions and transfer ownership if needed. + While this behavior may seem limiting, it's still possible configure multiple roles to effectively "own" a single object by leveraging PostgreSQL's powerful role inheritance functionality: + + 1. We can create a third role to directly own the object and act as a sort of proxy "group". (The group role doesn't need to be a `LOGIN` role and thus doesn't require a password to be configured.) + 1. Then we can grant _that group role_ to any other roles we'd like. + 1. Those granted roles will then have permission do things _as if they were the owner themselves_. + + You can use the Mathesar UI to configure an arrangement like the above, though it will require many steps. ### Database Permissions -Database permissions control access and actions at the database level. +The "Database Permissions" modal is accessible via a button at the top right of the database page and allows you to configure the owner and granted privileges for a database. - **Owner**: Each database has an owner who has administrative control over the database itself, including managing database-level permissions and transferring ownership. Ownership does not automatically extend to the objects within the database (such as schemas and tables), which may have their own separate ownership and permission settings. - **Granted Access**: Specific permissions can be granted to roles for various actions within the database. @@ -88,7 +94,7 @@ For each database, the following permission levels can be granted: ### Schema Permissions -Schema permissions control access and actions at the schema level. +The "Schema Permissions" modal is accessible via a button at the top right of the schema page and allows you to configure the owner and granted privileges for a schema. - **Owner**: Each schema has an owner who has administrative control over the schema itself, including managing schema-level permissions and transferring ownership. Ownership does not automatically extend to the objects within the schema (such as tables), which may have their own separate ownership and permission settings. - **Granted Access**: Specific permissions can be granted to roles for various actions within the schema. @@ -102,7 +108,7 @@ For each schema, the following permission levels can be granted: ### Table Permissions -Table permissions control access and actions at the table level. +The Table Permissions modal is accessible via a button from within the right-side inspector panel for each table and allows you to configure the owner and granted privileges for a table. - **Owner**: Each table has an owner who has administrative control over the table itself, including managing table-level permissions, transferring ownership, and modifying the table's structure (such as adding, removing, or altering columns). - **Granted Access**: Specific permissions can be granted to roles for various actions on the table. From 217889d95d5b045a4099af5bc099939de993affb Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Mon, 7 Oct 2024 15:57:49 -0400 Subject: [PATCH 24/31] Install compare-versions package --- mathesar_ui/package-lock.json | 6 ++++++ mathesar_ui/package.json | 1 + 2 files changed, 7 insertions(+) diff --git a/mathesar_ui/package-lock.json b/mathesar_ui/package-lock.json index cd79da17a9..11e3b932d8 100644 --- a/mathesar_ui/package-lock.json +++ b/mathesar_ui/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@fortawesome/free-solid-svg-icons": "^6.2.0", "@popperjs/core": "^2.11.6", + "compare-versions": "^6.1.1", "dayjs": "^1.11.5", "fast-diff": "^1.2.0", "flatpickr": "^4.6.13", @@ -2867,6 +2868,11 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", diff --git a/mathesar_ui/package.json b/mathesar_ui/package.json index e6ab0e021c..cd1dc272c5 100644 --- a/mathesar_ui/package.json +++ b/mathesar_ui/package.json @@ -53,6 +53,7 @@ "dependencies": { "@fortawesome/free-solid-svg-icons": "^6.2.0", "@popperjs/core": "^2.11.6", + "compare-versions": "^6.1.1", "dayjs": "^1.11.5", "fast-diff": "^1.2.0", "flatpickr": "^4.6.13", From 8211d3d15fbbcbaa16e4e6cc839c952d814a8b2d Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Mon, 7 Oct 2024 16:16:50 -0400 Subject: [PATCH 25/31] Compare versions using semver logic --- mathesar_ui/src/stores/releases.ts | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/mathesar_ui/src/stores/releases.ts b/mathesar_ui/src/stores/releases.ts index 7502290a67..f2ed065c43 100644 --- a/mathesar_ui/src/stores/releases.ts +++ b/mathesar_ui/src/stores/releases.ts @@ -1,3 +1,4 @@ +import { compare } from 'compare-versions'; import { getContext, setContext } from 'svelte'; import { @@ -31,20 +32,6 @@ function buildRelease(gh: GitHubRelease | undefined): Release | undefined { }; } -function orderableTag(tagName: string): number | undefined { - try { - const [major, minor, patch] = tagName - .split('.') - .map((s) => parseInt(s, 10)); - if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) { - return undefined; - } - return major * 1000000 + minor * 1000 + patch; - } catch (e) { - return undefined; - } -} - type UpgradeStatus = 'upgradable' | 'up-to-date'; function getUpgradeStatus( @@ -54,12 +41,9 @@ function getUpgradeStatus( if (current === undefined || latest === undefined) { return undefined; } - const currentNum = orderableTag(current.tagName); - const LatestNum = orderableTag(latest.tagName); - if (currentNum && LatestNum && LatestNum > currentNum) { - return 'upgradable'; - } - return 'up-to-date'; + return compare(latest.tagName, current.tagName, '>') + ? 'upgradable' + : 'up-to-date'; } export class ReleaseData { From 32a99d55a563bb206b2a39e6924129e65a8d8dab Mon Sep 17 00:00:00 2001 From: Pavish Kumar Ramani Gopal Date: Tue, 8 Oct 2024 17:41:52 +0530 Subject: [PATCH 26/31] Update docs/docs/user-guide/permissions.md --- docs/docs/user-guide/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index 8c3d4afcb4..e625a71e87 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -25,7 +25,7 @@ Use this section to manage the credentials (i.e. passwords) for roles that you'd ### _In Mathesar:_ Collaborators {:#collaborators} -A "collaborator" is a Mathesar users who has access to a database through a specific PostgreSQL sole. +A "collaborator" is a Mathesar user who has access to a database through a specific PostgreSQL role. The Collaborators section allows you to add and remove collaborators and edit their corresponding PostgreSQL roles. From e7fc8e142fc10b6995e169b977b524c5243748e8 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Tue, 8 Oct 2024 08:10:49 -0400 Subject: [PATCH 27/31] Use "child role" terminology --- docs/docs/user-guide/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/user-guide/permissions.md b/docs/docs/user-guide/permissions.md index e625a71e87..2a096f96ff 100644 --- a/docs/docs/user-guide/permissions.md +++ b/docs/docs/user-guide/permissions.md @@ -74,7 +74,7 @@ In PostgreSQL, an "object" is a thing like: a database, a schema, a table, _(and 1. We can create a third role to directly own the object and act as a sort of proxy "group". (The group role doesn't need to be a `LOGIN` role and thus doesn't require a password to be configured.) 1. Then we can grant _that group role_ to any other roles we'd like. - 1. Those granted roles will then have permission do things _as if they were the owner themselves_. + 1. Those child roles will then have permission do things _as if they were the owner themselves_. You can use the Mathesar UI to configure an arrangement like the above, though it will require many steps. From e60542aeee79d94eb677e749816c2c29adfd5e39 Mon Sep 17 00:00:00 2001 From: Anish Umale Date: Wed, 9 Oct 2024 02:35:18 +0530 Subject: [PATCH 28/31] fix response for explorations.run for summarizations --- mathesar/utils/explorations.py | 93 ++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/mathesar/utils/explorations.py b/mathesar/utils/explorations.py index 8035bcc163..621d1f18b8 100644 --- a/mathesar/utils/explorations.py +++ b/mathesar/utils/explorations.py @@ -3,7 +3,22 @@ from db.queries.base import DBQuery, InitialColumn, JoinParameter from db.queries.operations.process import get_transforms_with_summarizes_speced from db.tables.operations.select import get_table +from db.transforms.base import Summarize from db.transforms.operations.deserialize import deserialize_transformation +from db.functions.base import ( + Count, + ArrayAgg, + Sum, + Median, + Mode, + Percentage_True, + Max, + Min, + Mean, + PeakTime, + PeakMonth, +) +from db.functions.packed import DistinctArrayAgg from mathesar.api.utils import process_annotated_records from mathesar.models.base import Explorations, ColumnMetaData, Database from mathesar.rpc.columns.metadata import ColumnMetaDataRecord @@ -98,6 +113,11 @@ def run_exploration(exploration_def, conn, limit=100, offset=0): ) transformations = get_transforms_with_summarizes_speced(db_query, engine, metadata) db_query.transformations = transformations + exploration_def["transformations"] = [transformation.spec for transformation in transformations] + exploration_def["display_names"] = _get_default_display_names_for_summarize_transforms( + transformations, + exploration_def.get("display_names", {}) + ) records = db_query.get_records( limit=limit, offset=offset @@ -174,3 +194,76 @@ def _get_exploration_column_metadata( "input_alias": db_query.get_input_alias_for_output_alias(alias) } return exploration_column_metadata + + +def _get_default_display_names_for_summarize_transforms(transformations, current_display_names=dict()): + default_display_names = dict() + if not current_display_names: + return default_display_names + summarize_transforms = [ + db_transform + for db_transform in transformations + if isinstance(db_transform, Summarize) + ] + for summarize_transform in summarize_transforms: + # Find default display names for grouping output aliases + for output_alias in summarize_transform.grouping_output_aliases: + default_display_name = _get_default_display_name_for_group_output_alias( + summarize_transform, + output_alias, + current_display_names, + ) + if default_display_name: + default_display_names[output_alias] = default_display_name + # Find default display names for aggregation output aliases + for agg_col_spec in summarize_transform.aggregation_col_specs: + input_alias = agg_col_spec.get("input_alias") + output_alias = agg_col_spec.get("output_alias") + agg_function = agg_col_spec.get("function") + default_display_name = _get_default_display_name_for_agg_output_alias( + output_alias, + input_alias, + agg_function, + current_display_names, + ) + if default_display_name: + default_display_names[output_alias] = default_display_name + return default_display_names | current_display_names + + +def _get_default_display_name_for_agg_output_alias( + output_alias, + input_alias, + agg_function, + current_display_names, +): + if output_alias and input_alias and agg_function: + map_of_agg_function_to_suffix = { + DistinctArrayAgg.id: " distinct list", + ArrayAgg.id: " list", + Count.id: " count", + Sum.id: " sum", + Max.id: " max", + Median.id: " median", + Mode.id: " mode", + Percentage_True.id: " percentage true", + Min.id: " min", + Mean.id: " mean", + PeakTime.id: " peak_time", + PeakMonth.id: " peak_month", + } + suffix_to_add = map_of_agg_function_to_suffix.get(agg_function) + if suffix_to_add: + input_alias_display_name = current_display_names.get(input_alias) + if input_alias_display_name: + return input_alias_display_name + suffix_to_add + + +def _get_default_display_name_for_group_output_alias( + summarize_transform, + output_alias, + current_display_names, +): + input_alias = summarize_transform.map_of_output_alias_to_input_alias[output_alias] + input_alias_display_name = current_display_names.get(input_alias) + return input_alias_display_name From 9c5a11230b545117c5aa2ddc0508697ed606c4be Mon Sep 17 00:00:00 2001 From: Anish Umale Date: Wed, 9 Oct 2024 02:58:54 +0530 Subject: [PATCH 29/31] add a check --- mathesar/utils/explorations.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mathesar/utils/explorations.py b/mathesar/utils/explorations.py index 621d1f18b8..f3b288df07 100644 --- a/mathesar/utils/explorations.py +++ b/mathesar/utils/explorations.py @@ -113,7 +113,11 @@ def run_exploration(exploration_def, conn, limit=100, offset=0): ) transformations = get_transforms_with_summarizes_speced(db_query, engine, metadata) db_query.transformations = transformations - exploration_def["transformations"] = [transformation.spec for transformation in transformations] + if exploration_def.get("transformations") is not None: + exploration_def["transformations"] = [ + {"type": transformation.type, "spec": transformation.spec} + for transformation in transformations + ] exploration_def["display_names"] = _get_default_display_names_for_summarize_transforms( transformations, exploration_def.get("display_names", {}) From 6bf66a308b3efb79952d572d0e4f2748b0dc1183 Mon Sep 17 00:00:00 2001 From: Anish Umale Date: Thu, 10 Oct 2024 01:48:59 +0530 Subject: [PATCH 30/31] improvements for build from scrach docs --- .../installation/build-from-source/index.md | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/docs/installation/build-from-source/index.md b/docs/docs/installation/build-from-source/index.md index e28efe0bf7..2321ebfcf9 100644 --- a/docs/docs/installation/build-from-source/index.md +++ b/docs/docs/installation/build-from-source/index.md @@ -23,7 +23,7 @@ You should have **root access** to the machine you're installing Mathesar on. You'll need to install the following system packages before you install Mathesar: -- [Python](https://www.python.org/downloads/) 3.9, 3.10, or 3.11 +- [Python](https://www.python.org/downloads/) 3.9, 3.10, or 3.11 (along with appropriate [`venv`](https://docs.python.org/3/library/venv.html) module) !!! note "Python version" @@ -39,6 +39,8 @@ You'll need to install the following system packages before you install Mathesar - [GNU gettext](https://www.gnu.org/software/gettext/) (Verify with `gettext --version`) +- [unzip](https://packages.debian.org/search?keywords=unzip) A utility tool to de-archive .zip files (Verify with `unzip -v`) + ### Domain (optional) If you want Mathesar to be accessible over the internet, you'll probably want to set up a domain or sub-domain to use. **If you don't need a domain, you can skip this section.** @@ -177,23 +179,31 @@ Then press Enter to customize this guide with your domain name. Your `.env` file should look something like this ``` + SECRET_KEY='REPLACE_THIS_WITH_YOUR_RANDOMLY_GENERATED_VALUE' DOMAIN_NAME='xDOMAIN_NAMEx' ALLOWED_HOSTS='xDOMAIN_NAMEx' - SECRET_KEY='REPLACE_THIS_WITH_YOUR_RANDOMLY_GENERATED_VALUE' # REPLACE THIS! POSTGRES_DB=mathesar_django POSTGRES_USER=mathesar - POSTGRES_PASSWORD=mathesar1234 # Do not use this password! + POSTGRES_PASSWORD=REPLACE_THIS_WITH_APPROPRIATE_PASSWORD_FOR_THE_CHOSEN_POSTGRES_USER POSTGRES_HOST=localhost POSTGRES_PORT=5432 ``` !!! tip - You can generate a [SECRET_KEY variable](../../configuration/env-variables.md#secret_key) by running: + To generate a [`SECRET_KEY`](../../configuration/env-variables.md#secret_key) you can use this [browser-based generator](https://djecrety.ir/) or run this command on MacOS or Linux: ``` echo $(cat /dev/urandom | LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 50) ``` + !!! tip + If you want to host Mathesar on multiple domains/subdomains you can do so by adding multiple comma separated domain names to the following env variables without a whitespace: + + ``` + DOMAIN_NAME='xDOMAIN_NAMEx,xDOMAIN_NAMEx.example.org' + ALLOWED_HOSTS='xDOMAIN_NAMEx,xDOMAIN_NAMEx.example.org' + ``` + 1. Add the environment variables to the shell You need to `export` the environment variables listed in the `.env` file to your shell. The easiest way would be to run the below command. @@ -290,7 +300,7 @@ Then press Enter to customize this guide with your domain name. 1. Check the logs to verify if Gunicorn is running without any errors ``` - journalctl --priority=notice --unit=gunicorn.service + journalctl --unit=gunicorn.service ``` ### Set up the Caddy reverse proxy @@ -307,7 +317,7 @@ Then press Enter to customize this guide with your domain name. 2. Add the configuration details to the CaddyFile ``` - https://xDOMAIN_NAMEx { + $DOMAIN_NAME { log { output stdout } @@ -385,7 +395,7 @@ Then press Enter to customize this guide with your domain name. 1. Check the logs to verify if Caddy is running without any errors ``` - journalctl --priority=notice --unit=caddy.service + journalctl --unit=caddy.service ``` ### Set up your user account From 101818d467a7fdf63447c0ba32b760eb02d0a174 Mon Sep 17 00:00:00 2001 From: pavish Date: Thu, 10 Oct 2024 13:16:48 +0530 Subject: [PATCH 31/31] Fix 500s when rpc errors are thrown while rendering common data --- mathesar/urls.py | 12 +-- mathesar/views.py | 149 ++++++++++----------------- mathesar_ui/src/stores/schemas.ts | 13 ++- mathesar_ui/src/stores/tables.ts | 14 ++- mathesar_ui/src/utils/preloadData.ts | 17 ++- 5 files changed, 98 insertions(+), 107 deletions(-) diff --git a/mathesar/urls.py b/mathesar/urls.py index c8726b347c..17f821d555 100644 --- a/mathesar/urls.py +++ b/mathesar/urls.py @@ -54,18 +54,16 @@ path('administration/users/', views.admin_home, name='admin_users_home'), path('administration/users//', views.admin_home, name='admin_users_edit'), path('administration/update/', views.admin_home, name='admin_update'), - path('shares/tables//', views.shared_table, name='shared_table'), - path('shares/explorations//', views.shared_query, name='shared_query'), - path('databases/', views.databases, name='databases'), + path('databases/', views.databases_list_route, name='databases_list_route'), path('i18n/', include('django.conf.urls.i18n')), re_path( r'^db/(?P\d+)/schemas/(?P\d+)/', - views.schemas_home, - name='schema_home' + views.schema_route, + name='schema_route' ), re_path( r'^db/(?P\d+)/((schemas|settings)/)?', - views.schemas, - name='schemas' + views.database_route, + name='database_route' ), ] diff --git a/mathesar/views.py b/mathesar/views.py index 2a5e4b8f4c..84153c34dc 100644 --- a/mathesar/views.py +++ b/mathesar/views.py @@ -1,8 +1,11 @@ +from functools import wraps + from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import render, redirect from modernrpc.views import RPCEntryPoint +from modernrpc.exceptions import RPCException from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response @@ -12,15 +15,35 @@ from mathesar.rpc.schemas import list_ as schemas_list from mathesar.rpc.servers.configured import list_ as get_servers_list from mathesar.rpc.tables import list_with_metadata as tables_list -from mathesar.api.serializers.tables import TableSerializer -from mathesar.api.serializers.queries import QuerySerializer from mathesar.api.ui.serializers.users import UserSerializer -from mathesar.api.utils import is_valid_uuid_v4 -from mathesar.models.shares import SharedTable, SharedQuery from mathesar.state import reset_reflection from mathesar import __version__ +def get_database_list(request): + return databases_list(request=request) + + +def wrap_data_and_rpc_exceptions(f): + @wraps(f) + def safe_func(*args, **kwargs): + try: + return { + 'state': 'success', + 'data': f(*args, **kwargs) + } + except RPCException as exp: + return { + 'state': 'failure', + 'error': { + 'code': exp.code, + 'message': exp.message + } + } + return safe_func + + +@wrap_data_and_rpc_exceptions def get_schema_list(request, database_id): if database_id is not None: return schemas_list(request=request, database_id=database_id) @@ -28,10 +51,7 @@ def get_schema_list(request, database_id): return [] -def get_database_list(request): - return databases_list(request=request) - - +@wrap_data_and_rpc_exceptions def get_table_list(request, database_id, schema_oid): if database_id is not None and schema_oid is not None: return tables_list( @@ -76,74 +96,35 @@ def _get_internal_db_meta(): return {'type': 'sqlite'} -def _get_base_data_all_routes(request, database_id=None, schema_id=None): +def get_common_data(request, database_id=None, schema_oid=None): + databases = get_database_list(request) + database_id_int = int(database_id) if database_id else None + current_database = next((database for database in databases if database['id'] == database_id_int), None) + current_database_id = current_database['id'] if current_database else None + + schemas = get_schema_list(request, current_database_id) + schema_oid_int = int(schema_oid) if schema_oid else None + schemas_data = schemas['data'] if 'data' in schemas else [] + current_schema = next((schema for schema in schemas_data if schema['oid'] == schema_oid_int), None) + current_schema_oid = current_schema['oid'] if current_schema else None + return { - 'current_database': int(database_id) if database_id else None, - 'current_schema': int(schema_id) if schema_id else None, + 'current_database': current_database_id, + 'current_schema': current_schema_oid, 'current_release_tag_name': __version__, - 'databases': get_database_list(request), - 'servers': get_servers_list(), + 'databases': databases, 'internal_db': _get_internal_db_meta(), 'is_authenticated': not request.user.is_anonymous, - 'queries': [], - 'schemas': get_schema_list(request, database_id), + 'servers': get_servers_list(), + 'schemas': schemas, 'supported_languages': dict(getattr(settings, 'LANGUAGES', [])), - 'tables': [], - 'user': get_user_data(request) - } - - -def get_common_data(request, database_id=None, schema_id=None): - return { - **_get_base_data_all_routes(request, database_id, schema_id), - 'tables': get_table_list(request, database_id, schema_id), - 'queries': get_queries_list(request, database_id, schema_id), + 'tables': get_table_list(request, current_database_id, current_schema_oid), + 'user': get_user_data(request), + 'queries': get_queries_list(request, current_database_id, current_schema_oid), 'routing_context': 'normal', } -def get_common_data_for_shared_entity(request, schema=None): - # TODO: Provide only authorized schemas & databases - # database = schema.database if schema else None - # schemas = [schema] if schema else [] - # databases = [database] if database else [] - return { - # **_get_base_data_all_routes(request, database, schema), - # 'schemas': serialized_schemas, - # 'databases': serialized_databases, - **_get_base_data_all_routes(request), - 'routing_context': 'anonymous', - } - - -def get_common_data_for_shared_table(request, table): - tables = [table] if table else [] - serialized_tables = TableSerializer( - tables, - many=True, - context={'request': request} - ).data - schema = table.schema if table else None - return { - **get_common_data_for_shared_entity(request, schema), - 'tables': serialized_tables, - } - - -def get_common_data_for_shared_query(request, query): - queries = [query] if query else [] - serialized_queries = QuerySerializer( - queries, - many=True, - context={'request': request} - ).data - schema = query.base_table.schema if query else None - return { - **get_common_data_for_shared_entity(request, schema), - 'queries': serialized_queries, - } - - class MathesarRPCEntryPoint(LoginRequiredMixin, RPCEntryPoint): pass @@ -160,10 +141,10 @@ def home(request): database_list = get_database_list(request) number_of_databases = len(database_list) if number_of_databases > 1: - return redirect('databases') + return redirect('databases_list_route') elif number_of_databases == 1: db = database_list[0] - return redirect('schemas', database_id=db['id']) + return redirect('database_route', database_id=db['id']) else: return render(request, 'mathesar/index.html', { 'common_data': get_common_data(request) @@ -171,7 +152,7 @@ def home(request): @login_required -def databases(request): +def databases_list_route(request): return render(request, 'mathesar/index.html', { 'common_data': get_common_data(request) }) @@ -192,43 +173,19 @@ def admin_home(request, **kwargs): @login_required -def schemas(request, database_id, **kwargs): +def database_route(request, database_id, **kwargs): return render(request, 'mathesar/index.html', { 'common_data': get_common_data(request, database_id, None) }) @login_required -def schemas_home(request, database_id, schema_id, **kwargs): +def schema_route(request, database_id, schema_id, **kwargs): return render(request, 'mathesar/index.html', { 'common_data': get_common_data(request, database_id, schema_id) }) -def shared_table(request, slug): - shared_table_link = SharedTable.get_by_slug(slug) if is_valid_uuid_v4(slug) else None - table = shared_table_link.table if shared_table_link else None - - return render(request, 'mathesar/index.html', { - 'common_data': get_common_data_for_shared_table(request, table), - 'route_specific_data': { - 'shared_table': {'table_id': table.id if table else None} - } - }) - - -def shared_query(request, slug): - shared_query_link = SharedQuery.get_by_slug(slug) if is_valid_uuid_v4(slug) else None - query = shared_query_link.query if shared_query_link else None - - return render(request, 'mathesar/index.html', { - 'common_data': get_common_data_for_shared_query(request, query), - 'route_specific_data': { - 'shared_query': {'query_id': query.id if query else None} - } - }) - - def page_not_found_view(request, exception): return render(request, 'mathesar/index.html', { 'common_data': get_common_data(request), diff --git a/mathesar_ui/src/stores/schemas.ts b/mathesar_ui/src/stores/schemas.ts index 493ff7e5da..a3a231a1c9 100644 --- a/mathesar_ui/src/stores/schemas.ts +++ b/mathesar_ui/src/stores/schemas.ts @@ -152,7 +152,18 @@ export const schemas = collapse( const $schemasStore = get(schemasStore); if ($schemasStore.databaseId !== $currentDatabase?.id) { if (preload && commonData.current_database === $currentDatabase?.id) { - setSchemasInStore($currentDatabase, commonData.schemas); + if (commonData.schemas.state === 'success') { + setSchemasInStore($currentDatabase, commonData.schemas.data); + } else { + schemasStore.set({ + databaseId: $currentDatabase.id, + requestStatus: { + state: 'failure', + errors: [getErrorMessage(commonData.schemas.error)], + }, + data: new Map(), + }); + } } else { void fetchSchemasForCurrentDatabase(); } diff --git a/mathesar_ui/src/stores/tables.ts b/mathesar_ui/src/stores/tables.ts index d6022cd06e..3b7104340f 100644 --- a/mathesar_ui/src/stores/tables.ts +++ b/mathesar_ui/src/stores/tables.ts @@ -395,7 +395,19 @@ export const currentTablesData = collapse( commonData.current_schema === $currentSchema?.oid && commonData.current_database === $currentSchema?.database.id ) { - setTablesStore($currentSchema, commonData.tables); + if (commonData.tables.state === 'success') { + setTablesStore($currentSchema, commonData.tables.data); + } else { + tablesStore.set({ + databaseId: $currentSchema.database.id, + schemaOid: $currentSchema.oid, + tablesMap: new Map(), + requestStatus: { + state: 'failure', + errors: [getErrorMessage(commonData.tables.error)], + }, + }); + } } else { void fetchTablesForCurrentSchema(); } diff --git a/mathesar_ui/src/utils/preloadData.ts b/mathesar_ui/src/utils/preloadData.ts index c44f0d00c1..f80c22a766 100644 --- a/mathesar_ui/src/utils/preloadData.ts +++ b/mathesar_ui/src/utils/preloadData.ts @@ -5,11 +5,24 @@ import type { RawSchema } from '@mathesar/api/rpc/schemas'; import type { RawServer } from '@mathesar/api/rpc/servers'; import type { RawTableWithMetadata } from '@mathesar/api/rpc/tables'; +type WithStatus = + | { + state: 'success'; + data: D; + } + | { + state: 'failure'; + error: { + code: number; + message: string; + }; + }; + export interface CommonData { databases: RawDatabase[]; servers: RawServer[]; - schemas: RawSchema[]; - tables: RawTableWithMetadata[]; + schemas: WithStatus; + tables: WithStatus; queries: SavedExploration[]; current_database: RawDatabase['id'] | null; internal_db: {