ESI management

Main module

EVE ESI (public API) layer

class sni.esi.esi.EsiResponse[source]

Bases: pydantic.main.BaseModel

A model for ESI responses

data: Any = None
static from_response(response: requests.models.Response) → sni.esi.esi.EsiResponse[source]

Converts a request.Response object to a sni.esi.esi.EsiResponse.

headers: dict = None
id_annotations: dict = None
status_code: int = None
sni.esi.esi._id_annotations(data: Any) → Dict[int, concurrent.futures._base.Future][source]

Actual recursive concurrent implementation of sni.esi.esi.id_annotations(). Basically, calls to :meth`sni.esi.esi.id_to_name` are sumitted to an thread pool executor for better performances.

sni.esi.esi.esi_delete(path: str, *, kwargs: dict = {}, token: Optional[str] = None) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request() for DELETE requests.

sni.esi.esi.esi_get(path: str, *, kwargs: dict = {}, token: Optional[str] = None) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request() for GET requests.

sni.esi.esi.esi_get_all_pages(path: str, *, token: Optional[str] = None, kwargs: dict = {}) → sni.esi.esi.EsiResponse[source]

Returns all pages of an ESI GET path

sni.esi.esi.esi_post(path: str, *, kwargs: dict = {}, token: Optional[str] = None) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request() for POST requests.

sni.esi.esi.esi_put(path: str, *, kwargs: dict = {}, token: Optional[str] = None) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request() for PUT requests.

sni.esi.esi.esi_request(http_method: str, path: str, *, kwargs: dict = {}, token: Optional[str] = None) → sni.esi.esi.EsiResponse[source]

Makes an HTTP request to the ESI, and returns the response object.

sni.esi.esi.executor = <concurrent.futures.thread.ThreadPoolExecutor object>

Executor for sni.esi.esi._id_annotations()

sni.esi.esi.get_esi_path_scope(path: str) → sni.esi.scope.EsiScope[source]

Returns the ESI scope that is required for a given ESI path.

Raises mongoengine.DoesNotExist if no suitable path is found.

Examples

>>> get_esi_path_scope('latest/characters/0000000000/assets')
EsiScope.ESI_ASSETS_READ_ASSETS_V1
>>> get_esi_path_scope('latest/alliances')
EsiScope.PUBLICDATA
sni.esi.esi.id_annotations(data: Any) → Dict[int, str][source]

Annotates a JSON document. In documents returned by the ESI, ID fields always have the same name (e.g. solar_system_id, character_id, etc.). This method recursively searches for these ID fields and returns a dict mapping these IDs to a name.

sni.esi.esi.id_to_name(id_field_value: int, id_field_name: str) → str[source]

Converts an object ID (e.g. station, solar system, SDE type) to a name.

sni.esi.esi.load_esi_openapi() → None[source]

Loads the ESI Swagger API into the database.

Should be called in the initialization stage.

EVE SSO

This module handles the communication with EVE SSO

class sni.esi.sso.AuthorizationCodeResponse[source]

Bases: pydantic.main.BaseModel

A token document issued by the ESI looks like this:

{
    "access_token": "jZOzkRtA8B...LQJg2",
    "token_type": "Bearer",
    "expires_in": 1199,
    "refresh_token": "RGuc...w1"
}
access_token: str = None
expires_in: int = None
refresh_token: str = None
token_type: str = None
class sni.esi.sso.DecodedAccessToken[source]

Bases: pydantic.main.BaseModel

Decoded access token issued by the ESI. Should look like this:

{
    "scp": [
        "esi-skills.read_skills.v1",
        "esi-skills.read_skillqueue.v1"
    ],
    "jti": "998e12c7-3241-43c5-8355-2c48822e0a1b",
    "kid": "JWT-Signature-Key",
    "sub": "CHARACTER:EVE:123123",
    "azp": "my3rdpartyclientid",
    "name": "Some Bloke",
    "owner": "8PmzCeTKb4VFUDrHLc/AeZXDSWM=",
    "exp": 1534412504,
    "iss": "login.eveonline.com"
}
azp: str = None
property character_id

Extracts the character ID from the sub field.

exp: int = None
iss: str = None
jti: str = None
kid: str = None
name: str = None
owner: str = None
scp: List[EsiScope] = None
sub: str = None
exception sni.esi.sso.EsiTokenError[source]

Bases: Exception

Raised when something goes wrong with tokens.

sni.esi.sso.decode_access_token(access_token: str) → sni.esi.sso.DecodedAccessToken[source]

