#reviews #review #gui #cargo-toml #sled-database #crev

bin+lib cargo_crev_reviews

使用全栈Rust编写的跨平台应用程序在GUI中编写cargo-crev评论

1个稳定版本

2022.125.1258 2022年1月25日
2022.122.1621 2022年1月22日
2021.1230.1945 2021年12月30日
2021.1129.1919 2021年11月29日
2021.925.1120 2021年9月25日

#1806 in 开发工具

35 每月下载次数

MIT 协议

1.5MB
25K SLoC

cargo_crev_reviews

使用全栈Rust编写的跨平台应用程序在GUI中编写cargo-crev评论
仓库; 版本: 2022.125.1258 日期: 2022-01-25 作者: Luciano Bestia

Lines in Rust code Lines in Doc comments Lines in Comments Lines in examples Lines in tests

crates.io Documentation crev reviews Lib.rs License Rust

试用

安装cargo_crev_reviews

cargo install cargo_crev_reviews

转到包含Cargo.toml文件的Rust项目目录,并启动程序

cd ~/rustprojects/your-project-name
cargo_crev_reviews

并遵循简单说明...

Linux终端中的后端CLI
screen_5
浏览器中的前端GUI
screen_6

cargo tree

Cargo-tree是Rust的一个实用工具,它显示了Rust项目依赖关系的所有影响。它包含在cargo实用工具中。

你的个人评论

你的个人评论是最重要的。理想情况下,你希望亲自审查每一个crate,给它打分并写一些关于它的东西供自己使用。你想要知道你的程序所使用的依赖项不是恶意的或不可靠的。如果你有老板,他迟早会问你你是否审查了所有的依赖项。通过cargo_crev_reviews,你有一个基本的工具来做这件事。

不要惊慌!

要写评论,你需要看到crate的确切源代码和其他元数据。点击列表中的crate名称,它将打开

  • VSCode在包含原始依赖源代码副本的目录中
  • crev.dev 用于其他人的评论
  • crates.io 用于基本信息
  • lib.rs 用于扩展信息
  • 包含你评论的所有版本的crate列表

警告:现代浏览器阻止弹出窗口,你必须明确允许此网站 127.0.0.1
如果你没有VSCode,你可以在Config菜单中更改代码编辑器。

声誉与代码审查

个人认为,作者的声誉很重要。对于一些在Rust社区中非常知名且受尊敬的成员,我不会审查其代码。作者的声誉本身就足以让我感到安全。这种方法并不完美,因为可能会存在身份盗窃或版本错误。但我仍然认为,这对于我来说是一个高效且有效的方法。
Crates.io在作者和所有者之间造成了混淆。最近,他们为每个发布的版本引入了published_by字段。对我来说,这个字段代表了对该特定发布版本任何潜在问题的主要责任人。Crates.io保证发布的版本不能被修改。它们是只读的,因此你知道你所看到的就是正确的代码。

与社区分享

当你对自己的审查满意时,你就可以将其发布供其他开发者阅读。同样,其他开发者的审查在你分析依赖项时也会帮助你。更多的人写审查,我们得到的信息就越好,这有助于我们做出决策。
一个crate可以有许多版本。每个版本都是单独审查的。通常,许多版本之间的审查内容可能相同,但这很好。当一个开发者想查看特定版本的审查时,他不需要查看该crate所有其他版本的审查。

TL;DR

对于想要理解、调整代码并为项目做出贡献的开发者,以下是对项目重要方面的详细描述。如果你只是cargo_crev_reviews的用户,你不需要阅读所有这些内容。

动机

我认为cargo-crev是一个非常棒的工具体现开源社区的可靠性,特别是对于Rust编程语言。我非常担心使用crates.io的依赖项进行的供应链攻击。对于最小的项目,你很容易就能获得100个依赖项。如何信任它们所有?手动审查它们?这简直是疯狂。
但如果足够的人写审查,信任代码会容易得多。这与booking.comair-bnb的原理相同。酒店的客人会写下他们在酒店的真实体验。你可以阅读一个希望是真实的评论,并了解酒店是好是坏。有时可能会遇到虚假评论,但如果有人足够多,大多数人都会真诚。
不幸的是,在cargo-crev中写评论很困难。让我们围绕cargo-crev制作一个GUI包装器,让写评论变得更容易。
我们将看到在走这条路的过程中必须克服哪些障碍。

