pluginserver 0.5.6__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pluginserver
3
- Version: 0.5.6
3
+ Version: 0.6.0
4
4
  Summary: Plugin-driven API server
5
5
  Home-page: https://github.com/nicciniamh/pluginserver
6
6
  Author: Nicole Stevens
@@ -0,0 +1,8 @@
1
+ # Plugin Server
2
+
3
+ Plugin Server is a python script and library to manage a REST-like API server utilizing a plugin system to handle requests to API routes. It is built upon Python async and aiohttp.
4
+
5
+ # Installing Plugin Server
6
+ Please see the [Installation Instructions](https://pluginserver.readthedocs.io/en/latest/Install.html) for details.
7
+
8
+ Please see the [Project Documentation](https://pluginserver.readthedocs.io/) for information on usage, configuration and more.
@@ -1,4 +1,5 @@
1
1
  from aiohttp import web
2
+ import base64
2
3
 
3
4
  class BasePlugin:
4
5
  """
@@ -27,9 +28,35 @@ class BasePlugin:
27
28
  self.args = dict(kwargs)
28
29
 
29
30
  def _check_auth(self,data):
30
- #print(f"_check_auth: {self._auth_type} apikey {self._apikey}, args {data}")
31
+ toktype = 'Undefined'
32
+ def get_token(data):
33
+ nonlocal toktype
34
+ headers = data.get('request_headers', {})
35
+ auth_header = headers.get('Authorization')
36
+ if auth_header and auth_header.startswith('Bearer '):
37
+ toktype = 'token'
38
+ return auth_header.split(' ', 1)[1].strip()
39
+ return None
40
+
41
+ def get_custom_header_token(data):
42
+ nonlocal toktype
43
+ headers = data.get('request_headers', {})
44
+ custom_header = headers.get('X-Custom-Auth')
45
+ toktype = 'custom'
46
+ if custom_header:
47
+ return custom_header.strip()
48
+ return None
49
+
50
+ def get_user_token(data):
51
+ nonlocal toktype
52
+ token = data.get('apikey')
53
+ if token:
54
+ toktype='userdata'
55
+ return token
56
+ user_key = get_token(data) or get_custom_header_token(data) or get_user_token(data)
57
+ print(f"_check_auth: type: {toktype} {self._auth_type} apikey {self._apikey}, args {data}")
58
+
31
59
  if self._auth_type:
32
- user_key = data.get('apikey')
33
60
  #print(f"Checking {user_key}")
34
61
  if not user_key:
35
62
  #print("Returning false")
@@ -90,12 +90,43 @@ def main():
90
90
 
91
91
  # --- Auth Helper ---
92
92
  def check_auth(data, config):
93
+ toktype = 'Undefined'
94
+ def get_token(data):
95
+ nonlocal toktype
96
+ headers = data.get('request_headers', {})
97
+ auth_header = headers.get('Authorization')
98
+ if auth_header and auth_header.startswith('Bearer '):
99
+ toktype = 'token'
100
+ return auth_header.split(' ', 1)[1].strip()
101
+ return None
102
+
103
+ def get_custom_header_token(data):
104
+ nonlocal toktype
105
+ headers = data.get('request_headers', {})
106
+ custom_header = headers.get('X-Custom-Auth')
107
+ toktype = 'custom'
108
+ if custom_header:
109
+ return custom_header.strip()
110
+ return None
111
+
112
+ def get_user_token(data):
113
+ nonlocal toktype
114
+ token = data.get('apikey')
115
+ if token:
116
+ toktype='userdata'
117
+ return token
93
118
  try:
94
119
  expected = config.auth.apikey
95
120
  except AttributeError:
96
- expected = None
97
- provided = data.get('apikey')
98
- return expected and provided and expected == provided
121
+ return True
122
+ provided = get_token(data) or get_custom_header_token(data) or get_user_token(data)
123
+ #print(f"pserv:check_auth: provided/expected: {provided}/{expected}")
124
+ if not provided:
125
+ print("Returning false")
126
+ return False
127
+ auth_ok = expected == provided
128
+ #print("Returning {auth_ok}")
129
+ return auth_ok
99
130
 
100
131
  # --- Plugin Request Handler ---
101
132
  def register_plugin_route(plugin_id, instance, config):
@@ -125,16 +156,31 @@ def register_plugin_route(plugin_id, instance, config):
125
156
 
126
157
  # --- Control Routes ---
127
158
  def register_control_routes(config):
128
- @routes.get('/plugins')
159
+ print("Registering Control Routes")
160
+ @routes.route('*','/plugins')
129
161
  async def plugin_list(request):
130
- data = dict(request.query)
162
+ data = {}
163
+ if request.method == 'POST' and request.can_read_body:
164
+ try:
165
+ data.update(await request.json())
166
+ except Exception:
167
+ pass
168
+ data.update(request.query)
169
+ data['request_headers'] = dict(request.headers)
131
170
  if not check_auth(data, config):
132
171
  return web.json_response({'error': 'unauthorized'}, status=403)
133
172
  return corsobj.apply_headers(web.json_response({'loaded_plugins': list(manager.plugins.keys())}),request)
134
173
 
135
- @routes.get('/reload/{plugin_id}')
174
+ @routes.route('*','/reload/{plugin_id}')
136
175
  async def reload_plugin(request):
137
- data = dict(request.query)
176
+ data = {}
177
+ if request.method == 'POST' and request.can_read_body:
178
+ try:
179
+ data.update(await request.json())
180
+ except Exception:
181
+ pass
182
+ data.update(request.query)
183
+ data['request_headers'] = dict(request.headers)
138
184
  if not check_auth(data, config):
139
185
  return corsobj.apply_headers(web.json_response({'error': 'unauthorized'}, status=403),request)
140
186
 
@@ -144,9 +190,16 @@ def register_control_routes(config):
144
190
  return corsobj.apply_headers(web.json_response({'reloaded': pid, 'success': success}),request)
145
191
  return corsobj.apply_headers(web.json_response({'error': f'Plugin "{pid}" not found'}, status=404),request)
146
192
 
147
- @routes.get('/reload/all')
193
+ @routes.route('*', '/reload/all')
148
194
  async def reload_all(request):
149
- data = dict(request.query)
195
+ data = {}
196
+ if request.method == 'POST' and request.can_read_body:
197
+ try:
198
+ data.update(await request.json())
199
+ except Exception:
200
+ pass
201
+ data.update(request.query)
202
+ data['request_headers'] = dict(request.headers)
150
203
  if not check_auth(data, config):
151
204
  return corsobj.apply_headers(web.json_response({'error': 'unauthorized'}, status=403),request)
152
205
  manager.load_plugins()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pluginserver
3
- Version: 0.5.6
3
+ Version: 0.6.0
4
4
  Summary: Plugin-driven API server
5
5
  Home-page: https://github.com/nicciniamh/pluginserver
6
6
  Author: Nicole Stevens
@@ -4,7 +4,7 @@ from setuptools import setup
4
4
 
5
5
  setup(
6
6
  name='pluginserver',
7
- version='0.5.6',
7
+ version='0.6.0',
8
8
  packages=['plugincore'],
9
9
  include_package_data=True,
10
10
  description='Plugin-driven API server',
@@ -1,11 +0,0 @@
1
- # Plugin Server
2
-
3
- This server implements an API server using rest-like API routes. The server is implemented
4
- in Python using aiohttp.
5
-
6
- This relatively simplistic RESTapi servers use routes to determine the request handler when a request
7
- is made. A route is simply the ‘tail’ of the web address being requested.
8
- Think of a web address like `https://server.domain.tld/tail`. The tail portion is the route.
9
-
10
- Please see the documentation at [https://pluginserver.readthedocs.io](https://pluginserver.readthedocs.io/en/latest/).
11
-
File without changes
File without changes
File without changes