225 lines
8.0 KiB
Rust
225 lines
8.0 KiB
Rust
use async_trait::async_trait;
|
|
use log::{debug, warn};
|
|
use rear::depot::prelude::*;
|
|
use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, ModelTrait, Set};
|
|
use serde_json::Value;
|
|
|
|
use crate::models::UserRepository;
|
|
|
|
#[async_trait]
|
|
impl DepotRepository for UserRepository {
|
|
type Key = i64;
|
|
|
|
fn key_from_string(&self, s: String) -> Option<Self::Key> {
|
|
if let Ok(i) = s.parse::<i64>() {
|
|
Some(i)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
async fn info(&self, _: &RepositoryContext) -> RepositoryInfo {
|
|
RepoInfo {
|
|
name: "User",
|
|
lookup_key: "id",
|
|
display_list: &["id", "username"],
|
|
fields: &[
|
|
"username",
|
|
"password",
|
|
"first_name",
|
|
"last_name",
|
|
"email",
|
|
"is_staff",
|
|
"is_active",
|
|
"is_superuser",
|
|
],
|
|
// fields_readonly: &["last_login", "date_joined"]
|
|
}
|
|
.build()
|
|
.set_widget(
|
|
"password",
|
|
Widget::widget("/admin/widgets/password_change.jinja").as_password(),
|
|
)
|
|
.set_widget("is_staff", Widget::checkbox())
|
|
.set_widget("is_active", Widget::checkbox())
|
|
.set_widget("is_superuser", Widget::checkbox())
|
|
}
|
|
|
|
async fn get(&self, model: &RepositoryContext, id: &Self::Key) -> RepositoryResult {
|
|
let id: i32 = *id as i32; // use try_into() instead.
|
|
let get_user = entity::User::find_by_id(id).one(&self.connection).await;
|
|
if let Ok(get_user) = get_user {
|
|
if let Some(user) = get_user {
|
|
let id = user.id.to_string();
|
|
match serde_json::to_value(&user) {
|
|
Ok(item) => {
|
|
return Ok(RepositoryResponse::ItemOnly(model.build_item(&*id, item)));
|
|
}
|
|
Err(_) => {
|
|
return Err(RepositoryError::UnknownError(
|
|
"JSON Error creating value".to_owned(),
|
|
))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(RepositoryResponse::NoItem)
|
|
}
|
|
|
|
async fn list(&self, model: &RepositoryContext) -> RepositoryList {
|
|
let results = if let Ok(results) = entity::User::find().all(&self.connection).await {
|
|
results
|
|
} else {
|
|
return RepositoryList::Empty;
|
|
};
|
|
let repository_items: Vec<RepositoryItem> = results
|
|
.into_iter()
|
|
.filter_map(|item| match serde_json::to_value(&item) {
|
|
Ok(fields) => {
|
|
let id = item.id.to_string();
|
|
Some(model.build_item(&*id, fields))
|
|
}
|
|
Err(_) => None,
|
|
})
|
|
.collect();
|
|
RepositoryList::List {
|
|
values: repository_items,
|
|
}
|
|
}
|
|
|
|
async fn create(&mut self, model: &RepositoryContext, data: Value) -> RepositoryResult {
|
|
if let Value::Object(data) = data {
|
|
let username = data.get("username").unwrap().as_str().unwrap();
|
|
let password = data.get("password").unwrap().as_str().unwrap();
|
|
|
|
let mut user = UserRepository::new_user(username, password);
|
|
|
|
let keys = [
|
|
"first_name",
|
|
"last_name",
|
|
"email",
|
|
"is_staff",
|
|
"is_active",
|
|
"is_superuser",
|
|
];
|
|
|
|
for key in &keys {
|
|
if let Some(value) = data.get(*key) {
|
|
match *key {
|
|
"first_name" => user.first_name = Set(value.as_str().map(|s| s.to_owned())),
|
|
"last_name" => user.last_name = Set(value.as_str().map(|s| s.to_owned())),
|
|
"email" => user.email = Set(value.as_str().map(|s| s.to_owned())),
|
|
"is_staff" => user.is_staff = Set(value.as_bool().unwrap_or(false)),
|
|
"is_active" => user.is_active = Set(value.as_bool().unwrap_or(true)),
|
|
"is_superuser" => user.is_superuser = Set(value.as_bool().unwrap_or(false)),
|
|
_ => (),
|
|
}
|
|
}
|
|
}
|
|
|
|
if let Ok(user) = user.insert(&self.connection).await {
|
|
let id = user.id.to_string();
|
|
let item = model.build_item(&*id, serde_json::to_value(&user).unwrap());
|
|
return Ok(RepositoryResponse::ItemOnly(item));
|
|
}
|
|
}
|
|
Ok(RepositoryResponse::NoItem)
|
|
}
|
|
|
|
async fn update(
|
|
&mut self,
|
|
model: &RepositoryContext,
|
|
id: &Self::Key,
|
|
data: Value,
|
|
) -> RepositoryResult {
|
|
let id: i32 = *id as i32;
|
|
let user: Option<entity::user::Model> = entity::User::find_by_id(id)
|
|
.one(&self.connection)
|
|
.await
|
|
.map_err(|e| RepositoryError::DatabaseError(Box::new(e)))?;
|
|
let mut user: entity::user::ActiveModel = user.ok_or(RepositoryError::ItemNotFound)?.into();
|
|
|
|
// should we really allow username change?
|
|
if let Some(value) = data.get("username") {
|
|
if let Some(value) = value.as_str() {
|
|
user.username = Set(value.to_owned());
|
|
}
|
|
}
|
|
|
|
let keys = [
|
|
"first_name",
|
|
"last_name",
|
|
"email",
|
|
"is_staff",
|
|
"is_active",
|
|
"is_superuser",
|
|
];
|
|
|
|
for key in &keys {
|
|
if let Some(value) = data.get(*key) {
|
|
match *key {
|
|
"first_name" => user.first_name = Set(value.as_str().map(|s| s.to_owned())),
|
|
"last_name" => user.last_name = Set(value.as_str().map(|s| s.to_owned())),
|
|
"email" => user.email = Set(value.as_str().map(|s| s.to_owned())),
|
|
"is_staff" => user.is_staff = Set(value.as_bool().unwrap_or(false)),
|
|
"is_active" => user.is_active = Set(value.as_bool().unwrap_or(true)),
|
|
"is_superuser" => user.is_superuser = Set(value.as_bool().unwrap_or(false)),
|
|
_ => (),
|
|
}
|
|
}
|
|
}
|
|
|
|
// update
|
|
match user.update(&self.connection).await {
|
|
Ok(user) => {
|
|
let id = user.id.to_string();
|
|
return Ok(RepositoryResponse::ItemOnly(
|
|
model.build_item(&*id, serde_json::to_value(&user).unwrap()),
|
|
));
|
|
}
|
|
Err(err) => {
|
|
warn!("Error updating user");
|
|
return Err(RepositoryError::DatabaseError(Box::new(err)));
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn replace(
|
|
&mut self,
|
|
model: &RepositoryContext,
|
|
id: &Self::Key,
|
|
data: Value,
|
|
) -> RepositoryResult {
|
|
self.update(model, id, data).await
|
|
}
|
|
|
|
async fn delete(&mut self, _: &RepositoryContext, id: &Self::Key) -> Option<Value> {
|
|
let id: i32 = *id as i32;
|
|
let user: Option<entity::user::Model> = entity::User::find_by_id(id)
|
|
.one(&self.connection)
|
|
.await
|
|
.unwrap();
|
|
if let Some(user) = user {
|
|
let delete_result = user.delete(&self.connection).await.unwrap();
|
|
// .ok_or(RepositoryError::DatabaseError(Box::new(err)))?;
|
|
debug!("deleted rows: {}", delete_result.rows_affected);
|
|
}
|
|
|
|
None
|
|
}
|
|
}
|
|
|
|
pub fn register(registry: &mut DepotRegistry, db: DatabaseConnection) -> UserRepository {
|
|
let section_key = registry.register_section("Auth");
|
|
let repo = UserRepository::new(db);
|
|
let model_config = DepotModelConfig {
|
|
section_key: section_key,
|
|
name: "User".to_owned(),
|
|
};
|
|
let model_result = registry.register_model(model_config, repo.clone());
|
|
match model_result {
|
|
Err(err) => panic!("{}", err),
|
|
_ => repo,
|
|
}
|
|
}
|