client+server: switch to yaml config
This commit is contained in:
parent
19a357611b
commit
55cc7b59e4
18 changed files with 201 additions and 179 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
config.ini
|
||||
config.yaml
|
||||
*/*_modules/
|
||||
|
|
19
INSTALL.md
19
INSTALL.md
|
@ -75,12 +75,12 @@ user@host:szuru/server$ source python_modules/bin/activate # enters the sandbox
|
|||
1. Configure things:
|
||||
|
||||
```console
|
||||
user@host:szuru$ cp config.ini.dist config.ini
|
||||
user@host:szuru$ vim config.ini
|
||||
user@host:szuru$ cp config.yaml.dist config.yaml
|
||||
user@host:szuru$ vim config.yaml
|
||||
```
|
||||
|
||||
Pay extra attention to the `[database]` section, `[smtp]` section, API URL
|
||||
and base URL in `[basic]`.
|
||||
Pay extra attention to API URL, base URL, the `database` section and the
|
||||
`smtp` section.
|
||||
|
||||
2. Compile the frontend:
|
||||
|
||||
|
@ -132,7 +132,7 @@ Below are described the methods to integrate the API into a web server:
|
|||
`uwsgi`, but they'll need to write wrapper scripts themselves.
|
||||
|
||||
Note that the API URL in the virtual host configuration needs to be the same as
|
||||
the one in the `config.ini`, so that client knows how to access the backend!
|
||||
the one in the `config.yaml`, so that client knows how to access the backend!
|
||||
|
||||
#### Example
|
||||
|
||||
|
@ -157,12 +157,11 @@ server {
|
|||
}
|
||||
```
|
||||
|
||||
**`config.ini`**:
|
||||
**`config.yaml`**:
|
||||
|
||||
```ini
|
||||
[basic]
|
||||
api_url = http://big.dude/api/
|
||||
base_url = http://big.dude/
|
||||
```yaml
|
||||
api_url: 'http://big.dude/api/'
|
||||
base_url: 'http://big.dude/'
|
||||
```
|
||||
|
||||
Then the backend is started with `./server/host-waitress` from within
|
||||
|
|
|
@ -5,40 +5,47 @@ const glob = require('glob');
|
|||
const path = require('path');
|
||||
const util = require('util');
|
||||
const execSync = require('child_process').execSync;
|
||||
const camelcase = require('camelcase');
|
||||
|
||||
function convertKeysToCamelCase(input) {
|
||||
let result = {};
|
||||
Object.keys(input).map((key, _) => {
|
||||
const value = input[key];
|
||||
if (value !== null && value.constructor == Object) {
|
||||
result[camelcase(key)] = convertKeysToCamelCase(value);
|
||||
} else {
|
||||
result[camelcase(key)] = value;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getVersion() {
|
||||
return execSync('git describe --always --dirty --long --tags').toString();
|
||||
}
|
||||
|
||||
function getConfig() {
|
||||
const ini = require('ini');
|
||||
const yaml = require('js-yaml');
|
||||
const merge = require('merge');
|
||||
const camelcaseKeys = require('camelcase-keys');
|
||||
|
||||
function parseIniFile(path) {
|
||||
let result = ini.parse(fs.readFileSync(path, 'utf-8')
|
||||
.replace(/#.+$/gm, '')
|
||||
.replace(/\s+$/gm, ''));
|
||||
Object.keys(result).map((key, _) => {
|
||||
result[key] = camelcaseKeys(result[key]);
|
||||
});
|
||||
return result;
|
||||
function parseConfigFile(path) {
|
||||
let result = yaml.load(fs.readFileSync(path, 'utf-8'));
|
||||
return convertKeysToCamelCase(result);
|
||||
}
|
||||
|
||||
let config = parseIniFile('../config.ini.dist');
|
||||
let config = parseConfigFile('../config.yaml.dist');
|
||||
|
||||
try {
|
||||
const localConfig = parseIniFile('../config.ini');
|
||||
const localConfig = parseConfigFile('../config.yaml');
|
||||
config = merge.recursive(config, localConfig);
|
||||
} catch (e) {
|
||||
console.warn('Local config does not exist, ignoring');
|
||||
}
|
||||
|
||||
delete config.basic.secret;
|
||||
delete config.secret;
|
||||
delete config.smtp;
|
||||
delete config.database;
|
||||
config.service.userRanks = config.service.userRanks.split(/,\s*/);
|
||||
config.service.tagCategories = config.service.tagCategories.split(/,\s*/);
|
||||
config.meta = {
|
||||
version: getVersion(),
|
||||
buildDate: new Date().toUTCString(),
|
||||
|
@ -63,7 +70,7 @@ function bundleHtml(config) {
|
|||
.replace(/(<\/head>)/, templatesHtml + '$1')
|
||||
.replace(
|
||||
/(<title>)(.*)(<\/title>)/,
|
||||
util.format('$1%s$3', config.basic.name));
|
||||
util.format('$1%s$3', config.name));
|
||||
|
||||
fs.writeFileSync(
|
||||
'./public/index.htm',
|
||||
|
|
|
@ -48,7 +48,7 @@ class Api {
|
|||
continue;
|
||||
}
|
||||
const rankName = config.privileges[privilege];
|
||||
const rankIndex = config.service.userRanks.indexOf(rankName);
|
||||
const rankIndex = config.ranks.indexOf(rankName);
|
||||
if (minViableRank === null || rankIndex < minViableRank) {
|
||||
minViableRank = rankIndex;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ class Api {
|
|||
console.error('Bad privilege name: ' + lookup);
|
||||
}
|
||||
let myRank = this.user !== null ?
|
||||
config.service.userRanks.indexOf(this.user.accessRank) :
|
||||
config.ranks.indexOf(this.user.rank) :
|
||||
0;
|
||||
return myRank >= minViableRank;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ class Api {
|
|||
}
|
||||
|
||||
getFullUrl(url) {
|
||||
return (config.basic.apiUrl + '/' + url).replace(/([^:])\/+/g, '$1/');
|
||||
return (config.apiUrl + '/' + url).replace(/([^:])\/+/g, '$1/');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class HelpView extends BaseView {
|
|||
}
|
||||
|
||||
const content = this.sectionTemplates[section]({
|
||||
'name': config.basic.name,
|
||||
'name': config.name,
|
||||
});
|
||||
|
||||
this.showView(this.template({'content': content}));
|
||||
|
|
|
@ -11,7 +11,7 @@ class HomeView extends BaseView {
|
|||
|
||||
render(section) {
|
||||
this.showView(this.template({
|
||||
name: config.basic.name,
|
||||
name: config.name,
|
||||
version: config.meta.version,
|
||||
buildDate: config.meta.buildDate,
|
||||
}));
|
||||
|
|
|
@ -17,8 +17,8 @@ class LoginView extends BaseView {
|
|||
const userNameField = document.getElementById('user-name');
|
||||
const passwordField = document.getElementById('user-password');
|
||||
const rememberUserField = document.getElementById('remember-user');
|
||||
userNameField.setAttribute('pattern', config.service.userNameRegex);
|
||||
passwordField.setAttribute('pattern', config.service.passwordRegex);
|
||||
userNameField.setAttribute('pattern', config.userNameRegex);
|
||||
passwordField.setAttribute('pattern', config.passwordRegex);
|
||||
|
||||
form.addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -17,8 +17,8 @@ class RegistrationView extends BaseView {
|
|||
const userNameField = document.getElementById('user-name');
|
||||
const passwordField = document.getElementById('user-password');
|
||||
const emailField = document.getElementById('user-email');
|
||||
userNameField.setAttribute('pattern', config.service.userNameRegex);
|
||||
passwordField.setAttribute('pattern', config.service.passwordRegex);
|
||||
userNameField.setAttribute('pattern', config.userNameRegex);
|
||||
passwordField.setAttribute('pattern', config.passwordRegex);
|
||||
|
||||
form.addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"browserify": "^13.0.0",
|
||||
"camelcase-keys": "^2.1.0",
|
||||
"camelcase": "^2.1.1",
|
||||
"csso": "^1.8.0",
|
||||
"glob": "^7.0.3",
|
||||
"handlebars": "^4.0.5",
|
||||
"html-minifier": "^1.3.1",
|
||||
"ini": "^1.3.4",
|
||||
"js-cookie": "^2.1.0",
|
||||
"js-yaml": "^3.5.5",
|
||||
"merge": "^1.2.0",
|
||||
"page": "^1.7.1",
|
||||
"superagent": "^1.8.3",
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
# rather than editing this file, it is strongly suggested to create config.ini
|
||||
# and override only what you need.
|
||||
|
||||
[basic]
|
||||
name = szurubooru
|
||||
debug = 0
|
||||
secret = change
|
||||
api_url = "http://api.example.com/" # where frontend connects to
|
||||
base_url = "http://example.com/" # used in absolute links (e.g. password reminder)
|
||||
|
||||
[database]
|
||||
schema = postgres
|
||||
host = localhost
|
||||
port = 5432
|
||||
user = szuru
|
||||
pass = dog
|
||||
name = szuru
|
||||
|
||||
[smtp]
|
||||
# used to send password reminders
|
||||
host = localhost
|
||||
port = 25
|
||||
user = bot
|
||||
pass = groovy123
|
||||
|
||||
[service]
|
||||
user_ranks = anonymous, regular_user, power_user, mod, admin, nobody
|
||||
default_user_rank = regular_user
|
||||
users_per_page = 20
|
||||
posts_per_page = 40
|
||||
max_comment_length = 5000
|
||||
tag_categories = meta, artist, character, copyright, other unique
|
||||
|
||||
# don't change these regexes, unless you want to annoy people. but if you do
|
||||
# customize them, make sure to update the instructions in the registration form
|
||||
# template as well.
|
||||
password_regex = "^.{5,}$"
|
||||
user_name_regex = "^[a-zA-Z0-9_-]{1,32}$"
|
||||
|
||||
[privileges]
|
||||
users:create = anonymous
|
||||
users:list = regular_user
|
||||
users:view = regular_user
|
||||
users:edit:any:name = mod
|
||||
users:edit:any:pass = mod
|
||||
users:edit:any:email = mod
|
||||
users:edit:any:avatar = mod
|
||||
# note: promoting people to higher rank than one's own is always impossible
|
||||
users:edit:any:rank = mod
|
||||
users:edit:self:name = regular_user
|
||||
users:edit:self:pass = regular_user
|
||||
users:edit:self:email = regular_user
|
||||
users:edit:self:avatar = regular_user
|
||||
users:edit:self:rank = mod
|
||||
users:delete:any = admin
|
||||
users:delete:self = regular_user
|
||||
|
||||
posts:create:anonymous = regular_user
|
||||
posts:create:identified = regular_user
|
||||
posts:list = anonymous
|
||||
posts:view = anonymous
|
||||
posts:edit:content = power_user
|
||||
posts:edit:flags = regular_user
|
||||
posts:edit:notes = regular_user
|
||||
posts:edit:relations = regular_user
|
||||
posts:edit:safety = power_user
|
||||
posts:edit:source = regular_user
|
||||
posts:edit:tags = regular_user
|
||||
posts:edit:thumbnail = power_user
|
||||
posts:feature = mod
|
||||
posts:delete = mod
|
||||
|
||||
tags:create = regular_user
|
||||
tags:edit:name = power_user
|
||||
tags:edit:category = power_user
|
||||
tags:edit:implications = power_user
|
||||
tags:edit:suggestions = power_user
|
||||
tags:list = regular_user
|
||||
tags:masstag = power_user
|
||||
tags:merge = mod
|
||||
tags:delete = mod
|
||||
|
||||
comments:create = regular_user
|
||||
comments:delete:any = mod
|
||||
comments:delete:own = regular_user
|
||||
comments:edit:any = mod
|
||||
comments:edit:own = regular_user
|
||||
comments:list = regular_user
|
||||
|
||||
history:view = power_user
|
102
config.yaml.dist
Normal file
102
config.yaml.dist
Normal file
|
@ -0,0 +1,102 @@
|
|||
# rather than editing this file, it is strongly suggested to create config.ini
|
||||
# and override only what you need.
|
||||
|
||||
name: szurubooru
|
||||
debug: 0
|
||||
secret: change
|
||||
api_url: # where frontend connects to, example: http://api.example.com/
|
||||
base_url: # used to form absolute links, example: http://example.com/
|
||||
|
||||
database:
|
||||
schema: postgres
|
||||
host: # example: localhost
|
||||
port: # example: 5432
|
||||
user: # example: szuru
|
||||
pass: # example: dog
|
||||
name: # example: szuru
|
||||
|
||||
# used to send password reminders
|
||||
smtp:
|
||||
host: # example: localhost
|
||||
port: # example: 25
|
||||
user: # example: bot
|
||||
pass: # example: groovy123
|
||||
|
||||
limits:
|
||||
users_per_page: 20
|
||||
posts_per_page: 40
|
||||
max_comment_length: 5000
|
||||
|
||||
tag_categories:
|
||||
- meta
|
||||
- artist
|
||||
- character
|
||||
- copyright
|
||||
- other unique
|
||||
|
||||
# changing ranks after deployment may require manual tweaks to the database.
|
||||
ranks:
|
||||
- anonymous
|
||||
- regular_user
|
||||
- power_user
|
||||
- mod
|
||||
- admin
|
||||
- nobody
|
||||
default_rank: regular_user
|
||||
|
||||
# don't change these, unless you want to annoy people. if you do customize
|
||||
# them though, make sure to update the instructions in the registration form
|
||||
# template as well.
|
||||
password_regex: '^.{5,}$'
|
||||
user_name_regex: '^[a-zA-Z0-9_-]{1,32}$'
|
||||
|
||||
privileges:
|
||||
'users:create': anonymous
|
||||
'users:list': regular_user
|
||||
'users:view': regular_user
|
||||
'users:edit:any:name': mod
|
||||
'users:edit:any:pass': mod
|
||||
'users:edit:any:email': mod
|
||||
'users:edit:any:avatar': mod
|
||||
'users:edit:any:rank': mod
|
||||
'users:edit:self:name': regular_user
|
||||
'users:edit:self:pass': regular_user
|
||||
'users:edit:self:email': regular_user
|
||||
'users:edit:self:avatar': regular_user
|
||||
'users:edit:self:rank': mod # one can't promote themselves or anyone to upper rank than their own.
|
||||
'users:delete:any': admin
|
||||
'users:delete:self': regular_user
|
||||
|
||||
'posts:create:anonymous': regular_user
|
||||
'posts:create:identified': regular_user
|
||||
'posts:list': anonymous
|
||||
'posts:view': anonymous
|
||||
'posts:edit:content': power_user
|
||||
'posts:edit:flags': regular_user
|
||||
'posts:edit:notes': regular_user
|
||||
'posts:edit:relations': regular_user
|
||||
'posts:edit:safety': power_user
|
||||
'posts:edit:source': regular_user
|
||||
'posts:edit:tags': regular_user
|
||||
'posts:edit:thumbnail': power_user
|
||||
'posts:feature': mod
|
||||
'posts:delete': mod
|
||||
|
||||
'tags:create': regular_user
|
||||
'tags:edit:name': power_user
|
||||
'tags:edit:category': power_user
|
||||
'tags:edit:implications': power_user
|
||||
'tags:edit:suggestions': power_user
|
||||
'tags:list': regular_user
|
||||
'tags:masstag': power_user
|
||||
'tags:merge': mod
|
||||
'tags:delete': mod
|
||||
|
||||
'comments:create': regular_user
|
||||
'comments:delete:any': mod
|
||||
'comments:delete:own': regular_user
|
||||
'comments:edit:any': mod
|
||||
'comments:edit:own': regular_user
|
||||
'comments:list': regular_user
|
||||
|
||||
'history:view': power_user
|
|
@ -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')
|
||||
|
|
Loading…
Reference in a new issue