Skip to content

Commit 1801efa

Browse files
committed
- Implement user management features: - add user creation and deletion with home directory option, password management, and enhance search functionality.
- Update UI for new user modal and password management. - Add unit tests for search and system operations.
1 parent 12d2616 commit 1801efa

File tree

8 files changed

+462
-37
lines changed

8 files changed

+462
-37
lines changed

Improvements.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,40 @@ User management is inherently high-risk from a security perspective
130130

131131
- Provide transparent operation for debugging
132132

133-
- Handle partial failures gracefully in multi-user operations
133+
- Handle partial failures gracefully in multi-user operations
134+
135+
## Further Tests
136+
137+
### High‑value additions
138+
139+
- **Parsing edge cases (unit, in `src/sys/mod.rs`)**
140+
- Empty lines, comments, missing fields, extra fields.
141+
- Invalid numeric UIDs/GIDs → parsed as 0, no panics.
142+
- `/etc/shells` parsing ignores comments/blank lines.
143+
- `groups_for_user` returns primary group and supplementary memberships.
144+
- `format_cli_error` formats empty vs non‑empty stderr correctly.
145+
146+
- **Search behavior (unit, in `src/search.rs`)**
147+
- Empty query resets lists and selection index to 0.
148+
- Numeric queries match UID/GID string forms.
149+
- Case‑insensitive matches on full name, home, shell, group members.
150+
- Selection index clamping after filter (stays at 0 regardless of length).
151+
152+
- **State machine/input handling (unit, in `src/app/update.rs`)**
153+
- Tab/BackTab toggles `active_tab` and `users_focus`.
154+
- Arrow keys/page moves clamp within bounds for users vs member‑of lists.
155+
- `n` opens `UserAddInput` with `create_home = true`.
156+
- Non‑privileged flows that only open/close modals (no system calls).
157+
- Optional refactor: extract small pure helpers for index math to test easily.
158+
159+
- **UI rendering sanity (integration/snapshot)**
160+
- Use `ratatui::backend::TestBackend` to render a small `AppState` and assert key labels/titles/row highlights. Consider `insta` for snapshots.
161+
162+
- **Command‑line parsing (unit)**
163+
- If `clap` is used in `main.rs`, test flags/env via `Command::try_get_matches_from` (no TUI needed).
164+
165+
- **Architecture for privileged ops (mockable)**
166+
- Introduce a `trait System` that `SystemAdapter` implements; inject into `perform_pending_action` so tests can verify:
167+
- Correct command path chosen (add/remove user to group, change shell/name).
168+
- App state refreshes (`users_all`, `groups_all`), and info messages.
169+
- Without this, keep privileged paths out of tests.

README.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ UsrGrp-Manager-TUI (Rust Users/Groups Manager TUI)
22
================
33

44
## Description
5-
Keyboard‑driven terminal app to view and manage users and groups. Browse accounts, see memberships, search, and make common changes: rename users, update names or shells, adjust group membership. Safe to explore without admin rights; asks for permission to apply changes. Linux‑focused.
5+
Keyboard‑driven terminal app to view and manage users and groups. Browse accounts, see memberships, search, and make common changes: rename users, update names or shells, adjust group membership. Safe to explore without admin rights; asks for permission to apply changes. Linux‑focused. Written in Rust.
66

77
## Status
8-
Alpha. Read‑only browsing is safe; write operations require privileges and are limited (no user deletion yet).
8+
Alpha. Read‑only browsing is safe; write operations require privileges and are still limited.
99

1010
Alpha means:
1111
- Interfaces and keybindings may change without notice.
12-
- Some actions are intentionally missing or guarded (e.g., user deletion not implemented).
12+
- Some actions are intentionally guarded (e.g., user deletion requires confirmation; optional home removal).
1313
- Error handling, edge cases, and performance are still being improved.
14-
- Expect to run with `sudo` for any write operation (`usermod`, `gpasswd`, `groupadd`, `groupdel`).
14+
- Expect to run with `sudo` for any write operation (`usermod`, `gpasswd`, `groupadd`, `groupdel`, `useradd`, `userdel`).
1515

1616
## Install / Build
1717
---------------
@@ -33,13 +33,24 @@ Alpha means:
3333
- Open actions on selection: `Enter`
3434
- In popups: `↑/k`, `↓/j`, `PageUp`, `PageDown`, `Enter`, `Esc`
3535

36+
- New user: `n` (toggle "Create home" with `Space`)
37+
- Delete confirmation: `Space` toggles "Also delete home"
38+
- Password: Actions → Modify → Password
39+
- Set/change: masked input with confirm; toggle "must change at next login" with `Space`; select Submit and press `Enter`
40+
- Reset: expire password immediately (forces change at next login)
41+
3642
## What’s implemented
3743
------------------
3844

