diff --git a/keyserver/src/endpoints.js b/keyserver/src/endpoints.js --- a/keyserver/src/endpoints.js +++ b/keyserver/src/endpoints.js @@ -60,6 +60,7 @@ threadJoinResponder, toggleMessagePinResponder, roleModificationResponder, + roleDeletionResponder, } from './responders/thread-responders.js'; import { userSubscriptionUpdateResponder, @@ -144,6 +145,10 @@ responder: entryDeletionResponder, requiredPolicies: baseLegalPolicies, }, + delete_community_role: { + responder: roleDeletionResponder, + requiredPolicies: baseLegalPolicies, + }, delete_thread: { responder: threadDeletionResponder, requiredPolicies: baseLegalPolicies, diff --git a/keyserver/src/responders/thread-responders.js b/keyserver/src/responders/thread-responders.js --- a/keyserver/src/responders/thread-responders.js +++ b/keyserver/src/responders/thread-responders.js @@ -28,6 +28,8 @@ type ToggleMessagePinResult, type RoleModificationRequest, type RoleModificationResult, + type RoleDeletionRequest, + type RoleDeletionResult, rawThreadInfoValidator, } from 'lib/types/thread-types.js'; import { serverUpdateInfoValidator } from 'lib/types/update-types.js'; @@ -48,6 +50,7 @@ } from './entry-responders.js'; import { modifyRole } from '../creators/role-creator.js'; import { createThread } from '../creators/thread-creator.js'; +import { deleteRole } from '../deleters/role-deleters.js'; import { deleteThread } from '../deleters/thread-deleters.js'; import { fetchMediaForThread } from '../fetchers/upload-fetchers.js'; import type { Viewer } from '../session/viewer.js'; @@ -384,6 +387,36 @@ ); } +const roleDeletionRequestInputValidator = tShape({ + community: tID, + roleID: tID, +}); + +export const roleDeletionResultValidator: TInterface = + tShape({ + threadInfo: t.maybe(rawThreadInfoValidator), + updatesResult: tShape({ + newUpdates: t.list(serverUpdateInfoValidator), + }), + }); + +async function roleDeletionResponder( + viewer: Viewer, + input: mixed, +): Promise { + const request = await validateInput( + viewer, + roleDeletionRequestInputValidator, + input, + ); + const response = await deleteRole(viewer, request); + return validateOutput( + viewer.platformDetails, + roleDeletionResultValidator, + response, + ); +} + export { threadDeletionResponder, roleUpdateResponder, @@ -396,4 +429,5 @@ newThreadRequestInputValidator, toggleMessagePinResponder, roleModificationResponder, + roleDeletionResponder, }; diff --git a/lib/actions/thread-actions.js b/lib/actions/thread-actions.js --- a/lib/actions/thread-actions.js +++ b/lib/actions/thread-actions.js @@ -16,6 +16,8 @@ ToggleMessagePinResult, RoleModificationRequest, RoleModificationPayload, + RoleDeletionRequest, + RoleDeletionPayload, } from '../types/thread-types.js'; import type { CallServerEndpoint } from '../utils/call-server-endpoint.js'; import { values } from '../utils/objects.js'; @@ -212,6 +214,23 @@ }; }; +const deleteCommunityRoleActionTypes = Object.freeze({ + started: 'DELETE_COMMUNITY_ROLE_STARTED', + success: 'DELETE_COMMUNITY_ROLE_SUCCESS', + failed: 'DELETE_COMMUNITY_ROLE_FAILED', +}); +const deleteCommunityRole = + ( + callServerEndpoint: CallServerEndpoint, + ): ((request: RoleDeletionRequest) => Promise) => + async request => { + const response = await callServerEndpoint('delete_community_role', request); + return { + threadInfo: response.threadInfo, + updatesResult: response.updatesResult, + }; + }; + export { deleteThreadActionTypes, deleteThread, @@ -232,4 +251,6 @@ toggleMessagePin, modifyCommunityRoleActionTypes, modifyCommunityRole, + deleteCommunityRoleActionTypes, + deleteCommunityRole, }; diff --git a/lib/reducers/thread-reducer.js b/lib/reducers/thread-reducer.js --- a/lib/reducers/thread-reducer.js +++ b/lib/reducers/thread-reducer.js @@ -18,6 +18,7 @@ joinThreadActionTypes, leaveThreadActionTypes, modifyCommunityRoleActionTypes, + deleteCommunityRoleActionTypes, } from '../actions/thread-actions.js'; import { logOutActionTypes, @@ -222,7 +223,8 @@ action.type === incrementalStateSyncActionType || action.type === processUpdatesActionType || action.type === newThreadActionTypes.success || - action.type === modifyCommunityRoleActionTypes.success + action.type === modifyCommunityRoleActionTypes.success || + action.type === deleteCommunityRoleActionTypes.success ) { const { newUpdates } = action.payload.updatesResult; if (newUpdates.length === 0) { diff --git a/lib/types/endpoints.js b/lib/types/endpoints.js --- a/lib/types/endpoints.js +++ b/lib/types/endpoints.js @@ -57,6 +57,7 @@ CREATE_TEXT_MESSAGE: 'create_text_message', CREATE_THREAD: 'create_thread', DELETE_ENTRY: 'delete_entry', + DELETE_COMMUNITY_ROLE: 'delete_community_role', DELETE_THREAD: 'delete_thread', DELETE_UPLOAD: 'delete_upload', DISABLE_INVITE_LINK: 'disable_invite_link', diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js --- a/lib/types/redux-types.js +++ b/lib/types/redux-types.js @@ -109,6 +109,7 @@ ThreadJoinPayload, ToggleMessagePinResult, RoleModificationPayload, + RoleDeletionPayload, } from './thread-types.js'; import type { ClientUpdatesResultWithUserInfos } from './update-types.js'; import type { CurrentUserInfo, UserStore } from './user-types.js'; @@ -1185,6 +1186,22 @@ +error: true, +payload: Error, +loadingInfo: LoadingInfo, + } + | { + +type: 'DELETE_COMMUNITY_ROLE_STARTED', + +loadingInfo?: LoadingInfo, + +payload?: void, + } + | { + +type: 'DELETE_COMMUNITY_ROLE_SUCCESS', + +payload: RoleDeletionPayload, + +loadingInfo: LoadingInfo, + } + | { + +type: 'DELETE_COMMUNITY_ROLE_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, }; export type ActionPayload = ?(Object | Array<*> | $ReadOnlyArray<*> | string);