async def test_crud_perm_query_disallow_and_allow_simple(): db, MUsers, MTopics, MTopics2 = crud_db_init() permission = { 'visitor': RoleDefine({ User: TablePerm({ User.id: {A.READ}, User.password: {A.READ} }) }, match=None), 'user': RoleDefine({ User: TablePerm({ User.id: {A.READ, A.QUERY}, User.password: {A.READ} }) }), } c = PeeweeCrud(permission, {User: MUsers}, db) info = QueryInfo.from_json(User, { 'id.eq': 5, }) ret = await c.get_list_with_perm(info, perm=PermInfo(True, None, permission['visitor'])) assert len(ret) == 5 # 注意这里,权限过滤会改变info内部的样子 info = QueryInfo.from_json(User, { 'id.eq': 5, }) ret = await c.get_list_with_perm(info, perm=PermInfo(True, None, permission['user'])) assert len(ret) == 1
def test_parse_foreignkey(): with pytest.raises(InvalidQueryConditionValue): QueryInfo.from_json(User, {'$fks': {'topic': {'id.eq': '$user.id'}}}) q = QueryInfo.from_json( User, { '$fks': { 'topic': { '$select': 'id, title, user_id', 'user_id.eq': '$user:id' } } }) assert 'topic' in q.foreign_keys t = q.foreign_keys['topic'] assert t.from_table == Topic assert t.select == [Topic.id, Topic.title, Topic.user_id] assert len(t.conditions.items) == 1 c = t.conditions.items[0] assert c.column == Topic.user_id assert c.op == QUERY_OP_COMPARE.EQ assert c.value == User.id
async def test_crud_perm_write(): db, MUsers, MTopics, MTopics2 = crud_db_init() permission = { 'visitor': RoleDefine({ User: TablePerm({ User.id: {A.READ, A.QUERY}, User.nickname: {A.READ}, User.password: {A.READ} }) }, match=None), 'user': RoleDefine({ User: TablePerm({ User.id: {A.READ, A.QUERY}, User.nickname: {A.READ, A.UPDATE}, User.password: {A.READ} }) }, match=None) } c = PeeweeCrud(permission, {User: MUsers}, db) # perm visitor with pytest.raises(InvalidQueryValue): ret = await c.update_with_perm( QueryInfo.from_json(User, {'id.eq': 5}), ValuesToWrite({'nickname': 'aaa'}, User).bind(), perm=PermInfo(True, None, permission['visitor']) ) assert len(ret) == 0 # all filtered # not check ret = await c.update_with_perm( QueryInfo.from_json(User, {'id.eq': 5}), ValuesToWrite({'nickname': 'aaa'}, User).bind(), perm=PermInfo(False, None, permission['visitor']) ) assert len(ret) == 1 assert ret[0] == 5 # perm user ret = await c.update_with_perm( QueryInfo.from_json(User, {'id.eq': 5}), ValuesToWrite({'nickname': 'ccc'}, User).bind(), perm=PermInfo(True, None, permission['user']) ) assert len(ret) == 1 assert ret[0] == 5 # returning ret = await c.update_with_perm( QueryInfo.from_json(User, {'id.eq': 5}), ValuesToWrite({'nickname': 'ccc'}, User).bind(), perm=PermInfo(True, None, permission['user']), returning=True ) assert len(ret) == 1 assert isinstance(ret[0], QueryResultRow)
def test_condition_simple2_from_http(): q = QueryInfo.from_json(User, {'test.eq': '"111"'}, from_http_query=True) cond = q.conditions.items[0] assert cond.column == User.test assert cond.op == QUERY_OP_COMPARE.EQ assert cond.value == 111 q = QueryInfo.from_json(User, {'test.eq': '222'}, from_http_query=True) cond = q.conditions.items[0] assert cond.column == User.test assert cond.op == QUERY_OP_COMPARE.EQ assert cond.value == 222
def test_condition_simple_from_http(): q = QueryInfo.from_json(User, {'nickname.eq': '"test"'}, from_http_query=True) cond = q.conditions.items[0] assert cond.column == User.nickname assert cond.op == QUERY_OP_COMPARE.EQ assert cond.value == 'test'
def test_values_bug_2(): qi = QueryInfo.from_json( User, {'values.contains': json.dumps(["5ef99253000000041d4164ef"])}, from_http_query=True) assert qi.conditions.items[0].value[0] == binascii.unhexlify( '5ef99253000000041d4164ef')
def test_parse_order_by(): q = QueryInfo.from_json(User, {'$order-by': 'id, username.desc, test'}) assert q.order_by == [ QueryOrder(User.id), QueryOrder(User.username, 'desc'), QueryOrder(User.test) ]
def test_condition_logic_failed_1(key): q = QueryInfo.from_json(User, {'$' + key: { 'nickname.eq': 'test', 'test.lt': 5 }}) assert len(q.conditions.items) == 0
async def test_crud_array_contains_any(): c, db, TableOneModel = crud_db_init() await c.get_list( QueryInfo.from_json(TableOne, { '$select': 'id', 'arr.contains_any': ['a'] })) assert c.last_sql == 'SELECT "id","id" FROM "table_one" WHERE "arr"&&? LIMIT 20'
def test_parse_negated(): q = QueryInfo.from_json(User, {'$not': { 'id.eq': 1, }}) conds1 = q.conditions conds2 = QueryConditions([~(ConditionLogicExpr('and', [f(User.id) == 1]))]) assert check_same_expr(conds1, conds2)
def test_hexstr_in(): q = QueryInfo.from_json(User, { '$select': 'id, nickname, token', 'token.in': json.dumps(['aabb', '22']) }, from_http_query=True) assert q.conditions.items[0].value[0] == b'\xaa\xbb'
async def test_bytes_query_memoryview(): db, c, TestModel = crud_db_init() info = QueryInfo.from_json(ATest, {'token.eq': memoryview(b'abcd')}) ret = await c.get_list(info) assert ret[0].to_dict()['token'] == b'abcd' assert len(ret) == TestModel.select().where( TestModel.token == b'abcd').count()
async def test_crud_read_by_prefix(): db, MUsers, MTopics, MTopics2 = crud_db_init() c = PeeweeCrud(None, {User: MUsers}, db) n = QueryInfo.from_json(User, {'username.prefix': 'test4'}) ret = await c.get_list(n) assert ret[0].to_dict()['username'] == 'test4'
async def test_bytes_query_from_http(): db, c, TestModel = crud_db_init() info = QueryInfo.from_json(ATest, {'token.eq': '"eeff"'}, from_http_query=True) ret = await c.get_list(info) assert ret[0].to_dict()['token'] == b'\xee\xff' assert len(ret) == TestModel.select().where( TestModel.token == b'\xee\xff').count()
def test_condition_simple2(): q = QueryInfo.from_json(User, {'nickname.eq': 'test', 'test.lt': 5}) cond = q.conditions.items[0] assert cond.column == User.nickname assert cond.op == QUERY_OP_COMPARE.EQ assert cond.value == 'test' cond = q.conditions.items[1] assert cond.column == User.test assert cond.op == QUERY_OP_COMPARE.LT assert cond.value == 5
async def test_crud_is_null(): c, db, TableOneModel = crud_db_init() await c.get_list( QueryInfo.from_json(TableOne, { '$select': 'id', 'arr.is': 'null', }, from_http_query=True)) assert c.last_sql == 'SELECT "id","id" FROM "table_one" WHERE "arr" IS ? LIMIT 20'
async def test_crud_read_with_count(): db, MUsers, MTopics, MTopics2 = crud_db_init() c = PeeweeCrud(None, { Topic: MTopics, }, db) i = QueryInfo.from_json(Topic, {}) i.limit = 1 ret = await c.get_list(i, with_count=True) assert len(ret) == 1 assert ret.rows_count == MTopics.select().count()
async def test_crud_read_3(): db, MUsers, MTopics, MTopics2 = crud_db_init() c = PeeweeCrud(None, {Topic: MTopics}, db) q = QueryInfo.from_json(Topic, {'$not': {'id.eq': 1}}) ret = await c.get_list(q) v1 = {x.id for x in ret} v2 = {x.id for x in MTopics.select().where(MTopics.id != 1)} assert v1 == v2
async def test_crud_read_2(): db, MUsers, MTopics, MTopics2 = crud_db_init() c = PeeweeCrud(None, { User: MUsers, Topic: MTopics, }, db) n0 = QueryInfo.from_json(Topic, {'id.eq': 1}) n = n0.clone() ret = await c.get_list(n) assert len(ret) == 1
def test_condition_logic_1(key, op_name): q = QueryInfo.from_json(User, {'$' + key: { 'nickname.eq': 'test', 'test.lt': 5 }}) cond = q.conditions.items[0] assert isinstance(cond, ConditionLogicExpr) assert cond.type == op_name cond1 = cond.items[0] cond2 = cond.items[1] assert cond1.op == QUERY_OP_COMPARE.EQ assert cond2.op == QUERY_OP_COMPARE.LT
def test_parse_multi_same_op(): q = QueryInfo.from_json(User, { 'id.ne': 1, 'id.ne.1': 2, 'id.ne.2': 3, }) conds1 = q.conditions conds2 = QueryConditions([ f(User.id) != 1, f(User.id) != 2, f(User.id) != 3, ]) assert check_same_expr(conds1, conds2)
async def test_crud_delete_success(): db, MUsers, MTopics, MTopics2 = crud_db_init() c = PeeweeCrud(None, { User: MUsers, Topic: MTopics, }, db) assert MTopics.select().where(MTopics.id == 1).count() == 1 ret = await c.delete(QueryInfo.from_json(Topic, {'id.eq': 1})) assert len(ret) == 1 assert MTopics.select().where(MTopics.id == 1).count() == 0
async def test_crud_perm_delete(): db, MUsers, MTopics, MTopics2 = crud_db_init() role_visitor = RoleDefine({ User: TablePerm({ User.id: {A.READ, A.QUERY}, User.nickname: {A.READ}, User.password: {A.READ} }) }, match=None) role_user = RoleDefine({ User: TablePerm({ User.id: {A.READ, A.QUERY}, User.nickname: {A.READ, A.UPDATE}, User.password: {A.READ} }, allow_delete=True) }, match=None) c = PeeweeCrud(None, {User: MUsers}, db) # perm visitor with pytest.raises(PermissionException): await c.delete_with_perm( QueryInfo.from_json(User, {}), perm=PermInfo(True, None, role_visitor) ) # perm user assert len(await c.get_list(QueryInfo(User))) == 5 ret = await c.delete_with_perm( QueryInfo.from_json(User, {}), perm=PermInfo(True, None, role_user) ) assert len(ret) == 5 assert len(await c.get_list(QueryInfo(User))) == 0
async def test_crud_and_or(): db, MUsers, MTopics, MTopics2 = crud_db_init() c = PeeweeCrud(None, {User: MUsers}, db) info = QueryInfo.from_json( User, {'$or': { 'id.in': [1, 2], '$and': { 'id.ge': 4, 'id.le': 5 } }}) ret = await c.get_list(info) assert [x.id for x in ret] == [1, 2, 4, 5]
async def test_crud_perm_read(): db, MUsers, MTopics, MTopics2 = crud_db_init() permission = { 'visitor': RoleDefine({ User: TablePerm({ User.id: {A.READ}, User.password: {A.READ} }) }, match=None), } c = PeeweeCrud(permission, {User: MUsers}, db) info = QueryInfo.from_json(User, {}) ret = await c.get_list_with_perm(info, perm=PermInfo(True, None, permission['visitor'])) for i in ret: assert i.to_dict().keys() == {'id', 'password'}
def test_condition_logic_2(): q = QueryInfo.from_json(User, { '$and': { 'nickname.eq': 'test', '$or': { 'test.ge': 5, 'test.lt': 10 } } }) cond = q.conditions.items[0] assert isinstance(cond, ConditionLogicExpr) assert cond.type == 'and' assert cond.items[0].op == QUERY_OP_COMPARE.EQ assert isinstance(cond.items[1], ConditionLogicExpr) assert cond.items[1].type == 'or' assert cond.items[1].items[1].value == 10
async def test_crud_perm_insert(): db, MUsers, MTopics, MTopics2 = crud_db_init() role_visitor = RoleDefine({ User: TablePerm({ User.id: {A.READ, A.QUERY}, User.nickname: {A.READ}, User.password: {A.READ} }) }, match=None) role_user = RoleDefine({ User: TablePerm({ User.id: {A.READ, A.QUERY}, User.username: {A.CREATE}, User.nickname: {A.READ, A.UPDATE, A.CREATE}, User.password: {A.READ, A.CREATE} }, allow_delete=True) }, match=None) c = PeeweeCrud(None, {User: MUsers}, db) # perm visitor with pytest.raises(ValidationError): ret = await c.insert_many_with_perm( User, [ValuesToWrite({'id': 10, 'nickname': 'aaa', 'username': '******'}, User)], perm=PermInfo(True, None, role_visitor) ) assert len(ret) == 0 # all filtered # perm user ret = await c.insert_many_with_perm( User, [ValuesToWrite({'id': 10, 'nickname': 'aaa', 'username': '******'})], perm=PermInfo(True, None, role_user) ) assert len(ret) == 1 ret2 = await c.get_list(QueryInfo.from_json(User, {'id.eq': ret[0]})) assert ret2[0].to_dict()['id'] == ret[0] # perm not check ret = await c.insert_many_with_perm( User, [ValuesToWrite({'nickname': 'qqqq', 'username': '******'}, User).bind(True)], perm=PermInfo(False, None, role_visitor) ) assert len(ret) == 1 # with returning ret = await c.insert_many_with_perm( User, [ValuesToWrite({'nickname': 'wwww', 'username': '******'}, User).bind(check_insert=True)], perm=PermInfo(False, None, role_visitor), returning=True ) assert len(ret) == 1 d = ret[0].to_dict() assert d['username'] == 'u2' assert d['nickname'] == 'wwww'
def test_select_simple2(): q = QueryInfo.from_json(User, {}) assert q.select_for_crud == [ User.id, User.nickname, User.username, User.password, User.test ]
async def test_bytes_query_from_http_2(): # 双重 stringify with pytest.raises(InvalidQueryConditionValue): info = QueryInfo.from_json( ATest, {'token.eq': '"\\"5e8c3dea000000051d411585\\""'}, from_http_query=True)
def test_select_simple(): q = QueryInfo.from_json(User, { '$select': 'id, nickname, password', '$select-': '' }) assert q.select_for_crud == [User.id, User.nickname, User.password]