pub struct RequireAuthorizationLayer<UserId, User, Role = ()>(UserId, User, Role);
Expand description

A wrapper around tower_http::auth::RequireAuthorizationLayer which provides login authorization.

Tuple Fields§

§0: UserId§1: User§2: Role

Implementations§

source§

impl<UserId, User, Role> RequireAuthorizationLayer<UserId, User, Role>where Role: PartialOrd + PartialEq + Clone + Send + Sync + 'static, User: AuthUser<UserId, Role>,

source

pub fn login<ResBody>( ) -> RequireAuthorizationLayer<Login<UserId, User, ResBody, Role>>where ResBody: HttpBody + Default,

Authorizes requests by requiring a logged in user, otherwise it rejects with http::StatusCode::UNAUTHORIZED.

source

pub fn login_with_role<ResBody>( role_bounds: impl RangeBounds<Role> + Clone + Send + Sync + 'static ) -> RequireAuthorizationLayer<Login<UserId, User, ResBody, Role>>where ResBody: HttpBody + Default,

Authorizes requests by requiring a logged in user to have a specific range of roles, otherwise it rejects with http::StatusCode::UNAUTHORIZED.

source

pub fn login_or_redirect<ResBody>( login_url: Arc<Cow<'static, str>>, redirect_field_name: Option<Arc<Cow<'static, str>>> ) -> RequireAuthorizationLayer<Login<UserId, User, ResBody, Role>>where ResBody: HttpBody + Default,

Authorizes requests by requiring a logged in user, otherwise it redirects to the provided login URL.

If redirect_field_name is set to a value, the login page will receive the path it was redirected from in the URI query part. For example, attempting to visit a protected path /protected would redirect you to /login?next=/protected allowing you to know how to return the visitor to their requested page.

Examples found in repository?
web/src/main.rs (lines 107-110)
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
fn create_app(shared_state: Arc<AppState>) -> Router {
    let store = MemoryStore::new();
    let secret = rand::thread_rng().gen::<[u8; 128]>();
    let session_layer = SessionLayer::new(store, &secret).with_secure(false);

    let auth_layer = AuthLayer::new(shared_state.clone(), &secret);

    let login_url =
        Arc::new(format!("{}{}", shared_state.root_url_prefix, LoginPath.to_crumb()).into());
    Router::new()
        .route("/", get(root))
        .typed_get(list)
        .typed_get(list_post)
        .typed_get(list_post_raw)
        .typed_get(list_topics)
        .typed_get(list_post_eml)
        .typed_get(list_edit.layer(RequireAuth::login_with_role_or_redirect(
            Role::User..,
            Arc::clone(&login_url),
            Some(Arc::new("next".into())),
        )))
        .typed_post(
            {
                let shared_state = Arc::clone(&shared_state);
                move |path, session, user, payload| {
                    list_edit_POST(path, session, user, payload, State(shared_state))
                }
            }
            .layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(
            list_subscribers.layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(
            list_candidates.layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(help)
        .typed_get(auth::ssh_signin)
        .typed_post({
            let shared_state = Arc::clone(&shared_state);
            move |path, session, query, auth, body| {
                auth::ssh_signin_POST(path, session, query, auth, body, shared_state)
            }
        })
        .typed_get(logout_handler)
        .typed_post(logout_handler)
        .typed_get(
            {
                let shared_state = Arc::clone(&shared_state);
                move |path, session, user| settings(path, session, user, shared_state)
            }
            .layer(RequireAuth::login_or_redirect(
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_post(
            {
                let shared_state = Arc::clone(&shared_state);
                move |path, session, auth, body| {
                    settings_POST(path, session, auth, body, shared_state)
                }
            }
            .layer(RequireAuth::login_or_redirect(
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(
            user_list_subscription.layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_post(
            {
                let shared_state = Arc::clone(&shared_state);
                move |session, path, user, body| {
                    user_list_subscription_POST(session, path, user, body, shared_state)
                }
            }
            .layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .layer(auth_layer)
        .layer(session_layer)
        .with_state(shared_state)
}
source

pub fn login_with_role_or_redirect<ResBody>( role_bounds: impl RangeBounds<Role> + Clone + Send + Sync + 'static, login_url: Arc<Cow<'static, str>>, redirect_field_name: Option<Arc<Cow<'static, str>>> ) -> RequireAuthorizationLayer<Login<UserId, User, ResBody, Role>>where ResBody: HttpBody + Default,

Authorizes requests by requiring a logged in user to have a specific range of roles, otherwise it redirects to the provided login URL.

If redirect_field_name is set to a value, the login page will receive the path it was redirected from in the URI query part. For example, attempting to visit a protected path /protected would redirect you to /login?next=/protected allowing you to know how to return the visitor to their requested page.

Examples found in repository?
web/src/main.rs (lines 60-64)
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
fn create_app(shared_state: Arc<AppState>) -> Router {
    let store = MemoryStore::new();
    let secret = rand::thread_rng().gen::<[u8; 128]>();
    let session_layer = SessionLayer::new(store, &secret).with_secure(false);

    let auth_layer = AuthLayer::new(shared_state.clone(), &secret);

    let login_url =
        Arc::new(format!("{}{}", shared_state.root_url_prefix, LoginPath.to_crumb()).into());
    Router::new()
        .route("/", get(root))
        .typed_get(list)
        .typed_get(list_post)
        .typed_get(list_post_raw)
        .typed_get(list_topics)
        .typed_get(list_post_eml)
        .typed_get(list_edit.layer(RequireAuth::login_with_role_or_redirect(
            Role::User..,
            Arc::clone(&login_url),
            Some(Arc::new("next".into())),
        )))
        .typed_post(
            {
                let shared_state = Arc::clone(&shared_state);
                move |path, session, user, payload| {
                    list_edit_POST(path, session, user, payload, State(shared_state))
                }
            }
            .layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(
            list_subscribers.layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(
            list_candidates.layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(help)
        .typed_get(auth::ssh_signin)
        .typed_post({
            let shared_state = Arc::clone(&shared_state);
            move |path, session, query, auth, body| {
                auth::ssh_signin_POST(path, session, query, auth, body, shared_state)
            }
        })
        .typed_get(logout_handler)
        .typed_post(logout_handler)
        .typed_get(
            {
                let shared_state = Arc::clone(&shared_state);
                move |path, session, user| settings(path, session, user, shared_state)
            }
            .layer(RequireAuth::login_or_redirect(
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_post(
            {
                let shared_state = Arc::clone(&shared_state);
                move |path, session, auth, body| {
                    settings_POST(path, session, auth, body, shared_state)
                }
            }
            .layer(RequireAuth::login_or_redirect(
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_get(
            user_list_subscription.layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .typed_post(
            {
                let shared_state = Arc::clone(&shared_state);
                move |session, path, user, body| {
                    user_list_subscription_POST(session, path, user, body, shared_state)
                }
            }
            .layer(RequireAuth::login_with_role_or_redirect(
                Role::User..,
                Arc::clone(&login_url),
                Some(Arc::new("next".into())),
            )),
        )
        .layer(auth_layer)
        .layer(session_layer)
        .with_state(shared_state)
}

Auto Trait Implementations§

§

impl<UserId, User, Role> RefUnwindSafe for RequireAuthorizationLayer<UserId, User, Role>where Role: RefUnwindSafe, User: RefUnwindSafe, UserId: RefUnwindSafe,

§

impl<UserId, User, Role> Send for RequireAuthorizationLayer<UserId, User, Role>where Role: Send, User: Send, UserId: Send,

§

impl<UserId, User, Role> Sync for RequireAuthorizationLayer<UserId, User, Role>where Role: Sync, User: Sync, UserId: Sync,

§

impl<UserId, User, Role> Unpin for RequireAuthorizationLayer<UserId, User, Role>where Role: Unpin, User: Unpin, UserId: Unpin,

§

impl<UserId, User, Role> UnwindSafe for RequireAuthorizationLayer<UserId, User, Role>where Role: UnwindSafe, User: UnwindSafe, UserId: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more