server package

server.check_secrets(app)[source]
server.create_app(config_override={})[source]
server.populate_database()[source]

Initial commits to a new empty database.

server.run_server(config={}, server_kwargs={})[source]

Subpackages

Submodules

server.blacklist_helpers module

server.blacklist_helpers.add_token_to_database(encoded_token)[source]

Add a new token to the database. It is not revoked when it is added.

server.blacklist_helpers.get_user_tokens(user_identity)[source]

Return all tokens belonging to given user.

server.blacklist_helpers.prune_database()[source]

Delete all expired tokens from the database.

server.blacklist_helpers.revoke_all_tokens(user_identity)[source]

Revoke all tokens belonging to given user.

server.blacklist_helpers.revoke_token(token_id, user)[source]

Revoke token. If it does not exist in database, raise TokenNotFound.

server.blacklist_helpers.token_is_revoked(decoded_token)[source]

Check if token is revoked. If it does not exist in the database, consider it revoked.

server.blacklist_helpers.unrevoke_token(token_id, user)[source]

Unrevoke given token. Raise TokenNotFound if it does not exist in the database.

server.config module

server.exceptions module

exception server.exceptions.ItemMustHaveId[source]

Bases: PyplasError

exception server.exceptions.NonexistentDevice[source]

Bases: PyplasError

exception server.exceptions.NonexistentSid[source]

Bases: PyplasError

exception server.exceptions.PyplasError[source]

Bases: Exception

Base class for all exceptions

exception server.exceptions.TokenNotFound[source]

Bases: PyplasError

Token cannot be found in database.

exception server.exceptions.UniqueIdConflict[source]

Bases: PyplasError

server.functions module

server.functions.submit_device(name, password, ipv4, replace_device=None)[source]
server.functions.submit_experiment(name, devices, replace=None)[source]
server.functions.submit_session(name, begin, end, experiment, users, replace=None)[source]
server.functions.submit_user(username, password, role, email, replace_user=None)[source]
server.functions.submit_usergroup(name, users, description, style_json, replace=None)[source]

server.models module

class server.models.Device(**kwargs)[source]

Bases: Model

classmethod by_id(id_public)[source]

Find device by public id.

classmethod by_name(name)[source]

Find device by name.

check_password(password)[source]

Check hashed password.

id
id_public
ipv4
modify(**kwargs)[source]

Modify some or all modifiable properties.

name
password
set_password(password)[source]

Create hashed password.

to_dict()[source]

Return device as a dictionary (public id).

class server.models.Experiment(**kwargs)[source]

Bases: Model

classmethod by_id(id_public)[source]

Find experiment by public id.

classmethod by_name(name)[source]

Find device by name.

devices
id
id_public
modify(**kwargs)[source]

Modify some or all modifiable properties.

name
sessions
to_dict()[source]

Return experiment as a dictionary (public id).

class server.models.Session(**kwargs)[source]

Bases: Model

classmethod all_active(user=None, device=None)[source]

Get active sessions belonging to a user and/or device. If neither user nor device is specified, return all active sessions.

Parameters:
  • user – server.models.User or None

  • device – server.models.Device or None

Returns:

set of server.models.Session

begin
classmethod by_id(id_public)[source]

Find session by public id.

end
experiment
experiment_id
id
id_public
is_active()[source]
modify(**kwargs)[source]

Modify some or all modifiable properties.

name
to_dict()[source]

Return session as a dictionary (public id).

users
class server.models.Token(**kwargs)[source]

Bases: Model

expires
id
jti
revoked
to_dict()[source]

Return token as a dictionary (with private id).

token_type
user_identity
class server.models.User(**kwargs)[source]

Bases: Model

classmethod by_id(id_public)[source]

Find user by public id.

classmethod by_username(username)[source]

Find user by username.

check_password(password)[source]

Check hashed password.

email
get_active_sessions()[source]

Get all active session containing this user.

id
id_public
property is_admin
modify(**kwargs)[source]

Modify some or all modifiable properties.

password
role
sessions
set_password(password)[source]

Create hashed password.

to_dict()[source]

Return user as a dictionary (public id).

usergroups
username
class server.models.Usergroup(**kwargs)[source]

Bases: Model

classmethod by_id(id_public)[source]

Find usergroup by public id.

classmethod by_name(name)[source]

Find usergroup by name.

description
id
id_public
modify(**kwargs)[source]

Modify some or all modifiable properties.

name
style_json
to_dict()[source]

Return usergroup as a dictionary (public id).

users

server.protections module

This file contains protections that are used for routes in API.

server.protections.add_claims_to_access_token(identity)[source]
server.protections.admin_required(f)[source]

Decorator: accept when authenticated and role == admin.

server.protections.admin_required_sio(f)[source]

Event decorator: accept authenticated users with role admin.

server.protections.content_json(mandatory_keys)[source]

Endpoint decorator: Make sure content is application/json and json contains mandatory keys. Otherwise return with error status code.

server.protections.device_required_sio(f)[source]

Event decorator: accept authenticated devices. Corresponding Device object (queried from database) is passed as a first argument to the decorated func.

server.protections.user_authorized_for_device(device_id)[source]

Event security check: check if user, as the sender of request/event, belongs to an active session that can operate the device.

server.protections.user_required(f)[source]

Decorator: accept authenticated users.

server.protections.user_required_sio(f)[source]

Event decorator: accept authenticated users.

server.proxy_helpers module

server.proxy_helpers.real_remote_addr()[source]

Returns the real remote IP address. Uses BEHIND_PROXY config setting.

When the app is not behind a proxy (BEHIND_PROXY==None), the returned address is just request.remote_addr. Otherwise, the real address must be retrieved from a special header set by the proxy service.

server.serverlogging module

class server.serverlogging.SlackHandler(token, channel)[source]

Bases: Handler

Send messages or files to a Slack channel. To send a file, specify the path to the file as a file attribute:

slacklog.info(“Sending file”, extra={“file”: “path/to/file.txt”})

emit(record)[source]

Do whatever it takes to actually log the specified logging record.

This version is intended to be implemented by subclasses and so raises a NotImplementedError.

class server.serverlogging.TimedSummaryFilter(interval=10, levels=[20])[source]

Bases: Filter

This can deal with very frequent records from libraries like socketio.

  1. Start timer, intercept everything with specified level.
    • count identical records (identical: levelno & message & args)

    • let first through, drop any subsequent (i.e. infrequent records are not affected)

  2. Timer finishes, make a summary and log it.
    • log the counts (minus the first one) per each record entry

    • restart timer, continue with step 1.

filter(record)[source]

Determine if the specified record is to be logged.

Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.

log_summary()[source]
server.serverlogging.configure()[source]

Configure the loggers. Returns list of warnings that were encountered during the configuration (e.g. missing token for a Slack logger).