consider path when determining if an IA profile user can view a topic
[websub-hub] / src / manager.js
index 9d4a282c2aac17864d3e330ba4e655cd424493fc..b6d2ccb6322fa2162662cc925e0859b4927d42e2 100644 (file)
@@ -606,6 +606,21 @@ class Manager {
     this.logger.info(_scope, 'finished', { ctx });
   }
 
+
+  /**
+   * Determine if a profile url matches enough of a topic url to describe control over it.
+   * Topic must match hostname and start with the profile's path.
+   * @param {URL} profileUrlObj
+   * @param {URL} topicUrlObj
+   * @returns {Boolean}
+   */
+  static _profileControlsTopic(profileUrlObj, topicUrlObj) {
+    const hostnameMatches = profileUrlObj.hostname === topicUrlObj.hostname;
+    const pathIsPrefix = topicUrlObj.pathname.startsWith(profileUrlObj.pathname);
+    return hostnameMatches && pathIsPrefix;
+  }
+
+
   /**
    * GET request for authorized /admin information.
    * @param {http.ServerResponse} res
@@ -625,7 +640,7 @@ class Manager {
       const profileUrlObj = new URL(ctx.session.authenticatedProfile);
       ctx.topics = ctx.topics.filter((topic) => {
         const topicUrlObj = new URL(topic.url);
-        return (topicUrlObj.hostname === profileUrlObj.hostname);
+        return Manager._profileControlsTopic(profileUrlObj, topicUrlObj);
       });
     }
 
@@ -659,7 +674,7 @@ class Manager {
     if (ctx.session && ctx.session.authenticatedProfile) {
       const profileUrlObj = new URL(ctx.session.authenticatedProfile);
       const topicUrlObj = new URL(ctx.topic.url);
-      if (topicUrlObj.hostname !== profileUrlObj.hostname) {
+      if (!Manager._profileControlsTopic(profileUrlObj, topicUrlObj)) {
         ctx.topic = null;
         ctx.subscriptions = [];
       }