Files
testRestApi/node/openapi.yaml
T
2026-10-27 20:40:32 +01:00

610 lines
19 KiB
YAML

openapi: 3.0.3
info:
title: REST API
version: 1.0.0
description: API użytkowników, klientów i samochodów. Wszystkie endpointy wymagają HTTP Basic Auth; w Swagger UI wybierz Authorize i podaj login oraz hasło.
servers:
- url: /
security:
- basicAuth: []
tags:
- name: Auth
- name: Users
- name: Customers
- name: Cars
paths:
/api/auth/login:
post:
tags: [Auth]
summary: Potwierdź logowanie i zaktualizuj ostatnie logowanie
responses:
'200':
description: Uwierzytelniony użytkownik
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
/api/auth/me:
get:
tags: [Auth]
summary: Pobierz własny profil
responses:
'200':
description: Profil użytkownika
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
put:
tags: [Auth]
summary: Zaktualizuj własny profil
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ProfileInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
patch:
tags: [Auth]
summary: Częściowo zaktualizuj własny profil
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ProfileInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
/api/users:
get:
tags: [Users]
summary: Lista użytkowników (admin)
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/limit'
- name: q
in: query
schema: { type: string }
- name: role
in: query
schema: { type: string, enum: [admin, user] }
- name: active
in: query
schema: { type: boolean }
responses:
'200':
description: Lista użytkowników
content:
application/json:
schema: { $ref: '#/components/schemas/UserList' }
'403': { $ref: '#/components/responses/Forbidden' }
post:
tags: [Users]
summary: Dodaj użytkownika (admin)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/UserCreate' }
responses:
'201':
description: Utworzono
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
/api/users/{id}:
parameters:
- $ref: '#/components/parameters/id'
get:
tags: [Users]
summary: Pobierz użytkownika (admin)
responses:
'200':
description: Użytkownik
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [Users]
summary: Zaktualizuj użytkownika (admin)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/UserInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
patch:
tags: [Users]
summary: Częściowo zaktualizuj użytkownika (admin)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/UserInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/UserResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
delete:
tags: [Users]
summary: Usuń użytkownika (admin)
responses:
'204': { description: Usunięto }
'400': { $ref: '#/components/responses/BadRequest' }
/api/customers:
get:
tags: [Customers]
summary: Lista klientów
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/limit'
- name: q
in: query
schema: { type: string, description: Szukanie po danych klienta }
- name: type
in: query
schema: { type: string, enum: [individual, company] }
- name: city
in: query
schema: { type: string }
- name: country
in: query
schema: { type: string }
- name: with_cars
in: query
schema: { type: boolean }
responses:
'200':
description: Lista klientów
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerList' }
post:
tags: [Customers]
summary: Dodaj klienta
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerCreate' }
responses:
'201':
description: Utworzono
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
/api/customers/{id}:
parameters:
- $ref: '#/components/parameters/id'
get:
tags: [Customers]
summary: Szczegóły klienta wraz z samochodami
responses:
'200':
description: Klient
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerResponse' }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [Customers]
summary: Zaktualizuj klienta
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
patch:
tags: [Customers]
summary: Częściowo zaktualizuj klienta
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/CustomerResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
delete:
tags: [Customers]
summary: Usuń klienta i jego samochody
responses:
'204': { description: Usunięto }
'404': { $ref: '#/components/responses/NotFound' }
/api/customers/{customer_id}/cars:
parameters:
- name: customer_id
in: path
required: true
schema: { type: integer }
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/limit'
get:
tags: [Cars]
summary: Lista samochodów klienta
responses:
'200':
description: Samochody klienta
content:
application/json:
schema: { $ref: '#/components/schemas/CarList' }
'404': { $ref: '#/components/responses/NotFound' }
post:
tags: [Cars]
summary: Dodaj samochód klientowi
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/NestedCarInput' }
responses:
'201':
description: Utworzono
content:
application/json:
schema: { $ref: '#/components/schemas/CarResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
/api/cars:
get:
tags: [Cars]
summary: Lista samochodów
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/limit'
- name: q
in: query
schema: { type: string, description: Szukanie po marce, modelu i numerach auta }
- name: customer_id
in: query
schema: { type: integer }
- name: make
in: query
schema: { type: string }
- name: fuel_type
in: query
schema: { type: string, enum: [petrol, diesel, lpg, hybrid, electric] }
- name: transmission
in: query
schema: { type: string, enum: [manual, automatic] }
- name: year_from
in: query
schema: { type: integer }
- name: year_to
in: query
schema: { type: integer }
- name: with_customer
in: query
schema: { type: boolean }
responses:
'200':
description: Lista samochodów
content:
application/json:
schema: { $ref: '#/components/schemas/CarList' }
post:
tags: [Cars]
summary: Dodaj samochód
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CarCreate' }
responses:
'201':
description: Utworzono
content:
application/json:
schema: { $ref: '#/components/schemas/CarResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
/api/cars/{id}:
parameters:
- $ref: '#/components/parameters/id'
get:
tags: [Cars]
summary: Szczegóły samochodu z właścicielem
responses:
'200':
description: Samochód
content:
application/json:
schema: { $ref: '#/components/schemas/CarResponse' }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [Cars]
summary: Zaktualizuj samochód
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CarInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/CarResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
patch:
tags: [Cars]
summary: Częściowo zaktualizuj samochód
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CarInput' }
responses:
'200':
description: Zaktualizowano
content:
application/json:
schema: { $ref: '#/components/schemas/CarResponse' }
'422': { $ref: '#/components/responses/ValidationError' }
delete:
tags: [Cars]
summary: Usuń samochód
responses:
'204': { description: Usunięto }
'404': { $ref: '#/components/responses/NotFound' }
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
parameters:
id:
name: id
in: path
required: true
schema: { type: integer }
page:
name: page
in: query
schema: { type: integer, minimum: 1, default: 1 }
limit:
name: limit
in: query
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
responses:
Unauthorized:
description: Brak lub nieprawidłowe dane HTTP Basic Auth
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
Forbidden:
description: Wymagana rola admin
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
NotFound:
description: Nie znaleziono rekordu
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
BadRequest:
description: Niedozwolona operacja
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
ValidationError:
description: Błędy walidacji
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
schemas:
Error:
type: object
properties:
success: { type: boolean, example: false }
error:
type: object
properties:
code: { type: integer }
message: { type: string }
fields:
type: object
additionalProperties: true
Pagination:
type: object
properties:
page: { type: integer }
limit: { type: integer }
total: { type: integer }
pages: { type: integer }
has_next_page: { type: boolean }
has_prev_page: { type: boolean }
sort: { type: string }
direction: { type: string }
User:
type: object
properties:
id: { type: integer }
login: { type: string }
email: { type: string, format: email }
first_name: { type: string }
last_name: { type: string }
role: { type: string, enum: [admin, user] }
active: { type: boolean }
last_login: { type: string, format: date-time, nullable: true }
created: { type: string, format: date-time }
modified: { type: string, format: date-time }
UserInput:
type: object
properties:
login: { type: string, maxLength: 255 }
email: { type: string, format: email }
password: { type: string, format: password, minLength: 8, maxLength: 72 }
first_name: { type: string, maxLength: 100 }
last_name: { type: string, maxLength: 100 }
role: { type: string, enum: [admin, user] }
active: { type: boolean }
UserCreate:
allOf:
- $ref: '#/components/schemas/UserInput'
- type: object
required: [login, email, password, first_name, last_name]
ProfileInput:
type: object
properties:
email: { type: string, format: email }
password: { type: string, format: password, minLength: 8 }
first_name: { type: string }
last_name: { type: string }
UserResponse:
type: object
properties:
success: { type: boolean }
data: { $ref: '#/components/schemas/User' }
UserList:
type: object
properties:
success: { type: boolean }
data:
type: array
items: { $ref: '#/components/schemas/User' }
meta: { $ref: '#/components/schemas/Pagination' }
CustomerInput:
type: object
properties:
type: { type: string, enum: [individual, company], default: individual }
first_name: { type: string, maxLength: 100 }
last_name: { type: string, maxLength: 100 }
email: { type: string, format: email }
phone: { type: string, maxLength: 30 }
company_name: { type: string, nullable: true }
tax_id: { type: string, nullable: true }
street: { type: string, nullable: true }
city: { type: string, nullable: true }
postal_code: { type: string, nullable: true }
country: { type: string, default: PL }
birth_date: { type: string, format: date, nullable: true }
notes: { type: string, nullable: true }
CustomerCreate:
allOf:
- $ref: '#/components/schemas/CustomerInput'
- type: object
required: [first_name, last_name, email, phone]
Customer:
allOf:
- $ref: '#/components/schemas/CustomerInput'
- type: object
properties:
id: { type: integer }
created_by: { type: integer, nullable: true }
created: { type: string, format: date-time }
modified: { type: string, format: date-time }
CustomerResponse:
type: object
properties:
success: { type: boolean }
data:
allOf:
- $ref: '#/components/schemas/Customer'
- type: object
properties:
cars:
type: array
items: { $ref: '#/components/schemas/Car' }
CustomerList:
type: object
properties:
success: { type: boolean }
data:
type: array
items: { $ref: '#/components/schemas/Customer' }
meta: { $ref: '#/components/schemas/Pagination' }
CarInput:
type: object
properties:
customer_id: { type: integer }
make: { type: string }
model: { type: string }
production_year: { type: integer }
vin: { type: string, minLength: 17, maxLength: 17 }
registration_number: { type: string }
fuel_type: { type: string, enum: [petrol, diesel, lpg, hybrid, electric] }
color: { type: string, nullable: true }
engine_capacity: { type: integer, nullable: true }
power_hp: { type: integer, nullable: true }
transmission: { type: string, enum: [manual, automatic], nullable: true }
mileage: { type: integer, nullable: true }
notes: { type: string, nullable: true }
CarCreate:
allOf:
- $ref: '#/components/schemas/CarInput'
- type: object
required: [customer_id, make, model, production_year, vin, registration_number, fuel_type]
Car:
allOf:
- $ref: '#/components/schemas/CarInput'
- type: object
properties:
id: { type: integer }
created: { type: string, format: date-time }
modified: { type: string, format: date-time }
NestedCarInput:
type: object
required: [make, model, production_year, vin, registration_number, fuel_type]
properties:
make: { type: string }
model: { type: string }
production_year: { type: integer }
vin: { type: string, minLength: 17, maxLength: 17 }
registration_number: { type: string }
fuel_type: { type: string, enum: [petrol, diesel, lpg, hybrid, electric] }
color: { type: string, nullable: true }
engine_capacity: { type: integer, nullable: true }
power_hp: { type: integer, nullable: true }
transmission: { type: string, enum: [manual, automatic], nullable: true }
mileage: { type: integer, nullable: true }
notes: { type: string, nullable: true }
CarResponse:
type: object
properties:
success: { type: boolean }
data:
allOf:
- $ref: '#/components/schemas/Car'
- type: object
properties:
customer: { $ref: '#/components/schemas/Customer' }
CarList:
type: object
properties:
success: { type: boolean }
data:
type: array
items: { $ref: '#/components/schemas/Car' }
meta: { $ref: '#/components/schemas/Pagination' }