From 458fdd4938aaf25dfecd12669b51ec0432547306 Mon Sep 17 00:00:00 2001 From: Michal Iskierko Date: Fri, 10 May 2024 16:33:18 +0200 Subject: [PATCH] feat(@desktop/permissions): Use permission-check light functions Light functions are used first in order to reduce the number of calls to blockchain. If the permission is not met (user is not a member of community/channel member list), then normal permissions-check function is used. Issue #14220 --- .../modules/main/chat_section/controller.nim | 4 ++-- src/app/modules/main/communities/controller.nim | 8 ++++---- src/app/modules/main/communities/module.nim | 4 ++-- src/app_service/service/chat/async_tasks.nim | 16 +++++++++++++--- src/app_service/service/chat/service.nim | 14 ++++++-------- .../service/community/async_tasks.nim | 13 ++++++++++++- src/app_service/service/community/service.nim | 15 ++++----------- src/backend/communities.nim | 17 +++++++++++++++++ 8 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index aee2ad6bc9..e3c3acceb8 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -92,14 +92,14 @@ proc getMySectionId*(self: Controller): string = proc asyncCheckPermissionsToJoin*(self: Controller) = if self.delegate.getPermissionsToJoinCheckOngoing(): return - self.communityService.asyncCheckPermissionsToJoin(self.getMySectionId(), addresses = @[]) + self.communityService.asyncCheckPermissionsToJoin(self.getMySectionId(), addresses = @[], fullCheck = false) self.delegate.setPermissionsToJoinCheckOngoing(true) proc asyncCheckAllChannelsPermissions*(self: Controller) = if self.allChannelsPermissionCheckOngoing: return self.allChannelsPermissionCheckOngoing = true - self.chatService.asyncCheckAllChannelsPermissions(self.getMySectionId(), addresses = @[]) + self.chatService.asyncCheckAllChannelsPermissions(self.getMySectionId(), addresses = @[], fullCheck = false) self.delegate.setChannelsPermissionsCheckOngoing(true) proc asyncCheckChannelPermissions*(self: Controller, communityId: string, chatId: string) = diff --git a/src/app/modules/main/communities/controller.nim b/src/app/modules/main/communities/controller.nim index dda6ffe94f..1a5f2da06b 100644 --- a/src/app/modules/main/communities/controller.nim +++ b/src/app/modules/main/communities/controller.nim @@ -404,11 +404,11 @@ proc authenticate*(self: Controller) = proc getCommunityPublicKeyFromPrivateKey*(self: Controller, communityPrivateKey: string): string = result = self.communityService.getCommunityPublicKeyFromPrivateKey(communityPrivateKey) -proc asyncCheckPermissionsToJoin*(self: Controller, communityId: string, addressesToShare: seq[string]) = - self.communityService.asyncCheckPermissionsToJoin(communityId, addressesToShare) +proc asyncCheckPermissionsToJoin*(self: Controller, communityId: string, addressesToShare: seq[string], fullCheck: bool) = + self.communityService.asyncCheckPermissionsToJoin(communityId, addressesToShare, fullCheck) -proc asyncCheckAllChannelsPermissions*(self: Controller, communityId: string, sharedAddresses: seq[string]) = - self.chatService.asyncCheckAllChannelsPermissions(communityId, sharedAddresses) +proc asyncCheckAllChannelsPermissions*(self: Controller, communityId: string, sharedAddresses: seq[string], fullCheck: bool) = + self.chatService.asyncCheckAllChannelsPermissions(communityId, sharedAddresses, fullCheck) proc asyncGetRevealedAccountsForMember*(self: Controller, communityId, memberPubkey: string) = self.communityService.asyncGetRevealedAccountsForMember(communityId, memberPubkey) diff --git a/src/app/modules/main/communities/module.nim b/src/app/modules/main/communities/module.nim index a7b71704ce..57453584fb 100644 --- a/src/app/modules/main/communities/module.nim +++ b/src/app/modules/main/communities/module.nim @@ -858,11 +858,11 @@ method getCommunityPublicKeyFromPrivateKey*(self: Module, communityPrivateKey: s method checkPermissions*(self: Module, communityId: string, sharedAddresses: seq[string]) = self.joiningCommunityDetails.communityIdForPermissions = communityId - self.controller.asyncCheckPermissionsToJoin(communityId, sharedAddresses) + self.controller.asyncCheckPermissionsToJoin(communityId, sharedAddresses, fullCheck = true) self.view.setJoinPermissionsCheckSuccessful(false) self.setCheckingPermissionToJoinInProgress(true) - self.controller.asyncCheckAllChannelsPermissions(communityId, sharedAddresses) + self.controller.asyncCheckAllChannelsPermissions(communityId, sharedAddresses, fullCheck = true) self.view.setChannelsPermissionsCheckSuccessful(false) self.checkingAllChannelPermissionsInProgress = true diff --git a/src/app_service/service/chat/async_tasks.nim b/src/app_service/service/chat/async_tasks.nim index 2ae50da443..c49becb4f8 100644 --- a/src/app_service/service/chat/async_tasks.nim +++ b/src/app_service/service/chat/async_tasks.nim @@ -28,7 +28,11 @@ type const asyncCheckChannelPermissionsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[AsyncCheckChannelPermissionsTaskArg](argEncoded) try: - let response = status_communities.checkCommunityChannelPermissions(arg.communityId, arg.chatId) + var response = status_communities.checkCommunityChannelPermissionsLight(arg.communityId, arg.chatId).result + let channelPermissions = response.toCheckChannelPermissionsResponseDto() + if not channelPermissions.viewOnlyPermissions.satisfied and not channelPermissions.viewAndPostPermissions.satisfied: + response = status_communities.checkCommunityChannelPermissions(arg.communityId, arg.chatId).result + arg.finish(%* { "response": response, "communityId": arg.communityId, @@ -46,13 +50,19 @@ type AsyncCheckAllChannelsPermissionsTaskArg = ref object of QObjectTaskArg communityId: string addresses: seq[string] + fullCheck: bool const asyncCheckAllChannelsPermissionsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[AsyncCheckAllChannelsPermissionsTaskArg](argEncoded) try: - let response = status_communities.checkAllCommunityChannelsPermissions(arg.communityId, arg.addresses) + var result = JsonNode() + if arg.fullCheck: + result = status_communities.checkAllCommunityChannelsPermissions(arg.communityId, arg.addresses).result + else: + result = status_communities.checkAllCommunityChannelsPermissionsLight(arg.communityId).result + let allChannelsPermissions = result.toCheckAllChannelsPermissionsResponseDto() arg.finish(%* { - "response": response, + "response": allChannelsPermissions, "communityId": arg.communityId, "error": "", }) diff --git a/src/app_service/service/chat/service.nim b/src/app_service/service/chat/service.nim index 24725a3864..2218e96166 100644 --- a/src/app_service/service/chat/service.nim +++ b/src/app_service/service/chat/service.nim @@ -680,6 +680,7 @@ QtObject: communityId: communityId, chatId: chatId ) + self.threadpool.start(arg) proc onAsyncCheckChannelPermissionsDone*(self: Service, rpcResponse: string) {.slot.} = @@ -692,21 +693,22 @@ QtObject: let communityId = rpcResponseObj{"communityId"}.getStr() let chatId = rpcResponseObj{"chatId"}.getStr() - let checkChannelPermissionsResponse = rpcResponseObj["response"]["result"].toCheckChannelPermissionsResponseDto() - + let checkChannelPermissionsResponse = rpcResponseObj["response"].toCheckChannelPermissionsResponseDto() self.events.emit(SIGNAL_CHECK_CHANNEL_PERMISSIONS_RESPONSE, CheckChannelPermissionsResponseArgs(communityId: communityId, chatId: chatId, checkChannelPermissionsResponse: checkChannelPermissionsResponse)) except Exception as e: let errMsg = e.msg error "error checking all channel permissions: ", errMsg - proc asyncCheckAllChannelsPermissions*(self: Service, communityId: string, addresses: seq[string]) = + proc asyncCheckAllChannelsPermissions*(self: Service, communityId: string, addresses: seq[string], fullCheck: bool) = let arg = AsyncCheckAllChannelsPermissionsTaskArg( tptr: cast[ByteAddress](asyncCheckAllChannelsPermissionsTask), vptr: cast[ByteAddress](self.vptr), slot: "onAsyncCheckAllChannelsPermissionsDone", communityId: communityId, addresses: addresses, + fullCheck: fullCheck ) + self.threadpool.start(arg) proc onAsyncCheckAllChannelsPermissionsDone*(self: Service, rpcResponse: string) {.slot.} = @@ -716,11 +718,7 @@ QtObject: if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "": raise newException(CatchableError, rpcResponseObj["error"].getStr) - if rpcResponseObj["response"]{"error"}.kind != JNull: - let error = Json.decode(rpcResponseObj["response"]["error"].getStr, RpcError) - raise newException(RpcException, error.message) - - let checkAllChannelsPermissionsResponse = rpcResponseObj["response"]["result"].toCheckAllChannelsPermissionsResponseDto() + let checkAllChannelsPermissionsResponse = rpcResponseObj["response"].toCheckAllChannelsPermissionsResponseDto() # TODO save it self.events.emit(SIGNAL_CHECK_ALL_CHANNELS_PERMISSIONS_RESPONSE, CheckAllChannelsPermissionsResponseArgs(communityId: communityId, checkAllChannelsPermissionsResponse: checkAllChannelsPermissionsResponse)) except Exception as e: diff --git a/src/app_service/service/community/async_tasks.nim b/src/app_service/service/community/async_tasks.nim index 0acaefd0b6..73c4a67a2c 100644 --- a/src/app_service/service/community/async_tasks.nim +++ b/src/app_service/service/community/async_tasks.nim @@ -209,11 +209,22 @@ type AsyncCheckPermissionsToJoinTaskArg = ref object of QObjectTaskArg communityId: string addresses: seq[string] + fullCheck: bool const asyncCheckPermissionsToJoinTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[AsyncCheckPermissionsToJoinTaskArg](argEncoded) try: - let response = status_go.checkPermissionsToJoinCommunity(arg.communityId, arg.addresses) + var response = JsonNode() + if not arg.fullCheck: + let hasPermissionToJoin = status_go.checkPermissionsToJoinCommunityLight(arg.communityId, arg.addresses).result.getBool + if hasPermissionToJoin: + let permissionToJoin = CheckPermissionsToJoinResponseDto(satisfied: true) + response = %permissionToJoin + else: + response = status_go.checkPermissionsToJoinCommunity(arg.communityId, arg.addresses).result + else: + response = status_go.checkPermissionsToJoinCommunity(arg.communityId, arg.addresses).result + arg.finish(%* { "response": response, "communityId": arg.communityId, diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim index 2ac9df93af..72be14b962 100644 --- a/src/app_service/service/community/service.nim +++ b/src/app_service/service/community/service.nim @@ -242,10 +242,6 @@ const SIGNAL_ACCEPT_REQUEST_TO_JOIN_LOADING* = "acceptRequestToJoinLoading" const SIGNAL_ACCEPT_REQUEST_TO_JOIN_FAILED* = "acceptRequestToJoinFailed" const SIGNAL_ACCEPT_REQUEST_TO_JOIN_FAILED_NO_PERMISSION* = "acceptRequestToJoinFailedNoPermission" -const TOKEN_PERMISSIONS_ADDED = "tokenPermissionsAdded" -const TOKEN_PERMISSIONS_MODIFIED = "tokenPermissionsModified" -const TOKEN_PERMISSIONS_REMOVED = "tokenPermissionsRemoved" - const SIGNAL_CHECK_PERMISSIONS_TO_JOIN_RESPONSE* = "checkPermissionsToJoinResponse" const SIGNAL_CHECK_PERMISSIONS_TO_JOIN_FAILED* = "checkPermissionsToJoinFailed" @@ -1617,13 +1613,14 @@ QtObject: self.events.emit(SIGNAL_COMMUNITY_DATA_IMPORTED, CommunityArgs(community: community)) self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community])) - proc asyncCheckPermissionsToJoin*(self: Service, communityId: string, addresses: seq[string]) = + proc asyncCheckPermissionsToJoin*(self: Service, communityId: string, addresses: seq[string], fullCheck: bool) = let arg = AsyncCheckPermissionsToJoinTaskArg( tptr: cast[ByteAddress](asyncCheckPermissionsToJoinTask), vptr: cast[ByteAddress](self.vptr), slot: "onAsyncCheckPermissionsToJoinDone", communityId: communityId, - addresses: addresses + addresses: addresses, + fullCheck: fullCheck ) self.threadpool.start(arg) @@ -1634,11 +1631,7 @@ QtObject: if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "": raise newException(CatchableError, rpcResponseObj["error"].getStr) - if rpcResponseObj["response"]{"error"}.kind != JNull: - let error = Json.decode(rpcResponseObj["response"]["error"].getStr, RpcError) - raise newException(RpcException, error.message) - - let checkPermissionsToJoinResponse = rpcResponseObj["response"]["result"].toCheckPermissionsToJoinResponseDto + let checkPermissionsToJoinResponse = rpcResponseObj["response"].toCheckPermissionsToJoinResponseDto self.events.emit(SIGNAL_CHECK_PERMISSIONS_TO_JOIN_RESPONSE, CheckPermissionsToJoinResponseArgs( communityId: communityId, checkPermissionsToJoinResponse: checkPermissionsToJoinResponse diff --git a/src/backend/communities.nim b/src/backend/communities.nim index cf37bcc71c..3310d8cfd9 100644 --- a/src/backend/communities.nim +++ b/src/backend/communities.nim @@ -103,6 +103,12 @@ proc checkPermissionsToJoinCommunity*(communityId: string, addresses: seq[string "addresses": addresses }]) +proc checkPermissionsToJoinCommunityLight*(communityId: string, addresses: seq[string]): RpcResponse[JsonNode] = + result = callPrivateRPC("checkPermissionsToJoinCommunityLight".prefix, %*[{ + "communityId": communityId, + "addresses": addresses + }]) + proc reevaluateCommunityMembersPermissions*( communityId: string, ): RpcResponse[JsonNode] = @@ -122,6 +128,17 @@ proc checkAllCommunityChannelsPermissions*(communityId: string, addresses: seq[s "addresses": addresses, }]) +proc checkCommunityChannelPermissionsLight*(communityId: string, chatId: string): RpcResponse[JsonNode] = + result = callPrivateRPC("checkCommunityChannelPermissionsLight".prefix, %*[{ + "communityId": communityId, + "chatId": chatId + }]) + +proc checkAllCommunityChannelsPermissionsLight*(communityId: string): RpcResponse[JsonNode] = + result = callPrivateRPC("checkAllCommunityChannelsPermissionsLight".prefix, %*[{ + "communityId": communityId + }]) + proc allNonApprovedCommunitiesRequestsToJoin*(): RpcResponse[JsonNode] = result = callPrivateRPC("allNonApprovedCommunitiesRequestsToJoin".prefix)