models.py

This module contains the User model and other models for storing login attempts, a list of old hashed passwords, password change request and temporarily storages of the (hashed) login sms code.

An user is coupled to one of the 4 different possible roles in Remote Care:
  • Patient
  • Healthprofessional
  • Secretary
  • Manager

Via the polymorphicmodel: apps.healthperson.models.HealthPerson as can be seen in the next model relationship diagram:

digraph model_graph {
	graph [bb="7.1054e-15,0,816,297",
		fontname=Helvetica,
		fontsize=8,
		splines=true
	];
	node [fontname=Helvetica,
		fontsize=8,
		label="\N",
		shape=plaintext
	];
	edge [fontname=Helvetica,
		fontsize=8
	];
	core_models_AuditBaseModel	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    AuditBaseModel
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="367,18",
		width=1.6389];
	apps_account_models_EncryptionKey	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    EncryptionKey
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="56,18",
		width=1.5556];
	apps_account_models_User	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    User<BR/>&lt;<FONT FACE="Helvetica Italic">AbstractBaseUser,PermissionsMixin,AuditBaseModel</FONT>&gt;
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="202,108",
		width=3.1944];
	apps_account_models_User -> core_models_AuditBaseModel	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="abstract\ninheritance",
		lp="311,63",
		pos="e,327.95,36.027 229.23,89.765 246.64,79.007 269.83,65.137 291,54 299.87,49.333 309.48,44.639 318.79,40.272"];
	apps_account_models_User -> apps_account_models_EncryptionKey	 [arrowhead=none,
		arrowtail=none,
		dir=both,
		label="personal_encryption_key (user)",
		lp="141.5,63",
		pos="116.25,89.969 105.02,85.346 94.229,79.469 85,72 73.586,62.762 65.983,47.777 61.436,36.094"];
	apps_healthperson_models_HealthPerson	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    HealthPerson<BR/>&lt;<FONT FACE="Helvetica Italic">PolymorphicModel</FONT>&gt;
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="634,18",
		width=1.5278];
	apps_account_models_User -> apps_healthperson_models_HealthPerson	 [arrowhead=none,
		arrowtail=none,
		dir=both,
		label="healthperson (user)",
		lp="454.5,63",
		pos="266.27,89.904 309.3,78.804 367.31,64.502 419,54 473.11,43.006 535.43,33.168 579,26.743"];
	_	 [height=0.5,
		pos="202,18",
		width=0.75];
	apps_account_models_User -> _	 [pos="e,191.07,36.05 190.99,89.614 188.32,77.24 187.8,60.369 189.41,46.22"];
	apps_account_models_User -> _	 [pos="e,202,36.05 202,89.614 202,77.24 202,60.369 202,46.22"];
	apps_account_models_User -> _	 [pos="e,212.93,36.05 213.01,89.614 215.68,77.24 216.2,60.369 214.59,46.22"];
	apps_healthperson_models_HealthPerson -> apps_healthperson_models_HealthPerson	 [arrowhead=none,
		arrowtail=dot,
		dir=both,
		label="added_by (healthperson)",
		lp="752.5,18",
		pos="s,689.07,25.855 697.11,24.664 703.16,23.31 707,21.088 707,18 707,13.703 699.57,11.085 689.07,10.145"];
	apps_healthperson_healthprofessional_models_HealthProfessional	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    HealthProfessional<BR/>&lt;<FONT FACE="Helvetica Italic">AuditBaseModel</FONT>&gt;
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="433,198",
		width=1.6667];
	apps_healthperson_healthprofessional_models_HealthProfessional -> core_models_AuditBaseModel	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="abstract\ninheritance",
		lp="426,108",
		pos="e,373.31,36.016 426.67,179.93 415.14,148.83 390.63,82.735 376.88,45.652"];
	apps_healthperson_healthprofessional_models_HealthProfessional -> apps_healthperson_models_HealthPerson	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="multi-table\ninheritance",
		lp="663,108",
		pos="e,638.17,36.115 493.07,193.45 541.12,189.26 603.15,180.39 620,162 648.61,130.77 645.43,78.053 640.04,46.096"];
	apps_healthperson_healthprofessional_models_HealthProfessional -> apps_healthperson_healthprofessional_models_HealthProfessional	 [arrowhead=none,
		arrowtail=dot,
		dir=both,
		label="out_of_office_replacement (replacement_set)",
		lp="592.5,198",
		pos="s,493.18,205.03 501.19,203.91 507.22,202.66 511,200.7 511,198 511,194.25 503.69,191.91 493.18,190.97"];
	apps_healthperson_secretariat_models_Secretary	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    Secretary<BR/>&lt;<FONT FACE="Helvetica Italic">AuditBaseModel</FONT>&gt;
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="516,108",
		width=1.4167];
	apps_healthperson_healthprofessional_models_HealthProfessional -> apps_healthperson_secretariat_models_Secretary	 [arrowhead=none,
		arrowtail=dot,
		dir=both,
		label="urgent_control_secretary (healthprofessional)",
		lp="538.5,153",
		pos="s,437.84,179.73 440.68,172.02 444.49,162.48 449.84,152 457,144 463.28,136.99 471.3,130.97 479.39,126.01"];
	apps_healthperson_secretariat_models_Secretary -> core_models_AuditBaseModel	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="abstract\ninheritance",
		lp="526,63",
		pos="e,426.05,24.05 512.98,89.901 510.06,78.215 504.46,63.23 494,54 477.94,39.823 456.63,31.335 436.06,26.271"];
	apps_healthperson_secretariat_models_Secretary -> apps_healthperson_models_HealthPerson	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="multi-table\ninheritance",
		lp="600,63",
		pos="e,606.39,36.02 536.28,89.77 551.62,76.82 571.45,60.276 580,54 585.63,49.868 591.72,45.669 597.73,41.68"];
	apps_healthperson_patient_models_Patient	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    Patient<BR/>&lt;<FONT FACE="Helvetica Italic">AuditBaseModel</FONT>&gt;
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="433,279",
		width=1.4167];
	apps_healthperson_patient_models_Patient -> core_models_AuditBaseModel	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="abstract\ninheritance",
		lp="370,153",
		pos="e,362.15,36.03 404.44,260.87 389.38,250.09 372.33,234.68 364,216 338.93,159.77 350.6,85.22 359.73,45.912"];
	apps_healthperson_patient_models_Patient -> apps_healthperson_models_HealthPerson	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="multi-table\ninheritance",
		lp="725,153",
		pos="e,651.81,36.086 484.24,272.47 549.87,264.23 658.14,246.36 683,216 718.49,172.65 704.66,143.17 687,90 681.31,72.876 669.71,56.537 \
658.81,43.86"];
	apps_healthperson_patient_models_Patient -> apps_healthperson_healthprofessional_models_HealthProfessional	 [arrowhead=none,
		arrowtail=dot,
		dir=both,
		label="current_practitioner (patient)",
		lp="484.5,238.5",
		pos="s,433,260.86 433,252.6 433,240.67 433,226.76 433,216.11"];
	apps_healthperson_management_models_Manager	 [height=0.5,
		label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    Manager
    </FONT></TD></TR>
  
    </TABLE>
    >,
		pos="773,108",
		width=1.1944];
	apps_healthperson_management_models_Manager -> apps_healthperson_models_HealthPerson	 [arrowhead=empty,
		arrowtail=none,
		dir=both,
		label="multi-table\ninheritance",
		lp="757,63",
		pos="e,681.83,36.128 757.33,89.582 746.53,78.345 731.41,64.013 716,54 708.28,48.983 699.72,44.408 691.13,40.34"];
}

