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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//! Deprecated compatibility re-exports. Use the four modules named below.
//!
//! This file used to hold four unrelated concerns in ~900 lines under a name
//! that revealed none of them -- `dx` abbreviates "developer experience",
//! which names a goal rather than a thing. Each concern now lives in a module
//! named after what is in it:
//!
//! | Was `auth::dx::` | Is now |
//! |---|---|
//! | `Auth`, `OptionalAuth`, `Current`, `OptionalCurrent`, `AuthManager`, `LoginBuilder`, `AuthError`, `UserLoader` | [`crate::auth::extract`] |
//! | `Session`, `SessionError` | [`crate::auth::session_api`] |
//! | `Flash`, `FlashMessage`, `FlashLevel`, `FlashError` | [`crate::auth::flash`] |
//! | `Policy`, `AuthzError`, `Auth::authorize` | [`crate::auth::policy`] |
//!
//! Nothing here is a new type: every name below resolves to exactly the type
//! it always did, so code written against `arcature::auth::dx` keeps
//! compiling. The module is scheduled for removal in `0.2.0`. The shortest
//! fix is to delete the `dx` segment -- `arcature::auth::Auth` and the
//! crate-root `arcature::Auth` are unchanged and are not deprecated.
//!
//! # Why some of these warn and some do not
//!
//! rustc ignores `#[deprecated]` on a `pub use` (rust-lang/rust#30827), so a
//! re-export cannot carry a deprecation of its own. Every item that can be
//! spelled as a deprecated type alias instead is, and warns on use. The
//! exceptions are the two traits, which have no alias form, and the three
//! tuple structs with public fields -- `Auth`, `OptionalAuth` and
//! `SessionError` -- because a type alias cannot be used as a tuple-struct
//! constructor or pattern, so aliasing them would stop `Auth(user)` and
//! `let Auth(user) = ..` compiling. Keeping those callers working matters
//! more than warning them, and this page is their notice.
//!
//! # The compatibility contract
//!
//! Every name this module ever exported, spelled through `auth::dx`. This is
//! a compiled test rather than an illustration: if it stops compiling, a
//! `0.1.0` application stops compiling too, and the release stops being a
//! patch. It warns loudly when run -- that is the point.
//!
//! ```
//! use arcature::auth::AuthUser;
//! use arcature::auth::dx::{
//! Auth, AuthError, AuthManager, AuthzError, Current, Flash, FlashError, FlashLevel,
//! FlashMessage, LoginBuilder, OptionalAuth, OptionalCurrent, Policy, Session, SessionError,
//! UserLoader,
//! };
//!
//! struct User {
//! id: i64,
//! }
//!
//! impl AuthUser for User {
//! type Id = i64;
//! fn id(&self) -> &i64 {
//! &self.id
//! }
//! }
//!
//! // A loader written against the old path still names the trait the
//! // extractors resolve from its new home.
//! impl UserLoader<()> for User {
//! type Error = std::convert::Infallible;
//! async fn load_user(id: &i64, _state: &()) -> Result<Option<Self>, Self::Error> {
//! Ok(Some(User { id: *id }))
//! }
//! }
//!
//! struct Doc;
//! struct DocPolicy;
//!
//! // Likewise a policy.
//! impl Policy<Doc> for DocPolicy {
//! type User = User;
//! fn check(_user: &User, action: &str, _resource: &Doc) -> bool {
//! action == "view"
//! }
//! }
//!
//! // The four names that only ever appear in type position.
//! fn types(_m: AuthManager<User>, _b: LoginBuilder<'_, User>, _s: Session, _f: Flash) {}
//!
//! // Tuple structs, constructed and destructured exactly as at 0.1.0.
//! let auth = Auth(User { id: 7 });
//! assert_eq!(auth.user().id, 7);
//! let OptionalAuth(absent) = OptionalAuth::<User>(None);
//! assert!(absent.is_none());
//! assert_eq!(SessionError("boom".into()).to_string(), "session error: boom");
//!
//! // The golden-path aliases name the same extractor as before.
//! let _current: Current<User> = auth;
//! let _optional: OptionalCurrent<User> = OptionalAuth::<User>(None);
//!
//! // Enum variants, in expression and in pattern.
//! assert_eq!(FlashLevel::Success, arcature::auth::FlashLevel::Success);
//! assert!(matches!(AuthError::Session(String::new()), AuthError::Session(_)));
//! assert!(matches!(FlashError::Session(String::new()), FlashError::Session(_)));
//!
//! // A named-field struct.
//! let message = FlashMessage { level: FlashLevel::Info, message: "hi".into() };
//! assert_eq!(message.message, "hi");
//!
//! // The authorization seam, reached from the old path.
//! let auth = Auth(User { id: 1 });
//! assert!(auth.authorize::<Doc, DocPolicy>("view", &Doc).is_ok());
//! assert_eq!(
//! auth.authorize::<Doc, DocPolicy>("delete", &Doc),
//! Err(AuthzError::Forbidden),
//! );
//! ```
// The whole module exists to name items that have moved, so every reference
// to a moved item inside it is deliberate.
// --- Extractors -> `crate::auth::extract` -----------------------------------
// Plain re-exports: `Auth` and `OptionalAuth` are tuple structs with public
// fields, and `UserLoader` is a trait. See the module docs.
pub use crate;
/// Deprecated. Moved to [`crate::auth::extract::AuthManager`].
pub type AuthManager<U> = crateAuthManager;
/// Deprecated. Moved to [`crate::auth::extract::LoginBuilder`].
pub type LoginBuilder<'a, U> = crateLoginBuilder;
/// Deprecated. Moved to [`crate::auth::extract::Current`].
pub type Current<U> = crateCurrent;
/// Deprecated. Moved to [`crate::auth::extract::OptionalCurrent`].
pub type OptionalCurrent<U> = crateOptionalCurrent;
/// Deprecated. Moved to [`crate::auth::extract::AuthError`].
pub type AuthError = crateAuthError;
// --- Session API -> `crate::auth::session_api` ------------------------------
// A plain re-export: `SessionError` is a tuple struct with a public field.
pub use crateSessionError;
/// Deprecated. Moved to [`crate::auth::session_api::Session`].
pub type Session = crateSession;
// --- Flash -> `crate::auth::flash` ------------------------------------------
/// Deprecated. Moved to [`crate::auth::flash::Flash`].
pub type Flash = crateFlash;
/// Deprecated. Moved to [`crate::auth::flash::FlashMessage`].
pub type FlashMessage = crateFlashMessage;
/// Deprecated. Moved to [`crate::auth::flash::FlashLevel`].
pub type FlashLevel = crateFlashLevel;
/// Deprecated. Moved to [`crate::auth::flash::FlashError`].
pub type FlashError = crateFlashError;
// --- Authorization -> `crate::auth::policy` ---------------------------------
// A plain re-export: `Policy` is a trait and has no alias form.
pub use cratePolicy;
/// Deprecated. Moved to [`crate::auth::policy::AuthzError`].
pub type AuthzError = crateAuthzError;