1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! `Policy<M>` — explicit authorization (A9).
//!
//! Authorization stays explicit (PROGRAM.md). A policy is a type that
//! decides whether a user may perform an action on a resource. The
//! application writes the policy methods; the framework provides the
//! `Auth::authorize` seam.
//!
//! # Example
//!
//! ```ignore
//! #[policy(Link)]
//! pub struct LinkPolicy;
//!
//! impl LinkPolicy {
//! pub fn view(user: &User, _link: &Link) -> bool { true }
//! pub fn update(user: &User, link: &Link) -> bool { user.id == link.user_id }
//! }
//!
//! impl arcature::Policy<Link> for LinkPolicy {
//! type User = User;
//! fn check(user: &User, action: &str, link: &Link) -> bool {
//! match action {
//! "view" => Self::view(user, link),
//! "update" => Self::update(user, link),
//! _ => false,
//! }
//! }
//! }
//!
//! async fn show(auth: Auth<User>, link: Bound<Link>) -> Result<Page<ShowLinkPage>> {
//! auth.authorize::<LinkPolicy>("view", &link)?;
//! // ...
//! }
//! ```
//!
//! # Binding does NOT imply authorization
//!
//! `Bound<T>` loads the model; `Auth::authorize` checks the policy. These
//! are separate steps. Authorization is never automatic.
use crateDxComponent;
/// A typed authorization error.
/// A policy for resource type `M`.
///
/// The application implements this for its policy type. The `check` method
/// receives the authenticated user, an action name (e.g. `"view"`,
/// `"update"`), and the resource, and returns whether the action is
/// allowed.
///
/// The policy type also implements [`DxComponent`] (generated by the
/// `#[policy]` macro) so `arc services` / `arc check` can inspect it
/// without runtime reflection.