Source code for camcops_server.cc_modules.cc_client_api_core
#!/usr/bin/env python
# camcops_server/cc_modules/cc_client_api_core.py
"""
===============================================================================
Copyright (C) 2012-2018 Rudolf Cardinal (rudolf@pobox.com).
This file is part of CamCOPS.
CamCOPS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CamCOPS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CamCOPS. If not, see <http://www.gnu.org/licenses/>.
===============================================================================
"""
from typing import Any, Dict, List
# =============================================================================
# Constants
# =============================================================================
[docs]class TabletParam(object):
"""
Keys used by server or client (S server, C client, B bidirectional)
"""
CAMCOPS_VERSION = "camcops_version" # C->S
DATABASE_TITLE = "databaseTitle" # S->C
DATEVALUES = "datevalues" # C->S
DEVICE = "device" # C->S
DEVICE_FRIENDLY_NAME = "devicefriendlyname" # C->S
ERROR = "error" # S->C
FIELDS = "fields" # B
ID_DESCRIPTION_PREFIX = "idDescription" # S->C
ID_POLICY_FINALIZE = "idPolicyFinalize" # S->C
ID_POLICY_UPLOAD = "idPolicyUpload" # S->C
ID_SHORT_DESCRIPTION_PREFIX = "idShortDescription" # S->C
NFIELDS = "nfields" # B
NRECORDS = "nrecords" # B
OPERATION = "operation" # C->S
PASSWORD = "password" # C->S
PKNAME = "pkname" # C->S
PKVALUES = "pkvalues" # C->S
RECORD_PREFIX = "record" # B
RESULT = "result" # S->C
SERVER_CAMCOPS_VERSION = "serverCamcopsVersion" # S->C
SESSION_ID = "session_id" # B
SESSION_TOKEN = "session_token" # B
SUCCESS = "success" # S->C
TABLE = "table" # C->S
TABLES = "tables" # C->S
USER = "user" # C->S
VALUES = "values" # C->S
# Retired (part of defunct mobileweb interface):
# WHEREFIELDS = "wherefields"
# WHERENOTFIELDS = "wherenotfields"
# WHERENOTVALUES = "wherenotvalues"
# WHEREVALUES = "wherevalues"
[docs]class AllowedTablesFieldNames(object):
"""
To match allowedservertable.cpp on the tablet
"""
TABLENAME = "tablename"
MIN_CLIENT_VERSION = "min_client_version"
# =============================================================================
# Exceptions used by client API
# =============================================================================
# Note the following about exception strings:
#
# class Blah(Exception):
# pass
#
# x = Blah("hello")
# str(x) # 'hello'
[docs]class UserErrorException(Exception):
"""
Exception class for when the input from the tablet is dodgy.
"""
pass
[docs]class ServerErrorException(Exception):
"""
Exception class for when something's broken on the server side.
"""
pass
[docs]class IgnoringAntiqueTableException(Exception):
"""
Special exception to return success when we're ignoring an old tablet's
request to upload the "storedvars" table.
"""
pass
# =============================================================================
# Return message functions
# =============================================================================
def exception_description(e: Exception) -> str:
return "{t}: {m}".format(t=type(e).__name__, m=str(e))
# NO LONGER USED:
# def succeed_generic(operation: str) -> str:
# """
# Generic success message to tablet.
# """
# return "CamCOPS: {}".format(operation)
[docs]def fail_user_error(msg: str) -> None:
"""
Function to abort the script when the input is dodgy.
"""
# While Titanium-Android can extract error messages from e.g.
# finish("400 Bad Request: @_"), Titanium-iOS can't, and we need the error
# messages. Therefore, we will return an HTTP success code but "Success: 0"
# in the reply details.
raise UserErrorException(msg)
def require_keys(dictionary: Dict[Any, Any], keys: List[Any]) -> None:
for k in keys:
if k not in dictionary:
fail_user_error("Field {} missing in client input".format(repr(k)))
def fail_user_error_from_exception(e: Exception) -> None:
fail_user_error(exception_description(e))
[docs]def fail_server_error(msg: str) -> None:
"""
Function to abort the script when something's broken server-side.
"""
raise ServerErrorException(msg)
def fail_server_error_from_exception(e: Exception) -> None:
fail_server_error(exception_description(e))
[docs]def fail_unsupported_operation(operation: str) -> None:
"""
Abort the script when the operation is invalid.
"""
fail_user_error("operation={}: not supported".format(operation))