Custom backends¶
RestAuth Backends are written in a way that you can easily write a drop-in replacement, if you want to use a different storage system for users, groups or user properties.
To develop your own backend, simply implement one or all of the base classes below.
-
class
RestAuth.backends.base.
UserBackend
[source]¶ Provide the most basic user operations and password management.
-
check_password
(username, password)[source]¶ Check a users password.
Parameters: - username (str) – The username.
- password (str) – The password to check.
Returns: True if the password is correct, False otherwise.
Return type: boolean
Raise: UserNotFound
if the user doesn’t exist.
-
create
(username, password=None, properties=None, property_backend=None, dry=False, transaction=True)[source]¶ Create a new user.
The
username
is already validated, so you don’t need to do any additional validation here. If your backend has username restrictions, please implement a username validator.If
properties
are passed, please use the property backend passed to store the properties:user = ... # create the user property_backend.set_multiple(user, properties, dry=dry) return user
The
dry
parameter tells you if you should actually create the user. The parameter will be True for dry-runs. In a dry-run, the method should behave as closely as possible to a normal invocation but shouldn’t actually create the user.Parameters: - username (str) – The username.
- password (str) – The password to set. If not given, the user should not have a valid password and is unable to log in.
- properties (dict) – Any initial properties for the user.
- property_backend (
PropertyBackend
) – The backend to use to store properties. - dry (boolean) – Wether or not to actually create the user.
- transaction (boolean) – If False, execute statements outside any transactional context, if possible. This parameter is used by restauth-import to import multiple users at once with only one transaction.
Returns: A user object providing at least the properties of the UserInstance class.
Return type: Raise: UserExists
if the user already exist.
-
exists
(username)[source]¶ Determine if the username exists.
Parameters: username (str) – The username. Returns: True if the user exists, False otherwise. Return type: boolean
-
get
(username)[source]¶ Get a user object for the given username.
This method is used to get user objects passed to property- and group-backends.
Parameters: username (str) – The username. Returns: A user object providing at least the properties of the UserInstance class. Return type: UserInstance
Raise: UserNotFound
if the user doesn’t exist.
-
list
()[source]¶ Get a list of all usernames.
Each element of the returned list should be a valid username that can be passed to
get()
.Returns: A list of usernames. Return type: list
-
remove
(username)[source]¶ Remove a user.
Parameters: username (str) – The username. Raise: UserNotFound
if the user doesn’t exist.
-
rename
(username, name)[source]¶ Rename a user.
This operation is only available via restauth-user.py.
Parameters: - username (str) – The username.
- name (str) – The new username.
Raise: UserNotFound
if the user doesn’t exist.Raise: UserExists
if the user already exist.
-
set_password
(username, password=None)[source]¶ Set a new password.
Parameters: - username (str) – The username.
- password (str) – The new password. If None or empty, the user should get an unusable password.
Raise: UserNotFound
if the user doesn’t exist.
-
set_password_hash
(algorithm, hash, salt=None, **kwargs)[source]¶ Set a users password hash.
This method is called by restauth-import.py if users with a password hash should be imported. The most common implementation is to join each given field with a ‘$’.
Parameters: - algorithm (str) – The algorithm used for creating the hash.
- hash (str) – The hash created by the algorithm.
- salt (str) – The salt used to create the hash, if any. If None, do not add a field to be joined, only add this field if salt is a string (empty or non-empty).
-
testSetUp
()[source]¶ Set up your backend for a test run.
This method is exclusively used in unit tests. It should perform any actions necessary to start a unit test.
Note
You do not need to implement this method, if there is nothing to do.
-
testTearDown
()[source]¶ Tear down your backend after a test run.
This method is exclusively used in unit tests. It should perform any actions necessary after a unit test. In general, this should completely wipe all users created during a unit test.
Note
You do not need to implement this method if the backend automatically cleans itself.
-
-
class
RestAuth.backends.base.
PropertyBackend
[source]¶ Provide user properties.
-
create
(user, key, value, dry=False, transaction=True)[source]¶ Create a new user property.
This method should return
PropertyExists
if a property with the given key already exists.The
dry
parameter tells you if you should actually create the property. The parameter will be True for dry-runs. In a dry-run, the method should behave as closely as possible to a normal invocation but shouldn’t actually create the property.Parameters: - user (
UserInstance
) – A user as returned byUserBackend.get()
. - key (str) – The key identifying the property.
- value (str) – The value of the property.
- dry (boolean) – Wether or not to actually create the property.
- transaction (boolean) – If False, execute statements outside any transactional context, if possible. This parameter is used by restauth-import to import multiple users at once with only one transaction.
Returns: A tuple of key/value as they are stored in the database.
Return type: tuple
Raise: PropertyExists
if the property already exists.- user (
-
get
(user, key)[source]¶ Get a specific property of the user.
Parameters: - user (
UserInstance
) – A user as returned byUserBackend.get()
. - key (str) – The key identifying the property.
Returns: The value of the property.
Return type: str
Raise: RestAuth.common.errors.PropertyNotFound
if the property doesn’t exist.- user (
-
list
(user)[source]¶ Get a full list of all user properties.
Parameters: user ( UserInstance
) – A user as returned byUserBackend.get()
.Returns: A dictionary of key/value pairs, each describing a property. Return type: dict
-
remove
(user, key)[source]¶ Remove a property.
Parameters: - user (
UserInstance
) – A user as returned byUserBackend.get()
. - key (str) – The key identifying the property.
Raise: RestAuth.common.errors.PropertyNotFound
if the property doesn’t exist.- user (
-
set
(user, key, value, dry=False, transaction=True)[source]¶ Set a property for the given user.
Unlike
create()
this method overwrites an existing property.The
dry
parameter is never passed by RestAuth itself. You may pass the parameter when calling this method usingset_multiple()
.Parameters: - user (
UserInstance
) – A user as returned byUserBackend.get()
. - key (str) – The key identifying the property.
- value (str) – The value of the property.
- transaction (boolean) – If False, execute statements outside any transactional context, if possible. This parameter is used by restauth-import to import multiple users at once with only one transaction.
Returns: A tuple of key/value as they are stored in the database. The value should be
None
if the property didn’t exist previously or the old value, if it did.Return type: tuple
- user (
-
set_multiple
(user, props, dry=False, transaction=True)[source]¶ Set multiple properties at once.
This method may just call
set()
multiple times. Some backends have faster methods for setting multiple values at once, though.The
dry
parameter tells you if you should actually create the properties. The parameter will be True for dry-runs. In a dry-run, the method should behave as closely as possible to a normal invocation but shouldn’t actually create the properties.Parameters: - user (
UserInstance
) – A user as returned byUserBackend.get()
. - dry (boolean) – Wether or not to actually create the properties.
- transaction (boolean) – If False, execute statements outside any transactional context, if possible. This parameter is used by restauth-import to import multiple users at once with only one transaction.
- user (
-
testSetUp
()[source]¶ Set up your backend for a test run.
This method is exclusively used in unit tests. It should perform any actions necessary to start a unit test.
Note
You do not need to implement this method, if there is nothing to do.
-
testTearDown
()[source]¶ Tear down your backend after a test run.
This method is exclusively used in unit tests. It should perform any actions necessary after a unit test. In general, this should completely wipe all users and properties created during a unit test.
Note
You do not need to implement this method if the backend automatically cleans itself.
-
-
class
RestAuth.backends.base.
GroupBackend
[source]¶ Provide groups.
A group may be identified by its name and a service. The
service
parameter passed in many methods is an instance of django.contrib.auth.models.User. If aGroupInstance
is passed (or returned), the groups service is/should be available as theservice
property.-
add_subgroup
(group, subgroup)[source]¶ Make a group a subgroup of another group.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - subgroup (
GroupInstance
) – A group as provided byGroupBackend.get()
.
- group (
-
add_user
(group, user)[source]¶ Add a user to the given group.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - user (
UserInstance
) – A user as returned byUserBackend.get()
.
- group (
-
create
(name, service=None, dry=False, transaction=True)[source]¶ Create a new group for the given service.
The
dry
parameter tells you if you should actually create the group. The parameter will be True for dry-runs. In a dry-run, the method should behave as closely as possible to a normal invocation but shouldn’t actually create the group.Parameters: - name (str) – The name of the group.
- service (
Service
or None) – The service of the named group. If None, the group should not belong to any service. - dry (boolean) – Wether or not to actually create the group.
- transaction (boolean) – If False, execute statements outside any transactional context, if possible. This parameter is used by restauth-import to import multiple users at once with only one transaction.
Returns: A group object providing at least the properties of the GroupInstance class.
Return type: Raises: RestAuth.common.errors.GroupExists
if the group already exists.
-
exists
(name, service=None)[source]¶ Determine if a group exists for the given service.
Parameters: - name (str) – The name of the group.
- service (
Service
or None) – The service of the group to query.
Returns: True if the group exists, False otherwise.
Return type: boolean
-
get
(name, service=None)[source]¶ Get a group object representing the given group.
Parameters: - name (str) – The name of the group.
- service (
Service
or None) – The service of the named group. If None, the group should not belong to any service.
Returns: A group object providing at least the properties of the GroupInstance class.
Return type: Raises: RestAuth.common.errors.GroupNotFound
if the named group does not exist.
-
is_member
(group, user)[source]¶ Determine if a user is a member of the given group.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - user (
UserInstance
) – A user as returned byUserBackend.get()
.
Returns: True if the User is a member, False otherwise
Return type: boolean
- group (
-
list
(service, user=None)[source]¶ Get a list of group names for the given service.
Parameters: - service – The service of the named group.
- user (
UserInstance
) – If given, only return groups that the user is a member of.
Returns: list of strings, each representing a group name.
Return type:
-
members
(group, depth=None)[source]¶ Get a list of all members of this group.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - depth (int) – Override the recursion depth to use for meta-groups.
Normally, the backend should use
GROUP_RECURSION_DEPTH
.
Returns: list of strings, each representing a username
Return type: - group (
-
parents
(group)[source]¶ Get a list of all parent groups of a group.
This method is only used by some command-line scripts.
Parameters: group ( GroupInstance
) – A group as provided byGroupBackend.get()
.Returns: List of parent groups, each being a GroupInstance object. Return type: list
-
remove
(group)[source]¶ Remove a group.
Parameters: group ( GroupInstance
) – A group as provided byGroupBackend.get()
.
-
rename
(group, name)[source]¶ Rename a group.
This operation is only available via restauth-group.py.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - name (str) – The new groupname.
Raise: GroupExists
if the group already exist.- group (
-
rm_subgroup
(group, subgroup)[source]¶ Remove a subgroup from a group.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - subgroup (
GroupInstance
) – A group as provided byGroupBackend.get()
.
Raises: RestAuth.common.errors.GroupNotFound
if the named subgroup is not actually a subgroup of group.- group (
-
rm_user
(group, user)[source]¶ Remove a user from the group.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - user (
UserInstance
) – A user as returned byUserBackend.get()
.
Raises: RestAuth.common.errors.UserNotFound
if the user is not a member of the group.- group (
-
set_service
(group, service=None)[source]¶ Set the service of a group.
This operation is only available via restauth-group.py.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - service (
Service
or None) – The new service of the group.
- group (
-
subgroups
(group, filter=True)[source]¶ Get a list of subgroups.
If
filter=True
, the method should only return groups that belong to the same service as the given group. The returned list should be a list of strings, each representing a groupname.If
filter=False
, the method should return all groups, regardless of their service. The list should containGroupInstance
objects.Note
The filter argument is only False when called by some command line scripts.
Parameters: - group (
GroupInstance
) – A group as provided byGroupBackend.get()
. - filter (boolean) – Wether or not to filter for the groups service. See description for a detailled explanation.
Returns: A list of subgroups.
- group (
-
testSetUp
()[source]¶ Set up your backend for a test run.
This method is exclusively used in unit tests. It should perform any actions necessary to start a unit test.
Note
You do not need to implement this method, if there is nothing to do.
-
testTearDown
()[source]¶ Tear down your backend after a test run.
This method is exclusively used in unit tests. It should perform any actions necessary after a unit test. In general, this should completely wipe all users and groups created during a unit test.
Note
You do not need to implement this method if the backend automatically cleans itself.
-
Use RestAuth to hash passwords¶
If your backend has no facilities to hash passwords on its own, you should
definetly use the hash functions used by Django/RestAuth itself when processing
passwords. Django provides two simple functions, check_password()
and
make_password()
that you can use.
Simply use those functions in your implementations of
UserBackend.create()
,
UserBackend.set_password()
and
UserBackend.check_password()
. Here is a small example:
from django.contrib.auth.hashers import check_password, make_password
from RestAuth.backends.base import UserBackend
class CustomUserBackend(UserBackend):
def create(self, username, password=None, properties=None,
property_backend=None, dry=False, transaction=True):
# generate hashed password:
hashed_passsword = make_password(password)
# save user with hashed password...
def set_password(self, username, password):
# generate hashed password:
hashed_passsword = make_password(password)
# ... save hashed password for user
def check_password(self, username, password):
"""Checks password, also updates hash if using an old algorithm."""
# get password hash from user...
stored_pwdhash = ...
def setter(raw_password):
self.set_password(username, raw_password)
return check_password(raw_password, stored_pwdhash, setter)
Use third-party libraries¶
If you want to use a third-party library for your backend, use the
_load_library()
method implemented in RestAuthBackend
. All Backend
classes mentioned above inherit from this class.
-
class
RestAuth.backends.base.
RestAuthBackend
[source]¶ Base class for all RestAuth data backends.
RestAuthBackend
provides the_load_library
method that allows loading python modules upon first use. This is useful if you want to implement a backend that uses third-party libraries and do not want to cause immediate ImportErrors every time the module is loaded.To use this featurr, simply set the
library
class attribute and useself.load_library()
to load the module into the methods namespace.Example:
from RestAuth.backends.base import UserBackend class MyCustomBackend(UserBackend): library = 'redis' def get(self, username): redis = self._load_library() # use the redis module...
Returning User/Group objects¶
Some backend methods to implement expect (or return) a user/group object. The objects don’t have to be of any particular class but must have a few properties available. The classes below are given for convenience only, if your objects already provide the correct properties, there is no need to use them.
In most cases, backends are called similar to this:
user = user_backend.get(username='some username')
group = group_backend.get(name='group', service=service)
group_backend.add_user(group=group, user=user)
Note that in the above case, users and groups may be stored in totally different backends.
-
class
RestAuth.backends.base.
UserInstance
(id, username)[source]¶ Class representing a user.
Instances of this class should provide the
username
andid
property.- The
username
is the username of the user as used by the protocol. - The
id
may be the same as the username or some backend specific id, i.e. one that allows faster access.
- The
-
class
RestAuth.backends.base.
GroupInstance
(id, name, service)[source]¶ Class representing a group.
Instances of this class should provide the
name
,id
andservice
properties. For thename
andid
properties, the same semantics as forUserInstance
apply.The
service
property is a service as configured by restauth-service.py. Its name is (confusingly!) available as itsusername
property.