Skip to content

Commit e49546b

Browse files
Merge pull request #29 from geo-engine/disable_anonymous
enable login
2 parents c4ea05f + 9128a05 commit e49546b

File tree

12 files changed

+114
-17
lines changed

12 files changed

+114
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ env
1616

1717
# Private files
1818
.pypirc
19+
.env

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Geo Engine Python Package
22

3-
43
[![CI](https://github.com/geo-engine/geoengine-python/actions/workflows/ci.yml/badge.svg)](https://github.com/geo-engine/geoengine-python/actions/workflows/ci.yml)
54

65
This package allows easy access to Geo Engine functionality from Python environments.
@@ -101,3 +100,16 @@ print(workflow.get_result_descriptor())
101100

102101
workflow.get_dataframe(ge.Bbox([-60.0, 5.0, 61.0, 6.0], [time, time]))
103102
```
103+
104+
## Authentication
105+
106+
If the Geo Engine server requires authentication, you can set your credentials in the following ways:
107+
108+
1. in the initialize method: `ge.initialize("http://peter.geoengine.io:6060", ("email", "password"))`
109+
2. as environment variables `export GEOENGINE_EMAIL="email"` and `export GEOENGINE_PASSWORD="password"`
110+
3. in a .env file in the current working directory with the content:
111+
112+
```bash
113+
GEOENGINE_EMAIL="email"
114+
GEOENGINE_PASSWORD="password"
115+
```

geoengine/auth.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
Module for encapsulating Geo Engine authentication
33
'''
44

5-
from typing import ClassVar, Dict, Optional
5+
from typing import ClassVar, Dict, Optional, Tuple
66
from uuid import UUID
77

8+
import os
9+
from dotenv import load_dotenv
810
import requests as req
911
from requests.auth import AuthBase
1012

@@ -35,14 +37,26 @@ class Session:
3537

3638
session: ClassVar[req.Session] = None
3739

38-
def __init__(self, server_url: str) -> None:
40+
def __init__(self, server_url: str, credentials: Tuple[str, str] = None) -> None:
3941
'''
4042
Initialize communication between this library and a Geo Engine instance
43+
44+
if credentials are provided, the session will be authenticated
45+
46+
optional arguments: (email, password) as tuple
47+
optional environment variables: GEOENGINE_EMAIL, GEOENGINE_PASSWORD
4148
'''
4249

43-
# TODO: username and password for Pro version
50+
session = None
4451

45-
session = req.post(f'{server_url}/anonymous').json()
52+
if credentials is not None:
53+
session = req.post(f'{server_url}/login', json={"email": credentials[0], "password": credentials[1]}).json()
54+
elif "GEOENGINE_EMAIL" in os.environ and "GEOENGINE_PASSWORD" in os.environ:
55+
session = req.post(f'{server_url}/login',
56+
json={"email": os.environ.get("GEOENGINE_EMAIL"),
57+
"password": os.environ.get("GEOENGINE_PASSWORD")}).json()
58+
else:
59+
session = req.post(f'{server_url}/anonymous').json()
4660

4761
if 'error' in session:
4862
raise GeoEngineException(session)
@@ -87,6 +101,13 @@ def requests_bearer_auth(self) -> BearerAuth:
87101

88102
return BearerAuth(self.__id)
89103

104+
def logout(self):
105+
'''
106+
Logout the current session
107+
'''
108+
109+
req.post(f'{self.server_url}/logout', headers=self.auth_header)
110+
90111

91112
def get_session() -> Session:
92113
'''
@@ -101,19 +122,28 @@ def get_session() -> Session:
101122
return Session.session
102123

103124

104-
def initialize(server_url: str) -> None:
125+
def initialize(server_url: str, credentials: Tuple[str, str] = None) -> None:
105126
'''
106127
Initialize communication between this library and a Geo Engine instance
128+
129+
if credentials are provided, the session will be authenticated
130+
131+
optional arugments: (email, password) as tuple
132+
optional environment variables: GEOENGINE_EMAIL, GEOENGINE_PASSWORD
133+
optional .env file defining: GEOENGINE_EMAIL, GEOENGINE_PASSWORD
107134
'''
108135

109-
Session.session = Session(server_url)
136+
load_dotenv()
137+
138+
Session.session = Session(server_url, credentials)
110139

111140

112-
def reset() -> None:
141+
def reset(logout: bool = True) -> None:
113142
'''
114143
Resets the current session
115144
'''
116145

117-
# TODO: active logout for Pro version
146+
if Session.session is not None and logout:
147+
Session.session.logout()
118148

119149
Session.session = None

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ install_requires =
2222
numpy
2323
owslib
2424
pillow
25+
python-dotenv
2526
rasterio
2627
requests
2728
vega

tests/test_auth.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from datetime import datetime
44

55
import unittest
6+
import json
7+
import os
68
import requests_mock
79

810
import geoengine as ge
@@ -13,7 +15,9 @@ class AuthTests(unittest.TestCase):
1315
'''Tests runner regarding Geo Engine authentication'''
1416

1517
def setUp(self) -> None:
16-
ge.reset()
18+
assert "GEOENGINE_EMAIL" not in os.environ and "GEOENGINE_PASSWORD" not in os.environ, \
19+
"Please unset GEOENGINE_EMAIL and GEOENGINE_PASSWORD"
20+
ge.reset(False)
1721

1822
def test_uninitialized(self):
1923
with self.assertRaises(ge.UninitializedException) as exception:
@@ -45,6 +49,55 @@ def test_initialize(self):
4549
self.assertEqual(type(ge.get_session()),
4650
ge.Session)
4751

52+
def test_initialize_tuple(self):
53+
with requests_mock.Mocker() as m:
54+
m.post('http://mock-instance/login',
55+
additional_matcher=lambda request:
56+
request.text == json.dumps({"email": "[email protected]", "password": "secret123"}),
57+
json={
58+
"id": "e327d9c3-a4f3-4bd7-a5e1-30b26cae8064",
59+
"user": {
60+
"id": "328ca8d1-15d7-4f59-a989-5d5d72c98744",
61+
},
62+
"created": "2021-06-08T15:22:22.605891994Z",
63+
"validUntil": "2021-06-08T16:22:22.605892183Z",
64+
"project": None,
65+
"view": None
66+
})
67+
68+
ge.initialize("http://mock-instance", ("[email protected]", "secret123"))
69+
70+
self.assertEqual(type(ge.get_session()),
71+
ge.Session)
72+
73+
def test_initialize_env(self):
74+
with requests_mock.Mocker() as m:
75+
m.post('http://mock-instance/login',
76+
additional_matcher=lambda request:
77+
request.text == json.dumps({"email": "[email protected]", "password": "secret123"}),
78+
json={
79+
"id": "e327d9c3-a4f3-4bd7-a5e1-30b26cae8064",
80+
"user": {
81+
"id": "328ca8d1-15d7-4f59-a989-5d5d72c98744",
82+
},
83+
"created": "2021-06-08T15:22:22.605891994Z",
84+
"validUntil": "2021-06-08T16:22:22.605892183Z",
85+
"project": None,
86+
"view": None
87+
})
88+
89+
os.environ["GEOENGINE_EMAIL"] = "[email protected]"
90+
os.environ["GEOENGINE_PASSWORD"] = "secret123"
91+
92+
try:
93+
ge.initialize("http://mock-instance")
94+
finally:
95+
del os.environ["GEOENGINE_EMAIL"]
96+
del os.environ["GEOENGINE_PASSWORD"]
97+
98+
self.assertEqual(type(ge.get_session()),
99+
ge.Session)
100+
48101

49102
if __name__ == '__main__':
50103
unittest.main()

tests/test_plot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class WmsTests(unittest.TestCase):
1414
'''Test runner for the plotting functionality'''
1515

1616
def setUp(self) -> None:
17-
ge.reset()
17+
ge.reset(False)
1818

1919
def test_ndvi_histogram(self):
2020
with requests_mock.Mocker() as m:

tests/test_provenance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class ProvenanceTests(unittest.TestCase):
1111
'''Test runner for provenance tests'''
1212

1313
def setUp(self) -> None:
14-
ge.reset()
14+
ge.reset(False)
1515

1616
def test_provenance_call(self):
1717
with requests_mock.Mocker() as m:

tests/test_upload.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class UploadTests(unittest.TestCase):
1414
'''Test runner regarding upload functionality'''
1515

1616
def setUp(self) -> None:
17-
ge.reset()
17+
ge.reset(False)
1818

1919
def test_upload(self):
2020
with requests_mock.Mocker() as m:

tests/test_wcs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class WcsTests(unittest.TestCase):
1616
'''WCS test runner'''
1717

1818
def setUp(self) -> None:
19-
ge.reset()
19+
ge.reset(False)
2020

2121
def test_ndvi(self):
2222
with requests_mock.Mocker() as m, open("tests/responses/ndvi.tiff", "rb") as ndvi_tiff:

tests/test_wfs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class WfsTests(unittest.TestCase):
1818
'''WFS test runner'''
1919

2020
def setUp(self) -> None:
21-
ge.reset()
21+
ge.reset(False)
2222

2323
def test_geopandas(self):
2424
with requests_mock.Mocker() as m:

0 commit comments

Comments
 (0)