Implement GXS forum reasonable JSON API

Remove misleading comments around, and add some TODO of things we should
  fix at some point
This commit is contained in:
Gioacchino Mazzurco 2019-08-01 11:33:00 +02:00
parent 3ffb57f998
commit eff133b564
No known key found for this signature in database
GPG key ID: A1FBCA3872E87051
7 changed files with 353 additions and 85 deletions

View file

@ -3,7 +3,8 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2012-2012 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2012-2014 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -21,8 +22,8 @@
*******************************************************************************/
#include "services/p3gxsforums.h"
#include "rsitems/rsgxsforumitems.h"
#include <retroshare/rsidentity.h>
#include "retroshare/rspeers.h"
#include "retroshare/rsidentity.h"
#include "rsserver/p3face.h"
#include "retroshare/rsnotify.h"
@ -384,6 +385,165 @@ bool p3GxsForums::getMsgData(const uint32_t &token, std::vector<RsGxsForumMsg> &
/********************************************************************************************/
bool p3GxsForums::createForumV2(
const std::string& name, const std::string& description,
const RsGxsId& authorId, const std::set<RsGxsId>& moderatorsIds,
RsGxsCircleType circleType, const RsGxsCircleId& circleId,
RsGxsGroupId& forumId, std::string& errorMessage )
{
auto createFail = [&](std::string mErr)
{
errorMessage = mErr;
RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl;
return false;
};
if(name.empty()) return createFail("Forum name is required");
if(!authorId.isNull() && !rsIdentity->isOwnId(authorId))
return createFail("Author must be iether null or and identity owned by "
"this node");
switch(circleType)
{
case RsGxsCircleType::PUBLIC: // fallthrough
case RsGxsCircleType::LOCAL: // fallthrough
case RsGxsCircleType::YOUR_EYES_ONLY:
break;
case RsGxsCircleType::EXTERNAL:
if(circleId.isNull())
return createFail("circleType is EXTERNAL but circleId is null");
break;
case RsGxsCircleType::NODES_GROUP:
{
RsGroupInfo ginfo;
if(!rsPeers->getGroupInfo(RsNodeGroupId(circleId), ginfo))
return createFail("circleType is NODES_GROUP but circleId does not "
"correspond to an actual group of friends");
break;
}
default: return createFail("circleType has invalid value");
}
// Create a consistent channel group meta from the information supplied
RsGxsForumGroup forum;
forum.mMeta.mGroupName = name;
forum.mMeta.mAuthorId = authorId;
forum.mMeta.mCircleType = static_cast<uint32_t>(circleType);
forum.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ
| GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED;
forum.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC;
forum.mMeta.mCircleId.clear();
forum.mMeta.mInternalCircle.clear();
switch(circleType)
{
case RsGxsCircleType::NODES_GROUP:
forum.mMeta.mInternalCircle = circleId; break;
case RsGxsCircleType::EXTERNAL:
forum.mMeta.mCircleId = circleId; break;
default: break;
}
forum.mDescription = description;
forum.mAdminList.ids = moderatorsIds;
uint32_t token;
if(!createGroup(token, forum))
return createFail("Failed creating GXS group.");
// wait for the group creation to complete.
RsTokenService::GxsRequestStatus wSt =
waitToken( token, std::chrono::milliseconds(5000),
std::chrono::milliseconds(20) );
if(wSt != RsTokenService::COMPLETE)
return createFail( "GXS operation waitToken failed with: "
+ std::to_string(wSt) );
if(!RsGenExchange::getPublishedGroupMeta(token, forum.mMeta))
return createFail("Failure getting updated group data.");
forumId = forum.mMeta.mGroupId;
return true;
}
bool p3GxsForums::createPost(
const RsGxsGroupId& forumId, const std::string& title,
const std::string& mBody,
const RsGxsId& authorId, const RsGxsMessageId& parentId,
const RsGxsMessageId& origPostId, RsGxsMessageId& postMsgId,
std::string& errorMessage )
{
RsGxsForumMsg post;
auto failure = [&](std::string errMsg)
{
errorMessage = errMsg;
RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl;
return false;
};
if(title.empty()) return failure("Title is required");
if(authorId.isNull()) return failure("Author id is needed");
if(!rsIdentity->isOwnId(authorId))
return failure( "Author id: " + authorId.toStdString() + " is not of"
"own identity" );
if(!parentId.isNull())
{
std::vector<RsGxsForumMsg> msgs;
if( getForumContent(forumId, std::set<RsGxsMessageId>({parentId}), msgs)
&& msgs.size() == 1 )
{
post.mMeta.mParentId = parentId;
post.mMeta.mThreadId = msgs[0].mMeta.mThreadId;
}
else return failure("Parent post " + parentId.toStdString()
+ " doesn't exists locally");
}
std::vector<RsGxsForumGroup> forumInfo;
if(!getForumsInfo(std::list<RsGxsGroupId>({forumId}), forumInfo))
return failure( "Forum with Id " + forumId.toStdString()
+ " does not exist locally." );
if(!origPostId.isNull())
{
std::vector<RsGxsForumMsg> msgs;
if( getForumContent( forumId,
std::set<RsGxsMessageId>({origPostId}), msgs)
&& msgs.size() == 1 )
post.mMeta.mOrigMsgId = origPostId;
else return failure("Original post " + origPostId.toStdString()
+ " doesn't exists locally");
}
post.mMeta.mGroupId = forumId;
post.mMeta.mMsgName = title;
post.mMeta.mAuthorId = authorId;
post.mMsg = mBody;
uint32_t token;
if( !createMsg(token, post)
|| waitToken(
token,
std::chrono::milliseconds(5000) ) != RsTokenService::COMPLETE )
return failure("Failure creating GXS message");
if(!RsGenExchange::getPublishedMsgMeta(token, post.mMeta))
return failure("Failure getting created GXS message metadata");
postMsgId = post.mMeta.mMsgId;
return true;
}
bool p3GxsForums::createForum(RsGxsForumGroup& forum)
{
uint32_t token;
@ -461,8 +621,9 @@ bool p3GxsForums::getForumsInfo(
}
bool p3GxsForums::getForumContent(
const RsGxsGroupId& forumId, std::set<RsGxsMessageId>& msgs_to_request,
std::vector<RsGxsForumMsg>& msgs )
const RsGxsGroupId& forumId,
const std::set<RsGxsMessageId>& msgs_to_request,
std::vector<RsGxsForumMsg>& msgs )
{
uint32_t token;
RsTokReqOptions opts;
@ -844,3 +1005,6 @@ bool RsGxsForumGroup::canEditPosts(const RsGxsId& id) const
id == mMeta.mAuthorId;
}
RsGxsForumGroup::~RsGxsForumGroup() = default;
RsGxsForumMsg::~RsGxsForumMsg() = default;
RsGxsForums::~RsGxsForums() = default;

View file

@ -3,7 +3,8 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2012-2012 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2012-2014 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -19,21 +20,17 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef P3_GXSFORUMS_SERVICE_HEADER
#define P3_GXSFORUMS_SERVICE_HEADER
#include "retroshare/rsgxsforums.h"
#include "gxs/rsgenexchange.h"
#include "util/rstickevent.h"
#pragma once
#include <map>
#include <string>
/*
*
*/
#include "retroshare/rsgxsforums.h"
#include "gxs/rsgenexchange.h"
#include "retroshare/rsgxscircles.h"
#include "util/rstickevent.h"
#include "util/rsdebug.h"
class p3GxsForums: public RsGenExchange, public RsGxsForums, public p3Config,
public RsTickEvent /* only needed for testing - remove after */
@ -55,14 +52,39 @@ protected:
virtual bool loadList(std::list<RsItem *>& loadList); // @see p3Config::loadList(std::list<RsItem *>&)
public:
/// @see RsGxsForums::createForum
/// @see RsGxsForums::createForumV2
bool createForumV2(
const std::string& name, const std::string& description,
const RsGxsId& authorId = RsGxsId(),
const std::set<RsGxsId>& moderatorsIds = std::set<RsGxsId>(),
RsGxsCircleType circleType = RsGxsCircleType::PUBLIC,
const RsGxsCircleId& circleId = RsGxsCircleId(),
RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId),
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) override;
/// @see RsGxsForums::createPost
bool createPost(
const RsGxsGroupId& forumId,
const std::string& title,
const std::string& mBody,
const RsGxsId& authorId,
const RsGxsMessageId& parentId = RsGxsMessageId(),
const RsGxsMessageId& origPostId = RsGxsMessageId(),
RsGxsMessageId& postMsgId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) override;
/// @see RsGxsForums::createForum @deprecated
RS_DEPRECATED_FOR(createForumV2)
virtual bool createForum(RsGxsForumGroup& forum);
/// @see RsGxsForums::createMessage
/// @see RsGxsForums::createMessage @deprecated
RS_DEPRECATED_FOR(createPost)
virtual bool createMessage(RsGxsForumMsg& message);
/// @see RsGxsForums::editForum
virtual bool editForum(RsGxsForumGroup& forum);
virtual bool editForum(RsGxsForumGroup& forum) override;
/// @see RsGxsForums::getForumsSummaries
virtual bool getForumsSummaries(std::list<RsGroupMetaData>& forums);
@ -78,7 +100,7 @@ public:
/// @see RsGxsForums::getForumContent
virtual bool getForumContent(
const RsGxsGroupId& forumId,
std::set<RsGxsMessageId>& msgs_to_request,
const std::set<RsGxsMessageId>& msgs_to_request,
std::vector<RsGxsForumMsg>& msgs );
/// @see RsGxsForums::markRead
@ -130,5 +152,3 @@ bool generateGroup(uint32_t &token, std::string groupName);
std::map<RsGxsGroupId,rstime_t> mKnownForums ;
};
#endif