from flask_restful import Resource, reqparse, abort, fields, marshal_with import json import os import random import string class ClientsFile: file = "clients.json" mtime = 0 clients = {} parser = None def __init__(self): self.get() self.setup_request_parser() def get(self): try: mtime = os.path.getmtime(self.file) if mtime > self.mtime: with open(self.file, "r") as client_file: self.clients = json.load(client_file) except FileNotFoundError as error: self.clients = {} self.save() return self.clients def find(self, client_id): self.get() if client_id in self.clients: client = self.clients[client_id] else: client = None return client def add(self, client): client.secret = self.secret() self.clients[client["client_id"]] = client self.save() return client def remove(self, client): del self.clients[client["client_id"]] self.save() def update(self, client_updates): client = self.find(client_updates["client_id"]) client.update(client_updates) self.clients[client["client_id"]] = client self.save() return client def save(self): try: with open(self.file, "w") as client_file: client_file.write(json.dumps(self.clients, indent=2)) return True except OSError as error: print(str(error)) return False def secret(self, chars=36): res = "".join( random.choices( string.ascii_lowercase + string.ascii_uppercase + string.digits, k=chars ) ) return str(res) def setup_request_parser(self): parser = reqparse.RequestParser() parser.add_argument( "client_id", type=str, help="A unique name to identify the client" ) parser.add_argument( "client_name", type=str, help="A human friendly name to identify the client" ) parser.add_argument( "subscription", type=str, help="A dot delimited string identify topics to subscribe to", ) self.parser = parser def parse(self): return self.parser.parse_args() resource_fields = { "client_id": fields.String, "client_name": fields.String, "subscription": fields.String, } clients_file = ClientsFile() # Client class Client(Resource): @marshal_with(resource_fields) def get(self, client_id): client = clients_file.find(client_id) if not client: abort(404, message="No client with id: {}".format(client_id)) return client def delete(self, todo_id): client = clients_file.find(client_id) if not client: abort(404, message="No client with id: {}".format(client_id)) else: clients_file.remove(client) return client, 204 def put(self, client_id): args = clients_file.parse() client = clients_file.find(client_id) if not client: abort(404, message="No client with id: {}".format(client_id)) else: client = clients_file.update(args) return client, 201 # ClientList class ClientList(Resource): def get(self): return { client_id: (client, client.pop("secret", None))[0] for client_id, client in clients_file.get().items() } def post(self): args = clients_file.parse() client = clients_file.find(args["client_id"]) if client: abort(403, message="Duplicate client id: {}".format(client_id)) else: client = clients_file.add(args) return client, 201