Changeset View
Changeset View
Standalone View
Standalone View
keyserver/src/responders/thread-responders.js
// @flow | // @flow | ||||
import t from 'tcomb'; | import t from 'tcomb'; | ||||
import type { TUnion } from 'tcomb'; | import type { TInterface, TUnion } from 'tcomb'; | ||||
import { rawEntryInfoValidator } from 'lib/types/entry-types.js'; | |||||
import { mediaValidator } from 'lib/types/media-types.js'; | |||||
import { | |||||
rawMessageInfoValidator, | |||||
messageTruncationStatusesValidator, | |||||
} from 'lib/types/message-types.js'; | |||||
import { | import { | ||||
type ThreadDeletionRequest, | type ThreadDeletionRequest, | ||||
type RoleChangeRequest, | type RoleChangeRequest, | ||||
type ChangeThreadSettingsResult, | type ChangeThreadSettingsResult, | ||||
type RemoveMembersRequest, | type RemoveMembersRequest, | ||||
type LeaveThreadRequest, | type LeaveThreadRequest, | ||||
type LeaveThreadResult, | type LeaveThreadResult, | ||||
type UpdateThreadRequest, | type UpdateThreadRequest, | ||||
type ServerNewThreadRequest, | type ServerNewThreadRequest, | ||||
type NewThreadResponse, | type NewThreadResponse, | ||||
type ServerThreadJoinRequest, | type ServerThreadJoinRequest, | ||||
type ThreadJoinResult, | type ThreadJoinResult, | ||||
type ThreadFetchMediaResult, | type ThreadFetchMediaResult, | ||||
type ThreadFetchMediaRequest, | type ThreadFetchMediaRequest, | ||||
type ToggleMessagePinRequest, | type ToggleMessagePinRequest, | ||||
type ToggleMessagePinResult, | type ToggleMessagePinResult, | ||||
threadTypes, | threadTypes, | ||||
rawThreadInfoValidator, | |||||
} from 'lib/types/thread-types.js'; | } from 'lib/types/thread-types.js'; | ||||
import { serverUpdateInfoValidator } from 'lib/types/update-types.js'; | |||||
import { userInfosValidator } from 'lib/types/user-types.js'; | |||||
import { updateUserAvatarRequestValidator } from 'lib/utils/avatar-utils.js'; | import { updateUserAvatarRequestValidator } from 'lib/utils/avatar-utils.js'; | ||||
import { values } from 'lib/utils/objects.js'; | import { values } from 'lib/utils/objects.js'; | ||||
import { | import { | ||||
tShape, | tShape, | ||||
tNumEnum, | tNumEnum, | ||||
tColor, | tColor, | ||||
tPassword, | tPassword, | ||||
tID, | |||||
} from 'lib/utils/validation-utils.js'; | } from 'lib/utils/validation-utils.js'; | ||||
import { | import { | ||||
entryQueryInputValidator, | entryQueryInputValidator, | ||||
verifyCalendarQueryThreadIDs, | verifyCalendarQueryThreadIDs, | ||||
} from './entry-responders.js'; | } from './entry-responders.js'; | ||||
import { createThread } from '../creators/thread-creator.js'; | import { createThread } from '../creators/thread-creator.js'; | ||||
import { deleteThread } from '../deleters/thread-deleters.js'; | import { deleteThread } from '../deleters/thread-deleters.js'; | ||||
Show All 9 Lines | |||||
} from '../updaters/thread-updaters.js'; | } from '../updaters/thread-updaters.js'; | ||||
import { validateInput } from '../utils/validation-utils.js'; | import { validateInput } from '../utils/validation-utils.js'; | ||||
const threadDeletionRequestInputValidator = tShape({ | const threadDeletionRequestInputValidator = tShape({ | ||||
threadID: t.String, | threadID: t.String, | ||||
accountPassword: t.maybe(tPassword), | accountPassword: t.maybe(tPassword), | ||||
}); | }); | ||||
export const leaveThreadResultValidator: TInterface<LeaveThreadResult> = | |||||
tShape<LeaveThreadResult>({ | |||||
threadInfos: t.maybe(t.dict(tID, rawThreadInfoValidator)), | |||||
updatesResult: tShape({ | |||||
newUpdates: t.list(serverUpdateInfoValidator), | |||||
}), | |||||
}); | |||||
async function threadDeletionResponder( | async function threadDeletionResponder( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
input: any, | input: any, | ||||
): Promise<LeaveThreadResult> { | ): Promise<LeaveThreadResult> { | ||||
const request: ThreadDeletionRequest = input; | const request: ThreadDeletionRequest = input; | ||||
await validateInput(viewer, threadDeletionRequestInputValidator, request); | await validateInput(viewer, threadDeletionRequestInputValidator, request); | ||||
return await deleteThread(viewer, request); | return await deleteThread(viewer, request); | ||||
} | } | ||||
const roleChangeRequestInputValidator = tShape({ | const roleChangeRequestInputValidator = tShape({ | ||||
threadID: t.String, | threadID: t.String, | ||||
memberIDs: t.list(t.String), | memberIDs: t.list(t.String), | ||||
role: t.refinement(t.String, str => { | role: t.refinement(t.String, str => { | ||||
const int = parseInt(str, 10); | const int = parseInt(str, 10); | ||||
return String(int) === str && int > 0; | return String(int) === str && int > 0; | ||||
}), | }), | ||||
}); | }); | ||||
export const changeThreadSettingsResultValidator: TInterface<ChangeThreadSettingsResult> = | |||||
tShape<ChangeThreadSettingsResult>({ | |||||
newMessageInfos: t.list(rawMessageInfoValidator), | |||||
threadInfo: t.maybe(rawThreadInfoValidator), | |||||
threadInfos: t.maybe(t.dict(tID, rawThreadInfoValidator)), | |||||
updatesResult: tShape({ | |||||
newUpdates: t.list(serverUpdateInfoValidator), | |||||
}), | |||||
}); | |||||
async function roleUpdateResponder( | async function roleUpdateResponder( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
input: any, | input: any, | ||||
): Promise<ChangeThreadSettingsResult> { | ): Promise<ChangeThreadSettingsResult> { | ||||
const request: RoleChangeRequest = input; | const request: RoleChangeRequest = input; | ||||
await validateInput(viewer, roleChangeRequestInputValidator, request); | await validateInput(viewer, roleChangeRequestInputValidator, request); | ||||
return await updateRole(viewer, request); | return await updateRole(viewer, request); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | type: tNumEnum([ | ||||
threadTypes.COMMUNITY_OPEN_SUBTHREAD, | threadTypes.COMMUNITY_OPEN_SUBTHREAD, | ||||
threadTypes.COMMUNITY_SECRET_SUBTHREAD, | threadTypes.COMMUNITY_SECRET_SUBTHREAD, | ||||
threadTypes.PERSONAL, | threadTypes.PERSONAL, | ||||
threadTypes.LOCAL, | threadTypes.LOCAL, | ||||
]), | ]), | ||||
...threadRequestValidationShape, | ...threadRequestValidationShape, | ||||
}), | }), | ||||
]); | ]); | ||||
export const newThreadResponseValidator: TInterface<NewThreadResponse> = | |||||
tShape<NewThreadResponse>({ | |||||
updatesResult: tShape({ | |||||
newUpdates: t.list(serverUpdateInfoValidator), | |||||
}), | |||||
newMessageInfos: t.list(rawMessageInfoValidator), | |||||
newThreadInfo: t.maybe(rawThreadInfoValidator), | |||||
userInfos: userInfosValidator, | |||||
newThreadID: t.maybe(tID), | |||||
}); | |||||
async function threadCreationResponder( | async function threadCreationResponder( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
input: any, | input: any, | ||||
): Promise<NewThreadResponse> { | ): Promise<NewThreadResponse> { | ||||
const request: ServerNewThreadRequest = input; | const request: ServerNewThreadRequest = input; | ||||
await validateInput(viewer, newThreadRequestInputValidator, request); | await validateInput(viewer, newThreadRequestInputValidator, request); | ||||
return await createThread(viewer, request, { | return await createThread(viewer, request, { | ||||
silentlyFailMembers: request.type === threadTypes.SIDEBAR, | silentlyFailMembers: request.type === threadTypes.SIDEBAR, | ||||
}); | }); | ||||
} | } | ||||
const joinThreadRequestInputValidator = tShape({ | const joinThreadRequestInputValidator = tShape({ | ||||
threadID: t.String, | threadID: t.String, | ||||
calendarQuery: t.maybe(entryQueryInputValidator), | calendarQuery: t.maybe(entryQueryInputValidator), | ||||
inviteLinkSecret: t.maybe(t.String), | inviteLinkSecret: t.maybe(t.String), | ||||
}); | }); | ||||
export const threadJoinResultValidator: TInterface<ThreadJoinResult> = | |||||
tShape<ThreadJoinResult>({ | |||||
threadInfos: t.maybe(t.dict(tID, rawThreadInfoValidator)), | |||||
updatesResult: tShape({ | |||||
newUpdates: t.list(serverUpdateInfoValidator), | |||||
}), | |||||
rawMessageInfos: t.list(rawMessageInfoValidator), | |||||
truncationStatuses: messageTruncationStatusesValidator, | |||||
userInfos: userInfosValidator, | |||||
rawEntryInfos: t.maybe(t.list(rawEntryInfoValidator)), | |||||
}); | |||||
async function threadJoinResponder( | async function threadJoinResponder( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
input: any, | input: any, | ||||
): Promise<ThreadJoinResult> { | ): Promise<ThreadJoinResult> { | ||||
const request: ServerThreadJoinRequest = input; | const request: ServerThreadJoinRequest = input; | ||||
await validateInput(viewer, joinThreadRequestInputValidator, request); | await validateInput(viewer, joinThreadRequestInputValidator, request); | ||||
if (request.calendarQuery) { | if (request.calendarQuery) { | ||||
await verifyCalendarQueryThreadIDs(request.calendarQuery); | await verifyCalendarQueryThreadIDs(request.calendarQuery); | ||||
} | } | ||||
return await joinThread(viewer, request); | return await joinThread(viewer, request); | ||||
} | } | ||||
const threadFetchMediaRequestInputValidator = tShape({ | const threadFetchMediaRequestInputValidator = tShape({ | ||||
threadID: t.String, | threadID: t.String, | ||||
limit: t.Number, | limit: t.Number, | ||||
offset: t.Number, | offset: t.Number, | ||||
}); | }); | ||||
export const threadFetchMediaResultValidator: TInterface<ThreadFetchMediaResult> = | |||||
tShape<ThreadFetchMediaResult>({ media: t.list(mediaValidator) }); | |||||
async function threadFetchMediaResponder( | async function threadFetchMediaResponder( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
input: any, | input: any, | ||||
): Promise<ThreadFetchMediaResult> { | ): Promise<ThreadFetchMediaResult> { | ||||
const request: ThreadFetchMediaRequest = input; | const request: ThreadFetchMediaRequest = input; | ||||
await validateInput(viewer, threadFetchMediaRequestInputValidator, request); | await validateInput(viewer, threadFetchMediaRequestInputValidator, request); | ||||
return await fetchMediaForThread(viewer, request); | return await fetchMediaForThread(viewer, request); | ||||
} | } | ||||
const toggleMessagePinRequestInputValidator = tShape({ | const toggleMessagePinRequestInputValidator = tShape({ | ||||
messageID: t.String, | messageID: t.String, | ||||
action: t.enums.of(['pin', 'unpin']), | action: t.enums.of(['pin', 'unpin']), | ||||
}); | }); | ||||
export const toggleMessagePinResultValidator: TInterface<ToggleMessagePinResult> = | |||||
tShape<ToggleMessagePinResult>({ | |||||
newMessageInfos: t.list(rawMessageInfoValidator), | |||||
threadID: tID, | |||||
}); | |||||
async function toggleMessagePinResponder( | async function toggleMessagePinResponder( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
input: any, | input: any, | ||||
): Promise<ToggleMessagePinResult> { | ): Promise<ToggleMessagePinResult> { | ||||
const request: ToggleMessagePinRequest = input; | const request: ToggleMessagePinRequest = input; | ||||
await validateInput(viewer, toggleMessagePinRequestInputValidator, request); | await validateInput(viewer, toggleMessagePinRequestInputValidator, request); | ||||
return await toggleMessagePinForThread(viewer, request); | return await toggleMessagePinForThread(viewer, request); | ||||
} | } | ||||
Show All 13 Lines |