コード例 #1
0
ファイル: users.py プロジェクト: iraycd/jawaf
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 Exception('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)
コード例 #2
0
async def query(request):
    query = sa.select('*').select_from(question)
    results = 'Questions:\n'
    async with Connection() as con:
        row = await con.fetchrow(query)
        results += '%s\n' % str(row)
    return text(results)
コード例 #3
0
ファイル: permissions.py プロジェクト: dileepkannamala/jawaf
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')
コード例 #4
0
ファイル: permissions.py プロジェクト: dileepkannamala/jawaf
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
コード例 #5
0
ファイル: views.py プロジェクト: dileepkannamala/jawaf
async def query(request):
    query = sa.select('*').select_from(question)
    results = 'Questions:\n'
    async with Connection() as con:
        row = await con.fetchrow(query)
        question_text = row['question_text']
        results += f'{question_text}\n'
    return text(results)
コード例 #6
0
ファイル: test_db_init.py プロジェクト: iraycd/jawaf
async def test_create_tables(test_project, waf):
    """Test create tables command creates the table from the test app."""
    create_tables(['test_app'], warn=False)
    await waf.create_database_pool('default')
    async with Connection() as con:
        await con.execute("INSERT INTO test_app_person VALUES (1, 'test_1')")
        row = await con.fetchrow('''SELECT * FROM test_app_person''')
        assert row.id == 1
    await waf.close_database_pools()
コード例 #7
0
async def test_generate_password_reset_path(test_project, waf):
    await waf.create_database_pool('default')
    async with Connection() as con:
        query = sa.select('*').select_from(
            tables.user).where(tables.user.c.username == 'test')
        row = await con.fetchrow(query)
        user_id = row.get('id')
    url = await users.generate_password_reset_path(user_id)
    assert '/auth/password_reset/' in url
    await waf.close_database_pools()
コード例 #8
0
async def test_create_user(test_project, waf):
    """Test creating a user."""
    await waf.create_database_pool()
    await users.create_user(username='******', password='******')
    async with Connection() as con:
        query = sa.select('*').select_from(
            tables.user).where(tables.user.c.username == 'test')
        row = await con.fetchrow(query)
    assert users.check_password('pass', row.get('password'))
    await waf.close_database_pools()
コード例 #9
0
async def test_check_user_reset_access_split_token_bad_user_id(
        test_project, waf):
    await waf.create_database_pool('default')
    async with Connection() as con:
        query = sa.select('*').select_from(tables.user)
        row = await con.fetchrow(query)
        user_id = row.get('id')
    await users.generate_reset_split_token(user_id)
    verified = await users.check_user_reset_access('test', 3, 'whatever')
    assert not verified
    await waf.close_database_pools()
コード例 #10
0
ファイル: permissions.py プロジェクト: dileepkannamala/jawaf
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)
コード例 #11
0
ファイル: users.py プロジェクト: iraycd/jawaf
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.password):
            return row
        return False
コード例 #12
0
ファイル: views.py プロジェクト: dileepkannamala/jawaf
 async def post(self, request, table_name=None):
     """Post endpoint. Create a new row.
     :param request: Sanic Request.
     :param table_name: Name of the table to access.
     """
     if not check_csrf(request):
         return json({'message': 'access denied'}, status=403)
     get_jawaf()
     table = registry.get(table_name)
     if not table:
         return json({'message': 'access denied'}, status=403)
     async with Connection(table['database']) as con:
         stmt = table['table'].insert().values(**request.json)
         await con.execute(stmt)
     await add_audit_action(
         'post', 'admin', table_name, request['session']['user'])
     return json({'message': 'success'}, status=201)
