diff --git a/Makefile b/Makefile
index f602015..8d584ce 100644
--- a/Makefile
+++ b/Makefile
@@ -29,3 +29,8 @@ build:
syncDB:
@scp -P 19529 oa.db root@alco.host:/root/
+
+buildweb:
+ @cd oaweb && yarn build
+ @rm -rf ./oab/dist/*
+ @mv ./oaweb/dist/spa/* ./oab/dist/
diff --git a/oab/Cargo.lock b/oab/Cargo.lock
index 2a5e975..23a65ac 100644
--- a/oab/Cargo.lock
+++ b/oab/Cargo.lock
@@ -1914,8 +1914,10 @@ dependencies = [
"include_dir",
"jsonwebtoken",
"lazy_static",
+ "mime_guess",
"proc",
"rand",
+ "rust-embed",
"sea-orm",
"serde",
"serde-big-array",
@@ -2445,6 +2447,40 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "rust-embed"
+version = "8.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40"
+dependencies = [
+ "rust-embed-impl",
+ "rust-embed-utils",
+ "walkdir",
+]
+
+[[package]]
+name = "rust-embed-impl"
+version = "8.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rust-embed-utils",
+ "syn 2.0.37",
+ "walkdir",
+]
+
+[[package]]
+name = "rust-embed-utils"
+version = "8.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada"
+dependencies = [
+ "sha2",
+ "walkdir",
+]
+
[[package]]
name = "rust_decimal"
version = "1.32.0"
@@ -2538,6 +2574,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -3637,6 +3682,16 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+[[package]]
+name = "walkdir"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
diff --git a/oab/Cargo.toml b/oab/Cargo.toml
index 775ce77..39399af 100644
--- a/oab/Cargo.toml
+++ b/oab/Cargo.toml
@@ -53,4 +53,6 @@ http = "0.2.9"
http-auth-basic = "0.3.3"
actix-multipart = "0.6.1"
actix-cors = "0.6.4"
+rust-embed = "8.0.0"
+mime_guess = "2.0.4"
diff --git a/oab/dist/index.html b/oab/dist/index.html
new file mode 100644
index 0000000..0b5d476
--- /dev/null
+++ b/oab/dist/index.html
@@ -0,0 +1,3 @@
+
OA
+
+
\ No newline at end of file
diff --git a/oab/proc/src/curd.rs b/oab/proc/src/crud.rs
similarity index 100%
rename from oab/proc/src/curd.rs
rename to oab/proc/src/crud.rs
diff --git a/oab/proc/src/lib.rs b/oab/proc/src/lib.rs
index b15ee27..409de2e 100644
--- a/oab/proc/src/lib.rs
+++ b/oab/proc/src/lib.rs
@@ -9,9 +9,9 @@ use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, AttributeArgs, ItemFn};
mod access;
-mod curd;
+mod crud;
use access::AccessWrap;
-use curd::CrudWrap;
+use crud::CrudWrap;
#[proc_macro_attribute]
pub fn have_access(args: TokenStream, input: TokenStream) -> TokenStream {
diff --git a/oab/src/api/access.rs b/oab/src/api/access.rs
index 1cbd951..85fe373 100644
--- a/oab/src/api/access.rs
+++ b/oab/src/api/access.rs
@@ -6,109 +6,108 @@
//
//
//
-use actix_web::{web, Responder};
-use proc::crud_update;
-use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, TransactionTrait};
+use actix_web::{delete, get, patch, post, web, Responder};
+use proc::{access_create, access_delete, access_read, crud_update};
+use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter};
use serde::{Deserialize, Serialize};
+use tracing::info;
-use crate::{models::app, AppState, Error, Result};
+use crate::{
+ models::{self},
+ AppState, Error, Result,
+};
-#[derive(Debug, Deserialize, Serialize, Clone)]
-pub struct UpdateOpt {
- pub name: Option,
- pub icon: Option,
- pub des: Option,
- pub join_method: Option,
- pub role_id: Option,
- pub redirect: Option,
- pub status: Option,
+#[derive(Debug, Deserialize, Serialize)]
+pub struct Options {
+ name: Option,
+ role_id: Option,
+ user_id: Option,
+ rid: Option,
+ level: Option,
}
-impl UpdateOpt {
- // #[crud_update(
- // app,
- // id = "Id",
- // name,
- // icon,
- // des,
- // join_method,
- // role_id,
- // redirect,
- // status
- // )]
- pub async fn update(
- id: web::Path,
- stat: web::Data,
- data: web::Json,
- ) -> Result {
- let data = data.into_inner();
- let id = id.into_inner();
- let obj = app::Entity::find_by_id(&id).one(stat.db()).await?;
- let mut obj: app::ActiveModel = match obj {
- Some(o) => o.into(),
- None => return Err(Error::NotFound(id)),
- };
- if let Some(name) = data.name {
- obj.name = sea_orm::Set(name)
- };
- let obj = obj.update(stat.db()).await?;
- Ok(web::Json(obj))
- }
+
+#[get("/app/{aid}/access/")]
+#[access_read("app")]
+pub async fn list(
+ aid: web::Path,
+ stat: web::Data,
+ query: web::Query,
+) -> Result {
+ let aid = aid.into_inner();
+ let mut q = models::access::Entity::find().filter(models::access::Column::AppId.eq(aid));
+ let query = query.into_inner();
+ if let Some(rid) = query.role_id {
+ q = q.filter(models::access::Column::RoleId.eq(rid));
+ };
+ if let Some(v) = query.name {
+ q = q.filter(models::access::Column::Name.eq(v));
+ };
+ if let Some(v) = query.user_id {
+ q = q.filter(models::access::Column::UserId.eq(v));
+ };
+ let aus = q.all(stat.db()).await?;
+ Ok(web::Json(aus))
}
-pub async fn update(
- id: web::Path,
+#[derive(Debug, Deserialize, Serialize)]
+pub struct CreateOptions {
+ name: String,
+ level: i32,
+ role_id: Option,
+ user_id: Option,
+ rid: Option,
+}
+#[post("/app/{aid}/access/")]
+#[access_create("app")]
+pub async fn creat(
+ aid: web::Path,
stat: web::Data,
- data: web::Json,
+ query: web::Json,
) -> Result {
- let _id = &id.clone();
- let _data = data.clone();
- let _db = &stat.db().clone();
- let f = || async move {
- let data = data.into_inner();
- let id = id.into_inner();
- let obj = app::Entity::find_by_id(&id).one(stat.db()).await?;
- let mut obj: app::ActiveModel = match obj {
- Some(o) => o.into(),
- None => return Err(Error::NotFound(id)),
- };
- if let Some(name) = data.name {
- obj.name = sea_orm::Set(name)
- };
- let obj = obj.update(stat.db()).await?;
- Ok(web::Json(obj))
+ let aid = aid.into_inner();
+ let query = query.into_inner();
+ let obj = models::access::ActiveModel {
+ app_id: sea_orm::ActiveValue::Set(aid),
+ name: sea_orm::ActiveValue::Set(query.name),
+ level: sea_orm::ActiveValue::Set(query.level),
+ role_id: sea_orm::ActiveValue::Set(query.role_id),
+ user_id: sea_orm::ActiveValue::Set(query.user_id),
+ rid: sea_orm::ActiveValue::Set(query.rid),
+ ..Default::default()
};
- let res = f().await;
- match res {
- Err(e) => Err(e),
- Ok(res) => {
- let obj = crate::models::app::Entity::find_by_id(_id).one(_db).await?;
- let mut obj: crate::models::app::ActiveModel = match obj {
- Some(o) => o.into(),
- None => return Err(Error::NotFound(_id.to_owned())),
- };
- if let Some(name) = _data.name {
- obj.name = sea_orm::Set(name.into())
- };
- if let Some(icon) = _data.icon {
- obj.icon = sea_orm::Set(icon.into())
- };
- if let Some(des) = _data.des {
- obj.des = sea_orm::Set(des.into())
- };
- if let Some(join_method) = _data.join_method {
- obj.join_method = sea_orm::Set(join_method.into())
- };
- if let Some(role_id) = _data.role_id {
- obj.role_id = sea_orm::Set(role_id.into())
- };
- if let Some(redirect) = _data.redirect {
- obj.redirect = sea_orm::Set(redirect.into())
- };
- if let Some(status) = _data.status {
- obj.status = sea_orm::Set(status.into())
- };
- let obj = obj.update(_db).await?;
- Ok(actix_web::web::Json(obj))
- }
- }
+ let obj: models::access::Model = obj.insert(stat.db()).await?;
+ Ok(web::Json(obj))
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct UpdateOpt {
+ pub level: Option,
+ pub rid: Option,
+}
+
+#[patch("/app/{aid}/access/{id}")]
+#[access_delete("app")]
+#[crud_update(access, AppId = "_id", Id = "_id", level, rid)]
+pub async fn update(
+ id: web::Path<(String, String)>,
+ data: web::Json,
+ stat: web::Data,
+) -> Result {
+ Ok("")
+}
+
+#[delete("/app/{aid}/access/{id}")]
+#[access_delete("app")]
+pub async fn delete(
+ params: web::Path<(String, String)>,
+ stat: web::Data,
+) -> Result {
+ let (aid, rid) = params.into_inner();
+ let res = models::access::Entity::delete_many()
+ .filter(models::access::Column::AppId.eq(aid))
+ .filter(models::access::Column::Id.eq(rid))
+ .exec(stat.db())
+ .await?;
+ info!("{:#?}", res);
+ Ok("ok")
}
diff --git a/oab/src/api/app.rs b/oab/src/api/app.rs
index 873346d..b2144c4 100644
--- a/oab/src/api/app.rs
+++ b/oab/src/api/app.rs
@@ -88,6 +88,7 @@ pub struct UpdateOpt {
pub join_method: Option,
pub role_id: Option,
pub redirect: Option,
+ pub host: Option,
pub status: Option,
}
@@ -102,6 +103,7 @@ pub struct UpdateOpt {
join_method,
role_id,
redirect,
+ host,
status
)]
pub async fn update(
diff --git a/oab/src/api/mod.rs b/oab/src/api/mod.rs
index 8d742a4..25eedf7 100644
--- a/oab/src/api/mod.rs
+++ b/oab/src/api/mod.rs
@@ -21,6 +21,7 @@ pub fn routes(cfg: &mut web::ServiceConfig) {
.service(user::list)
.service(user::register)
.service(user::login)
+ .service(user::update)
.service(user::delete);
cfg.service(app::get)
.service(app::list)
@@ -32,4 +33,19 @@ pub fn routes(cfg: &mut web::ServiceConfig) {
cfg.service(appuser::get)
.service(appuser::add)
.service(appuser::update);
+
+ cfg.service(access::list)
+ .service(access::creat)
+ .service(access::update)
+ .service(access::delete);
+ cfg.service(resource::list)
+ .service(resource::create)
+ .service(resource::update)
+ .service(resource::delete);
+ cfg.service(role::list)
+ .service(role::create)
+ .service(role::update)
+ .service(role::delete)
+ .service(role::add)
+ .service(role::drop);
}
diff --git a/oab/src/api/resource.rs b/oab/src/api/resource.rs
index 7dcce20..cccad92 100644
--- a/oab/src/api/resource.rs
+++ b/oab/src/api/resource.rs
@@ -4,3 +4,85 @@
// 2022-07-09 03:09
// Distributed under terms of the Apache license.
//
+use actix_web::{delete, get, patch, post, web, Responder};
+use proc::{access_create, access_delete, access_read, crud_update};
+use sea_orm::{
+ ActiveModelTrait, ColumnTrait, EntityTrait, LoaderTrait, QueryFilter, TransactionTrait,
+};
+use serde::{Deserialize, Serialize};
+use tracing::info;
+
+use crate::{
+ models::{self},
+ AppState, Error, Result,
+};
+
+#[get("/app/{aid}/resource/")]
+#[access_read("app")]
+pub async fn list(aid: web::Path, stat: web::Data) -> Result {
+ let n = aid.into_inner();
+ if !n.is_empty() {
+ let s = models::resource::Entity::find()
+ .filter(models::resource::Column::AppId.eq(n))
+ .all(stat.db())
+ .await?;
+ Ok(web::Json(s))
+ } else {
+ Err(Error::Missing("id".to_string()))
+ }
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct CreateOpt {
+ name: String,
+ des: Option,
+}
+#[post("/app/{aid}/resource/")]
+#[access_create("app")]
+pub async fn create(
+ aid: web::Path,
+ stat: web::Data,
+ data: web::Json,
+) -> Result {
+ let data = data.into_inner();
+ let obj = models::resource::ActiveModel {
+ name: sea_orm::ActiveValue::Set(data.name),
+ des: sea_orm::ActiveValue::Set(data.des),
+ app_id: sea_orm::ActiveValue::Set(aid.into_inner()),
+ ..Default::default()
+ };
+ let obj = obj.insert(stat.db()).await?;
+ Ok(web::Json(obj))
+}
+
+#[delete("/app/{aid}/resource/{rid}")]
+#[access_delete("app")]
+pub async fn delete(
+ params: web::Path<(String, String)>,
+ stat: web::Data,
+) -> Result {
+ let (aid, rid) = params.into_inner();
+ let res = models::resource::Entity::delete_many()
+ .filter(models::resource::Column::AppId.eq(aid))
+ .filter(models::resource::Column::Name.eq(rid))
+ .exec(stat.db())
+ .await?;
+ info!("{:#?}", res);
+ Ok("ok")
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct UpdateOpt {
+ pub des: Option,
+}
+
+#[patch("/app/{aid}/resource/{rid}")]
+#[access_delete("app")]
+#[crud_update(resource, AppId = "_id", Name = "_id", des)]
+pub async fn update(
+ id: web::Path<(String, String)>,
+ data: web::Json,
+ stat: web::Data,
+) -> Result {
+ Ok("")
+}
diff --git a/oab/src/api/role.rs b/oab/src/api/role.rs
index edb1fad..981ac29 100644
--- a/oab/src/api/role.rs
+++ b/oab/src/api/role.rs
@@ -4,3 +4,141 @@
// 2022-07-09 03:10
// Distributed under terms of the Apache license.
//
+//
+use actix_web::{delete, get, patch, post, web, Responder};
+use proc::{access_create, access_delete, access_read, access_update, crud_update};
+use sea_orm::{
+ ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, LoaderTrait, QueryFilter,
+ TransactionTrait,
+};
+use serde::{Deserialize, Serialize};
+use tracing::info;
+
+use crate::{
+ libs,
+ models::{self},
+ AppState, Error, Result,
+};
+
+#[get("/app/{aid}/role/")]
+#[access_read("app")]
+pub async fn list(aid: web::Path, stat: web::Data) -> Result {
+ let n = aid.into_inner();
+ if !n.is_empty() {
+ let s = models::role::Entity::find()
+ .filter(models::role::Column::AppId.eq(n))
+ .all(stat.db())
+ .await?;
+ Ok(web::Json(s))
+ } else {
+ Err(Error::Missing("id".to_string()))
+ }
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct CreateOpt {
+ name: String,
+ des: Option,
+}
+#[post("/app/{aid}/role/")]
+#[access_create("app")]
+pub async fn create(
+ aid: web::Path,
+ stat: web::Data,
+ data: web::Json,
+) -> Result {
+ let data = data.into_inner();
+ let id = uuid::Uuid::new_v4().to_string().replace("-", "");
+ let obj = models::role::ActiveModel {
+ name: sea_orm::ActiveValue::Set(data.name),
+ id: sea_orm::ActiveValue::Set(id),
+ des: sea_orm::ActiveValue::Set(data.des),
+ app_id: sea_orm::ActiveValue::Set(aid.into_inner()),
+ ..Default::default()
+ };
+ let obj = obj.insert(stat.db()).await?;
+ Ok(web::Json(obj))
+}
+
+#[delete("/app/{aid}/role/{rid}")]
+#[access_delete("app", id = "&id.clone().0")]
+pub async fn delete(
+ id: web::Path<(String, String)>,
+ stat: web::Data,
+) -> Result {
+ let (aid, rid) = id.into_inner();
+ let res = models::role::Entity::delete_many()
+ .filter(models::role::Column::AppId.eq(aid))
+ .filter(models::role::Column::Id.eq(rid))
+ .exec(stat.db())
+ .await?;
+ info!("{:#?}", res);
+ Ok("ok")
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct UpdateOpt {
+ pub des: Option,
+}
+
+#[patch("/app/{aid}/role/{rid}")]
+#[access_update("app", id = "&id.clone().0")]
+#[crud_update(role, AppId = "_id", Id = "_id", des)]
+pub async fn update(
+ id: web::Path<(String, String)>,
+ data: web::Json,
+ stat: web::Data,
+) -> Result {
+ Ok("")
+}
+
+#[get("/app/{aid}/role/{rid}/user/{uid}")]
+#[access_delete("app", id = "&id.clone().0")]
+pub async fn add(
+ id: web::Path<(String, String, String)>,
+ stat: web::Data,
+) -> Result {
+ let (_, rid, uid) = id.into_inner();
+ let s = models::user_role::ActiveModel {
+ user_id: sea_orm::ActiveValue::Set(uid),
+ role_id: sea_orm::ActiveValue::Set(rid.clone()),
+ ..Default::default()
+ };
+ let s = s.insert(stat.db()).await?;
+ let sql = format!(
+ "update role set user_count = user_count + 1 where id = '{}'",
+ rid,
+ );
+ stat.db()
+ .execute(sea_orm::Statement::from_string(
+ sea_orm::DatabaseBackend::MySql,
+ sql,
+ ))
+ .await?;
+ Ok(web::Json(s))
+}
+
+#[delete("/app/{aid}/role/{rid}/user/{uid}")]
+#[access_delete("app", id = "&id.clone().0")]
+pub async fn drop(
+ id: web::Path<(String, String, String)>,
+ stat: web::Data,
+) -> Result {
+ let (_, rid, uid) = id.into_inner();
+ models::user_role::Entity::delete_many()
+ .filter(models::user_role::Column::RoleId.eq(rid.clone()))
+ .filter(models::user_role::Column::UserId.eq(uid))
+ .exec(stat.db())
+ .await?;
+ let sql = format!(
+ "update role set user_count = user_count - 1 where id = '{}'",
+ rid,
+ );
+ stat.db()
+ .execute(sea_orm::Statement::from_string(
+ sea_orm::DatabaseBackend::MySql,
+ sql,
+ ))
+ .await?;
+ Ok("ok")
+}
diff --git a/oab/src/api/user.rs b/oab/src/api/user.rs
index 8ea8154..ed8ec1d 100644
--- a/oab/src/api/user.rs
+++ b/oab/src/api/user.rs
@@ -12,10 +12,10 @@ use crate::{
models::{self, app_user, user, AUStatus, UserPlugin},
AppState, Error, Result,
};
-use actix_web::{delete, get, head, http, post, web, HttpResponse, Responder};
+use actix_web::{delete, get, head, http, patch, post, web, HttpResponse, Responder};
use base64;
use chrono::{DateTime, Local, NaiveDateTime};
-use proc::access_read;
+use proc::{access_read, access_update, crud_update};
use rand::Rng;
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, TransactionTrait};
use serde::{Deserialize, Serialize};
@@ -35,10 +35,46 @@ pub async fn get(id: web::Path, stat: web::Data) -> Result,
+ role_id: Option,
+ app_id: Option,
+}
+
#[get("/user/")]
#[access_read("user")]
-pub async fn list(stat: web::Data) -> Result {
- let res: Vec = user::Entity::find().all(stat.db()).await?;
+pub async fn list(
+ stat: web::Data,
+ query: web::Query,
+) -> Result {
+ let query = query.into_inner();
+ let res = if let Some(v) = query.name {
+ user::Entity::find()
+ .filter(user::Column::Username.contains(v))
+ .all(stat.db())
+ .await?
+ } else if let Some(v) = query.role_id {
+ models::user_role::Entity::find()
+ .filter(models::user_role::Column::RoleId.eq(v))
+ .find_also_related(user::Entity)
+ .all(stat.db())
+ .await?
+ .into_iter()
+ .filter_map(|(_, u)| return u)
+ .collect()
+ } else if let Some(v) = query.app_id {
+ models::app_user::Entity::find()
+ .filter(models::app_user::Column::AppId.eq(v))
+ .find_also_related(user::Entity)
+ .all(stat.db())
+ .await?
+ .into_iter()
+ .filter_map(|(_, u)| return u)
+ .collect()
+ } else {
+ user::Entity::find().all(stat.db()).await?
+ };
Ok(web::Json(res))
}
@@ -175,6 +211,26 @@ pub async fn register(
Ok(web::Json(u))
}
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct UpdateOpt {
+ pub username: Option,
+ pub icon: Option,
+ pub nickname: Option,
+ pub email: Option,
+ pub phone: Option,
+}
+
+#[patch("/user/{id}")]
+#[access_update("user")]
+#[crud_update(user, Id = "_id", username, icon, nickname, email, phone)]
+pub async fn update(
+ id: web::Path,
+ stat: web::Data,
+ data: web::Json,
+) -> Result {
+ Ok("")
+}
+
#[delete("/user/")]
pub async fn delete() -> impl Responder {
""
diff --git a/oab/src/api/userapp.rs b/oab/src/api/userapp.rs
deleted file mode 100644
index f1dd499..0000000
--- a/oab/src/api/userapp.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// userapp.rs
-// Copyright (C) 2023 veypi
-// 2023-10-09 03:12
-// Distributed under terms of the MIT license.
-//
-
-use actix_web::{get, post, web, Responder};
-use proc::access_read;
-use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, TransactionTrait};
-
-use crate::{
- libs,
- models::{app, app_user},
- AppState, Error, Result,
-};
-
-// 获取 app
-#[get("/user/{uid}/user/{aid}")]
-#[access_read("app")]
-pub async fn get(
- params: web::Path<(String, String)>,
- stat: web::Data,
-) -> Result {
- let (mut aid, mut uid) = params.into_inner();
- let mut q = app_user::Entity::find();
- if uid == "-" {
- uid = "".to_string();
- } else {
- q = q.filter(app_user::Column::UserId.eq(uid.clone()));
- }
- if aid == "-" {
- aid = "".to_string();
- } else {
- q = q.filter(app_user::Column::AppId.eq(aid.clone()));
- }
- if uid.is_empty() && aid.is_empty() {
- Err(Error::Missing("uid or aid".to_string()))
- } else {
- let s: Vec<(app_user::Model, Option)> =
- q.find_also_related(app::Entity).all(stat.db()).await?;
- let res: Vec = s
- .into_iter()
- .filter_map(|(l, a)| match a {
- Some(a) => Some(app::Model {
- status: l.status,
- ..a
- }),
- None => None,
- })
- .collect();
- // let s: Vec = q.all(stat.db()).await?;
- Ok(web::Json(res))
- }
-}
-
-// 关联app
-#[post("/user/{uid}/app/{aid}")]
-#[access_read("app")]
-pub async fn add(
- params: web::Path<(String, String)>,
- stat: web::Data,
-) -> Result {
- let (aid, uid) = params.into_inner();
- let db = stat.db().begin().await?;
- let res = libs::user::connect_to_app(uid, aid, &db, None).await?;
- db.commit().await?;
- Ok(web::Json(res))
-}
diff --git a/oab/src/libs/user.rs b/oab/src/libs/user.rs
index 33898e5..08e3930 100644
--- a/oab/src/libs/user.rs
+++ b/oab/src/libs/user.rs
@@ -60,14 +60,23 @@ pub async fn after_connected_to_app(
obj: app::Model,
db: &DatabaseTransaction,
) -> Result<()> {
- if obj.role_id.is_some() {
+ if let Some(role_id) = obj.role_id {
user_role::ActiveModel {
user_id: sea_orm::ActiveValue::Set(uid.clone()),
- role_id: sea_orm::ActiveValue::Set(obj.role_id.unwrap().clone()),
+ role_id: sea_orm::ActiveValue::Set(role_id.clone()),
..Default::default()
}
.insert(db)
.await?;
+ let sql = format!(
+ "update role set user_count = user_count + 1 where id = '{}'",
+ role_id,
+ );
+ db.execute(sea_orm::Statement::from_string(
+ sea_orm::DatabaseBackend::MySql,
+ sql,
+ ))
+ .await?;
};
let sql = format!(
"update app set user_count = user_count + 1 where id = '{}'",
diff --git a/oab/src/main.rs b/oab/src/main.rs
index d72502d..cef3870 100644
--- a/oab/src/main.rs
+++ b/oab/src/main.rs
@@ -11,9 +11,11 @@ use actix_web::{
http::StatusCode,
middleware::{self, ErrorHandlerResponse, ErrorHandlers},
web::{self},
- App, HttpServer,
+ App, HttpResponse, HttpServer, Responder,
};
use futures_util::future::FutureExt;
+use mime_guess::from_path;
+use rust_embed::RustEmbed;
use http::{HeaderName, HeaderValue};
use oab::{api, init_log, libs, models, AppState, Clis, Result, CLI};
@@ -100,6 +102,7 @@ async fn web(data: AppState) -> Result<()> {
.app_data(web::Data::new(dav.clone()))
.service(web::resource("/{tail:.*}").to(libs::fs::dav_handler)),
)
+ .service(index)
});
info!("listen to {}", url);
serv.bind(url)?.run().await?;
@@ -113,3 +116,21 @@ fn add_error_header(
Ok(ErrorHandlerResponse::Response(res.map_into_left_body()))
}
+
+#[derive(RustEmbed)]
+#[folder = "dist/"]
+struct Asset;
+
+#[actix_web::get("/{_:.*}")]
+async fn index(p: web::Path) -> impl Responder {
+ info!("{}", p);
+ let p = &p.into_inner();
+ match Asset::get(p) {
+ Some(content) => HttpResponse::Ok()
+ .content_type(from_path(p).first_or_octet_stream().as_ref())
+ .body(content.data.into_owned()),
+ None => HttpResponse::Ok()
+ .content_type(from_path("index.html").first_or_octet_stream().as_ref())
+ .body(Asset::get("index.html").unwrap().data.into_owned()),
+ }
+}
diff --git a/oab/src/models/mod.rs b/oab/src/models/mod.rs
index 32101b7..1df22a8 100644
--- a/oab/src/models/mod.rs
+++ b/oab/src/models/mod.rs
@@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize};
use tracing::info;
pub use app_plugin::{AUStatus, AppJoin};
-pub use entity::{access, app, app_user, role, user, user_role};
+pub use entity::{access, app, app_user, resource, role, user, user_role};
pub use user_plugin::{rand_str, AccessCore, AccessLevel, Token, UserPlugin};
use crate::AppState;
diff --git a/oaweb/public/doc/markdown.md b/oaweb/public/doc/markdown.md
index 4b14f3a..90093b1 100644
--- a/oaweb/public/doc/markdown.md
+++ b/oaweb/public/doc/markdown.md
@@ -1,8 +1,6 @@
+[[toc]]
# 例子
# Markdown { 简明手册 | jiǎn míng shǒu cè }
-
-[[toc]]
-
# 基本语法
---
diff --git a/oaweb/quasar.config.js b/oaweb/quasar.config.js
index d3d726d..d5170bc 100644
--- a/oaweb/quasar.config.js
+++ b/oaweb/quasar.config.js
@@ -76,7 +76,7 @@ module.exports = configure(function(/* ctx */) {
// rebuildCache: true, // rebuilds Vite/linter/etc cache on startup
- // publicPath: '/',
+ publicPath: '/',
// analyze: true,
// env: {},
// rawDefine: {}
diff --git a/oaweb/src/boot/api/access.ts b/oaweb/src/boot/api/access.ts
new file mode 100644
index 0000000..ab0a777
--- /dev/null
+++ b/oaweb/src/boot/api/access.ts
@@ -0,0 +1,30 @@
+/*
+ * access.ts
+ * Copyright (C) 2023 veypi
+ * 2023-10-12 19:32
+ * Distributed under terms of the MIT license.
+ */
+
+
+import ajax from './axios'
+
+export default (app_id: string) => {
+ return {
+ local: `./app/${app_id}/access/`,
+ create(name: string, props?: { name?: string, level?: number, role_id?: string, user_id?: string, rid?: string }) {
+ return ajax.post(this.local, Object.assign({ name, level: 0 }, props))
+ },
+ get(id: string) {
+ return ajax.get(this.local + id)
+ },
+ list(props?: { name?: string, role_id?: string, user_id?: string }) {
+ return ajax.get(this.local, props)
+ },
+ update(uuid: string, props: any) {
+ return ajax.patch(this.local + uuid, props)
+ },
+ del(id: string) {
+ return ajax.delete(this.local + id)
+ },
+ }
+}
diff --git a/oaweb/src/boot/api/index.ts b/oaweb/src/boot/api/index.ts
index 215d0a5..4158b3c 100644
--- a/oaweb/src/boot/api/index.ts
+++ b/oaweb/src/boot/api/index.ts
@@ -6,16 +6,21 @@
*/
import app from "./app";
+import role from "./role";
import token from "./token";
import user from "./user";
-
+import resource from "./resource";
+import access from './access';
const api = {
- user: user,
- app: app,
- token: token
+ user,
+ app,
+ token,
+ role,
+ resource,
+ access,
}
diff --git a/oaweb/src/boot/api/resource.ts b/oaweb/src/boot/api/resource.ts
new file mode 100644
index 0000000..39c00fd
--- /dev/null
+++ b/oaweb/src/boot/api/resource.ts
@@ -0,0 +1,30 @@
+/*
+ * resource.ts
+ * Copyright (C) 2023 veypi
+ * 2023-10-12 18:03
+ * Distributed under terms of the MIT license.
+ */
+
+
+import ajax from './axios'
+
+export default (app_id: string) => {
+ return {
+ local: `./app/${app_id}/resource/`,
+ create(name: string, props?: { des?: string }) {
+ return ajax.post(this.local, Object.assign({ name }, props))
+ },
+ get(id: string) {
+ return ajax.get(this.local + id)
+ },
+ list() {
+ return ajax.get(this.local)
+ },
+ update(uuid: string, props: any) {
+ return ajax.patch(this.local + uuid, props)
+ },
+ del(id: string) {
+ return ajax.delete(this.local + id)
+ },
+ }
+}
diff --git a/oaweb/src/boot/api/role.ts b/oaweb/src/boot/api/role.ts
new file mode 100644
index 0000000..583ab10
--- /dev/null
+++ b/oaweb/src/boot/api/role.ts
@@ -0,0 +1,36 @@
+/*
+ * role.ts
+ * Copyright (C) 2023 veypi
+ * 2023-10-12 15:40
+ * Distributed under terms of the MIT license.
+ */
+
+
+import ajax from './axios'
+
+export default (app_id: string) => {
+ return {
+ local: `./app/${app_id}/role/`,
+ create(name: string, props?: { des?: string }) {
+ return ajax.post(this.local, Object.assign({ name }, props))
+ },
+ get(id: string) {
+ return ajax.get(this.local + id)
+ },
+ list() {
+ return ajax.get(this.local)
+ },
+ update(uuid: string, props: any) {
+ return ajax.patch(this.local + uuid, props)
+ },
+ del(id: string) {
+ return ajax.delete(this.local + id)
+ },
+ add(id: string, uid: string) {
+ return ajax.get(this.local + `${id}/user/${uid}`)
+ },
+ drop(id: string, uid: string) {
+ return ajax.delete(this.local + `${id}/user/${uid}`)
+ }
+ }
+}
diff --git a/oaweb/src/boot/api/user.ts b/oaweb/src/boot/api/user.ts
index bfbb63f..7a679b3 100644
--- a/oaweb/src/boot/api/user.ts
+++ b/oaweb/src/boot/api/user.ts
@@ -31,10 +31,10 @@ export default {
get(id: number) {
return ajax.get(this.local + id)
},
- list() {
- return ajax.get(this.local)
+ list(props?: { name?: string, role_id?: string, app_id?: string }) {
+ return ajax.get(this.local, props)
},
- update(id: number, props: any) {
+ update(id: string, props: any) {
return ajax.patch(this.local + id, props)
},
}
diff --git a/oaweb/src/components/crud.vue b/oaweb/src/components/crud.vue
index a039c59..88cc8e1 100644
--- a/oaweb/src/components/crud.vue
+++ b/oaweb/src/components/crud.vue
@@ -9,7 +9,8 @@
-
+
{{ k.label || k.name }}
@@ -20,17 +21,19 @@
+ cstyle.width[k.name], cstyle.v, cstyle.kv[k.name])">
-
- {{ item[k.name] === undefined ? k.default :
- item[k.name] }}
+
+ {{ item[k.name] === undefined ? k.default :
+ item[k.name] }}
+
@@ -42,7 +45,7 @@
diff --git a/oaweb/src/pages/AppCfg.vue b/oaweb/src/pages/AppCfg.vue
index e5a6cd6..52c32e5 100644
--- a/oaweb/src/pages/AppCfg.vue
+++ b/oaweb/src/pages/AppCfg.vue
@@ -7,7 +7,7 @@
-
diff --git a/oaweb/src/pages/AppUser.vue b/oaweb/src/pages/AppUser.vue
index 7d9be15..ba71566 100644
--- a/oaweb/src/pages/AppUser.vue
+++ b/oaweb/src/pages/AppUser.vue
@@ -5,8 +5,8 @@
* Distributed under terms of the MIT license.
-->
-
-
+
+
{{ util.datetostr(props.value) }}
diff --git a/oaweb/src/pages/docItem.vue b/oaweb/src/pages/docItem.vue
index 34783d8..9392be9 100644
--- a/oaweb/src/pages/docItem.vue
+++ b/oaweb/src/pages/docItem.vue
@@ -7,11 +7,10 @@
文档中心
-
- {{ url }}
-
-
+
+
+
diff --git a/oaweb/src/pages/user.vue b/oaweb/src/pages/user.vue
index 04380e7..b969ce5 100644
--- a/oaweb/src/pages/user.vue
+++ b/oaweb/src/pages/user.vue
@@ -7,10 +7,55 @@
账号设置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/oaweb/src/stores/user.ts b/oaweb/src/stores/user.ts
index b6e45d5..92aee79 100644
--- a/oaweb/src/stores/user.ts
+++ b/oaweb/src/stores/user.ts
@@ -35,6 +35,9 @@ export const useUserStore = defineStore('user', {
}
let data = JSON.parse(Base64.decode(token[1]))
if (data.id) {
+ let l = 'access to'
+ data.access.map((e: any) => l = l + `\n${e.name}.${e.level}`)
+ console.log(l)
this.auth = NewAuths(data.access)
api.user.get(data.id).then((e: modelsUser) => {
this.id = e.id