diff --git a/libretroshare/src/retroshare/rsgxschannels.h b/libretroshare/src/retroshare/rsgxschannels.h index 4d28cad22..8ed0dc285 100644 --- a/libretroshare/src/retroshare/rsgxschannels.h +++ b/libretroshare/src/retroshare/rsgxschannels.h @@ -107,6 +107,28 @@ public: */ virtual bool createChannel(RsGxsChannelGroup& channel) = 0; + /** + * @brief Create channel. Blocking API. + * @jsonapi{development} + * @param[in] name Name of the channel + * @param[in] description Description of the channel + * @param[in] image Thumbnail that is shown to advertise the channel. Possibly empty. + * @param[in] author_id GxsId of the contact author. For an anonymous channel, leave this to RsGxsId()="00000....0000" + * @param[in] circle_type Type of visibility restriction, among { GXS_CIRCLE_TYPE_PUBLIC, GXS_CIRCLE_TYPE_EXTERNAL, GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY, GXS_CIRCLE_TYPE_YOUR_EYES_ONLY } + * @param[in] circle_id Id of the circle (should be an external circle or GXS_CIRCLE_TYPE_EXTERNAL, a local friend group for GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY, GxsCircleId()="000....000" otherwise + * @param[out] channel_group_id Group id of the created channel, if command succeeds. + * @param[out] error_message Error messsage supplied when the channel creation fails. + * @return False on error, true otherwise. + */ + virtual bool createChannel(const std::string& name, + const std::string& description, + const RsGxsImage& image, + const RsGxsId& author_id, + uint32_t circle_type, + RsGxsCircleId& circle_id, + RsGxsGroupId& channel_group_id, + std::string& error_message)=0; + /** * @brief Add a comment on a post or on another comment * @jsonapi{development} diff --git a/libretroshare/src/retroshare/rsgxsflags.h b/libretroshare/src/retroshare/rsgxsflags.h index 7a737c74c..ff6f164c2 100644 --- a/libretroshare/src/retroshare/rsgxsflags.h +++ b/libretroshare/src/retroshare/rsgxsflags.h @@ -52,14 +52,15 @@ namespace GXS_SERV { static const uint32_t FLAG_AUTHOR_AUTHENTICATION_MASK = 0x0000ff00; static const uint32_t FLAG_AUTHOR_AUTHENTICATION_NONE = 0x00000000; static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG = 0x00000100; // Anti-spam feature. Allows to ask higher reputation to anonymous IDs - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200; - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400; + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200; // unused + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400; // ??? static const uint32_t FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES = 0x00000800; // not used anymore static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN = 0x00001000; // Anti-spam feature. Allows to ask higher reputation to unknown IDs and anonymous IDs + // These are *not used* static const uint32_t FLAG_GROUP_SIGN_PUBLISH_MASK = 0x000000ff; static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED = 0x00000001; - static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002; + static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002; // unused static const uint32_t FLAG_GROUP_SIGN_PUBLISH_THREADHEAD = 0x00000004; static const uint32_t FLAG_GROUP_SIGN_PUBLISH_NONEREQ = 0x00000008; diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc index 3f34b6438..f332dfbac 100644 --- a/libretroshare/src/services/p3gxschannels.cc +++ b/libretroshare/src/services/p3gxschannels.cc @@ -31,6 +31,7 @@ #include "retroshare/rsgxsflags.h" #include "retroshare/rsfiles.h" +#include "retroshare/rspeers.h" #include "rsserver/p3face.h" #include "retroshare/rsnotify.h" @@ -1055,6 +1056,116 @@ bool p3GxsChannels::getChannelContent( const RsGxsGroupId& channelId, return getPostData(token, posts, comments); } +bool p3GxsChannels::createChannel(const std::string& name, + const std::string& description, + const RsGxsImage& image, + const RsGxsId& author_id, + uint32_t circle_type, + RsGxsCircleId& circle_id, + RsGxsGroupId& channel_group_id, + std::string& error_message) +{ + // do some checks + + if( circle_type != GXS_CIRCLE_TYPE_PUBLIC + && circle_type != GXS_CIRCLE_TYPE_EXTERNAL + && circle_type != GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY + && circle_type != GXS_CIRCLE_TYPE_LOCAL + && circle_type != GXS_CIRCLE_TYPE_YOUR_EYES_ONLY ) + { + error_message = std::string("circle_type has a non allowed value") ; + return false ; + } + + switch(circle_type) + { + case GXS_CIRCLE_TYPE_EXTERNAL: + if(circle_id.isNull()) + { + error_message = std::string("circle_type is GXS_CIRCLE_TYPE_EXTERNAL but circle_id is null"); + return false ; + } + break; + + case GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY: + { + RsGroupInfo ginfo; + + if(!rsPeers->getGroupInfo(RsNodeGroupId(circle_id),ginfo)) + { + error_message = std::string("circle_type is GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY but circle_id is not set or does not correspond to a actual group of friends"); + return false; + } + } + break; + + default: + if(!circle_id.isNull()) + { + error_message = std::string("circle_type requires a null circle id, but a non null circle id (" + circle_id.toStdString() + ") was supplied"); + return false; + } + } + + // Create a consistent channel group meta from the information supplied + + RsGxsChannelGroup channel ; + + channel.mMeta.mGroupName = name ; + channel.mMeta.mAuthorId = author_id ; + channel.mMeta.mCircleType = circle_type ; + + channel.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ + | GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; + + channel.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; + + channel.mMeta.mCircleId.clear(); + channel.mMeta.mInternalCircle.clear(); + + if(circle_type == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) + channel.mMeta.mInternalCircle = circle_id; + else if(circle_type == GXS_CIRCLE_TYPE_EXTERNAL) + channel.mMeta.mCircleId = circle_id; + + // Create the channel + + channel.mDescription = description ; + channel.mImage = image ; + + uint32_t token; + if(!createGroup(token, channel)) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating group." + << std::endl; + return false; + } + + // wait for the group creation to complete. + + if(waitToken(token) != RsTokenService::COMPLETE) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." + << std::endl; + return false; + } + + if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta)) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " + << " group data." << std::endl; + return false; + } + + channel_group_id = channel.mMeta.mGroupId; + +#ifdef RS_DEEP_SEARCH + DeepSearch::indexChannelGroup(channel); +#endif // RS_DEEP_SEARCH + + return true; +} + bool p3GxsChannels::createChannel(RsGxsChannelGroup& channel) { uint32_t token; diff --git a/libretroshare/src/services/p3gxschannels.h b/libretroshare/src/services/p3gxschannels.h index 7ac63f8e7..6ddcedadb 100644 --- a/libretroshare/src/services/p3gxschannels.h +++ b/libretroshare/src/services/p3gxschannels.h @@ -197,6 +197,16 @@ virtual bool ExtraFileRemove(const RsFileHash &hash); /// Implementation of @see RsGxsChannels::createChannel virtual bool createChannel(RsGxsChannelGroup& channel); + /// Implementation of @see RsGxsChannels::createChannel + virtual bool createChannel(const std::string& name, + const std::string& description, + const RsGxsImage& image, + const RsGxsId& author_id, + uint32_t circle_type, + RsGxsCircleId& circle_id, + RsGxsGroupId& channel_group_id, + std::string& error_message); + /// Implementation of @see RsGxsChannels::createComment virtual bool createComment(RsGxsComment& comment); diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp index 4bf950a5e..fb50f9acc 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp @@ -755,12 +755,12 @@ void GxsGroupDialog::setGroupSignFlags(uint32_t signFlags) // (cyril) very weird piece of code. Need to clear this up. ui.comments_allowed->setChecked(true); - ui.commentsValueLabel->setText("Allowed") ; + ui.commentsValueLabel->setText("Allowed") ; } else { ui.comments_no->setChecked(true); - ui.commentsValueLabel->setText("Allowed") ; + ui.commentsValueLabel->setText("Forbidden") ; } } diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp index b33c49b60..6fb832a69 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp @@ -61,11 +61,15 @@ const uint32_t ChannelEditDefaultsFlags = ChannelCreateDefaultsFlags; GxsChannelGroupDialog::GxsChannelGroupDialog(TokenQueue *tokenQueue, QWidget *parent) : GxsGroupDialog(tokenQueue, ChannelCreateEnabledFlags, ChannelCreateDefaultsFlags, parent) { + ui.commentGroupBox->setEnabled(false); // These are here because comments_allowed are actually not used yet, so the group will not be changed by the setting and when + ui.comments_allowed->setChecked(true); // the group info is displayed it will therefore be set to "disabled" in all cases although it is enabled. } GxsChannelGroupDialog::GxsChannelGroupDialog(TokenQueue *tokenExternalQueue, RsTokenService *tokenService, Mode mode, RsGxsGroupId groupId, QWidget *parent) : GxsGroupDialog(tokenExternalQueue, tokenService, mode, groupId, ChannelEditEnabledFlags, ChannelEditDefaultsFlags, parent) { + ui.commentGroupBox->setEnabled(false); // These are here because comments_allowed are actually not used yet, so the group will not be changed by the setting and when + ui.comments_allowed->setChecked(true); // the group info is displayed it will therefore be set to "disabled" in all cases although it is enabled. } void GxsChannelGroupDialog::initUi()