Merged in jmathison/demo-table (pull request #213)

Add demo dashboard settings table and CRUD API

* Add demo dashboard settings table and CRUD API

- Migration 00000000000123: create demoDashboardSettings table (id, guid, key, value JSONB, isDeleted, timestamps)
- SQLC queries and repository for create, list, listByGuid, get, update, soft delete
- OpenAPI paths and schemas in queryAPI.yaml; regenerate api.gen.go (embedded spec)
- Handlers in api/queryAPI/demodashboardsettings.go; ConfigProvider GetDBQueries for repo access
- Unit tests for demo dashboard settings CRUD

* Fix sqlc-generated demo dashboard setting types

Align demo dashboard settings handlers with sqlc output (DemoDashboardSetting model + pointer slices) so CI codegen/build succeeds.

* Fix CI gosec and gofmt issues

- Suppress gosec G115 for TotalCount len->int32 cast (consistent with other list endpoints)
- gofmt mock GetDBQueries() in test helpers

* gofmt query API demo settings

* Tighten demo dashboard settings OpenAPI constraints

* Regenerate query API embedded spec

* refactor: generic UI settings (table, API, service) and three-layer architecture

- Replace demo-dashboard-settings with generic UI settings:
  - Table uiSettings with namespace (was guid), key, value JSONB; UNIQUE(namespace, key)
  - Migration 123: create_ui_settings (single migration, no rename)
  - OpenAPI: /ui-settings, UISettingsService, UISetting schemas with namespace
  - API types and handlers: CreateUISetting, ListUISettings, GetUISetting, UpdateUISetting, DeleteUISetting

- Add service layer (architecture fix):
  - internal/uisettings: Service with Create, List, ListByNamespace, Get, Update, SoftDelete
  - Controllers call s.svc.UISettings only; remove GetDBQueries from queryAPI ConfigProvider
  - Wire UISettings in Services, main.go, and testutils

- Repository: uisettings.sql + uisettings.sql.go, UISetting model; remove demodashboardsettings
- Controller: uisettings.go (replaces demodashboardsettings.go), ErrNotFound from uisettings package
- Tests: uisettings_test.go with namespace-based list/cre…
* Add UISetting model and generated queries for uiSettings table

- models.go: add UISetting struct (sqlc 1.30.0)
- uisettings.sql.go: generated CRUD for ui_settings feature

Made-with: Cursor

* Use repository.UiSetting to match sqlc-generated type

- service and API use repository.UiSetting (sqlc struct name for uiSettings table)
- uisettings.sql.go: keep CreateUISetting/GetUISetting etc. from query names, return *UiSetting
- Fixes Docker/CI build undefined repository.UISetting

* Fix import formatting for golangci-lint

* Lint fix

* uisettings list test

* tests fixes

* Merge main: resolve api.gen.go conflicts (UI settings + DeleteDocument)

* Doc updates and elimination of index redundancy


Approved-by: Jay Brown
This commit is contained in:
Jacob Mathison
2026-03-04 23:00:50 +00:00
parent 09c61ea9b4
commit 8a4029058b
17 changed files with 1693 additions and 289 deletions
+258
View File
@@ -35,6 +35,8 @@ tags:
description: Operations related to user management and administration
- name: EulaService
description: Operations related to End User License Agreement management and tracking
- name: UISettingsService
description: Generic UI key-value settings (e.g. demo-dashboard:{userId}, feature-flags:global, saved-filters:{clientId})
paths:
@@ -1350,6 +1352,169 @@ paths:
"500":
$ref: "#/components/responses/InternalError"
/ui-settings:
post:
operationId: createUISetting
tags:
- UISettingsService
summary: Create a UI setting
description: >
Creates a new UI setting (namespace, key, value).
Use namespace to scope data (e.g. demo-dashboard:{userId}, feature-flags:global).
Returns 201 with the created resource.
security:
- jwtAuth: []
requestBody:
description: UI setting payload.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UISettingCreate"
responses:
"201":
description: Setting created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISetting"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: listUISettings
tags:
- UISettingsService
summary: List UI settings
description: Returns settings where isDeleted is false. Optional query param namespace filters by namespace (e.g. demo-dashboard:user123).
security:
- jwtAuth: []
parameters:
- name: namespace
in: query
required: false
schema:
type: string
maxLength: 255
description: Filter by namespace (omit to list all).
responses:
"200":
description: List of settings.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISettingListResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/ui-settings/{id}:
parameters:
- $ref: "#/components/parameters/UISettingID"
get:
operationId: getUISetting
tags:
- UISettingsService
summary: Get a UI setting by ID
description: Returns a single setting by id. Returns 404 if not found or soft-deleted.
security:
- jwtAuth: []
responses:
"200":
description: Setting details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISetting"
"400":
$ref: "#/components/responses/InvalidRequest"
"404":
$ref: "#/components/responses/NotFound"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateUISetting
tags:
- UISettingsService
summary: Update a UI setting
description: Updates the value of an existing setting. Returns 404 if not found or soft-deleted.
security:
- jwtAuth: []
requestBody:
description: Updated UI setting value payload.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UISettingUpdate"
responses:
"200":
description: Setting updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISetting"
"404":
$ref: "#/components/responses/NotFound"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteUISetting
tags:
- UISettingsService
summary: Soft-delete a UI setting
description: Sets isDeleted to true. Returns 204 on success, 404 if not found.
security:
- jwtAuth: []
responses:
"204":
description: Setting soft-deleted.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"404":
$ref: "#/components/responses/NotFound"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/identity:
get:
operationId: getIdentity
@@ -2512,6 +2677,16 @@ components:
maxLength: 36
description: The EULA version ID.
UISettingID:
in: path
name: id
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The UI setting ID.
headers:
RateLimit:
schema:
@@ -2875,6 +3050,89 @@ components:
- clients
- totalCount
UISettingCreate:
type: object
description: Request body for creating a UI setting
required:
- namespace
- key
- value
properties:
namespace:
type: string
maxLength: 255
description: Scope for the setting (e.g. demo-dashboard:{userId}, feature-flags:global, saved-filters:{clientId})
key:
type: string
maxLength: 255
description: Setting key within the namespace
value:
type: object
description: JSON value (object) for the setting
UISetting:
type: object
description: A UI setting record
required:
- id
- namespace
- key
- value
- isDeleted
- createdAt
- updatedAt
properties:
id:
type: string
format: uuid
maxLength: 36
namespace:
type: string
maxLength: 255
key:
type: string
maxLength: 255
value:
type: object
isDeleted:
type: boolean
createdAt:
type: string
format: date-time
maxLength: 32
updatedAt:
type: string
format: date-time
maxLength: 32
UISettingUpdate:
type: object
description: Request body for updating a UI setting
required:
- value
properties:
value:
type: object
description: New JSON value for the setting
UISettingListResponse:
type: object
description: List of UI settings
required:
- settings
- totalCount
properties:
settings:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/UISetting"
totalCount:
type: integer
format: int32
minimum: 0
maximum: 10000
ListDocuments:
type: array
description: The documents in the client.