Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endpoints for Servers, Collaborators #3684

Merged
merged 8 commits into from
Jul 16, 2024
2 changes: 2 additions & 0 deletions config/settings/common_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def pipe_delim(pipe_string):
ROOT_URLCONF = "config.urls"

MODERNRPC_METHODS_MODULES = [
'mathesar.rpc.collaborators',
'mathesar.rpc.connections',
'mathesar.rpc.constraints',
'mathesar.rpc.columns',
Expand All @@ -73,6 +74,7 @@ def pipe_delim(pipe_string):
'mathesar.rpc.databases',
'mathesar.rpc.roles',
'mathesar.rpc.schemas',
'mathesar.rpc.servers',
'mathesar.rpc.tables',
'mathesar.rpc.tables.metadata',
'mathesar.rpc.types'
Expand Down
19 changes: 19 additions & 0 deletions docs/docs/api/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ To use an RPC function:
}
```

## Collaborators

::: collaborators
options:
members:
- list_
- add
- delete
- set_role
- CollaboratorInfo

## Connections

::: connections
Expand Down Expand Up @@ -161,6 +172,14 @@ To use an RPC function:
- RoleInfo
- RoleMember

## Servers

::: servers
options:
members:
- list_
- ServerInfo

## Responses

### Success
Expand Down
123 changes: 123 additions & 0 deletions mathesar/rpc/collaborators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
from typing import TypedDict

from modernrpc.core import rpc_method
from modernrpc.auth.basic import http_basic_auth_login_required, http_basic_auth_superuser_required

from mathesar.models.base import UserDatabaseRoleMap, Database, Role
from mathesar.models.users import User
from mathesar.rpc.exceptions.handlers import handle_rpc_exceptions


class CollaboratorInfo(TypedDict):
"""
Information about a collaborator.

Attributes:
id: the Django ID of the UserDatabaseRoleMap model instance.
user_id: The Django ID of the User model instance of the collaborator.
database_id: the Django ID of the Database model instance for the collaborator.
role_id: The Django ID of the Role model instance for the collaborator.
"""
id: int
user_id: int
database_id: int
role_id: int

@classmethod
def from_model(cls, model):
return cls(
id=model.id,
user_id=model.user.id,
database_id=model.database.id,
role_id=model.role.id
)


@rpc_method(name="collaborators.list")
@http_basic_auth_login_required
@handle_rpc_exceptions
def list_(*, database_id: int = None, **kwargs) -> list[CollaboratorInfo]:
"""
List information about collaborators. Exposed as `list`.

If called with no `database_id`, all collaborators for all databases are listed.

Args:
database_id: The Django id of the database associated with the collaborators.

Returns:
A list of collaborators.
"""
if database_id is not None:
user_database_role_map_qs = UserDatabaseRoleMap.objects.filter(database__id=database_id)
else:
user_database_role_map_qs = UserDatabaseRoleMap.objects.all()

return [CollaboratorInfo.from_model(db_model) for db_model in user_database_role_map_qs]


@rpc_method(name='collaborators.add')
@http_basic_auth_superuser_required
@handle_rpc_exceptions
def add(
*,
database_id: int,
user_id: int,
role_id: int,
**kwargs
) -> CollaboratorInfo:
"""
Set up a new collaborator for a database.

Args:
database_id: The Django id of the Database to associate with the collaborator.
user_id: The Django id of the User who'd be the collaborator.
role_id: The Django id of the Role to associate with the collaborator.
"""
database = Database.objects.get(id=database_id)
user = User.objects.get(id=user_id)
role = Role.objects.get(id=role_id)
collaborator = UserDatabaseRoleMap.objects.create(
database=database,
user=user,
role=role,
server=role.server
)
return CollaboratorInfo.from_model(collaborator)


@rpc_method(name='collaborators.delete')
@http_basic_auth_superuser_required
@handle_rpc_exceptions
def delete(*, collaborator_id: int, **kwargs):
"""
Delete a collaborator from a database.

Args:
collaborator_id: The Django id of the UserDatabaseRoleMap model instance of the collaborator.
"""
collaborator = UserDatabaseRoleMap.objects.get(id=collaborator_id)
collaborator.delete()


@rpc_method(name='collaborators.set_role')
@http_basic_auth_superuser_required
@handle_rpc_exceptions
def set_role(
*,
collaborator_id: int,
role_id: int,
**kwargs
) -> CollaboratorInfo:
"""
Set the role of a collaborator for a database.

Args:
collaborator_id: The Django id of the UserDatabaseRoleMap model instance of the collaborator.
role_id: The Django id of the Role to associate with the collaborator.
"""
collaborator = UserDatabaseRoleMap.objects.get(id=collaborator_id)
role = Role.objects.get(id=role_id)
collaborator.role = role
collaborator.save()
return CollaboratorInfo.from_model(collaborator)
44 changes: 44 additions & 0 deletions mathesar/rpc/servers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from typing import TypedDict

from modernrpc.core import rpc_method
from modernrpc.auth.basic import http_basic_auth_login_required

from mathesar.models.base import Server
from mathesar.rpc.exceptions.handlers import handle_rpc_exceptions


class ServerInfo(TypedDict):
"""
Information about a database server.

Attributes:
id: the Django ID of the server model instance.
host: The host of the database server.
port: the port of the database server.
"""
id: int
host: str
port: int

@classmethod
def from_model(cls, model):
return cls(
id=model.id,
host=model.host,
port=model.port
)


@rpc_method(name="servers.list")
@http_basic_auth_login_required
@handle_rpc_exceptions
def list_() -> list[ServerInfo]:
"""
List information about servers. Exposed as `list`.

Returns:
A list of server details.
"""
server_qs = Server.objects.all()

return [ServerInfo.from_model(db_model) for db_model in server_qs]
28 changes: 28 additions & 0 deletions mathesar/tests/rpc/test_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,39 @@
import pytest
from modernrpc.auth import user_is_authenticated, user_is_superuser

from mathesar.rpc import collaborators
from mathesar.rpc import columns
from mathesar.rpc import connections
from mathesar.rpc import constraints
from mathesar.rpc import database_setup
from mathesar.rpc import databases
from mathesar.rpc import roles
from mathesar.rpc import schemas
from mathesar.rpc import servers
from mathesar.rpc import tables
from mathesar.rpc import types

METHODS = [
(
collaborators.add,
"collaborators.add",
[user_is_superuser]
),
(
collaborators.delete,
"collaborators.delete",
[user_is_superuser]
),
(
collaborators.list_,
"collaborators.list",
[user_is_authenticated]
),
(
collaborators.set_role,
"collaborators.set_role",
[user_is_superuser]
),
(
columns.delete,
"columns.delete",
Expand Down Expand Up @@ -120,6 +142,12 @@
[user_is_authenticated]
),
(
servers.list_,
"servers.list",
[user_is_authenticated]
),
(

types.list_,
"types.list",
[user_is_authenticated]
Expand Down
Loading