14.2.92. camcops_server.cc_modules.cc_user

camcops_server/cc_modules/cc_user.py


Copyright (C) 2012-2019 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/>.


CamCOPS users.

class camcops_server.cc_modules.cc_user.SecurityAccountLockout(**kwargs)[source]

Represents an account “lockout”.

A simple constructor that allows initialization from kwargs.

Sets attributes on the constructed instance using the names and values in kwargs.

Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.

classmethod delete_old_account_lockouts(req: CamcopsRequest) → None[source]

Delete all expired account lockouts.

classmethod is_user_locked_out(req: CamcopsRequest, username: str) → bool[source]

Is the specified user locked out?

Parameters:
classmethod lock_user_out(req: CamcopsRequest, username: str, lockout_minutes: int) → None[source]

Lock user out for a specified number of minutes.

Parameters:
classmethod unlock_user(req: CamcopsRequest, username: str) → None[source]

Unlock a user.

Parameters:
classmethod user_locked_out_until(req: CamcopsRequest, username: str) → Union[pendulum.datetime.DateTime, NoneType][source]

When is the user locked out until?

Parameters:
Returns:

Pendulum datetime in local timezone (or None if not locked out).

class camcops_server.cc_modules.cc_user.SecurityLoginFailure(**kwargs)[source]

Represents a record of a failed login.

Too many failed logins lead to a lockout; see SecurityAccountLockout.

A simple constructor that allows initialization from kwargs.

Sets attributes on the constructed instance using the names and values in kwargs.

Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.

classmethod act_on_login_failure(req: CamcopsRequest, username: str) → None[source]

Record login failure and lock out user if necessary.

Parameters:
classmethod clear_dummy_login_failures_if_necessary(req: CamcopsRequest) → None[source]

Clear dummy login failures if we haven’t done so for a while.

Not too often! See CLEAR_DUMMY_LOGIN_PERIOD.

Parameters:reqcamcops_server.cc_modules.cc_request.CamcopsRequest
classmethod clear_login_failures(req: CamcopsRequest, username: str) → None[source]

Clear login failures for a user.

Parameters:
classmethod clear_login_failures_for_nonexistent_users(req: CamcopsRequest) → None[source]

Clear login failures for nonexistent users.

Login failues are recorded for nonexistent users to mimic the lockout seen for real users, i.e. to reduce the potential for username discovery.

Parameters:reqcamcops_server.cc_modules.cc_request.CamcopsRequest
classmethod enable_user(req: CamcopsRequest, username: str) → None[source]

Unlock user and clear login failures.

Parameters:
classmethod how_many_login_failures(req: CamcopsRequest, username: str) → int[source]

How many times has the user tried and failed to log in (recently)?

Parameters:
classmethod record_login_failure(req: CamcopsRequest, username: str) → None[source]

Record that a user has failed to log in.

Parameters:
class camcops_server.cc_modules.cc_user.User(**kwargs)[source]

Class representing a user.

A simple constructor that allows initialization from kwargs.

Sets attributes on the constructed instance using the names and values in kwargs.

Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.

agree_terms(req: CamcopsRequest) → None[source]

Mark the user as having agreed to the terms/conditions of use now.

authorized_as_groupadmin

Is the user authorized as a group administrator for any group (either by being specifically set as a group administrator, or by being a superuser)?

authorized_for_reports

Is the user authorized to run reports (for some group)?

authorized_to_add_special_note(group_id: int) → bool[source]

Is this user authorized to add special notes for the group identified by group_id?

authorized_to_dump

Is the user authorized to dump data (for some group)?

authorized_to_erase_tasks(group_id: int) → bool[source]

Is this user authorized to add erase tasks for the group identified by group_id?

clear_login_failures(req: CamcopsRequest) → None[source]

Clear login failures.

classmethod create_superuser(req: CamcopsRequest, username: str, password: str) → bool[source]

Creates a superuser.

Will fail if the user already exists.

Parameters:
Returns:

success?

enable(req: CamcopsRequest) → None[source]

Re-enables the user, unlocking them and clearing login failures.

force_password_change() → None[source]

Make the user change their password at next login.

classmethod get_system_user(dbsession: sqlalchemy.orm.session.Session) → camcops_server.cc_modules.cc_user.User[source]

Returns a user representing “command-line access”.

classmethod get_user_by_id(dbsession: sqlalchemy.orm.session.Session, user_id: Union[int, NoneType]) → Union[_ForwardRef('User'), NoneType][source]

Returns a User from their integer ID, or None.

classmethod get_user_by_name(dbsession: sqlalchemy.orm.session.Session, username: str) → Union[_ForwardRef('User'), NoneType][source]

Returns a User from their username, or None.

classmethod get_user_from_username_password(req: CamcopsRequest, username: str, password: str, take_time_for_nonexistent_user: bool = True) → Union[_ForwardRef('User'), NoneType][source]

Retrieve a User object from the supplied username, if the password is correct; otherwise, return None.

Parameters:
  • reqcamcops_server.cc_modules.cc_request.CamcopsRequest
  • username – the username
  • password – the password attempt
  • take_time_for_nonexistent_user – if True (the default), then even if the user doesn’t exist, we take some time to mimic the time we spend doing deliberately wasteful password encryption (to prevent attackers from discovering real usernames via timing attacks).
classmethod get_username_from_id(req: CamcopsRequest, user_id: int) → Union[str, NoneType][source]

Looks up a user from their integer ID and returns their name, if found.

group_ids

Return a list of group IDs for all the groups that the user is a member of.

group_ids_that_nonsuperuser_may_see_when_unfiltered() → List[int][source]