Converts an access token in JWT form to a sni.esi.sso.DecodedAccessToken

sni.esi.sso.get_access_token_from_callback_code(code: str) → sni.esi.sso.AuthorizationCodeResponse[source]

Gets an access token (along with its refresh token) from an EVE SSO authorization code.

Returns

The document issued by the ESI, or None

Reference:

OAuth 2.0 for Web Based Applications <https://docs.esi.evetech.net/docs/sso/web_based_sso_flow.html>

Todo

Validate the ESI JWT token

sni.esi.sso.get_auth_url(esi_scopes: List[sni.esi.scope.EsiScope], state: str = '00000000-0000-0000-0000-000000000000') → str[source]

Returns an EVE SSO login url based on the scopes passed in argument.

Parameters
  • esi_scopes – List of esi scope

  • state – A state string (default: None)

Returns

A url in string form

sni.esi.sso.get_basic_authorization_code() → str[source]

Returns an authorization code derived from the ESI client_id and client_secret.

More precisely, it is:

urlsafe_b64encode('<client_id>:<client_secret>')
sni.esi.sso.refresh_access_token(refresh_token: str) → sni.esi.sso.AuthorizationCodeResponse[source]

Refreshes an access token.

Returns

The response in an sni.esi.sso.AuthorizationCodeResponse

Reference:

esi-docs

ESI Token management

EVE token (access and refresh) management

class sni.esi.token.TrackingStatus[source]

Bases: int, enum.Enum

Tracking status of a user, i.e. wether this user has a valid refresh token attached to it, or not.

HAS_A_VALID_REFRESH_TOKEN = 2
HAS_NO_REFRESH_TOKEN = 0
ONLY_HAS_INVALID_REFRESH_TOKEN = 1
sni.esi.token.available_esi_scopes(usr: sni.user.models.User) → Set[sni.esi.scope.EsiScope][source]

Given a user, returns all the scopes for which SNI has a valid refresh token.

sni.esi.token.esi_delete_on_befalf_of(path: str, character_id: int, *, invalidate_token_on_4xx=False, **kwargs) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request_on_behalf_of() for DELETE requests.

sni.esi.token.esi_get_on_befalf_of(path: str, character_id: int, *, invalidate_token_on_4xx=False, **kwargs) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request_on_behalf_of() for GET requests.

sni.esi.token.esi_post_on_befalf_of(path: str, character_id: int, *, invalidate_token_on_4xx=False, **kwargs) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request_on_behalf_of() for POST requests.

sni.esi.token.esi_put_on_befalf_of(path: str, character_id: int, *, invalidate_token_on_4xx=False, **kwargs) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request_on_behalf_of() for PUT requests.

sni.esi.token.esi_request_on_behalf_of(http_method: str, path: str, character_id: int, *, invalidate_token_on_4xx=False, **kwargs) → sni.esi.esi.EsiResponse[source]

Wrapper for sni.esi.esi.esi_request_on_behalf_of() for GET requests. If the argument invalidate_token_on_4xx is set to True, then the user token is invalidated if the ESI request results in a 403.

sni.esi.token.get_access_token(character_id: int, scope: sni.esi.scope.EsiScope = <EsiScope.PUBLICDATA: 'publicData'>) → sni.esi.models.EsiAccessToken[source]

Returns an access token, refreshes if needed

Todo

Support multiple scopes.

sni.esi.token.has_esi_scope(usr: sni.user.models.User, scope: sni.esi.scope.EsiScope) → bool[source]

Tells wether the user has a refresh token with the given scope.

sni.esi.token.save_esi_tokens(esi_response: sni.esi.sso.AuthorizationCodeResponse) → sni.esi.models.EsiAccessToken[source]

Saves the tokens contained in an SSO reponse into the database.

Create the owner user if necessary.

Returns

The new ESI access token.

sni.esi.token.token_has_enough_scopes(access_token: sni.esi.sso.DecodedAccessToken, usr: sni.user.models.User) → bool[source]

Tells wether the access token has all the cropes that are required for a given user.

sni.esi.token.tracking_status(usr: sni.user.models.User) → sni.esi.token.TrackingStatus[source]

Reports the tracking status of this user, see sni.esi.token.TrackingStatus

Database models

ESI related database models

class sni.esi.models.EsiAccessToken(*args, **values)[source]

Bases: mongoengine.document.Document

A model representing an ESI access token, along with its refresh token and relevant metadatas.

SCHEMA_VERSION = 2

Latest schema version for this collection

_version

Schema version of this document

access_token

The ESI access token string

created_on

Timestamp of the creation of this access token (according to the ESI)