All personal user data is stored encrypted and, if searchable, also hashed. This key for encryption/decryption is the encryption_key of the user which is encrypted/decrypted with the MASTER_KEY in the settings file. The hashes are in HMAC format. The HMAC secrets are stored in the settings file.

Users are hospital ‘bound’ meaning that an healthprofessional/secretary can only find patients within the same hospital during searching.

Class definitions:

class apps.account.models.UserManager[source]

Bases: django.contrib.auth.base_user.BaseUserManager

Custom user manager which allows adding an user via the manage.py command using email as unique key and filling in other required information

create_user(email=None, password=None, **extra_fields)[source]

Creates and saves a User with the given username, email and password. note: encrypted_email is not encrypted yet here, will be encrypted when the user is saved.

create_superuser(email, password, **extra_fields)[source]

Creates and saves a super user with the same parameters as create_user

class apps.account.models.EncryptionKey(*args, **kwargs)[source]

Bases: django.db.models.base.Model

Stores all encryption keys of the users.

Encrypts/decrypts them with the MASTER_KEY setting.

Parameters:
class apps.account.models.User(*args, **kwargs)[source]

Bases: django.contrib.auth.base_user.AbstractBaseUser, django.contrib.auth.models.PermissionsMixin, core.models.AuditBaseModel