技术决策

Rust没有真正的GUI故事。它主要用于CLI和库。因为GUI大多是非跨平台的。但Rust是Wasm/Webassembly的最佳语言。所以让我们结合这些。
我将创建一个Rust workspace(多项目)

  1. 用于Web服务器的CLI(本地微服务器)
  2. Wasm用于浏览器(chrome和类似)

Web服务器CLI将访问文件、命令、库和网络。这只能在Linux上工作,但今天Win10已经通过WSL2集成了Linux。它将在所有对Rust开发敏感的操作系统上运行得很好。
浏览器中的Wasm将仅访问本地微Web服务器。这将作为GUI,因为浏览器在所有操作系统上都能运行,所以这是跨平台开发。

我想要最简单的网络服务器。它将仅由一个超级简单的网络应用在本地上使用,因此不需要过多关注安全性。我选择了来自《Rust书》中的simple server。我不关心多线程异步,因为它的使用者只有浏览器。书中的例子演变成了作者在GitHub上的仓库github.com/steveklabnik。我克隆了它,更新了依赖项,并相应地修复了一些损坏的代码。我将其发布为dev_bestia_simple_server在crates.io上。

对于浏览器,我将创建一个简单的网络应用。所有代码都将使用Rust编写,我将避免使用JavaScript。GUI将使用HTML5CSS3。所有现代浏览器都支持这些。

开发

我将使用cargo-auto来自动化构建项目所需的任务。
子目录automation_tasks_rscargo-auto的Rust项目。
我的项目dev_bestia_cargo_completion有助于bash自动补全。

我的Rust工作空间由以下成员组成

  • 后端CLI(这将是在crates.io上发布的主要和唯一的项目)
  • GUI前端

子目录web_server_folder包含开发工作所需的所有文件和文件夹结构。
但是这些文件不会被直接使用。由于发布到crates.io的方式,我将它们嵌入到Rust代码中作为字符串(如果需要,将它们base64编码)。我将为此创建一个自动化任务。

有一个文件auto_generated_mod.rs,其中自动化任务生成样板代码。我更喜欢生成代码而不是过程宏,因为编写(生成)、阅读和调试代码更简单。此外,自动补全工具可能会遇到过程宏的问题。

后端 - cargo_crev_reviews

这是一个针对本地使用的微Web服务器,只有一个本地浏览器连接到它。
这是网络应用网络服务器后端。我必须在这里使用相同的名称。
后端和前端一起形成一个完整的跨平台应用程序。
它们共享一些在common_structs_mod模块中定义的用于通信的结构。一个自动化任务会将后端的内容复制到前端项目中,以保持它们同步。
服务器操作的唯一URL是:http://127.0.0.1:8182/cargo_crev_reviews

Web服务器CLI将访问文件、命令、库和网络。对于crev reviews的签名过程,它需要crev密码短语。这可以通过交互式输入或在环境变量中使用_export CREV_PASSPHRASE=your_passphrase输入。
在export命令之前添加一个空格,以避免将秘密保存在bash历史记录中。

如果我想在crates.io上发布,所有内容必须在一个二进制可执行文件内。
这意味着所有静态文件:css、html、图标、图片等都必须包含在Rust代码中。
对于开发来说,将所有这些文件作为文件使用是非常实用的。
但在发布之前,一个自动化任务会将这些文件转换为字符串,并将它们放入Rust代码中。

微型服务器主要接受与POST类似,并包含json-rpc的json请求。但当然,我不得不修改它以更适合我的使用案例。我认为将来我会进一步修改,使其更适合。

Syntax:

--> data sent to Server - request
<-- data sent to Client - response

rpc call with named parameters:

--> {
"request_method": "subtract_calculate", 
"request_data": {
    "subtrahend": 23, 
    "minuend": 42, 
    }
}

