Twitcher: OWS Security Proxy¶
- Twitcher (the bird-watcher)
a birdwatcher mainly interested in catching sight of rare birds. (Leo).
Twitcher is a security proxy for OWS services like Web Processing Services (WPS). The proxy service uses OAuth2 access tokens to protect the OWS service access. In addition one can also use X.509 certificates for client authentication.
The implementation is not restricted to WPS services. It will be extended to more OWS services like WMS (Web Map Service) and might also be used for Thredds catalog services.
Twitcher extensions:
Magpie is an AuthN/AuthZ service provided by the PAVICS project.
Weaver middleware by CRIM. A reimplementation of an old Twitcher fork for workflow execution and a Swagger RESTful interface for Web Processing Services.
Twitcher is implemented with the Python Pyramid web framework.
You can try Twitcher online using Binder, or view the notebooks on NBViewer.
Twitcher is part of the Birdhouse project. The documentation is on ReadTheDocs.
Twitcher Docker images are also available for most recent tagged versions.
Overview¶
Twitcher Components¶
Twitcher consists of the following main parts:
- OWS Security
A security layer to protect service access with OAuth2 Tokens.
- OWS Registry
OWS Registry is a registration service with an OpenAPI interface to register OWS services for the OWS proxy protected by basic authentication.
- OWS Proxy
OWS Proxy a service which acts as a proxy for registered OWS services.
OAuth access tokens can be retrieved from a Keycloak authentication service using the client credentials workflow.

Installation¶
Quick Installation¶
Quick steps to install and start Twitcher:
$ git clone https://github.com/bird-house/twitcher.git
$ cd twitcher
$ conda env create
$ conda activate twitcher
$ make install
$ make migrate
$ make start
From GitHub Sources¶
Get Twitcher source from GitHub:
$ git clone https://github.com/bird-house/twitcher.git
$ cd twitcher
Create Conda environment named twitcher:
$ conda env update -f environment.yml
$ conda activate twitcher
Install the Twitcher app:
$ pip install -e .
OR
make install
For development you can use this command:
$ pip install -e .[dev]
OR
$ make develop
Initialize Database¶
Before you can start the service you need to initialize or upgrade the database:
$ make migrate
Starting Twitcher Service¶
For development twitcher is using the the waitress WSGI server.
Start the twitcher service using the development.ini configuration:
$ pserve development.ini --reload
OR
$ make start
Configuration¶
Twitcher has a configuration file development.ini for local development. Copy and edit this configuration to adapt to your settings.
Service¶
Edit the configuration to change the service parameters.
The URL of the Twitcher service endpoint:
twitcher.url = http://localhost:8000
Basic Authentication¶
Twitcher uses basic authentication for client application registration and service registration. Edit username and password in the configuration:
twitcher.username = demo
twitcher.password = demo
OAuth2 Token Generator¶
Twitcher uses OAuth2 tokens to control OWS service access. You can use several types of tokens.
Random Token¶
Tokens with UUID strings stored in the local twitcher database.
Edit the configuration file:
twitcher.token.type = random_token
Signed Token¶
JWT tokens signed with a certificate. You can generate a self-signed certificate for testing with the Makefile:
$ make gencert
Edit the configuration file:
twitcher.token.type = signed_token
twitcher.token.keyfile = key.pem # private key
twitcher.token.certfile = pubkey.pem # public key
Custom Token¶
JWT tokens using a shared secret. You can generate a UUID secret with:
$ make gensecret
Edit the configuration file:
twitcher.token.type = custom_token
twitcher.token.secret = secret
Keycloak Token¶
JWT tokens generated by a Keycloak OAuth2 service.
Edit the configuration file:
twitcher.token.type = keycloak_token
You need to copy the public key of your Keycloak realm to the configuration (see screenshot):
keycloak.token.secret = secret

