Add language switching, fix logout

This commit is contained in:
2021-08-12 15:48:02 +02:00
committed by dietrich
parent fa924a8e8c
commit 0a23b786b0
16 changed files with 220 additions and 85 deletions
+3
View File
@@ -234,6 +234,7 @@ pub async fn webservice(
// admin block
.service(
web::scope("/admin")
.route("/logout/", web::to(views::logout))
.service(
web::scope("/download")
.route("/png/{redirect_id}", web::get().to(views::download_png)),
@@ -241,6 +242,8 @@ pub async fn webservice(
.service(
web::scope("/json")
.route("/list_links/", web::post().to(views::index_json))
.route("/get_language/", web::get().to(views::get_language))
.route("/change_language/", web::post().to(views::set_language))
.route(
"/create_link/",
web::post().to(views::process_create_link_json),
+11 -7
View File
@@ -1,3 +1,5 @@
use std::str::FromStr;
use crate::{forms::LinkForm, Secret, ServerConfig, ServerError};
use argonautica::Hasher;
@@ -7,7 +9,7 @@ use serde::{Deserialize, Serialize};
use shared::{
apirequests::links::LinkDelta,
datatypes::{Count, Link, User},
datatypes::{Count, Lang, Link, User},
};
use sqlx::Row;
use tracing::{error, info, instrument};
@@ -22,7 +24,7 @@ pub trait UserDbOperations<T> {
async fn set_language(
self,
server_config: &ServerConfig,
new_language: &str,
new_language: Lang,
) -> Result<(), ServerError>;
async fn count_admins(server_config: &ServerConfig) -> Result<Count, ServerError>;
}
@@ -40,7 +42,7 @@ impl UserDbOperations<Self> for User {
email: row.email,
password: Secret::new(row.password),
role: row.role,
language: row.language,
language: Lang::from_str(&row.language).expect("Should parse"),
});
user.map_err(ServerError::Database)
}
@@ -63,7 +65,7 @@ impl UserDbOperations<Self> for User {
email: row.email,
password: Secret::new(row.password),
role: row.role,
language: row.language,
language: Lang::from_str(&row.language).expect("Should parse"),
});
user.map_err(ServerError::Database)
}
@@ -81,7 +83,8 @@ impl UserDbOperations<Self> for User {
email: r.get("email"),
password: Secret::new(r.get("password")),
role: r.get("role"),
language: r.get("language"),
language: Lang::from_str(r.get("language"))
.expect("should parse correctly"),
})
.collect()
});
@@ -124,11 +127,12 @@ impl UserDbOperations<Self> for User {
async fn set_language(
self,
server_config: &ServerConfig,
new_language: &str,
new_language: Lang,
) -> Result<(), ServerError> {
let lang_code = new_language.to_string();
sqlx::query!(
"UPDATE users SET language = ? where id = ?",
new_language,
lang_code,
self.id
)
.execute(&server_config.db_pool)
+10 -18
View File
@@ -1,3 +1,5 @@
use std::str::FromStr;
use actix_identity::Identity;
use actix_web::web;
use enum_map::EnumMap;
@@ -8,7 +10,7 @@ use shared::{
links::{LinkDelta, LinkOverviewColumns, LinkRequestForm},
users::{UserDelta, UserOverviewColumns, UserRequestForm},
},
datatypes::{Count, FullLink, Link, Secret, User},
datatypes::{Count, FullLink, Lang, Link, Secret, User},
};
use sqlx::Row;
use tracing::{info, instrument, warn};
@@ -129,7 +131,7 @@ pub async fn list_all_allowed(
email: v.get("uemail"),
password: Secret::new("invalid".to_string()),
role: v.get("urole"),
language: v.get("ulang"),
language: Lang::from_str(v.get("ulang")).expect("Should parse"),
},
clicks: Count {
number: v.get("counter"), /* count is never None */
@@ -242,7 +244,7 @@ pub async fn list_users(
email: v.get("email"),
password: Secret::new("".to_string()),
role: v.get("role"),
language: v.get("language"),
language: Lang::from_str(v.get("language")).expect("Should parse"),
})
.collect();
@@ -591,24 +593,14 @@ pub async fn toggle_admin(
#[instrument(skip(id))]
pub async fn set_language(
id: &Identity,
lang_code: &str,
lang_code: Lang,
server_config: &ServerConfig,
) -> Result<(), ServerError> {
match lang_code {
"de" | "en" => match authenticate(id, server_config).await? {
Role::Admin { user } | Role::Regular { user } => {
user.set_language(server_config, lang_code).await
}
Role::Disabled | Role::NotAuthenticated => {
Err(ServerError::User("Not Allowed".to_owned()))
}
},
_ => {
warn!("An invalid language was selected!");
Err(ServerError::User(
"This language is not supported!".to_owned(),
))
match authenticate(id, server_config).await? {
Role::Admin { user } | Role::Regular { user } => {
user.set_language(server_config, lang_code).await
}
Role::Disabled | Role::NotAuthenticated => Err(ServerError::User("Not Allowed".to_owned())),
}
}
+53 -12
View File
@@ -14,10 +14,13 @@ use fluent_templates::LanguageIdentifier;
use image::{DynamicImage, ImageOutputFormat, Luma};
use qrcode::QrCode;
use queries::{authenticate, Role};
use shared::apirequests::{
general::{Message, Status},
links::{LinkDelta, LinkRequestForm},
users::{LoginUser, UserDelta, UserRequestForm},
use shared::{
apirequests::{
general::{Message, Status},
links::{LinkDelta, LinkRequestForm},
users::{LoginUser, UserDelta, UserRequestForm},
},
datatypes::Lang,
};
use tracing::{error, info, instrument, warn};
@@ -38,7 +41,7 @@ fn redirect_builder(target: &str) -> HttpResponse {
}
#[instrument]
fn detect_language(request: &HttpRequest) -> Result<String, ServerError> {
fn detect_language(request: &HttpRequest) -> Result<Lang, ServerError> {
let requested = parse_accepted_languages(
request
.headers()
@@ -49,7 +52,9 @@ fn detect_language(request: &HttpRequest) -> Result<String, ServerError> {
ServerError::User("Failed to convert Accept_language to str".to_owned())
})?,
);
info!("accepted languages: {:?}", requested);
let available = convert_vec_str_to_langids_lossy(&["de", "en"]);
info!("available languages: {:?}", available);
let default: LanguageIdentifier = "en"
.parse()
.map_err(|_| ServerError::User("Failed to parse a langid.".to_owned()))?;
@@ -60,10 +65,18 @@ fn detect_language(request: &HttpRequest) -> Result<String, ServerError> {
Some(&default),
NegotiationStrategy::Filtering,
);
let languagecode = supported
.get(0)
.map_or("en".to_string(), std::string::ToString::to_string);
Ok(languagecode)
info!("supported languages: {:?}", supported);
if let Some(languagecode) = supported.get(0) {
info!("Supported Language: {}", languagecode);
Ok(languagecode
.to_string()
.parse()
.expect("Failed to parse 2 language"))
} else {
info!("Unsupported language using default!");
Ok("enEN".parse::<Lang>().unwrap())
}
}
#[instrument()]
@@ -201,14 +214,35 @@ pub async fn toggle_admin(
)))
}
#[instrument(skip(id))]
pub async fn get_language(
id: Option<Identity>,
config: web::Data<crate::ServerConfig>,
req: HttpRequest,
) -> Result<HttpResponse, ServerError> {
if let Some(id) = id {
let user = authenticate(&id, &config).await?;
match user {
Role::NotAuthenticated | Role::Disabled => {
Ok(HttpResponse::Ok().json2(&detect_language(&req)?))
}
Role::Regular { user } | Role::Admin { user } => {
Ok(HttpResponse::Ok().json2(&user.language))
}
}
} else {
Ok(HttpResponse::Ok().json2(&detect_language(&req)?))
}
}
#[instrument(skip(id))]
pub async fn set_language(
data: web::Path<String>,
data: web::Json<Lang>,
config: web::Data<crate::ServerConfig>,
id: Identity,
) -> Result<HttpResponse, ServerError> {
queries::set_language(&id, &data.0, &config).await?;
Ok(redirect_builder("/admin/index/"))
queries::set_language(&id, data.0, &config).await?;
Ok(HttpResponse::Ok().json2(&data.0))
}
#[instrument(skip(id))]
@@ -259,6 +293,13 @@ pub async fn process_login_json(
}
}
#[instrument(skip(id))]
pub async fn logout(id: Identity) -> Result<HttpResponse, ServerError> {
info!("Logging out the user");
id.forget();
Ok(redirect_builder("/app/"))
}
#[instrument()]
pub async fn redirect(
config: web::Data<crate::ServerConfig>,
+8 -1
View File
@@ -210,7 +210,14 @@ img.trashicon {
width: 0.5cm;
}
qrdownload {
.qrdownload {
display: flex;
vertical-align: middle;
}
.languageselector a {
height: 70%;
padding: 5px;
margin: 3px;
border-radius: 50%;
}