Coder Social home page Coder Social logo

enraged-dun-cookie-development-team / ceobe-canteen-serve Goto Github PK

View Code? Open in Web Editor NEW
21.0 21.0 3.0 12.07 MB

快来帮小刻找找蜜饼吧,小刻要饿昏啦

License: GNU Affero General Public License v3.0

Rust 97.56% Python 2.31% Dockerfile 0.13%
actix-web arknights ceobe mongodb rust sea-orm

ceobe-canteen-serve's People

Contributors

azidecupric avatar felinae98 avatar goodjooy avatar phidialam avatar yun-shan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

ceobe-canteen-serve's Issues

管理员鉴权模块重构

现状

在当前状态下,鉴权功能由以下几个部分共同提供

  • libs\crypto_str : 提供密码的加密和验证抽象
  • src\middleware\authorize: 提供鉴权中间件
  • src\utils\user_authorize: 提供鉴权相关的功能支持,包括用户权限分级、鉴权配置初始化内容
  • persisitence\dao\admin : 定义管理员相关的数据库操作
  • persistence\sql-models\src\admin_user : 定义管理相关的数据库模型

其中数据库相关的定义与操作已经集成到 persistence 即持久化模块中。
但是其他部分的功能,却分散在四处

解决

同时,由于鉴权模块由以下几个部分组成

  • 中间件: 用于挂载在特定handle/router 下,以提供鉴权功能
  • Extractor: 通过 Extension 中转,为handler 提供获取已鉴权用户的信息功能

看起来,鉴权模块似乎可以归入中间件当中,但是个人认为用户鉴权是具有特殊功能的组件,应该独立模块。

当前的鉴权相关的依赖树大概如下

┌──────────────────────────┐          ┌────────────┐
│                          │          │            │
│ presisitence/model_admin │          │ crypto_str │
│                          │          │            │
└───────┬────────┬─────────┘          └───┬────────┘
        │        │                        │
        │    ┌───┼────────────────────────┘
        │    │   │
        │    │   └────────────────┐
        │    │                    │
        │    │      ┌─────────┐   │   ┌─────────┐
        │    │      │         │   │   │         │
  ┌─────▼────▼──────▼──┐   ┌──┴───▼───▼─┐   ┌───┴────────┐
  │                    │   │            │   │            │
  │ handlers/user_auth │   │ middleware │   │ validation │
  │                    │   │            │   │            │
  └────────────────────┘   └────────────┘   └────────────┘

handlers/user_auth 部分创建用户时会使用crypto_str 中的加密算法供 presisitence/model_admin 相关接口使用。
middleware 鉴权时,会先使用 Validation 获取请求中的用户token, 然后使用presisitence/model_admin 获取对应用户信息,并比对密码版本,进行鉴权。

能否将鉴权部分合并到一起,成为一个crate,将以上的依赖关系改成下面这样

                                 ┌──────────────────┐
                                 │    Authorize     │
                                 │  ┌────────────┐  │
┌──────────────────────────┐     │  │            │  │
│                          │     │  │ validation │  │
│ presisitence/model_admin │     │  │            │  │
│                          │     │  └────────────┘  │
└───────┬──────────────────┘     │                  │
        │                        │  ┌────────────┐  │
        │                        │  │            │  │
        │       ┌────────────────┤  │ middleware │  │
        │       │                │  │            │  │
        │       │                │  └────────────┘  │
  ┌─────▼───────▼──────┐         │                  │
  │                    │         │  ┌────────────┐  │
  │ handlers/user_auth │         │  │            │  │
  │                    │         │  │ crypto_str │  │
  └────────────────────┘         │  │            │  │
                                 │  └────────────┘  │
                                 │                  │
                                 │                  │
                                 └──────────────────┘

将鉴权相关的代码进行一定包装,统一暴露给handlers,同时从跟项目中独立出来,便于后续的serve 代码迁移工作

还可以对密码加密流程提供一定包装,简化密码加密过程(raw -> md5 ->...)

类型转换为 `ActiveModel` 过于冗余

现状

当前情况下

  • Checked 转换为 ActiveModel
  • Checked 更新作用于 ActiveModel
  • Model 转换为 View
    都会带来要将整个Model 的每一个field 手动遍历一次,有一定冗余与重复

如以下接口,就存在比较大重复,并当代码增长后不易于阅读

impl IntoActiveModel<ActiveModel> for CeobeOperationAppVersion {
    fn into_active_model(self) -> ActiveModel {
        let CeobeOperationAppVersion {
            version,
            force,
            last_force_version,
            description,
        } = self;
        let now = get_now_naive_date_time();
        ActiveModel {
            version: Set(version),
            force: Set(force),
            last_force_version: Set(last_force_version),
            description: Set(description),
            create_at: Set(now),
            modify_at: Set(now),
            ..Default::default()
        }
    }
}

希望的改进方式