コード例 #13
0
ファイル: users.py プロジェクト: dileepkannamala/jawaf
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)
コード例 #14
0
ファイル: users.py プロジェクト: iraycd/jawaf
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=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 '%s%s' % (selector.decode('utf-8'), verifier.decode('utf-8'))
コード例 #15
0
async def add_audit_action(name, target, table_name, user_row, database=None):
    """Add audit action
    :param name: String. Action name.
    :param target: String. Action target.
    :param table_name: String. Table name.
    :param user_row: SQLAlchemy Record. User row.
    :param database: String. Database id to use, or default for AUTH.
    """
    database = database_key(database)
    async with Connection(database) as con:
        stmt = audit_action.insert().values(
            name=name,
            table=table_name,
            target=target,
            user_id=user_row.get('id'),
            username=user_row.get('username'),
        )
        await con.execute(stmt)
コード例 #16
0
ファイル: users.py プロジェクト: dileepkannamala/jawaf
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
コード例 #17
0
ファイル: views.py プロジェクト: dileepkannamala/jawaf
 async def get(self, request, table_name=None):
     """Get endpoint. Retrieve one object by id (url param `id=`)
     :param request: Sanic Request.
     :param table_name: Name of the table to access.
     """
     get_jawaf()
     table = registry.get(table_name)
     try:
         target_id = int(request.raw_args.get('id', None))
     except:
         return json({'message': 'no id'}, status=400)
     if not table:
         return json({'message': 'access denied'}, status=403)
     async with Connection(table['database']) as con:
         query = sa.select('*').select_from(table['table']).where(
             table['table'].c.id == target_id)
         result = await con.fetchrow(query)
         if not result:
             return json({'message': 'not found', 'data': None}, status=404)
         return json({'message': 'success', 'data': result}, status=200)
コード例 #18
0
ファイル: views.py プロジェクト: dileepkannamala/jawaf
 async def delete(self, request, table_name=None):
     """Delete endpoint.
     :param request: Sanic Request.
     :param table_name: Name of the table to access.
     """
     if not check_csrf(request):
         return json({'message': 'access denied'}, status=403)
     get_jawaf()
     table = registry.get(table_name)
     target_id = request.json.get('id', None)
     if not target_id:
         return json({'message': 'no id'}, status=400)
     if not table:
         return json({'message': 'access denied'}, status=403)
     async with Connection(table['database']) as con:
         stmt = table['table'].delete().where(
             table['table'].c.id == target_id)
         await con.execute(stmt)
     await add_audit_action(
         'delete', 'admin', table_name, request['session']['user'])
     return json({'message': 'success'}, status=200)
コード例 #19
0
ファイル: views.py プロジェクト: dileepkannamala/jawaf
 async def get(self, request, table_name=None):
     """Get endpoint. Search for objects by `field`/`value` params.
     Optionally add `sort`, `limit`, and `offset`. Default is no sort.
     :param request: Sanic Request.
     :param table_name: Name of the table to access.
     """
     field = request.raw_args.get('field', '')
     value = request.raw_args.get('value', '')
     sort = request.raw_args.get('sort', '')
     limit = request.raw_args.get('limit', '')
     offset = request.raw_args.get('offset', '')
     get_jawaf()
     table = registry.get(table_name)
     if not table:
         return json({'message': 'access denied'}, status=403)
     if field and value:
         async with Connection(table['database']) as con:
             query = sa.select('*').select_from(table['table']).where(
                 getattr(table['table'].c, field).ilike(value))
             if sort:
                 if sort[0] == '-':
                     sort = sort.lstrip('-')
                     query = query.order_by(
                         sa.desc(getattr(table['table'].c, sort)))
                 else:
                     query = query.order_by(getattr(table['table'].c, sort))
             if limit:
                 query = query.limit(int(limit))
             if offset:
                 query = query.offset(int(offset))
             results = await con.fetch(query)
             if results:
                 return json({
                     'message': 'success',
                     'results': [r for r in results]},
                     status=200)
     return json({'message': 'no data', 'results': ''}, status=401)
コード例 #20
0
ファイル: test_db_init.py プロジェクト: iraycd/jawaf
async def test_connection(test_project, waf):
    """Test the Connection class."""
    await waf.create_database_pool('default')
    async with Connection() as con:
        assert type(con) == asyncpgsa.connection.SAConnection
    await waf.close_database_pools()