Developer Guide¶
Running tests¶
Run tests using pytest.
First activate the twitcher
Conda environment and install pytest
.
$ source activate twitcher
$ pip install -r requirements_dev.txt # if not already installed
OR
$ make develop
Run quick tests (skip slow and online):
$ pytest -m 'not slow and not online'"
Run all tests:
$ pytest
Check pep8:
$ flake8
Run tests the lazy way¶
Do the same as above using the Makefile
.
$ make test
$ make test-all
$ make lint
$ make coverage
Upgrade Database¶
Initialize and upgrade the database using Alembic.
Generate your first revision:
$ conda activate twitcher
$ alembic -c development.ini revision --autogenerate -m "init"
Warning
This first step is only needed in development to generate a new database schema version.
Upgrade to that revision:
$ alembic -c development.ini upgrade head
Load default data into the database using a script.
$ initialize_twitcher_db development.ini
Note
You can use make migrate as a shortcut to upgrade or init the twitcher database (last two steps).
Building the docs¶
First install dependencies for the documentation:
$ make docs
Prepare a release¶
Update CHANGES.rst.
Bump a new version¶
Make a new version of twitcher in the following steps:
Make sure everything is commit to GitHub.
Update
CHANGES.rst
with the next version.Dry Run:
bumpversion --dry-run --verbose --new-version 0.5.1 patch
Do it:
bumpversion --new-version 0.5.1 patch
… or:
bumpversion --new-version 0.6.0 minor
Push it:
git push
Push tag:
git push --tags
See the bumpversion documentation for details.
Tutorial¶
Using the OWSProxy with a WPS application¶
The OWSProxy
is a proxy service for OWS services.
First you need an external WPS. You can use Emu WPS service from Birdhouse. Get it from GitHub and run the installation:
$ git clone https://github.com/bird-house/emu.git
$ cd emu
$ make install
$ make start
The Emu WPS service is available by default at the URL: http://localhost:5000/wps?service=WPS&version=1.0.0&request=GetCapabilities
Make sure Twitcher is installed and running:
$ cd ../twitcher # cd into the twitcher installation folder
$ pserve development.ini
Prepare your Client Application¶
Register your client application at twitcher to get a client_id and client_secret:
$ twitcherctl -k --username demo --password demo add --name demo_app
{'name': 'demo_app', 'client_id': 'id', 'client_secret': 'secret'}
Get an access token to use the registration service using your OAuth client_id and client_secret with scope register:
$ twitcherctl -k gentoken -i client_id -s client_secret --scope register
{'access_token': 'TOKEN', 'expires_in': 3600, 'scope': ['register'], 'token_type': 'Bearer'}
Register a WPS service¶
Register the Emu WPS service at the Twitcher OWSProxy
:
$ twitcherctl -k --username demo --password demo register --name emu http://localhost:5000/wps
If you don’t provide a name with --name
option then a nice name will be generated, for example sleepy_flamingo
.
Use the list
command to see which WPS services are registered with OWSProxy:
$ twitcherctl -k --username demo --password demo list
[{'url': 'http://localhost:5000/wps', 'type': 'wps', 'name': 'emu', 'auth': 'token'}]
Access a registered service¶
By default the registered service is available at the URL https://localhost:8000/ows/proxy/{service_name}
.
Replace the service_name
with the registered name.
Run a GetCapabilities
request for the registered Emu WPS service:
$ curl -k "http://localhost:8000/ows/proxy/emu?service=WPS&request=GetCapabilities"
Run a DescribeProcess
request:
$ curl -k "http://localhost:8000/ows/proxy/emu?service=WPS&version=1.0.0&request=DescribeProcess&identifier=hello"
Use a token to run an execute request¶
By default the WPS service is protected by the OWSSecurity
wsgi middleware.
You need to provide an OAuth access token to run an execute request.
Run an Exceute
request:
$ curl -k "http://localhost:8000/ows/proxy/emu?service=WPS&version=1.0.0&request=Execute&identifier=hello&DataInputs=name=tux"
Now you should get an XML error response with a message that you need to provide an access token.
We need to generate an access token with twitcherctl
using OAuth client_id and client_secret
with scope compute:
$ twitcherctl -k gentoken -i client_id -s client_secret --scope compute
{'access_token': 'TOKEN', 'expires_in': 3600, 'scope': ['compute'], 'token_type': 'Bearer'}
By default the token has a limited life time of one hour.
For testing you can provide the OAuth token as HTTP parameter:
$ curl -k "http://localhost:8000/ows/proxy/emu?service=WPS&version=1.0.0&request=Execute&identifier=hello&DataInputs=name=tux&access_token=TOKEN"
But you should use an HTTP header:
$ curl -k -H 'Authorization: Bearer TOKEN' "http://localhost:8000/ows/proxy/emu?service=WPS&version=1.0.0&request=Execute&identifier=hello&DataInputs=name=tux"
Use x509 certificates to control client access¶
Warning
You need an Nginx web-server in front of the Twitcher WSGI service to use x509 certificates.
Hint
You can install Twitcher with Nginx using an Ansible playbook_.
Since version 0.3.6 Twitcher is prepared to use x509 certificates to control client access. By default it is configured to accept x509 proxy certificates from ESGF.
Register the Emu WPS service at the Twitcher OWSProxy
with auth
option cert
:
$ twitcherctl -k --username demo --password demo register --name emu --auth cert http://localhost:5000/wps
The GetCapabilities
and DescribeProcess
requests are not blocked:
$ curl -k "http://localhost:8000/ows/proxy/emu?service=WPS&request=GetCapabilities"
$ curl -k "http://localhost:8000/ows/proxy/emu?service=WPS&version=1.0.0&request=DescribeProcess&identifier=hello"
When you run an Exceute
request without a certificate you should get an exception report:
$ curl -k "http://localhost:8000/ows/proxy/emu?service=WPS&version=1.0.0&request=Execute&identifier=hello&DataInputs=name=tux"
Now you should get an XML error response with a message that you need to provide a valid X509 certificate.
Get a valid proxy certificate from ESGF, you may use the esgf-pyclient to run a myproxy logon.
Let’s say your proxy certificate is cert.pem
, then run the exceute request again using this certificate:
$ curl --cert cert.pem --key cert.pem -k "http://localhost:8000/ows/proxy/emu?service=WPS&version=1.0.0request=Execute&identifier=hello&DataInputs=name=tux"
Keycloak example¶
Set-up a demo Keycloak service using an Ansible playbook.
The keycloak service is available at (username=admin
, password=admin
):
http://localhost:8080/auth/
You need to copy the public key of your Keycloak realm to the twitcher configuration (see screenshot):