expires_on

Expiration timestamp of this access token (according to the ESI)

owner

Reference to the owner of this token

refresh_token

Reference towards the refresh token that issued this access token

scopes

ESI scopes of the access token

class sni.esi.models.EsiPath(*args, **values)[source]

Bases: mongoengine.document.Document

Represents a path in ESI’s openapi specification.

http_method

HTTP method

path

String form of the path, e.g. /characters/{character_id}/

path_re

Regular expression for this path, in string form

scope

Scope required for this path

version

ESI version (NOT schema version)

class sni.esi.models.EsiRefreshToken(*args, **values)[source]

Bases: mongoengine.document.Document

A model representing an ESI access token, along with its refresh token and relevant metadatas.

SCHEMA_VERSION = 2

Latest schema version for this collection

_version

Schema version of this document

created_on

Timestamp of the creation of this document

owner

Reference to the owner of this token

refresh_token

The ESI refresh token string

scopes

ESI scopes of the refresh token

updated_on

Timestamp of the last update of this document

valid

Wether this refresh token is valid

Jobs

Some jobs to he scheduled, regarding the state of the database (e.g. making sure all users are in the good corp, etc.)

sni.esi.jobs.refresh_tokens()[source]

Iterates through the ESI refresh tokens and refreshes the corresponding ESI access tokens.

Database signals

Database signals. See Mongoengine signals

Migration

Database migrations

sni.esi.migration.migrate() → None[source]

Runs migration tasks

sni.esi.migration.migrate_esi_access_token() → None[source]

Run migration tasks on the esi_access_token connection.

sni.esi.migration.migrate_esi_refresh_token() → None[source]

Run migration tasks on the esi_refresh_token collection.

ESI scopes

esi-alliances.read_contacts.v1
esi-assets.read_assets.v1
esi-assets.read_corporation_assets.v1
esi-bookmarks.read_character_bookmarks.v1
esi-bookmarks.read_corporation_bookmarks.v1
esi-calendar.read_calendar_events.v1
esi-calendar.respond_calendar_events.v1
esi-characters.read_agents_research.v1
esi-characters.read_blueprints.v1
esi-characters.read_chat_channels.v1
esi-characters.read_contacts.v1
esi-characters.read_corporation_roles.v1
esi-characters.read_fatigue.v1
esi-characters.read_fw_stats.v1
esi-characters.read_loyalty.v1
esi-characters.read_medals.v1
esi-characters.read_notifications.v1
esi-characters.read_opportunities.v1
esi-characters.read_standings.v1
esi-characters.read_titles.v1
esi-characters.write_contacts.v1
esi-characterstats.read.v1
esi-clones.read_clones.v1
esi-clones.read_implants.v1
esi-contracts.read_character_contracts.v1
esi-contracts.read_corporation_contracts.v1
esi-corporations.read_blueprints.v1
esi-corporations.read_contacts.v1
esi-corporations.read_container_logs.v1
esi-corporations.read_corporation_membership.v1
esi-corporations.read_divisions.v1
esi-corporations.read_facilities.v1
esi-corporations.read_fw_stats.v1
esi-corporations.read_medals.v1
esi-corporations.read_standings.v1
esi-corporations.read_starbases.v1
esi-corporations.read_structures.v1
esi-corporations.read_titles.v1
esi-corporations.track_members.v1
esi-fittings.read_fittings.v1
esi-fittings.write_fittings.v1
esi-fleets.read_fleet.v1
esi-fleets.write_fleet.v1
esi-industry.read_character_jobs.v1
esi-industry.read_character_mining.v1
esi-industry.read_corporation_jobs.v1
esi-industry.read_corporation_mining.v1
esi-killmails.read_corporation_killmails.v1
esi-killmails.read_killmails.v1
esi-location.read_location.v1
esi-location.read_online.v1
esi-location.read_ship_type.v1
esi-mail.organize_mail.v1
esi-mail.read_mail.v1
esi-mail.send_mail.v1
esi-markets.read_character_orders.v1
esi-markets.read_corporation_orders.v1
esi-markets.structure_markets.v1
esi-planets.manage_planets.v1
esi-planets.read_customs_offices.v1
esi-search.search_structures.v1
esi-skills.read_skillqueue.v1
esi-skills.read_skills.v1
esi-ui.open_window.v1
esi-ui.write_waypoint.v1
esi-universe.read_structures.v1
esi-wallet.read_character_wallet.v1
esi-wallet.read_corporation_wallet.v1
esi-wallet.read_corporation_wallets.v1
publicData