update user app conntector

master
veypi 1 year ago
parent f206d770ee
commit ad4f9d4b6a

@ -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,

@ -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<String>, stat: web::Data<AppState>) -> Result<impl Responder> {
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<AppState>) -> Result<impl Responder> {
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<String>,
// enable_register: Option<String>,
// des: Option<String>,
// host: Option<String>,
// redirect: Option<String>,
}
#[post("/app/")]
pub async fn create() -> Result<impl Responder> {
Ok("")
#[access_create("app")]
pub async fn create(
stat: web::Data<AppState>,
data: web::Json<CreateOpt>,
t: web::ReqData<Token>,
) -> Result<impl Responder> {
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<String>) -> Result<impl Responder> {
pub async fn del(_id: web::Path<String>) -> Result<impl Responder> {
Ok("")
}

@ -33,13 +33,6 @@ pub async fn get(
Err(Error::Missing("uid or aid".to_string()))
} else {
let s: Vec<app_user::Model> = 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))
}
}

@ -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<String>,
stat: web::Data<AppState>,
) -> Result<HttpResponse> {
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<user::Model> = models::user::Entity::find().filter(filter).one(db).await?;
let u: Option<user::Model> = 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::Model> = 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<models::access::Model> = 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<RegisterOpt>, stat: web::Data<AppState>) -> Result<String> {
pub async fn register(
q: web::Json<RegisterOpt>,
stat: web::Data<AppState>,
) -> Result<impl Responder> {
let q = q.into_inner();
// let mut tx = dbtx().await;
info!("{:#?}", q);
let u: Option<models::user::Model> =
sqlx::query_as::<_, models::user::Model>("select * from user where username = ?")
.bind(q.username.clone())
.fetch_optional(stat.sqlx())
let u: Option<models::user::Model> = user::Entity::find()
.filter(user::Column::Username.eq(&q.username))
.one(stat.db())
.await?;
let u: models::user::Model = match u {
// 初始化用户信息
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<RegisterOpt>, stat: web::Data<AppState>) -> 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/")]

@ -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;

@ -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;

@ -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

@ -0,0 +1,68 @@
//
// user.rs
// Copyright (C) 2023 veypi <i@veypi.com>
// 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<app_user::Model> {
let app_obj: Option<app::Model> = 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(())
}

@ -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();

@ -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<i32> 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,

@ -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;

@ -1,48 +0,0 @@
//
// role.rs
// Copyright (C) 2022 veypi <i@veypi.com>
// 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<NaiveDateTime>,
pub updated: Option<NaiveDateTime>,
pub delete_flag: bool,
pub app_id: String,
pub name: Option<String>,
pub des: Option<String>,
pub user_count: usize,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Resource {
pub created: Option<NaiveDateTime>,
pub updated: Option<NaiveDateTime>,
pub delete_flag: bool,
pub app_id: String,
pub name: String,
pub des: Option<String>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Access {
pub created: Option<NaiveDateTime>,
pub updated: Option<NaiveDateTime>,
pub delete_flag: bool,
pub app_id: String,
pub name: String,
pub role_id: Option<String>,
pub user_id: Option<String>,
pub rid: Option<String>,
pub level: usize,
}

@ -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<String>,
pub level: AccessLevel,
}
pub trait UserPlugin {
fn token(&self, ac: Vec<super::entity::access::Model>) -> Token;
fn token(&self, ac: Vec<AccessCore>) -> 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<super::entity::access::Model>) -> Token {
fn token(&self, ac: Vec<AccessCore>) -> 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<Vec<super::access::Model>>,
pub access: Option<Vec<AccessCore>>,
}
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 {

@ -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<T> = std::result::Result<T, Error>;
@ -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()))

@ -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",

@ -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)

@ -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)

@ -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)

@ -0,0 +1,10 @@
/*
* @name: index
* @author: veypi <i@veypi.com>
* @date: 2021-12-04 14:32
* @descriptionindex
*/
import upload from './uploader.vue'
export default upload

