Beispiel #1
0
async def create_group(name, permission_pairs, database=None):
    """Create a group with specified permissions on targets, plus all join tables.
    :param name: Group name.
    :param permission_pairs: Tuple. List of permission names/targets to create.
    :param database: String. Database id to use, or default for AUTH.
    :return: Int. Group id created.
    """
    database = database_key(database)
    async with Connection(database) as con:
        stmt = group.insert().values(name=name)
        await con.execute(stmt)
        query = sa.select('*').select_from(group).where(
            group.c.name == name).order_by(group.c.id.desc())
        grp = await con.fetchrow(query)
        perms = []
        for permission_pair in permission_pairs:
            stmt = permission.insert().values(**permission_pair)
            await con.execute(stmt)
            query = sa.select('*').select_from(permission).order_by(
                permission.c.id.desc())
            perm = await con.fetchrow(query)
            perms.append(perm)
        for perm in perms:
            stmt = group_permission.insert().values(
                    permission_id=perm.get('id'),
                    group_id=grp.get('id')
                )
            await con.execute(stmt)
    return grp.get('id')
Beispiel #2
0
async def check_permission(user_row, name, target, database=None):
    """Check permission via groups.
    :param user_row: SQLAlchemy Record. User row to check.
    :param name: String. Name of permission.
    :param target: String. Target for permission (eg a table).
    :return: Boolean. If user has permission on target.
    """
    # TODO: Clean this up.
    if user_row.get('is_superuser'):
        return True
    database = database_key(database)
    async with Connection(database) as con:
        query = sa.select('*').select_from(user_group).where(
            user_group.c.user_id == user_row.get('id'))
        rows = await con.fetch(query)
        group_ids = [row.get('group_id') for row in rows]
        if not group_ids:
            return False
        query = sa.select('*').select_from(group_permission).where(
            group_permission.c.group_id.in_(group_ids))
        rows = await con.fetch(query)
        permission_ids = [row.get('permission_id') for row in rows]
        if not permission_ids:
            return False
        query = sa.select('*').select_from(permission) \
            .where(permission.c.id.in_(permission_ids)) \
            .where(permission.c.name == name) \
            .where(permission.c.target == target)
        row = await con.fetchrow(query)
        if row:
            return True
    return False
Beispiel #3
0
async def add_user_to_group(user_id, group_id, database=None):
    """Add user to group
    :param user_id: Int. User id to add.
    :param group_id: Int. Group id to add user to.
    :param database: String. Database id to use, or default for AUTH.
    """
    database = database_key(database)
    async with Connection(database) as con:
        stmt = user_group.insert().values(
            user_id=user_id,
            group_id=group_id
            )
        await con.execute(stmt)
Beispiel #4
0
async def create_user(username,
                      password,
                      first_name=None,
                      last_name=None,
                      email=None,
                      user_type=None,
                      is_staff=False,
                      is_superuser=False,
                      is_active=True,
                      date_joined=None,
                      database=None):
    """Create a user.
    :param username: String. Username.
    :param password: String. Password. Will be stored encoded.
    :param first_name: String. User's first name. (Default None)
    :param last_name: String. User's last name. (Default None)
    :param user_type: String. Optionally segment users with string categories.
        (Default None)
    :param is_active: Boolean. If user account is active. (Default True)
    :param is_staff: Boolean. If user is "staff" and has "admin" level access.
        (Default False)
    :param is_superuser: Boolean.
        If user is a "superuser" and has all permissions without being
        explicitly assigned. (Default False)
    :param date_joined: Datetime (with timezone).
        Date user account was created.
    :param database: String. Database name to connect to.
        (Default: None - use jawaf.auth default)
    """
    database = database_key(database)
    if date_joined is None:
        date_joined = get_utc(datetime.datetime.now())
    async with Connection(database) as con:
        stmt = user.insert().values(username=username,
                                    password=make_password(password),
                                    first_name=first_name,
                                    last_name=last_name,
                                    email=email,
                                    user_type=user_type,
                                    is_staff=is_staff,
                                    is_superuser=is_superuser,
                                    is_active=is_active,
                                    date_joined=date_joined,
                                    last_login=None)
        await con.execute(stmt)
