Accounts should now support requiring moderator approval. Also dropped pydantic dep.

This commit is contained in:
Zergling_man 2024-05-12 17:36:50 +10:00
parent 10586b480a
commit 2fcd9be1b0
3 changed files with 22 additions and 21 deletions

View File

@ -2,4 +2,4 @@ import os
import json import json
file=os.environ.get('AUTH_CONFIG_FILE') file=os.environ.get('AUTH_CONFIG_FILE')
if not file: raise Exception('AUTH_CONFIG_FILE not set. (It should point to a json file.) Exiting.') if not file: raise Exception('AUTH_CONFIG_FILE not set. (It should point to a json file.) Exiting.')
config=json.load(open(file)) config=json.load(open(file))

11
main.py
View File

@ -1,11 +0,0 @@
from importlib import import_module
from . import utils, models
from .config import config
globals()['backend']=import_module('.backends.'+config['backend']['type'],'auth')
backend.config=config['backend']['options']
backend.utils=utils
backend.models=models
models.utils=utils
models.backend=backend
backend.init()

View File

@ -1,6 +1,6 @@
from dataclasses import dataclass from dataclasses import dataclass
from pydantic.v1 import validate_arguments
from datetime import datetime from datetime import datetime
from enum import Enum
import uuid import uuid
class AbstractUser(): class AbstractUser():
@ -29,9 +29,11 @@ class Token():
class InviteToken(Token): class InviteToken(Token):
_uses: int=0 _uses: int=0
_max_uses: int=-1 _max_uses: int=-1
expires: datetime=None expires: datetime|None=None
@validate_arguments
def __init__(self,value,owner,uses:int,maxuses:int,expiry:datetime|None): def __init__(self,value,owner,uses:int,maxuses:int,expiry:datetime|None):
uses=int(uses); maxuses=int(maxuses);
if expiry!='None': expiry=datetime(expiry)
else: expiry=None
self.uses,self.max_uses,self.expires=uses,maxuses,expiry self.uses,self.max_uses,self.expires=uses,maxuses,expiry
return super().__init__(value,owner) return super().__init__(value,owner)
@property @property
@ -62,6 +64,7 @@ class User(AbstractUser):
salt: str salt: str
_invited_by: AbstractUser|str # Root node will just reference itself _invited_by: AbstractUser|str # Root node will just reference itself
email: str='' email: str=''
state: str='pending'
def _load_invite(self): def _load_invite(self):
if self._invited_by==self.username: return self # Sanity-check to prevent infinite recursion. if self._invited_by==self.username: return self # Sanity-check to prevent infinite recursion.
return backend.load_user(self._invited_by) return backend.load_user(self._invited_by)
@ -72,8 +75,11 @@ class User(AbstractUser):
return self._invited_by return self._invited_by
@property @property
def serialise(self): def serialise(self):
return ','.join([self.username,self.password_hash,str(self.salt),self.invited_by.username,self.email or '']) upstream=self.invited_by
upstream=upstream.username if upstream else 'None'
return ','.join([self.username,self.password_hash,str(self.salt),upstream,self.email or '',self.state])
def create_inv_token(self,*args,**kwargs): def create_inv_token(self,*args,**kwargs):
""" All arguments are passed directly to InviteToken's constructor, with self added at the beginning """
tok=InviteToken(self,*args,**kwargs) tok=InviteToken(self,*args,**kwargs)
backend.save_invite(tok) backend.save_invite(tok)
return tok return tok
@ -97,12 +103,18 @@ class User(AbstractUser):
return a return a
raise Exception("Incorrect password") raise Exception("Incorrect password")
@classmethod @classmethod
def register(cls,username:str,password:str,invite:InviteToken,email:str=''): def register(cls,username:str,password:str,invite:InviteToken=None,email:str=''):
if set([chr(n) for n in range(32)]+[','])&set(username): raise Exception('Invalid username') if set([chr(n) for n in range(32)]+[','])&set(username): raise Exception('Invalid username')
u=backend.load_user(username) u=backend.load_user(username)
if u is not None: raise Exception("User already exists") if u is not None: raise Exception("User already exists")
u=User(username,*utils.phash(password),invite.owner,email) if invite:
owner=invite.owner
else:
owner=None
u=User(username,*utils.phash(password),owner,email)
if invite:
user.state='approved' # Invited users don't need approval
invite.uses+=1
backend.save_invite(invite)
u.save() u.save()
invite.uses+=1 return u
backend.save_invite(invite)
return u