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

This commit is contained in:
Jake Moshenko 2015-01-21 13:39:27 -05:00
commit 44f7ab53a2
46 changed files with 664 additions and 263 deletions

View file

@ -4,14 +4,17 @@ import json
import string
import datetime
# Register the various exceptions via decorators.
import endpoints.decorated
from flask import make_response, render_template, request, abort, session
from flask.ext.login import login_user, UserMixin
from flask.ext.login import login_user
from flask.ext.principal import identity_changed
from random import SystemRandom
from data import model
from data.database import db
from app import app, login_manager, dockerfile_build_queue, notification_queue, oauth_apps
from app import app, oauth_apps, dockerfile_build_queue, LoginWrappedDBUser
from auth.permissions import QuayDeferredPermissionUser
from auth import scopes
@ -21,7 +24,6 @@ from functools import wraps
from config import getFrontendVisibleConfig
from external_libraries import get_external_javascript, get_external_css
from endpoints.notificationhelper import spawn_notification
from util.useremails import CannotSendEmailException
import features
@ -84,34 +86,8 @@ def param_required(param_name):
return wrapper
@login_manager.user_loader
def load_user(user_uuid):
logger.debug('User loader loading deferred user with uuid: %s' % user_uuid)
return _LoginWrappedDBUser(user_uuid)
class _LoginWrappedDBUser(UserMixin):
def __init__(self, user_uuid, db_user=None):
self._uuid = user_uuid
self._db_user = db_user
def db_user(self):
if not self._db_user:
self._db_user = model.get_user_by_uuid(self._uuid)
return self._db_user
def is_authenticated(self):
return self.db_user() is not None
def is_active(self):
return self.db_user().verified
def get_id(self):
return unicode(self._uuid)
def common_login(db_user):
if login_user(_LoginWrappedDBUser(db_user.uuid, db_user)):
if login_user(LoginWrappedDBUser(db_user.uuid, db_user)):
logger.debug('Successfully signed in as: %s (%s)' % (db_user.username, db_user.uuid))
new_identity = QuayDeferredPermissionUser(db_user.uuid, 'user_uuid', {scopes.DIRECT_LOGIN})
identity_changed.send(app, identity=new_identity)
@ -121,17 +97,6 @@ def common_login(db_user):
logger.debug('User could not be logged in, inactive?.')
return False
@app.errorhandler(model.DataModelException)
def handle_dme(ex):
logger.exception(ex)
return make_response(json.dumps({'message': ex.message}), 400)
@app.errorhandler(CannotSendEmailException)
def handle_emailexception(ex):
message = 'Could not send email. Please contact an administrator and report this problem.'
return make_response(json.dumps({'message': message}), 400)
def random_string():
random = SystemRandom()
return ''.join([random.choice(string.ascii_uppercase + string.digits) for _ in range(8)])

19
endpoints/decorated.py Normal file
View file

@ -0,0 +1,19 @@
import logging
import json
from flask import make_response
from app import app
from util.useremails import CannotSendEmailException
from data import model
logger = logging.getLogger(__name__)
@app.errorhandler(model.DataModelException)
def handle_dme(ex):
logger.exception(ex)
return make_response(json.dumps({'message': ex.message}), 400)
@app.errorhandler(CannotSendEmailException)
def handle_emailexception(ex):
message = 'Could not send email. Please contact an administrator and report this problem.'
return make_response(json.dumps({'message': message}), 400)

View file

@ -305,9 +305,7 @@ def get_repository_images(namespace, repository):
permission = ReadRepositoryPermission(namespace, repository)
# TODO invalidate token?
profile.debug('Looking up public status of repository')
is_public = model.repository_is_public(namespace, repository)
if permission.can() or is_public:
if permission.can() or model.repository_is_public(namespace, repository):
# We can't rely on permissions to tell us if a repo exists anymore
profile.debug('Looking up repository')
repo = model.get_repository(namespace, repository)
@ -382,6 +380,11 @@ def get_search():
resp.mimetype = 'application/json'
return resp
# Note: This is *not* part of the Docker index spec. This is here for our own health check,
# since we have nginx handle the _ping below.
@index.route('/_internal_ping')
def internal_ping():
return make_response('true', 200)
@index.route('/_ping')
@index.route('/_ping')

View file