Beispiel #5
0
async def check_user(username='', password='', database=None):
    """Check a user username/password combination agains the database.
    :param username: String. Username to check.
    :param password: String. password to verify.
    :param database: String. Database name to connect to.
        (Default: None - use jawaf.auth default)
    :return: Boolean. If username and password are a valid combination.
    """
    database = database_key(database)
    async with Connection(database) as con:
        query = sa.select('*').select_from(user).where(
            user.c.username == username)
        row = await con.fetchrow(query)
        if not row:
            return False
        if check_password(password, row.get('password')):
            return row
        return False
Beispiel #6
0
async def check_user_reset_access(username,
                                  user_id,
                                  split_token,
                                  database=None):
    """Check password reset token for the current user.
    :param username: String. Username to check.
    :param user_id: Int. User_id..
    :param split_token: String. Split token to search for and validate against.
    :param database: String. Database name to connect to.
        (Default: None - use jawaf.auth default)
    """
    if username is None or user_id is None:
        return False
    database = database_key(database)
    selector = split_token[:SELECTOR_ENCODED_LENGTH].encode('utf-8')
    verifier = split_token[SELECTOR_ENCODED_LENGTH:].encode('utf-8')
    async with Connection(database) as con:
        query = sa.select('*').select_from(user) \
            .where(user.c.username == username) \
            .where(user.c.id == user_id)
        row = await con.fetchrow(query)
        if not row:
            # username and id don't match!
            return False
        query = sa.select('*').select_from(user_password_reset) \
            .where(user_password_reset.c.selector == str(selector)) \
            .where(user_password_reset.c.user_id == user_id)
        row = await con.fetchrow(query)
        if not row:
            # Selector not found - invalid link.
            return False
        if get_utc(datetime.datetime.now()) > row.get('expires'):
            # First remove the expired record.
            stmt = user_password_reset.delete().where(
                user_password_reset.c.id == row.get('id'))
            await con.execute(stmt)
            return False
        if hashlib.sha256(verifier).hexdigest() == row.get('verifier'):
            # Only allow this reset token to be used once.
            stmt = user_password_reset.delete().where(
                user_password_reset.c.id == row.get('id'))
            await con.execute(stmt)
            return True
        return False
Beispiel #7
0
async def generate_reset_split_token(user_id, database=None):
    """Generate a password reset token for the current user.
    :param user_id: Int. User id to generate split token for.
    :param database: String. Database name to connect to.
        (Default: None - use jawaf.auth default)
    :return: String. Joined token.
    """
    database = database_key(database)
    selector, verifier = _generate_split_token()
    async with Connection(database) as con:
        stmt = user_password_reset.insert().values(
            user_id=user_id,
            selector=str(selector),
            verifier=hashlib.sha256(verifier).hexdigest(),
            expires=get_utc(datetime.datetime.now() + datetime.timedelta(
                hours=settings.AUTH_CONFIG['password_reset_expiration'])),
        )
        await con.execute(stmt)
    return '{0}{1}'.format(selector.decode('utf-8'), verifier.decode('utf-8'))
Beispiel #8
0
async def update_user(database=None,
                      target_username=None,
                      target_user_id=None,
                      **kwargs):
    """Update user. Accepts same optional kwargs as create_user + last_login.
    :param database: String. Database name to connect to.
        (Default: None - use jawaf.auth default)
    :param target_username: String. Username to search against.
    :param username: String. Username.
    :param password: String. Password. Will be stored encoded.
    :param first_name: String. User's first name. (Default None)
    :param last_name: String. User's last name. (Default None)
    :param user_type: String. Optionally segment users with string categories.
        (Default None)
    :param is_active: Boolean. If user account is active. (Default True)
    :param is_staff: Boolean. If user is "staff" and has "admin" level access.
        (Default False)
    :param is_superuser: Boolean.
        If user is a "superuser" and has all permissions without being
        explicitly assigned. (Default False)
    :param date_joined: Datetime (with timezone).
        Date user account was created.
    :param last_login: Datetime (with timezone).
        Date user account was last accessed.
    """
    database = database_key(database)
    if 'password' in kwargs:
        kwargs['password'] = make_password(kwargs['password'])
    if not target_username and not target_user_id:
        raise ServerError('Must provide username or user_id to update')
    async with Connection(database) as con:
        if target_username:
            stmt = user.update().where(
                user.c.username == target_username).values(**kwargs)
        else:
            stmt = user.update().where(user.c.id == target_user_id).values(
                **kwargs)
        await con.execute(stmt)