@ -0,0 +1,56 @@
<template>
<div @click="click">
<input ref="file" type="file" hidden @change="upload">
<slot></slot>
</div>
</template>
<script lang="ts" setup>
import { createClient } from "webdav";
import { ref } from 'vue';
import { useAppStore } from "src/stores/app";
let file = ref<HTMLInputElement>()
let app = useAppStore();
let emits = defineEmits<{
(e: 'success', v: string): void
(e: 'failed'): void
}>()
let props = withDefaults(defineProps<{
url: string
}>(), {
url: '',
})
function click() {
file.value?.dispatchEvent(new MouseEvent('click'))
}
let prefix = '/file/public/app/' + app.id + '/'
let client = createClient(prefix,
{ headers: { auth_token: localStorage.getItem('auth_token') || '' } })
async function upload() {
let list = file.value?.files || []
if (list.length) {
let reader = new FileReader()
reader.onload = function (event) {
var res = event.target?.result
// let data = new Blob([res])
let url = props.url.replaceAll('.', '.' + new Date().getTime().toString() + '.')
client.putFileContents(url, res).then(e => {
if (e) {
emits('success', prefix + url)
} else {
emits('failed')
}
})
}
reader.readAsArrayBuffer(list[0])
} else {
}
}
</script>
<style scoped></style>

@ -1,10 +1,16 @@
/*
* auth.ts
* Copyright (C) 2023 veypi <i@veypi.com>
* 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
}
}

@ -5,10 +5,10 @@
* @descriptionindex
*/
import { NewAuths, Auths, modelsSimpleAuth } from './auth'
export { type Auths, type modelsSimpleAuth, NewAuths, R } from './auth'
export { NewAuths }
export interface modelsBread {
Index: number

@ -4,7 +4,7 @@
<div class="flex justify-between">
<h1 class="page-h1">我的应用</h1>
<div class="my-5 mr-10">
<q-btn @click="new_flag = true" v-if="store.state.user.auth.Get(R.App, '').CanCreate()">
<q-btn @click="new_flag = true" v-if="user.auth.Get(R.App, '').CanCreate()">
</q-btn>
</div>
</div>
@ -22,23 +22,29 @@
</div>
</div>
</div>
<q-dialog v-model="new_flag">
<q-dialog :square="false" v-model="new_flag">
<q-card class="w-4/5 md:w-96 rounded-2xl">
<q-card-section>
<div class="text-h6">Our Changing Planet</div>
<div class="text-subtitle2">by John Doe</div>
<div class="text-h6">创建应用</div>
</q-card-section>
<q-separator></q-separator>
<q-card-section>
<q-form @submit="create_new">
<q-input label="应用名" v-model="temp_app.name"></q-input>
<!-- <uploader url="test.ico" @success="(e) => { -->
<!-- temp_app.icon = e; -->
<!-- } -->
<!-- "> -->
<!-- <q-avatar size="large" round :src="temp_app.icon"> </q-avatar> -->
<!-- </uploader> -->
<div class="flex justify-end">
<q-input label="应用名" v-model="temp_app.name" :rules="rules.name"></q-input>
<q-field label="icon" stack-label>
<template v-slot:control>
<uploader url="test.ico" @success="(e) => {
temp_app.icon = e;
}
">
<q-avatar size="xl" round>
<img :src="temp_app.icon">
</q-avatar>
</uploader>
</template>
</q-field>
<q-separator></q-separator>
<div class="flex justify-end mt-8">
<q-btn class="mx-3" @click="new_flag = false">取消</q-btn>
<q-btn type="submit">创建</q-btn>
</div>
@ -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<modelsApp[]>([]);
let ofApps = ref<modelsApp[]>([]);
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("创建成功");
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;
},
(e) => {
msg.warning("创建失败: " + e);
}
);
}
});
}).catch(e => {
msg.Warn("创建失败: " + e);
})
}
</script>

@ -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()) {
// 此路由需要授权,请检查是否已登录
// 如果没有,则重定向到登录页面

@ -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

@ -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"

Loading…
Cancel
Save