///|
pub(all) enum RuntimeInvokeAuthorizationKind {
RuntimeInvokeAuthorized
RuntimeInvokeInvalidRequest
RuntimeInvokeUnknownCommand
RuntimeInvokeUnregisteredCommand
RuntimeInvokePermissionDenied
} derive(Debug, Eq)
///|
pub struct RuntimeInvokeAuthorization {
kind : RuntimeInvokeAuthorizationKind
route : String
window_label : String
origin : String
platform : String
permission : Permission?
registered : Bool
capability : String
reason : String
} derive(Debug, Eq)
///|
pub fn RuntimeInvokeAuthorizationKind::name(
self : RuntimeInvokeAuthorizationKind,
) -> String {
match self {
RuntimeInvokeAuthorized => "authorized"
RuntimeInvokeInvalidRequest => "invalid-request"
RuntimeInvokeUnknownCommand => "unknown-command"
RuntimeInvokeUnregisteredCommand => "unregistered-command"
RuntimeInvokePermissionDenied => "permission-denied"
}
}
///|
fn RuntimeInvokeAuthorization::allow(
request : InvokeRequest,
platform~ : String,
permission~ : Permission,
registered~ : Bool,
capability~ : String,
) -> RuntimeInvokeAuthorization {
{
kind: RuntimeInvokeAuthorized,
route: request.route(),
window_label: request.window_label(),
origin: request.origin(),
platform,
permission: Some(permission),
registered,
capability,
reason: "",
}
}
///|
fn RuntimeInvokeAuthorization::deny(
kind~ : RuntimeInvokeAuthorizationKind,
request : InvokeRequest,
platform? : String = "",
permission? : Permission,
registered~ : Bool,
reason~ : String,
) -> RuntimeInvokeAuthorization {
{
kind,
route: request.route(),
window_label: request.window_label(),
origin: request.origin(),
platform,
permission,
registered,
capability: "",
reason,
}
}
///|
fn RuntimeInvokeAuthorization::invalid(
request : InvokeRequest,
reason~ : String,
) -> RuntimeInvokeAuthorization {
RuntimeInvokeAuthorization::deny(
kind=RuntimeInvokeInvalidRequest,
request,
registered=false,
reason~,
)
}
///|
pub fn RuntimeInvokeAuthorization::kind(
self : RuntimeInvokeAuthorization,
) -> RuntimeInvokeAuthorizationKind {
self.kind
}
///|
pub fn RuntimeInvokeAuthorization::allowed(
self : RuntimeInvokeAuthorization,
) -> Bool {
self.kind is RuntimeInvokeAuthorized
}
///|
pub fn RuntimeInvokeAuthorization::route(
self : RuntimeInvokeAuthorization,
) -> String {
self.route
}
///|
pub fn RuntimeInvokeAuthorization::window_label(
self : RuntimeInvokeAuthorization,
) -> String {
self.window_label
}
///|
pub fn RuntimeInvokeAuthorization::origin(
self : RuntimeInvokeAuthorization,
) -> String {
self.origin
}
///|
pub fn RuntimeInvokeAuthorization::platform(
self : RuntimeInvokeAuthorization,
) -> String {
self.platform
}
///|
pub fn RuntimeInvokeAuthorization::permission(
self : RuntimeInvokeAuthorization,
) -> Permission? {
self.permission
}
///|
pub fn RuntimeInvokeAuthorization::registered(
self : RuntimeInvokeAuthorization,
) -> Bool {
self.registered
}
///|
pub fn RuntimeInvokeAuthorization::capability(
self : RuntimeInvokeAuthorization,
) -> String {
self.capability
}
///|
pub fn RuntimeInvokeAuthorization::reason(
self : RuntimeInvokeAuthorization,
) -> String {
self.reason
}
///|
pub fn RuntimeInvokeAuthorization::to_response(
self : RuntimeInvokeAuthorization,
id : String,
) -> InvokeResponse {
match self.kind {
RuntimeInvokeAuthorized => InvokeResponse::ok(id, "")
RuntimeInvokeInvalidRequest =>
InvokeResponse::invalid_request(id, self.reason)
RuntimeInvokeUnknownCommand | RuntimeInvokeUnregisteredCommand =>
InvokeResponse::unknown_command(id, self.route)
RuntimeInvokePermissionDenied =>
InvokeResponse::permission_denied(id, self.route)
}
}
///|
pub fn RuntimeInvokeAuthorization::to_json(
self : RuntimeInvokeAuthorization,
) -> String {
let permission = match self.permission {
Some(permission) => permission.name()
None => ""
}
[
"{",
"\"allowed\":\{self.allowed().json_bool()},",
"\"kind\":\{self.kind.name().json_string()},",
"\"route\":\{self.route.json_string()},",
"\"windowLabel\":\{self.window_label.json_string()},",
"\"origin\":\{self.origin.json_string()},",
"\"platform\":\{self.platform.json_string()},",
"\"permission\":\{permission.json_string()},",
"\"registered\":\{self.registered.json_bool()},",
"\"capability\":\{self.capability.json_string()},",
"\"reason\":\{self.reason.json_string()}",
"}",
].join("")
}
///|
pub fn RuntimePlan::authorize_invoke(
self : RuntimePlan,
request : InvokeRequest,
registered_routes? : Array[String] = [],
check_registered? : Bool = false,
) -> RuntimeInvokeAuthorization {
let request_problems = request.validate()
if !request_problems.is_empty() {
return RuntimeInvokeAuthorization::invalid(
request,
reason=request_problems[0],
)
}
let route = request.route()
let registered = registered_routes.contains(route)
match self.command_manifest().entry(route) {
None =>
RuntimeInvokeAuthorization::deny(
kind=RuntimeInvokeUnknownCommand,
request,
platform=self.platform(),
registered~,
reason="command is not declared: \{route}",
)
Some(entry) => {
if check_registered && !registered {
return RuntimeInvokeAuthorization::deny(
kind=RuntimeInvokeUnregisteredCommand,
request,
platform=self.platform(),
permission=entry.permission(),
registered~,
reason="command has no registered native handler: \{route}",
)
}
let decision = CapabilityPolicy::new(capabilities=self.capabilities()).evaluate(
window_label=request.window_label(),
permission=entry.permission(),
origin=request.origin(),
platform=self.platform(),
)
if decision.allowed() {
RuntimeInvokeAuthorization::allow(
request,
platform=self.platform(),
permission=entry.permission(),
registered~,
capability=decision.capability(),
)
} else {
RuntimeInvokeAuthorization::deny(
kind=RuntimeInvokePermissionDenied,
request,
platform=self.platform(),
permission=entry.permission(),
registered~,
reason=decision.reason(),
)
}
}
}
}