add first user storage implementation
This commit is contained in:
		| @@ -2,6 +2,7 @@ from .template import WebpageController | ||||
| from urllib.parse import parse_qs | ||||
| from uuid import uuid4 | ||||
| from http.cookies import SimpleCookie | ||||
| from owrx.users import UserList | ||||
|  | ||||
|  | ||||
| class SessionStorage(object): | ||||
| @@ -40,18 +41,18 @@ class SessionController(WebpageController): | ||||
|     def processLoginAction(self): | ||||
|         data = parse_qs(self.get_body().decode("utf-8")) | ||||
|         data = {k: v[0] for k, v in data.items()} | ||||
|         userlist = UserList.getSharedInstance() | ||||
|         if "user" in data and "password" in data: | ||||
|             # TODO actually check user and password | ||||
|             if data["user"] == "admin" and data["password"] == "password": | ||||
|                 # TODO pass the final destination | ||||
|                 key = SessionStorage.getSharedInstance().startSession({"user": data["user"]}) | ||||
|                 cookie = SimpleCookie() | ||||
|                 cookie["owrx-session"] = key | ||||
|                 self.send_redirect("/admin", cookies=cookie) | ||||
|             else: | ||||
|                 self.send_redirect("/login") | ||||
|         else: | ||||
|             self.send_response("invalid request", code=400) | ||||
|             if data["user"] in userlist: | ||||
|                 user = userlist[data["user"]] | ||||
|                 if user.password.is_valid(data["password"]): | ||||
|                     # TODO pass the final destination | ||||
|                     key = SessionStorage.getSharedInstance().startSession({"user": user.name}) | ||||
|                     cookie = SimpleCookie() | ||||
|                     cookie["owrx-session"] = key | ||||
|                     self.send_redirect("/admin", cookies=cookie) | ||||
|                     return | ||||
|         self.send_redirect("/login") | ||||
|  | ||||
|     def logoutAction(self): | ||||
|         self.send_redirect("logout happening here") | ||||
|   | ||||
							
								
								
									
										80
									
								
								owrx/users.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								owrx/users.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| import json | ||||
|  | ||||
| import logging | ||||
|  | ||||
| logger = logging.getLogger(__name__) | ||||
|  | ||||
|  | ||||
| class PasswordException(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class Password(ABC): | ||||
|     @staticmethod | ||||
|     def from_dict(d: dict): | ||||
|         if "encoding" not in d: | ||||
|             raise PasswordException("password encoding not set") | ||||
|         if d["encoding"] == "string": | ||||
|             return CleartextPassword(d) | ||||
|         raise PasswordException("invalid passord encoding: {0}".format(d["type"])) | ||||
|  | ||||
|     def __init__(self, pwinfo: dict): | ||||
|         self.pwinfo = pwinfo | ||||
|  | ||||
|     @abstractmethod | ||||
|     def is_valid(self, inp: str): | ||||
|         pass | ||||
|  | ||||
|  | ||||
| class CleartextPassword(Password): | ||||
|     def is_valid(self, inp: str): | ||||
|         return self.pwinfo['value'] == inp | ||||
|  | ||||
|  | ||||
| class User(object): | ||||
|     def __init__(self, name: str, enabled: bool, password: Password): | ||||
|         self.name = name | ||||
|         self.enabled = enabled | ||||
|         self.password = password | ||||
|  | ||||
|  | ||||
| class UserList(object): | ||||
|     sharedInstance = None | ||||
|  | ||||
|     @staticmethod | ||||
|     def getSharedInstance(): | ||||
|         if UserList.sharedInstance is None: | ||||
|             UserList.sharedInstance = UserList() | ||||
|         return UserList.sharedInstance | ||||
|  | ||||
|     def __init__(self): | ||||
|         self.users = self._loadUsers() | ||||
|  | ||||
|     def _loadUsers(self): | ||||
|         for file in ["/etc/openwebrx/users.json", "users.json"]: | ||||
|             try: | ||||
|                 f = open(file, "r") | ||||
|                 users_json = json.load(f) | ||||
|                 f.close() | ||||
|  | ||||
|                 return {u.name: u for u in [self.buildUser(d) for d in users_json]} | ||||
|             except FileNotFoundError: | ||||
|                 pass | ||||
|             except json.JSONDecodeError: | ||||
|                 logger.exception("error while parsing users file %s", file) | ||||
|                 return {} | ||||
|             except Exception: | ||||
|                 logger.exception("error while processing users from %s", file) | ||||
|                 return {} | ||||
|         return {} | ||||
|  | ||||
|     def buildUser(self, d): | ||||
|         if "user" in d and "password" in d and "enabled" in d: | ||||
|             return User(d["user"], d["enabled"], Password.from_dict(d["password"])) | ||||
|  | ||||
|     def __getitem__(self, item): | ||||
|         return self.users[item] | ||||
|  | ||||
|     def __contains__(self, item): | ||||
|         return item in self.users | ||||
							
								
								
									
										11
									
								
								users.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								users.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| [ | ||||
|   { | ||||
|     "user": "admin", | ||||
|     "password": { | ||||
|       "encoding": "string", | ||||
|       "value": "password", | ||||
|       "force_change": true | ||||
|     }, | ||||
|     "enabled": true | ||||
|   } | ||||
| ] | ||||
		Reference in New Issue
	
	Block a user
	 Jakob Ketterl
					Jakob Ketterl