clients.py 3.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
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