通过一组 derive macro 提供以上功能的自动派生

  • DeriveToActiveModel attr: model_conv
    • attr[container]
      • target: 转换/更新的目标model
      • preprocessing optional: 在转换前执行的一个或多个操作,可以要求获取0个或者多个原类型field 所有权
        • var_name optional: 预处理的返回结果的变量名称
        • process: 预处理本身,为一个函数
        • update_skip | update_only optional: 当更新时忽略这个预处理过程 | 只有更新时执行
        • requires optional: 需要获取原类型的参数,顺序为process 参数顺序
          • name : 需要的field 名称
          • onwner| mut_ref optional: 默认为获取不可变引用,可以通过指定为 onwner(所有权) 或者 mut-ref(可变引用)被获取所有权的field 会自动ignore
          • require_self optional: processing 需要 &self, 可以指定为 mut 以获得可变引用
      • default_non_exist optional: 不存在的colume 使用default 填充
      • generate_fields k-v pair optional: 生成的fields, 来自于preprocessing
    • attr[field]
      • rename optional: 默认情况,field IdentActiveModel 一致,可以通过该attr 更改指定field
      • project optional: 对原始类型进行转换
      • ignore optional: 视为该field 不存在
      • condition_set optional: 使用条件赋值,当条件满足将Set ,否则无修改(into 使用默认, update 不更改)
        • condition: 判定函数,第一个参数为 该field 原始值所有权,后续参数可以通过requires 定义
        • requires optional : 需要的参数,只能来自 preprocessing 结果,只能获取不可变引用
  • DeriveUpdateActiveModel attr: model_conv 与 DeriveToActiveModel` 使用相同参数,但是生成Update 代码
  • DeriveViewFromModel attr: model_conv 与 DeriveToActiveModel` 使用相同参数,但是生成Model -> View 代码

可能的代码样例

use Model::ActiveModel
#[derive(DeriveToActiveModel,DeriveUpdateActiveModel)]
#[model_conv(
    preprocessing(
       var_name="now",
       update_skip
       process = “get_now_naive_date_time”,
    ),
    preprocessing(
       update_only
       process = “|this|this.now_update(),
       require_self="mut"
    ),
    default_non_exist,
    generate_fields(
        access_time = "now"
    )
)]
struct Checked {
    #[model_conv(
    rename=“foo_name”
    )]
    foo: int,
    #[model_conv(
    project=“Into<String>::into”
    )]
    bar: Version,
}

屎山爆破计划

由于长时间维护,复杂的多个功能区合在一起。导致当前项目虽然已经具备了发布1.0的完整功能,但是代码本身质量依旧存疑。因此这里提出对于Rust端源码的大型重构。

首先,在开始重构前,希望能够提供全套的单元测试与集成测试,以确保在重构之后也能确认功能正确。

  • 占位符:添加 XXX 单元测试/集成测试,测试XXX 功能运作正常
  • 这里添加关于添加、修改、更新单元测试的 pull request

接下来,关于当前整个项目具有的缺陷,也许不同的人具有不同的看法,因此,可以在这里进行讨论。不管是新的issue 或者 在discussions 中发表

  • 占位符

最后,开始重构吧。需要知道每一个pull request 对应的 issue

  • PR [ ]:完成Issue [ ] 内容要求的XXX 部分/全部
  • 这里列出所有PR 与 issue 关系,并添加引用

关于前后端“同名不同模”的结构优化

在当前项目中,存在大量的由于前后台的结构不同带来的相同的数据却有着不同的具体结构的情况存在,在很多时候,都需要同时使用2种类似的struct来区分前后端。

在当前情况下,“同名不同模” 有以下的一些问题

  • 命名困难:为了区分模型使用位置,使得模型需要在类型名称中进行区分
  • 冗余代码:相近的类型带来了相近的代码,这使得代码出现大量重复。

改进想法:

  • 使用基于定制trait + 辅助宏的方式对这些代码改进

trait方面

  • ViewModelTrait trait提供关联类型FrontendBackend, 用于分别定位到具体的前端\后端响应模型
  • IntoFrontendTryIntoFrontend 用于从ViewModelTrait 转换到前台类型
  • IntoBackendTryIntoBackend 用于从ViewModelTrait 转换到后台类型

宏方面
提供一个派生宏,提供ViewModelTrait 的自动派生

  • field参数:
    • backend(ignore) / frontend(ignore)/ignore 后端/前端/双端忽视这个字段
    • backend(conv(ty=, err=, conv=)) / frontend(conv(ty=, err=, conv=)) /conv(ty=, err=, conv=) 后台/前台/两者都 提供类型转换,如果给定err将会实现TryIntoXXX, 否则实现IntoXXX

屎山爆破计划

由于长时间维护,复杂的多个功能区合在一起。导致当前项目虽然已经具备了发布1.0的完整功能,但是代码本身质量依旧存疑。因此这里提出对于Rust端源码的大型重构。

首先,在开始重构前,希望能够提供全套的单元测试与集成测试,以确保在重构之后也能确认功能正确。

  • 占位符:添加 XXX 单元测试/集成测试,测试XXX 功能运作正常
  • 这里添加关于添加、修改、更新单元测试的 pull request

接下来,关于当前整个项目具有的缺陷,也许不同的人具有不同的看法,因此,可以在这里进行讨论。不管是新的issue 或者 在discussions 中发表

最后,开始重构吧。需要知道每一个pull request 对应的 issue

  • PR [ ]:完成Issue [ ] 内容要求的XXX 部分/全部
  • 这里列出所有PR 与 issue 关系,并添加引用

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.