Merge remote-tracking branch 'origin/master' into comewithmeifyouwanttowork

Conflicts:
	data/model/legacy.py
	static/js/app.js
This commit is contained in:
Jake Moshenko 2014-09-12 11:03:30 -04:00
commit c5ca46a14b
70 changed files with 1566 additions and 630 deletions

View file

@ -1,12 +1,17 @@
import bcrypt
import logging
import datetime
import dateutil.parser
import json
from datetime import datetime, timedelta
from data.database import *
from util.validation import *
from util.names import format_robot_username
from util.backoff import exponential_backoff
EXPONENTIAL_BACKOFF_SCALE = timedelta(seconds=1)
logger = logging.getLogger(__name__)
@ -75,6 +80,12 @@ class UserAlreadyInTeam(DataModelException):
pass
class TooManyLoginAttemptsException(Exception):
def __init__(self, message, retry_after):
super(TooManyLoginAttemptsException, self).__init__(message)
self.retry_after = retry_after
def is_create_user_allowed():
return True
@ -413,7 +424,8 @@ def set_team_org_permission(team, team_role_name, set_by_username):
return team
def create_federated_user(username, email, service_name, service_id, set_password_notification):
def create_federated_user(username, email, service_name, service_id,
set_password_notification, metadata={}):
if not is_create_user_allowed():
raise TooManyUsersException()
@ -423,7 +435,8 @@ def create_federated_user(username, email, service_name, service_id, set_passwor
service = LoginService.get(LoginService.name == service_name)
FederatedLogin.create(user=new_user, service=service,
service_ident=service_id)
service_ident=service_id,
metadata_json=json.dumps(metadata))
if set_password_notification:
create_notification('password_required', new_user)
@ -431,9 +444,10 @@ def create_federated_user(username, email, service_name, service_id, set_passwor
return new_user
def attach_federated_login(user, service_name, service_id):
def attach_federated_login(user, service_name, service_id, metadata={}):
service = LoginService.get(LoginService.name == service_name)
FederatedLogin.create(user=user, service=service, service_ident=service_id)
FederatedLogin.create(user=user, service=service, service_ident=service_id,
metadata_json=json.dumps(metadata))
return user
@ -452,7 +466,7 @@ def verify_federated_login(service_name, service_id):
def list_federated_logins(user):
selected = FederatedLogin.select(FederatedLogin.service_ident,
LoginService.name)
LoginService.name, FederatedLogin.metadata_json)
joined = selected.join(LoginService)
return joined.where(LoginService.name != 'quayrobot',
FederatedLogin.user == user)
@ -588,11 +602,30 @@ def verify_user(username_or_email, password):
except User.DoesNotExist:
return None
now = datetime.utcnow()
if fetched.invalid_login_attempts > 0:
can_retry_at = exponential_backoff(fetched.invalid_login_attempts, EXPONENTIAL_BACKOFF_SCALE,
fetched.last_invalid_login)
if can_retry_at > now:
retry_after = can_retry_at - now
raise TooManyLoginAttemptsException('Too many login attempts.', retry_after.total_seconds())
if (fetched.password_hash and
bcrypt.hashpw(password, fetched.password_hash) ==
fetched.password_hash):
if fetched.invalid_login_attempts > 0:
fetched.invalid_login_attempts = 0
fetched.save()
return fetched
fetched.invalid_login_attempts += 1
fetched.last_invalid_login = now
fetched.save()
# We weren't able to authorize the user
return None
@ -1078,7 +1111,8 @@ def find_create_or_link_image(docker_image_id, repository, username, translation
.join(Repository)
.join(Visibility)
.switch(Repository)
.join(RepositoryPermission, JOIN_LEFT_OUTER))
.join(RepositoryPermission, JOIN_LEFT_OUTER)
.where(ImageStorage.uploading == False))
query = (_filter_to_repos_for_user(query, username)
.where(Image.docker_image_id == docker_image_id))