krona-staff/api/openapi.yaml

263 lines
9.3 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

openapi: 3.1.0
info:
title: Krona Staff API
version: 0.2.5
description: API посещаемости Krona Staff для кабинета сотрудника, терминала и табеля руководителя.
license:
name: Proprietary
url: https://git.ochenstarik.ru/ochenstarik/krona-staff/src/branch/main/LICENSE
servers:
- url: /api/v1/staff
security: []
paths:
/live:
get:
summary: Check process liveness
operationId: getLiveness
tags: [Operations]
responses:
'200':
description: Process is alive
content:
application/json:
schema: { $ref: '#/components/schemas/Health' }
'400': { $ref: '#/components/responses/BadRequest' }
/ready:
get:
summary: Check dependency readiness
operationId: getReadiness
tags: [Operations]
responses:
'200':
description: Required dependencies are ready
content:
application/json:
schema: { $ref: '#/components/schemas/Health' }
'503': { description: A required dependency is unavailable }
'400': { $ref: '#/components/responses/BadRequest' }
/version:
get:
summary: Read runtime build identity
operationId: getVersion
tags: [Operations]
responses:
'200':
description: Runtime build identity
content:
application/json:
schema: { $ref: '#/components/schemas/Version' }
'400': { $ref: '#/components/responses/BadRequest' }
/session:
post:
summary: Открыть защищённую сессию администратора
operationId: createStaffSession
tags: [Authentication]
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required: [access_token]
properties:
access_token: { type: string, minLength: 32, maxLength: 4096, writeOnly: true }
responses:
'200':
description: Сессия открыта; токен перенесён в HttpOnly Secure cookie
'401': { description: Ключ недействителен }
'403': { description: Ключ не имеет прав администратора }
delete:
summary: Завершить сессию администратора
operationId: deleteStaffSession
tags: [Authentication]
responses:
'204': { description: Сессия завершена }
'403': { description: Запрос с постороннего сайта отклонён }
/portal:
get:
summary: Получить доступную пользователю сводку посещаемости и табеля
operationId: getStaffPortal
tags: [Attendance]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Сводка с автоматическим ограничением данными текущего сотрудника
content:
application/json:
schema: { type: object }
'403': { description: Недостаточно прав }
/employees:
post:
summary: Добавить сотрудника
operationId: createStaffEmployee
tags: [Employees]
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EmployeeCreate'
responses:
'201':
description: Сотрудник создан
content:
application/json:
schema: { $ref: '#/components/schemas/Employee' }
'403': { description: Недостаточно прав }
'409': { description: Табельный номер уже используется }
/employees/{employeeId}:
patch:
summary: Изменить карточку или статус сотрудника
operationId: updateStaffEmployee
tags: [Employees]
security: [{ bearerAuth: [] }]
parameters:
- in: path
name: employeeId
required: true
schema: { $ref: '#/components/schemas/Ulid' }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EmployeeUpdate'
responses:
'200':
description: Сотрудник изменён
content:
application/json:
schema: { $ref: '#/components/schemas/Employee' }
'403': { description: Недостаточно прав }
'404': { description: Сотрудник не найден }
/attendance/events:
post:
summary: Принять идемпотентную отметку терминала
operationId: recordAttendanceEvent
tags: [Attendance]
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required: [employee_id, event_type, occurred_at, source_event_id]
properties:
event_id: { $ref: '#/components/schemas/Ulid' }
employee_id: { $ref: '#/components/schemas/Ulid' }
event_type: { enum: [check_in, check_out] }
occurred_at: { type: string, format: date-time }
source_event_id: { type: string, minLength: 1, maxLength: 200 }
device_id: { $ref: '#/components/schemas/Ulid' }
responses:
'201': { description: Отметка принята }
'200': { description: Повтор уже принятой отметки }
'403': { description: Недостаточно прав }
/timesheets/{employeeId}/{workDate}:
put:
summary: Сохранить строку табеля
operationId: saveTimesheetEntry
tags: [Timesheet]
security: [{ bearerAuth: [] }]
parameters:
- in: path
name: employeeId
required: true
schema: { $ref: '#/components/schemas/Ulid' }
- in: path
name: workDate
required: true
schema: { type: string, format: date }
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required: [minutes_worked, status]
properties:
minutes_worked: { type: integer, minimum: 0, maximum: 1440 }
status: { enum: [draft, submitted, approved, rejected] }
note: { type: string, maxLength: 1000 }
responses:
'200': { description: Строка табеля сохранена }
'403': { description: Недостаточно прав }
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
responses:
BadRequest:
description: Invalid request
content:
application/json:
schema: { $ref: '#/components/schemas/Problem' }
schemas:
Ulid:
type: string
pattern: '^[0-9A-HJKMNP-TV-Z]{26}$'
examples: [01J00000000000000000000000]
Health:
type: object
additionalProperties: false
required: [status]
properties:
status: { type: string }
Employee:
type: object
additionalProperties: false
required: [id, personnel_number, display_name, position, gender, status]
properties:
id: { $ref: '#/components/schemas/Ulid' }
core_user_id:
oneOf:
- { $ref: '#/components/schemas/Ulid' }
- { type: 'null' }
personnel_number: { type: string }
display_name: { type: string }
position: { type: string }
gender: { enum: ['', male, female] }
status: { enum: [active, blocked, dismissed] }
EmployeeCreate:
type: object
additionalProperties: false
required: [personnel_number, display_name]
properties:
personnel_number: { type: string, minLength: 1, maxLength: 80 }
display_name: { type: string, minLength: 1, maxLength: 240 }
position: { type: string, maxLength: 160 }
gender: { enum: ['', male, female] }
EmployeeUpdate:
type: object
additionalProperties: false
minProperties: 1
properties:
personnel_number: { type: string, minLength: 1, maxLength: 80 }
display_name: { type: string, minLength: 1, maxLength: 240 }
position: { type: string, maxLength: 160 }
gender: { enum: ['', male, female] }
status: { enum: [active, blocked, dismissed] }
Problem:
type: object
additionalProperties: false
required: [type, title, status, trace_id]
properties:
type: { type: string, format: uri-reference }
title: { type: string }
status: { type: integer, minimum: 400, maximum: 599 }
trace_id: { $ref: '#/components/schemas/Ulid' }
Version:
type: object
additionalProperties: false
required: [name, version, mode]
properties:
name: { const: krona-staff }
version: { type: string }
mode: { enum: [standalone, platform] }