Merge branch 'master' of https://bitbucket.org/yackob03/quay
This commit is contained in:
commit
038e9afc97
7 changed files with 68 additions and 4 deletions
|
@ -3,6 +3,8 @@ import logging
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
|
|
||||||
from database import *
|
from database import *
|
||||||
|
from util.validation import (validate_email, validate_username,
|
||||||
|
validate_password)
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -14,8 +16,20 @@ class DataModelException(Exception):
|
||||||
|
|
||||||
def create_user(username, password, email):
|
def create_user(username, password, email):
|
||||||
pw_hash = bcrypt.hashpw(password, bcrypt.gensalt())
|
pw_hash = bcrypt.hashpw(password, bcrypt.gensalt())
|
||||||
new_user = User.create(username=username, password_hash=pw_hash,
|
|
||||||
email=email)
|
if not validate_email(email):
|
||||||
|
raise DataModelException('Invalid email address: %s' % email)
|
||||||
|
if not validate_username(username):
|
||||||
|
raise DataModelException('Invalid username: %s' % username)
|
||||||
|
if not validate_password(password):
|
||||||
|
raise DataModelException('Invalid password, password must be at least ' +
|
||||||
|
'8 characters and contain no whitespace.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
new_user = User.create(username=username, password_hash=pw_hash,
|
||||||
|
email=email)
|
||||||
|
except Exception as ex:
|
||||||
|
raise DataModelException(ex.message)
|
||||||
return new_user
|
return new_user
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ from functools import wraps
|
||||||
from data import model
|
from data import model
|
||||||
from app import app
|
from app import app
|
||||||
from util.names import parse_repository_name
|
from util.names import parse_repository_name
|
||||||
|
from util.gravatar import compute_hash
|
||||||
from auth.permissions import (ReadRepositoryPermission,
|
from auth.permissions import (ReadRepositoryPermission,
|
||||||
ModifyRepositoryPermission,
|
ModifyRepositoryPermission,
|
||||||
AdministerRepositoryPermission)
|
AdministerRepositoryPermission)
|
||||||
|
@ -15,6 +16,11 @@ from auth.permissions import (ReadRepositoryPermission,
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(model.DataModelException)
|
||||||
|
def handle_dme(ex):
|
||||||
|
return make_response(ex.message, 400)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/')
|
@app.route('/api/')
|
||||||
def welcome():
|
def welcome():
|
||||||
return make_response('welcome', 200)
|
return make_response('welcome', 200)
|
||||||
|
@ -29,6 +35,7 @@ def get_logged_in_user():
|
||||||
'anonymous': False,
|
'anonymous': False,
|
||||||
'username': user.username,
|
'username': user.username,
|
||||||
'email': user.email,
|
'email': user.email,
|
||||||
|
'gravatar': compute_hash(user.email),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,17 @@ p.editable:hover i {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar-nav > li > .user-dropdown {
|
||||||
|
padding-top: 9px;
|
||||||
|
padding-bottom: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-dropdown > img {
|
||||||
|
padding-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides for typeahead to work with bootstrap 3. */
|
||||||
|
|
||||||
.twitter-typeahead .tt-query,
|
.twitter-typeahead .tt-query,
|
||||||
.twitter-typeahead .tt-hint {
|
.twitter-typeahead .tt-hint {
|
||||||
|
@ -279,4 +290,4 @@ p.editable:hover i {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.428571429;
|
line-height: 1.428571429;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,13 @@
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<li class="dropdown" ng-switch-when="false">
|
<li class="dropdown" ng-switch-when="false">
|
||||||
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">{{ user.username }} <b class="caret"></b></a>
|
<!--<button type="button" class="btn btn-default navbar-btn">Sign in</button>-->
|
||||||
|
|
||||||
|
<a href="javascript:void(0)" class="dropdown-toggle user-dropdown" data-toggle="dropdown">
|
||||||
|
<img src="http://www.gravatar.com/avatar/{{ user.gravatar }}?s=32&d=identicon" />
|
||||||
|
{{ user.username }}
|
||||||
|
<b class="caret"></b>
|
||||||
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="/signout">Sign out</a></li>
|
<li><a href="/signout">Sign out</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
BIN
test.db
BIN
test.db
Binary file not shown.
5
util/gravatar.py
Normal file
5
util/gravatar.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
|
||||||
|
def compute_hash(email_address):
|
||||||
|
return hashlib.md5(email_address.strip().lower()).hexdigest()
|
21
util/validation.py
Normal file
21
util/validation.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import re
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
|
||||||
|
def validate_email(email_address):
|
||||||
|
if re.match(r'[^@]+@[^@]+\.[^@]+', email_address):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def validate_username(username):
|
||||||
|
# Minimum length of 2, maximum length of 255, no url unsafe characters
|
||||||
|
return (urllib.quote(username, safe='') == username and
|
||||||
|
len(username) > 1 and
|
||||||
|
len(username) < 256)
|
||||||
|
|
||||||
|
def validate_password(password):
|
||||||
|
# No whitespace and minimum length of 8
|
||||||
|
if re.search(r'\s', password):
|
||||||
|
return False
|
||||||
|
return len(password) > 7
|
Reference in a new issue