- user_scopes 由"假开关"做成生效:粒度到项目级(组织隔离 ∧ 项目∈范围,取交集);未配置=不限制(逐字向后兼容);
总管理员豁免;脏数据保守忽略不锁死;配置期校验存在性+归属;逐接口叠加(列表/详情/写操作/Excel 导出落 scope_project_ids);
前端新增"数据范围"弹窗入口。顺带修 GET /api/charge-orders 此前完全没有组织隔离(跨租户泄露)、
GET /api/projects/{id}/cabinets 的 500
- 数据库列类型系统性对齐:扫描并修复 pms_dev 32 项 / pms 18 项漂移(时间列统一 DATETIME,sqlx NaiveDateTime 只兼容 DATETIME);
DECIMAL→BIGINT 与列注释口径拉平;修复生产 GET /api/charge-orders、GET /api/device-logs 必然 500 的根因;
恢复 7 张表丢失的 updated_at ON UPDATE(行为变化,已记入 AGENTS.md);修正 SCHEMA_SQL 前向引用(空库建表必崩);
新增 tools/db_schema_diff.py(漂移检查,退出码可接部署前置)与 test/schema_alignment_e2e.py
- 安全加固四项:上传去 .svg + 魔数嗅探(堵存储型 XSS);登录失败锁定(5次/15分)+challenge 限流+并发闸门+验证码容差收紧;
服务降权 root→pms;nginx 安全头 + limit_req + CORS 白名单收敛
- TCP 连接登录门控(上行+下行同一规则):login 前只放行 auth_str/login(PRE_LOGIN_ALLOWED_ACTS)
- 状态位按归属层级展示:柜级 status1/status2 显示在柜子(含柜门 + 开门按钮,独立动作不联动业务)、
仓体级 batt_status/pow_status 显示在仓体;两端解析函数同源同名
- 能耗报表改实时聚合 charge_records(原 energy_stats 全表只读不写导致报表恒 0)+ 补复合索引
- 组织可见性:新增 GET /api/my-organizations(工厂全量、客户仅本组织)
- 仓体 status 仅表占用,充满/故障由 Redis 通道状态派生
- 订单/占用/队列运维缺口:h5 建单漏单、214 仓体自愈、device:reports 上限、死信 TTL、LimitNOFILE、
每日 mysqldump + 回滚点保留 5 次
- 文档:AGENTS.md 补层级可见性/数据范围/状态位约定/数据库工具/行为变化;docs/API.md 删除废弃 TCP 章节、接口总表对齐 mod.rs
153 lines
13 KiB
Plaintext
153 lines
13 KiB
Plaintext
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.50s
|
|
Running unittests src\main.rs (.cargo-check-target\debug\deps\pms_api-0e8b7d95b05a137e.exe)
|
|
|
|
running 145 tests
|
|
test db::migrate::tests::test_alignment_targets_cover_known_broken_columns ... ok
|
|
test db::migrate::tests::test_schema_sql_energy_columns_comment_unit_is_wh ... ok
|
|
test commands::tests::test_is_valid_command_target_rejects_imei_and_malformed ... ok
|
|
test commands::tests::test_is_valid_command_target_accepts_board_and_compartment ... ok
|
|
test db::migrate::tests::test_every_alignment_target_appears_verbatim_in_schema_sql ... ok
|
|
test db::migrate::tests::test_schema_sql_table_order_has_forward_reference_returns_none ... ok
|
|
test middleware::auth::tests::test_builtin_role_name_covers_all_valid_levels ... ok
|
|
test db::migrate::tests::test_referenced_tables_single_foreign_key_returns_table_name ... ok
|
|
test middleware::auth::tests::test_builtin_role_name_invalid_level_returns_none ... ok
|
|
test db::migrate::tests::test_legacy_column_comments_marker_matches_ddl ... ok
|
|
test middleware::auth::tests::test_builtin_role_name_operator_maps_to_normal_user ... ok
|
|
test middleware::auth::tests::test_builtin_role_name_super_admin_maps_to_super_admin ... ok
|
|
test middleware::auth::tests::test_builtin_role_name_org_admin_maps_to_org_admin ... ok
|
|
test middleware::auth::tests::test_check_permission_operator_empty_permissions_forbidden ... ok
|
|
test middleware::auth::tests::test_append_condition_handles_empty_clause ... ok
|
|
test middleware::auth::tests::test_org_condition_normal_admin ... ok
|
|
test db::migrate::tests::test_schema_sql_contains_no_timestamp_column ... ok
|
|
test middleware::auth::tests::test_org_condition_super_admin ... ok
|
|
test middleware::auth::tests::test_super_admin_role_level_constant_matches_mapping ... ok
|
|
test commands::tests::test_take_command_target_extracts_and_removes_id ... ok
|
|
test commands::tests::test_take_command_target_absent_returns_none ... ok
|
|
test commands::tests::test_take_command_target_rejects_invalid_id ... ok
|
|
test middleware::auth::tests::test_user_scope_allows_project ... ok
|
|
test db::migrate::tests::test_column_spec_from_target_parses_all_dimensions ... ok
|
|
test middleware::auth::tests::test_user_scope_default_is_unrestricted ... ok
|
|
test middleware::auth::tests::test_verify_password_invalid_hash ... ok
|
|
test middleware::auth::tests::test_org_condition_no_org ... ok
|
|
test routes::cabinet_tree::tests::test_build_filter_where_super_admin_ignores_scope ... ok
|
|
test routes::cabinet_tree::tests::test_build_filter_where_without_scope_is_unchanged ... ok
|
|
test routes::cabinet_tree::tests::test_channel_flags_has_data_and_status_code_match_frontend_mapping ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_counts_all_idle_channels_yield_zero_full_fault ... ok
|
|
test routes::cabinet_tree::tests::test_build_filter_where_scope_combines_with_bound_filter ... ok
|
|
test middleware::auth::tests::test_user_scope_project_condition_narrows_by_project ... ok
|
|
test routes::cabinet_tree::tests::test_build_filter_where_scope_applies_to_explicit_project_and_org_params ... ok
|
|
test routes::cabinet_tree::tests::test_build_filter_where_with_scope_appends_project_narrowing ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_counts_charging_channels_counted_as_charging ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_counts_fault_channels_counted_as_fault ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_counts_fault_wins_over_full_on_conflict ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_counts_full_channels_counted_as_full ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_counts_offline_missing_data_yields_zero_full_fault ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_charging_channel_sets_on_true ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_batt_fault_bits_map_to_fault ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_empty_channel_keeps_power_status ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_full_battery_prefers_full_over_charging ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_missing_fields_yields_idle_and_empty_hex ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_normalizes_hex_case_and_padding ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_pow_fault_maps_to_fault ... ok
|
|
test routes::cabinet_tree::tests::test_derive_channel_view_single_byte_yields_empty_hex ... ok
|
|
test routes::cabinet_tree::tests::test_device_access_sql_appends_scope_only_when_configured ... ok
|
|
test routes::cabinet_tree::tests::test_device_list_fields_in_sync ... ok
|
|
test routes::cabinet_tree::tests::test_parse_channel_key_accepts_real_channel_keys ... ok
|
|
test routes::cabinet_tree::tests::test_parse_channel_key_rejects_internal_keys ... ok
|
|
test routes::cabinet_tree::tests::test_parse_channel_key_rejects_out_of_range_and_malformed ... ok
|
|
test routes::cabinet_tree::tests::test_parse_hex_byte_rejects_malformed_values ... ok
|
|
test routes::cabinet_tree::tests::test_pick_non_empty_hex_keeps_00_but_drops_missing ... ok
|
|
test routes::cabinets::tests::test_apply_realtime_keeps_null_when_missing ... ok
|
|
test routes::cabinets::tests::test_cabinet_realtime_field_indices_are_in_sync ... ok
|
|
test routes::cabinets::tests::test_parse_cabinet_realtime_cabinet_status_bits_raw_hex ... ok
|
|
test routes::cabinets::tests::test_parse_cabinet_realtime_cabinet_status_missing_is_null_not_00 ... ok
|
|
test routes::cabinets::tests::test_parse_cabinet_realtime_missing_fields_stay_none ... ok
|
|
test routes::cabinets::tests::test_parse_cabinet_realtime_reads_voltage_current_and_temp ... ok
|
|
test routes::charge_orders::tests::test_order_scope_conditions_super_admin_exempt ... ok
|
|
test routes::charge_orders::tests::test_order_scope_conditions_org_isolation ... ok
|
|
test routes::charge_records::tests::test_build_export_where_scope_appends_to_existing_conditions ... ok
|
|
test routes::charge_orders::tests::test_order_scope_conditions_applies_scope ... ok
|
|
test routes::charge_records::tests::test_build_export_where_applies_scope_project_ids ... ok
|
|
test routes::energy_stats::tests::test_build_export_clause_empty_when_no_filters ... ok
|
|
test routes::energy_stats::tests::test_build_export_clause_targets_charge_records ... ok
|
|
test routes::energy_stats::tests::test_build_export_where_keeps_org_isolation ... ok
|
|
test routes::energy_stats::tests::test_clamp_range_bounds_illegal_values ... ok
|
|
test routes::energy_stats::tests::test_estimated_cost_unit_is_wh_times_80_cent_per_kwh ... ok
|
|
test routes::energy_stats::tests::test_time_window_uses_start_time_half_open_ranges ... ok
|
|
test routes::h5::tests::test_compartment_realtime_fields_order_matches_indexes ... ok
|
|
test routes::h5::tests::test_h5_list_pick_non_empty_hex_keeps_00_but_drops_missing ... ok
|
|
test routes::h5::tests::test_parse_compartment_realtime_garbage_is_none ... ok
|
|
test routes::h5::tests::test_parse_compartment_realtime_no_data_returns_none_not_zero ... ok
|
|
test routes::h5::tests::test_parse_compartment_realtime_reads_all_fields ... ok
|
|
test routes::h5::tests::test_parse_compartment_realtime_real_zero_is_kept ... ok
|
|
test routes::h5::tests::test_visible_org_scope_operator_sees_own_org_only ... ok
|
|
test routes::h5::tests::test_visible_org_scope_org_admin_sees_own_org_only ... ok
|
|
test routes::h5::tests::test_visible_org_scope_org_user_without_org_is_empty ... ok
|
|
test routes::h5::tests::test_visible_org_scope_super_admin_sees_all ... ok
|
|
test routes::h5::tests::test_visible_orgs_own_sql_filters_by_id ... ok
|
|
test routes::scope_guard::tests::test_access_sql_with_scope_narrows_by_project ... ok
|
|
test routes::scope_guard::tests::test_access_sql_without_scope_has_no_narrowing ... ok
|
|
test routes::scope_guard::tests::test_verify_org_ownership_rules ... ok
|
|
test routes::tests::test_is_allowed_origin_allows_whitelist ... ok
|
|
test routes::tests::test_is_allowed_origin_rejects_others ... ok
|
|
test routes::upload_guard::tests::test_sniff_image_ext_recognizes_bitmaps ... ok
|
|
test routes::upload_guard::tests::test_validate_image_upload_accepts_real_images ... ok
|
|
test routes::upload_guard::tests::test_validate_image_upload_rejects_scriptable_exts ... ok
|
|
test routes::upload_guard::tests::test_validate_image_upload_rejects_svg_content_with_image_ext ... ok
|
|
test routes::upload_guard::tests::test_validate_image_upload_rejects_unknown_ext ... ok
|
|
test workers::energy::tests::test_fixed_interval_is_conservative ... ok
|
|
test workers::energy::tests::test_full_hour_charge_magnitude ... ok
|
|
test workers::energy::tests::test_mwh_delta_real_world_case ... ok
|
|
test workers::energy::tests::test_mwh_delta_rejects_non_positive_inputs ... ok
|
|
test workers::energy::tests::test_mwh_delta_small_current_not_lost_by_rounding ... ok
|
|
test workers::energy::tests::test_mwh_delta_zero_current_no_accumulation ... ok
|
|
test workers::energy::tests::test_mwh_to_wh_rounding ... ok
|
|
test workers::energy::tests::test_order_energy_key_format ... ok
|
|
test workers::log_retention::tests::test_retention_constants_are_sane ... ok
|
|
test workers::report_worker::tests::test_board_channel_id_range_guards ... ok
|
|
test workers::report_worker::tests::test_build_spec_complete_topology_prefers_real_topology ... ok
|
|
test workers::report_worker::tests::test_build_spec_incomplete_topology_falls_back_to_legacy_cell ... ok
|
|
test workers::report_worker::tests::test_build_spec_legacy_cell_clamped_into_protocol_range ... ok
|
|
test workers::report_worker::tests::test_build_spec_never_produces_all_zero_spec ... ok
|
|
test workers::report_worker::tests::test_build_spec_no_cell_uses_constant_default ... ok
|
|
test workers::report_worker::tests::test_channel_battery_key_format_contract ... ok
|
|
test workers::report_worker::tests::test_channel_hex_len_constant ... ok
|
|
test workers::report_worker::tests::test_channel_status_key_format_contract ... ok
|
|
test workers::report_worker::tests::test_compartment_lock_key_is_identity ... ok
|
|
test workers::report_worker::tests::test_decide_order_action_boundary_is_strict ... ok
|
|
test workers::report_worker::tests::test_decide_order_action_create_when_no_active_order ... ok
|
|
test workers::report_worker::tests::test_decide_order_action_replace_on_different_battery ... ok
|
|
test workers::report_worker::tests::test_decide_order_action_skip_same_battery ... ok
|
|
test workers::report_worker::tests::test_decide_order_action_skip_when_either_battery_id_empty ... ok
|
|
test workers::report_worker::tests::test_is_unique_violation_ignores_non_database_errors ... ok
|
|
test workers::report_worker::tests::test_normalize_hex_byte_rejects_invalid ... ok
|
|
test workers::report_worker::tests::test_normalize_hex_byte_valid_and_lowercased ... ok
|
|
test workers::report_worker::tests::test_order_timeout_bound_goes_backwards ... ok
|
|
test workers::report_worker::tests::test_out_of_range_sample_contributes_zero_energy ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_case_insensitive_and_lowercased ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_doc_example_bat_in ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_doc_example_bat_out ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_doc_example_full ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_doc_example_off ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_empty_channel_keeps_power_status ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_handles_multibyte_without_panic ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_rejects_non_hex ... ok
|
|
test workers::report_worker::tests::test_parse_channel_hex_rejects_wrong_length ... ok
|
|
test workers::report_worker::tests::test_parse_compartment_id_accepts_two_segments ... ok
|
|
test workers::report_worker::tests::test_parse_compartment_id_rejects_invalid_values ... ok
|
|
test workers::report_worker::tests::test_parse_compartment_id_rejects_other_segment_counts ... ok
|
|
test workers::report_worker::tests::test_parse_compartment_id_rejects_out_of_range ... ok
|
|
test workers::report_worker::tests::test_pending_key_format_matches_device_server ... ok
|
|
test workers::report_worker::tests::test_power_fail_mask_semantics ... ok
|
|
test workers::report_worker::tests::test_sanitize_sample_value_accepts_in_range ... ok
|
|
test workers::report_worker::tests::test_sanitize_sample_value_rejects_out_of_range ... ok
|
|
test workers::report_worker::tests::test_should_finalize_bat_out_skips_late_report_of_previous_battery ... ok
|
|
test workers::report_worker::tests::test_should_finalize_bat_out_when_same_or_unknown_battery ... ok
|
|
test workers::report_worker::tests::test_compartment_lock_allows_different_compartments ... ok
|
|
test workers::report_worker::tests::test_compartment_lock_excludes_same_compartment ... ok
|
|
test middleware::auth::tests::test_verify_password_correct ... ok
|
|
test middleware::auth::tests::test_verify_password_wrong ... ok
|
|
|
|
test result: ok. 145 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.05s
|
|
|