Skip to content

Commit

Permalink
Workspaces (#150)
Browse files Browse the repository at this point in the history
* add workspaces endpoint

* Add global_namespace() and server_type() methods

* black

* cache global namespace while checking server type

* black

* Add only_namespace parameter to projects_list

* switch to using /v1/user/profile for new servers

* remove unused method global_namespace

* use enum for ServerType and remove unused var

* rename global_namespace to global_workspace, fix blunder

* use new api for server_type and workspace services
  • Loading branch information
uclaros authored Jan 26, 2023
1 parent 499d531 commit 0f45468
Showing 1 changed file with 91 additions and 4 deletions.
95 changes: 91 additions & 4 deletions mergin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from datetime import datetime, timezone
import dateutil.parser
import ssl
from enum import Enum, auto
import re

from .common import ClientError, LoginError, InvalidProject
Expand All @@ -37,6 +38,13 @@ class TokenError(Exception):
pass


class ServerType(Enum):
OLD = auto() # Server is old and does not support workspaces
CE = auto() # Server is Community Edition
EE = auto() # Server is Enterprise Edition
SAAS = auto() # Server is SaaS


def decode_token_data(token):
token_prefix = "Bearer ."
if not token.startswith(token_prefix):
Expand Down Expand Up @@ -70,6 +78,7 @@ def __init__(self, url=None, auth_token=None, login=None, password=None, plugin_
self._auth_params = None
self._auth_session = None
self._user_info = None
self._server_type = None
self.client_version = "Python-client/" + __version__
if plugin_version is not None: # this could be e.g. "Plugin/2020.1 QGIS/3.14"
self.client_version += " " + plugin_version
Expand Down Expand Up @@ -310,6 +319,7 @@ def user_service(self):
Requests information about user from /user/service endpoint if such exists in self.url server.
Returns response from server as JSON dict or None if endpoint is not found
This can be removed once our SaaS server is upgraded to support workspaces
"""

try:
Expand All @@ -322,6 +332,58 @@ def user_service(self):

return response

def workspace_service(self, workspace_id):
"""
This Requests information about a workspace service from /workspace/{id}/service endpoint,
if such exists in self.url server.
Returns response from server as JSON dict or None if endpoint is not found
"""

try:
response = self.get(f"/v1/workspace/{workspace_id}/service")
except ClientError as e:
self.log.debug(f"Unable to query for /workspace/{workspace_id}/service endpoint")
return

response = json.loads(response.read())

return response

def server_type(self):
"""
Returns the deployment type of the server
The value is cached for self's lifetime
:returns: ServerType of server deployment
:rtype: ServerType
"""
if not self._server_type:
try:
resp = self.get("/config")
config = json.load(resp)
if config["server_type"] == "ce":
self._server_type = ServerType.CE
elif config["server_type"] == "ee":
self._server_type = ServerType.EE
elif config["server_type"] == "saas":
self._server_type = ServerType.SAAS
except (ClientError, KeyError):
self._server_type = ServerType.OLD

return self._server_type

def workspaces_list(self):
"""
Find all available workspaces
:rtype: List[Dict]
"""
resp = self.get("/v1/workspaces")
workspaces = json.load(resp)
return workspaces

def create_project(self, project_name, is_public=False, namespace=None):
"""
Create new project repository in user namespace on Mergin Maps server.
Expand Down Expand Up @@ -367,7 +429,16 @@ def create_project_and_push(self, project_name, directory, is_public=False, name
self.push_project(directory)

def paginated_projects_list(
self, page=1, per_page=50, tags=None, user=None, flag=None, name=None, namespace=None, order_params=None
self,
page=1,
per_page=50,
tags=None,
user=None,
flag=None,
name=None,
only_namespace=None,
namespace=None,
order_params=None,
):
"""
Find all available Mergin Maps projects.
Expand All @@ -384,6 +455,9 @@ def paginated_projects_list(
:param name: Filter projects with name like name
:type name: String
:param only_namespace: Filter projects with namespace exactly equal to namespace
:type namespace: String
:param namespace: Filter projects with namespace like namespace
:type namespace: String
Expand All @@ -409,7 +483,9 @@ def paginated_projects_list(
params["flag"] = flag
if name:
params["name"] = name
if namespace:
if only_namespace:
params["only_namespace"] = only_namespace
elif namespace:
params["namespace"] = namespace
params["page"] = page
params["per_page"] = per_page
Expand All @@ -419,7 +495,9 @@ def paginated_projects_list(
projects = json.load(resp)
return projects

def projects_list(self, tags=None, user=None, flag=None, name=None, namespace=None, order_params=None):
def projects_list(
self, tags=None, user=None, flag=None, name=None, only_namespace=None, namespace=None, order_params=None
):
"""
Find all available Mergin Maps projects.
Expand All @@ -437,6 +515,9 @@ def projects_list(self, tags=None, user=None, flag=None, name=None, namespace=No
:param name: Filter projects with name like name
:type name: String
:param only_namespace: Filter projects with namespace exactly equal to namespace
:type namespace: String
:param namespace: Filter projects with namespace like namespace
:type namespace: String
Expand All @@ -458,6 +539,7 @@ def projects_list(self, tags=None, user=None, flag=None, name=None, namespace=No
user=user,
flag=flag,
name=name,
only_namespace=only_namespace,
namespace=namespace,
order_params=order_params,
)
Expand Down Expand Up @@ -558,7 +640,11 @@ def enough_storage_available(self, data):
return True, free_space

def user_info(self):
resp = self.get("/v1/user/" + self.username())
server_type = self.server_type()
if server_type == ServerType.OLD:
resp = self.get("/v1/user/" + self.username())
else:
resp = self.get("/v1/user/profile")
return json.load(resp)

def set_project_access(self, project_path, access):
Expand Down Expand Up @@ -709,6 +795,7 @@ def project_status(self, directory):
project_path = mp.metadata["name"]
local_version = mp.metadata["version"]
server_info = self.project_info(project_path, since=local_version)

pull_changes = mp.get_pull_changes(server_info["files"])

push_changes = mp.get_push_changes()
Expand Down

0 comments on commit 0f45468

Please sign in to comment.