Commit graph

28 commits

Author SHA1 Message Date
c93144cc37
snmp v3 support 2026-02-04 12:02:38 -06:00
02833d0b44 Add rate limiting to auth and API endpoints using Hammer 2026-02-01 14:59:54 -06:00
7ca07010ab
Use detected timezone from session in user registration 2026-02-01 12:18:33 -06:00
77e62df9da
Move CaptureTimezone plug to browser pipeline
The plug was incorrectly placed in the endpoint, causing it to run on
all requests including APIs. Moved to :browser pipeline where it belongs,
and removed redundant fetch_session call since the pipeline handles it.
2026-02-01 11:15:51 -06:00
d05c493943
Add CaptureTimezone plug to browser pipeline 2026-02-01 11:10:34 -06:00
c4e8c70e7d
Add CaptureTimezone plug to extract cf-timezone header 2026-02-01 11:02:57 -06:00
25397139c1 nif ci fix complie in ci 2026-01-30 13:01:44 -06:00
de1ad8bc8a nif ci fixes and dialyzer fixes 2026-01-30 12:38:50 -06:00
55e9397d59 user session tracking 2026-01-29 14:14:21 -06:00
c0736d4c2e gdpr consent tracking 2026-01-29 11:12:35 -06:00
e0552ac97d add security headers 2026-01-29 10:33:24 -06:00
d1fd1d4a62 remove Mix.env and support ip database import 2026-01-28 13:08:06 -06:00
220f1edce3 cookie improvements 2026-01-28 12:30:28 -06:00
588639a47a gdpr cookie consent 2026-01-28 10:52:40 -06:00
756a6b4cd4
poller agent fix and trigger device rediscovery 2026-01-26 14:51:32 -06:00
9b613f7a40
feat: update UI to Tailwind Plus design system and fix auth redirects
- Update user settings page to use Tailwind Plus 3-column grid layout
- Add API token management section to user settings
- Implement organization name display in navigation menu
- Update table component to use Tailwind Plus styling across all tables
- Update flash notifications with Tailwind Plus design
- Update dropdown menus and select inputs with custom chevron styling
- Fix authentication redirect to return to original page after login
- Preserve user_return_to session key across session renewal
- Add store_return_to_for_liveview plug to browser pipeline
- Add profiles.json to gitignore
2026-01-18 09:56:49 -06:00
56093bb493
refactor: use API token auth for profile imports instead of session cookies
Changes profile import endpoint to use standard API token authentication:

API Token Changes:
- Add user_id to api_tokens table (tracks who created the token)
- Update ApiTokens.verify_token/1 to return user along with org_id
- Update ApiAuth plug to assign current_user from token

Profile Import Changes:
- Move endpoint from /api/v1/admin/profiles/import to /api/v1/profiles/import
- Check user.is_superuser in controller instead of using RequireSuperuser plug
- Use api_v1 pipeline (Bearer token auth) instead of browser session
- Update documentation to show API token usage

Security:
- Only API tokens created by superusers can import profiles
- Returns 403 Forbidden if token user is not a superuser
- Logs import attempts with user email for audit trail

This provides a consistent API experience using Bearer tokens
instead of requiring browser session cookies.
2026-01-18 09:30:21 -06:00
e0bcd4feda
feat: add profile export/import workflow via API
Add export and import functionality for device SNMP profiles:

Export (local):
- New mix task: mix export_profiles --librenms-path ~/dev/librenms --output profiles.json
- Exports all profiles to JSON format
- Can filter specific profiles with --profiles flag

Import (production):
- New API endpoint: POST /api/v1/admin/profiles/import
- Requires superuser authentication via browser session
- Processes imports in background via Exq worker (maintenance queue)
- Returns job ID for tracking

New modules:
- Mix.Tasks.ExportProfiles - Export profiles to JSON
- ProfileImportWorker - Background job for importing profiles
- ProfilesController - API endpoint for bulk import
- RequireSuperuser plug - Restricts access to superusers
- Importer.import_profile_from_data/2 - Import from data structures

