From 9ae4506a0ddb7fda78bc8acf25ff0a28fe8f6809 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Tue, 18 Mar 2014 16:45:18 -0400 Subject: [PATCH] Add OAuth usage information the API logs, have it be displayed in the logs UI and start on the code to display application information when clicked. Note that this does not (yet) do anything with the information returned as we need to wait for the mainline merge of Angular 1.2.9 (which is in master) before I can continue on the display --- auth/auth.py | 4 ++- auth/auth_context.py | 9 +++++ data/model/oauth.py | 6 ++++ endpoints/api/__init__.py | 13 +++++-- endpoints/api/organization.py | 20 ++++++++++- static/directives/application-reference.html | 4 +++ static/directives/logs-view.html | 18 +++++++--- static/js/app.js | 38 ++++++++++++++++++++ 8 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 static/directives/application-reference.html diff --git a/auth/auth.py b/auth/auth.py index f2b512121..0cfcedfc4 100644 --- a/auth/auth.py +++ b/auth/auth.py @@ -14,7 +14,7 @@ from data.model import oauth from app import app from permissions import QuayDeferredPermissionUser from auth_context import (set_authenticated_user, set_validated_token, - set_authenticated_user_deferred) + set_authenticated_user_deferred, set_validated_oauth_token) from util.http import abort @@ -140,7 +140,9 @@ def process_oauth(f): scope_set = scopes.scopes_from_scope_string(validated.scope) logger.debug('Successfully validated oauth access token: %s with scope: %s', token, scope_set) + set_authenticated_user(validated.authorized_user) + set_validated_oauth_token(validated) new_identity = QuayDeferredPermissionUser(validated.authorized_user.username, 'username', scope_set) diff --git a/auth/auth_context.py b/auth/auth_context.py index 16d62f5d9..2aad14685 100644 --- a/auth/auth_context.py +++ b/auth/auth_context.py @@ -35,6 +35,15 @@ def set_authenticated_user_deferred(username_or_robotname): ctx.authenticated_username = username_or_robotname +def get_validated_oauth_token(): + return getattr(_request_ctx_stack.top, 'validated_oauth_token', None) + + +def set_validated_oauth_token(token): + ctx = _request_ctx_stack.top + ctx.validated_oauth_token = token + + def get_validated_token(): return getattr(_request_ctx_stack.top, 'validated_token', None) diff --git a/data/model/oauth.py b/data/model/oauth.py index 475893b4d..75596c535 100644 --- a/data/model/oauth.py +++ b/data/model/oauth.py @@ -176,3 +176,9 @@ def validate_access_token(access_token): return found except OAuthAccessToken.DoesNotExist: return None + +def get_application_for_client_id(client_id): + try: + return OAuthApplication.get(client_id=client_id) + except OAuthApplication.DoesNotExist: + return None diff --git a/endpoints/api/__init__.py b/endpoints/api/__init__.py index 7ba2500a1..c593f6649 100644 --- a/endpoints/api/__init__.py +++ b/endpoints/api/__init__.py @@ -16,7 +16,7 @@ from auth.permissions import (ReadRepositoryPermission, ModifyRepositoryPermission, AdministerRepositoryPermission) from auth import scopes -from auth.auth_context import get_authenticated_user +from auth.auth_context import get_authenticated_user, get_validated_oauth_token from auth.auth import process_oauth @@ -213,7 +213,16 @@ def request_error(exception=None, **kwargs): raise InvalidRequest(exception.message, data) -def log_action(kind, user_or_orgname, metadata={}, repo=None): +def log_action(kind, user_or_orgname, metadata=None, repo=None): + if not metadata: + metadata = {} + + oauth_token = get_validated_oauth_token() + if 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 + performer = get_authenticated_user() model.log_action(kind, user_or_orgname, performer=performer, ip=request.remote_addr, metadata=metadata, repository=repo) diff --git a/endpoints/api/organization.py b/endpoints/api/organization.py index fe886410f..9597bdb52 100644 --- a/endpoints/api/organization.py +++ b/endpoints/api/organization.py @@ -248,4 +248,22 @@ class OrganizationMember(ApiResource): return {'member': member_dict} - raise Unauthorized() \ No newline at end of file + raise Unauthorized() + + +@resource('/v1/app/') +class ApplicationInformation(ApiResource): + """ Resource that returns public information about a registered application. """ + @nickname('getApplicationInformation') + def get(self, client_id): + """ Get information on the specified application. """ + application = model.oauth.get_application_for_client_id(client_id) + if not application: + raise NotFound() + + return { + 'name': application.name, + 'description': application.description, + 'uri': application.application_uri, + 'organization': org_view(application.organization, []) + } diff --git a/static/directives/application-reference.html b/static/directives/application-reference.html new file mode 100644 index 000000000..0f61c5dc2 --- /dev/null +++ b/static/directives/application-reference.html @@ -0,0 +1,4 @@ + + + {{ title }} + diff --git a/static/directives/logs-view.html b/static/directives/logs-view.html index d6405d342..2268d0dc3 100644 --- a/static/directives/logs-view.html +++ b/static/directives/logs-view.html @@ -42,7 +42,7 @@ Description Date/Time - User/Token + User/Token/App @@ -53,14 +53,24 @@ {{ log.datetime }} - + +
+ +
+
on behalf of
+
+ +
+
+ - + {{ log.metadata.token }} - + (anonymous) diff --git a/static/js/app.js b/static/js/app.js index 03ca9d383..861f627b7 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -921,6 +921,44 @@ quayApp.directive('entityReference', function () { }); +quayApp.directive('applicationReference', function () { + var directiveDefinitionObject = { + priority: 0, + templateUrl: '/static/directives/application-reference.html', + replace: false, + transclude: false, + restrict: 'C', + scope: { + 'title': '=title', + 'clientId': '=clientId' + }, + controller: function($scope, $element, ApiService, $modal) { + $scope.showAppDetails = function() { + var params = { + 'client_id': $scope.clientId + }; + + ApiService.getApplicationInformation(null, params).then(function(resp) { + // TODO: display the application information here. + }, function() { + bootbox.dialog({ + "message": 'The application could not be found; it might have been deleted.', + "title": "Cannot find application", + "buttons": { + "close": { + "label": "Close", + "className": "btn-primary" + } + } + }); + }); + }; + } + }; + return directiveDefinitionObject; +}); + + quayApp.directive('markdownView', function () { var directiveDefinitionObject = { priority: 0,