geforkt von mirrored/vaultwarden
don't use param for passing the redirect info
revert some changes and also rename catcher to `admin_login` to make its function clearer Co-authored-by: BlackDex <black.dex@gmail.com>
Dieser Commit ist enthalten in:
Ursprung
fa7dbedd5d
Commit
0aa33a2cb4
2 geänderte Dateien mit 36 neuen und 32 gelöschten Zeilen
|
@ -31,7 +31,6 @@ pub fn routes() -> Vec<Route> {
|
||||||
}
|
}
|
||||||
|
|
||||||
routes![
|
routes![
|
||||||
admin_login,
|
|
||||||
get_users_json,
|
get_users_json,
|
||||||
get_user_json,
|
get_user_json,
|
||||||
post_admin_login,
|
post_admin_login,
|
||||||
|
@ -61,19 +60,10 @@ pub fn catchers() -> Vec<Catcher> {
|
||||||
if !CONFIG.disable_admin_token() && !CONFIG.is_admin_token_set() {
|
if !CONFIG.disable_admin_token() && !CONFIG.is_admin_token_set() {
|
||||||
catchers![]
|
catchers![]
|
||||||
} else {
|
} else {
|
||||||
catchers![unauthorized]
|
catchers![admin_login]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[catch(401)]
|
|
||||||
fn unauthorized(request: &Request<'_>) -> Result<Redirect, Error> {
|
|
||||||
if request.format() == Some(&MediaType::JSON) {
|
|
||||||
err_code!("Authorization failed.", Status::Unauthorized.code);
|
|
||||||
}
|
|
||||||
let redirect = request.segments::<std::path::PathBuf>(0..).unwrap_or_default().display().to_string();
|
|
||||||
Ok(Redirect::to(admin_redirect_url(&redirect)))
|
|
||||||
}
|
|
||||||
|
|
||||||
static DB_TYPE: Lazy<&str> = Lazy::new(|| {
|
static DB_TYPE: Lazy<&str> = Lazy::new(|| {
|
||||||
DbConnType::from_url(&CONFIG.database_url())
|
DbConnType::from_url(&CONFIG.database_url())
|
||||||
.map(|t| match t {
|
.map(|t| match t {
|
||||||
|
@ -102,10 +92,6 @@ fn admin_path() -> String {
|
||||||
format!("{}{}", CONFIG.domain_path(), ADMIN_PATH)
|
format!("{}{}", CONFIG.domain_path(), ADMIN_PATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn admin_redirect_url(redirect: &str) -> String {
|
|
||||||
format!("{}/?redirect=/{}", admin_path(), redirect)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct IpHeader(Option<String>);
|
struct IpHeader(Option<String>);
|
||||||
|
|
||||||
|
@ -134,24 +120,31 @@ fn admin_url() -> String {
|
||||||
|
|
||||||
#[derive(Responder)]
|
#[derive(Responder)]
|
||||||
enum AdminResponse {
|
enum AdminResponse {
|
||||||
|
#[response(status = 200)]
|
||||||
|
Ok(ApiResult<Html<String>>),
|
||||||
#[response(status = 401)]
|
#[response(status = 401)]
|
||||||
Unauthorized(ApiResult<Html<String>>),
|
Unauthorized(ApiResult<Html<String>>),
|
||||||
#[response(status = 429)]
|
#[response(status = 429)]
|
||||||
TooManyRequests(ApiResult<Html<String>>),
|
TooManyRequests(ApiResult<Html<String>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/?<_redirect..>")]
|
#[catch(401)]
|
||||||
fn admin_login(_redirect: &str) -> ApiResult<Html<String>> {
|
fn admin_login(request: &Request<'_>) -> ApiResult<Html<String>> {
|
||||||
render_admin_login(None)
|
if request.format() == Some(&MediaType::JSON) {
|
||||||
|
err_code!("Authorization failed.", Status::Unauthorized.code);
|
||||||
|
}
|
||||||
|
let redirect = request.segments::<std::path::PathBuf>(0..).unwrap_or_default().display().to_string();
|
||||||
|
render_admin_login(None, Some(redirect))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_admin_login(msg: Option<&str>) -> ApiResult<Html<String>> {
|
fn render_admin_login(msg: Option<&str>, redirect: Option<String>) -> ApiResult<Html<String>> {
|
||||||
// If there is an error, show it
|
// If there is an error, show it
|
||||||
let msg = msg.map(|msg| format!("Error: {msg}"));
|
let msg = msg.map(|msg| format!("Error: {msg}"));
|
||||||
let json = json!({
|
let json = json!({
|
||||||
"page_content": "admin/login",
|
"page_content": "admin/login",
|
||||||
"version": VERSION,
|
"version": VERSION,
|
||||||
"error": msg,
|
"error": msg,
|
||||||
|
"redirect": redirect,
|
||||||
"urlpath": CONFIG.domain_path()
|
"urlpath": CONFIG.domain_path()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -163,25 +156,25 @@ fn render_admin_login(msg: Option<&str>) -> ApiResult<Html<String>> {
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct LoginForm {
|
struct LoginForm {
|
||||||
token: String,
|
token: String,
|
||||||
|
redirect: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/?<redirect>", data = "<data>")]
|
#[post("/", data = "<data>")]
|
||||||
fn post_admin_login(
|
fn post_admin_login(data: Form<LoginForm>, cookies: &CookieJar<'_>, ip: ClientIp) -> Result<Redirect, AdminResponse> {
|
||||||
data: Form<LoginForm>,
|
|
||||||
redirect: &str,
|
|
||||||
cookies: &CookieJar<'_>,
|
|
||||||
ip: ClientIp,
|
|
||||||
) -> Result<Redirect, AdminResponse> {
|
|
||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
|
let redirect = data.redirect;
|
||||||
|
|
||||||
if crate::ratelimit::check_limit_admin(&ip.ip).is_err() {
|
if crate::ratelimit::check_limit_admin(&ip.ip).is_err() {
|
||||||
return Err(AdminResponse::TooManyRequests(render_admin_login(Some("Too many requests, try again later."))));
|
return Err(AdminResponse::TooManyRequests(render_admin_login(
|
||||||
|
Some("Too many requests, try again later."),
|
||||||
|
redirect,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the token is invalid, redirect to login page
|
// If the token is invalid, redirect to login page
|
||||||
if !_validate_token(&data.token) {
|
if !_validate_token(&data.token) {
|
||||||
error!("Invalid admin token. IP: {}", ip.ip);
|
error!("Invalid admin token. IP: {}", ip.ip);
|
||||||
Err(AdminResponse::Unauthorized(render_admin_login(Some("Invalid admin token, please try again."))))
|
Err(AdminResponse::Unauthorized(render_admin_login(Some("Invalid admin token, please try again."), redirect)))
|
||||||
} else {
|
} else {
|
||||||
// If the token received is valid, generate JWT and save it as a cookie
|
// If the token received is valid, generate JWT and save it as a cookie
|
||||||
let claims = generate_admin_claims();
|
let claims = generate_admin_claims();
|
||||||
|
@ -195,7 +188,11 @@ fn post_admin_login(
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
cookies.add(cookie);
|
cookies.add(cookie);
|
||||||
Ok(Redirect::to(format!("{}{}", admin_path(), redirect)))
|
if let Some(redirect) = redirect {
|
||||||
|
Ok(Redirect::to(format!("{}{}", admin_path(), redirect)))
|
||||||
|
} else {
|
||||||
|
Err(AdminResponse::Ok(render_admin_page()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,12 +244,16 @@ impl AdminTemplateData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
fn render_admin_page() -> ApiResult<Html<String>> {
|
||||||
fn admin_page(_token: AdminToken) -> ApiResult<Html<String>> {
|
|
||||||
let text = AdminTemplateData::new().render()?;
|
let text = AdminTemplateData::new().render()?;
|
||||||
Ok(Html(text))
|
Ok(Html(text))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
fn admin_page(_token: AdminToken) -> ApiResult<Html<String>> {
|
||||||
|
render_admin_page()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
struct InviteData {
|
struct InviteData {
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
<h6 class="mb-0 text-white">Authentication key needed to continue</h6>
|
<h6 class="mb-0 text-white">Authentication key needed to continue</h6>
|
||||||
<small>Please provide it below:</small>
|
<small>Please provide it below:</small>
|
||||||
|
|
||||||
<form class="form-inline" method="post">
|
<form class="form-inline" method="post" action="{{urlpath}}/admin">
|
||||||
<input type="password" class="form-control w-50 mr-2" name="token" placeholder="Enter admin token" autofocus="autofocus">
|
<input type="password" class="form-control w-50 mr-2" name="token" placeholder="Enter admin token" autofocus="autofocus">
|
||||||
|
{{#if redirect}}
|
||||||
|
<input type="hidden" id="redirect" name="redirect" value="/{{redirect}}">
|
||||||
|
{{/if}}
|
||||||
<button type="submit" class="btn btn-primary">Enter</button>
|
<button type="submit" class="btn btn-primary">Enter</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
Laden …
In neuem Issue referenzieren