This enables bulk profile management without SSH access to production.
2026-01-18 09:23:38 -06:00
c4760ca0dc
Add API v1 endpoints with organization-scoped API tokens
Created API token system for programmatic access:
- API tokens table with organization scoping
- ApiTokens context for token management
- ApiAuth plug for Bearer token authentication
- Tokens shown once on creation, then hashed for security

Implemented RESTful API v1 endpoints:
- SitesController: CRUD operations for sites
- DevicesController: CRUD operations for devices
- All operations scoped to authenticated organization
- Proper authorization checks via site ownership

Technical details:
- Tokens prefixed with "towerops_" for easy identification
- SHA-256 hashing for token storage
- Last used timestamp tracking (async update)
- Optional token expiration support
- Standard JSON error responses (40x status codes)

Routes:
- /api/v1/sites (GET, POST, PATCH, DELETE)
- /api/v1/devices (GET, POST, PATCH, DELETE)

Authentication:
- Authorization: Bearer towerops_xxxxx header required
- Returns 401 for invalid/expired tokens
- Returns 403 for unauthorized resource access
2026-01-17 16:53:31 -06:00
b53a53b199
Add comprehensive Dialyzer type specifications
- Add @type definitions to all schema modules:
  - User, UserCredential, Membership, Invitation
  - Organization, Site, AgentAssignment
  - InterfaceStat, SensorReading, Alert
- Fix all compilation warnings with stronger Elixir types:
  - Remove unused require Logger in log_filter.ex
  - Remove unused parse_float(nil) clause
  - Add pin operators (^) for variables in binary pattern matches
- Fix Dialyzer errors (25 → 0):
  - Remove unreachable pattern match clauses
  - Fix unmatched return values with _ = prefix
  - Update @spec for deliver_alert_notification/1
- Properly handle all Phoenix.PubSub.subscribe and Task.start return values
- Explicitly ignore if statement return values where needed

All files now pass mix compile --warnings-as-errors and mix dialyzer.
2026-01-17 10:52:02 -06:00
eb91798729
agent improvements and agent config 2026-01-16 17:26:51 -06:00
c7f02eac24
add api for mobile login 2026-01-15 15:36:14 -06:00
31b906b0fa
Fix agent IP detection to use real client IP from proxy headers
The agent's last_seen IP was showing the Docker container IP (10.244.x.x)
because conn.remote_ip returns the proxy/load balancer IP.

Changes:
- Added get_client_ip/1 helper that checks X-Forwarded-For first
- Falls back to X-Real-IP if X-Forwarded-For not present
- Falls back to conn.remote_ip as last resort
- Applied to both AgentAuth plug and AgentController heartbeat endpoint

Now correctly shows the actual external IP of the remote agent.
2026-01-14 17:04:59 -06:00
9a6369bd27
Fix agent API protobuf support and Mix.env runtime error
Fixed two critical issues preventing agent communication:

1. Fix Mix.env() runtime error in production
   - Replace Mix.env() with Application.get_env(:towerops, :env)
   - Add :env config to test.exs
   - Mix module not available in production releases

2. Add Protocol Buffers support to agent API endpoints
   - GET /api/v1/agent/config now accepts application/x-protobuf
   - POST /api/v1/agent/heartbeat now accepts application/x-protobuf
   - Added conversion functions for config/equipment/sensors/interfaces
   - Maintains JSON backward compatibility as fallback

All agent controller tests passing (14 tests, 0 failures)
2026-01-14 16:35:47 -06:00
f9b575816a
Fix database ownership issues in agent auth tests
- Update AgentAuth plug to use synchronous heartbeat updates in test env
- Refactor async heartbeat logic to reduce nesting (Credo)
- Remove Process.sleep from tests (no longer needed with sync updates)

This fixes 'owner exited' database errors in the test suite by avoiding
async Task spawns during tests, which caused DB connection ownership
conflicts with Ecto's sandbox mode.
2026-01-13 13:16:54 -06:00
36175be74e
fix dialyzer and credo 2026-01-11 15:01:57 -06:00
5e1a97fcb3
fix tests 2026-01-11 14:58:55 -06:00
cf77949527
add remote agent setup 2026-01-09 13:15:31 -06:00