import json import redis from flask import Flask, request, Response from pymongo import MongoClient, errors from bson import json_util from flasgger import Swagger from utils import read_docker_secret from caching import cache, cache_invalidate app = Flask(__name__) swagger = Swagger(app) users = MongoClient("mongodb", 27017).demo.users redis_cache = redis.Redis( host="redis", port=6379, db=0, password=read_docker_secret("REDIS_PASSWORD") ) @app.route("/users/", methods=["POST"]) def add_user(userid): """Create user --- parameters: - name: userid in: path type: string required: true - name: email in: formData type: string required: true - name: name in: formData type: string required: true responses: 200: description: Creation succeded """ request_params = request.form if "email" not in request_params or "name" not in request_params: return Response( "Email and name not present in parameters!", status=404, mimetype="application/json", ) try: users.insert_one( { "_id": userid, "email": request_params["email"], "name": request_params["name"], } ) except errors.DuplicateKeyError as e: return Response("Duplicate user id!", status=404, mimetype="application/json") return Response( json.dumps(users.find_one({"_id": userid})), status=200, mimetype="application/json", ) @app.route("/users/", methods=["PUT"]) @cache_invalidate(redis=redis_cache, key="userid") def update_user(userid): """Update user information --- parameters: - name: userid in: path type: string required: true - name: email in: formData type: string required: false - name: name in: formData type: string required: false responses: 200: description: Update succeded """ request_params = request.form if "email" not in request_params and "name" not in request_params: return Response( "Email or name must be present in parameters!", status=404, mimetype="application/json", ) set = {} if "email" in request_params: set["email"] = request_params["email"] if "name" in request_params: set["name"] = request_params["name"] users.update_one({"_id": userid}, {"$set": set}) return Response( json.dumps(users.find_one({"_id": userid})), status=200, mimetype="application/json", ) @app.route("/users/", methods=["GET"]) @cache(redis=redis_cache, key="userid") def get_user(userid): """Details about a user --- parameters: - name: userid in: path type: string required: true definitions: User: type: object properties: _id: type: integer email: type: string name: type: string responses: 200: description: User model schema: $ref: '#/definitions/User' 404: description: User not found """ user = users.find_one({"_id": userid}) print("getting user") if None == user: return Response("", status=404, mimetype="application/json") return Response(json.dumps(user), status=200, mimetype="application/json") @app.route("/users", methods=["GET"]) def get_users(): """Example endpoint returning all users with pagination --- parameters: - name: limit in: query type: integer required: false - name: offset in: query type: integer required: false definitions: Users: type: array items: properties: _id: type: integer email: type: string name: type: string responses: 200: description: List of user models schema: $ref: '#/definitions/Users' """ request_args = request.args limit = int(request_args.get("limit")) if "limit" in request_args else 10 offset = int(request_args.get("offset")) if "offset" in request_args else 0 user_list = users.find().limit(limit).skip(offset) if None == users: return Response(json.dumps([]), status=200, mimetype="application/json") extracted = [ {"userid": d["_id"], "name": d["name"], "email": d["email"]} for d in user_list ] return Response( json.dumps(extracted, default=json_util.default), status=200, mimetype="application/json", ) @app.route("/users/", methods=["DELETE"]) @cache_invalidate(redis=redis_cache, key="userid") def delete_user(userid): """Delete operation for a user --- parameters: - name: userid in: path type: string required: true responses: 200: description: User deleted """ users.delete_one({"_id": userid}) return Response("", status=200, mimetype="application/json") if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=5000)