Which group IDs may this user see all patients for, when unfiltered?

groups_user_is_admin_for

Returns a list of camcops_server.cc_modules.cc_group.Group objects for groups the user is an administrator for.

Less efficient than the group ID version; for visual display (see view_own_user_info.mako).

groups_user_may_add_special_notes

Returns a list of camcops_server.cc_modules.cc_group.Group objects for groups the user can add special notes to.

For visual display (see view_own_user_info.mako).

groups_user_may_dump

Returns a list of camcops_server.cc_modules.cc_group.Group objects for groups the user can dump.

For security notes, see ids_of_groups_user_may_dump().

Less efficient than the group ID version (see ids_of_groups_user_may_dump()). This version is for visual display (see view_own_user_info.mako).

groups_user_may_report_on

Returns a list of camcops_server.cc_modules.cc_group.Group objects for groups the user can report on.

For security notes, see ids_of_groups_user_may_report_on().

Less efficient than the group ID version (see ids_of_groups_user_may_report_on()). This version is for visual display (see view_own_user_info.mako).

groups_user_may_see

Returns a list of camcops_server.cc_modules.cc_group.Group objects for groups the user can see.

Less efficient than the group ID version; for visual display (see view_own_user_info.mako).

groups_user_may_see_all_pts_when_unfiltered

Returns a list of camcops_server.cc_modules.cc_group.Group objects for groups the user can see all patients when unfiltered.

For visual display (see view_own_user_info.mako).

groups_user_may_upload_into

Returns a list of camcops_server.cc_modules.cc_group.Group objects for groups the user can upload into.

For visual display (see view_own_user_info.mako).

ids_of_groups_user_is_admin_for

Returns a list of group IDs for groups that the user is an administrator for.

ids_of_groups_user_may_dump

Return a list of group IDs for groups that the user may dump data from.

See also groups_user_may_dump().

This does not give “second-hand authority” to dump. For example, if group G1 can “see” G2, and user U has authority to dump G1, that authority does not extend to G2.

ids_of_groups_user_may_report_on

Returns a list of group IDs for groups that the user may run reports on.

This does not give “second-hand authority” to dump. For example, if group G1 can “see” G2, and user U has authority to report on G1, that authority does not extend to G2.

ids_of_groups_user_may_see

Return a list of group IDs for groups that the user may see data from. (That means the groups the user is in, plus any other groups that the user’s groups are authorized to see.)

is_a_groupadmin

Is the user a specifically defined group administrator (for any group)?

is_locked_out(req: CamcopsRequest) → bool[source]

Is the user locked out because of multiple login failures?

is_password_valid(password: str) → bool[source]

Is the supplied password valid for this user?

static is_username_permissible(username: str) → bool[source]

Is this a permissible username?

locked_out_until(req: CamcopsRequest) → Union[pendulum.datetime.DateTime, NoneType][source]

When is the user locked out until?

Returns a Pendulum datetime in local timezone (or None if the user isn’t locked out).

login(req: CamcopsRequest) → None[source]

Called when the framework has determined a successful login.

Clears any login failures. Requires the user to change their password if policies say they should.

managed_users() → Union[sqlalchemy.orm.query.Query, NoneType][source]

Return a query for all users managed by this user.

LOGIC SHOULD MATCH may_edit_user().

may_administer_group(group_id: int) → bool[source]

May this user administer the group identified by group_id?

may_edit_user(req: CamcopsRequest, other: User) → Tuple[bool, str][source]

May the self user edit the other user?

Parameters:
Returns:

may_edit (bool), reason_why_not (str)

Return type:

tuple

LOGIC SHOULD MATCH managed_users().

may_login_as_tablet

May the user login via the client (tablet) API?

may_register_devices

May this user register devices?

You can register a device if your chosen upload groups allow you to do so. (You have to have a chosen group – even for superusers – because the tablet wants group ID policies at the moment of registration, so we have to know which group.)

may_upload

May this user upload to the group that is set as their upload group?

may_upload_to_group(group_id: int) → bool[source]

May this user upload to the specified group?

may_use_webviewer

May this user log in to the web front end?

may_view_all_patients_when_unfiltered

May the user view all patients when no filters are applied (for all groups that the user is a member of)?

may_view_no_patients_when_unfiltered

May the user view no patients when no filters are applied?

membership_for_group_id(group_id: int) → camcops_server.cc_modules.cc_membership.UserGroupMembership[source]

Returns the UserGroupMembership object relating this user to the group identified by group_id.

must_agree_terms

Does the user still need to agree the terms/conditions of use?

set_group_ids(group_ids: List[int]) → None[source]

Set the user’s groups to the groups whose integer IDs are in the group_ids list, and remove the user from any other groups.

set_password(req: CamcopsRequest, new_password: str) → None[source]

Set a user’s password.

set_password_change_flag_if_necessary(req: CamcopsRequest) → None[source]

If we’re requiring users to change their passwords, then check to see if they must do so now.

static take_some_time_mimicking_password_encryption() → None[source]

Waste some time. We use this when an attempt has been made to log in with a nonexistent user; we know the user doesn’t exist very quickly, but we mimic the time it takes to check a real user’s password.

classmethod user_exists(req: CamcopsRequest, username: str) → bool[source]

Does a user exist with this username?

class camcops_server.cc_modules.cc_user.UserTests(methodName='runTest')[source]

Unit tests.

Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name.

camcops_server.cc_modules.cc_user.set_password_directly(req: CamcopsRequest, username: str, password: str) → bool[source]

If the user exists, set its password. Returns Boolean success. Used from the command line.