Skip to content

Commit

Permalink
can edit user in webconsole
Browse files Browse the repository at this point in the history
  • Loading branch information
eltorio committed May 22, 2024
1 parent 76a28b5 commit 2e79ad9
Show file tree
Hide file tree
Showing 14 changed files with 379 additions and 42 deletions.
59 changes: 29 additions & 30 deletions libs/state/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ use sqlx::{
sqlite::{Sqlite, SqliteConnectOptions, SqliteJournalMode, SqlitePool},
QueryBuilder,
};
use utils::Group;
use utils::Peer;
use std::env;
use std::path::Path;
use utils::guid_into_uuid;
use utils::types::AddressBook;
use utils::AbPeer;
use utils::AbTag;
use utils::Group;
use utils::Peer;
use utils::UpdateUserRequest;
use utils::UserListResponse;

Expand Down Expand Up @@ -102,7 +103,10 @@ impl Database {
pub async fn find_user_by_name(
&self,
username: &str,
) -> (DatabaseConnection, Option<(UserId, Option<String>, DatabaseUserInfo)>) {
) -> (
DatabaseConnection,
Option<(UserId, Option<String>, DatabaseUserInfo)>,
) {
let mut conn = DatabaseConnection {
conn: self.pool.acquire().await.unwrap(),
};
Expand Down Expand Up @@ -1146,19 +1150,23 @@ impl Database {
let mut conn = self.pool.acquire().await.unwrap();
let mut query = "UPDATE user SET ".to_string();
let mut query_params = Vec::new();
if user_parameters.name.is_some() {
if user_parameters.name.is_some() && user_parameters.name.clone().unwrap().len() > 0 {
query.push_str("name = ?, ");
query_params.push(user_parameters.name.unwrap());
}
if user_parameters.email.is_some() {
if user_parameters.email.is_some() && user_parameters.email.clone().unwrap().len() > 0 {
query.push_str("email = ?, ");
query_params.push(user_parameters.email.unwrap());
}
if user_parameters.note.is_some() {
if user_parameters.note.is_some() && user_parameters.note.clone().unwrap().len() > 0 {
query.push_str("note = ?, ");
query_params.push(user_parameters.note.unwrap());
}
if user_parameters.password.is_some() && user_parameters.confirm_password.is_some() {
if user_parameters.password.is_some()
&& user_parameters.confirm_password.is_some()
&& user_parameters.password.clone().unwrap().len() > 0
&& user_parameters.confirm_password.clone().unwrap().len() > 0
{
let password = user_parameters.password.unwrap();
let confirm_password = user_parameters.confirm_password.unwrap();
if password == confirm_password {
Expand All @@ -1173,7 +1181,7 @@ impl Database {
}
if let Some(is_admin) = user_parameters.is_admin {
query.push_str("role = ?, ");
query_params.push(is_admin.to_string());
query_params.push(if is_admin { "1" } else { "0" }.to_string());
}
query.pop();
query.pop();
Expand All @@ -1185,12 +1193,15 @@ impl Database {
for param in query_params {
res = res.bind(param);
}
let _res = res.bind(user_id).execute(&mut conn).await;

let res = res.bind(user_id).execute(&mut conn).await;
if res.is_err() {
log::error!("user_update error: {:?}", res);
return None;
}
Some(())
}

pub async fn get_all_peers(&self) -> Option<Vec<Peer>> {
pub async fn get_all_peers(&self) -> Option<Vec<Peer>> {
let mut conn = self.pool.acquire().await.unwrap();
let res = sqlx::query!(
r#"
Expand All @@ -1209,7 +1220,7 @@ impl Database {
.await
.ok()?;

let mut peers:Vec<Peer> = Vec::new();
let mut peers: Vec<Peer> = Vec::new();
for row in res {
let uuid = guid_into_uuid(row.guid).unwrap_or("".to_string());
let peer_info = serde_json::from_str::<utils::PeerInfo>(&row.info);
Expand All @@ -1218,7 +1229,7 @@ impl Database {
return None;
}
let peer_info = peer_info.unwrap();
peers.push(Peer{
peers.push(Peer {
id: row.id,
guid: uuid,
info: peer_info,
Expand All @@ -1230,7 +1241,7 @@ impl Database {
Some(peers)
}

pub async fn get_groups(&self, offset: u32, page_size: u32)->Option<Vec<Group>>{
pub async fn get_groups(&self, offset: u32, page_size: u32) -> Option<Vec<Group>> {
let mut conn = self.pool.acquire().await.unwrap();
let res = sqlx::query!(
r#"
Expand All @@ -1252,33 +1263,21 @@ impl Database {
.fetch_all(&mut conn)
.await
.ok()?;
let mut groups:Vec<Group> = Vec::new();
let mut groups: Vec<Group> = Vec::new();
for row in res {
let guid = guid_into_uuid(row.guid).unwrap_or("".to_string());
let team = guid_into_uuid(row.team).unwrap_or("".to_string());
groups.push(Group{
let team = guid_into_uuid(row.team).unwrap_or("".to_string());
groups.push(Group {
guid: guid,
name: row.name,
team: team,
note: row.note,
created_at: row.created_at.into(),
access_to: Vec::<String>::new(),
accessed_from: Vec::<String>::new(),
info: row.info
info: row.info,
});
}
Some(groups)

}
}

fn guid_into_uuid(guid: Vec<u8>) -> Option<String> {
let guid_u8: Result<[u8; 16], _> = guid.try_into();
if guid_u8.is_err() {
log::error!("get_ab_personal_guid error: {:?}", guid_u8);
return None;
}
let guid_u8: [u8; 16] = guid_u8.unwrap();
let guid = Uuid::from_bytes(guid_u8).to_string();
Some(guid)
}
8 changes: 7 additions & 1 deletion libs/state/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use oauth2::ProviderConfig;

use tokio::sync::RwLock;
use utils::{
AbPeer, AbTag, AddUserRequest, AddressBook, Group, OidcState, Peer, PeerInfo, Token, UpdateUserRequest, UserListResponse
AbPeer, AbTag, AddUserRequest, AddressBook, Group, OidcState, Peer, Token, UpdateUserRequest, UserListResponse
};

pub struct ApiState {
Expand Down Expand Up @@ -169,6 +169,7 @@ impl ApiState {
utils::UserInfo {
name: username.to_string(),
email,
admin: db_user_info.admin,
..Default::default()
},
access_token,
Expand Down Expand Up @@ -319,6 +320,11 @@ impl ApiState {
state_users.get(&user.user_id).map(|ui| ui.username.clone())
}

pub async fn is_current_user_admin(&self, user: &AuthenticatedUserInfo) -> Option<bool> {
let state_users = self.users.read().await;
state_users.get(&user.user_id).map(|ui| ui.admin)
}

pub async fn with_user_info<R>(
&self,
user_id: &UserId,
Expand Down
23 changes: 23 additions & 0 deletions libs/utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub use tokens::Token;
pub use bearer::{BearerAuthToken, CookieAuthToken, MixedAuthToken, IntoToken};
// pub use address_book::AddressBook;
pub use types::*;
use uuid::Uuid;

#[macro_export]
macro_rules! unwrap_or_return {
Expand Down Expand Up @@ -46,3 +47,25 @@ macro_rules! include_png_as_base64 {
}
};
}

pub fn guid_into_uuid(guid: Vec<u8>) -> Option<String> {
let guid_u8: Result<[u8; 16], _> = guid.try_into();
if guid_u8.is_err() {
log::error!("get_ab_personal_guid error: {:?}", guid_u8);
return None;
}
let guid_u8: [u8; 16] = guid_u8.unwrap();
let guid = Uuid::from_bytes(guid_u8).to_string();
Some(guid)
}

pub fn uuid_into_guid(uuid: &str) -> Option<Vec<u8>> {
let uuid = Uuid::parse_str(uuid);
if uuid.is_err() {
log::error!("uuid_into_guid error: {:?}", uuid);
return None;
}
let uuid = uuid.unwrap();
let guid = uuid.as_bytes().to_vec();
Some(guid)
}
3 changes: 3 additions & 0 deletions libs/utils/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ pub struct UserInfo {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
pub admin: bool
}

#[derive(Serialize, Debug, JsonSchema)]
Expand Down Expand Up @@ -400,6 +401,7 @@ pub struct User {

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
pub struct UpdateUserRequest {
pub uuid: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
Expand All @@ -420,6 +422,7 @@ pub struct UpdateUserRequest {
impl Default for UpdateUserRequest {
fn default() -> Self {
UpdateUserRequest {
uuid: uuid::Uuid::new_v4().to_string(),
name: None,
password: None,
confirm_password: None,
Expand Down
24 changes: 19 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ use rocket::{
};
use state::{ApiState, UserPasswordInfo};
use utils::{
include_png_as_base64, unwrap_or_return, AbTagRenameRequest, AddUserRequest, AddressBook,
EnableUserRequest, Group, GroupsResponse, OidcSettingsResponse, PeersResponse,
SoftwareResponse, SoftwareVersionResponse, UpdateUserRequest, UserList,
include_png_as_base64, unwrap_or_return, uuid_into_guid, AbTagRenameRequest, AddUserRequest, AddressBook, EnableUserRequest, Group, GroupsResponse, OidcSettingsResponse, PeersResponse, SoftwareResponse, SoftwareVersionResponse, UpdateUserRequest, UserList

Check warning on line 39 in src/lib.rs

View workflow job for this annotation

GitHub Actions / build (x86_64-unknown-linux-gnu, ubuntu-latest)

unused import: `Group`
};
use utils::{
AbGetResponse, AbRequest, AuditRequest, CurrentUserRequest, CurrentUserResponse,
Expand Down Expand Up @@ -397,6 +395,11 @@ async fn users(
log::debug!("users");
state.check_maintenance().await;

let email = if email.is_some() && email.unwrap().is_empty() {
None
} else {
email
};
let res = state.get_all_users(name, email, current, pageSize).await;
if res.is_none() {
return Err(status::NotFound::<()>(()));
Expand Down Expand Up @@ -1001,19 +1004,30 @@ async fn user_enable(
#[openapi(tag = "user")]
#[put("/api/user", format = "application/json", data = "<request>")]
async fn user_update(
state: &State<ApiState>,
state: &State<ApiState>,
user: AuthenticatedUser,
request: Json<UpdateUserRequest>,
) -> Result<Json<UsersResponse>, status::Unauthorized<()>> {
log::debug!("update_user");
state.check_maintenance().await;
let mut guid = uuid_into_guid(request.0.uuid.as_str());
if guid.is_none() {
guid = Some(user.info.user_id.clone());
}

let guid = guid.unwrap();
let is_admin = state.is_current_user_admin(&user.info).await.unwrap_or(false);

if !is_admin && user.info.user_id != guid {
return Err(status::Unauthorized::<()>(()));
}
let response = UsersResponse {
msg: "success".to_string(),
total: 1,
data: "[{}]".to_string(),
};
let user_update = request.0;
state.user_update(user.info.user_id, user_update).await;
state.user_update(guid, user_update).await;
Ok(Json(response))
}

Expand Down
1 change: 1 addition & 0 deletions swagger-codegen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ if [ "$response" -eq 200 ]; then
curl http://127.0.0.1:21114/openapi.json >webconsole/src/api/openapi.json &&
docker run --rm -v ${PWD}:/local swaggerapi/swagger-codegen-cli-v3 generate -i file:///local/webconsole/src/api/openapi.json --additional-properties modelPropertyNaming=snake_case -l typescript-axios -o /local/webconsole/src/api &&
sed -ibak -e 's/confirm_password/\"confirm-password\"/' webconsole/src/api/models/add-user-request.ts &&
sed -ibak -e 's/confirm_password/\"confirm-password\"/' webconsole/src/api/models/update-user-request.ts &&
sed -ibak -e 's/device_info/\"deviceInfo\"/' webconsole/src/api/models/oidc-auth-request.ts &&
rm webconsole/src/api/models/*tsbak
else
Expand Down
6 changes: 6 additions & 0 deletions webconsole/src/api/models/current-user-response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@ export interface CurrentUserResponse {
* @memberof CurrentUserResponse
*/
email?: string | null;

/**
* @type {boolean}
* @memberof CurrentUserResponse
*/
admin: boolean;
}
8 changes: 7 additions & 1 deletion webconsole/src/api/models/update-user-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
*/
export interface UpdateUserRequest {

/**
* @type {string}
* @memberof UpdateUserRequest
*/
uuid: string;

/**
* @type {string}
* @memberof UpdateUserRequest
Expand All @@ -36,7 +42,7 @@ export interface UpdateUserRequest {
* @type {string}
* @memberof UpdateUserRequest
*/
confirm_password?: string | null;
"confirm-password"?: string | null;

/**
* @type {string}
Expand Down
6 changes: 6 additions & 0 deletions webconsole/src/api/models/user-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,10 @@ export interface UserInfo {
* @memberof UserInfo
*/
email?: string | null;

/**
* @type {boolean}
* @memberof UserInfo
*/
admin: boolean;
}
14 changes: 14 additions & 0 deletions webconsole/src/api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,7 @@
"UserInfo": {
"type": "object",
"required": [
"admin",
"name"
],
"properties": {
Expand All @@ -1551,6 +1552,9 @@
"email": {
"type": "string",
"nullable": true
},
"admin": {
"type": "boolean"
}
}
},
Expand Down Expand Up @@ -1620,6 +1624,7 @@
"CurrentUserResponse": {
"type": "object",
"required": [
"admin",
"error",
"name"
],
Expand All @@ -1633,6 +1638,9 @@
"email": {
"type": "string",
"nullable": true
},
"admin": {
"type": "boolean"
}
}
},
Expand Down Expand Up @@ -1958,7 +1966,13 @@
},
"UpdateUserRequest": {
"type": "object",
"required": [
"uuid"
],
"properties": {
"uuid": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
Expand Down
Loading

0 comments on commit 2e79ad9

Please sign in to comment.