diff --git a/libretroshare/src/retroshare/rsgxscircles.h b/libretroshare/src/retroshare/rsgxscircles.h index 6ff854360..8b94bd829 100644 --- a/libretroshare/src/retroshare/rsgxscircles.h +++ b/libretroshare/src/retroshare/rsgxscircles.h @@ -301,7 +301,26 @@ public: const std::set& gxsIdMembers = std::set(), const std::set& localMembers = std::set() ) = 0; - /** + /** + * @brief Edit an existing circle + * @jsonapi{development} + * @param[in] circleId Optional storage to output created circle id + * @param[in] circleName String containing cirlce name + * @param[in] circleType Circle type + * @param[in] restrictedId Optional id of a pre-existent circle that see the + * created circle. Meaningful only if circleType == EXTERNAL, must be null + * in all other cases. + * @param[in] authorId Optional author of the circle. + * @param[in] gxsIdMembers GXS ids of the members of the circle. + * @param[in] localMembers PGP ids of the members if the circle. + * @return false if something failed, true otherwhise + */ + virtual bool editCircle( const RsGxsCircleId& circleId, const std::string& circleName, RsGxsCircleType circleType, + const RsGxsCircleId& restrictedId, + const RsGxsId& authorId, const std::set& gxsIdMembers, + const std::set& localMembers ) =0; + + /** * @brief Edit own existing circle * @jsonapi{development} * @param[inout] cData Circle data with modifications, storage for data diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc index b1a3bc5e2..43032db70 100644 --- a/libretroshare/src/services/p3gxscircles.cc +++ b/libretroshare/src/services/p3gxscircles.cc @@ -194,96 +194,111 @@ bool p3GxsCircles::createCircle( { // 1 - Check consistency of the request data - if(circleName.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " Circle name is empty" << std::endl; - return false; - } - - switch(circleType) - { - case RsGxsCircleType::PUBLIC: - if(!restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId - << " must be null with RsGxsCircleType::PUBLIC" - << std::endl; - return false; - } - break; - case RsGxsCircleType::EXTERNAL: - if(restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId can't be null " - << "with RsGxsCircleType::EXTERNAL" << std::endl; - return false; - } - break; - case RsGxsCircleType::NODES_GROUP: - if(localMembers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " localMembers can't be empty " - << "with RsGxsCircleType::NODES_GROUP" << std::endl; - return false; - } - break; - case RsGxsCircleType::LOCAL: - break; - case RsGxsCircleType::EXT_SELF: - if(!restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId - << " must be null with RsGxsCircleType::EXT_SELF" - << std::endl; - return false; - } - if(gxsIdMembers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " gxsIdMembers can't be empty " - << "with RsGxsCircleType::EXT_SELF" << std::endl; - return false; - } - break; - case RsGxsCircleType::YOUR_EYES_ONLY: - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Invalid circle type: " - << static_cast(circleType) << std::endl; - return false; - } + if(!checkCircleParamConsistency(circleName,circleType,restrictedId,authorId,gxsIdMembers,localMembers)) + { + RsErr() << __PRETTY_FUNCTION__ << " Circle name is empty" << std::endl; + return false; + } // 2 - Create the actual request - RsGxsCircleGroup cData; - cData.mMeta.mGroupName = circleName; - cData.mMeta.mAuthorId = authorId; - cData.mMeta.mCircleType = static_cast(circleType); - cData.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - cData.mMeta.mCircleId = restrictedId; - cData.mLocalFriends = localMembers; - cData.mInvitedMembers = gxsIdMembers; + RsGxsCircleGroup cData; + cData.mMeta.mGroupName = circleName; + cData.mMeta.mAuthorId = authorId; + cData.mMeta.mCircleType = static_cast(circleType); + cData.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; + cData.mMeta.mCircleId = restrictedId; + cData.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ | GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; + cData.mLocalFriends = localMembers; + cData.mInvitedMembers = gxsIdMembers; + // 3 - Send it and wait, for a sync response. - uint32_t token; - createGroup(token, cData); + uint32_t token; + createGroup(token, cData); - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; - return false; - } + if(waitToken(token) != RsTokenService::COMPLETE) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; + return false; + } - if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting created" << " group data." << std::endl; - return false; - } + if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting created" << " group data." << std::endl; + return false; + } - circleId = static_cast(cData.mMeta.mGroupId); - return true; + circleId = static_cast(cData.mMeta.mGroupId); + return true; }; +bool p3GxsCircles::checkCircleParamConsistency( const std::string& circleName, RsGxsCircleType circleType, + const RsGxsCircleId& restrictedId, + const RsGxsId& authorId, const std::set& gxsIdMembers, + const std::set& localMembers ) const +{ + if(circleName.empty()) + { + RsErr() << __PRETTY_FUNCTION__ << " Circle name is empty" << std::endl; + return false; + } + + switch(circleType) + { + case RsGxsCircleType::PUBLIC: + if(!restrictedId.isNull()) + { + RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId + << " must be null with RsGxsCircleType::PUBLIC" + << std::endl; + return false; + } + break; + case RsGxsCircleType::EXTERNAL: + if(restrictedId.isNull()) + { + RsErr() << __PRETTY_FUNCTION__ << " restrictedId can't be null " + << "with RsGxsCircleType::EXTERNAL" << std::endl; + return false; + } + break; + case RsGxsCircleType::NODES_GROUP: + if(localMembers.empty()) + { + RsErr() << __PRETTY_FUNCTION__ << " localMembers can't be empty " + << "with RsGxsCircleType::NODES_GROUP" << std::endl; + return false; + } + break; + case RsGxsCircleType::LOCAL: + break; + case RsGxsCircleType::EXT_SELF: + if(!restrictedId.isNull()) + { + RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId + << " must be null with RsGxsCircleType::EXT_SELF" + << std::endl; + return false; + } + if(gxsIdMembers.empty()) + { + RsErr() << __PRETTY_FUNCTION__ << " gxsIdMembers can't be empty " + << "with RsGxsCircleType::EXT_SELF" << std::endl; + return false; + } + break; + case RsGxsCircleType::YOUR_EYES_ONLY: + break; + default: + RsErr() << __PRETTY_FUNCTION__ << " Invalid circle type: " + << static_cast(circleType) << std::endl; + return false; + } + return true; +} + bool p3GxsCircles::editCircle(RsGxsCircleGroup& cData) { uint32_t token; @@ -306,6 +321,52 @@ bool p3GxsCircles::editCircle(RsGxsCircleGroup& cData) return true; } +bool p3GxsCircles::editCircle(const RsGxsCircleId &circleId, const std::string& circleName, RsGxsCircleType circleType, const RsGxsCircleId& restrictedId, + const RsGxsId& authorId, const std::set& gxsIdMembers, + const std::set& localMembers ) +{ + // 1 - Check consistency of the request data + + if(!checkCircleParamConsistency(circleName,circleType,restrictedId,authorId,gxsIdMembers,localMembers)) + { + RsErr() << __PRETTY_FUNCTION__ << " Circle data is not consistent." << std::endl; + return false; + } + + // 2 - Create the actual request + + RsGxsCircleGroup cData; + cData.mMeta.mGroupId = RsGxsGroupId(circleId); + cData.mMeta.mGroupName = circleName; + cData.mMeta.mAuthorId = authorId; + cData.mMeta.mCircleType = static_cast(circleType); + cData.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; + cData.mMeta.mCircleId = restrictedId; + cData.mLocalFriends = localMembers; + cData.mInvitedMembers = gxsIdMembers; + + // 3 - Send it and wait, for a sync response. + + uint32_t token; + updateGroup(token, cData); + + if(waitToken(token) != RsTokenService::COMPLETE) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." + << std::endl; + return false; + } + + if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated" + << " group data." << std::endl; + return false; + } + + return true; +}; + bool p3GxsCircles::getCirclesSummaries(std::list& circles) { uint32_t token; diff --git a/libretroshare/src/services/p3gxscircles.h b/libretroshare/src/services/p3gxscircles.h index a98e09184..3ff041ce1 100644 --- a/libretroshare/src/services/p3gxscircles.h +++ b/libretroshare/src/services/p3gxscircles.h @@ -227,7 +227,12 @@ public: const std::set& localMembers = std::set() ) override; - /// @see RsGxsCircles + bool editCircle( const RsGxsCircleId& circleId,const std::string& circleName, RsGxsCircleType circleType, + const RsGxsCircleId& restrictedId, + const RsGxsId& authorId, const std::set& gxsIdMembers, + const std::set& localMembers ) override; + + /// @see RsGxsCircles bool editCircle(RsGxsCircleGroup& cData) override; /// @see RsGxsCircles @@ -303,6 +308,10 @@ public: virtual void service_tick() override; protected: + bool checkCircleParamConsistency( const std::string& circleName, RsGxsCircleType circleType, + const RsGxsCircleId& restrictedId, + const RsGxsId& authorId, const std::set& gxsIdMembers, + const std::set& localMembers ) const ; // overloads p3Config virtual bool saveList(bool &cleanup, std::list&saveList) override; diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index d34f406a6..d35d3afe0 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -1139,6 +1139,7 @@ bool p3IdService::updateIdentity( const RsGxsId& id, const std::string& name, co goto LabelUpdateIdentityCleanup; } } + mKeyCache.erase(id); if(!updateGroup(token, group)) { @@ -1154,6 +1155,9 @@ bool p3IdService::updateIdentity( const RsGxsId& id, const std::string& name, co goto LabelUpdateIdentityCleanup; } + // clean the Identity cache as well + cache_request_load(id); + LabelUpdateIdentityCleanup: if(!pseudonimous && !pgpPassword.empty()) rsNotify->clearPgpPassphrase();