<-- {
"response_method": "subtract_show", 
"response_data": {
    "subtracted": 19,     
    },
"response_html":"..."    
}

以下是如何使用curl测试POST请求的示例

curl -d '{"request_method": "subtract", "request_data": {"subtrahend": 23, "minuend": 42}}' -H 'Content-Type: application/json' http://127.0.0.1:8182/cargo_crev_reviews

还有一些GET请求用于静态文件,主要是为了开始浏览器和服务器之间的通信。
TODO:将来有一天,我将添加WebSocket通信,以便客户端可以在服务器上处理操作时显示进度条。

GUI前端 - cargo_crev_reviews_wasm

这是一个简单的Web应用程序,是应用程序cargo_crev_reviews的GUI前端。
它专门设计用于桌面使用,因为它是一个程序员工具。无需制作移动版本。RPC服务器返回的响应包含

  1. 响应方法名称
  2. HTML模板
  3. 数据

方法名称用于匹配并调用相应的函数。
HTML模板必须与microXml兼容。wasm代码逐个读取元素,并当找到标记时,插入数据。我希望HTML模板包含一些示例文本。因此,标记被添加到它们要替换的元素或属性之前。

常见结构体 - common_structs_mod.rs

后端和前端之间的常见结构。它是一种通信合约。
全部使用100%的Rust语言。一个自动化任务保持后端和前端模块同步。
TODO:使用结构体不够通用。大多数时候我需要字段名称。因为有了名称,我可以在不同的场景中绑定。使用结构体,我无法在运行时获取字段名称。我认为我会放弃大多数结构体,只使用带有QVS21的纯旧扁平文本。在这个文本中,每个字段都将有一个切片和一个名称。然后我可以在运行时使用这些进行绑定。

cargo-crev集成

cargo-crev项目包含许多crate。crate crev-libcrev-data是用于集成的库。所有与crev工作的代码都封装在crev_mod.rs模块中。

cargo注册表

cargo应用程序对于使用Rust语言是必不可少的。Cargo在目录~/.cargo/registry/中维护一个本地的cargo registry。它有3个基本子目录:索引、缓存和src。
注册表索引是包含crate元数据的数据库,并从GitHub通过git获取。索引文件的路径
~/.cargo/registry/index/github.com-1ecc6299db9ec823/cache/re/ad/reader_for_microxml

此文件的内容看起来像这样

bc688d353fc7c7a2f3f1f5fed9a27fc1773fc710
1.0.0 {
    "name": "reader_for_microxml",
    "vers": "1.0.0",
    "deps": [],
    "cksum": "623616f68a6441e2f61aa01c9bbcf76f4c9989328e0e10ab747e936718791912",
    "features": {},
    "yanked": true,
    "links": null
}
1.1.11 {
    "name": "reader_for_microxml",
    "vers": "1.1.11",
    "deps": [],
    "cksum": "fd50abb1f0d11a59ebe6d3f31446e4af8d0f8a7df668034b6c9b94453fa30c42",
    "features": {},
    "yanked": true,
    "links": null
}

Cargo从crates.io下载了项目中每个依赖项的完整源代码。
首先,它将tar gz文件下载到缓存目录,文件名以.crate结尾
~/.cargo/registry/cache/github.com-1ecc6299db9ec823/cargo_auto_lib-0.7.23.crate
很可能,cksum 字段是从这个 .crate 文件中计算出来的,位于 registry index 中。
然后,这些内容会被解压到 src 文件夹中,作为完整的源代码目录和文件
~/.cargo/registry/src/github.com-1ecc6299db9ec823/.
Crates.io 保证对于 crate+版本的 .crate 文件不能被修改或删除,并且始终可以从 crates.io 下载(即使被撤回)。
我们可以自信地审查这段本地代码,因为我们知道它永远不会改变。
这些本地文件不应以任何方式被修改。但如果在不经意间和不愿意的情况下打开代码编辑器,这可能会发生。它将创建 target 文件夹和 Cargo.lock 文件。还可能出现 Go to definition 在编辑器中打开这些文件,并且我们可能会修改一些注释或代码。这是不好的。
config and utils 中,可以进行完整性检查,以确保这些文件未被篡改。如果有什么被修改了,只需简单地从 src 中删除该文件夹即可。下次 cargo 需要这些 crate 时,它将自动下载和解压。

