From ad4f9d4b6ab70cad7331aee8fc7e7ceb1ada99c2 Mon Sep 17 00:00:00 2001 From: veypi Date: Mon, 2 Oct 2023 22:00:09 +0800 Subject: [PATCH] update user app conntector --- oab/migrations/20220720220617_base.sql | 5 - oab/src/api/app.rs | 75 +++++++-- oab/src/api/appuser.rs | 7 - oab/src/api/user.rs | 174 ++++++--------------- oab/src/cfg.rs | 6 +- oab/src/libs/auth.rs | 2 +- oab/src/libs/mod.rs | 2 +- oab/src/libs/user.rs | 68 ++++++++ oab/src/main.rs | 4 +- oab/src/models/app_plugin.rs | 4 +- oab/src/models/mod.rs | 5 +- oab/src/models/role.rs | 48 ------ oab/src/models/user_plugin.rs | 19 ++- oab/src/result.rs | 4 +- oaweb/package.json | 3 +- oaweb/src/App.vue | 1 - oaweb/src/boot/api/app.ts | 4 +- oaweb/src/boot/api/axios.ts | 16 +- oaweb/src/components/uploader/index.ts | 10 ++ oaweb/src/components/uploader/uploader.vue | 56 +++++++ oaweb/src/models/auth.ts | 12 +- oaweb/src/models/index.ts | 4 +- oaweb/src/pages/IndexPage.vue | 107 ++++++------- oaweb/src/router/index.ts | 1 - oaweb/src/stores/user.ts | 4 +- oaweb/yarn.lock | 161 +++++++++++++++++++ 26 files changed, 489 insertions(+), 313 deletions(-) create mode 100644 oab/src/libs/user.rs delete mode 100644 oab/src/models/role.rs create mode 100644 oaweb/src/components/uploader/index.ts create mode 100644 oaweb/src/components/uploader/uploader.vue diff --git a/oab/migrations/20220720220617_base.sql b/oab/migrations/20220720220617_base.sql index f496d14..89f1a7d 100644 --- a/oab/migrations/20220720220617_base.sql +++ b/oab/migrations/20220720220617_base.sql @@ -10,7 +10,6 @@ CREATE TABLE IF NOT EXISTS `user` `id` varchar(32) NOT NULL DEFAULT '' COMMENT 'User UUID', `created` datetime DEFAULT CURRENT_TIMESTAMP, `updated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `delete_flag` tinyint(1) NOT NULL DEFAULT 0, `username` varchar(255) NOT NULL UNIQUE, `nickname` varchar(255), @@ -32,7 +31,6 @@ CREATE TABLE IF NOT EXISTS `app` `id` varchar(32) NOT NULL, `created` datetime DEFAULT CURRENT_TIMESTAMP, `updated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `delete_flag` tinyint(1) NOT NULL DEFAULT 0, `key` varchar(32) NOT NULL, `name` varchar(255) NOT NULL, @@ -70,7 +68,6 @@ CREATE TABLE IF NOT EXISTS `role` `id` varchar(32) NOT NULL, `created` datetime DEFAULT CURRENT_TIMESTAMP, `updated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `delete_flag` tinyint(1) NOT NULL DEFAULT 0, `app_id` varchar(32) NOT NULL, `name` varchar(255) NOT NULL, @@ -99,7 +96,6 @@ CREATE TABLE IF NOT EXISTS `resource` ( `created` datetime DEFAULT CURRENT_TIMESTAMP, `updated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `delete_flag` tinyint(1) NOT NULL DEFAULT 0, `app_id` varchar(32) NOT NULL, `name` varchar(32) NOT NULL, @@ -116,7 +112,6 @@ CREATE TABLE IF NOT EXISTS `access` `id` int NOT NULL AUTO_INCREMENT, `created` datetime DEFAULT CURRENT_TIMESTAMP, `updated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `delete_flag` tinyint(1) NOT NULL DEFAULT 0, `app_id` varchar(32) NOT NULL, `name` varchar(32) NOT NULL, diff --git a/oab/src/api/app.rs b/oab/src/api/app.rs index c871598..010d558 100644 --- a/oab/src/api/app.rs +++ b/oab/src/api/app.rs @@ -6,11 +6,13 @@ // // use actix_web::{delete, get, post, web, Responder}; -use proc::access_read; +use proc::{access_create, access_read}; +use sea_orm::{ActiveModelTrait, EntityTrait, TransactionTrait}; use serde::{Deserialize, Serialize}; +use tracing::info; use crate::{ - models::{self, app}, + models::{self, access, app, app_user, rand_str, AUStatus, AccessLevel, Token}, AppState, Error, Result, }; use chrono::NaiveDateTime; @@ -20,10 +22,7 @@ use chrono::NaiveDateTime; pub async fn get(id: web::Path, stat: web::Data) -> Result { let n = id.into_inner(); if !n.is_empty() { - let s = sqlx::query_as::<_, app::Model>("select * from app where id = ?") - .bind(n) - .fetch_one(stat.sqlx()) - .await?; + let s = app::Entity::find_by_id(n).one(stat.db()).await?; Ok(web::Json(s)) } else { Err(Error::Missing("id".to_string())) @@ -53,20 +52,66 @@ pub struct App { #[get("/app/")] #[access_read("app")] pub async fn list(stat: web::Data) -> Result { - let result = sqlx::query_as::<_, App>( - "select app.id,app.created, app.updated, app.icon, app.name, app.des, app.user_count, app.hide,app.join_method, app.role_id, app.redirect, app.status, app_user.status as u_status from app left join app_user on app_user.user_id = ? && app_user.app_id = app.id", - ).bind(_auth_token.id) - .fetch_all(stat.sqlx()) - .await?; + let res = app::Entity::find().all(stat.db()).await?; + // let result = sqlx::query_as::<_,app::Model>( + // "select app.*,app_userstatus as status from app left join app_user on app_user.user_id = ? && app_user.app_id = app.id", + // ).bind(_auth_token.id) + // .fetch_all(stat.sqlx()) + // .await?; - Ok(web::Json(result)) + Ok(web::Json(res)) +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct CreateOpt { + name: String, + icon: Option, + // enable_register: Option, + // des: Option, + // host: Option, + // redirect: Option, } #[post("/app/")] -pub async fn create() -> Result { - Ok("") +#[access_create("app")] +pub async fn create( + stat: web::Data, + data: web::Json, + t: web::ReqData, +) -> Result { + let data = data.into_inner(); + let id = uuid::Uuid::new_v4().to_string().replace("-", ""); + let t = t.into_inner(); + info!("{} create app {}", t.id, t.nickname); + let obj = app::ActiveModel { + name: sea_orm::ActiveValue::Set(data.name), + icon: sea_orm::ActiveValue::Set(data.icon), + id: sea_orm::ActiveValue::Set(id), + key: sea_orm::ActiveValue::Set(rand_str(32)), + ..Default::default() + }; + let db = stat.db().begin().await?; + let obj: app::Model = obj.insert(&db).await?; + let ac = access::ActiveModel { + app_id: sea_orm::ActiveValue::Set(stat.uuid.clone()), + name: sea_orm::ActiveValue::Set("app".to_string()), + rid: sea_orm::ActiveValue::Set(Some(obj.id.clone())), + user_id: sea_orm::ActiveValue::Set(Some(t.id.clone())), + level: sea_orm::ActiveValue::Set(AccessLevel::ALL as i32), + ..Default::default() + }; + let ac: access::Model = ac.insert(&db).await?; + let au = app_user::ActiveModel { + app_id: sea_orm::ActiveValue::Set(obj.id.clone()), + user_id: sea_orm::ActiveValue::Set(t.id.clone()), + status: sea_orm::ActiveValue::Set(AUStatus::OK as i32), + ..Default::default() + }; + let au: app_user::Model = au.insert(&db).await?; + db.commit().await?; + Ok(web::Json(obj)) } #[delete("/app/{id}")] -pub async fn del(id: web::Path) -> Result { +pub async fn del(_id: web::Path) -> Result { Ok("") } diff --git a/oab/src/api/appuser.rs b/oab/src/api/appuser.rs index 9bf7a31..07d3c21 100644 --- a/oab/src/api/appuser.rs +++ b/oab/src/api/appuser.rs @@ -33,13 +33,6 @@ pub async fn get( Err(Error::Missing("uid or aid".to_string())) } else { let s: Vec = q.all(stat.db()).await?; - // let s = sqlx::query_as::<_, app_user::Model>( - // "select * from app_user where app_id = ? and user_id = ?", - // ) - // .bind(aid) - // .bind(uid) - // .fetch_all(stat.sqlx()) - // .await?; Ok(web::Json(s)) } } diff --git a/oab/src/api/user.rs b/oab/src/api/user.rs index 8e42068..76359c1 100644 --- a/oab/src/api/user.rs +++ b/oab/src/api/user.rs @@ -8,14 +8,18 @@ use std::fmt::Debug; use crate::{ - models::{self, access, app, app_user, user, UserPlugin}, + libs, + models::{self, access, app, app_user, user, user_role, AUStatus, UserPlugin}, AppState, Error, Result, }; use actix_web::{delete, get, head, http, post, web, HttpResponse, Responder}; use base64; use proc::access_read; use rand::Rng; -use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseConnection, DatabaseTransaction, + EntityTrait, QueryFilter, TransactionTrait, +}; use serde::{Deserialize, Serialize}; use tracing::info; @@ -52,7 +56,6 @@ pub async fn login( id: web::Path, stat: web::Data, ) -> Result { - let db = stat.db(); let id = id.into_inner(); let q = q.into_inner(); let filter = match q.typ { @@ -71,7 +74,10 @@ pub async fn login( Ok(p) => p, Err(_) => return Err(Error::ArgInvalid("password".to_string())), }; - let u: Option = models::user::Entity::find().filter(filter).one(db).await?; + let u: Option = models::user::Entity::find() + .filter(filter) + .one(stat.db()) + .await?; let u = match u { Some(u) => u, None => return Err(Error::NotFound("user".to_string())), @@ -81,64 +87,22 @@ pub async fn login( let au: Option = app_user::Entity::find() .filter(app_user::Column::AppId.eq(&stat.uuid)) .filter(app_user::Column::UserId.eq(&u.id)) - .one(db) + .one(stat.db()) .await?; - // let au = sqlx::query_as::<_, models::AppUser>( - // "select * from app_user where app_id = ? and user_id = ?", - // ) - // .bind(&CONFIG.uuid) - // .bind(&u.id) - // .fetch_optional(CONFIG.sqlx()) - // .await?; - let i: i64 = match au { - Some(au) => match au.status.into() { - models::AUStatus::OK => 0, - models::AUStatus::Deny => { - return Err(Error::BusinessException("apply denied".to_string())) - } - models::AUStatus::Disabled => { - return Err(Error::BusinessException("login disabled".to_string())) - } - models::AUStatus::Applying => { - return Err(Error::BusinessException("applying".to_string())) - } - }, + let au = match au { + Some(au) => au, None => { - let app_obj: app::Model = app::Entity::find_by_id(stat.uuid.clone()) - .one(db) - .await? - .unwrap(); - let s = match app_obj.join_method.into() { - models::AppJoin::Disabled => { - return Err(Error::BusinessException( - "this app diabled login".to_string(), - )) - } - models::AppJoin::Auto => models::AUStatus::OK, - models::AppJoin::Applying => models::AUStatus::Applying, - }; - sqlx::query( - r#" -insert into app_user (app_id,user_id,status) -values ( ?, ?, ? ) - "#, - ) - .bind(&app_obj.id) - .bind(&u.id) - .bind(&s) - .execute(stat.sqlx()) - .await?; - match s { - models::AUStatus::OK => 0, - _ => 1, - } + // 未绑定应用时进行绑定操作 + let aid = stat.uuid.clone(); + let db = stat.db().begin().await?; + let s = libs::user::connect_to_app(u.clone(), aid, &db).await?; + db.commit().await?; + s } }; - if i == 0 { - // let result: Vec = access::Entity::find().all(db).await?; - info!("asd"); - let result = sqlx::query_as::<_, access::Model>( - "select access.* from access, user_role, role WHERE user_role.user_id = ? && access.role_id=user_role.role_id && role.id=user_role.role_id && role.app_id = ?", + if au.status == AUStatus::OK as i32 { + let result = sqlx::query_as::<_, models::AccessCore>( + "select access.name, access.rid, access.level from access, user_role, role WHERE user_role.user_id = ? && access.role_id=user_role.role_id && role.id=user_role.role_id && role.app_id = ?", ) .bind(&u.id) .bind(stat.uuid.clone()) @@ -148,8 +112,8 @@ values ( ?, ?, ? ) .insert_header(("auth_token", u.token(result).to_string()?)) .body("".to_string())) } else { - Ok(HttpResponse::build(http::StatusCode::OK) - .insert_header(("stat", "applying")) + Ok(HttpResponse::build(http::StatusCode::FORBIDDEN) + .insert_header(("error", au.status)) .body("".to_string())) } } @@ -161,21 +125,21 @@ pub struct RegisterOpt { } #[post("/user/")] -pub async fn register(q: web::Json, stat: web::Data) -> Result { +pub async fn register( + q: web::Json, + stat: web::Data, +) -> Result { let q = q.into_inner(); // let mut tx = dbtx().await; info!("{:#?}", q); - let u: Option = - sqlx::query_as::<_, models::user::Model>("select * from user where username = ?") - .bind(q.username.clone()) - .fetch_optional(stat.sqlx()) - .await?; - let u: models::user::Model = match u { + let u: Option = user::Entity::find() + .filter(user::Column::Username.eq(&q.username)) + .one(stat.db()) + .await?; + // 初始化用户信息 + let u: models::user::ActiveModel = match u { Some(_) => return Err(Error::ArgDuplicated(format!("username: {}", q.username))), None => { - let mut u = models::user::Model::default(); - u.username = q.username.clone(); - u.id = uuid::Uuid::new_v4().to_string().replace("-", ""); let p = match base64::decode(q.password.as_bytes()) { Err(_) => return Err(Error::ArgInvalid("password".to_string())), Ok(p) => p, @@ -185,75 +149,27 @@ pub async fn register(q: web::Json, stat: web::Data) -> R Err(_) => return Err(Error::ArgInvalid("password".to_string())), }; info!("{}", p); + let mut u = models::user::Model::default(); + u.username = q.username.clone(); + u.id = uuid::Uuid::new_v4().to_string().replace("-", ""); u.update_pass(&p)?; let mut rng = rand::thread_rng(); let idx: i64 = rng.gen_range(1..221); u.icon = Some(format!("/media/icon/usr/{:04}.jpg", idx)); - u + u.into() } }; - let oa: app::Model = sqlx::query_as::<_, app::Model>("select * from app where id = ?") - .bind(stat.uuid.clone()) - .fetch_one(stat.sqlx()) - .await?; + let db = stat.db().begin().await?; - let mut au = app_user::Model::default(); - au.app_id = oa.id; - au.user_id = u.id.clone(); - match oa.join_method.into() { - models::AppJoin::Disabled => return Err(Error::AppDisabledRegister), - models::AppJoin::Auto => { - au.status = models::AUStatus::OK as i32; - } - models::AppJoin::Applying => au.status = models::AUStatus::Applying as i32, - } - let mut c = stat.sqlx().begin().await?; // 创建用户 - sqlx::query!( - r#" -insert into user (id,username,_real_code,_check_code,icon) -values ( ?, ?, ?, ?, ?) - "#, - u.id, - u.username, - u.real_code, - u.check_code, - u.icon, - ) - .execute(&mut c) - .await?; + let u = u.insert(&db).await?; // 关联应用 - sqlx::query!( - r#" - insert into app_user ( app_id, user_id, status) - values (?, ?, ? ) - "#, - au.app_id, - au.user_id, - au.status, - ) - .execute(&mut c) - .await?; - if oa.role_id.is_some() { - match au.status.into() { - models::AUStatus::OK => { - sqlx::query!( - r#" - insert into user_role (user_id, role_id) - values (?, ?) - "#, - au.user_id, - oa.role_id.unwrap(), - ) - .execute(&mut c) - .await?; - } - _ => {} - } - } - c.commit().await?; - Ok("ok".to_string()) + libs::user::connect_to_app(u.clone(), stat.uuid.clone(), &db).await?; + + db.commit().await?; + + Ok(web::Json(u)) } #[delete("/user/")] diff --git a/oab/src/cfg.rs b/oab/src/cfg.rs index 22b5153..7b3120d 100644 --- a/oab/src/cfg.rs +++ b/oab/src/cfg.rs @@ -11,17 +11,13 @@ use std::{ fs::File, io::{self, Read}, - str::FromStr, time::Duration, }; use clap::{Args, Parser, Subcommand}; use lazy_static::lazy_static; use sea_orm::{ConnectOptions, Database, DatabaseConnection}; -use sqlx::{ - mysql::{MySqlConnectOptions, MySqlPoolOptions}, - Pool, -}; +use sqlx::{mysql::MySqlPoolOptions, Pool}; use crate::Result; diff --git a/oab/src/libs/auth.rs b/oab/src/libs/auth.rs index 0f54fa3..fca0fab 100644 --- a/oab/src/libs/auth.rs +++ b/oab/src/libs/auth.rs @@ -12,7 +12,7 @@ use std::task::{Context, Poll}; use actix_web::body::MessageBody; use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform}; -use actix_web::http::header::HeaderValue; + use actix_web::{Error, HttpMessage}; use futures_util::future::{ok, Ready}; use futures_util::Future; diff --git a/oab/src/libs/mod.rs b/oab/src/libs/mod.rs index de67944..adc0c35 100644 --- a/oab/src/libs/mod.rs +++ b/oab/src/libs/mod.rs @@ -6,6 +6,7 @@ // pub mod auth; +pub mod user; use std::future::{ready, Ready}; @@ -14,7 +15,6 @@ use actix_web::{ Error, }; use futures_util::future::LocalBoxFuture; -use tracing::info; // There are two steps in middleware processing. // 1. Middleware initialization, middleware factory gets called with diff --git a/oab/src/libs/user.rs b/oab/src/libs/user.rs new file mode 100644 index 0000000..5bf00cb --- /dev/null +++ b/oab/src/libs/user.rs @@ -0,0 +1,68 @@ +// +// user.rs +// Copyright (C) 2023 veypi +// 2023-10-02 21:00 +// Distributed under terms of the MIT license. +// + +use crate::{ + models::{self, app, app_user, user, user_role}, + Error, Result, +}; +use sea_orm::{ActiveModelTrait, ConnectionTrait, DatabaseTransaction, EntityTrait}; + +// 尝试绑定应用 +pub async fn connect_to_app( + u: user::Model, + aid: String, + db: &DatabaseTransaction, +) -> Result { + let app_obj: Option = app::Entity::find_by_id(&aid).one(db).await?; + let app_obj = match app_obj { + Some(o) => o, + None => return Err(Error::NotFound(aid.clone())), + }; + let m = match app_obj.join_method.into() { + models::AppJoin::Disabled => return Err(Error::AppDisabledRegister), + models::AppJoin::Auto => models::AUStatus::OK, + models::AppJoin::Applying => models::AUStatus::Applying, + }; + let au = app_user::ActiveModel { + app_id: sea_orm::ActiveValue::Set(aid.clone()), + user_id: sea_orm::ActiveValue::Set(u.id.clone()), + status: sea_orm::ActiveValue::Set(m.clone() as i32), + ..Default::default() + }; + let au = au.insert(db).await?; + if m == models::AUStatus::OK { + after_connected_to_app(u, app_obj, db).await?; + } + Ok(au) +} + +// 成功绑定应用后操作 +pub async fn after_connected_to_app( + u: user::Model, + obj: app::Model, + db: &DatabaseTransaction, +) -> Result<()> { + if obj.role_id.is_some() { + user_role::ActiveModel { + user_id: sea_orm::ActiveValue::Set(u.id.clone()), + role_id: sea_orm::ActiveValue::Set(obj.role_id.unwrap().clone()), + ..Default::default() + } + .insert(db) + .await?; + }; + let sql = format!( + "update app set user_count = user_count + 1 where app_id = {}", + obj.id + ); + db.execute(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::MySql, + sql, + )) + .await?; + Ok(()) +} diff --git a/oab/src/main.rs b/oab/src/main.rs index 08e5163..cac2a08 100644 --- a/oab/src/main.rs +++ b/oab/src/main.rs @@ -18,6 +18,8 @@ use tracing::{error, info, warn}; #[tokio::main] async fn main() -> Result<()> { + std::env::set_var("RUST_LOG", "debug"); + std::env::set_var("RUST_BACKTRACE", "1"); init_log(); let mut data = AppState::new(); data.connect().await?; @@ -35,8 +37,6 @@ async fn main() -> Result<()> { Ok(()) } async fn web(data: AppState) -> Result<()> { - std::env::set_var("RUST_LOG", "info"); - std::env::set_var("RUST_BACKTRACE", "1"); let url = data.server_url.clone(); let serv = HttpServer::new(move || { let logger = middleware::Logger::default(); diff --git a/oab/src/models/app_plugin.rs b/oab/src/models/app_plugin.rs index dc3f62a..3873efa 100644 --- a/oab/src/models/app_plugin.rs +++ b/oab/src/models/app_plugin.rs @@ -7,7 +7,7 @@ use serde_repr::*; -#[derive(Debug, Serialize_repr, Deserialize_repr, Clone, sqlx::Type)] +#[derive(Debug, Serialize_repr, Deserialize_repr, Clone, sqlx::Type, PartialEq, Eq)] #[repr(i32)] pub enum AppJoin { Auto = 0, @@ -25,7 +25,7 @@ impl From for AppJoin { } } -#[derive(Debug, Deserialize_repr, Serialize_repr, Clone, sqlx::Type)] +#[derive(Debug, Deserialize_repr, Serialize_repr, Clone, sqlx::Type, PartialEq, Eq)] #[repr(i32)] pub enum AUStatus { OK = 0, diff --git a/oab/src/models/mod.rs b/oab/src/models/mod.rs index e75bf01..f1f99cd 100644 --- a/oab/src/models/mod.rs +++ b/oab/src/models/mod.rs @@ -7,14 +7,13 @@ mod app_plugin; pub mod entity; -mod role; mod user_plugin; use tracing::info; pub use app_plugin::{AUStatus, AppJoin}; -pub use entity::{access, app, app_user, user}; -pub use user_plugin::{AccessLevel, Token, UserPlugin}; +pub use entity::{access, app, app_user, role, user, user_role}; +pub use user_plugin::{rand_str, AccessCore, AccessLevel, Token, UserPlugin}; use crate::AppState; diff --git a/oab/src/models/role.rs b/oab/src/models/role.rs deleted file mode 100644 index 7c900f2..0000000 --- a/oab/src/models/role.rs +++ /dev/null @@ -1,48 +0,0 @@ -// -// role.rs -// Copyright (C) 2022 veypi -// 2022-07-09 02:42 -// Distributed under terms of the Apache license. -// - -use chrono::NaiveDateTime; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Default, Serialize, Deserialize, sqlx::Type, sqlx::FromRow)] -#[sqlx(type_name = "role")] -pub struct Role { - pub id: String, - pub created: Option, - pub updated: Option, - pub delete_flag: bool, - - pub app_id: String, - pub name: Option, - pub des: Option, - pub user_count: usize, -} - -#[derive(Debug, Default, Serialize, Deserialize)] -pub struct Resource { - pub created: Option, - pub updated: Option, - pub delete_flag: bool, - - pub app_id: String, - pub name: String, - pub des: Option, -} - -#[derive(Debug, Default, Serialize, Deserialize)] -pub struct Access { - pub created: Option, - pub updated: Option, - pub delete_flag: bool, - - pub app_id: String, - pub name: String, - pub role_id: Option, - pub user_id: Option, - pub rid: Option, - pub level: usize, -} diff --git a/oab/src/models/user_plugin.rs b/oab/src/models/user_plugin.rs index a31878a..062beff 100644 --- a/oab/src/models/user_plugin.rs +++ b/oab/src/models/user_plugin.rs @@ -9,7 +9,6 @@ use chrono::{prelude::*, Duration}; use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; use serde::{Deserialize, Serialize}; -use tracing::info; use crate::{Error, Result}; use aes_gcm::aead::{Aead, NewAead}; @@ -23,7 +22,7 @@ use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use serde_repr::*; -fn rand_str(l: usize) -> String { +pub fn rand_str(l: usize) -> String { thread_rng() .sample_iter(&Alphanumeric) .take(l) @@ -42,16 +41,24 @@ fn rand_str(l: usize) -> String { // assert_eq!(res, msg); // block // } +// + +#[derive(Debug, Serialize, Deserialize, Clone, sqlx::FromRow)] +pub struct AccessCore { + pub name: String, + pub rid: Option, + pub level: AccessLevel, +} pub trait UserPlugin { - fn token(&self, ac: Vec) -> Token; + fn token(&self, ac: Vec) -> Token; fn check_pass(&self, p: &str) -> Result<()>; fn update_pass(&mut self, p: &str) -> Result<()>; } // impl User { impl UserPlugin for super::entity::user::Model { - fn token(&self, ac: Vec) -> Token { + fn token(&self, ac: Vec) -> Token { let default_ico = "/media/".to_string(); let t = Token { iss: "onedt".to_string(), @@ -167,7 +174,7 @@ pub struct Token { pub id: String, // 用户id pub nickname: String, pub ico: String, - pub access: Option>, + pub access: Option>, } impl Token { @@ -200,8 +207,6 @@ impl Token { } fn check(&self, domain: &str, did: &str, l: AccessLevel) -> bool { - info!("{:#?}|{:#?}|{}|", self.access, domain, did); - let l = l as i32; match &self.access { Some(ac) => { for ele in ac { diff --git a/oab/src/result.rs b/oab/src/result.rs index 6fd0f19..d7fb833 100644 --- a/oab/src/result.rs +++ b/oab/src/result.rs @@ -14,7 +14,7 @@ use actix_web::{ use serde::{Deserialize, Serialize}; use thiserror::Error as ThisError; -use tracing::info; +use tracing::warn; pub type Result = std::result::Result; @@ -177,7 +177,7 @@ impl actix_web::Responder for Error { impl error::ResponseError for Error { fn error_response(&self) -> HttpResponse { - info!("{}", self); + warn!("{}", self); HttpResponse::build(self.status_code()) .insert_header(ContentType::html()) .insert_header(("error", self.to_string())) diff --git a/oaweb/package.json b/oaweb/package.json index 9d57ddb..810850e 100644 --- a/oaweb/package.json +++ b/oaweb/package.json @@ -21,7 +21,8 @@ "quasar": "^2.6.0", "vue": "^3.0.0", "vue-i18n": "^9.2.2", - "vue-router": "^4.0.0" + "vue-router": "^4.0.0", + "webdav": "^5.3.0" }, "devDependencies": { "@intlify/vite-plugin-vue-i18n": "^3.3.1", diff --git a/oaweb/src/App.vue b/oaweb/src/App.vue index 77fc88b..d689f51 100644 --- a/oaweb/src/App.vue +++ b/oaweb/src/App.vue @@ -14,7 +14,6 @@ $q.iconMapFn = (iconName) => { // your custom approach, the following // is just an example: - console.log(iconName) if (iconName.startsWith('app:') === true) { // we strip the "app:" part const name = iconName.substring(4) diff --git a/oaweb/src/boot/api/app.ts b/oaweb/src/boot/api/app.ts index 9aeba26..191f994 100644 --- a/oaweb/src/boot/api/app.ts +++ b/oaweb/src/boot/api/app.ts @@ -34,8 +34,8 @@ export default { } return { local: this.local + uuid + '/user/', - list(uid: number) { - return ajax.get(this.local + uid) + list(id: string) { + return ajax.get(this.local + id) }, add(uid: number) { return ajax.post(this.local + uid) diff --git a/oaweb/src/boot/api/axios.ts b/oaweb/src/boot/api/axios.ts index 24d2e3e..4cbb923 100644 --- a/oaweb/src/boot/api/axios.ts +++ b/oaweb/src/boot/api/axios.ts @@ -49,23 +49,13 @@ const responseSuccess = (response: AxiosResponse) => { const responseFailed = (error: AxiosError) => { const { response } = error - const code = error.response?.status - const e_msg = error.response?.headers.error - if (e_msg) { - msg.Warn(e_msg) - } - if (code == 404) { - console.warn('api not exist: ') - return - } - if (response) { - return Promise.reject() - } else if (!window.navigator.onLine) { + if (!window.navigator.onLine) { alert('没有网络') return Promise.reject(new Error('请检查网络连接')) } - return Promise.reject(error.response) + console.log(response) + return Promise.reject(response?.data || response?.headers.error) } proxy.interceptors.response.use(responseSuccess, responseFailed) diff --git a/oaweb/src/components/uploader/index.ts b/oaweb/src/components/uploader/index.ts new file mode 100644 index 0000000..8540cef --- /dev/null +++ b/oaweb/src/components/uploader/index.ts @@ -0,0 +1,10 @@ +/* +* @name: index +* @author: veypi +* @date: 2021-12-04 14:32 +* @description:index +*/ +import upload from './uploader.vue' + + +export default upload diff --git a/oaweb/src/components/uploader/uploader.vue b/oaweb/src/components/uploader/uploader.vue new file mode 100644 index 0000000..27e0796 --- /dev/null +++ b/oaweb/src/components/uploader/uploader.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/oaweb/src/models/auth.ts b/oaweb/src/models/auth.ts index 6071f1e..ff71c51 100644 --- a/oaweb/src/models/auth.ts +++ b/oaweb/src/models/auth.ts @@ -1,10 +1,16 @@ +/* + * auth.ts + * Copyright (C) 2023 veypi + * 2023-10-02 16:44 + * Distributed under terms of the MIT license. + */ + + export interface modelsSimpleAuth { level: number name: string rid: string - // RID: string - // RUID: string } @@ -67,7 +73,7 @@ export class auths { Get(name: string, rid: string): authLevel { let l = level.None for (let i of this.list) { - if (i.name == name && (i.rid === '' || i.rid === rid) && i.level > l) { + if (i.name == name && (!i.rid || i.rid === rid) && i.level > l) { l = i.level } } diff --git a/oaweb/src/models/index.ts b/oaweb/src/models/index.ts index 0e53a39..9a1aa47 100644 --- a/oaweb/src/models/index.ts +++ b/oaweb/src/models/index.ts @@ -5,10 +5,10 @@ * @description:index */ -import { NewAuths, Auths, modelsSimpleAuth } from './auth' + +export { type Auths, type modelsSimpleAuth, NewAuths, R } from './auth' -export { NewAuths } export interface modelsBread { Index: number diff --git a/oaweb/src/pages/IndexPage.vue b/oaweb/src/pages/IndexPage.vue index 025fb32..6c7d3f5 100644 --- a/oaweb/src/pages/IndexPage.vue +++ b/oaweb/src/pages/IndexPage.vue @@ -4,7 +4,7 @@

我的应用

- 创建应用 + 创建应用
@@ -22,23 +22,29 @@ - + -
Our Changing Planet
-
by John Doe
+
创建应用
- - - - - - - -
+ + + + + +
取消 创建
@@ -53,41 +59,34 @@ import { onMounted, ref } from 'vue'; import api from 'src/boot/api'; import msg from '@veypi/msg'; -import { modelsApp, modelsUser } from 'src/models'; -import { useQuasar } from 'quasar'; -import { useUserStore } from 'src/stores/user'; +import { AUStatus, modelsApp, modelsAppUser } from 'src/models'; import AppCard from 'components/app.vue' +import { useUserStore } from 'src/stores/user'; +import { R } from 'src/models'; +import uploader from 'components/uploader' + +let user = useUserStore() let apps = ref([]); let ofApps = ref([]); -let $q = useQuasar() function getApps() { - $q.loadingBar.start() api.app.list().then( (e: modelsApp[]) => { apps.value = e; - api.app - .user("") - .list(useUserStore().id) - .then( - (e: modelsUser[]) => { - $q.loadingBar.stop(); - ofApps.value = []; - console.log(e) - // for (let i in e) { - // let ai = apps.value.findIndex((a) => a.id === e[i]); - // if (ai >= 0) { - // apps.value[ai].UserStatus = e[i].Status; - // if (e[i].Status === "ok") { - // ofApps.value.push(apps.value[ai]); - // apps.value.splice(ai, 1); - // } - // } - // } + api.app.user('-').list(user.id).then((aus: modelsAppUser[]) => { + for (let i in aus) { + let ai = apps.value.findIndex(a => a.id === aus[i].app_id) + if (ai >= 0) { + apps.value[ai].au = aus[i] + if (aus[i].status === AUStatus.OK) { + ofApps.value.push(apps.value[ai]) + apps.value.splice(ai, 1) + } } - ); + } + }) } ); } @@ -101,37 +100,23 @@ let temp_app = ref({ name: "", icon: "", }); -let form_ref = ref(null); let rules = { name: [ - { - required: true, - validator(r: any, v: any) { - return ( - (v && v.length >= 2 && v.length <= 16) || "长度要求2~16" - ); - }, - trigger: ["input", "blur"], - }, + (v: string) => (v && v.length >= 2 && v.length <= 16) || "长度要求2~16" ], }; function create_new() { - form_ref.value.validate((e: any) => { - if (!e) { - api.app.create(temp_app.value.name, temp_app.value.icon).Start( - (e) => { - e.Status = "ok"; - ofApps.value.push(e); - msg.success("创建成功"); - new_flag.value = false; - }, - (e) => { - msg.warning("创建失败: " + e); - } - ); - } - }); + api.app.create(temp_app.value.name, temp_app.value.icon).then((e: + modelsApp) => { + console.log(e) + // e.Status = "ok"; + // ofApps.value.push(e); + msg.Info("创建成功"); + new_flag.value = false; + }).catch(e => { + msg.Warn("创建失败: " + e); + }) } diff --git a/oaweb/src/router/index.ts b/oaweb/src/router/index.ts index 5c6915b..443b311 100644 --- a/oaweb/src/router/index.ts +++ b/oaweb/src/router/index.ts @@ -36,7 +36,6 @@ export default route(function(/* { store, ssrContext } */) { const u = useUserStore() Router.beforeEach((to, from) => { - console.log(to.meta) if (to.meta.requiresAuth && !util.checkLogin()) { // 此路由需要授权,请检查是否已登录 // 如果没有,则重定向到登录页面 diff --git a/oaweb/src/stores/user.ts b/oaweb/src/stores/user.ts index cf24cf5..5df767d 100644 --- a/oaweb/src/stores/user.ts +++ b/oaweb/src/stores/user.ts @@ -35,9 +35,9 @@ export const useUserStore = defineStore('user', { } let data = JSON.parse(Base64.decode(token[1])) if (data.id) { - this.auth = NewAuths(data.Auth) + console.log(data) + this.auth = NewAuths(data.access) api.user.get(data.id).then((e: modelsUser) => { - console.log(e) this.id = e.id this.local = e this.ready = true diff --git a/oaweb/yarn.lock b/oaweb/yarn.lock index 741e09c..6ae2e37 100644 --- a/oaweb/yarn.lock +++ b/oaweb/yarn.lock @@ -17,6 +17,13 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95" integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA== +"@buttercup/fetch@^0.1.1": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@buttercup/fetch/-/fetch-0.1.2.tgz#528e457aa0bddd74a802427318a3e061993092fd" + integrity sha512-mDBtsysQ0Gnrp4FamlRJGpu7HUHwbyLC4uUav1I7QAqThFAa/4d1cdZCxrV5gKvh6zO1fu95bILNJi4Y2hALhQ== + optionalDependencies: + node-fetch "^3.3.0" + "@esbuild/linux-loong64@0.14.54": version "0.14.54" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028" @@ -739,6 +746,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-64@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a" + integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg== + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -826,6 +838,11 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/byte-length/-/byte-length-1.0.2.tgz#ba5a5909240b0121c079b7f7b15248d6f08223cc" + integrity sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q== + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -880,6 +897,11 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +charenc@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== + "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -1060,6 +1082,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypt@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -1070,6 +1097,11 @@ csstype@^3.1.1: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1688,6 +1720,13 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-xml-parser@^4.2.4: + version "4.3.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.3.1.tgz#4f89c31e4c392d6e3d68b299733cad0c2d50d495" + integrity sha512-viVv3xb8D+SiS1W4cv4tva3bni08kAkx0gQnWrykMM8nXPc1FxqZPU00dCEVjkiCg4HoXd2jC4x29Nzg/l2DAA== + dependencies: + strnum "^1.0.5" + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -1695,6 +1734,14 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -1765,6 +1812,13 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -1918,6 +1972,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hot-patcher@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hot-patcher/-/hot-patcher-2.0.1.tgz#1473b799a3b756460ef226e10cf2cea4d79b435e" + integrity sha512-ECg1JFG0YzehicQaogenlcs2qg6WsXQsxtnbr1i696u5tLUjtJdQAh0u2g0Q5YV45f263Ta1GnUJsc8WIfJf4Q== + html-minifier@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-4.0.0.tgz#cca9aad8bce1175e02e17a8c33e46d8988889f56" @@ -2018,6 +2077,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-buffer@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-core-module@^2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" @@ -2180,6 +2244,11 @@ kolorist@^1.5.1: resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== +layerr@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/layerr/-/layerr-2.0.1.tgz#0c98e6f599de4f76b75c7a6522c54b8c6c591ff0" + integrity sha512-z0730CwG/JO24evdORnyDkwG1Q7b7mF2Tp1qRQ0YvrMMARbt1DFG694SOv439Gm7hYKolyZyaB49YIrYIfZBdg== + lazystream@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" @@ -2279,6 +2348,15 @@ magic-string@^0.30.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -2343,6 +2421,13 @@ minimatch@^5.1.0: dependencies: brace-expansion "^2.0.1" +minimatch@^7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.6.tgz#845d6f254d8f4a5e4fd6baf44d5f10c8448365fb" + integrity sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -2397,6 +2482,11 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +nested-property@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/nested-property/-/nested-property-4.0.0.tgz#a67b5a31991e701e03cdbaa6453bc5b1011bb88d" + integrity sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA== + no-case@^2.2.0: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" @@ -2404,6 +2494,20 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-releases@^2.0.13: version "2.0.13" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" @@ -2561,6 +2665,11 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-posix@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f" + integrity sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA== + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -2697,6 +2806,11 @@ quasar@^2.6.0: resolved "https://registry.yarnpkg.com/quasar/-/quasar-2.12.7.tgz#1e5c1ff06335c8e053d93350cac2e3aeaad8201f" integrity sha512-JF2rb8u1RcXPpiaDh/RnO/5rFx7kABDMov0WnRI3acJ5s4TD2FyPrCmS7VgleLubDYRSsSAontJ6EijGz4BHig== +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -2787,6 +2901,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -3044,6 +3163,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + sucrase@^3.32.0: version "3.34.0" resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f" @@ -3249,6 +3373,19 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-join@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-5.0.0.tgz#c2f1e5cbd95fa91082a93b58a1f42fecb4bdbcf1" + integrity sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA== + +url-parse@^1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -3328,6 +3465,30 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + +webdav@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/webdav/-/webdav-5.3.0.tgz#0be7690003884a250f7595ee42e583c71f01661d" + integrity sha512-xRu/URZGCxDPXmT+9Gu6tNGvlETBwjcuz69lx/6Qlq/0q3Gu2GSVyRt+mP0vTlLFfaY3xZ5O/SPTQ578tC/45Q== + dependencies: + "@buttercup/fetch" "^0.1.1" + base-64 "^1.0.0" + byte-length "^1.0.2" + fast-xml-parser "^4.2.4" + he "^1.2.0" + hot-patcher "^2.0.0" + layerr "^2.0.1" + md5 "^2.3.0" + minimatch "^7.4.6" + nested-property "^4.0.0" + path-posix "^1.0.0" + url-join "^5.0.0" + url-parse "^1.5.10" + webpack-merge@^5.8.0: version "5.9.0" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826"