This commit is contained in:
2026-03-16 09:09:54 -04:00
parent e289d1a29b
commit ecf77fd105
37 changed files with 3505 additions and 119 deletions

View File

@@ -2,8 +2,6 @@ package v1
import (
"context"
"strconv"
"time"
"reichard.io/antholume/database"
)
@@ -48,12 +46,24 @@ func (s *Server) GetActivity(ctx context.Context, request GetActivityRequestObje
apiActivities := make([]Activity, len(activities))
for i, a := range activities {
// Convert StartTime from interface{} to string
startTimeStr := ""
if a.StartTime != nil {
if str, ok := a.StartTime.(string); ok {
startTimeStr = str
}
}
apiActivities[i] = Activity{
ActivityType: a.DeviceID,
DocumentId: a.DocumentID,
Id: strconv.Itoa(i),
Timestamp: time.Now(),
UserId: auth.UserName,
DocumentId: a.DocumentID,
DeviceId: a.DeviceID,
StartTime: startTimeStr,
Title: a.Title,
Author: a.Author,
Duration: a.Duration,
StartPercentage: float32(a.StartPercentage),
EndPercentage: float32(a.EndPercentage),
ReadPercentage: float32(a.ReadPercentage),
}
}

140
api/v1/admin.go Normal file
View File

@@ -0,0 +1,140 @@
package v1
import (
"context"
"time"
)
// GET /admin
func (s *Server) GetAdmin(ctx context.Context, request GetAdminRequestObject) (GetAdminResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return GetAdmin401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// Get database info from the main API
// This is a placeholder - you'll need to implement this in the main API or database
// For now, return empty data
response := GetAdmin200JSONResponse{
DatabaseInfo: &DatabaseInfo{
DocumentsSize: 0,
ActivitySize: 0,
ProgressSize: 0,
DevicesSize: 0,
},
}
return response, nil
}
// POST /admin
func (s *Server) PostAdminAction(ctx context.Context, request PostAdminActionRequestObject) (PostAdminActionResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return PostAdminAction401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// TODO: Implement admin actions (backup, restore, etc.)
// For now, this is a placeholder
return PostAdminAction200ApplicationoctetStreamResponse{}, nil
}
// GET /admin/users
func (s *Server) GetUsers(ctx context.Context, request GetUsersRequestObject) (GetUsersResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return GetUsers401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// Get users from database
users, err := s.db.Queries.GetUsers(ctx)
if err != nil {
return GetUsers500JSONResponse{Code: 500, Message: err.Error()}, nil
}
apiUsers := make([]User, len(users))
for i, user := range users {
createdAt, _ := time.Parse("2006-01-02T15:04:05", user.CreatedAt)
apiUsers[i] = User{
Id: user.ID,
Admin: user.Admin,
CreatedAt: createdAt,
}
}
response := GetUsers200JSONResponse{
Users: &apiUsers,
}
return response, nil
}
// POST /admin/users
func (s *Server) UpdateUser(ctx context.Context, request UpdateUserRequestObject) (UpdateUserResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return UpdateUser401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// TODO: Implement user creation, update, deletion
// For now, this is a placeholder
return UpdateUser200JSONResponse{
Users: &[]User{},
}, nil
}
// GET /admin/import
func (s *Server) GetImportDirectory(ctx context.Context, request GetImportDirectoryRequestObject) (GetImportDirectoryResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return GetImportDirectory401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// TODO: Implement directory listing
// For now, this is a placeholder
return GetImportDirectory200JSONResponse{
CurrentPath: ptrOf("/data"),
Items: &[]DirectoryItem{},
}, nil
}
// POST /admin/import
func (s *Server) PostImport(ctx context.Context, request PostImportRequestObject) (PostImportResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return PostImport401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// TODO: Implement import functionality
// For now, this is a placeholder
return PostImport200JSONResponse{
Results: &[]ImportResult{},
}, nil
}
// GET /admin/import-results
func (s *Server) GetImportResults(ctx context.Context, request GetImportResultsRequestObject) (GetImportResultsResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return GetImportResults401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// TODO: Implement import results retrieval
// For now, this is a placeholder
return GetImportResults200JSONResponse{
Results: &[]ImportResult{},
}, nil
}
// GET /admin/logs
func (s *Server) GetLogs(ctx context.Context, request GetLogsRequestObject) (GetLogsResponseObject, error) {
_, ok := s.getSessionFromContext(ctx)
if !ok {
return GetLogs401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
}
// TODO: Implement log retrieval
// For now, this is a placeholder
return GetLogs200JSONResponse{
Logs: &[]string{},
Filter: request.Params.Filter,
}, nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -91,23 +91,36 @@ components:
Activity:
type: object
properties:
id:
type: string
user_id:
type: string
document_id:
type: string
activity_type:
device_id:
type: string
timestamp:
start_time:
type: string
format: date-time
title:
type: string
author:
type: string
duration:
type: integer
format: int64
start_percentage:
type: number
format: float
end_percentage:
type: number
format: float
read_percentage:
type: number
format: float
required:
- id
- user_id
- document_id
- activity_type
- timestamp
- device_id
- start_time
- duration
- start_percentage
- end_percentage
- read_percentage
SearchItem:
type: object
@@ -482,6 +495,95 @@ components:
- user_statistics
- user
BackupType:
type: string
enum: [COVERS, DOCUMENTS]
ImportType:
type: string
enum: [DIRECT, COPY]
OperationType:
type: string
enum: [CREATE, UPDATE, DELETE]
User:
type: object
properties:
id:
type: string
admin:
type: boolean
created_at:
type: string
format: date-time
required:
- id
- admin
- created_at
UsersResponse:
type: object
properties:
users:
type: array
items:
$ref: '#/components/schemas/User'
ImportResult:
type: object
properties:
id:
type: string
name:
type: string
path:
type: string
status:
type: string
enum: [FAILED, SUCCESS, EXISTS]
error:
type: string
ImportResultsResponse:
type: object
properties:
results:
type: array
items:
$ref: '#/components/schemas/ImportResult'
DirectoryItem:
type: object
properties:
name:
type: string
path:
type: string
DirectoryListResponse:
type: object
properties:
current_path:
type: string
items:
type: array
items:
$ref: '#/components/schemas/DirectoryItem'
LogEntry:
type: string
LogsResponse:
type: object
properties:
logs:
type: array
items:
$ref: '#/components/schemas/LogEntry'
filter:
type: string
securitySchemes:
BearerAuth:
type: http
@@ -1057,4 +1159,307 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
$ref: '#/components/schemas/ErrorResponse'
/admin:
get:
summary: Get admin page data
operationId: getAdmin
tags:
- Admin
security:
- BearerAuth: []
responses:
200:
description: Successful response
content:
application/json:
schema:
type: object
properties:
database_info:
$ref: '#/components/schemas/DatabaseInfo'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
summary: Perform admin action (backup, restore, etc.)
operationId: postAdminAction
tags:
- Admin
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
action:
type: string
enum: [BACKUP, RESTORE, METADATA_MATCH, CACHE_TABLES]
backup_types:
type: array
items:
$ref: '#/components/schemas/BackupType'
restore_file:
type: string
format: binary
required:
- action
security:
- BearerAuth: []
responses:
200:
description: Action completed successfully
content:
application/octet-stream:
schema:
type: string
format: binary
400:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/admin/users:
get:
summary: Get all users
operationId: getUsers
tags:
- Admin
security:
- BearerAuth: []
responses:
200:
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/UsersResponse'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
summary: Create, update, or delete user
operationId: updateUser
tags:
- Admin
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
operation:
$ref: '#/components/schemas/OperationType'
user:
type: string
password:
type: string
is_admin:
type: boolean
required:
- operation
- user
security:
- BearerAuth: []
responses:
200:
description: User updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/UsersResponse'
400:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/admin/import:
get:
summary: Get import directory list
operationId: getImportDirectory
tags:
- Admin
parameters:
- name: directory
in: query
schema:
type: string
- name: select
in: query
schema:
type: string
security:
- BearerAuth: []
responses:
200:
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DirectoryListResponse'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
summary: Perform import
operationId: postImport
tags:
- Admin
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
directory:
type: string
type:
$ref: '#/components/schemas/ImportType'
required:
- directory
- type
security:
- BearerAuth: []
responses:
200:
description: Import completed
content:
application/json:
schema:
$ref: '#/components/schemas/ImportResultsResponse'
400:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/admin/import-results:
get:
summary: Get import results
operationId: getImportResults
tags:
- Admin
security:
- BearerAuth: []
responses:
200:
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ImportResultsResponse'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/admin/logs:
get:
summary: Get logs with optional filter
operationId: getLogs
tags:
- Admin
parameters:
- name: filter
in: query
schema:
type: string
security:
- BearerAuth: []
responses:
200:
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/LogsResponse'
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'