@ -19,20 +19,23 @@ def track_and_log(event_name, repo, **kwargs):
analytics_id = 'anonymous'
authenticated_oauth_token = get_validated_oauth_token()
authenticated_user = get_authenticated_user()
authenticated_token = get_validated_token() if not authenticated_user else None
profile.debug('Logging the %s to Mixpanel and the log system', event_name)
if get_validated_oauth_token():
oauth_token = get_validated_oauth_token()
metadata['oauth_token_id'] = oauth_token.id
metadata['oauth_token_application_id'] = oauth_token.application.client_id
metadata['oauth_token_application'] = oauth_token.application.name
analytics_id = 'oauth:' + oauth_token.id
elif get_authenticated_user():
metadata['username'] = get_authenticated_user().username
analytics_id = get_authenticated_user().username
elif get_validated_token():
metadata['token'] = get_validated_token().friendly_name
metadata['token_code'] = get_validated_token().code
analytics_id = 'token:' + get_validated_token().code
if authenticated_oauth_token:
metadata['oauth_token_id'] = authenticated_oauth_token.id
metadata['oauth_token_application_id'] = authenticated_oauth_token.application.client_id
metadata['oauth_token_application'] = authenticated_oauth_token.application.name
analytics_id = 'oauth:' + authenticated_oauth_token.id
elif authenticated_user:
metadata['username'] = authenticated_user.username
analytics_id = authenticated_user.username
elif authenticated_token:
metadata['token'] = authenticated_token.friendly_name
metadata['token_code'] = authenticated_token.code
analytics_id = 'token:' + authenticated_token.code
else:
metadata['public'] = True
analytics_id = 'anonymous'
@ -42,21 +45,27 @@ def track_and_log(event_name, repo, **kwargs):
}
# Publish the user event (if applicable)
if get_authenticated_user():
profile.debug('Checking publishing %s to the user events system', event_name)
if authenticated_user:
profile.debug('Publishing %s to the user events system', event_name)
user_event_data = {
'action': event_name,
'repository': repository,
'namespace': namespace
}
event = userevents.get_event(get_authenticated_user().username)
event = userevents.get_event(authenticated_user.username)
event.publish_event_data('docker-cli', user_event_data)
# Save the action to mixpanel.
profile.debug('Logging the %s to Mixpanel', event_name)
analytics.track(analytics_id, event_name, extra_params)
# Log the action to the database.
profile.debug('Logging the %s to logs system', event_name)
model.log_action(event_name, namespace,
performer=get_authenticated_user(),
performer=authenticated_user,
ip=request.remote_addr, metadata=metadata,
repository=repo)
profile.debug('Track and log of %s complete', event_name)

View file

@ -226,7 +226,7 @@ class GithubBuildTrigger(BuildTrigger):
'personal': False,
'repos': repo_list,
'info': {
'name': org.name,
'name': org.name or org.login,
'avatar_url': org.avatar_url
}
})

View file

@ -6,7 +6,7 @@ from flask import (abort, redirect, request, url_for, make_response, Response,
from avatar_generator import Avatar
from flask.ext.login import current_user
from urlparse import urlparse
from health.healthcheck import HealthCheck
from health.healthcheck import get_healthchecker
from data import model
from data.model.oauth import DatabaseAuthorizationProvider
@ -27,6 +27,9 @@ import features
logger = logging.getLogger(__name__)
# Capture the unverified SSL errors.
logging.captureWarnings(True)
web = Blueprint('web', __name__)
STATUS_TAGS = app.config['STATUS_TAGS']
@ -153,33 +156,27 @@ def v1():
return index('')
# TODO(jschorr): Remove this mirrored endpoint once we migrate ELB.
@web.route('/health', methods=['GET'])
@web.route('/health/instance', methods=['GET'])
@no_cache
def health():
db_healthy = model.check_health()
buildlogs_healthy = build_logs.check_health()
check = HealthCheck.get_check(app.config['HEALTH_CHECKER'][0], app.config['HEALTH_CHECKER'][1])
(data, is_healthy) = check.conduct_healthcheck(db_healthy, buildlogs_healthy)
response = jsonify(dict(data = data, is_healthy = is_healthy))
response.status_code = 200 if is_healthy else 503
def instance_health():
checker = get_healthchecker(app)
(data, status_code) = checker.check_instance()
response = jsonify(dict(data=data, status_code=status_code))
response.status_code = status_code
return response
# TODO(jschorr): Remove this mirrored endpoint once we migrate pingdom.
@web.route('/status', methods=['GET'])
@web.route('/health/endtoend', methods=['GET'])
@no_cache
def status():
db_healthy = model.check_health()
buildlogs_healthy = build_logs.check_health()
response = jsonify({
'db_healthy': db_healthy,
'buildlogs_healthy': buildlogs_healthy,
'is_testing': app.config['TESTING'],
})
response.status_code = 200 if db_healthy and buildlogs_healthy else 503
def endtoend_health():
checker = get_healthchecker(app)
(data, status_code) = checker.check_endtoend()
response = jsonify(dict(data=data, status_code=status_code))
response.status_code = status_code
return response