diff --git a/data/database.py b/data/database.py index 9400e0aa2..5ff37345c 100644 --- a/data/database.py +++ b/data/database.py @@ -86,7 +86,7 @@ class Image(BaseModel): # to be globally unique we can't treat them as such for permissions and # security reasons. So rather than Repository <-> Image being many to many # each image now belongs to exactly one repository. - image_id = CharField() + docker_image_id = CharField() checksum = CharField(null=True) created = DateTimeField(null=True) comment = TextField(null=True) @@ -99,7 +99,7 @@ class Image(BaseModel): database = db indexes = ( # we don't really want duplicates - (('repository', 'image_id'), True), + (('repository', 'docker_image_id'), True), ) diff --git a/data/model.py b/data/model.py index cc3646f03..2fc075669 100644 --- a/data/model.py +++ b/data/model.py @@ -182,25 +182,26 @@ def create_repository(namespace, name, owner): return repo -def create_image(image_id, repository): - new_image = Image.create(image_id=image_id, repository=repository) +def create_image(docker_image_id, repository): + new_image = Image.create(docker_image_id=docker_image_id, + repository=repository) return new_image -def set_image_checksum(image_id, repository, checksum): - fetched = Image.get(Image.image_id == image_id, +def set_image_checksum(docker_image_id, repository, checksum): + fetched = Image.get(Image.docker_image_id == docker_image_id, Image.repository == repository) fetched.checksum = checksum fetched.save() return fetched -def set_image_metadata(image_id, namespace_name, repository_name, +def set_image_metadata(docker_image_id, namespace_name, repository_name, created_date_str, comment, parent=None): joined = Image.select().join(Repository) image_list = list(joined.where(Repository.name == repository_name, Repository.namespace == namespace_name, - Image.image_id == image_id)) + Image.docker_image_id == docker_image_id)) if not image_list: raise DataModelException('No image with specified id and repository') @@ -232,9 +233,9 @@ def list_repository_tags(namespace_name, repository_name): def get_tag_image(namespace_name, repository_name, tag_name): joined = Image.select().join(RepositoryTag).join(Repository) - fetched = joined.where(Repository.name == repository_name, - Repository.namespace == namespace_name, - RepositoryTag.name == tag_name) + fetched = list(joined.where(Repository.name == repository_name, + Repository.namespace == namespace_name, + RepositoryTag.name == tag_name)) if not fetched: raise DataModelException('Unable to find image for tag.') @@ -242,8 +243,16 @@ def get_tag_image(namespace_name, repository_name, tag_name): return fetched[0] -def get_image_by_id(image_id): - return Image.get(Image.image_id == image_id) +def get_image_by_id(namespace_name, repository_name, docker_image_id): + joined = Image.select().join(Repository) + fetched = list(joined.where(Repository.name == repository_name, + Repository.namespace == namespace_name, + Image.docker_image_id == docker_image_id)) + + if not fetched: + raise DataModelException('Unable to find image for tag with repo.') + + return fetched[0] def get_parent_images(image_obj): @@ -259,10 +268,10 @@ def get_parent_images(image_obj): def create_or_update_tag(namespace_name, repository_name, tag_name, - tag_image_id): + tag_docker_image_id): repo = Repository.get(Repository.name == repository_name, Repository.namespace == namespace_name) - image = Image.get(Image.image_id == tag_image_id) + image = Image.get(Image.docker_image_id == tag_docker_image_id) try: tag = RepositoryTag.get(RepositoryTag.repository == repo, diff --git a/endpoints/api.py b/endpoints/api.py index 1f09d8b27..4896116d9 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -154,7 +154,7 @@ def delete_repository(namespace, repository): def image_view(image): return { - 'id': image.image_id, + 'id': image.docker_image_id, 'created': image.created, 'comment': image.comment, } diff --git a/endpoints/index.py b/endpoints/index.py index 2c2ca6e0a..4e146d254 100644 --- a/endpoints/index.py +++ b/endpoints/index.py @@ -44,11 +44,22 @@ def generate_headers(f): @app.route('/v1/users/', methods=['POST']) def create_user(): user_data = request.get_json() - new_user = model.create_user(user_data['username'], user_data['password'], - user_data['email']) - code = model.create_confirm_email_code(new_user) - send_confirmation_email(new_user.username, new_user.email, code.code) - return make_response('Created', 201) + username = user_data['username'] + password = user_data['password'] + + existing_user = model.get_user(username) + if existing_user: + verified = model.verify_user(username, password) + if verified: + return make_response('Verified', 201) + else: + abort(401) + else: + # New user case + new_user = model.create_user(username, password, user_data['email']) + code = model.create_confirm_email_code(new_user) + send_confirmation_email(new_user.username, new_user.email, code.code) + return make_response('Created', 201) @app.route('/v1/users', methods=['GET']) @@ -112,8 +123,8 @@ def create_repository(namespace, repository): new_repo_images = {desc['id']: desc for desc in image_descriptions} added_images = dict(new_repo_images) for existing in model.get_repository_images(namespace, repository): - if existing.image_id in new_repo_images: - added_images.pop(existing.image_id) + if existing.docker_image_id in new_repo_images: + added_images.pop(existing.docker_image_id) else: existing.repositoryimage.delete() @@ -158,7 +169,7 @@ def get_repository_images(namespace, repository): all_images = [] for image in model.get_repository_images(namespace, repository): new_image_view = { - 'id': image.image_id, + 'id': image.docker_image_id, 'checksum': image.checksum, } all_images.append(new_image_view) diff --git a/endpoints/registry.py b/endpoints/registry.py index 830575d11..0fda2db78 100644 --- a/endpoints/registry.py +++ b/endpoints/registry.py @@ -291,7 +291,7 @@ def put_image_json(namespace, repository, image_id): # on a failed push # save the metadata if parent_id: - parent_obj = model.get_image_by_id(parent_id) + parent_obj = model.get_image_by_id(namespace, repository, parent_id) else: parent_obj = None diff --git a/endpoints/web.py b/endpoints/web.py index ca4f07c91..959b0fb8d 100644 --- a/endpoints/web.py +++ b/endpoints/web.py @@ -1,6 +1,7 @@ import logging -from flask import abort, send_file, redirect, request, url_for +from flask import (abort, send_file, redirect, request, url_for, + render_template) from flask.ext.login import login_user, UserMixin, login_required, logout_user from flask.ext.principal import identity_changed, Identity, AnonymousIdentity @@ -42,6 +43,11 @@ def common_login(db_user): identity_changed.send(app, identity=Identity(db_user.username, 'username')) +@app.route('/signin', methods=['GET']) +def render_signin_page(): + return render_template('signin.html') + + @app.route('/signin', methods=['POST']) def signin(): username = request.form['username'] @@ -54,7 +60,10 @@ def signin(): return redirect(request.args.get('next') or url_for('index')) - abort(403) + else: + return render_template('signin.html', + username=username, + error='Invalid username or password.') @app.route('/confirm', methods=['GET']) @@ -72,11 +81,6 @@ def password_reset(): pass -@app.route('/signin', methods=['GET']) -def render_signin_page(): - return send_file('templates/signin.html') - - @app.route("/signout") @login_required def logout(): diff --git a/initdb.py b/initdb.py new file mode 100644 index 000000000..d18a62084 --- /dev/null +++ b/initdb.py @@ -0,0 +1,4 @@ +from data.database import initialize_db + +if __name__ == '__main__': + initialize_db() \ No newline at end of file diff --git a/static/css/signin.css b/static/css/signin.css index a6bf9b159..637ffdfb5 100644 --- a/static/css/signin.css +++ b/static/css/signin.css @@ -37,4 +37,9 @@ body { margin-bottom: 10px; border-top-left-radius: 0; border-top-right-radius: 0; +} + +.alert { + max-width: 300px; + margin: 0 auto; } \ No newline at end of file diff --git a/static/js/controllers.js b/static/js/controllers.js index 5c75e3370..2e53a98ea 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -168,7 +168,7 @@ function RepoCtrl($scope, Restangular, $routeParams, $rootScope) { $scope.repo = repo; $scope.currentTag = repo.tags[tag] || repo.tags['latest']; - var clip = new ZeroClipboard($('#copyClipboard'), { 'moviePath': 'static/js/ZeroClipboard.swf' }); + var clip = new ZeroClipboard($('#copyClipboard'), { 'moviePath': 'static/lib/ZeroClipboard.swf' }); clip.on('complete', function() { // Resets the animation. var elem = $('#clipboardCopied')[0]; diff --git a/static/js/ZeroClipboard.min.js b/static/lib/ZeroClipboard.min.js similarity index 100% rename from static/js/ZeroClipboard.min.js rename to static/lib/ZeroClipboard.min.js diff --git a/static/js/ZeroClipboard.swf b/static/lib/ZeroClipboard.swf similarity index 100% rename from static/js/ZeroClipboard.swf rename to static/lib/ZeroClipboard.swf diff --git a/static/js/typeahead.min.js b/static/lib/typeahead.min.js similarity index 100% rename from static/js/typeahead.min.js rename to static/lib/typeahead.min.js diff --git a/templates/index.html b/templates/index.html index 3f2d6e08b..88c8e8fcb 100644 --- a/templates/index.html +++ b/templates/index.html @@ -24,8 +24,8 @@ - - + + diff --git a/templates/signin.html b/templates/signin.html index 15051a495..20d9f2a38 100644 --- a/templates/signin.html +++ b/templates/signin.html @@ -10,10 +10,14 @@
- +
+ + {% if error %} +
{{ error }}
+ {% endif %}
\ No newline at end of file diff --git a/test.db b/test.db index de63aaddb..6041988e4 100644 Binary files a/test.db and b/test.db differ