Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,297 @@
|
||||
// JWT 解析在计时前完成;本场景测 Provider 数据库复核及随后实际角色读取。
|
||||
use dever_runtime::api::{Request, Response};
|
||||
|
||||
struct AuthInput {
|
||||
service: Arc<auth::Service>,
|
||||
requests: Vec<Request>,
|
||||
claims: Vec<Claims>,
|
||||
now: i64,
|
||||
}
|
||||
|
||||
fn prepare(path: &Path) -> (Arc<dever_runtime::api::Config>, AuthInput) {
|
||||
let config = Arc::new(dever_runtime::api::Config::load(path, &["admin"]).unwrap());
|
||||
let service = Arc::new(
|
||||
auth::Service::new(
|
||||
config.clone(),
|
||||
&[auth::Verification {
|
||||
name: "bench.account.verify",
|
||||
user_model: AUTH_USER_MODEL,
|
||||
tenant_model: AUTH_TENANT_MODEL,
|
||||
}],
|
||||
&[auth::Route {
|
||||
topic: "admin",
|
||||
required: true,
|
||||
user_models: &[AUTH_USER_MODEL],
|
||||
tenant_models: &[AUTH_TENANT_MODEL],
|
||||
}],
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
let now = auth::now().unwrap();
|
||||
let claims = (0..17)
|
||||
.map(|index| Claims {
|
||||
subject: format!("account-{index:02} 中文\""),
|
||||
session: format!("session-{index}"),
|
||||
site: "admin".into(),
|
||||
tenant: None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let requests = claims
|
||||
.iter()
|
||||
.map(|claims| {
|
||||
// 只用公开 Cookie 接口准备凭据,不读取 Secret 的私有字节。
|
||||
let mut bootstrap = Request::new(Default::default());
|
||||
*bootstrap.method_mut() = "POST".parse().unwrap();
|
||||
*bootstrap.uri_mut() = "/login".parse().unwrap();
|
||||
bootstrap
|
||||
.headers_mut()
|
||||
.insert("host", "benchmark.test".parse().unwrap());
|
||||
bootstrap
|
||||
.headers_mut()
|
||||
.insert("origin", "https://benchmark.test".parse().unwrap());
|
||||
let (mut context, _) = service.prepare("admin", &bootstrap, true, now).unwrap();
|
||||
context
|
||||
.issue_cookie(&claims.subject, &claims.session, None, now)
|
||||
.unwrap();
|
||||
let mut response = Response::new(Default::default());
|
||||
context.publish(&mut response);
|
||||
let cookie = response.headers().get("set-cookie").unwrap();
|
||||
let cookie = std::str::from_utf8(cookie.as_bytes())
|
||||
.unwrap()
|
||||
.split(';')
|
||||
.next()
|
||||
.unwrap()
|
||||
.as_bytes()
|
||||
.to_vec();
|
||||
let mut request = Request::new(Default::default());
|
||||
*request.uri_mut() = "/bench/account/admin/permissions".parse().unwrap();
|
||||
request
|
||||
.headers_mut()
|
||||
.insert("host", "benchmark.test".parse().unwrap());
|
||||
request
|
||||
.headers_mut()
|
||||
.insert("cookie", cookie.try_into().unwrap());
|
||||
request
|
||||
})
|
||||
.collect();
|
||||
(
|
||||
config,
|
||||
AuthInput {
|
||||
service,
|
||||
requests,
|
||||
claims,
|
||||
now,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn measure_auth(
|
||||
runtime: &Runtime,
|
||||
registry: &Arc<Registry>,
|
||||
input: &AuthInput,
|
||||
generated: bool,
|
||||
roles: bool,
|
||||
count: usize,
|
||||
) -> (u128, u64) {
|
||||
runtime
|
||||
.run(async |scope| {
|
||||
let mut contexts = input.requests[..16]
|
||||
.iter()
|
||||
.map(|request| {
|
||||
input
|
||||
.service
|
||||
.prepare("admin", request, false, input.now)
|
||||
.unwrap()
|
||||
.0
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut checksum = 0u64;
|
||||
let start = Instant::now();
|
||||
for index in 0..count {
|
||||
let position = index % contexts.len();
|
||||
let context = &mut contexts[position];
|
||||
verify(
|
||||
generated,
|
||||
context,
|
||||
black_box(&input.claims[position]).clone(),
|
||||
scope,
|
||||
registry,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| error.0)
|
||||
.unwrap();
|
||||
checksum += black_box(
|
||||
context.user_id(None).unwrap().unwrap() as u64
|
||||
+ context.id().unwrap().len() as u64,
|
||||
);
|
||||
if roles {
|
||||
let mut database = DbContext::new(registry.clone());
|
||||
let values =
|
||||
black_box(permissions(generated, context, scope, &mut database).await);
|
||||
for value in &values {
|
||||
for field in value {
|
||||
checksum += field.bytes().map(u64::from).sum::<u64>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(start.elapsed().as_nanos(), checksum)
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn check_auth(runtime: &Runtime, registry: &Arc<Registry>, input: &AuthInput) {
|
||||
runtime
|
||||
.run(async |scope| {
|
||||
let expected = vec![
|
||||
[
|
||||
"bench.account.admin.permissions",
|
||||
"bench",
|
||||
"account",
|
||||
"admin",
|
||||
"permissions",
|
||||
"GET",
|
||||
"http",
|
||||
]
|
||||
.map(String::from),
|
||||
];
|
||||
for generated in [true, false] {
|
||||
for index in 0..16 {
|
||||
let (mut context, claims) = input
|
||||
.service
|
||||
.prepare("admin", &input.requests[index], false, input.now)
|
||||
.unwrap();
|
||||
verify(generated, &mut context, claims.unwrap(), scope, registry)
|
||||
.await
|
||||
.map_err(|error| error.0)
|
||||
.unwrap();
|
||||
assert_eq!(context.id().unwrap(), input.claims[index].subject);
|
||||
assert_eq!(
|
||||
context.user_id(Some(AUTH_USER_MODEL)).unwrap(),
|
||||
Some(index as i64 + 1)
|
||||
);
|
||||
assert!(
|
||||
context
|
||||
.tenant_id(Some(AUTH_TENANT_MODEL))
|
||||
.unwrap()
|
||||
.is_none()
|
||||
);
|
||||
let mut database = DbContext::new(registry.clone());
|
||||
assert_eq!(
|
||||
permissions(generated, &mut context, scope, &mut database).await,
|
||||
expected
|
||||
);
|
||||
}
|
||||
for (index, wrong_session) in [(16, false), (0, true)] {
|
||||
let (mut context, claims) = input
|
||||
.service
|
||||
.prepare("admin", &input.requests[index], false, input.now)
|
||||
.unwrap();
|
||||
let mut claims = claims.unwrap();
|
||||
if wrong_session {
|
||||
claims.session.push_str("-revoked");
|
||||
}
|
||||
assert_eq!(
|
||||
verify(generated, &mut context, claims, scope, registry)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.0,
|
||||
401
|
||||
);
|
||||
assert!(context.id().is_err());
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (directory, path) = directory(
|
||||
"auth",
|
||||
r#""http":{"host":"127.0.0.1","port":18001},"sites":{"admin":{"path":"admin","hosts":["benchmark.test"],"auth":"session","origin":"https://benchmark.test"}},"auth":{"providers":{"session":{"verify":"bench.account.verify","jwtSecret":"benchmark-only-key-not-for-any-deployment","ttlSeconds":3600,"cookie":"session"}}}"#,
|
||||
);
|
||||
let runtime = runtime();
|
||||
let registry = runtime
|
||||
.run(async |scope| database_registry(&path, scope).await)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let (config, input) = prepare(&path);
|
||||
runtime
|
||||
.run(async |scope| {
|
||||
let mut database = DbContext::new(registry.clone());
|
||||
for (index, claims) in input.claims.iter().enumerate() {
|
||||
let account = GENERATED_SEED(
|
||||
&claims.subject,
|
||||
&claims.session,
|
||||
index < 16,
|
||||
scope,
|
||||
&mut database,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(account.field0.0, index as i64 + 1);
|
||||
}
|
||||
let (mut context, claims) = input
|
||||
.service
|
||||
.prepare("admin", &input.requests[0], false, input.now)
|
||||
.unwrap();
|
||||
drop(database);
|
||||
api_verify(&mut context, claims.unwrap(), scope, ®istry)
|
||||
.await
|
||||
.map_err(|error| error.0)
|
||||
.unwrap();
|
||||
let mut database = DbContext::new(registry.clone());
|
||||
let executor = database.on(AUTH_BINDING, scope).await.unwrap();
|
||||
dever_runtime::authorization::synchronize(
|
||||
executor,
|
||||
scope,
|
||||
&config,
|
||||
&[dever_runtime::authorization::Declaration {
|
||||
topic: "admin",
|
||||
component: "bench",
|
||||
domain: "account",
|
||||
action: "permissions",
|
||||
method: "GET",
|
||||
}],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
dever_runtime::authorization::save(
|
||||
&mut database,
|
||||
AUTH_BINDING,
|
||||
scope,
|
||||
&context,
|
||||
"reader",
|
||||
"Benchmark reader",
|
||||
false,
|
||||
&["bench.account.admin.permissions".into()],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
for user in 1..=16 {
|
||||
let executor = database.on(AUTH_BINDING, scope).await.unwrap();
|
||||
dever_runtime::authorization::grant(executor, scope, &context, user, "reader")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
check_auth(&runtime, ®istry, &input);
|
||||
header();
|
||||
if HTTP_BENCH {
|
||||
protected_http::run(&runtime, ®istry, &config, &input);
|
||||
} else {
|
||||
for (name, roles) in [
|
||||
("auth_provider_verify", false),
|
||||
("auth_provider_role_read", true),
|
||||
] {
|
||||
samples(name, |generated, count| {
|
||||
measure_auth(&runtime, ®istry, &input, generated, roles, count)
|
||||
});
|
||||
}
|
||||
}
|
||||
check_auth(&runtime, ®istry, &input);
|
||||
drop(registry);
|
||||
drop(runtime);
|
||||
drop(directory);
|
||||
}
|
||||
Reference in new issue
Block a user