feat: add Makefile with reset-db target, update submodule refs
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# Deployment Tools: Makefile + HWID Migration
|
||||
|
||||
## TODOs
|
||||
|
||||
- [ ] 1. Create Makefile with reset-db command
|
||||
|
||||
**What to do**:
|
||||
- Create `D:\www-project\NexusGuard\Makefile` with this content:
|
||||
```makefile
|
||||
.PHONY: up down reset-db logs dev migrate
|
||||
|
||||
up:
|
||||
docker compose up -d
|
||||
|
||||
down:
|
||||
docker compose down
|
||||
|
||||
logs:
|
||||
docker compose logs -f
|
||||
|
||||
reset-db:
|
||||
docker compose down -v
|
||||
docker compose up -d postgres redis
|
||||
@echo "Waiting for postgres to be ready..."
|
||||
@for i in $$(seq 1 30); do \
|
||||
docker compose exec -T postgres pg_isready -U nexusguard >/dev/null 2>&1 && break; \
|
||||
echo " waiting... $$i"; \
|
||||
sleep 2; \
|
||||
done
|
||||
cd apps/server-core && go run -tags dev . -migrate-prod
|
||||
@echo ""
|
||||
@echo "Database reset complete. Run 'make up' to start all services."
|
||||
|
||||
dev:
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||
|
||||
migrate:
|
||||
cd apps/server-core && go run -tags dev . -migrate-prod
|
||||
```
|
||||
|
||||
- Then run `cd D:\www-project\NexusGuard && git add Makefile`
|
||||
|
||||
**Recommended Agent Profile**: `build` (file creation + git)
|
||||
|
||||
- [ ] 2. SSH: Migrate empty HWIDs to NULL + restart container
|
||||
|
||||
**What to do**:
|
||||
- SSH into 172.20.8.191:
|
||||
```bash
|
||||
ssh root@172.20.8.191 "docker exec nexus-guard-suite-postgres-1 psql -U nexusguard -d nexusguard -c \"UPDATE devices SET hwid = NULL WHERE hwid = '';\""
|
||||
```
|
||||
- Then restart server-core:
|
||||
```bash
|
||||
ssh root@172.20.8.191 "docker restart nexus-guard-suite-server-core-1"
|
||||
```
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Verify no empty HWIDs remain
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. ssh root@172.20.8.191 "docker exec nexus-guard-suite-postgres-1 psql -U nexusguard -d nexusguard -c \"SELECT count(*) FROM devices WHERE hwid = '';\""
|
||||
Expected Result: count = 0
|
||||
```
|
||||
|
||||
- [ ] 3. Commit and push all changes (server-core HWID fix, frontend delete button, Makefile)
|
||||
|
||||
- [ ] 4. Verify POST /api/v1/peers returns 201
|
||||
|
||||
```bash
|
||||
ssh root@172.20.8.191 'curl -s -X POST http://localhost:3000/api/v1/auth/login -H "Content-Type: application/json" -d "{\"username\":\"admin\",\"password\":\"...\"}"'
|
||||
# Then use token to create a peer
|
||||
```
|
||||
@@ -0,0 +1,154 @@
|
||||
# Fix Peers API 500 + Add Delete Device to Devices List
|
||||
|
||||
## TL;DR
|
||||
> **Quick Summary**: Fix `HWID` unique constraint violation causing 500 on POST `/api/v1/peers` by making `HWID` nullable; add delete button to Devices.vue list view
|
||||
>
|
||||
> **Deliverables**:
|
||||
> - Backend: HWID model change `string` → `*string`, fix CreatePeer/CreateDevice
|
||||
> - Frontend: Delete button in Devices.vue table rows
|
||||
> - Migration: SQL to convert existing empty HWIDs to NULL + container restart
|
||||
>
|
||||
> **Estimated Effort**: Short
|
||||
> **Parallel Execution**: YES
|
||||
|
||||
## Context
|
||||
### Root Cause
|
||||
- `Device.HWID` is `string` with `uniqueIndex`. `CreatePeer` sets `HWID: ""` which collides with other devices having empty HWID → SQLSTATE 23505
|
||||
- Fix: make HWID `*string` (nullable), PostgreSQL treats NULLs as distinct in unique constraints
|
||||
|
||||
### Delete Missing
|
||||
- Backend: `DELETE /devices/:id` exists at `main.go:176`, `devicesHandler.Delete` in `devices.go:235`
|
||||
- API: `deleteDevice(id)` exists in `devices.ts:50`
|
||||
- DeviceDetail: has delete button with confirm dialog
|
||||
- Devices.vue: Actions column only has View, Config, Firewall — no Delete
|
||||
|
||||
## TODOs
|
||||
|
||||
- [ ] 1. Backend: Change HWID to `*string` in Device model
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/server-core/internal/models/models.go` line 60:
|
||||
- Change `HWID string \`gorm:"column:hwid;uniqueIndex;size:64"\``
|
||||
- To `HWID *string \`gorm:"column:hwid;uniqueIndex;size:64"\``
|
||||
|
||||
**Must NOT do**:
|
||||
- Don't change any other fields in the model
|
||||
|
||||
**Recommended Agent Profile**: `unspecified-high` (precise Go struct edit)
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Verify build after model change
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. cd apps/server-core && go build ./...
|
||||
Expected Result: No compilation errors
|
||||
Evidence: .sisyphus/evidence/task-1-build.txt
|
||||
```
|
||||
|
||||
- [ ] 2. Backend: Fix CreatePeer to not set empty HWID
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/server-core/api/peers.go` — remove `HWID: ""` line (line 96)
|
||||
- Since `HWID` is now `*string`, the zero value (nil) is correct — it won't violate unique constraint
|
||||
- Keep `RegTokenHash: ""` as-is (no unique index on that)
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Build passes after fix
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. cd apps/server-core && go build ./...
|
||||
Expected Result: Clean build
|
||||
Evidence: .sisyphus/evidence/task-2-build.txt
|
||||
```
|
||||
|
||||
- [ ] 3. Backend: Fix CreateDevice to not set empty HWID
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/server-core/api/devices.go` — verify `Create` function (line 84-89) doesn't set HWID
|
||||
- It currently doesn't set HWID at all, so with `*string` it will default to nil — correct
|
||||
- Verify `Delete` function (line 235-255) already works — it does, no changes needed
|
||||
|
||||
- [ ] 4. Migration: Convert existing empty HWIDs to NULL on server
|
||||
|
||||
**What to do**:
|
||||
- SSH into 172.20.8.191 and run SQL against the postgres container:
|
||||
```bash
|
||||
docker exec nexus-guard-suite-postgres-1 psql -U nexusguard -d nexusguard -c "UPDATE devices SET hwid = NULL WHERE hwid = '';"
|
||||
```
|
||||
- Then restart server-core container:
|
||||
```bash
|
||||
docker restart nexus-guard-suite-server-core-1
|
||||
```
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Verify empty HWIDs are now NULL
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. docker exec nexus-guard-suite-postgres-1 psql -U nexusguard -d nexusguard -c "SELECT count(*) FROM devices WHERE hwid = '';"
|
||||
Expected Result: count = 0
|
||||
Evidence: .sisyphus/evidence/task-4-sql.txt
|
||||
|
||||
Scenario: Verify POST /api/v1/peers succeeds
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. Obtain auth token via POST /api/v1/auth/login with admin credentials
|
||||
2. POST /api/v1/peers with valid body (name, wg_server_id)
|
||||
Expected Result: 201 Created (not 500)
|
||||
Evidence: .sisyphus/evidence/task-4-peers-api.txt
|
||||
```
|
||||
|
||||
- [ ] 5. Frontend: Add delete button to Devices.vue list
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/dashboard-ui/src/views/Devices.vue`
|
||||
- Add delete button in the Actions column (line 34-39), after Firewall button:
|
||||
```html
|
||||
<button @click="handleDelete(device.ID, device.Name)" class="text-red-400 hover:text-red-300 font-bold">Delete</button>
|
||||
```
|
||||
- Import `deleteDevice` from `../api/devices`
|
||||
- Add `handleDelete` function:
|
||||
```typescript
|
||||
const handleDelete = async (id: string, name: string) => {
|
||||
if (!confirm(`Delete device "${name}"? This will destroy its tunnel and all firewall rules.`)) return
|
||||
try {
|
||||
await deleteDevice(id)
|
||||
store.loadDevices()
|
||||
} catch (err: any) {
|
||||
alert(err.response?.data?.error || 'Failed to delete device')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Must NOT do**:
|
||||
- Don't remove the existing Config/Firewall buttons
|
||||
|
||||
**Recommended Agent Profile**: `visual-engineering` (Vue UI)
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Build passes
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. cd apps/dashboard-ui && npx vue-tsc --noEmit
|
||||
Expected Result: No type errors
|
||||
Evidence: .sisyphus/evidence/task-5-tsc.txt
|
||||
```
|
||||
|
||||
- [ ] 6. Commit and push changes
|
||||
|
||||
**What to do**:
|
||||
- Commit server-core changes
|
||||
- Commit dashboard-ui changes
|
||||
- Push both submodules
|
||||
- Commit/push root submodule pointer
|
||||
|
||||
|
||||
## Success Criteria
|
||||
- [ ] `go build ./...` passes
|
||||
- [ ] `vue-tsc --noEmit` passes
|
||||
- [ ] POST `/api/v1/peers` returns 201, not 500
|
||||
- [ ] Devices.vue has a delete button per row that works
|
||||
- [ ] Existing empty HWIDs migrated to NULL
|
||||
@@ -0,0 +1,29 @@
|
||||
.PHONY: up down reset-db logs dev migrate
|
||||
|
||||
up:
|
||||
docker compose up -d
|
||||
|
||||
down:
|
||||
docker compose down
|
||||
|
||||
logs:
|
||||
docker compose logs -f
|
||||
|
||||
reset-db:
|
||||
docker compose down -v
|
||||
docker compose up -d postgres redis
|
||||
@echo "Waiting for postgres to be ready..."
|
||||
@for i in $$(seq 1 30); do \
|
||||
docker compose exec -T postgres pg_isready -U nexusguard >/dev/null 2>&1 && break; \
|
||||
echo " waiting... $$i"; \
|
||||
sleep 2; \
|
||||
done
|
||||
cd apps/server-core && go run -tags dev . -migrate-prod
|
||||
@echo ""
|
||||
@echo "Database reset complete. Run 'make up' to start all services."
|
||||
|
||||
dev:
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||
|
||||
migrate:
|
||||
cd apps/server-core && go run -tags dev . -migrate-prod
|
||||
+1
-1
Submodule apps/dashboard-ui updated: e6c71e6c50...24ae0119fd
+1
-1
Submodule apps/server-core updated: 9980cd3ec6...4ebf097fe2
Reference in New Issue
Block a user