Add support for temp usernames and an interstitial to confirm username

When a user now logs in for the first time for any external auth (LDAP, JWT, Keystone, Github, Google, Dex), they will be presented with a confirmation screen that affords them the opportunity to change their Quay-assigned username.

Addresses most of the user issues around #74
This commit is contained in:
Joseph Schorr 2016-09-08 18:43:50 -04:00
parent 840ea4e768
commit 1e3b354201
18 changed files with 388 additions and 24 deletions

View file

@ -11,7 +11,8 @@ from data.database import (User, LoginService, FederatedLogin, RepositoryPermiss
Team, Repository, TupleSelector, TeamRole, Namespace, Visibility,
EmailConfirmation, Role, db_for_update, random_string_generator,
UserRegion, ImageStorageLocation, QueueItem, TeamMemberInvite,
ServiceKeyApproval, OAuthApplication, RepositoryBuildTrigger)
ServiceKeyApproval, OAuthApplication, RepositoryBuildTrigger,
UserPromptKind, UserPrompt)
from data.model import (DataModelException, InvalidPasswordException, InvalidRobotException,
InvalidUsernameException, InvalidEmailAddressException,
TooManyLoginAttemptsException, db_transaction,
@ -102,6 +103,38 @@ def change_password(user, new_password):
notification.delete_notifications_by_kind(user, 'password_required')
def has_user_prompts(user):
try:
UserPrompt.select().where(UserPrompt.user == user).get()
return True
except UserPrompt.DoesNotExist:
return False
def has_user_prompt(user, prompt_name):
prompt_kind = UserPromptKind.get(name=prompt_name)
try:
UserPrompt.get(user=user, kind=prompt_kind)
return True
except UserPrompt.DoesNotExist:
return False
def create_user_prompt(user, prompt_name):
prompt_kind = UserPromptKind.get(name=prompt_name)
return UserPrompt.create(user=user, kind=prompt_kind)
def remove_user_prompt(user, prompt_name):
prompt_kind = UserPromptKind.get(name=prompt_name)
UserPrompt.delete().where(UserPrompt.user == user, UserPrompt.kind == prompt_kind).execute()
def get_user_prompts(user):
query = UserPrompt.select().where(UserPrompt.user == user).join(UserPromptKind)
return [prompt.kind.name for prompt in query]
def change_username(user_id, new_username):
(username_valid, username_issue) = validate_username(new_username)
if not username_valid:
@ -121,6 +154,10 @@ def change_username(user_id, new_username):
# Rename the user
user.username = new_username
user.save()
# Remove any prompts for username.
remove_user_prompt(user, 'confirm_username')
return user
@ -305,11 +342,15 @@ def list_entity_robot_permission_teams(entity_name, include_permissions=False):
def create_federated_user(username, email, service_name, service_ident,
set_password_notification, metadata={}, email_required=True):
set_password_notification, metadata={},
email_required=True, confirm_username=False):
new_user = create_user_noverify(username, email, email_required=email_required)
new_user.verified = True
new_user.save()
if confirm_username:
create_user_prompt(new_user, 'confirm_username')
service = LoginService.get(LoginService.name == service_name)
FederatedLogin.create(user=new_user, service=service,
service_ident=service_ident,