from virtool.utils import random_alphanumeric


class Session:

    def __init__(self, session_document):
        self.id = session_document["_id"]

        self.authorized = session_document["authorized"]

        self.user_id = session_document.get("user_id")
        self.groups = session_document.get("groups")
        self.permissions = session_document.get("permissions")

    def has_group(self, *args):
        if not all(isinstance(str, arg) for arg in args):
            raise ValueError("Permissions must be of type str")

        return all(grp in self.groups for grp in args)

    def has_permission(self, *args):
        if not all(isinstance(str, arg) for arg in args):
            raise ValueError("Permissions must be of type str")

        return all(self.permissions[perm] is True for perm in args)


async def middleware_factory(app, handler):
    async def middleware_handler(request):
        session_id = request.cookies.get("session_id", None)
        ip = request.transport.get_extra_info("peername")[0]
        user_agent = request.headers["User-Agent"]

        document = None

        if session_id:
            document = await app["db"].sessions.find_one({"_id": session_id})

        if not document:
            document = {
                "_id": random_alphanumeric(128, mixed_case=True),
                "ip": ip,
                "user_agent": user_agent,
                "authorized": False
            }

            await app["db"].sessions.insert_one(document)

        session = Session(document)

        request["session"] = session

        response = await handler(request)

        response.set_cookie("session_id", request["session"].id)

        return response

    return middleware_handler

Add sessions module