3945
- Users tab
4046
- Table of users (from `/etc/passwd`), selection, paging
4147
- Detail pane: UID, GID, name, home, shell
4248
- Member‑of pane: primary and supplementary groups
49+
- Create user (`useradd`; optional `-m` to create home)
50+
- Delete user (`userdel`; optional `-r` to remove home)
51+
- Password management:
52+
- Set/change (masked via `chpasswd`, optional "must change at next login")
53+
- Reset (expire now via `chage -d 0`)
4354
- Actions → Modify:
4455
- Add user to groups (via `gpasswd -a`)
4556
- Remove user from groups (via `gpasswd -d`, excluding primary group)
@@ -62,14 +73,14 @@ Alpha means:
6273
--------------------
6374

6475
- Linux/BSD only. macOS behavior may differ (Directory Services).
65-
- Write actions call system tools and require appropriate privileges (root or sudo): `usermod`, `gpasswd`, `groupadd`, `groupdel`.
66-
- User deletion is not implemented yet (guarded with a confirmation and an informational message).
76+
- Write actions call system tools and require appropriate privileges (root or sudo): `usermod`, `gpasswd`, `groupadd`, `groupdel`, `useradd`, `userdel`, `chpasswd`, `chage`.
77+
- User deletion is implemented with confirmation and optional home removal.
6778

6879
## TODO (next steps)
6980
-----------------
7081

7182
- Lock/unlock, enable/disable login shell: show status in table; actions in detail view; confirm + dry‑run; apply via `usermod -L/-U` and `chsh` (or edit `/etc/passwd` when in file‑parse mode)
72-
- Password set/reset with strength checks: masked prompt; basic rules or zxcvbn; optional "must change at next login"; respect PAM; clear error messages
83+
- Password strength checks/validation: enforce basic rules or integrate zxcvbn; respect PAM policies; clearer error messages
7384
- Fuzzy find users/groups: incremental filtering while typing; highlight matches; toggle fuzzy vs substring; performance guard for large datasets
7485
- Filters (system vs human, inactive, expired, locked, no home, no password): quick filter menu; combinable chips; persisted per session; NSS‑aware where possible
7586
- Multi‑select bulk ops (add to groups, lock, shell change, expiry set): selection mode with count; preview + confirmation; batched execution with per‑item results and rollback on failure
@@ -83,6 +94,23 @@ Alpha means:
8394
- Build: `cargo build --release`
8495
- Run: `cargo run --release`
8596

97+
## Tests
98+
-----
99+
100+
- Run all tests: `cargo test`
101+
102+
What’s covered today:
103+
- Unit tests for parsers in `src/sys/mod.rs` (fake `/etc/passwd` and `/etc/group` files).
104+
- Unit tests for filtering in `src/search.rs` (case‑insensitive user/group search, membership matching).
105+
106+
Guidelines:
107+
- Keep small unit tests inline next to the code with `#[cfg(test)]` for private helpers and pure logic.
108+
- For broader or cross‑module tests, add a `src/lib.rs` exposing modules (e.g., `pub mod app; pub mod search; pub mod sys;`) and place integration tests in `tests/`.
109+
- Avoid invoking privileged commands (`useradd`, `gpasswd`, etc.) in tests. Prefer testing pure parts (parsing, filtering) or introduce a trait to mock `SystemAdapter` in higher‑level tests.
110+
111+
Optional:
112+
- UI snapshot/sanity tests can be written using `ratatui`’s test backend (and, if desired, a snapshot tool like `insta`). These should render minimal views and assert on expected labels/highlights, not terminal specifics.
113+
86114
## Project Structure
87115
```
88116
src/

src/app/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ pub enum ModalState {
6666
ModifyDetailsMenu { selected: usize },
6767
ModifyShell { selected: usize, offset: usize, shells: Vec<String> },
6868
ModifyTextInput { field: ModifyField, value: String },
69-
DeleteConfirm { selected: usize, allowed: bool },
69+
DeleteConfirm { selected: usize, allowed: bool, delete_home: bool },
70+
ModifyPasswordMenu { selected: usize },
71+
ChangePassword { selected: usize, password: String, confirm: String, must_change: bool },
7072
Info { message: String },
7173
SudoPrompt { next: PendingAction, password: String, error: Option<String> },
7274
GroupsActions { selected: usize, target_gid: Option<u32> },
@@ -75,6 +77,7 @@ pub enum ModalState {
7577
GroupModifyMenu { selected: usize, target_gid: Option<u32> },
7678
GroupModifyAddMembers { selected: usize, offset: usize, target_gid: Option<u32> },
7779
GroupModifyRemoveMembers { selected: usize, offset: usize, target_gid: Option<u32> },
80+
UserAddInput { name: String, create_home: bool },
7881
}
7982

8083
#[derive(Clone, Debug)]
@@ -89,6 +92,10 @@ pub enum PendingAction {
8992
ChangeUsername { old_username: String, new_username: String },
9093
CreateGroup { groupname: String },
9194
DeleteGroup { groupname: String },
95+
CreateUser { username: String, create_home: bool },
96+
DeleteUser { username: String, delete_home: bool },
97+
SetPassword { username: String, password: String, must_change: bool },
98+
ResetPassword { username: String },
9299
}
93100

94101
pub struct AppState {

0 commit comments

Comments
 (0)