diff --git a/Makefile b/Makefile index 7b4b6d6..8cfd75d 100644 --- a/Makefile +++ b/Makefile @@ -1,103 +1,22 @@ -TRIDENT := ${PWD} -GOPATH := ${PWD}/ext/_gopath -export GOPATH - ifndef $GIT_BRANCH - GIT_BRANCH := `git rev-parse --abbrev-ref HEAD 2>/dev/null || printf "nogit"` + GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || printf "nogit") endif -# Pull correct branches for PF from local files. -PF_GIT_BRANCH = master -PF_GIT_REPO = https://github.com/tridentli/pitchfork.git - -# dpkg-buildpackage calls make, so should be empty. all: @echo "All does nothing" help: - @echo "all - Build it all (called from dpkg-buildpackage)" - @echo "clean_ext - cleans 'ext' directory" - @echo "pkg - ext+deps+pkg_only" - @echo "pkg_only - Only builds Debian package (no dependency updates)" + @echo "check - runs: go vet/fmt" + @echo "tests - Runs all Golang based tests" + @echo "vtests - Runs all Golang based tests (verbose)" @echo "versions - Show pre-selected versions" - @echo "ext - Fetches initial external dependencies (for use by local devs or trident-ext-pkg)" - @echo "deps - Updates external dependencies (for use by local devs or trident-ext-pkg)" - @echo "build_ext - Create a GOPATH version of the local trident dir" - @echo "check - runs: go vet/fmt, also on Pitchfork" - @echo "tests - Runs all Golang based tests" - @echo "vtests - Runs all Golang based tests (verbose)" - -clean_ext: - @echo "Cleansing 'ext'" - @rm -rf ext - -pkg: ext deps pkg_only - -pkg_only: build_ext - @echo "Starting package build..." - dpkg-buildpackage -uc -us -F - @echo "Starting package build - done" versions: @echo "Trident: $(GIT_BRANCH)" - @echo "Pitchfork: $(PF_GIT_BRANCH)" @echo @printf "Go version: "; go version @printf "Trident branch: "; git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "nogit"; printf "Trident Git commit: "; git rev-parse HEAD 2>/dev/null || echo "nogit" @echo - @printf "Build OS: " - @if [ -f /etc/debian_version ]; then printf "Debian "; cat /etc/debian_version; else echo "Not Debian"; fi - @echo - -build_ext: - @echo "Creating temporary 'ext' for build..." - - @echo - @echo "Creating 'ext' directory for external dependencies and gopath" - @mkdir -p ext/_gopath/src/trident.li - @echo "Symlink Trident into GOPATH" - @ln -s ../../../../ ext/_gopath/src/trident.li/trident - -ext: - @$(MAKE) versions - @echo "Retrieving 'ext' dependencies..." - - @echo "Git Clone Pitchfork into GOPATH [ $(PF_GIT_BRANCH) ]" - @mkdir -p ext/_gopath/src/trident.li - @git clone -b $(PF_GIT_BRANCH) $(PF_GIT_REPO) ext/_gopath/src/trident.li/pitchfork - - @echo - @echo "Clone Trident Go Dependencies" - @mkdir -p ext/_gopath/src/trident.li - @git clone https://github.com/tridentli/go ext/_gopath/src/trident.li/go - - @echo - @echo "Retrieving 'ext' dependencies - done" - @echo - -deps: ext - @$(MAKE) versions - @echo "Updating 'ext' Dependencies..." - - @echo - @echo "Updating Pitchfork..." - @cd ext/_gopath/src/trident.li/pitchfork; (git pull 2>/dev/null && git checkout ${PF_GIT_BRANCH} && printf "Pitchfork branch: " && git rev-parse --abbrev-ref HEAD && printf "Pitchfork GIT commit: " && git rev-parse HEAD) || echo "NO GIT" - - @echo - @echo "Updating Pitchfork dependencies" - @cd ext/_gopath/src/trident.li/pitchfork && $(MAKE) deps - - @echo - @echo "Updating Trident Go Dependencies" - @cd ext/_gopath/src/trident.li/go; git pull 2>/dev/null || echo "NO GIT" - - @echo - @echo "Updating Golang dependencies (imports)..." - @GOPATH=${PWD}/ext/_gopath go get -v -d -t ./... - - @echo - @echo "Updating Dependencies - done" - @echo check: @echo "Running 'go vet'" @@ -108,11 +27,9 @@ check: tests: @echo "Running 'go test'..." @go test ./... - @cd ext/_gopath/src/trident.li/pitchfork && make tests vtests: @echo "Running 'go test' (verbose)..." @go test -v ./... - @cd ext/_gopath/src/trident.li/pitchfork && make vtests -.PHONY : all help clean_ext pkg pkg_only versions deps check tests vtests +.PHONY : all help check tests vtests versions diff --git a/doc/modernization/modernization_plan.md b/doc/modernization/modernization_plan.md new file mode 100644 index 0000000..8cea3e1 --- /dev/null +++ b/doc/modernization/modernization_plan.md @@ -0,0 +1,113 @@ +# Phased Modernization and Security Review Plan for Trident + +This document outlines a phased plan to modernize the Trident codebase, transition it to modern Go standards, establish a robust testing harness with high code coverage, and conduct a thorough security review. + +--- + +## Phase 1: Build System & Dependency Modernization (Completed) + +**Objective**: Transition the codebase fully to modern Go Modules, eliminating legacy `GOPATH` requirements and ensuring the project can be built and tested using standard Go toolchain commands. + +### 1.1. Go Module Transition & Clean Up +* **Issue**: The current build system relies on a legacy `GOPATH` hack (`ext/_gopath`) and clones dependencies manually via Git in the `Makefile`. +* **Tasks**: + * [x] Permanently adopt Go Modules (`go.mod`). + * [x] Update the `go.mod` file to use a modern Go version (e.g., `go 1.21` or higher) to leverage modern language features and security updates. (Updated to Go 1.26.2). + * [x] Configure `replace` directives in `go.mod` to point to local checkouts ... or migrate them to standard GitHub import paths. (Migrated to GitHub import paths: `github.com/tridentli/pitchfork`, `github.com/tridentli/go`, and `github.com/secludedsoc/keyval` to fully eliminate local checkout requirements). + * [x] Ensure all local dependency repositories have valid, tidied `go.mod` files. (N/A: bypassed by using GitHub replaces). + * [x] Clean up the `Makefile` to remove `GOPATH` exports and replace legacy commands with standard `go build`, `go test`, and `go vet` commands. + +### 1.2. Code Quality & Static Analysis (Style Fixes) +* **Issue**: `go vet` currently flags multiple warnings regarding unkeyed struct literals in menu definitions (e.g., `PfMEntry` and `PfUIMentry`). +* **Tasks**: + * [x] Refactor all struct initializations to use keyed fields. + * [x] Integrate `go vet` and `go fmt` checks as blocking steps in the local development loop. (Integrated into Makefile `check` target). + +--- + +## Phase 2: Test Harness & Unit Testing Strategy + +**Objective**: Introduce a comprehensive test suite targeting near 100% code coverage for core business logic in `src/lib/`, and establish an automated test execution environment. + +### 2.1. Establish the Test Harness +* **Database Dependency**: Trident relies heavily on PostgreSQL. Running unit tests requires a strategy to handle database operations without polluting production or requiring a complex local DB setup for every developer. +* **Proposed Solutions**: + 1. **Unit Testing with Mocking**: Use `github.com/DATA-DOG/go-sqlmock` to mock database responses for unit tests in `src/lib/` (e.g., testing `user.go`, `vouch.go` logic without a real DB). This is fast and suitable for pure unit tests. + 2. **Integration Testing with Testcontainers**: Use `github.com/testcontainers/testcontainers-go` to automatically spin up a temporary PostgreSQL Docker container during test execution. This allows running integration tests against a real database with the actual schema applied, ensuring query compatibility. + * **Decision**: We will implement **both**: `go-sqlmock` for rapid unit tests of business logic, and `testcontainers` for database-centric integration tests. + +### 2.2. Unit Testing Targets (`src/lib/`) +* **User Management (`src/lib/user.go`)**: + * Test `IsNominator` and `BestNominator` with mocked DB states. + * Test `user_pw_send` (split password recovery): Verify that the recovery token is correctly generated, split into two unique halves, hashed/stored correctly, and that the correct emails are dispatched to the user and nominator. + * Test `user_merge` transactional integrity. +* **Vouching Registry (`src/lib/vouch.go`)**: + * Test vouch validation rules: Ensure a user cannot vouch for themselves, cannot vouch without meeting group attestations, and that positive/negative vouches transition member states correctly. +* **Group Attestations (`src/lib/group_attestation.go`)**: + * Test parsing and validation of custom group attestations. + +### 2.3. UI Testing (`src/ui/`) +* * Use `net/http/httptest` to mock HTTP requests and responses. + * Verify that UI handlers correctly parse form inputs, enforce session permissions, and call the underlying library functions. + * Verify that HTML outputs are correctly sanitized using `Blue Monday`. + +### 2.4. CI/CD Integration (GitHub Actions) +* Define a GitHub Actions workflow (`.github/workflows/test.yml`) that: + 1. Runs on every push and Pull Request. + 2. Sets up a modern Go environment. + 3. Starts a PostgreSQL service container (or relies on Testcontainers). + 4. Runs `go vet ./...` and `go fmt` checks. + 5. Runs all tests with race detection enabled: `go test -race -coverprofile=coverage.out ./...`. + 6. Reports code coverage metrics. + +--- + +## Phase 3: Code Refactoring & Idiomatic Go Adoption + +**Objective**: Clean up legacy code patterns, improve safety, and adopt modern Go idioms. + +### 3.1. Language Feature Upgrades (Go 1.21+) +* **Structured Logging**: Replace custom verbose logging/debugging with the standard `log/slog` package for structured, levels-based logging. +* **Slices & Maps**: Replace manual slice manipulation loops with functions from the standard `slices` and `maps` packages. +* **Context Propagation**: Ensure `context.Context` is passed through all database and network boundary calls (e.g., propagating context from HTTP requests down to `pgx` database queries) to support cancellation and timeouts. + +### 3.2. Refactoring Package Names and Cycle Resolution +* Resolve the duplicate `crypt` package naming (in `osutil-crypt` and its `common` subdirectory) by renaming the internal packages to be distinct (e.g., `common` to `cryptcommon` or merging them) to prevent import shadowing and confusion. +* Ensure explicit error wrapping using `fmt.Errorf("...: %w", err)` to preserve error chains for debugging. + +--- + +## Phase 4: Deep Security Review Plan & Findings Mitigation + +**Objective**: Conduct a rigorous security assessment of Trident's high-trust model and establish a clear protocol for addressing vulnerabilities. + +### 4.1. Static & Dynamic Security Scanning +* **SAST (Static Application Security Testing)**: + * Integrate `github.com/securego/gosec/v2` into the CI/CD pipeline to scan for Go-specific security issues (e.g., hardcoded credentials, weak cryptography, unsafe SQL query construction). +* **Vulnerability Scanning**: + * Use `govulncheck` to identify known vulnerabilities in imported dependencies. + +### 4.2. Targeted Manual Security Audits +Given Trident's threat model (high-trust threat intelligence exchange), we must manually audit these critical areas: + +1. **Split Password Recovery Flow**: + * **Entropy**: Verify that the random generator used for `user_portion` and `nom_portion` (`pw.GenPass`) uses a cryptographically secure source (`crypto/rand`) and has sufficient entropy. + * **Storage**: Ensure the combined hash stored in the DB uses a modern secure hashing algorithm (e.g., bcrypt, Argon2id) and is not vulnerable to timing attacks during comparison. + * **Transit**: Verify that the transit channels (emails) are encrypted (enforced STARTTLS in Postfix configuration). +2. **SQL Injection Prevention**: + * Review all raw SQL strings in `src/lib/` and `pitchfork`. Ensure *all* queries use parameterized placeholders (`$1`, `$2`) and that no string concatenation of user input occurs. +3. **Cross-Site Scripting (XSS) in Wiki & UI**: + * Review the rendering pipeline of the Wiki. Ensure that `Blue Monday` sanitization is applied *immediately before* rendering to the user and that no unescaped templates allow bypasses. + * Audit the dual Markdown engine setup to ensure no discrepancies allow "mutation XSS" (where preview behaves differently from final rendered output in a exploitable way). +4. **Session & Authentication (JWT)**: + * Review JWT signing key generation and storage. Ensure keys are loaded securely and rotated. + * Verify JWT expiration times and revocation mechanisms (if any). + * Ensure secure cookie flags (`Secure`, `HttpOnly`, `SameSite`) are enforced in production (disabling them only via explicitly flagged development arguments like `--insecurecookies`). + +### 4.3. Handling Security Findings +* **Triage Process**: Findings from scans and audits will be logged in a secure, restricted tracker and triaged by severity (Critical, High, Medium, Low). +* **Remediation SLA**: + * *Critical/High*: Fix within 14 days. + * *Medium*: Fix within 30 days. + * *Low*: Fix within 90 days. + * **Coordinated Disclosure**: Since Trident is a community project, establish a secure security contact (currently `project@trident.li`) and a policy for coordinated disclosure, allowing existing operators of Trident instances to update before details are made public. diff --git a/doc/modernization/overview.md b/doc/modernization/overview.md new file mode 100644 index 0000000..bbc7920 --- /dev/null +++ b/doc/modernization/overview.md @@ -0,0 +1,165 @@ +# Trident Codebase Overview + +Trident is a **Trusted Information Exchange Toolkit** designed as a modernized, full redesign and rewrite in [Go](https://golang.org/) of the original [Ops-Trust Portal](https://github.com/ops-trust/portal/) software. Its primary purpose is to power highly secure, vetted, trust-based communication communities (such as [Ops-Trust](https://www.ops-trust.net)) where members share sensitive threat intelligence, coordinate incident response, and exchange security notifications. + +--- + +## 1. Core Purpose & High-Trust Model + +Unlike generic collaboration systems, Trident assumes a threat model and operational environment where membership is strictly controlled by human-to-human trust. The core value proposition of the toolkit is to manage the lifecycle of this trust-based network through several distinct properties: + +- **Vetting-Based Membership**: A new user cannot simply sign up. They must be **Nominated** by an existing active member. To become an active member, they must be **Vouched** for by multiple active members of a specific trust group. +- **Structured Attestations**: Vouches are not simple ratings. A vouch is backed by specific, mandatory assertions (attestations), such as: + * *"I have met them in person more than once"* + * *"I trust them to take action"* + * *"I will share membership fate with them"* +- **Dual-Token Account Recovery (Split Passwords)**: To prevent account-takeover and ensure physical/social verification, resetting a password or setting up a new account requires split-token coordination. One part of the recovery token is sent to the user's registered email; the other part is sent to their **Nominator**. The user must contact their nominator through a trusted out-of-band channel to retrieve the other half of the token to gain account access. + +--- + +## 2. System Architecture + +Trident uses a clean, separation-of-concerns architecture. Instead of bundling generic community portal logic with the custom trust-network logic, the core framework has been split into a separate, reusable library project called **Pitchfork** (`trident.li/pitchfork`). + +### Architectural Topology + +```mermaid +graph TD + subgraph Client Layer + TCLI[tcli CLI Client] + WebUI[Web UI / Browser] + TSetup[tsetup DB Admin CLI] + end + + subgraph Application Server (tridentd) + TriDaemon[tridentd Daemon] + TriUI[trident.li/trident/src/ui] + TriLib[trident.li/trident/src/lib] + + subgraph Core Framework (pitchfork) + PfServer[pitchfork/cmd/server] + PfUI[pitchfork/ui] + PfLib[pitchfork/lib] + end + end + + subgraph Database Layer + DB[(PostgreSQL Database)] + end + + TCLI -->|REST API / JWT| TriDaemon + WebUI -->|HTTP / OAuth2 / OpenID| TriDaemon + TSetup -->|Direct SQL / Admin| DB + + TriDaemon --> PfServer + TriUI --> PfUI + TriLib --> PfLib + + PfLib -->|SQL Queries| DB + TriLib -->|Domain SQL Queries| DB +``` + +### The Pitchfork Extension Design + +Trident implements a modular plug-in pattern on top of the Pitchfork framework: +1. **Context Extension (`TriCtx`)**: Trident wraps Pitchfork's `PfCtx` to maintain domain-specific context data, such as the selected vouchee (`TriUser`) during vouching workflows. +2. **User Customization (`TriUser`)**: Adds domain-specific user methods like checking if another user is a valid nominator (`IsNominator`) and discovering the best nominator (`BestNominator`). +3. **Group Customization (`TriGroup`)**: Extends groups to handle complex parameter controls (e.g., min/max inbound and outbound vouches required for active status, inactivity expirations, and nomination settings) and introduces structured attestations. +4. **Vouch Customization (`TriVouch`)**: Implements the data structures and query interfaces mapping vouchors to vouchees within specific trust groups. + +--- + +## 3. Key Core Modules + +### User Management & Split Password Flow (`src/lib/user.go`, `src/lib/mail.go`) +Ensures that account creation and password recovery are structurally authenticated by trust chains. When a recovery/setup is triggered (`user_pw_reset`): +1. A random recovery token is split into two halves: the User Portion and the Nominator Portion. +2. **User Portion**: Emailed directly to the target user (`Mail_PassResetUser`). +3. **Nominator Portion**: Emailed to their verified nominator (`Mail_PassResetNominator`). +4. The database stores the combined hash (`SetRecoverToken`). The user can only complete recovery at `/recover/` when they input both parts correctly. + +### Trust Groups & Attestations (`src/lib/group.go`, `src/lib/group_attestation.go`) +Trust groups maintain their own specific security parameters. Administrative controls allow each group to define: +- Minimum incoming vouches needed to vet a user. +- Minimum outgoing vouches a user must make to maintain active status. +- The list of customized vouching requirements (attestations). + +### Vouching Registry (`src/lib/vouch.go`) +Tracks active and historical vouches. It validates that all required group attestations are satisfied before allowing a vouch to be inserted. + +### UI Web & API Routing (`src/ui/`) +Trident provides a clean web interface by overriding and extending the Pitchfork UI menus and handler functions (`TriUIMenuOverride`): +- Renders profile views displaying incoming/outgoing vouches. +- Interfaces directly with the underlying library core via commands (e.g., `group member add`, `group vouch add`). + +--- + +## 4. Member Lifecycle States + +Membership is tracked through a fine-grained state machine. The transition table governs member capabilities: + +```mermaid +stateDiagram-v2 + [*] --> Nominated : Nomination + Nominated --> Vetted : Sufficient Invouches + Nominated --> Failed : Timeout / Unvetted + Vetted --> Approved : Admin Approval + Approved --> Active : Meet Checklist (PGP, Outvouches) + + Active --> Inactive : Lost PGP / Dropped Vouches + Inactive --> Active : Key added / Vouched again + + Active --> SoonIdle : Inactivity warning + SoonIdle --> Active : Login / Activity + SoonIdle --> Idle : Continued inactivity + Idle --> Active : Login / Activity + + state Blocked { + [*] --> AdminBlocked + } + + Active --> Blocked : Admin Negvouch / Investigation + Nominated --> Blocked : Admin Negvouch + Vetted --> Blocked : Admin Negvouch +``` + +### Member Capabilities Table + +| State | Can Login | Can See Directory & Wiki | Can Send Group Mail | Can Recv Group Mail | Blocked | Hidden | +| :--- | :---: | :---: | :---: | :---: | :---: | :---: | +| **Nominated** | False | False | False | False | False | False | +| **Vetted** | False | False | False | False | False | False | +| **Approved** | True | True | False | False | False | False | +| **Active** | True | True | True | True | False | False | +| **Inactive** | True | True | True | False | False | False | +| **Blocked** | False | False | False | False | True | True | +| **Failed** | False | False | False | False | False | True | +| **SoonIdle** | True | True | True | True | False | False | +| **Idle** | True | True | True | False | False | False | + +--- + +## 5. Database Architecture & Migration Strategy + +Trident relies heavily on relational integrity and transactional security in PostgreSQL. + +- **Data Isolation & DB Grantees**: Database migrations and schema structures are executed as the database owner (`postgres`). The running application user (`trident`) is configured with standard CRUD privileges (`SELECT`, `INSERT`, `UPDATE`, `DELETE`) but cannot modify database schema topology. +- **Transactional Migrations**: Every database migration (located under `share/dbschemas/`) is packaged in standard transactional SQL format: + ```sql + BEGIN; + -- Alterations here + UPDATE system SET db_version = ; + COMMIT; + ``` + This ensures atomic database state upgrades; any migration failure will automatically roll back changes, preventing database corruption. + +--- + +## 6. Operational & Administrative Core Utilities + +Trident provides three specialized binaries and one migration tool in its build setup: + +1. **`tridentd` (Daemon)**: The background HTTP/S server. Runs on port `8333` by default. Provides the JSON REST API (with JWT authentication) and the core web portal interface. Designed to be run behind a TLS terminating proxy (like Nginx). +2. **`tcli` (Command Line Client)**: Pronounced *"Tickly"*. Allows full administration and automation by issuing JSON REST API commands directly to `tridentd`. Reads credentials from `~/.trident_token` (customizable using the `TRIDENT_TOKEN` environment variable). +3. **`tsetup` (Database & Admin Setup)**: Staging and schema management CLI utility. Must be executed under database administrative rights (e.g. the `postgres` system user). Used for bootstrapping the DB (`setup_db`), creating initial admins (`adduser`), and performing migrations (`upgrade_db`). +4. **`twikiexport`**: Command-line utility to export historical legacy trust group wikis (like FosWiki) into standard compressed tar archives, which can then be cleanly imported into Trident wikis using `tcli`. diff --git a/go.mod b/go.mod index e93ad0a..8b5544b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module trident.li/trident -go 1.18 +go 1.26.2 require ( trident.li/keyval v0.0.0-20220511083218-ca9b9e7f42ab @@ -35,3 +35,9 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect trident.li/go v0.0.0-20161021100159-4bb271e8a450 // indirect ) + +replace trident.li/pitchfork => github.com/tridentli/pitchfork v1.4.6-0.20220511083412-a5bad841e7b0 + +replace trident.li/keyval => github.com/secludedsoc/keyval v0.0.0-20220511083218-ca9b9e7f42ab + +replace trident.li/go => github.com/tridentli/go v0.0.0-20161021100159-4bb271e8a450 diff --git a/go.sum b/go.sum index 0592be2..ed359de 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,7 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -37,13 +38,20 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/secludedsoc/keyval v0.0.0-20220511083218-ca9b9e7f42ab h1:NmRWEzcRLTyjKB+/P8tvl7go1vE6PxKOi+R+16pIBlA= +github.com/secludedsoc/keyval v0.0.0-20220511083218-ca9b9e7f42ab/go.mod h1:FQWKo+Kz5zMDgQe9iFvkwd1g0hCMGoqrToHjKZr3gpI= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636 h1:aSISeOcal5irEhJd1M+IrApc0PdcN7e7Aj4yuEnOrfQ= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/highlight_go v0.0.0-20191220051317-782971ddf21b h1:rBIwpb5ggtqf0uZZY5BPs1sL7njUMM7I8qD2jiou70E= github.com/shurcooL/highlight_go v0.0.0-20191220051317-782971ddf21b/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/tridentli/go v0.0.0-20161021100159-4bb271e8a450 h1:sTbXt2T+q2XuwHMGZGV8ARcOjW/NZUEZvYjzbP/Bs4U= +github.com/tridentli/go v0.0.0-20161021100159-4bb271e8a450/go.mod h1:PgS8aHg1g3/e4nQFtZGtzO39PcwgXnywzSbai9pHJpo= +github.com/tridentli/pitchfork v1.4.6-0.20220511083412-a5bad841e7b0 h1:0sx0sKmtFP6N7CkCX9XMsH0u9JVxXO7fRM5aqYG8t+I= +github.com/tridentli/pitchfork v1.4.6-0.20220511083412-a5bad841e7b0/go.mod h1:ETCwKJgp42Q5dogTQ8bo3/bcnUQ7bZIte7oU9jv9Zpg= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -69,9 +77,3 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -trident.li/go v0.0.0-20161021100159-4bb271e8a450 h1:7dul4gtgXO2S/J2Mlhd3Xy+ZWd7VSDGteJY56hF6Bkk= -trident.li/go v0.0.0-20161021100159-4bb271e8a450/go.mod h1:cvsYz/H6ez4T7FS88ECu9/BwYkhRwDaDUqyR3f3OwoY= -trident.li/keyval v0.0.0-20220511083218-ca9b9e7f42ab h1:ANgOjsKOjjm0wMLRzqoBU/0gI1e14GB9X3+I0NcPbKc= -trident.li/keyval v0.0.0-20220511083218-ca9b9e7f42ab/go.mod h1:FQWKo+Kz5zMDgQe9iFvkwd1g0hCMGoqrToHjKZr3gpI= -trident.li/pitchfork v1.4.6-0.20220511083412-a5bad841e7b0 h1:i2dOXU+7hzaWdipR1EMH+LeAH0qUS594A7ef6YzdAGI= -trident.li/pitchfork v1.4.6-0.20220511083412-a5bad841e7b0/go.mod h1:ETCwKJgp42Q5dogTQ8bo3/bcnUQ7bZIte7oU9jv9Zpg= diff --git a/src/lib/group.go b/src/lib/group.go index f193f77..ffedf51 100644 --- a/src/lib/group.go +++ b/src/lib/group.go @@ -357,8 +357,8 @@ func group_menu(ctx pf.PfCtx, menu *pf.PfMenu) { menu.Replace("add", group_add) m := []pf.PfMEntry{ - {"vouch", vouch_menu, 0, -1, nil, pf.PERM_USER, "Vouch Commands"}, - {"nominate", group_member_nominate, 2, 2, []string{"group", "username"}, pf.PERM_GROUP_MEMBER, "Nominate a member for a group"}, + {Cmd: "vouch", Fun: vouch_menu, Args_min: 0, Args_max: -1, Args: nil, Perms: pf.PERM_USER, Desc: "Vouch Commands"}, + {Cmd: "nominate", Fun: group_member_nominate, Args_min: 2, Args_max: 2, Args: []string{"group", "username"}, Perms: pf.PERM_GROUP_MEMBER, Desc: "Nominate a member for a group"}, } menu.Add(m...) diff --git a/src/lib/group_attestation.go b/src/lib/group_attestation.go index 66f7bcb..b5a947a 100644 --- a/src/lib/group_attestation.go +++ b/src/lib/group_attestation.go @@ -133,9 +133,9 @@ func grp_attestation_delete(ctx pf.PfCtx, args []string) (err error) { func attestation_menu(ctx pf.PfCtx, args []string) (err error) { menu := pf.NewPfMenu([]pf.PfMEntry{ - {"list", grp_attestation_list, 1, 1, []string{"groupname"}, pf.PERM_USER, "List attestations"}, - {"add", grp_attestation_add, 3, 3, []string{"groupname", "ident", "Description"}, pf.PERM_GROUP_ADMIN, "Add an attestation"}, - {"delete", grp_attestation_delete, 2, 2, []string{"groupname", "ident"}, pf.PERM_GROUP_ADMIN, "Delete an attestation"}, + {Cmd: "list", Fun: grp_attestation_list, Args_min: 1, Args_max: 1, Args: []string{"groupname"}, Perms: pf.PERM_USER, Desc: "List attestations"}, + {Cmd: "add", Fun: grp_attestation_add, Args_min: 3, Args_max: 3, Args: []string{"groupname", "ident", "Description"}, Perms: pf.PERM_GROUP_ADMIN, Desc: "Add an attestation"}, + {Cmd: "delete", Fun: grp_attestation_delete, Args_min: 2, Args_max: 2, Args: []string{"groupname", "ident"}, Perms: pf.PERM_GROUP_ADMIN, Desc: "Delete an attestation"}, }) err = ctx.Menu(args, menu) diff --git a/src/lib/user.go b/src/lib/user.go index 9f12c02..183350b 100755 --- a/src/lib/user.go +++ b/src/lib/user.go @@ -205,7 +205,7 @@ func user_merge(ctx pf.PfCtx, args []string) (err error) { func user_pw_menu(ctx pf.PfCtx, menu *pf.PfMenu) { m := []pf.PfMEntry{ - {"reset", user_pw_reset, 1, 2, []string{"username", "nominator"}, pf.PERM_USER, "Send a recovery password split between the user and a nominator"}, + {Cmd: "reset", Fun: user_pw_reset, Args_min: 1, Args_max: 2, Args: []string{"username", "nominator"}, Perms: pf.PERM_USER, Desc: "Send a recovery password split between the user and a nominator"}, } menu.Add(m...) @@ -213,7 +213,7 @@ func user_pw_menu(ctx pf.PfCtx, menu *pf.PfMenu) { func user_menu(ctx pf.PfCtx, menu *pf.PfMenu) { m := []pf.PfMEntry{ - {"nominate", user_nominate, 5, 5, []string{"username", "email", "bio_info", "affiliation", "descr"}, pf.PERM_USER, "Nominate New User"}, + {Cmd: "nominate", Fun: user_nominate, Args_min: 5, Args_max: 5, Args: []string{"username", "email", "bio_info", "affiliation", "descr"}, Perms: pf.PERM_USER, Desc: "Nominate New User"}, } menu.Add(m...) diff --git a/src/lib/vouch.go b/src/lib/vouch.go index df9c5e6..8b68a7c 100644 --- a/src/lib/vouch.go +++ b/src/lib/vouch.go @@ -381,12 +381,12 @@ func vouch_menu(ctx pf.PfCtx, args []string) (err error) { perms := pf.PERM_USER var menu = pf.NewPfMenu([]pf.PfMEntry{ - {"add", vouch_add, 5, 5, []string{"group", "vouchor", "vouchee", "comment", "attestations"}, pf.PERM_USER, "Add a vouch"}, - {"update", vouch_update, 4, 4, []string{"group", "vouchor", "vouchee", "comment"}, perms, "Update vouch comment"}, - {"remove", vouch_remove, 3, 3, []string{"group", "vouchor", "vouchee"}, perms, "Remove a vouch"}, - {"list_for", vouches_for_member, 2, 2, []string{"group", "username"}, perms, "List vouches for a member"}, - {"list_by", vouches_by_member, 2, 2, []string{"group", "username"}, perms, "List vouches by a member"}, - {"emit", vouches_emit, 1, 1, []string{"group"}, perms, "Emit Vouches"}, + {Cmd: "add", Fun: vouch_add, Args_min: 5, Args_max: 5, Args: []string{"group", "vouchor", "vouchee", "comment", "attestations"}, Perms: pf.PERM_USER, Desc: "Add a vouch"}, + {Cmd: "update", Fun: vouch_update, Args_min: 4, Args_max: 4, Args: []string{"group", "vouchor", "vouchee", "comment"}, Perms: perms, Desc: "Update vouch comment"}, + {Cmd: "remove", Fun: vouch_remove, Args_min: 3, Args_max: 3, Args: []string{"group", "vouchor", "vouchee"}, Perms: perms, Desc: "Remove a vouch"}, + {Cmd: "list_for", Fun: vouches_for_member, Args_min: 2, Args_max: 2, Args: []string{"group", "username"}, Perms: perms, Desc: "List vouches for a member"}, + {Cmd: "list_by", Fun: vouches_by_member, Args_min: 2, Args_max: 2, Args: []string{"group", "username"}, Perms: perms, Desc: "List vouches by a member"}, + {Cmd: "emit", Fun: vouches_emit, Args_min: 1, Args_max: 1, Args: []string{"group"}, Perms: perms, Desc: "Emit Vouches"}, }) return ctx.Menu(args, menu) diff --git a/src/ui/group.go b/src/ui/group.go index 6bd6416..2420935 100644 --- a/src/ui/group.go +++ b/src/ui/group.go @@ -275,10 +275,10 @@ func h_group(cui pu.PfUI, menu *pu.PfUIMenu) { menu.Replace("member", h_group_member) m := []pu.PfUIMentry{ - {"nominate", "Nominate", pf.PERM_GROUP_MEMBER, h_group_nominate, nil}, - {"nominate_existing", "Nominate existing user", pf.PERM_GROUP_MEMBER | pf.PERM_HIDDEN, h_group_nominate_existing, nil}, - {"vouches", "Vouches", pf.PERM_GROUP_MEMBER, h_vouches, nil}, - {"vcp", "Vouching Control Panel", pf.PERM_GROUP_MEMBER, h_group_vcp, nil}, + {URI: "nominate", Desc: "Nominate", Perms: pf.PERM_GROUP_MEMBER, Fun: h_group_nominate, Subs: nil}, + {URI: "nominate_existing", Desc: "Nominate existing user", Perms: pf.PERM_GROUP_MEMBER | pf.PERM_HIDDEN, Fun: h_group_nominate_existing, Subs: nil}, + {URI: "vouches", Desc: "Vouches", Perms: pf.PERM_GROUP_MEMBER, Fun: h_vouches, Subs: nil}, + {URI: "vcp", Desc: "Vouching Control Panel", Perms: pf.PERM_GROUP_MEMBER, Fun: h_group_vcp, Subs: nil}, } menu.Add(m...) diff --git a/src/ui/root.go b/src/ui/root.go index 51ad212..3cd9e78 100644 --- a/src/ui/root.go +++ b/src/ui/root.go @@ -5,5 +5,5 @@ import ( ) func h_root(cui pu.PfUI, menu *pu.PfUIMenu) { - menu.Add(pu.PfUIMentry{"recover", "Password Recover", pu.PERM_NONE | pu.PERM_HIDDEN, h_recover, nil}) + menu.Add(pu.PfUIMentry{URI: "recover", Desc: "Password Recover", Perms: pu.PERM_NONE | pu.PERM_HIDDEN, Fun: h_recover, Subs: nil}) }