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 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.

commit_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

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:

UserInstance

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.
init_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

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.

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.

rollback_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

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)[source]

Set a users password hash.

This method is called by restauth-import if users with a password hash should be imported.

If you can store password hashes as an arbitrary string and then use Djangos password hashing framework for verifying those hashes, you can import the hash like this:

from common.hashers import import_hash
django_hash = import_hash(algorithm, hash)
Parameters:
  • algorithm (str) – The algorithm used for creating the hash.
  • hash (str) – The hash created by the algorithm.
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 backends.base.PropertyBackend[source]

Provide user properties.

commit_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

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 by UserBackend.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.

get(user, key)[source]

Get a specific property of the user.

Parameters:
Returns:

The value of the property.

Return type:

str

Raise:

common.errors.PropertyNotFound if the property doesn’t exist.

init_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

list(user)[source]

Get a full list of all user properties.

Parameters:user (UserInstance) – A user as returned by UserBackend.get().
Returns:A dictionary of key/value pairs, each describing a property.
Return type:dict
remove(user, key)[source]

Remove a property.

Parameters:
Raise:

common.errors.PropertyNotFound if the property doesn’t exist.

rollback_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

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 using set_multiple().

Parameters:
  • user (UserInstance) – A user as returned by UserBackend.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

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 by UserBackend.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.
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 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 a GroupInstance is passed (or returned), the groups service is/should be available as the service property.

add_subgroup(group, subgroup)[source]

Make a group a subgroup of another group.

Parameters:
add_user(group, user)[source]

Add a user to the given group.

Parameters:
commit_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

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:

GroupInstance

Raises:

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:

GroupInstance

Raises:

common.errors.GroupNotFound if the named group does not exist.

init_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

is_member(group, user)[source]

Determine if a user is a member of the given group.

Parameters:
Returns:

True if the User is a member, False otherwise

Return type:

boolean

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:

list

members(group, depth=None)[source]

Get a list of all members of this group.

Parameters:
Returns:

list of strings, each representing a username

Return type:

list

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 by GroupBackend.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 by GroupBackend.get().
rename(group, name)[source]

Rename a group.

This operation is only available via restauth-group.

Parameters:
Raise:

GroupExists if the group already exist.

rm_subgroup(group, subgroup)[source]

Remove a subgroup from a group.

Parameters:
Raises:

common.errors.GroupNotFound if the named subgroup is not actually a subgroup of group.

rm_user(group, user)[source]

Remove a user from the group.

Parameters:
Raises:

common.errors.UserNotFound if the user is not a member of the group.

rollback_transaction()[source]

Start a transaction.

This method is only used by restauth-import.

set_service(group, service=None)[source]

Set the service of a group.

This operation is only available via restauth-group.

Parameters:
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 contain GroupInstance objects.

Note

The filter argument is only False when called by some command line scripts.

Parameters:
  • group (GroupInstance) – A group as provided by GroupBackend.get().
  • filter (boolean) – Wether or not to filter for the groups service. See description for a detailled explanation.
Returns:

A list of subgroups.

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 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 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 use self.load_library() to load the module into the methods namespace.

Example:

from 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 backends.base.UserInstance(id, username)[source]

Class representing a user.

Instances of this class should provide the username and id 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.
class backends.base.GroupInstance(id, name, service)[source]

Class representing a group.

Instances of this class should provide the name, id and service properties. For the name and id properties, the same semantics as for UserInstance apply.

The service property is a service as configured by restauth-service. Its name is (confusingly!) available as its username property.

Table Of Contents

Previous topic

Run a testserver

Next topic

Overview of implemented HTTP queries

This Page