use super::*; #[test] fn capability_directory_includes_permissions_beyond_the_model_page_limit() { let fixture = Fixture::new(); let post = request("POST"); Runtime::new(Default::default()) .unwrap() .run(async |scope| { let database = fixture.database(scope, "pages", true).await; let mut executor = database.executor().await.unwrap(); crate::authorization::owner(&mut executor, scope, "admin", 7) .await .unwrap(); let mut tenant = Tenant { executor: &mut executor, id: 1, }; let context = fixture.context(&post, "admin", Some(1), Some(("news", "article"))); for value in 1u128..=101 { register_capability(&mut tenant, scope, &context, value.to_be_bytes()) .await .unwrap(); } for current in [false, true] { let entries = capabilities(&mut tenant, scope, &context, current) .await .unwrap(); assert_eq!(entries.len(), 101); assert!(entries.windows(2).all(|pair| pair[0].key < pair[1].key)); } }) .unwrap(); } #[test] fn removal_is_atomic_clears_all_grants_and_reregistration_does_not_restore_them() { let fixture = Fixture::new(); let post = request("POST"); Runtime::new(Default::default()).unwrap().run(async |scope| { let database = fixture.database(scope, "removal", true).await; let mut executor = database.executor().await.unwrap(); let mut tenant = Tenant { executor: &mut executor, id: 1 }; let context = fixture.context(&post, "admin", Some(1), Some(("news", "article"))); register_capability(&mut tenant, scope, &context, ID).await.unwrap(); tenant.executor.initialize(scope, "INSERT INTO _dever_role VALUES ('admin','reader','Reader',0,1,0),('admin','second','Second',0,1,0); INSERT INTO _dever_user_role VALUES ('admin',7,'reader');").await.unwrap(); for role in ["reader", "second"] { tenant.executor.execute(scope, "INSERT INTO _dever_role_permission VALUES ('admin',$1,$2)", vec![Parameter::Text(role.into()), Parameter::Text(KEY.into())]).await.unwrap(); } assert_eq!(capabilities(&mut tenant, scope, &context, true).await.unwrap().len(), 1); let owner = tenant.executor.begin(scope).await.unwrap(); remove_capability(&mut tenant, scope, &context, ID).await.unwrap(); assert!(capabilities(&mut tenant, scope, &context, true).await.unwrap().is_empty()); tenant.executor.finish(scope, owner, false).await.unwrap(); assert_eq!(capabilities(&mut tenant, scope, &context, true).await.unwrap().len(), 1); remove_capability(&mut tenant, scope, &context, ID).await.unwrap(); remove_capability(&mut tenant, scope, &context, ID).await.unwrap(); let counts = tenant.executor.query(scope, "SELECT COUNT(*) FROM _dever_role_permission", vec![], 1, |row| row.get::<_, i64>(0)).await.unwrap(); assert_eq!(counts, [0]); register_capability(&mut tenant, scope, &context, ID).await.unwrap(); assert!(capabilities(&mut tenant, scope, &context, true).await.unwrap().is_empty()); assert_eq!(capabilities(&mut tenant, scope, &context, false).await.unwrap().len(), 1); }).unwrap(); } #[test] fn registration_and_models_share_rollback_and_failed_removal_keeps_the_catalog_active() { let fixture = Fixture::new(); let post = request("POST"); Runtime::new(Default::default()).unwrap().run(async |scope| { let database = fixture.database(scope, "rollback", true).await; let mut executor = database.executor().await.unwrap(); executor.initialize(scope, "CREATE TABLE article(id BIGINT PRIMARY KEY);").await.unwrap(); let mut tenant = Tenant { executor: &mut executor, id: 1 }; let context = fixture.context(&post, "admin", Some(1), Some(("news", "article"))); let owner = tenant.executor.begin(scope).await.unwrap(); tenant.executor.execute(scope, "INSERT INTO article VALUES (1)", vec![]).await.unwrap(); register_capability(&mut tenant, scope, &context, ID).await.unwrap(); tenant.executor.finish(scope, owner, false).await.unwrap(); assert!(capabilities(&mut tenant, scope, &context, false).await.unwrap().is_empty()); assert_eq!(tenant.executor.query(scope, "SELECT COUNT(*) FROM article", vec![], 1, |row| row.get::<_, i64>(0)).await.unwrap(), [0]); register_capability(&mut tenant, scope, &context, ID).await.unwrap(); tenant.executor.initialize(scope, "CREATE TRIGGER reject_removal BEFORE DELETE ON _dever_role_permission BEGIN SELECT RAISE(ABORT, 'test-only failure'); END; INSERT INTO _dever_role VALUES ('admin','reader','Reader',0,1,0);").await.unwrap(); tenant.executor.execute(scope, "INSERT INTO _dever_role_permission VALUES ('admin','reader',$1)", vec![Parameter::Text(KEY.into())]).await.unwrap(); assert!(matches!(remove_capability(&mut tenant, scope, &context, ID).await, Err(Failure::Database(_)))); assert_eq!(capabilities(&mut tenant, scope, &context, false).await.unwrap().len(), 1); assert_eq!(tenant.executor.query(scope, "SELECT COUNT(*) FROM _dever_role_permission", vec![], 1, |row| row.get::<_, i64>(0)).await.unwrap(), [1]); }).unwrap(); }