Accounts should now support requiring moderator approval. Also dropped pydantic dep.
This commit is contained in:
parent
10586b480a
commit
2fcd9be1b0
|
@ -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
11
main.py
|
@ -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()
|
|
30
models.py
30
models.py
|
@ -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
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user