initial create user
This commit is contained in:
@@ -71,8 +71,3 @@ tokio = "0.2.25"
|
||||
[dev-dependencies.reqwest]
|
||||
features = ["cookies"]
|
||||
version = "0.10.10"
|
||||
|
||||
[profile]
|
||||
[profile.release]
|
||||
lto = true
|
||||
#codegen-units = 1
|
||||
+5
-1
@@ -370,7 +370,11 @@ pub async fn webservice(
|
||||
.service(
|
||||
web::scope("/json")
|
||||
.route("/list_links/", web::post().to(views::index_json))
|
||||
.route("/list_users/", web::post().to(views::index_users_json)),
|
||||
.route("/list_users/", web::post().to(views::index_users_json))
|
||||
.route(
|
||||
"/create_user/",
|
||||
web::post().to(views::process_create_user_json),
|
||||
),
|
||||
)
|
||||
// login to the admin area
|
||||
.route("/login/", web::get().to(views::login))
|
||||
|
||||
@@ -23,7 +23,7 @@ pub trait UserDbOperations<T> {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl UserDbOperations<User> for User {
|
||||
impl UserDbOperations<Self> for User {
|
||||
async fn get_user(id: i64, server_config: &ServerConfig) -> Result<Self, ServerError> {
|
||||
let user = sqlx::query_as!(Self, "Select * from users where id = ? ", id)
|
||||
.fetch_one(&server_config.db_pool)
|
||||
@@ -186,7 +186,7 @@ pub trait LinkDbOperations<T> {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl LinkDbOperations<Link> for Link {
|
||||
impl LinkDbOperations<Self> for Link {
|
||||
async fn get_link_by_code(
|
||||
code: &str,
|
||||
server_config: &ServerConfig,
|
||||
|
||||
+46
-1
@@ -6,7 +6,7 @@ use shared::{
|
||||
apirequests::{
|
||||
general::{Filter, Operation, Ordering},
|
||||
links::{LinkOverviewColumns, LinkRequestForm},
|
||||
users::{UserOverviewColumns, UserRequestForm},
|
||||
users::{UserDelta, UserOverviewColumns, UserRequestForm},
|
||||
},
|
||||
datatypes::{Count, FullLink, Link, User},
|
||||
};
|
||||
@@ -389,6 +389,51 @@ pub async fn create_user(
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Create a new user and save it to the database
|
||||
///
|
||||
/// # Errors
|
||||
/// Fails with [`ServerError`] if access to the database fails, this user does not have permissions or the user already exists.
|
||||
#[instrument(skip(id))]
|
||||
pub async fn create_user_json(
|
||||
id: &Identity,
|
||||
data: &web::Json<UserDelta>,
|
||||
server_config: &ServerConfig,
|
||||
) -> Result<Item<User>, ServerError> {
|
||||
info!("Creating a User: {:?}", &data);
|
||||
let auth = authenticate(id, server_config).await?;
|
||||
|
||||
// Require a password on user creation!
|
||||
let password = match &data.password {
|
||||
Some(pass) => pass,
|
||||
None => {
|
||||
return Err(ServerError::User(
|
||||
"A new users does require a password".to_string(),
|
||||
))
|
||||
}
|
||||
};
|
||||
match auth {
|
||||
Role::Admin { user } => {
|
||||
let new_user = NewUser::new(
|
||||
data.username.clone(),
|
||||
data.email.clone(),
|
||||
password,
|
||||
&server_config.secret,
|
||||
)?;
|
||||
|
||||
new_user.insert_user(server_config).await?;
|
||||
|
||||
// querry the new user
|
||||
let new_user = get_user_by_name(&data.username, server_config).await?;
|
||||
Ok(Item {
|
||||
user,
|
||||
item: new_user,
|
||||
})
|
||||
}
|
||||
Role::Regular { .. } | Role::Disabled | Role::NotAuthenticated => {
|
||||
Err(ServerError::User("Permission denied!".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Take a [`actix_web::web::Form<NewUser>`] and update the corresponding entry in the database.
|
||||
/// The password is only updated if a new password of at least 4 characters is provided.
|
||||
/// The `user_id` is never changed.
|
||||
|
||||
+20
-1
@@ -14,7 +14,11 @@ use fluent_templates::LanguageIdentifier;
|
||||
use image::{DynamicImage, ImageOutputFormat, Luma};
|
||||
use qrcode::{render::svg, QrCode};
|
||||
use queries::{authenticate, Role};
|
||||
use shared::apirequests::{links::LinkRequestForm, users::UserRequestForm};
|
||||
use shared::apirequests::{
|
||||
general::SuccessMessage,
|
||||
links::LinkRequestForm,
|
||||
users::{UserDelta, UserRequestForm},
|
||||
};
|
||||
use tera::{Context, Tera};
|
||||
use tracing::{error, info, instrument, warn};
|
||||
|
||||
@@ -346,6 +350,21 @@ pub async fn process_signup(
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(id))]
|
||||
pub async fn process_create_user_json(
|
||||
config: web::Data<crate::ServerConfig>,
|
||||
form: web::Json<UserDelta>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
info!("Listing Users to Json api");
|
||||
match queries::create_user_json(&id, &form, &config).await {
|
||||
Ok(item) => Ok(HttpResponse::Ok().json2(&SuccessMessage {
|
||||
message: format!("Successfully saved user: {}", item.item.username),
|
||||
})),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(id))]
|
||||
pub async fn toggle_admin(
|
||||
data: web::Path<String>,
|
||||
|
||||
+115
-105
@@ -1,163 +1,173 @@
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.center {
|
||||
position: absolute;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -200px;
|
||||
margin-top: -200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 30px;
|
||||
color: #333;
|
||||
position: absolute;
|
||||
width: 600px;
|
||||
max-width: 100%;
|
||||
height: 400px;
|
||||
max-height: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -300px;
|
||||
margin-top: -200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 30px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.center input {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin: 5px;
|
||||
border-radius: 1px;
|
||||
border: 1px solid rgb(90, 90, 90);
|
||||
font-family: inherit;
|
||||
background-color: #eae9ea;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 1px;
|
||||
border: 1px solid rgb(90, 90, 90);
|
||||
font-family: inherit;
|
||||
background-color: #eae9ea;
|
||||
}
|
||||
|
||||
.center {
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
margin-left: -400px;
|
||||
margin-top: -300px;
|
||||
|
||||
.center table p {
|
||||
font-size: x-small;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
th, td {
|
||||
text-align: center;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
th,
|
||||
td {
|
||||
text-align: center;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
table tr:nth-child(even) {
|
||||
background-color: #eee;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
table tr:nth-child(odd) {
|
||||
background-color: #fff;
|
||||
}
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
table tr.filters input {
|
||||
background-image: url("/static/search.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
background-image: url("/static/search.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
table tr.filters td {
|
||||
padding:5px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
align-items:stretch;
|
||||
width:100%;
|
||||
height: 60px;
|
||||
}
|
||||
nav ol {
|
||||
display:flex;
|
||||
align-items: center;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
nav li a, nav li div.willkommen {
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
border-radius: 0 0 10px 10px;
|
||||
nav ol {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
nav li a,
|
||||
nav li div.willkommen {
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
nav li a {
|
||||
background: rgb(2,0,36);
|
||||
background: linear-gradient(180deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgb(0, 145, 174) 100%);
|
||||
background: rgb(2, 0, 36);
|
||||
background: linear-gradient(180deg, rgba(2, 0, 36, 1) 0%, rgba(9, 9, 121, 1) 35%, rgb(0, 145, 174) 100%);
|
||||
}
|
||||
|
||||
nav li {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
nav li a:hover {
|
||||
background: rgb(2,0,36);
|
||||
background: linear-gradient(180deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgb(60, 170, 255) 100%);
|
||||
background: rgb(2, 0, 36);
|
||||
background: linear-gradient(180deg, rgba(2, 0, 36, 1) 0%, rgba(9, 9, 121, 1) 35%, rgb(60, 170, 255) 100%);
|
||||
}
|
||||
|
||||
nav li {
|
||||
margin: 5px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
nav li div{
|
||||
background-color: burlywood;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
border-radius: 0 0 10px 10px;
|
||||
nav li div {
|
||||
background-color: burlywood;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
|
||||
svg {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
div.actions {
|
||||
margin-left:5px;
|
||||
display: flex;
|
||||
width:100%;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
flex-flow: row wrap;
|
||||
justify-content: center;
|
||||
margin-left: 5px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
color: #333;
|
||||
flex-flow: row wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
div.danger {
|
||||
background-color: rgb(235, 127, 77);
|
||||
font-size: smaller;
|
||||
border: 2px solid crimson;
|
||||
background-color: rgb(235, 127, 77);
|
||||
font-size: smaller;
|
||||
border: 2px solid crimson;
|
||||
}
|
||||
|
||||
div.danger h3 {
|
||||
width:100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a.button, div.actions input {
|
||||
width: 250px;
|
||||
display:block;
|
||||
padding: 15px;
|
||||
margin-left: 15px;
|
||||
text-align: center;
|
||||
border-radius: 1px;
|
||||
border: 1px solid rgb(90, 90, 90);
|
||||
font-family: inherit;
|
||||
background-color: #eae9ea;
|
||||
a.button,
|
||||
div.actions input {
|
||||
width: 250px;
|
||||
display: block;
|
||||
padding: 15px;
|
||||
margin-left: 15px;
|
||||
text-align: center;
|
||||
border-radius: 1px;
|
||||
border: 1px solid rgb(90, 90, 90);
|
||||
font-family: inherit;
|
||||
background-color: #eae9ea;
|
||||
}
|
||||
|
||||
div.editdialog {
|
||||
background-color: aliceblue;
|
||||
border: 5px solid rgb(90, 90, 90);
|
||||
}
|
||||
Reference in New Issue
Block a user