mirror of
https://github.com/rr-/szurubooru.git
synced 2025-07-17 08:26:24 +00:00
client+server: switch to yaml config
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
alembic>=0.8.5
|
||||
configobj>=5.0.6
|
||||
pyyaml>=3.11
|
||||
falcon>=0.3.0
|
||||
psycopg2>=2.6.1
|
||||
SQLAlchemy>=1.0.12
|
||||
|
@ -19,12 +19,12 @@ class PasswordResetApi(BaseApi):
|
||||
'User %r hasn\'t supplied email. Cannot reset password.' % user_name)
|
||||
token = auth.generate_authentication_token(user)
|
||||
url = '%s/password-reset/%s:%s' % (
|
||||
config.config['basic']['base_url'].rstrip('/'), user.name, token)
|
||||
config.config['base_url'].rstrip('/'), user.name, token)
|
||||
mailer.send_mail(
|
||||
'noreply@%s' % config.config['basic']['name'],
|
||||
'noreply@%s' % config.config['name'],
|
||||
user.email,
|
||||
MAIL_SUBJECT.format(name=config.config['basic']['name']),
|
||||
MAIL_BODY.format(name=config.config['basic']['name'], url=url))
|
||||
MAIL_SUBJECT.format(name=config.config['name']),
|
||||
MAIL_BODY.format(name=config.config['name'], url=url))
|
||||
return {}
|
||||
|
||||
def post(self, context, user_name):
|
||||
|
@ -1,13 +1,26 @@
|
||||
import os
|
||||
import configobj
|
||||
import yaml
|
||||
from szurubooru import errors
|
||||
|
||||
def merge(left, right):
|
||||
for key in right:
|
||||
if key in left:
|
||||
if isinstance(left[key], dict) and isinstance(right[key], dict):
|
||||
merge(left[key], right[key])
|
||||
elif left[key] != right[key]:
|
||||
left[key] = right[key]
|
||||
else:
|
||||
left[key] = right[key]
|
||||
return left
|
||||
|
||||
class Config(object):
|
||||
''' INI config parser and container. '''
|
||||
''' Config parser and container. '''
|
||||
def __init__(self):
|
||||
self.config = configobj.ConfigObj('../config.ini.dist')
|
||||
if os.path.exists('../config.ini'):
|
||||
self.config.merge(configobj.ConfigObj('../config.ini'))
|
||||
with open('../config.yaml.dist') as handle:
|
||||
self.config = yaml.load(handle.read())
|
||||
if os.path.exists('../config.yaml'):
|
||||
with open('../config.yaml') as handle:
|
||||
self.config = merge(self.config, yaml.load(handle.read()))
|
||||
self._validate()
|
||||
|
||||
def __getitem__(self, key):
|
||||
@ -15,22 +28,25 @@ class Config(object):
|
||||
|
||||
def _validate(self):
|
||||
'''
|
||||
Check whether config.ini doesn't contain errors that might prove
|
||||
Check whether config doesn't contain errors that might prove
|
||||
lethal at runtime.
|
||||
'''
|
||||
all_ranks = self['service']['user_ranks']
|
||||
all_ranks = self['ranks']
|
||||
for privilege, rank in self['privileges'].items():
|
||||
if rank not in all_ranks:
|
||||
raise errors.ConfigError(
|
||||
'Rank %r for privilege %r is missing from user_ranks' % (
|
||||
rank, privilege))
|
||||
'Rank %r for privilege %r is missing' % (rank, privilege))
|
||||
for rank in ['anonymous', 'admin', 'nobody']:
|
||||
if rank not in all_ranks:
|
||||
raise errors.ConfigError(
|
||||
'Fixed rank %r is missing from user_ranks' % rank)
|
||||
if self['service']['default_user_rank'] not in all_ranks:
|
||||
raise errors.ConfigError('Protected rank %r is missing' % rank)
|
||||
if self['default_rank'] not in all_ranks:
|
||||
raise errors.ConfigError(
|
||||
'Default rank %r is missing from user_ranks' % (
|
||||
self['service']['default_user_rank']))
|
||||
'Default rank %r is not on the list of known ranks' % (
|
||||
self['default_rank']))
|
||||
|
||||
for key in ['schema', 'host', 'port', 'user', 'pass', 'name']:
|
||||
if not self['database'][key]:
|
||||
raise errors.ConfigError(
|
||||
'Database is not configured: %r is missing' % key)
|
||||
|
||||
config = Config() # pylint: disable=invalid-name
|
||||
|
@ -9,11 +9,9 @@ class TestPasswordReset(DatabaseTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
config_mock = {
|
||||
'basic': {
|
||||
'secret': 'x',
|
||||
'base_url': 'http://example.com/',
|
||||
'name': 'Test instance',
|
||||
},
|
||||
'secret': 'x',
|
||||
'base_url': 'http://example.com/',
|
||||
'name': 'Test instance',
|
||||
}
|
||||
self.old_config = config.config
|
||||
config.config = config_mock
|
||||
|
@ -13,9 +13,7 @@ class TestRetrievingUsers(DatabaseTestCase):
|
||||
'users:view': 'regular_user',
|
||||
'users:create': 'regular_user',
|
||||
},
|
||||
'service': {
|
||||
'user_ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
|
||||
},
|
||||
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
|
||||
}
|
||||
self.old_config = config.config
|
||||
config.config = config_mock
|
||||
@ -74,15 +72,11 @@ class TestCreatingUser(DatabaseTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
config_mock = {
|
||||
'basic': {
|
||||
'secret': '',
|
||||
},
|
||||
'service': {
|
||||
'user_name_regex': '.{3,}',
|
||||
'password_regex': '.{3,}',
|
||||
'user_ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
|
||||
'default_user_rank': 'regular_user',
|
||||
},
|
||||
'secret': '',
|
||||
'user_name_regex': '.{3,}',
|
||||
'password_regex': '.{3,}',
|
||||
'default_rank': 'regular_user',
|
||||
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
|
||||
'privileges': {
|
||||
'users:create': 'anonymous',
|
||||
},
|
||||
@ -146,14 +140,10 @@ class TestUpdatingUser(DatabaseTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
config_mock = {
|
||||
'basic': {
|
||||
'secret': '',
|
||||
},
|
||||
'service': {
|
||||
'user_name_regex': '.{3,}',
|
||||
'password_regex': '.{3,}',
|
||||
'user_ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
|
||||
},
|
||||
'secret': '',
|
||||
'user_name_regex': '.{3,}',
|
||||
'password_regex': '.{3,}',
|
||||
'ranks': ['anonymous', 'regular_user', 'mod', 'admin'],
|
||||
'privileges': {
|
||||
'users:edit:self:name': 'regular_user',
|
||||
'users:edit:self:pass': 'regular_user',
|
||||
|
@ -6,7 +6,7 @@ from szurubooru import errors
|
||||
def get_password_hash(salt, password):
|
||||
''' Retrieve new-style password hash. '''
|
||||
digest = hashlib.sha256()
|
||||
digest.update(config.config['basic']['secret'].encode('utf8'))
|
||||
digest.update(config.config['secret'].encode('utf8'))
|
||||
digest.update(salt.encode('utf8'))
|
||||
digest.update(password.encode('utf8'))
|
||||
return digest.hexdigest()
|
||||
@ -42,7 +42,7 @@ def verify_privilege(user, privilege_name):
|
||||
'''
|
||||
Throw an AuthError if the given user doesn't have given privilege.
|
||||
'''
|
||||
all_ranks = config.config['service']['user_ranks']
|
||||
all_ranks = config.config['ranks']
|
||||
|
||||
assert privilege_name in config.config['privileges']
|
||||
assert user.rank in all_ranks
|
||||
@ -54,6 +54,6 @@ def verify_privilege(user, privilege_name):
|
||||
def generate_authentication_token(user):
|
||||
''' Generate nonguessable challenge (e.g. links in password reminder). '''
|
||||
digest = hashlib.md5()
|
||||
digest.update(config.config['basic']['secret'].encode('utf8'))
|
||||
digest.update(config.config['secret'].encode('utf8'))
|
||||
digest.update(user.password_salt.encode('utf8'))
|
||||
return digest.hexdigest()
|
||||
|
@ -10,7 +10,7 @@ def create_user(name, password, email):
|
||||
update_name(user, name)
|
||||
update_password(user, password)
|
||||
update_email(user, email)
|
||||
user.rank = config.config['service']['default_user_rank']
|
||||
user.rank = config.config['default_rank']
|
||||
user.creation_time = datetime.now()
|
||||
user.avatar_style = db.User.AVATAR_GRAVATAR
|
||||
return user
|
||||
@ -18,7 +18,7 @@ def create_user(name, password, email):
|
||||
def update_name(user, name):
|
||||
''' Validate and update user's name. '''
|
||||
name = name.strip()
|
||||
name_regex = config.config['service']['user_name_regex']
|
||||
name_regex = config.config['user_name_regex']
|
||||
if not re.match(name_regex, name):
|
||||
raise errors.ValidationError(
|
||||
'Name must satisfy regex %r.' % name_regex)
|
||||
@ -26,7 +26,7 @@ def update_name(user, name):
|
||||
|
||||
def update_password(user, password):
|
||||
''' Validate and update user's password. '''
|
||||
password_regex = config.config['service']['password_regex']
|
||||
password_regex = config.config['password_regex']
|
||||
if not re.match(password_regex, password):
|
||||
raise errors.ValidationError(
|
||||
'Password must satisfy regex %r.' % password_regex)
|
||||
@ -43,10 +43,10 @@ def update_email(user, email):
|
||||
|
||||
def update_rank(user, rank, authenticated_user):
|
||||
rank = rank.strip()
|
||||
available_ranks = config.config['service']['user_ranks']
|
||||
available_ranks = config.config['ranks']
|
||||
if not rank in available_ranks:
|
||||
raise errors.ValidationError(
|
||||
'Bad rank. Valid ranks: %r' % available_ranks)
|
||||
'Bad rank %r. Valid ranks: %r' % (rank, available_ranks))
|
||||
if available_ranks.index(authenticated_user.rank) \
|
||||
< available_ranks.index(rank):
|
||||
raise errors.AuthError('Trying to set higher rank than your own')
|
||||
|
Reference in New Issue
Block a user