Custom user model which saves basic information about the user. All private information is encrypted.

Private information is stored encrypted in the database via encrypted model fields. See the core.models.EncryptBaseField for more information on encryption.

Private information that should also be searchable is represented by both an encrypted field and an HMAC field. See the core.models.EncryptLookupBaseField for more information on encryption and HMAC lookup.

Parameters:
new_questionnaire_request

Returns true if the patient has no questionnaire requests

new_message_count

Returns the amount of unread messages

full_name

Returns the full_name of an user which is: first_name + prefix + last_name

professional_name

Returns the full_name of an user which is: initials + prefix + last_name

is_deleted

Returns True if the user has been set for deletion.

audit_encryption_key_id

Get the EncryptionKey id so it can be coupled to the log item in the audit.

Returns:
The id of the EncryptionKey that is used to encrypt the model instance.
encryption_key

Get the encryption key of the user.

Returns:
The encryption key of the user instance.
class apps.account.models.LoginAttempt(*args, **kwargs)[source]

Bases: django.db.models.base.Model

Stores all login attempts for administration purposes. Login attempts with extra info and an hash of the username = email address

Parameters:
  • id (AutoField) –
  • succesfull (YesNoChoiceField) –
  • ipaddress (CharField) –
  • useragent (TextField) –
  • extra_info (TextField) –
  • session_id (TextField) –
  • date (DateTimeField) –
  • username_hash (TextField) –
class apps.account.models.LoginSMSCode(*args, **kwargs)[source]

Bases: django.db.models.base.Model

Temporarily stores the hmac_sms_code used during login

Parameters:
  • id (AutoField) –
  • user_id (ForeignKey to User) –
  • hmac_sms_code (CharField) –
class apps.account.models.OldPassword(*args, **kwargs)[source]

Bases: django.db.models.base.Model

Stores previous passwords and the current password. Can both be used to validate that the password is different from the # last passwords and check if the password is expired.

Parameters:
  • id (AutoField) –
  • user_id (ForeignKey to User) –
  • password_hash (CharField) –
  • date_added (DateField) –
class apps.account.models.PasswordChangeRequest(*args, **kwargs)[source]

Bases: django.db.models.base.Model

Temporarly stores the sms_code and key for resetting the password. Email and sms HMAC thus when set only can check using HMAC secret. The attempt_nr field is used to limit the total amount of attempts possible.

Parameters:
  • id (AutoField) –
  • user_id (ForeignKey to User) –
  • hmac_email_key (CharField) –
  • hmac_sms_code (CharField) –
  • added_on (DateField) –
  • attempt_nr (IntegerField) –
class apps.account.models.AgreedwithRules(*args, **kwargs)[source]

Bases: django.db.models.base.Model

Stores whether the user agreed with the rules for using Remotecare.

Parameters:
  • id (AutoField) –
  • user_id (OneToOneField to User) –
  • dateofagreement (DateTimeField) –