mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
aurweb.auth: add user credentials and matcher functions
This clones the behavior already present in the PHP implementation, but it uses a global dict with credential constant keys to validation functions to determine if a given user has a credential. Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
670f711b59
commit
07d5907ecd
4 changed files with 154 additions and 1 deletions
101
aurweb/auth.py
101
aurweb/auth.py
|
@ -17,6 +17,10 @@ class AnonymousUser:
|
||||||
def is_authenticated():
|
def is_authenticated():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def has_credential(credential):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class BasicAuthBackend(AuthenticationBackend):
|
class BasicAuthBackend(AuthenticationBackend):
|
||||||
async def authenticate(self, conn: HTTPConnection):
|
async def authenticate(self, conn: HTTPConnection):
|
||||||
|
@ -75,3 +79,100 @@ def auth_required(is_required: bool = True,
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
CRED_ACCOUNT_CHANGE_TYPE = 1
|
||||||
|
CRED_ACCOUNT_EDIT = 2
|
||||||
|
CRED_ACCOUNT_EDIT_DEV = 3
|
||||||
|
CRED_ACCOUNT_LAST_LOGIN = 4
|
||||||
|
CRED_ACCOUNT_SEARCH = 5
|
||||||
|
CRED_ACCOUNT_LIST_COMMENTS = 28
|
||||||
|
CRED_COMMENT_DELETE = 6
|
||||||
|
CRED_COMMENT_UNDELETE = 27
|
||||||
|
CRED_COMMENT_VIEW_DELETED = 22
|
||||||
|
CRED_COMMENT_EDIT = 25
|
||||||
|
CRED_COMMENT_PIN = 26
|
||||||
|
CRED_PKGBASE_ADOPT = 7
|
||||||
|
CRED_PKGBASE_SET_KEYWORDS = 8
|
||||||
|
CRED_PKGBASE_DELETE = 9
|
||||||
|
CRED_PKGBASE_DISOWN = 10
|
||||||
|
CRED_PKGBASE_EDIT_COMAINTAINERS = 24
|
||||||
|
CRED_PKGBASE_FLAG = 11
|
||||||
|
CRED_PKGBASE_LIST_VOTERS = 12
|
||||||
|
CRED_PKGBASE_NOTIFY = 13
|
||||||
|
CRED_PKGBASE_UNFLAG = 15
|
||||||
|
CRED_PKGBASE_VOTE = 16
|
||||||
|
CRED_PKGREQ_FILE = 23
|
||||||
|
CRED_PKGREQ_CLOSE = 17
|
||||||
|
CRED_PKGREQ_LIST = 18
|
||||||
|
CRED_TU_ADD_VOTE = 19
|
||||||
|
CRED_TU_LIST_VOTES = 20
|
||||||
|
CRED_TU_VOTE = 21
|
||||||
|
|
||||||
|
|
||||||
|
def has_any(user, *account_types):
|
||||||
|
return str(user.AccountType) in set(account_types)
|
||||||
|
|
||||||
|
|
||||||
|
def user_developer_or_trusted_user(user):
|
||||||
|
return has_any(user, "User", "Trusted User", "Developer",
|
||||||
|
"Trusted User & Developer")
|
||||||
|
|
||||||
|
|
||||||
|
def trusted_user(user):
|
||||||
|
return has_any(user, "Trusted User", "Trusted User & Developer")
|
||||||
|
|
||||||
|
|
||||||
|
def developer(user):
|
||||||
|
return has_any(user, "Developer", "Trusted User & Developer")
|
||||||
|
|
||||||
|
|
||||||
|
def trusted_user_or_dev(user):
|
||||||
|
return has_any(user, "Trusted User", "Developer",
|
||||||
|
"Trusted User & Developer")
|
||||||
|
|
||||||
|
|
||||||
|
# A mapping of functions that users must pass to have credentials.
|
||||||
|
cred_filters = {
|
||||||
|
CRED_PKGBASE_FLAG: user_developer_or_trusted_user,
|
||||||
|
CRED_PKGBASE_NOTIFY: user_developer_or_trusted_user,
|
||||||
|
CRED_PKGBASE_VOTE: user_developer_or_trusted_user,
|
||||||
|
CRED_PKGREQ_FILE: user_developer_or_trusted_user,
|
||||||
|
CRED_ACCOUNT_CHANGE_TYPE: trusted_user_or_dev,
|
||||||
|
CRED_ACCOUNT_EDIT: trusted_user_or_dev,
|
||||||
|
CRED_ACCOUNT_LAST_LOGIN: trusted_user_or_dev,
|
||||||
|
CRED_ACCOUNT_LIST_COMMENTS: trusted_user_or_dev,
|
||||||
|
CRED_ACCOUNT_SEARCH: trusted_user_or_dev,
|
||||||
|
CRED_COMMENT_DELETE: trusted_user_or_dev,
|
||||||
|
CRED_COMMENT_UNDELETE: trusted_user_or_dev,
|
||||||
|
CRED_COMMENT_VIEW_DELETED: trusted_user_or_dev,
|
||||||
|
CRED_COMMENT_EDIT: trusted_user_or_dev,
|
||||||
|
CRED_COMMENT_PIN: trusted_user_or_dev,
|
||||||
|
CRED_PKGBASE_ADOPT: trusted_user_or_dev,
|
||||||
|
CRED_PKGBASE_SET_KEYWORDS: trusted_user_or_dev,
|
||||||
|
CRED_PKGBASE_DELETE: trusted_user_or_dev,
|
||||||
|
CRED_PKGBASE_EDIT_COMAINTAINERS: trusted_user_or_dev,
|
||||||
|
CRED_PKGBASE_DISOWN: trusted_user_or_dev,
|
||||||
|
CRED_PKGBASE_LIST_VOTERS: trusted_user_or_dev,
|
||||||
|
CRED_PKGBASE_UNFLAG: trusted_user_or_dev,
|
||||||
|
CRED_PKGREQ_CLOSE: trusted_user_or_dev,
|
||||||
|
CRED_PKGREQ_LIST: trusted_user_or_dev,
|
||||||
|
CRED_TU_ADD_VOTE: trusted_user,
|
||||||
|
CRED_TU_LIST_VOTES: trusted_user,
|
||||||
|
CRED_TU_VOTE: trusted_user,
|
||||||
|
CRED_ACCOUNT_EDIT_DEV: developer,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def has_credential(user: User,
|
||||||
|
credential: int,
|
||||||
|
approved_users: list = tuple()):
|
||||||
|
|
||||||
|
if user in approved_users:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if credential in cred_filters:
|
||||||
|
cred_filter = cred_filters.get(credential)
|
||||||
|
return cred_filter(user)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
|
@ -141,6 +141,11 @@ class User:
|
||||||
request.cookies["AURSID"] = self.session.SessionID
|
request.cookies["AURSID"] = self.session.SessionID
|
||||||
return self.session.SessionID
|
return self.session.SessionID
|
||||||
|
|
||||||
|
def has_credential(self, credential: str, approved: list = tuple()):
|
||||||
|
import aurweb.auth
|
||||||
|
cred = getattr(aurweb.auth, credential)
|
||||||
|
return aurweb.auth.has_credential(self, cred, approved)
|
||||||
|
|
||||||
def logout(self, request):
|
def logout(self, request):
|
||||||
from aurweb.db import session
|
from aurweb.db import session
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ import pytest
|
||||||
|
|
||||||
from starlette.authentication import AuthenticationError
|
from starlette.authentication import AuthenticationError
|
||||||
|
|
||||||
|
from aurweb.auth import BasicAuthBackend, has_credential
|
||||||
from aurweb.db import query
|
from aurweb.db import query
|
||||||
from aurweb.auth import BasicAuthBackend
|
|
||||||
from aurweb.models.account_type import AccountType
|
from aurweb.models.account_type import AccountType
|
||||||
from aurweb.testing import setup_test_db
|
from aurweb.testing import setup_test_db
|
||||||
from aurweb.testing.models import make_session, make_user
|
from aurweb.testing.models import make_session, make_user
|
||||||
|
@ -78,3 +78,8 @@ async def test_basic_auth_backend():
|
||||||
LastUpdateTS=now_ts + 5)
|
LastUpdateTS=now_ts + 5)
|
||||||
_, result = await backend.authenticate(request)
|
_, result = await backend.authenticate(request)
|
||||||
assert result == user
|
assert result == user
|
||||||
|
|
||||||
|
|
||||||
|
def test_has_fake_credential_fails():
|
||||||
|
# Fake credential 666 does not exist.
|
||||||
|
assert not has_credential(user, 666)
|
||||||
|
|
|
@ -163,6 +163,11 @@ def test_user_minimum_passwd_length():
|
||||||
assert User.minimum_passwd_length() == passwd_min_len
|
assert User.minimum_passwd_length() == passwd_min_len
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_has_credential():
|
||||||
|
assert user.has_credential("CRED_PKGBASE_FLAG")
|
||||||
|
assert not user.has_credential("CRED_ACCOUNT_CHANGE_TYPE")
|
||||||
|
|
||||||
|
|
||||||
def test_user_ssh_pub_key():
|
def test_user_ssh_pub_key():
|
||||||
from aurweb.db import session
|
from aurweb.db import session
|
||||||
|
|
||||||
|
@ -178,3 +183,40 @@ def test_user_ssh_pub_key():
|
||||||
|
|
||||||
session.delete(ssh_pub_key)
|
session.delete(ssh_pub_key)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_credential_types():
|
||||||
|
from aurweb.db import session
|
||||||
|
|
||||||
|
assert aurweb.auth.user_developer_or_trusted_user(user)
|
||||||
|
assert not aurweb.auth.trusted_user(user)
|
||||||
|
assert not aurweb.auth.developer(user)
|
||||||
|
assert not aurweb.auth.trusted_user_or_dev(user)
|
||||||
|
|
||||||
|
trusted_user_type = query(AccountType,
|
||||||
|
AccountType.AccountType == "Trusted User")\
|
||||||
|
.first()
|
||||||
|
user.AccountType = trusted_user_type
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
assert aurweb.auth.trusted_user(user)
|
||||||
|
assert aurweb.auth.trusted_user_or_dev(user)
|
||||||
|
|
||||||
|
developer_type = query(AccountType,
|
||||||
|
AccountType.AccountType == "Developer")\
|
||||||
|
.first()
|
||||||
|
user.AccountType = developer_type
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
assert aurweb.auth.developer(user)
|
||||||
|
assert aurweb.auth.trusted_user_or_dev(user)
|
||||||
|
|
||||||
|
type_str = "Trusted User & Developer"
|
||||||
|
elevated_type = query(AccountType,
|
||||||
|
AccountType.AccountType == type_str).first()
|
||||||
|
user.AccountType = elevated_type
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
assert aurweb.auth.trusted_user(user)
|
||||||
|
assert aurweb.auth.developer(user)
|
||||||
|
assert aurweb.auth.trusted_user_or_dev(user)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue