diff --git a/README.md b/README.md index 5c77467..a3004cf 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,17 @@ A modern HTTP client for GNOME, built with GTK 4 and libadwaita. - Export requests (cURL and more) - GNOME-native UI +## Screenshots + +### Main Interface +![Main Interface](screenshots/main.png) + +### Request History +![Request History](screenshots/history.png) + +### Environment Variables +![Environment Variables](screenshots/variables.png) + ## Quick Start ### Installation diff --git a/SENSITIVE_VARIABLES_UI_GUIDE.md b/SENSITIVE_VARIABLES_UI_GUIDE.md deleted file mode 100644 index a3045f2..0000000 --- a/SENSITIVE_VARIABLES_UI_GUIDE.md +++ /dev/null @@ -1,230 +0,0 @@ -# Sensitive Variables - UI User Guide - -## Overview - -Roster now supports marking variables as **sensitive** to store their values securely in GNOME Keyring instead of plain text. This guide explains how to use this feature in the UI. - -## Features - -### 🔒 Lock Icon Toggle - -Each variable in the Environments dialog has a lock icon button: -- **Unlocked** (🔓 `channel-insecure-symbolic`) - Variable is stored in plain JSON -- **Locked** (🔒 `channel-secure-symbolic`) - Variable is stored encrypted in GNOME Keyring - -### Visual Indicators - -1. **Lock Icon Color/State** - - Inactive (gray): Non-sensitive variable - - Active (accent color): Sensitive variable - -2. **Variable Name Styling** - - Regular variables: Normal text - - Sensitive variables: Colored with accent color and bold weight - -3. **Value Entry Fields** - - Regular variables: Show plain text - - Sensitive variables: Show bullets (••••••) instead of text - -## How to Use - -### Step 1: Open Environments Dialog - -1. Select a project from the sidebar -2. Click the "Environments" button in the header bar -3. The dialog shows a table with: - - Rows: Variable names - - Columns: Environment values - -### Step 2: Create Variables - -If you haven't already: -1. Click the **"Add Variable"** button (bottom-left) -2. Enter a variable name (e.g., `api_key`) -3. Click "Add" - -### Step 3: Mark Variable as Sensitive - -**Option A: Before Entering Values (Recommended)** -1. Find the variable row in the table -2. Click the **lock icon** next to the variable name -3. Icon changes from 🔓 to 🔒 -4. Now enter your secret values - they go directly to keyring - -**Option B: After Entering Values (Migration)** -1. If you already entered sensitive values in plain text -2. Click the lock icon to mark as sensitive -3. Values are automatically moved from JSON to GNOME Keyring -4. JSON file now shows empty placeholders - -### Step 4: Enter Sensitive Values - -1. Click in the value entry field for any environment -2. Type your secret value -3. You'll see bullets (••••••) instead of text -4. Value is automatically saved to GNOME Keyring - -### Step 5: Use in Requests - -Sensitive variables work exactly like regular variables: -``` -URL: {{base_url}}/users -Headers: - Authorization: Bearer {{api_key}} -``` - -When you send the request, values are automatically retrieved from the keyring and substituted. - -## UI Walkthrough - -### Example: Storing a GitHub Token - -**Before (Insecure - in plain JSON):** -``` -Variables Table: -┌─────────────┬──────────────────┬──────────────────┐ -│ Variable │ Production │ Development │ -├─────────────┼──────────────────┼──────────────────┤ -│ base_url 🔓 │ api.github.com │ api.dev.local │ -│ token 🔓 │ ghp_abc123... │ ghp_dev456... │ ← VISIBLE! -└─────────────┴──────────────────┴──────────────────┘ -``` - -**After (Secure - in GNOME Keyring):** -``` -Variables Table: -┌─────────────┬──────────────────┬──────────────────┐ -│ Variable │ Production │ Development │ -├─────────────┼──────────────────┼──────────────────┤ -│ base_url 🔓 │ api.github.com │ api.dev.local │ -│ token 🔒 │ •••••••••••• │ •••••••••••• │ ← HIDDEN! -└─────────────┴──────────────────┴──────────────────┘ -``` - -## Tooltips - -Hover over the lock icon to see: -- **Unlocked**: "Not sensitive (stored in JSON) - Click to mark as sensitive" -- **Locked**: "Sensitive (stored in keyring) - Click to make non-sensitive" - -## Making a Variable Non-Sensitive Again - -If you accidentally marked a variable as sensitive: -1. Click the lock icon again (🔒 → 🔓) -2. Values are moved from keyring back to JSON -3. You can now see the values in plain text - -**Warning**: Only do this if the variable truly doesn't contain secrets! - -## Viewing Secrets in GNOME Keyring - -Want to verify your secrets are stored? -1. Open **"Passwords and Keys"** application (Seahorse) -2. Look under **"Login"** keyring -3. Find entries labeled: `Roster: ProjectName/EnvironmentName/VariableName` - -Example: -``` -Login Keyring - └─ Roster: My API Project/Production/api_key - └─ Roster: My API Project/Development/api_key -``` - -## Best Practices - -### ✅ DO Mark as Sensitive: -- `api_key` - API keys -- `secret_key` - Secret keys -- `password` - Passwords -- `token` - Bearer tokens, OAuth tokens -- `client_secret` - OAuth client secrets -- `private_key` - Private keys -- Any variable containing credentials - -### ❌ DON'T Mark as Sensitive: -- `base_url` - API endpoints -- `env` - Environment names -- `region` - Cloud regions -- `timeout` - Timeout values -- `version` - API versions -- Any non-secret configuration - -### Workflow Tips - -1. **Create variables first, then mark as sensitive** - - Add variable - - Click lock icon - - Enter values (they go directly to keyring) - -2. **Use descriptive names** - - ✅ `stripe_secret_key` - - ❌ `key1` - -3. **Group related variables** - ``` - base_url 🔓 - api_key 🔒 - api_secret 🔒 - timeout 🔓 - ``` - -4. **Audit regularly** - - Check which variables are marked as sensitive - - Ensure all secrets are locked (🔒) - -## Troubleshooting - -### Q: I clicked the lock but it didn't work -**A:** Check the application logs. The keyring might be locked. Unlock it with your login password. - -### Q: Can I see my secret values after marking as sensitive? -**A:** The UI shows bullets (••••••) for security. To view: -- Temporarily unlock (click 🔒 → 🔓) -- Or use "Passwords and Keys" app to view in keyring - -### Q: What happens if I delete a sensitive variable? -**A:** Both the JSON entry AND the keyring secret are deleted automatically. - -### Q: What happens if I rename a sensitive variable? -**A:** The keyring secret is automatically renamed. No data is lost. - -### Q: What happens if I delete an environment? -**A:** All keyring secrets for that environment are deleted automatically. - -### Q: What happens if I delete a project? -**A:** ALL keyring secrets for that project are deleted automatically. - -## Security Notes - -- ✅ Secrets are encrypted with your login password -- ✅ Automatically unlocked when you log in -- ✅ Protected by OS-level security -- ✅ Same security as browser passwords, WiFi passwords, SSH keys -- ⚠️ Non-sensitive variables are still in plain JSON -- ⚠️ Mark variables as sensitive BEFORE entering secret values - -## Keyboard Shortcuts - -- **Tab**: Move between value fields -- **Enter**: Confirm value (auto-saved) -- **Escape**: Close dialog - -## Visual Design - -The UI uses the following visual cues: - -1. **Lock Icon State** - - Gray/inactive = Plain JSON storage - - Colored/active = Encrypted keyring storage - -2. **Variable Name Color** - - Sensitive variables have accent color and bold font - -3. **Password Entry** - - Sensitive variable values show as bullets - - Same UX as password fields throughout GNOME - -4. **Consistent with GNOME HIG** - - Follows GNOME Human Interface Guidelines - - Familiar patterns (lock icon = security) - - Accessible and keyboard-navigable diff --git a/SENSITIVE_VARIABLES_USAGE.md b/SENSITIVE_VARIABLES_USAGE.md deleted file mode 100644 index 4a6b133..0000000 --- a/SENSITIVE_VARIABLES_USAGE.md +++ /dev/null @@ -1,271 +0,0 @@ -# Sensitive Variables - Usage Guide - -This document explains how to use the GNOME Keyring integration for storing sensitive variable values securely. - -## Overview - -Roster now supports marking variables as **sensitive**, which stores their values encrypted in GNOME Keyring instead of plain text in the JSON file. - -**Use sensitive variables for:** -- API keys (`api_key`, `secret_key`) -- Authentication tokens (`bearer_token`, `oauth_token`) -- Passwords (`password`, `db_password`) -- Any secret credentials - -**Use regular variables for:** -- Base URLs (`base_url`, `api_endpoint`) -- Environment names (`env`, `region`) -- Non-sensitive configuration values - -## Storage - -### Regular Variables -Stored in: `~/.local/share/cz.bugsy.roster/requests.json` -```json -{ - "projects": [{ - "variable_names": ["base_url", "api_key"], - "sensitive_variables": [], // empty = not sensitive - "environments": [{ - "variables": { - "base_url": "https://api.example.com", // visible in JSON - "api_key": "secret-key-123" // visible (NOT SAFE!) - } - }] - }] -} -``` - -### Sensitive Variables -Stored in: GNOME Keyring (encrypted) -```json -{ - "projects": [{ - "variable_names": ["base_url", "api_key"], - "sensitive_variables": ["api_key"], // marked as sensitive - "environments": [{ - "variables": { - "base_url": "https://api.example.com", // visible in JSON - "api_key": "" // empty placeholder - } - }] - }] -} -``` - -The actual value of `api_key` is stored encrypted in GNOME Keyring and automatically retrieved when needed. - -## Code Examples - -### Basic Usage - -```python -from roster.project_manager import ProjectManager - -pm = ProjectManager() -project_id = "your-project-id" -env_id = "your-environment-id" - -# Mark a variable as sensitive (moves existing values to keyring) -pm.mark_variable_as_sensitive(project_id, "api_key") - -# Set a sensitive variable value (goes to keyring) -pm.set_variable_value(project_id, env_id, "api_key", "my-secret-key-123") - -# Get a sensitive variable value (retrieved from keyring) -value = pm.get_variable_value(project_id, env_id, "api_key") -# Returns: "my-secret-key-123" - -# Check if variable is sensitive -is_sensitive = pm.is_variable_sensitive(project_id, "api_key") -# Returns: True -``` - -### Using in Request Substitution - -```python -# Get environment with ALL values (including secrets from keyring) -environment = pm.get_environment_with_secrets(project_id, env_id) - -# Now use this environment for variable substitution -from roster.variable_substitution import VariableSubstitution - -vs = VariableSubstitution() -request = HttpRequest( - method="GET", - url="{{base_url}}/users", - headers={"Authorization": "Bearer {{api_key}}"}, - body="" -) - -substituted_request, undefined = vs.substitute_request(request, environment) -# Result: -# url = "https://api.example.com/users" -# headers = {"Authorization": "Bearer my-secret-key-123"} -``` - -### Mark Variable as Sensitive - -```python -# Existing variable with values in all environments -pm.mark_variable_as_sensitive(project_id, "token") - -# This will: -# 1. Add "token" to project.sensitive_variables list -# 2. Move all environment values to GNOME Keyring -# 3. Clear values in JSON (replaced with empty strings) -``` - -### Mark Variable as Non-Sensitive - -```python -# Move back from keyring to JSON -pm.mark_variable_as_nonsensitive(project_id, "base_url") - -# This will: -# 1. Remove "base_url" from project.sensitive_variables list -# 2. Move all environment values from keyring to JSON -# 3. Delete secrets from keyring -``` - -### Variable Operations (Automatic Secret Handling) - -```python -# Rename a sensitive variable -pm.rename_variable(project_id, "old_token", "new_token") -# Automatically renames in both JSON AND keyring - -# Delete a sensitive variable -pm.delete_variable(project_id, "api_key") -# Automatically deletes from both JSON AND keyring - -# Delete an environment -pm.delete_environment(project_id, env_id) -# Automatically deletes all secrets for that environment - -# Delete a project -pm.delete_project(project_id) -# Automatically deletes ALL secrets for that project -``` - -## Integration with UI - -When implementing UI for sensitive variables: - -### Variable List Display - -```python -# Show lock icon for sensitive variables -for var_name in project.variable_names: - is_sensitive = var_name in project.sensitive_variables - icon = "🔒" if is_sensitive else "" - label = f"{icon} {var_name}" -``` - -### Variable Value Entry - -```python -# Use password entry for sensitive variables -entry = Gtk.Entry() -if var_name in project.sensitive_variables: - entry.set_visibility(False) # Show bullets instead of text - entry.set_input_purpose(Gtk.InputPurpose.PASSWORD) -``` - -### Context Menu - -```python -# Right-click menu on variable -menu = Gio.Menu() - -if pm.is_variable_sensitive(project_id, var_name): - menu.append("Mark as Non-Sensitive", f"app.mark-nonsensitive::{var_name}") -else: - menu.append("Mark as Sensitive", f"app.mark-sensitive::{var_name}") -``` - -## How It Works - -### GNOME Keyring Schema - -Each secret is stored with these attributes: -```python -{ - "project_id": "uuid-of-project", - "environment_id": "uuid-of-environment", - "variable_name": "api_key" -} -``` - -Label shown in Seahorse (Passwords and Keys app): -``` -"Roster: ProjectName/EnvironmentName/variable_name" -``` - -### Viewing Secrets in Seahorse - -1. Open "Passwords and Keys" application -2. Look under "Login" keyring -3. Find entries labeled "Roster: ..." -4. These are your sensitive variable values - -### Security - -- Encrypted at rest with your login password -- Automatically unlocked when you log in -- Protected by OS-level security -- Uses the same secure backend as browser passwords, WiFi passwords, SSH keys - -## Migration Guide - -If you have existing variables with sensitive data: - -```python -project_id = "your-project-id" -sensitive_vars = ["api_key", "token", "password", "secret"] - -for var_name in sensitive_vars: - pm.mark_variable_as_sensitive(project_id, var_name) - -# Done! All values are now encrypted in GNOME Keyring -``` - -## Error Handling - -```python -from roster.secret_manager import get_secret_manager - -sm = get_secret_manager() - -# store_secret returns bool -success = sm.store_secret(project_id, env_id, "api_key", "value") -if not success: - # Handle error (check logs) - print("Failed to store secret") - -# retrieve_secret returns None on failure -value = sm.retrieve_secret(project_id, env_id, "api_key") -if value is None: - # Secret not found or error occurred - print("Secret not found") -``` - -## Best Practices - -1. **Mark variables as sensitive BEFORE entering values** - - This ensures values never touch the JSON file - -2. **Use descriptive variable names** - - `github_token` instead of `token` - - `stripe_api_key` instead of `key` - -3. **Don't commit the JSON file with sensitive data** - - If you accidentally stored secrets in JSON, mark as sensitive to move them - -4. **Regular variables are fine for most things** - - Only use sensitive variables for actual secrets - - Base URLs, regions, etc. don't need encryption - -5. **Backup your GNOME Keyring** - - Sensitive variables are stored in your system keyring - - Backup `~/.local/share/keyrings/` if needed diff --git a/screenshots/history.png b/screenshots/history.png new file mode 100644 index 0000000..ed9c012 Binary files /dev/null and b/screenshots/history.png differ diff --git a/screenshots/main.png b/screenshots/main.png new file mode 100644 index 0000000..0c77d82 Binary files /dev/null and b/screenshots/main.png differ diff --git a/screenshots/variables.png b/screenshots/variables.png new file mode 100644 index 0000000..d149cc4 Binary files /dev/null and b/screenshots/variables.png differ