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
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);
});
}
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 = [];
}
manager.db.topicGetById.resolves({
id: '56c557ce-e667-11eb-bd80-0025905f714a',
created: new Date(),
- url: 'https://example.com/',
+ url: 'https://example.com/topic',
leaseSecondsPreferred: 123,
leaseSecondsMin: 12,
leaseSecondsMax: 123456789,
});
it('covers matching profile', async function () {
ctx.session = {
- authenticatedProfile: 'https://example.com/profile',
+ authenticatedProfile: 'https://example.com/',
};
await manager.getTopicDetails(res, ctx);
assert(ctx.topic);
});
}); // postRoot
+ describe('_profileControlsTopic', function () {
+ let profileUrlObj, topicUrlObj;
+ it('allows exact match', function () {
+ profileUrlObj = new URL('https://profile.example.com/');
+ topicUrlObj = new URL('https://profile.example.com/');
+ const result = Manager._profileControlsTopic(profileUrlObj, topicUrlObj);
+ assert.strictEqual(result, true);
+ });
+ it('allows descendent-path match', function () {
+ profileUrlObj = new URL('https://profile.example.com/');
+ topicUrlObj = new URL('https://profile.example.com/feed/atom');
+ const result = Manager._profileControlsTopic(profileUrlObj, topicUrlObj);
+ assert.strictEqual(result, true);
+ });
+ it('disallows non-descendent-path', function () {
+ profileUrlObj = new URL('https://profile.example.com/itsame');
+ topicUrlObj = new URL('https://profile.example.com/');
+ const result = Manager._profileControlsTopic(profileUrlObj, topicUrlObj);
+ assert.strictEqual(result, false);
+ });
+ it('disallows non-matched host', function () {
+ profileUrlObj = new URL('https://profile.example.com/itsame');
+ topicUrlObj = new URL('https://elsewhere.example.com/itsame/feed');
+ const result = Manager._profileControlsTopic(profileUrlObj, topicUrlObj);
+ assert.strictEqual(result, false);
+ });
+ }); // _profileControlsTopic
+
describe('_getRootData', function () {
it('extracts expected values', function () {
req.getHeader.returns('user@example.com');