Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3360794
D12354.id41125.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D12354.id41125.diff
View Options
diff --git a/keyserver/src/creators/invite-link-creator.js b/keyserver/src/creators/invite-link-creator.js
--- a/keyserver/src/creators/invite-link-creator.js
+++ b/keyserver/src/creators/invite-link-creator.js
@@ -59,40 +59,61 @@
threadPermissions.MANAGE_INVITE_LINKS,
);
const existingPrimaryLinksPromise = fetchPrimaryInviteLinks(viewer);
+ const threadIDs = new Set([request.communityID]);
+ if (request.threadID) {
+ threadIDs.add(request.threadID);
+ }
const fetchThreadInfoPromise = fetchServerThreadInfos({
- threadID: request.communityID,
+ threadIDs,
});
const blobDownloadPromise = getInviteLinkBlob(request.name);
+ const canManageThreadLinksPromise = request.threadID
+ ? checkThreadPermission(
+ viewer,
+ request.threadID,
+ threadPermissions.MANAGE_INVITE_LINKS,
+ )
+ : false;
const [
hasPermission,
existingPrimaryLinks,
{ threadInfos },
blobDownloadResult,
+ canManageThreadLinks,
] = await Promise.all([
permissionPromise,
existingPrimaryLinksPromise,
fetchThreadInfoPromise,
blobDownloadPromise,
+ canManageThreadLinksPromise,
]);
- if (!hasPermission) {
+ if (!hasPermission || (request.threadID && !canManageThreadLinks)) {
throw new ServerError('invalid_credentials');
}
if (blobDownloadResult.found) {
throw new ServerError('already_in_use');
}
- const threadInfo = threadInfos[request.communityID];
- if (!threadInfo) {
- throw new ServerError('invalid_parameters');
- }
- const defaultRoleID = Object.keys(threadInfo.roles).find(
- roleID => threadInfo.roles[roleID].isDefault,
- );
- if (!defaultRoleID) {
- throw new ServerError('invalid_parameters');
+
+ const defaultRoleIDs: { [string]: string } = {};
+ for (const threadID of threadIDs) {
+ const threadInfo = threadInfos[threadID];
+ if (!threadInfo) {
+ throw new ServerError('invalid_parameters');
+ }
+ const defaultRoleID = Object.keys(threadInfo.roles).find(
+ roleID => threadInfo.roles[roleID].isDefault,
+ );
+ if (!defaultRoleID) {
+ throw new ServerError('invalid_parameters');
+ }
+ defaultRoleIDs[threadID] = defaultRoleID;
}
const existingPrimaryLink = existingPrimaryLinks.find(
- link => link.communityID === request.communityID && link.primary,
+ link =>
+ link.communityID === request.communityID &&
+ link.primary &&
+ (request.threadID ? link.threadID === request.threadID : !link.threadID),
);
const blobHolder = uuid.v4();
@@ -109,8 +130,14 @@
const query = SQL`
UPDATE invite_links
SET name = ${request.name}, blob_holder = ${blobHolder}
- WHERE \`primary\` = 1 AND community = ${request.communityID}
+ WHERE \`primary\` = 1 AND
+ community = ${request.communityID}
`;
+ if (request.threadID) {
+ query.append(SQL`AND thread = ${request.threadID}`);
+ } else {
+ query.append(SQL`AND thread IS NULL`);
+ }
try {
await dbQuery(query);
const holder = existingPrimaryLink.blobHolder;
@@ -139,7 +166,7 @@
return {
name: request.name,
primary: true,
- role: defaultRoleID,
+ role: defaultRoleIDs[request.communityID],
communityID: request.communityID,
expirationTime: null,
limitOfUses: null,
@@ -154,19 +181,28 @@
request.name,
true,
request.communityID,
- defaultRoleID,
+ defaultRoleIDs[request.communityID],
blobHolder,
+ request.threadID ?? null,
+ request.threadID ? defaultRoleIDs[request.threadID] : null,
];
const createLinkQuery = SQL`
- INSERT INTO invite_links(id, name, \`primary\`, community, role, blob_holder)
+ INSERT INTO invite_links(id, name, \`primary\`, community, role,
+ blob_holder, thread, thread_role)
SELECT ${row}
WHERE NOT EXISTS (
SELECT i.id
FROM invite_links i
WHERE i.\`primary\` = 1 AND i.community = ${request.communityID}
- )
`;
+ if (request.threadID) {
+ createLinkQuery.append(SQL`AND thread = ${request.threadID}`);
+ } else {
+ createLinkQuery.append(SQL`AND thread IS NULL`);
+ }
+ createLinkQuery.append(SQL`)`);
+
let result = null;
const deleteIDs = SQL`
DELETE FROM ids
@@ -208,7 +244,7 @@
return {
name: request.name,
primary: true,
- role: defaultRoleID,
+ role: defaultRoleIDs[request.communityID],
communityID: request.communityID,
expirationTime: null,
limitOfUses: null,
diff --git a/keyserver/src/fetchers/link-fetchers.js b/keyserver/src/fetchers/link-fetchers.js
--- a/keyserver/src/fetchers/link-fetchers.js
+++ b/keyserver/src/fetchers/link-fetchers.js
@@ -64,22 +64,33 @@
const query = SQL`
SELECT i.name, i.role, i.community, i.expiration_time AS expirationTime,
i.limit_of_uses AS limitOfUses, i.number_of_uses AS numberOfUses,
- i.\`primary\`, blob_holder AS blobHolder
+ i.\`primary\`, i.blob_holder AS blobHolder, i.thread,
+ i.thread_role AS threadRole
FROM invite_links i
`;
query.append(condition);
const [result] = await dbQuery(query);
- return result.map(row => ({
- name: row.name,
- primary: row.primary === 1,
- role: row.role.toString(),
- communityID: row.community.toString(),
- expirationTime: row.expirationTime,
- limitOfUses: row.limitOfUses,
- numberOfUses: row.numberOfUses,
- blobHolder: row.blobHolder,
- }));
+ return result.map(row => {
+ const link = {
+ name: row.name,
+ primary: row.primary === 1,
+ role: row.role.toString(),
+ communityID: row.community.toString(),
+ expirationTime: row.expirationTime,
+ limitOfUses: row.limitOfUses,
+ numberOfUses: row.numberOfUses,
+ blobHolder: row.blobHolder,
+ };
+ if (row.thread && row.threadRole) {
+ return {
+ ...link,
+ threadID: row.thread.toString(),
+ threadRole: row.threadRole.toString(),
+ };
+ }
+ return link;
+ });
}
function fetchPrimaryInviteLinks(
diff --git a/keyserver/src/responders/link-responders.js b/keyserver/src/responders/link-responders.js
--- a/keyserver/src/responders/link-responders.js
+++ b/keyserver/src/responders/link-responders.js
@@ -48,6 +48,7 @@
tShape<CreateOrUpdatePublicLinkRequest>({
name: t.String,
communityID: tID,
+ threadID: t.maybe(tID),
});
async function createOrUpdatePublicLinkResponder(
diff --git a/lib/types/link-types.js b/lib/types/link-types.js
--- a/lib/types/link-types.js
+++ b/lib/types/link-types.js
@@ -28,6 +28,8 @@
+expirationTime: ?number,
+limitOfUses: ?number,
+numberOfUses: number,
+ +threadID?: string,
+ +threadRole?: string,
};
export type InviteLinkWithHolder = $ReadOnly<{
@@ -43,6 +45,8 @@
expirationTime: t.maybe(t.Number),
limitOfUses: t.maybe(t.Number),
numberOfUses: t.Number,
+ threadID: t.maybe(tID),
+ threadRole: t.maybe(tID),
});
export type FetchInviteLinksResponse = {
@@ -73,6 +77,7 @@
export type CreateOrUpdatePublicLinkRequest = {
+name: string,
+communityID: string,
+ +threadID?: string,
};
export type DisableInviteLinkRequest = {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 25, 2:30 PM (19 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2579712
Default Alt Text
D12354.id41125.diff (7 KB)
Attached To
Mode
D12354: [keyserver] Extend link creation logic to support invite links to threads
Attached
Detach File
Event Timeline
Log In to Comment