Skip to content

Repository files navigation

tea-and-snacks

API to manage madoxx bar tea and snacks catalog.

Starting db

first thing first, start the PostgreSQL database:

docker-compose up -d

Running the application in dev mode

run in dev mode that enables live coding using:

./gradlew quarkusDev

API Endpoints

🌱 Seed Data

initialize or reset the database with sample data:

Initialize Database

curl -X POST http://localhost:8080/api/seed/initialize -H 'Content-Type: application/json'

Response: {"message":"Base de dados inicializada com sucesso","seeded":true}

Reset Database

curl -X POST http://localhost:8080/api/seed/reset -H 'Content-Type: application/json'

Response: {"message":"Base de dados resetada com sucesso","seeded":false}

Check Status

curl -X GET http://localhost:8080/api/seed/status

Response: {"seeded":true} or {"seeded":false}

Get All Seed Data

curl -X GET http://localhost:8080/api/seed/data

Response (if seeded):

{
  "teas": [],
  "snacks": [],
  "sauces": [],
  "total": {
    "teas": 4,
    "snacks": 3,
    "sauces": 5
  }
}

Response (if not seeded): {"message":"Database not seeded"}


🍵 Teas

List all teas (paginated - default)

curl -X GET http://localhost:8080/teas

List all teas (without pagination)

curl -X GET 'http://localhost:8080/teas?paginated=false'

List teas with custom pagination

curl -X GET 'http://localhost:8080/teas?page=0&size=10'

Filter teas by category

curl -X GET 'http://localhost:8080/teas?category=GREEN&paginated=false'

Available categories: BLACK, GREEN, HERBAL, OOLONG, WHITE, FLORAL, OTHER

Filter teas by caffeine level and origin

curl -X GET 'http://localhost:8080/teas?caffeineLevel=MEDIUM&origin=japan&paginated=false'

Available caffeine levels: NONE, LOW, MEDIUM, HIGH

Get tea by ID

curl -X GET http://localhost:8080/teas/{id}

Create new tea

curl -X POST http://localhost:8080/teas \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sencha",
    "origin": "japan",
    "description": "Japanese green tea",
    "ingredients": [
      {
        "name": "Green Tea Leaves",
        "quantity": 5.0,
        "unitOfMeasure": "GRAMS"
      }
    ],
    "category": "GREEN",
    "caffeineLevel": "MEDIUM"
  }'

Update tea

curl -X PUT http://localhost:8080/teas/{id} \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sencha Premium",
    "origin": "japan",
    "description": "Premium Japanese green tea",
    "ingredients": [
      {
        "name": "Premium Green Tea Leaves",
        "quantity": 6.0,
        "unitOfMeasure": "GRAMS"
      }
    ],
    "category": "GREEN",
    "caffeineLevel": "LOW"
  }'

Delete tea by ID

curl -X DELETE http://localhost:8080/teas/{id}

Delete teas with filters

curl -X DELETE 'http://localhost:8080/teas?category=GREEN'

🍿 Snacks

List all snacks (paginated - default)

curl -X GET http://localhost:8080/snacks

List all snacks (without pagination)

curl -X GET 'http://localhost:8080/snacks?paginated=false'

List snacks with custom pagination

curl -X GET 'http://localhost:8080/snacks?page=0&size=10'

Filter vegan snacks

curl -X GET 'http://localhost:8080/snacks?vegan=true&paginated=false'

Filter snacks by flavor

curl -X GET 'http://localhost:8080/snacks?flavour=cheese&paginated=false'

Filter snacks by sauce flavor

curl -X GET 'http://localhost:8080/snacks?sauce=spicy&paginated=false'

Get snack by ID

curl -X GET http://localhost:8080/snacks/{id}

Create new snack

curl -X POST http://localhost:8080/snacks \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Chips",
    "flavour": "Salt",
    "vegan": true
  }'

Update snack

curl -X PUT http://localhost:8080/snacks/{id} \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Chips Updated",
    "flavour": "BBQ",
    "vegan": false
  }'