crates.io API

一些数据在 cargo 注册表中不可用,需要从 https://crates.io//api/v1/crates/{}/{}/ 获取。然后我将其存储在 ~/.config/crev/cargo_crev_reviews_data/db 中。crates.io 的数据都是不可变的,除了被撤回的版本。我将在本地注册表中找到撤回和新版本的数据。这将触发从 crates.io 下载数据。

RustSec cargo audit

我将 cargo audit --json 的结果添加到 cargo 树列表中。

受信任的发布者

在 crates.io 上,谁负责一个 crate 版本的拥有者、作者或组存在混淆。最近他们为 crate_version 添加了一个 published_by 字段。这听起来更准确。发布者是负责检查其中没有恶意软件的人。
您可以在应用程序中编辑您的受信任发布者列表。

代码流程

所有内容都编译成一个单独的可执行二进制文件,用于 Linux:cargo_crev_reviews
首先,它使用 xdg-open 打开默认浏览器,访问 http://127.0.0.1:8182/cargo_crev_reviews/index.html
我收到一个评论说 xdg-open 并非每个 Linux 发行版都预安装。我使用 Debian 10 并且有它。
在其他发行版上,可以使用 xdg-utils 来安装它。
您也可以使用环境变量 export CREV_BROWSER_PATH=/usr/bin/xdg-open 来更改它,对于您系统上存在的命令。稍后您可以在配置菜单中更改此命令。
如果您的 WSL2 尚未运行默认浏览器,请运行此命令

ln -s "/mnt/c/Program Files/Mozilla Firefox/firefox.exe" /usr/bin/browser_in_win
export BROWSER='/usr/bin/browser_in_win'

命令 ln -sf 是永久和持久的。它创建一个符号链接文件,将永远保留在那里。
但是 export BROWSER= 并不持久。您需要将此命令添加到 ~/.bashrc,以便在每次启动终端时运行。

在下个毫秒,Web服务器开始监听 127.0.0.1 端口 8182
第一组请求是GET,响应是嵌入在auto_generated_files_mod.rs中的“静态”文件。

  1. 浏览器对 /cargo_crev_reviews/index.html 的请求是GET,响应是嵌入在auto_generated_files_mod.rs中的函数 index_html() 中的html文本文件。
    这个html只是一个空壳,用于获取css和wasm代码。里面没有实际内容。这个概念是 单页应用程序SPA
  2. index.html请求:3个css文件,pkg/cargo_crev_reviews.jspkg/cargo_crev_reviews_bg.wasm,“favicon” icons/icon-032.png。所有这些请求都是GET,响应来自auto_generated_files_mod.rs函数,其中一些是文本文件,另一些是base64文件。
  3. 浏览器导入wasm模块并启动init函数,该函数请求 request_cargo_tree_list。它响应:response_method_name,response_html和response_data。
  4. wasm(在浏览器内部)是Rust代码。首先它匹配method_name并调用适当的函数。它使用数据处理html并将其插入到index.html(空壳)中。
  5. 浏览器渲染我们的第一个页面。太棒了!
  6. 用户点击某个按钮。
  7. on_click!row_on_click! 隐藏在web_sys事件处理定义背后的丑陋Rust代码,并调用一个函数
  8. wasm创建一个rpc请求并将其/POST发送到服务器
  9. 请求是POST,服务器首先匹配method_name并调用适当的函数。该函数处理调用并准备一些数据。它加载html模板。
  10. 响应包含要渲染的html以及在此html中渲染前要插入的数据。

如何添加带有数据的页面

定义数据结构

common_structs_mod.rs 中添加类似的结构

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct VersionItemData {
    pub crate_name: String,
    pub crate_version: String,
}

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct VersionListData {
    pub list_of_version: Vec<VersionItemData>,
}

创建一个“标准”html页面

