Beispiel #1
0
def character_knife():
    """Start a new knife run for a character."""

    if "access_token" in request.args and "state" in request.args:
        # verify token/start knife process for character
        # do this all out of band, we might be error limited right now
        if CACHE.get("authstate.{}".format(request.args["state"])):
            CACHE.delete("authstate.{}".format(request.args["state"]))
            token = uuid.uuid4()
            CACHE.set("new.{}".format(token), request.args["access_token"])
            return redirect("/view/{}/".format(token))

    # start sso flow
    state = uuid.uuid4()
    CACHE.set("authstate.{}".format(state), "1", timeout=300)

    return redirect(
        ("https://login.eveonline.com/oauth/authorize?response_type=token"
         "&redirect_uri={callback}&client_id={client}"
         "&scope={scopes}&state={state}").format(
             callback=CALLBACK_URL,
             client=CLIENT_ID,
             scopes=SCOPES,
             state=state,
         ))
Beispiel #2
0
def rate_limit():
    """Apply a rate limit."""

    key = "".join((Keys.rate_limit.value, get_ip()))
    reqs = CACHE.get(key) or 0
    if reqs >= 20:
        return True

    CACHE.set(key, reqs + 1, timeout=60)
    return False
Beispiel #3
0
def process_new():
    """Process all new tokens, verify or we're done early."""

    for new_key in utils.list_keys(Keys.new.value):
        uuid = new_key.split(".")[-1]
        LOG.warning("processing new uuid: %r", uuid)

        token = CACHE.get(new_key)
        CACHE.delete(new_key)

        if not token:
            LOG.warning("no token stored for uuid: %r", uuid)
            continue

        pending_key = "{}{}".format(Keys.pending.value, uuid)
        CACHE.set(
            pending_key,
            "1",
            timeout=70,
        )
        headers = {"Authorization": "Bearer {}".format(token)}
        _, res = utils.request_or_wait(
            "{}/verify/".format(ESI),
            headers=headers,
        )

        failed = False
        if isinstance(res, str) or "CharacterID" not in res:
            utils.write_data(uuid, {"auth failure": res})
            failed = True
        else:
            _, roles = utils.request_or_wait(
                "{}/latest/characters/{}/roles/".format(
                    ESI,
                    res["CharacterID"],
                ),
                headers=headers,
            )
            if isinstance(roles, str):
                utils.write_data(uuid, {"roles failure": roles})
                failed = True

        CACHE.delete(pending_key)

        if not failed:
            CACHE.set(
                "{}{}".format(Keys.processing.value, uuid),
                res["CharacterID"],
                timeout=7200,
            )

            WORKERS.append(
                gevent.spawn(knife, uuid, token, res, roles)
            )
Beispiel #4
0
def write_data(uuid, data):
    """Try to store the data, log errors."""

    try:
        CACHE.set(
            "{}{}".format(Keys.complete.value, uuid),
            codecs.decode(
                base64.b64encode(
                    gzip.compress(codecs.encode(
                        ujson.dumps(data),
                        "utf-8",
                    ))),
                "utf-8",
            ),
            timeout=EXPIRY,
        )
    except Exception as error:
        LOG.warning("Failed to save data: %r", error)
Beispiel #5
0
def refresh_spec():
    """Refresh the ESI spec.

    Returns:
        dictionary: JSON loaded swagger spec
    """

    try:
        spec_details = CACHE.get(Keys.spec.value)
    except redis.exceptions.ConnectionError:
        spec_details = None
        save_results = False
    else:
        save_results = True

    if spec_details is None:
        spec_details = {"timestamp": 0}

    if time.time() - spec_details["timestamp"] > 300:
        headers = {}
        if spec_details.get("etag"):
            headers["If-None-Match"] = spec_details["etag"]

        _, _, res = request_or_wait(
            "{}/latest/swagger.json".format(ESI),
            _as_res=True,
            headers=headers,
        )

        if isinstance(res, str):
            LOG.warning("failed to refresh spec: %s", res)
            return spec_details.get("spec", {})

        spec_details["timestamp"] = time.time()

        if res.status_code != 304:
            spec_details["etag"] = res.headers.get("ETag")
            spec_details["spec"] = JsonDeref().deref(res.json())

        if save_results:
            CACHE.set(Keys.spec.value, spec_details, timeout=3600)

    return spec_details["spec"]