From 117a978e62cb0c126fdea40202924ed5c924e003 Mon Sep 17 00:00:00 2001 From: Peter Williams Date: Mon, 23 Mar 2020 22:27:44 -0400 Subject: [PATCH] Add the "login" API. The API doesn't really do anything on the server, but the Windows clients use this API to undertake big actions such as invalidating the cache or demanding that the user download an update. --- docs/endpoints/index.rst | 1 + docs/endpoints/login.rst | 91 ++++++++++++++++++++++++++++++++++++++ wwt_api_client/__init__.py | 75 ++++++++++++++++++++++++++++++- 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 docs/endpoints/login.rst diff --git a/docs/endpoints/index.rst b/docs/endpoints/index.rst index 12745c6..c9c4561 100644 --- a/docs/endpoints/index.rst +++ b/docs/endpoints/index.rst @@ -4,5 +4,6 @@ Endpoints .. toctree:: :maxdepth: 1 + login.rst show-image.rst tile-image.rst diff --git a/docs/endpoints/login.rst b/docs/endpoints/login.rst new file mode 100644 index 0000000..61d4406 --- /dev/null +++ b/docs/endpoints/login.rst @@ -0,0 +1,91 @@ +.. _endpoint-Login: + +``wwtweb/login.aspx`` +===================== + +Windows clients invoke this API when they boot up. They send advisory version +information to the server. The server returns compatibility information that +the clients use to recommend or require updates. + +Query Parameters +---------------- + +The ``WWTWeb/Login.aspx`` endpoint processes the following URL query +parameters: + +=========== ============== ========= ======= +Name Type Required? Summary +=========== ============== ========= ======= +``user`` GUID No A GUID associated with this user +``Version`` Version string No The version number of the client logging in +``Equinox`` Existential No If present, indicates a non-ancient client +=========== ============== ========= ======= + +The ``user`` and ``Version`` are purely advisory and are not verified in any +way. In particular, the GUID is not coordinated with WWT Communities +activities. These values may be logged for diagnostic purposes. + +The ``Equinox`` parameter should always be set to ``true``. The WWT “Equinox” +release came out in 2008, and all subsequent Windows client versions set it to +true. + +Reponse Format +-------------- + +The reponse is plain text. For ``Equinox`` clients, the response may look like:: + + ClientVersion:5.5.3.1 + DataVersion:330 + Message: + WarnVersion:5.5.0.1 + MinVersion:2.2.32.1 + UpdateUrl:https://wwtweb.blob.core.windows.net/drops/WWTSetup.5.5.03.msi + +For ancient clients, the response looks like:: + + ClientVersion:2.2.32.1 + DataVersion:225 + Message: + + WarnVersion:2.2.31.1 + MinVersion:2.2.32.1 + UpdateUrl:http://content.worldwidetelescope.org/equinox/wwtequinoxsetup.msi + +Modern (post-Equinox) Windows clients parse the response in the following way: + +- The response is split on ``\n`` characters. +- The first line must start with ``ClientVersion:``; the text after the colon + is the “latest version”. This version, and all others, have four + dot-separated components as in the examples above. +- The second line must start with ``DataVersion:``; the text after the colon + is the “data version”. +- The text after the colon on the third line is the “message”. +- If there are more than three lines, the text after the colon on the fourth + line is the “warn version”; otherwise the warn version is the latest + version. +- If there are more than four lines, the text after the colon on the fifth + line is the “minimum version”; otherwise the minimum version is the latest + version. +- If there are more than five lines, the text after the colon on the sixth + line is the “update URL”; otherwise the update URL is + ``http://www.worldwidetelescope.org/wwtweb/setup.aspx``. + +These pieces of data are then acted upon in the following way by the Windows +client: + +- If the message is non-empty, it is shown to the user in a dialog box. +- If the version of the running client is less than the minimum version, the + user will be prompted to download an MSI installer from the update URL. + The installer will be automatically run if consent is given and successfully + downloaded. Either way, the Windows client will exit. +- If the warn version is newer than the running client and automatic updates + are turned on, the user will also be prompted to download an MSI installer + from the update URL. But if they do not update, the program continues + running. +- If the user has explicitly asked to check for updates and the latest version + is newer than the running client, the behavior is as above. +- When the Windows client first logs in, it records the data version with its + local cache. If the server-provided data version changes, the client will + consider its cache out-of-date and re-download all data. Note that this + comparison is purely for textual equality, unlike the software version + checks. diff --git a/wwt_api_client/__init__.py b/wwt_api_client/__init__.py index 0c4a5a0..3d28b31 100644 --- a/wwt_api_client/__init__.py +++ b/wwt_api_client/__init__.py @@ -1,5 +1,5 @@ # -*- mode: python; coding: utf-8 -*- -# Copyright 2019 the .Net Foundation +# Copyright 2019-2020 the .Net Foundation # Distributed under the terms of the revised (3-clause) BSD license. from __future__ import absolute_import, division, print_function @@ -81,6 +81,34 @@ class Client(object): return self._session + def login(self, user_guid='00000000-0000-0000-0000-000000000000', client_version='6.0.0.0', + equinox_version_or_later=True): + """Create a :ref:`Login ` request object. + + Parameters are assigned to attributes of the return value; see + :class:`the class documentation ` for descriptions. + + Examples + -------- + The arguments are for informational purposes only and so may be left + at their defaults. + + >>> from wwt_api_client import Client + >>> req = Client().login() + >>> info = req.send() # textual data about versions on server + + Returns + ------- + request : an initialized :class:`LoginRequest` object + The request. + + """ + req = LoginRequest(self) + req.user_guid = user_guid + req.client_version = client_version + req.equinox_version_or_later = equinox_version_or_later + return req + def show_image(self, image_url=None, name=None, credits=None, credits_url=None, dec_deg=0.0, ra_deg=0.0, reverse_parity=False, rotation_deg=0.0, scale_arcsec=1.0, thumbnail_url=None, x_offset_pixels=0.0, y_offset_pixels=0.0): @@ -373,6 +401,49 @@ class APIRequest(object): return resp.text +class LoginRequest(APIRequest): + """Indicate a client login to the server. + + """ + user_guid = '00000000-0000-0000-0000-000000000000' + "A GUID associated with the user logging in. The server doesn't track these." + + client_version = '6.0.0.0' + "The version of the client logging in." + + equinox_version_or_later = True + "Whether this client is of the \"Equinox\" release (~2008) or later." + + def invalidity_reason(self): + if not _is_textable(self.user_guid): + return '"user_guid" must be a string-like object' + + if not _is_textable(self.client_version): + return '"client_version" must be a string-like object' + + if not isinstance(self.equinox_version_or_later, bool): + return '"equinox_version_or_later" must be a boolean' + + return None + + def make_request(self): + params = [ + ('user', _maybe_as_bytes(self.user_guid)), + ('Version', _maybe_as_bytes(self.client_version)), + ] + + if self.equinox_version_or_later: + params.append(('Equinox', 'true')) + + return requests.Request( + method = 'GET', + url = self._client._api_base + '/WWTWeb/login.aspx', + params = params, + ) + + +# TODO: connect this to wwt_data_formats! + class ShowImageRequest(APIRequest): """Request a WTML XML document suitable for showing an image in a client. @@ -521,6 +592,8 @@ class ShowImageRequest(APIRequest): ) +# TODO: connect this to wwt_data_formats! + class TileImageRequest(APIRequest): """Tile a large image on the server and obtain a WTML XML document suitable for displaying it in a client. FITS images are not supported.