Update your twitcher configuration in development.ini
:
twitcher.token.type = keycloak_token
keycloak.token.secret = public_key_copied_from_keycloak
Start the twitcher service and register the Emu WPS:
$ twitcherctl -k --username demo --password demo register --name emu http://localhost:5000/wps
Try the demo notebook to access a token from the keycloak and execute a WPS process.
Use client_id=demo
and copy the client secret from Keycloak in Clients/demo/Credentials/Secret (see screenshot).

Using Twitcher with Keycloak¶
Setup a Keycloak service with client credentials grant type. You can use this Ansible playbook. The Keycloak service is running on: http://localhost:8080
Configure the twitcher as described in the keycloak example of the twitcher tutorial and register the Emu WPS.
[ ]:
# disable ssl warnings
import urllib3
urllib3.disable_warnings()
Keycloak client¶
https://www.keycloak.org/docs/latest/server_admin/index.html#_service_accounts
[ ]:
keycloak_url = 'http://localhost:8080'
token_endpoint = '/auth/realms/demo/protocol/openid-connect/token'
client_id = 'demo'
client_secret = 'c083d72c-a262-40b1-ad51-326f6977d74b'
Get OAuth access token from Keycloak¶
scope=compute
[ ]:
token_url = "{}{}".format(keycloak_url, token_endpoint)
token_url
[ ]:
import os
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(
token_url,
scope='compute',
client_id=client_id,
client_secret=client_secret,
include_client_id=True,
verify=False)
token
[ ]:
token['access_token']
Execute WPS Process with access token¶
[ ]:
base_url = 'http://localhost:8000'
url = "{}/ows/proxy/emu?service=WPS&version=1.0.0&request=Execute&identifier=chomsky".format(base_url)
url
[ ]:
import requests
headers = {'Authorization': 'Bearer {}'.format(token['access_token'])}
resp = requests.get(url, headers=headers, verify=False)
resp.ok
[ ]:
'ProcessSucceeded' in resp.text
API Reference¶
Twitcher Client¶
- class twitcher.client.TwitcherService(url, username=None, password=None, verify=True)[source]¶
TwitcherService is a twitcher client to talk to the twitcher service API.
- add_client_app(name=None, redirect_uri=None)[source]¶
Add a client application to twitcher with optional name.
Twitcher CLI¶
The twitcherctl
is a command line tool to control the twitcher service.
It is used to generate access tokens and to register OWS services.
twitcherctl
is part of the twitcher installation:
$ twitcherctl -h
twitcherctl Commands and Options¶
twitcherctl
has the following command line options:
- -h, --help
Print usage message and exit
- -s, --serverurl
URL on which twitcher server is listening (default “http://localhost:8000/”).
- -u, --username
Username to access twitcher server.
- -p, --password
Password to access twitcher server.
- -k, --insecure
Don’t validate the server’s certificate.
List of available commands:
- add
Add OAuth2 client application.
- gentoken
Generates an access token.
- list
Lists all registered OWS services used by OWS proxy.
- clear
Removes all OWS services from the registry.
- register
Adds OWS service to the registry to be used by the OWS proxy.
- unregister
Removes OWS service from the registry.
Add an OAuth2 client application¶
Register an application using basic authentication with username and password (name and redirect-uri are optional):
$ twitcherctl -k --username demo --password demo add --name demo_app --redirect-uri http://localhost/demo_app
{'client_id': 'id', 'client_secret': 'secret'}
The result is an OAuth client_id and client_secret.
Generate an access token¶
Get an OAuth access token using client_id and client_secret for given scope:
$ twitcherctl -k gentoken -i client_id -s client_secret --scope compute
{'access_token': 'TOKEN', 'expires_in': 3600, 'scope': ['compute'], 'token_type': 'Bearer'}
Possible scopes are: compute, register.
You can also get a token from a Keycloak OAuth service using the client credentials workflow:
$ twitcherctl -k -s http://localhost:8080 gentoken -i client_id -s client_secret --scope compute --keycloak
Register an OWS Service for the OWS Proxy¶
See the available options:
twitcherctl -k register -h
Register a local WPS service using an OAuth access token:
$ twitcherctl -k --username demo --password demo register http://localhost:5000/wps
tiny_buzzard
You can use the --name
option to provide a name (used by the OWS proxy).
Otherwise a nice name will be generated.
List registered services¶
The list
command shows the registered OWS services:
$ twitcherctl -k --username demo --password demo list
[{'url': 'http://localhost:5000/wps', 'type': 'wps', 'name': 'tiny_buzzard', 'auth': 'token'}]
OpenAPI interface¶
OAuth2 Tokens¶
twitcher.oauth2¶
This module implements the OAuth2 model to generate access tokens. These tokens are used to access the compute services (scope=compute). The compute services are accessed via the OWS proxy.
The implementation is using the OAuth2 client credentials grant type
Currently three types of access tokens can be used:
- random_token
The access token is a UUID string. The tokens are stored in a local database and can be used for local validation only.
- signed_token
A JWT token signed with a X.509 certificate. The token can be validated without contacting a validation service.
- custom_token
A JWT token with a secret (UUID string) which can be shared for validation. The token can be validated without contacting a validation service.
- keycloak_token
A JWT token generated by a Keycloak OAuth2 service.
See also the OAuth2 token documenation
The implementation is using the pyramid-oauthlib library. The code is also inspired by the following OAuth libraries:
Further reading:
https://requests-oauthlib.readthedocs.io/en/latest/index.html
https://docs.apigee.com/api-platform/security/oauth/oauth-20-client-credentials-grant-type
- class twitcher.oauth2.RandomTokenValidator[source]¶
-
- validate_bearer_token(token, scopes, request)[source]¶
Validate access token.
- Parameters
token – A string of random characters
scopes – A list of scopes
request – The Request object passed by oauthlib
The validation validates:
if the token is available
if the token has expired
if the scopes are available
- class twitcher.oauth2.SignedTokenValidator(cert, key, issuer)[source]¶
- validate_bearer_token(token, scopes, request)[source]¶
Ensure the Bearer token is valid and authorized access to scopes.
- Parameters
token – A string of random characters.
scopes – A list of scopes associated with the protected resource.
request – The HTTP Request (oauthlib.common.Request)
A key to OAuth 2 security and restricting impact of leaked tokens is the short expiration time of tokens, always ensure the token has not expired!.
Two different approaches to scope validation:
- all(scopes). The token must be authorized access to all scopes
associated with the resource. For example, the token has access to
read-only
andimages
, thus the client can view images but not upload new. Allows for fine grained access control through combining various scopes.
- any(scopes). The token must be authorized access to one of the
scopes associated with the resource. For example, token has access to
read-only-images
. Allows for fine grained, although arguably less convenient, access control.
A powerful way to use scopes would mimic UNIX ACLs and see a scope as a group with certain privileges. For a restful API these might map to HTTP verbs instead of read, write and execute.
Note, the request.user attribute can be set to the resource owner associated with this token. Similarly the request.client and request.scopes attribute can be set to associated client object and authorized scopes. If you then use a decorator such as the one provided for django these attributes will be made available in all protected views as keyword arguments.
- Parameters
token – Unicode Bearer token
scopes – List of scopes (defined by you)
request – The HTTP Request (oauthlib.common.Request)
- Return type
True or False
- Method is indirectly used by all core Bearer token issuing grant types:
Authorization Code Grant
Implicit Grant
Resource Owner Password Credentials Grant
Client Credentials Grant
- class twitcher.oauth2.CustomTokenValidator(secret, issuer)[source]¶
- validate_bearer_token(token, scopes, request)[source]¶
Ensure the Bearer token is valid and authorized access to scopes.
- Parameters
token – A string of random characters.
scopes – A list of scopes associated with the protected resource.
request – The HTTP Request (oauthlib.common.Request)
A key to OAuth 2 security and restricting impact of leaked tokens is the short expiration time of tokens, always ensure the token has not expired!.
Two different approaches to scope validation:
- all(scopes). The token must be authorized access to all scopes
associated with the resource. For example, the token has access to
read-only
andimages
, thus the client can view images but not upload new. Allows for fine grained access control through combining various scopes.
- any(scopes). The token must be authorized access to one of the
scopes associated with the resource. For example, token has access to
read-only-images
. Allows for fine grained, although arguably less convenient, access control.
A powerful way to use scopes would mimic UNIX ACLs and see a scope as a group with certain privileges. For a restful API these might map to HTTP verbs instead of read, write and execute.
Note, the request.user attribute can be set to the resource owner associated with this token. Similarly the request.client and request.scopes attribute can be set to associated client object and authorized scopes. If you then use a decorator such as the one provided for django these attributes will be made available in all protected views as keyword arguments.
- Parameters
token – Unicode Bearer token
scopes – List of scopes (defined by you)
request – The HTTP Request (oauthlib.common.Request)
- Return type
True or False
- Method is indirectly used by all core Bearer token issuing grant types:
Authorization Code Grant
Implicit Grant
Resource Owner Password Credentials Grant
Client Credentials Grant
OWS Security¶
OWS Registry¶
OWS Proxy¶
The owsproxy is a service which acts as a proxy for registered OWS services.
The implementation of owsproxy is based on papyrus_ogcproxy
See also: https://github.com/nive/outpost/blob/master/outpost/proxy.py
Changes¶
Unreleased¶
0.7.0 (2022-05-11)¶
Changes:
Add request and response hooks operations to adapter allowing derived implementations to modify OWS proxied requests and returned responses from the service. The default adapter applies no modifications to the original definitions.
0.6.2 (2021-12-01)¶
Changes:
Enforce regeneration of the
OWSRegistry
object on each request to avoid incorrect handling by adapters that require the new transaction or refreshed database session state each time.
0.6.1 (2021-10-27)¶
Changes:
Integrate functionality changes of
0.5.x
branch back into0.6.x
.Align
twitcher.adapter
features of0.6.x
branch to support0.5.x
behaviour.Revert removal of
ServiceStoreInterface
to provide relevant implementation details to external adapters.Apply missing interface classes as bases to default implementations.
Add
owsproxy_uri
in frontpage response.Use
hybrid_property
to provide directtwitcher.models.Service.verify
setter instead of protected_verify
.Add more logging and handling of errors to catch cases where adapter doesn’t return a valid
Service
instance.Add
scoped_session
tosession_factory
object to ensure distinct connections and transactions are created for concurrent requests.
0.6.0 (2020-04-01)¶
Changes:
0.5.6 (2021-09-10)¶
Changes:
Add Github Actions workflow to run local tests and Docker smoke tests for pre-validation of features and changes.
Add Github issue, feature request and pull request templates.
Fixes:
Pin packages
pyramid<2
,zope.sqlalchemy>=1.5
andsqlalchemy>=1.4,<2
to avoid errors with conflicting and upcoming release and features employed in code.Fix failing
cryptography
package build step in Docker image due to missingg++
andrust
dependencies (rust
installed viacargo
).
0.5.5 (2021-01-27)¶
Fixes:
Update invalid reference to
python3-dev
in docker image. Travis-CI is also updated to run a smoke test build of this docker image prior to merge to help early detection of problems prior to deploy triggers from tags.
0.5.4 (2020-10-29)¶
Changes:
Replace
waitress
bygunicorn
to resolve issue related to slow download of large files (#97).
0.5.3 (2020-02-20)¶
Changes:
Reduce log level of
"failed security check"
fromexception
towarning
as it corresponds to the expected code behavior (unauthorised access) whenOWSException
is raised, instead of dumping an unhandled error traceback.
0.5.2 (2019-07-11)¶
New Features:
Adds route
/info
which returns contents oftwitcher.__version__
.Adds route /versions which returns version details such as Twitcher app version and employed adapter version.
Changes:
Updated
README.rst
to match recent development, reference and docker image link.Adds URI of
/info
and/versions
routes in the frontpage response.Corresponding HTTP status codes are returned for raised
OWSException
.
Fixes:
0.5.1 (2019-05-24)¶
New Features:
Add postgres extra requirements for when it is used as database driver with
sqlalchemy
.
Changes:
Use
container
instead ofconfig
forAdapterInterface.owsproxy_config
to match real use cases.
Fixes:
Improve the adapter import methodology to work with more use cases (Ouranosinc/Magpie#182).
Fix incorrect setup for bump version within
Makefile
.Fix Twitcher
main
includingtwitcher.<module>
instead of.<module>
.
0.5.0 (2019-05-22)¶
Changes:
Skipped Buildout (#49).
Replaced mongodb by sqlalchemy (#51).
Simplified
Makefile
and skipped conda targets (#75).Add
Makefile
targets fordocker
,bumpversion
andcoverage
analysis related tasks (#67).Removed unused
config
module (#70).
New Features:
Provided a
Dockerfile
for building Twitcher (#67).Provide
AdapterInterface
to allow overriding store implementations with configuration settingtwitcher.adapter
(#67).Add version auto-update (number and date) of these ‘changes’ with
bump2version
(#67).
Fixes:
0.4.0 (2019-05-02)¶
Changes:
0.3.8 (2018-09-11)¶
Fixes:
New Features:
make protected path configurable (#36).
0.3.7 (2018-03-13)¶
Fixes:
Fixed exclude filter in
MANIFEST.in
.
New Features:
Feature #28: use request upstream when not using WPS (e.g download file through
thredds
).
0.3.6 (2018-03-08)¶
Fix PEP8
Removed unused
c4i
option.Added
auth
option to set authentication method.Updated docs for usage of x509 certificates.
New Features:
Feature #25: using x509 certificates for service authentication.
0.3.5 (2018-03-01)¶
Fix PEP8.
Updated makefile.
Updated buildout recipes.
Fixed nginx dependency.
Updated mongodb 3.4.
Configured csrf in
xmlrpc
.Fixed tutorial example.
Added readthedocs, licence and chat badges.
0.3.4 (2017-05-05)¶
Updated logging.
Fixed: creates workdir if it does not exist.
0.3.3 (2017-04-27)¶
Fixed fetching of access token when service is public.
0.3.2 (2017-01-31)¶
Set header
X-X509-User-Proxy
.
0.3.1 (2017-01-26)¶
Fix PEP8.
Set permission of
certfile
.Added option
ows-proxy-delegate
.
0.3.0 (2017-01-11)¶
Fix PEP8.
Changed rpc interface.
Added twitcher.client module.
Using esgf scls service to get credentials.
Updated internal pywps to version 4.0.0.
Using default port 5000.
Added ipython notebook examples.
Moved
namesgenerator
to top-level.Added
_compat
module for Python 3.x/2.x compatibility.Added
twitcher.api
and cleaned up rpcinterface.Added
twitcher.store
with mongodb and memory implementation.Added
twitcher.datatype
withAccessToken
andService
.Using https port only.
Using
OWSExceptions
on errors in owsproxy.
0.2.4 (2016-12-23)¶
Fix PEP8.
Using
replace_caps_url
inowsproxy
.Pinned
mongodb=2.6*|3.3.9
.Replaced
service_url
byproxy_url
.Added
wms_130
and renamedwms_111
.
0.2.3 (2016-11-18)¶
Fix PEP8.
Using
doc2dict
, renamedget_service_by_name()
.Added support for c4i tokens.
Updated deps:
pytest
,mongodb
.Updated buildout recipes.
Fixed functional tests.
0.2.2 (2016-08-18)¶
Fix PEP8.
Don’t allow duplicate service names.
0.2.1 (2016-08-05)¶
Register service with public access.
WMS services can be registered.
0.2.0 (2016-07-18)¶
Updated to new buildout with separated conda environment.
Replaced nose by pytest.
Updated installation docs.
0.1.7 (2016-06-09)¶
Fixes:
Update of service failed (#17).
0.1.6 (2016-06-01)¶
Updated docs.
Renamed Python package to
pyramid_twitcher
.Conda
environment.yml
added.Using
get_sane_name()
.Replaced
httplib2
byrequests
.
Fixes:
0.1.5 (2016-04-22)¶
Fixed docs links
0.1.4 (2016-04-19)¶
Fixed
MANIFEST.in
Fixed service database index.
Updated
Makefile
.Added more links to appendix.
0.1.0 (2015-12-07)¶
Initial Release.