Delete snack by ID

curl -X DELETE http://localhost:8080/snacks/{id}

Delete all snacks

curl -X DELETE http://localhost:8080/snacks

List sauces of a snack

curl -X GET http://localhost:8080/snacks/{id}/sauces

Add sauce to a snack

curl -X POST http://localhost:8080/snacks/{snackId}/sauces/{sauceId}

Remove sauce from a snack

curl -X DELETE http://localhost:8080/snacks/{snackId}/sauces/{sauceId}

🌶️ Sauces

List all sauces (paginated - default)

curl -X GET http://localhost:8080/sauces

List all sauces (without pagination)

curl -X GET 'http://localhost:8080/sauces?paginated=false'

List sauces with custom pagination

curl -X GET 'http://localhost:8080/sauces?page=0&size=10'

Filter sauces by flavor

curl -X GET 'http://localhost:8080/sauces?flavour=spicy&paginated=false'

Get sauce by ID

curl -X GET http://localhost:8080/sauces/{id}

Create new sauce

curl -X POST http://localhost:8080/sauces \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Hot Sauce",
    "flavour": "Spicy"
  }'

Update sauce

curl -X PUT http://localhost:8080/sauces/{id} \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Super Hot Sauce",
    "flavour": "Extra Spicy"
  }'

Delete sauce by ID

curl -X DELETE http://localhost:8080/sauces/{id}

Delete all sauces

curl -X DELETE http://localhost:8080/sauces

🔑 Authentication

Login

curl -X POST http://localhost:8080/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "password": "admin"
  }'

Response:

{
  "accessToken": "YOUR_JWT_TOKEN",
  "expiresIn": 3600,
  "refreshToken": "YOUR_REFRESH_TOKEN"
}

Refresh Token

curl -X POST http://localhost:8080/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refreshToken": "YOUR_REFRESH_TOKEN"
  }'

Response:

{
  "accessToken": "YOUR_NEW_JWT_TOKEN",
  "expiresIn": 3600,
  "refreshToken": "YOUR_NEW_REFRESH_TOKEN"
}

Logout

curl -X POST http://localhost:8080/auth/logout \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

👤 Users

Get Current User Info

curl -X GET http://localhost:8080/auth/me \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

⚠️ Requires ADMIN role

Response:

{
  "username": "admin",
  "email": "admin@maddoxbar.com",
  "roles": ["USER", "ADMIN"]
}

List All Users

# List only active users (default)
curl -X GET http://localhost:8080/auth/users \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

# List all users (active and inactive)
curl -X GET 'http://localhost:8080/auth/users?active=' \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

# List only inactive users
curl -X GET 'http://localhost:8080/auth/users?active=false' \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

⚠️ Requires ADMIN role

Response:

[
  {
    "username": "admin",
    "email": "admin@maddoxbar.com",
    "roles": ["USER", "ADMIN"]
  },
  {
    "username": "user",
    "email": "user@maddoxbar.com",
    "roles": ["USER"]
  }
]

Packaging and running the application

can be packaged using:

./gradlew build

produces the quarkus-run.jar file in the build/quarkus-app/ directory. be aware that it’s not an über-jar as the dependencies are copied into the build/quarkus-app/lib/ directory.

then runnable using java -jar build/quarkus-app/quarkus-run.jar.

if you want to build an über-jar, execute the following command:

./gradlew build -Dquarkus.package.jar.type=uber-jar

packaged as an über-jar, is now runnable using java -jar build/*-runner.jar.

Creating a native executable

native executable:

./gradlew build -Dquarkus.native.enabled=true

or run the native executable build in a container using:

./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true

and, yes. it has swagger-ui too: http://localhost:8080/swagger-ui

also, ill try to keep this updated. :D


this is a work in progress. see next-steps.md for upcoming features and technical roadmap.

About

api for managing teas and snacks with seeds using kotlin w quarkus

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages