From 42b5196b21c39954014020aecb1fbd8fe361f46a Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Tue, 29 Mar 2016 15:58:14 -0400 Subject: [PATCH] add notification path and use for service keys --- data/database.py | 1 + data/model/notification.py | 25 ++++++++++++++++++++----- data/model/service_keys.py | 27 ++++++++++++++++----------- endpoints/key_server.py | 4 ++-- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/data/database.py b/data/database.py index 3aea96e84..0fc2d29c9 100644 --- a/data/database.py +++ b/data/database.py @@ -772,6 +772,7 @@ class Notification(BaseModel): metadata_json = TextField(default='{}') created = DateTimeField(default=datetime.now, index=True) dismissed = BooleanField(default=False) + lookup_path = CharField(null=True, index=True) class ExternalNotificationEvent(BaseModel): diff --git a/data/model/notification.py b/data/model/notification.py index c42ddd07d..9ce0a5de4 100644 --- a/data/model/notification.py +++ b/data/model/notification.py @@ -6,10 +6,11 @@ from data.database import (Notification, NotificationKind, User, Team, TeamMembe ExternalNotificationMethod, Namespace) -def create_notification(kind_name, target, metadata={}): +def create_notification(kind_name, target, metadata={}, lookup_path=None): kind_ref = NotificationKind.get(name=kind_name) notification = Notification.create(kind=kind_ref, target=target, - metadata_json=json.dumps(metadata)) + metadata_json=json.dumps(metadata), + lookup_path=lookup_path) return notification @@ -27,6 +28,12 @@ def lookup_notification(user, uuid): return results[0] +def lookup_notifications_by_path_prefix(prefix): + return list((Notification + .select() + .where(Notification.lookup_path % prefix))) + + def list_notifications(user, kind_name=None, id_filter=None, include_dismissed=False, page=None, limit=None): @@ -69,6 +76,13 @@ def list_notifications(user, kind_name=None, id_filter=None, include_dismissed=F return query.order_by(base_query.c.created.desc()) +def delete_all_notifications_by_path_prefix(prefix): + (Notification + .delete() + .where(Notification.lookup_path % prefix) + .execute()) + + def delete_all_notifications_by_kind(kind_name): kind_ref = NotificationKind.get(name=kind_name) (Notification @@ -87,9 +101,10 @@ def delete_matching_notifications(target, kind_name, **kwargs): kind_ref = NotificationKind.get(name=kind_name) # Load all notifications for the user with the given kind. - notifications = Notification.select().where( - Notification.target == target, - Notification.kind == kind_ref) + notifications = (Notification + .select() + .where(Notification.target == target, + Notification.kind == kind_ref)) # For each, match the metadata to the specified values. for notification in notifications: diff --git a/data/model/service_keys.py b/data/model/service_keys.py index 1f02288eb..601eb4d43 100644 --- a/data/model/service_keys.py +++ b/data/model/service_keys.py @@ -3,8 +3,7 @@ from datetime import datetime, timedelta from app import app from data.database import db_for_update, User, ServiceKey, ServiceKeyApproval from data.model import ServiceKeyDoesNotExist, ServiceKeyAlreadyApproved, db_transaction -from data.model.notification import create_notification - +from data.model.notification import create_notification, delete_all_notifications_by_path_prefix # TODO ACTION_LOGS for keys UNAPPROVED_TTL = timedelta(seconds=app.config['UNAPPROVED_SERVICE_KEY_TTL_SEC']) @@ -30,19 +29,22 @@ def create_service_key(name, kid, service, jwk, metadata, expiration_date): sk = ServiceKey.create(name=name, kid=kid, service=service, jwk=jwk, metadata=metadata, expiration_date=expiration_date) + notification_metadata = { + 'name': name, + 'kid': kid, + 'service': service, + 'jwk': jwk, + 'metadata': metadata, + 'created_date': sk.created_date, + 'expiration_date': expiration_date, + } + superusers = User.select().where(User.username << app.config['SUPER_USERS']) for superuser in superusers: # TODO(jzelinskie): create notification type in the database migration # I already put it in initdb - create_notification('service_key_submitted', superuser, { - 'name': name, - 'kid': kid, - 'service': service, - 'jwk': jwk, - 'metadata': metadata, - 'created_date': sk.created_date, - 'expiration_date': expiration_date, - }) + create_notification('service_key_submitted', superuser, metadata=notification_metadata, + lookup_path='/service_key_approval/{0}'.format(kid)) _gc_expired(service) @@ -98,6 +100,9 @@ def approve_service_key(kid, approver, approval_type): except ServiceKey.DoesNotExist: raise ServiceKeyDoesNotExist + delete_all_notifications_by_path_prefix('/service_key_approval/{0}'.format(kid)) + _gc_expired(key.service) + def _get_service_keys_query(kid=None, service=None, approved_only=False): query = ServiceKey.select() diff --git a/endpoints/key_server.py b/endpoints/key_server.py index bc8c231af..cb4cc0ae2 100644 --- a/endpoints/key_server.py +++ b/endpoints/key_server.py @@ -65,14 +65,14 @@ def get_service_keys(service): @key_server.route('/services//keys/', methods=['GET']) -def get_service_key(kid): +def get_service_key(service, kid): try: key = data.model.service_keys.get_service_key(kid) except data.model.ServiceKeyDoesNotExist: abort(404) if key.approval is None: - abort(404) + abort(409) return jsonify(key.jwk)