commit 6833cba08b8f164e2c22ebd752ba938c75a15094 Author: Anrab35 Date: Wed Mar 27 17:04:51 2024 +0100 First commit :tada: diff --git a/Barnabe_DUPONT_TP1_R410.zip b/Barnabe_DUPONT_TP1_R410.zip new file mode 100644 index 0000000..b7f4d10 Binary files /dev/null and b/Barnabe_DUPONT_TP1_R410.zip differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/__pycache__/APItest.cpython-310-pytest-6.2.5.pyc b/__pycache__/APItest.cpython-310-pytest-6.2.5.pyc new file mode 100644 index 0000000..ec3c20d Binary files /dev/null and b/__pycache__/APItest.cpython-310-pytest-6.2.5.pyc differ diff --git a/app/__pycache__/medals.cpython-310.pyc b/app/__pycache__/medals.cpython-310.pyc new file mode 100644 index 0000000..24931bc Binary files /dev/null and b/app/__pycache__/medals.cpython-310.pyc differ diff --git a/app/athletes.py b/app/athletes.py new file mode 100644 index 0000000..ace8966 --- /dev/null +++ b/app/athletes.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# encoding: utf-8 +import os +import json +from flask import Flask, request, jsonify + +file = 'data/'+os.path.splitext(os.path.basename(__file__))[0]+'.json' + + +with open(file, 'r') as f: + j = json.load(f) + +def save_json(new_json): + with open(file, 'w') as f: + f.write(json.dumps(new_json, indent=4)) + with open(file, 'r') as f: + j = json.load(f) + +app = Flask(__name__) + +@app.route('/healthcheck', methods=['GET']) +def ping(): + return jsonify({"conatiner_status": "healthy"}) + +@app.route('/athletes', methods=['GET']) +def list_athletes(): + return jsonify({"status": "success", "data": j}) + +@app.route('/athletes', methods=['POST']) +def add_athlete(): + try: + new = json.loads(request.data) + next_id = j[-1]['id']+1 + j.append({ + "id": next_id, + "name": new['name'], + "surname": new['surname'], + "email": new['email'], + "country": new['country'], + "isDisabled": new['isDisabled'] + }) + save_json(j) + return jsonify({"status": "success", "id": next_id}) + except Exception as e: + print(e) + return jsonify({"status": "error", "message": "Please provide a valid JSON"}), 500 + +@app.route('/athletes/', methods=['GET']) +def get_athlete(id): + for a in j: + print(a['id']) + if a['id'] == int(id): + return jsonify({"status": "success", "data": a}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + +@app.route('/athletes/', methods=['PATCH']) +def edit_athlete(id): + try: + update = json.loads(request.data) + entries = ['name', 'surname', 'email', 'country', 'isDisabled'] + for i, a in enumerate(j): + if a['id'] == int(id): + for e in entries: + if update.get(e) is not None: + j[i][e] = update[e] + save_json(j) + return jsonify({"status": "success"}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + except Exception as e: + print(e) + return jsonify({"status": "error", "message": "Please provide a valid JSON"}), 500 + +@app.route('/athletes/', methods=['DELETE']) +def rm_athlete(id): + for i, a in enumerate(j): + print(a['id']) + if a['id'] == int(id): + j.pop(i) + save_json(j) + return jsonify({"status": "success"}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + + +app.run(host="0.0.0.0", debug=False) \ No newline at end of file diff --git a/app/data/athletes.json b/app/data/athletes.json new file mode 100644 index 0000000..db98f51 --- /dev/null +++ b/app/data/athletes.json @@ -0,0 +1,5 @@ +[ + { + "id": 0 + } +] \ No newline at end of file diff --git a/app/data/medals.json b/app/data/medals.json new file mode 100644 index 0000000..db98f51 --- /dev/null +++ b/app/data/medals.json @@ -0,0 +1,5 @@ +[ + { + "id": 0 + } +] \ No newline at end of file diff --git a/app/data/sports.json b/app/data/sports.json new file mode 100644 index 0000000..db98f51 --- /dev/null +++ b/app/data/sports.json @@ -0,0 +1,5 @@ +[ + { + "id": 0 + } +] \ No newline at end of file diff --git a/app/docs.py b/app/docs.py new file mode 100644 index 0000000..12b4bf0 --- /dev/null +++ b/app/docs.py @@ -0,0 +1,25 @@ +from flask import Flask, send_file +from flask_swagger_ui import get_swaggerui_blueprint + +app = Flask(__name__) + +SWAGGER_URL = '/docs' # URL for exposing Swagger UI (without trailing '/') +API_URL = '/docs/api/swagger.yml' # Our API url (can of course be a local resource) + +@app.route(API_URL, methods=['GET']) +def swagger_yml(): + # Read before use: http://flask.pocoo.org/docs/0.12/api/#flask.send_file + return send_file('/app/swagger.yml') + +# Call factory function to create our blueprint +swaggerui_blueprint = get_swaggerui_blueprint( + SWAGGER_URL, # Swagger UI static files will be mapped to '{SWAGGER_URL}/dist/' + API_URL, + config={ # Swagger UI config overrides + 'app_name': "JO" + }, +) + +app.register_blueprint(swaggerui_blueprint) + +app.run(host="0.0.0.0", debug=False) \ No newline at end of file diff --git a/app/medals.py b/app/medals.py new file mode 100644 index 0000000..753b751 --- /dev/null +++ b/app/medals.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# encoding: utf-8 +import os +import json +from flask import Flask, request, jsonify + +file = 'data/'+os.path.splitext(os.path.basename(__file__))[0]+'.json' + +with open(file, 'r') as f: + j = json.load(f) + +def save_json(new_json): + with open(file, 'w') as f: + f.write(json.dumps(new_json, indent=4)) + with open(file, 'r') as f: + j = json.load(f) + +valid_ranks = ['gold', 'silver', 'bronze'] + +app = Flask(__name__) + +@app.route('/healthcheck', methods=['GET']) +def ping(): + return jsonify({"conatiner_status": "healthy"}) + +@app.route('/medals', methods=['GET']) +def list_medals(): + return jsonify({"status": "success", "data": j}) + +@app.route('/medals', methods=['POST']) +def add_medal(): + try: + new = json.loads(request.data) + if new['rank'] not in valid_ranks: + return jsonify({"status": "error", "message": "The valid ranks are gold, silver and bronze"}), 400 + next_id = j[-1]['id']+1 + j.append({ + "id": next_id, + "rank": new['rank'], + "sportID": new['sportID'], + "athleteID": new['athleteID'] + }) + save_json(j) + return jsonify({"status": "success", "id": next_id}) + except Exception as e: + print(e) + return jsonify({"status": "error", "message": "Please provide a valid JSON"}), 500 + +@app.route('/medals/', methods=['GET']) +def get_medal(id): + for m in j: + print(m['id']) + if m['id'] == int(id): + return jsonify({"status": "success", "data": m}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + +@app.route('/medals/', methods=['PATCH']) +def edit_medal(id): + try: + update = json.loads(request.data) + entries = ['rank', 'sportID', 'athleteID'] + for i, m in enumerate(j): + if m['id'] == int(id): + for e in entries: + if update.get(e) is not None: + if e == "rank": + if update[e] not in valid_ranks: + return jsonify({"status": "error", "message": "The valid ranks are gold, silver and bronze"}), 400 + j[i][e] = update[e] + save_json(j) + return jsonify({"status": "success"}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + except Exception as e: + print(e) + return jsonify({"status": "error", "message": "Please provide a valid JSON"}), 500 + +@app.route('/medals/', methods=['DELETE']) +def rm_medal(id): + for i, m in enumerate(j): + print(m['id']) + if m['id'] == int(id): + j.pop(i) + save_json(j) + return jsonify({"status": "success"}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + + +app.run(host="0.0.0.0", debug=False) \ No newline at end of file diff --git a/app/sports.py b/app/sports.py new file mode 100644 index 0000000..0712941 --- /dev/null +++ b/app/sports.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# encoding: utf-8 +import os +import json +from flask import Flask, request, jsonify + +file = 'data/'+os.path.splitext(os.path.basename(__file__))[0]+'.json' + + +with open(file, 'r') as f: + j = json.load(f) + +def save_json(new_json): + with open(file, 'w') as f: + f.write(json.dumps(new_json, indent=4)) + with open(file, 'r') as f: + j = json.load(f) + +app = Flask(__name__) + +@app.route('/healthcheck', methods=['GET']) +def ping(): + return jsonify({"conatiner_status": "healthy"}) + +@app.route('/sports', methods=['GET']) +def list_sports(): + return jsonify({"status": "success", "data": j}) + +@app.route('/sports', methods=['POST']) +def add_sport(): + try: + new = json.loads(request.data) + next_id = j[-1]['id']+1 + j.append({ + "id": next_id, + "name": new['name'], + "place": new['place'], + "category": new['category'], + }) + save_json(j) + return jsonify({"status": "success", "id": next_id}) + except Exception as e: + print(e) + return jsonify({"status": "error", "message": "Please provide a valid JSON"}), 500 + +@app.route('/sports/', methods=['GET']) +def get_sport(id): + for s in j: + if s['id'] == int(id): + return jsonify({"status": "success", "data": s}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + +@app.route('/sports/', methods=['PATCH']) +def edit_sport(id): + try: + update = json.loads(request.data) + entries = ['name', 'place', 'category'] + for i, s in enumerate(j): + if s['id'] == int(id): + for e in entries: + if update.get(e) is not None: + j[i][e] = update[e] + save_json(j) + return jsonify({"status": "success"}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + except Exception as e: + print(e) + return jsonify({"status": "error", "message": "Please provide a valid JSON"}), 500 + +@app.route('/sports/', methods=['DELETE']) +def rm_sport(id): + for i, s in enumerate(j): + if s['id'] == int(id): + j.pop(i) + save_json(j) + return jsonify({"status": "success"}) + return jsonify({"status": "error", "message": "Id not found"}), 404 + + +app.run(host="0.0.0.0", debug=False) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2a38fbc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,71 @@ +version: "3.3" + +services: + traefik: + image: "traefik:v2.11" + container_name: "traefik" + command: + - "--log.level=DEBUG" + - "--api.insecure=true" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web.address=:80" + ports: + - "80:80" + - "8080:8080" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + networks: + - backend + + docs: + image: "git.gnous.eu/anrab35/sae410_docs:latest" + container_name: "JO_docs" + networks: + - backend + labels: + - "traefik.enable=true" + - "traefik.http.routers.docs.rule=PathPrefix(`/docs`)" + + athletes: + image: "git.gnous.eu/anrab35/sae410_athletes:latest" + container_name: "JO_athletes" + networks: + - backend + volumes: + - "JO_athletes_data:/app/data:rw" + labels: + - "traefik.enable=true" + - "traefik.http.routers.athletes.rule=PathPrefix(`/athletes`)" + + medals: + image: "git.gnous.eu/anrab35/sae410_medals:latest" + container_name: "JO_medals" + networks: + - backend + volumes: + - "JO_medals_data:/app/data:rw" + labels: + - "traefik.enable=true" + - "traefik.http.routers.medals.rule=PathPrefix(`/medals`)" + + sports: + image: "git.gnous.eu/anrab35/sae410_sports:latest" + container_name: "JO_sports" + networks: + - backend + volumes: + - "JO_sports_data:/app/data:rw" + labels: + - "traefik.enable=true" + - "traefik.http.routers.sports.rule=PathPrefix(`/sports`)" + +networks: + backend: + name: backend + external: false + +volumes: + JO_athletes_data: + JO_medals_data: + JO_sports_data: \ No newline at end of file diff --git a/docker/athletes/Dockerfile b/docker/athletes/Dockerfile new file mode 100644 index 0000000..a9fe3ec --- /dev/null +++ b/docker/athletes/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3-alpine + +MAINTAINER Barnabé Dupont + +LABEL version="1.0.0" + +RUN apk add curl + +RUN adduser -D worker + +USER worker + +WORKDIR /home/worker + +COPY --chown=worker:worker docker/requirements.txt /home/worker + +RUN pip install --user -r requirements.txt + +WORKDIR /app + +COPY --chown=worker:worker app/athletes.py /app/ + +COPY --chown=worker:worker app/data/athletes.json /app/data/ + +EXPOSE 5000 + +HEALTHCHECK --interval=15s --timeout=30s --start-period=10s --retries=3 CMD curl --fail http://localhost:5000/healthcheck || exit 1 + +CMD ["python3", "athletes.py"] \ No newline at end of file diff --git a/docker/docs/Dockerfile b/docker/docs/Dockerfile new file mode 100644 index 0000000..2d7ca83 --- /dev/null +++ b/docker/docs/Dockerfile @@ -0,0 +1,26 @@ +FROM python:3-alpine + +MAINTAINER Barnabé Dupont + +LABEL version="1.0.0" + +RUN adduser -D worker + +USER worker + +WORKDIR /home/worker + +COPY --chown=worker:worker docker/docs/requirements.txt /home/worker + +RUN pip install --user -r requirements.txt + +WORKDIR /app + +COPY --chown=worker:worker app/docs.py /app/ + +COPY --chown=worker:worker swagger.yml /app/ + +EXPOSE 5000 + + +CMD ["python3", "docs.py"] \ No newline at end of file diff --git a/docker/docs/requirements.txt b/docker/docs/requirements.txt new file mode 100644 index 0000000..87945d1 --- /dev/null +++ b/docker/docs/requirements.txt @@ -0,0 +1,2 @@ +flask==3.0.0 +flask-swagger-ui==4.11.1 \ No newline at end of file diff --git a/docker/medals/Dockerfile b/docker/medals/Dockerfile new file mode 100644 index 0000000..8d9c775 --- /dev/null +++ b/docker/medals/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3-alpine + +MAINTAINER Barnabé Dupont + +LABEL version="1.0.0" + +RUN apk add curl + +RUN adduser -D worker + +USER worker + +WORKDIR /home/worker + +COPY --chown=worker:worker docker/requirements.txt /home/worker + +RUN pip install --user -r requirements.txt + +WORKDIR /app + +COPY --chown=worker:worker app/medals.py /app/ + +COPY --chown=worker:worker app/data/medals.json /app/data/ + +EXPOSE 5000 + +HEALTHCHECK --interval=15s --timeout=30s --start-period=10s --retries=3 CMD curl --fail http://localhost:5000/healthcheck || exit 1 + +CMD ["python3", "medals.py"] \ No newline at end of file diff --git a/docker/requirements.txt b/docker/requirements.txt new file mode 100644 index 0000000..0f800fc --- /dev/null +++ b/docker/requirements.txt @@ -0,0 +1 @@ +flask==3.0.0 \ No newline at end of file diff --git a/docker/sports/Dockerfile b/docker/sports/Dockerfile new file mode 100644 index 0000000..4042d77 --- /dev/null +++ b/docker/sports/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3-alpine + +MAINTAINER Barnabé Dupont + +LABEL version="1.0.0" + +RUN apk add curl + +RUN adduser -D worker + +USER worker + +WORKDIR /home/worker + +COPY --chown=worker:worker docker/requirements.txt /home/worker + +RUN pip install --user -r requirements.txt + +WORKDIR /app + +COPY --chown=worker:worker app/sports.py /app/ + +COPY --chown=worker:worker app/data/sports.json /app/data/ + +EXPOSE 5000 + +HEALTHCHECK --interval=15s --timeout=30s --start-period=10s --retries=3 CMD curl --fail http://localhost:5000/healthcheck || exit 1 + +CMD ["python3", "sports.py"] \ No newline at end of file diff --git a/pytest/__pycache__/APItest.cpython-310-pytest-6.2.5.pyc b/pytest/__pycache__/APItest.cpython-310-pytest-6.2.5.pyc new file mode 100644 index 0000000..36b2e37 Binary files /dev/null and b/pytest/__pycache__/APItest.cpython-310-pytest-6.2.5.pyc differ diff --git a/pytest/__pycache__/conftest.cpython-310-pytest-6.2.5.pyc b/pytest/__pycache__/conftest.cpython-310-pytest-6.2.5.pyc new file mode 100644 index 0000000..eb8bbc0 Binary files /dev/null and b/pytest/__pycache__/conftest.cpython-310-pytest-6.2.5.pyc differ diff --git a/pytest/__pycache__/test_athletes.cpython-310-pytest-6.2.5.pyc b/pytest/__pycache__/test_athletes.cpython-310-pytest-6.2.5.pyc new file mode 100644 index 0000000..77e47fc Binary files /dev/null and b/pytest/__pycache__/test_athletes.cpython-310-pytest-6.2.5.pyc differ diff --git a/pytest/__pycache__/test_medals.cpython-310-pytest-6.2.5.pyc b/pytest/__pycache__/test_medals.cpython-310-pytest-6.2.5.pyc new file mode 100644 index 0000000..142e28c Binary files /dev/null and b/pytest/__pycache__/test_medals.cpython-310-pytest-6.2.5.pyc differ diff --git a/pytest/__pycache__/test_sports.cpython-310-pytest-6.2.5.pyc b/pytest/__pycache__/test_sports.cpython-310-pytest-6.2.5.pyc new file mode 100644 index 0000000..e8263c3 Binary files /dev/null and b/pytest/__pycache__/test_sports.cpython-310-pytest-6.2.5.pyc differ diff --git a/pytest/test_athletes.py b/pytest/test_athletes.py new file mode 100644 index 0000000..ffd9a76 --- /dev/null +++ b/pytest/test_athletes.py @@ -0,0 +1,27 @@ +import requests +import random +import pytest + + +def pytest_namespace(): + return {'current_id': 0} + +def test_add_new_athlete(): + test_id = str(random.randint(1000,9999)) + x = requests.post('http://localhost/athletes', json={"name": "TEST", "surname": test_id, "email": "test@test.org", "country": "Listenbourg", "isDisabled": True}) + pytest.current_id = x.json()['id'] + assert x.status_code == 200 +def test_get_athlete(): + assert requests.get("http://localhost/athletes/"+str(pytest.current_id)).status_code == 200 +def test_edit_athlete(): + assert requests.patch("http://localhost/athletes/"+str(pytest.current_id), json={"name": "HELLO", "isDisabled": False}).status_code == 200 +def test_get_modified_athlete(): + x = requests.get("http://localhost/athletes/"+str(pytest.current_id)) + json = x.json()['data'] + assert x.status_code == 200 and json['name'] == "HELLO" and json['isDisabled'] == False +def test_delete_athlete(): + assert requests.delete("http://localhost/athletes/"+str(pytest.current_id)).status_code == 200 +def test_deleted_athlete(): + assert requests.get("http://localhost/athletes/"+str(pytest.current_id)).status_code == 404 +def test_add_fake_athlete(): + requests.post('http://localhost/athletes', json={"PEBCAK": True}).status_code == 400 \ No newline at end of file diff --git a/pytest/test_medals.py b/pytest/test_medals.py new file mode 100644 index 0000000..6f3efd7 --- /dev/null +++ b/pytest/test_medals.py @@ -0,0 +1,27 @@ +import requests +import random +import pytest + + +def pytest_namespace(): + return {'current_id': 0} + +def test_add_new_medal(): + test_id = random.randint(1000,9999) + x = requests.post('http://localhost/medals', json={"rank": "gold", "sportID": test_id, "athleteID": 1}) + pytest.current_id = x.json()['id'] + assert x.status_code == 200 +def test_get_medal(): + assert requests.get("http://localhost/medals/"+str(pytest.current_id)).status_code == 200 +def test_edit_medal(): + assert requests.patch("http://localhost/medals/"+str(pytest.current_id), json={"athleteID": 88}).status_code == 200 +def test_get_modified_medal(): + x = requests.get("http://localhost/medals/"+str(pytest.current_id)) + json = x.json()['data'] + assert x.status_code == 200 and json['rank'] == "gold" and json['athleteID'] == 88 +def test_delete_medal(): + assert requests.delete("http://localhost/medals/"+str(pytest.current_id)).status_code == 200 +def test_deleted_medal(): + assert requests.get("http://localhost/medals/"+str(pytest.current_id)).status_code == 404 +def test_add_fake_medal(): + requests.post('http://localhost/medals', json={"rank": "Loris"}).status_code == 400 \ No newline at end of file diff --git a/pytest/test_sports.py b/pytest/test_sports.py new file mode 100644 index 0000000..cacdb64 --- /dev/null +++ b/pytest/test_sports.py @@ -0,0 +1,28 @@ +import requests +import random +import pytest + + +def pytest_namespace(): + return {'current_id': 0} + +def test_add_new_sport(): + test_id = str(random.randint(1000,9999)) + x = requests.post('http://localhost/sports', json={"name": "TEST", "place": test_id, "category": "Multiplayer"}) + pytest.current_id = x.json()['id'] + assert x.status_code == 200 +def test_get_sport(): + print("http://localhost/sports/"+str(pytest.current_id)) + assert requests.get("http://localhost/sports/"+str(pytest.current_id)).status_code == 200 +def test_edit_sport(): + assert requests.patch("http://localhost/sports/"+str(pytest.current_id), json={"category": "Aquatic"}).status_code == 200 +def test_get_modified_sport(): + x = requests.get("http://localhost/sports/"+str(pytest.current_id)) + json = x.json()['data'] + assert x.status_code == 200 and json['category'] == "Aquatic" +def test_delete_sport(): + assert requests.delete("http://localhost/sports/"+str(pytest.current_id)).status_code == 200 +def test_deleted_sport(): + assert requests.get("http://localhost/sports/"+str(pytest.current_id)).status_code == 404 +def test_add_fake_sport(): + requests.post('http://localhost/sports', json={"rank": "gold", "sportID": 666, "athleteID": 1}).status_code == 400 \ No newline at end of file diff --git a/swagger.yml b/swagger.yml new file mode 100644 index 0000000..54ba976 --- /dev/null +++ b/swagger.yml @@ -0,0 +1,227 @@ +openapi: '3.0.2' +info: + title: API Jo + version: '1.0' +servers: + - url: http://localhost/ + +components: + schemas: + Athlete: + type: object + properties: + name: + type: string + surname: + type: string + email: + type: string + country: + type: string + isDisabled: + type: boolean + default: false + Sport: + type: object + properties: + name: + type: string + place: + type: string + category: + type: string + Medal: + type: object + properties: + rank: + type: string + enum: + - gold + - silver + - bronze + sportID: + type: integer + athleteID: + type: integer + + + + +paths: + /athletes: + get: + tags: + - Athletes + summary: Display athletes list + responses: + '200': + description: OK + post: + tags: + - Athletes + summary: Add a new athlete + responses: + '200': + description: OK + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Athlete' + + /athletes/{id}: + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + get: + tags: + - Athletes + summary: Display one athlete using the ID + responses: + '200': + description: 'OK' + content: + application/json: + schema: + $ref: '#/components/schemas/Athlete' + '404': + description: 'Not found' + patch: + tags: + - Athletes + summary: Modify a athlete using the ID + responses: + '200': + description: 'OK' + delete: + tags: + - Athletes + summary: Delete an athlete using the ID + responses: + '200': + description: 'OK' + '404': + description: 'Athete not found' + /sports: + get: + tags: + - Sports + summary: List all available sports + responses: + '200': + description: OK + post: + tags: + - Sports + summary: Add a sport + responses: + '200': + description: OK + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Sport' + /sports/{id}: + get: + tags: + - Sports + summary: Display a specific sport using the ID + responses: + '200': + description: 'OK' + content: + application/json: + schema: + $ref: '#/components/schemas/Sport' + '404': + description: 'Not found' + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + patch: + tags: + - Sports + summary: Edit a specific sport using the ID + responses: + '200': + description: 'OK' + delete: + tags: + - Sports + summary: Delete a specific sport using the ID + responses: + '200': + description: 'OK' + '404': + description: 'Sport not found' + /medal: + get: + tags: + - Medal + summary: Display medals list + responses: + '200': + description: OK + post: + tags: + - Medal + summary: Add a new medal + responses: + '200': + description: OK + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Medal' + /medals/{id}: + get: + tags: + - Medal + summary: Display a medal + responses: + '200': + description: 'OK' + content: + application/json: + schema: + $ref: '#/components/schemas/Medal' + '404': + description: 'Not found' + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + patch: + tags: + - Medal + summary: Modify element from medal + responses: + '200': + description: 'OK' + '404': + description: 'Medal not found' + delete: + tags: + - Medal + summary: Delete medal from Id + responses: + '200': + description: 'OK' + '404': + description: 'Medal not found' \ No newline at end of file