• James Kirk's avatar
    feat: dockerised the app · d6b2e404
    James Kirk authored
    feat: added docker-compose setup, inc run-compose and .env to handle vars for locally running
    refactor: changed rmq to fail when it can't connect, allowing stuff to wait until the MQ is available
    refactor: moved from assuming pipenv to just pip
    refactor: mounted volumes, so changed interactions with clients.json to match
    d6b2e404
clients.py 3.74 KB
from flask_restful import Resource, request, abort
from marshmallow import Schema, fields
import json
import os
import random
import string


class ClientSchema(Schema):
    client_id = fields.Str(required=True)
    client_name =  fields.Str(required=True)
    subscription = fields.Str(required=True)


class ClientsFile:
    file = "/data/clients.json"
    mtime = 0
    clients = {}
    parser = None

    def __init__(self):
        self.get()

    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)

clients_file = ClientsFile()

# Client
class Client(Resource):
    clients_file = None
    def __init__(self): 
        self.schema = ClientSchema()
        self.clients_file = ClientsFile()

    def get(self, client_id):
        client = self.clients_file.find(client_id)
        del client['secret']
        if not client:
            abort(404, message="No client with id: {}".format(client_id))
        return client

    def delete(self, todo_id):
        client = self.clients_file.find(client_id)
        if not client:
            abort(404, message="No client with id: {}".format(client_id))
        else:
            self.clients_file.remove(client)
        return client, 204

    def put(self, client_id):
        args = request.get_json()
        errors = self.schema.validate(args)
        if errors: 
            abort(400, message=str(errors))
        
        client = self.clients_file.find(client_id)
        if not client:
            abort(404, message="No client with id: {}".format(client_id))
        else:
            client = self.clients_file.update(args)
        return client, 201


# ClientList
class ClientList(Resource):
    def __init__(self): 
        self.schema = ClientSchema()
        self.clients_file = ClientsFile()

    def get(self):
        return {
            client_id: (client, client.pop("secret", None))[0]
            for client_id, client in self.clients_file.get().items()
        }

    def post(self):
        args = request.get_json()

        errors = self.schema.validate(args)
        if errors: 
            abort(400, message=str(errors))
        
        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