use affinidi_secrets_resolver::secrets::Secret;
use trust_tasks_https::{BearerAuth, HttpsServer};
use trust_tasks_proof::affinidi::Verifier;
use trust_tasks_rs::{
specs::acl::{grant, revoke},
RejectReason,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (_, alice_did) = demo_identity();
let auth = BearerAuth::from_pairs([
("alice", alice_did.as_str()),
("bob", "did:web:bob.example"),
]);
let server = HttpsServer::builder()
.local_vid("did:web:maintainer.example")
.with_auth(auth)
.with_verifier(Verifier::for_did_key())
.on::<grant::v0_1::Payload, _>(|req, ctx| {
println!(
"acl/grant received from {} for subject {} (role {})",
ctx.authenticated_sender.as_deref().unwrap_or("<unauth>"),
req.payload.entry.subject,
&*req.payload.entry.role,
);
Ok(grant::v0_1::Response::builder()
.entry(req.payload.entry.clone())
.try_into()
.expect("acl grant response builder"))
})
.on::<revoke::v0_1::Payload, _>(|req, ctx| {
println!(
"acl/revoke received from {} for subject {}",
ctx.authenticated_sender.as_deref().unwrap_or("<unauth>"),
req.payload.subject,
);
if !ctx
.authenticated_sender
.as_deref()
.map(|s| s.starts_with("did:web:"))
.unwrap_or(false)
{
return Err(RejectReason::PermissionDenied {
reason: "revoke requires an authenticated did:web sender".into(),
});
}
Ok(revoke::v0_1::Response::builder()
.entry(Option::<revoke::v0_1::AclEntry>::None)
.try_into()
.expect("acl revoke response builder"))
})
.build();
println!("Trust Tasks server listening on http://127.0.0.1:3000/trust-tasks");
server.serve("127.0.0.1:3000").await?;
Ok(())
}
fn demo_identity() -> (Secret, String) {
const SEED: [u8; 32] = [7u8; 32];
let throwaway = Secret::generate_ed25519(None, Some(&SEED));
let pk_mb = throwaway
.get_public_keymultibase()
.expect("ed25519 public multikey");
let vm = format!("did:key:{pk_mb}#{pk_mb}");
let mut secret = Secret::generate_ed25519(Some(&vm), Some(&SEED));
secret.id = vm.clone();
let did = vm.split('#').next().expect("did:key prefix").to_string();
(secret, did)
}