api-playground/app.py

139 lines
4.7 KiB
Python
Raw Normal View History

2026-06-08 17:11:32 +07:00
from bottle import Bottle, request, response, static_file
import json
import os
import db
app = Bottle()
db.init_db()
# ── auth config ──────────────────────────────────────────
# Token simpel, mudah diingat. Ganti sesuai kebutuhan.
API_TOKEN = "secret123"
# ── helpers ──────────────────────────────────────────────
def json_response(data, status=200):
response.content_type = "application/json"
response.status = status
return json.dumps(data)
2026-06-13 12:20:05 +07:00
def get_request_params():
"""
Ambil parameter request dari form URL-encoded atau JSON.
Ini menjaga endpoint tetap kompatibel dengan curl, playground, dan tools API.
"""
if request.content_type.startswith("application/json"):
payload = request.json or {}
return {key: str(value) for key, value in payload.items()}
return request.forms
2026-06-08 17:11:32 +07:00
def check_auth():
"""
Cek Bearer token.
Return None jika OK, atau string JSON error jika gagal.
"""
auth = request.get_header("Authorization", "")
if not auth.startswith("Bearer "):
return json.dumps({"error": "missing or invalid Authorization header"})
token = auth.split(" ", 1)[1].strip()
if token != API_TOKEN:
return json.dumps({"error": "invalid token"})
return None # ✅ token valid
# ── static playground page (tanpa auth) ──────────────────
@app.get("/")
def index():
return static_file("playground.html", root=os.path.join(os.path.dirname(__file__), "templates"))
# ── API: /api/enroll (butuh auth) ────────────────────────
@app.get("/api/enroll")
def api_enroll():
"""
GET /api/enroll list all
GET /api/enroll?id=3 detail id=3
"""
err = check_auth()
if err:
return json_response(json.loads(err), 401)
enroll_id = request.query.id
if enroll_id:
row = db.get_enroll(int(enroll_id))
if not row:
return json_response({"error": "not found"}, 404)
return json_response({"data": row})
rows = db.list_enrolls()
return json_response({"data": rows})
@app.post("/api/enroll")
def api_enroll_post():
"""
POST /api/enroll (form fields + Bearer token)
id if present edit, otherwise add
type
service
user
action "remove" to delete (needs id)
"""
err = check_auth()
if err:
return json_response(json.loads(err), 401)
2026-06-13 12:20:05 +07:00
params = get_request_params()
action = params.get("action", "").strip()
enroll_id = params.get("id", "").strip()
type_ = params.get("type", "").strip()
service = params.get("service", "").strip()
user = params.get("user", "").strip()
2026-06-08 17:11:32 +07:00
# ── remove ──
if action == "remove":
if not enroll_id:
return json_response({"error": "id is required for remove"}, 400)
2026-06-13 12:20:05 +07:00
if not enroll_id.isdigit():
return json_response({"error": "id must be an integer"}, 400)
if not db.get_enroll(int(enroll_id)):
return json_response({"error": "not found"}, 404)
2026-06-08 17:11:32 +07:00
db.remove_enroll(int(enroll_id))
return json_response({"message": "removed", "id": int(enroll_id)})
2026-06-13 12:20:05 +07:00
# ── validate required fields ──
if not type_ or not service or not user:
return json_response({"error": "type, service, user are required"}, 400)
2026-06-08 17:11:32 +07:00
# ── validate type ──
if type_ not in db.VALID_TYPES:
return json_response(
{"error": f"type must be one of: {', '.join(db.VALID_TYPES)}"}, 400
)
# ── validate service ──
if service not in db.VALID_SERVICES:
return json_response(
{"error": f"service must be one of: {', '.join(db.VALID_SERVICES)}"}, 400
)
# ── edit ──
if enroll_id:
2026-06-13 12:20:05 +07:00
if not enroll_id.isdigit():
return json_response({"error": "id must be an integer"}, 400)
if not db.get_enroll(int(enroll_id)):
return json_response({"error": "not found"}, 404)
2026-06-08 17:11:32 +07:00
db.edit_enroll(int(enroll_id), type_, service, user)
return json_response({"message": "updated", "id": int(enroll_id)})
# ── add ──
new_id = db.add_enroll(type_, service, user)
return json_response({"message": "created", "id": new_id}, 201)
# ── run ──────────────────────────────────────────────────
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True, reloader=True)