diff --git a/src/Socialbox/Classes/StandardMethods/EncryptionChannel/EncryptionDeclineChannel.php b/src/Socialbox/Classes/StandardMethods/EncryptionChannel/EncryptionDeclineChannel.php new file mode 100644 index 0000000..d99c483 --- /dev/null +++ b/src/Socialbox/Classes/StandardMethods/EncryptionChannel/EncryptionDeclineChannel.php @@ -0,0 +1,187 @@ +isExternal()) + { + return self::handleExternal($request, $rpcRequest); + } + + return self::handleInternal($request, $rpcRequest); + } + catch (DatabaseOperationException $e) + { + throw new StandardRpcException('An error occurred while checking the request type', StandardError::INTERNAL_SERVER_ERROR, $e); + } + } + + /** + * @param ClientRequest $request + * @param RpcRequest $rpcRequest + * @return SerializableInterface|null + * @throws StandardRpcException + */ + private static function handleInternal(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface + { + if(!$rpcRequest->containsParameter('channel_uuid')) + { + throw new MissingRpcArgumentException('channel_uuid'); + } + elseif(!Validator::validateUuid($rpcRequest->getParameter('channel_uuid'))) + { + throw new InvalidRpcArgumentException('channel_uuid', 'The given channel uuid is not a valid UUID V4'); + } + + try + { + $receivingPeer = $request->getPeer(); + $encryptionChannel = EncryptionChannelManager::getChannel($rpcRequest->getParameter('channel_uuid')); + } + catch(DatabaseOperationException $e) + { + throw new StandardRpcException('There was an error while trying to obtain the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); + } + + if($encryptionChannel === null) + { + return $rpcRequest->produceError(StandardError::NOT_FOUND, 'The requested encryption channel was not found'); + } + elseif($encryptionChannel->getReceivingPeerAddress()->getAddress() !== $receivingPeer->getAddress()) + { + return $rpcRequest->produceError(StandardError::UNAUTHORIZED, 'The requested encryption channel is not accessible'); + } + elseif($encryptionChannel->getStatus() !== EncryptionChannelStatus::AWAITING_RECEIVER) + { + return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The encryption channel is not awaiting the receiver'); + } + + if($encryptionChannel->getCallingPeerAddress()->isExternal()) + { + try + { + $rpcClient = Socialbox::getExternalSession($encryptionChannel->getCallingPeerAddress()->getDomain()); + $rpcClient->encryptionDeclineChannel( + channelUuid: $rpcRequest->getParameter('channel_uuid'), + identifiedAs: $receivingPeer->getAddress() + ); + } + catch(Exception $e) + { + try + { + EncryptionChannelManager::declineChannel($rpcRequest->getParameter('channel_uuid'), true); + } + catch(DatabaseOperationException $e) + { + Logger::getLogger()->error('Error declining channel as server', $e); + } + + if($e instanceof RpcException) + { + throw StandardRpcException::fromRpcException($e); + } + + throw new StandardRpcException('There was an error while trying to notify the external server of the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); + } + } + + try + { + EncryptionChannelManager::declineChannel( + channelUuid: $rpcRequest->getParameter('channel_uuid') + ); + } + catch (DatabaseOperationException $e) + { + throw new StandardRpcException('There was an error while trying to decline the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); + } + + return $rpcRequest->produceResponse(true); + } + + /** + * @param ClientRequest $request + * @param RpcRequest $rpcRequest + * @return SerializableInterface|null + * @throws StandardRpcException + */ + private static function handleExternal(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface + { + if($request->getIdentifyAs() === null) + { + return $rpcRequest->produceError(StandardError::BAD_REQUEST, 'Missing required header IdentifyAs'); + } + + if(!$rpcRequest->containsParameter('channel_uuid')) + { + throw new MissingRpcArgumentException('channel_uuid'); + } + elseif(!Validator::validateUuid($rpcRequest->getParameter('channel_uuid'))) + { + throw new InvalidRpcArgumentException('channel_uuid', 'The given channel uuid is not a valid UUID V4'); + } + + try + { + $receivingPeer = Socialbox::resolvePeer($request->getIdentifyAs()); + $encryptionChannel = EncryptionChannelManager::getChannel($rpcRequest->getParameter('channel_uuid')); + } + catch(DatabaseOperationException $e) + { + throw new StandardRpcException('There was an error while trying to obtain the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); + } + + if($encryptionChannel === null) + { + return $rpcRequest->produceError(StandardError::NOT_FOUND, 'The requested encryption channel was not found'); + } + elseif($encryptionChannel->getReceivingPeerAddress() !== $receivingPeer->getAddress()) + { + return $rpcRequest->produceError(StandardError::UNAUTHORIZED, 'The requested encryption channel is not accessible'); + } + elseif($encryptionChannel->getStatus() !== EncryptionChannelStatus::AWAITING_RECEIVER) + { + return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The encryption channel is not awaiting the receiver'); + } + + try + { + EncryptionChannelManager::declineChannel( + channelUuid: $rpcRequest->getParameter('channel_uuid') + ); + } + catch (DatabaseOperationException $e) + { + throw new StandardRpcException('There was an error while trying to decline the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e); + } + + return $rpcRequest->produceResponse(true); + } + } \ No newline at end of file