From 3259cda000c39bb5d04f16e8ab578c09cef77ab4 Mon Sep 17 00:00:00 2001 From: Jake Moshenko Date: Mon, 22 Sep 2014 17:27:02 -0400 Subject: [PATCH] The new strategy is to do a three phase migration. This is the first phase: getting the namespace user in the db and written for all new repositories. --- application.py | 2 +- data/database.py | 1 + ...6878560_migrate_registry_namespaces_to_.py | 30 ------- data/model/legacy.py | 84 ++++++++++-------- endpoints/common.py | 15 ++-- test/data/test.db | Bin 630784 -> 638976 bytes test/test_api_security.py | 4 +- 7 files changed, 62 insertions(+), 74 deletions(-) diff --git a/application.py b/application.py index 2fb79835b..493b34fed 100644 --- a/application.py +++ b/application.py @@ -7,7 +7,7 @@ from peewee import Proxy from app import app as application from flask import request, Request from util.names import urn_generator -from data.model import db as model_db, read_slave +from data.database import db as model_db, read_slave # Turn off debug logging for boto logging.getLogger('boto').setLevel(logging.CRITICAL) diff --git a/data/database.py b/data/database.py index 760ca7f17..2a824e1da 100644 --- a/data/database.py +++ b/data/database.py @@ -181,6 +181,7 @@ class Repository(BaseModel): indexes = ( # create a unique index on namespace and name (('namespace', 'name'), True), + (('namespace_user', 'name'), False), ) diff --git a/data/migrations/versions/13da56878560_migrate_registry_namespaces_to_.py b/data/migrations/versions/13da56878560_migrate_registry_namespaces_to_.py index 68b2e83c1..8d2810af7 100644 --- a/data/migrations/versions/13da56878560_migrate_registry_namespaces_to_.py +++ b/data/migrations/versions/13da56878560_migrate_registry_namespaces_to_.py @@ -19,36 +19,6 @@ def upgrade(tables): # Add the namespace_user column, allowing it to be nullable op.add_column('repository', sa.Column('namespace_user', sa.Integer(), sa.ForeignKey('user.id'))) - # backfill the namespace_user column - namespace_to_user = {} - for user in User.select(User.name, User.id).where(User.robot == False): - namespace_to_user[user.username] = user - - for repo in Repository.select(): - repo.namespace_user = namespace_to_user[repo.namespace] - repo.save() - - # Ensure the backfill was a success, then remove the namespace column - op.alter_column('repository', 'namespace_user', nullable=False) - op.create_index('repository_namespace_user_name', 'repository', ['namespace_user', 'name'], - unique=True) - - op.drop_index('repository_namespace_user', table_name='repository') - op.drop_column('repository', 'namespace') - def downgrade(tables): - # Add the namespace column, allowing it to be nullable - op.add_column('repository', sa.Column('namespace', sa.String(length=255))) - - # backfill the namespace column - for repo in Repository.select(Repository, User.username).join(User): - repo.namespace = repo.namespace_user.username - repo.save() - - # Ensure the backfill was a success, then remove the namespace column - op.alter_column('repository', 'namespace', nullable=False) - op.create_index('repository_namespace_name', 'repository', ['namespace', 'name'], unique=True) - - op.drop_index('repository_namespace_user', table_name='repository') op.drop_column('repository', 'namespace_user') diff --git a/data/model/legacy.py b/data/model/legacy.py index a50a675d1..ced35063f 100644 --- a/data/model/legacy.py +++ b/data/model/legacy.py @@ -5,8 +5,18 @@ import json from datetime import datetime, timedelta -from data.database import * -from util.validation import * +from data.database import (User, Repository, Image, AccessToken, Role, RepositoryPermission, + Visibility, RepositoryTag, EmailConfirmation, FederatedLogin, + LoginService, RepositoryBuild, Team, TeamMember, TeamRole, + LogEntryKind, LogEntry, PermissionPrototype, ImageStorage, + BuildTriggerService, RepositoryBuildTrigger, NotificationKind, + Notification, ImageStorageLocation, ImageStoragePlacement, + ExternalNotificationEvent, ExternalNotificationMethod, + RepositoryNotification, RepositoryAuthorizedEmail, TeamMemberInvite, + random_string_generator, db, BUILD_PHASE) +from peewee import JOIN_LEFT_OUTER, fn +from util.validation import (validate_username, validate_email, validate_password, + INVALID_PASSWORD_MESSAGE) from util.names import format_robot_username from util.backoff import exponential_backoff @@ -560,9 +570,9 @@ def get_user_or_org(username): return None -def get_user_by_id(user_dbid): +def get_user_by_id(user_db_id): try: - return User.get(User.id == user_dbid, User.organization == False) + return User.get(User.id == user_db_id, User.organization == False) except User.DoesNotExist: return None @@ -632,7 +642,8 @@ def verify_user(username_or_email, password): retry_after = can_retry_at - now raise TooManyLoginAttemptsException('Too many login attempts.', retry_after.total_seconds()) - if (fetched.password_hash and hash_password(password, fetched.password_hash) == fetched.password_hash): + if (fetched.password_hash and + hash_password(password, fetched.password_hash) == fetched.password_hash): if fetched.invalid_login_attempts > 0: fetched.invalid_login_attempts = 0 fetched.save() @@ -765,23 +776,23 @@ def _filter_to_repos_for_user(query, username=None, namespace=None, AdminUser = User.alias() query = (query - .switch(RepositoryPermission) - .join(User, JOIN_LEFT_OUTER) - .switch(RepositoryPermission) - .join(Team, JOIN_LEFT_OUTER) - .join(TeamMember, JOIN_LEFT_OUTER) - .join(UserThroughTeam, JOIN_LEFT_OUTER, on=(UserThroughTeam.id == - TeamMember.user)) - .switch(Repository) - .join(Org, JOIN_LEFT_OUTER, on=(Org.username == Repository.namespace)) - .join(AdminTeam, JOIN_LEFT_OUTER, on=(Org.id == - AdminTeam.organization)) - .join(TeamRole, JOIN_LEFT_OUTER, on=(AdminTeam.role == TeamRole.id)) - .switch(AdminTeam) - .join(AdminTeamMember, JOIN_LEFT_OUTER, on=(AdminTeam.id == - AdminTeamMember.team)) - .join(AdminUser, JOIN_LEFT_OUTER, on=(AdminTeamMember.user == - AdminUser.id))) + .switch(RepositoryPermission) + .join(User, JOIN_LEFT_OUTER) + .switch(RepositoryPermission) + .join(Team, JOIN_LEFT_OUTER) + .join(TeamMember, JOIN_LEFT_OUTER) + .join(UserThroughTeam, JOIN_LEFT_OUTER, on=(UserThroughTeam.id == + TeamMember.user)) + .switch(Repository) + .join(Org, JOIN_LEFT_OUTER, on=(Org.username == Repository.namespace)) + .join(AdminTeam, JOIN_LEFT_OUTER, on=(Org.id == + AdminTeam.organization)) + .join(TeamRole, JOIN_LEFT_OUTER, on=(AdminTeam.role == TeamRole.id)) + .switch(AdminTeam) + .join(AdminTeamMember, JOIN_LEFT_OUTER, on=(AdminTeam.id == + AdminTeamMember.team)) + .join(AdminUser, JOIN_LEFT_OUTER, on=(AdminTeamMember.user == + AdminUser.id))) where_clause = ((User.username == username) | (UserThroughTeam.username == username) | @@ -1048,8 +1059,9 @@ def __apply_default_permissions(repo, proto_query, name_property, def create_repository(namespace, name, creating_user, visibility='private'): private = Visibility.get(name=visibility) - repo = Repository.create(namespace=namespace, name=name, - visibility=private) + namespace_user = User.get(username=namespace) + repo = Repository.create(namespace=namespace, name=name, visibility=private, + namespace_user=namespace_user) admin = Role.get(name='admin') if creating_user and not creating_user.organization: @@ -1121,26 +1133,26 @@ def find_create_or_link_image(docker_image_id, repository, username, translation return repo_image query = (Image - .select(Image, ImageStorage) - .distinct() - .join(ImageStorage) - .switch(Image) - .join(Repository) - .join(Visibility) - .switch(Repository) - .join(RepositoryPermission, JOIN_LEFT_OUTER) - .where(ImageStorage.uploading == False)) + .select(Image, ImageStorage) + .distinct() + .join(ImageStorage) + .switch(Image) + .join(Repository) + .join(Visibility) + .switch(Repository) + .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)) - + .where(Image.docker_image_id == docker_image_id)) + new_image_ancestry = '/' origin_image_id = None try: to_copy = query.get() msg = 'Linking image to existing storage with docker id: %s and uuid: %s' logger.debug(msg, docker_image_id, to_copy.storage.uuid) - + new_image_ancestry = __translate_ancestry(to_copy.ancestors, translations, repository, username, preferred_location) diff --git a/endpoints/common.py b/endpoints/common.py index 5479be6e0..1c6439371 100644 --- a/endpoints/common.py +++ b/endpoints/common.py @@ -82,15 +82,18 @@ def param_required(param_name): @login_manager.user_loader -def load_user(user_dbid): - logger.debug('User loader loading deferred user id: %s' % user_dbid) - return _LoginWrappedDBUser(user_dbid) +def load_user(user_db_id): + logger.debug('User loader loading deferred user id: %s' % user_db_id) + try: + user_db_id_int = int(user_db_id) + return _LoginWrappedDBUser(user_db_id_int) + except ValueError: + return None class _LoginWrappedDBUser(UserMixin): - def __init__(self, user_dbid, db_user=None): - - self._db_id = int(user_dbid) + def __init__(self, user_db_id, db_user=None): + self._db_id = user_db_id self._db_user = db_user def db_user(self): diff --git a/test/data/test.db b/test/data/test.db index 68f838e57c1414788549bfc39fec51ede0008c52..f6e5f83d912c419441ed127a8e6cd9a993b4f0a5 100644 GIT binary patch delta 9314 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 diff --git a/test/test_api_security.py b/test/test_api_security.py index 04498ad2a..d9e4f223b 100644 --- a/test/test_api_security.py +++ b/test/test_api_security.py @@ -5,6 +5,7 @@ from urllib import urlencode from urlparse import urlparse, urlunparse, parse_qs from app import app +from data import model from initdb import setup_database_for_testing, finished_database_for_testing from endpoints.api import api_bp, api @@ -75,7 +76,8 @@ class ApiTestCase(unittest.TestCase): with client.session_transaction() as sess: if auth_username: - sess['user_id'] = auth_username + loaded = model.get_user(auth_username) + sess['user_id'] = loaded.id sess[CSRF_TOKEN_KEY] = CSRF_TOKEN # Restore the teardown functions