这个html页面必须与MicroXml兼容,基本上是XHtml。将例如 web_server_folder/review_list.html 复制到新的html文件。用浏览器打开此文件以预览。我使用VSCode扩展 vscode-open-wsl,右键单击文件并选择 Open with default application。在WSL2中,我使用我的项目 wsl_open_browser 从WSL2打开默认浏览器到Windows。现在编辑html文件以符合您的喜好,然后使用F5重新加载浏览器以查看更改。使用一些示例文本使其看起来尽可能接近您想要的效果。这些文本稍后将由程序替换,但在设计良好布局时非常有价值。

添加标记

在HTML中,您需要将示例文本替换为从服务器获取的数据。在文本前添加(不可见)标记,例如 <!--wt_crate_name-->。您也可以替换属性,如果在其前面插入属性,则如下所示 data-wt_variable_name="next_attribute_name"
现在运行自动化任务 cargo auto build,它将此文件复制/嵌入到 auto_generated_files_mod.rs

编写服务器函数

srv_methods_mod.rs 中添加一个如下所示的函数

#[named]
pub fn srv_function_name(request_data: serde_json::Value) -> anyhow::Result<String> {
    log::info!(function_name!());
    let filter: ReviewFilterData = unwrap!(serde_json::from_value(request_data));
    let response_data  = get_some_data(filter)?;
    let response_html = crate::auto_generated_files_mod::review_edit_html();
    // cln_methods::cln_review_edit(response_data, response_html)
}

现在运行自动化任务 cargo auto build,它将生成 auto_generated_mod.rs

客户端模块

如果我为数据使用不同的结构体,我必须有不同的客户端模块和函数。
使用泛型数据结构体,所有这些都可以泛化。
待办事项:使用QVS21

cln_version_mod.rs 中添加一个如下所示的客户端函数

pub fn cln_review_edit(srv_response: RpcResponse) {
    let html = extract_html(&srv_response);
    store_to_review_item_data(srv_response);

    // the mutex is locked inside a scope. When this structure falls out of scope, the lock will be unlocked.
    let html_after_process = {
        let data = REVIEW_ITEM_DATA.lock().unwrap().deref();
        process_html(data, &html)
    };

    inject_into_html(&html_after_process);

    on_click!("button_review_save", request_review_save);
    on_click!("button_review_list", request_review_list);
}

sled数据库

我不想重复使用crates.io API来获取相同的数据。我需要一个磁盘持久存储来存储这些数据。
我将尝试使用sled数据库。这是一个轻量级纯Rust高性能事务性嵌入式数据库。这是一个键值数据库。值可以是任何结构体。可以有多个独立的树/键空间:crates、versions、reviews、yanked、....

plantUml

使用plantUml在代码中编写您的图表。语言语法很简单。我有一个文本文件 images/server_plantuml_v3.txt。然后我使用在线服务 plantuml.com/plantuml/proxy 来创建png图像。由于缓存,我在文件名中有文件的版本。当版本更改时,旧的缓存不再使用。
服务器模块

plant_uml

WSL2中的意外情况

我的git仓库已损坏。看起来这发生在许多使用WSL2的人身上。
治疗方法是

# backup the repo first!
find .git/objects/ -type f -empty | xargs rm
git fetch -p
git fsck --full

一些其他信息

Cargo-crev还知道关于问题和警告的信息。但在这个项目中,我只关注评论。如果您认为版本真的有问题,可以将版本评为负面。我还将crates源限制为仅 crates.io。其他来源对公众不感兴趣。

cargo crev评论和建议

我们生活在供应链攻击的危险时期。供应链攻击
建议始终使用cargo-crev
来验证每个依赖项的可信度。
请,传播这个信息。
您也可以在网络上快速查看评论
https://web.crev.dev/rust-reviews/crates/

开源和免费如啤酒

我的开源项目免费如啤酒(MIT许可证)。
我只是喜欢编程。
但我也需要喝酒。如果您发现我的项目和教程有帮助,
请通过我在paypal上的捐款购买啤酒。
您知道您当地酒吧啤酒的价格 ;-)
因此,我可以免费喝啤酒祝你健康 :-)
Na zdravje! Alla salute! Prost! Nazdravlje! 🍻

依赖项

~28–44MB
~824K SLoC