first version of circle messages

This commit is contained in:
csoler 2016-05-10 21:24:31 -04:00
parent c9846c0dcf
commit 9a86989060
4 changed files with 134 additions and 16 deletions

View File

@ -136,8 +136,8 @@ virtual bool getCirclePersonalIdList(std::list<RsGxsCircleId> &circleIds) = 0;
/* membership management for external circles */ /* membership management for external circles */
virtual bool requestCircleMembership(const RsGxsCircleId& id)=0 ; virtual bool requestCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id)=0 ;
virtual bool cancelCircleMembership(const RsGxsCircleId& id)=0 ; virtual bool cancelCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id)=0 ;
/* standard load */ /* standard load */
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups) = 0; virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups) = 0;

View File

@ -1819,15 +1819,132 @@ void p3GxsCircles::handle_event(uint32_t event_type, const std::string &elabel)
} }
} }
// Circle membership is requested/denied by posting a message into the cicle group, according to the following rules:
//
// - a subscription request is a RsItem (which serialises into a radix64 message, that is further signed by the group message publishing system)
// The item contains:
// * subscribe order (yes/no), boolean
// * circle ID (this is important, otherwise people can copy subscribe messages from one circle to another)
// * subscribe date
// * subscribe timeout (how long is the message kept. When timed out, the message is removed and subscription cancelled)
//
// - subscribe messages follow the following rules, which are enforced by a timer-based method:
// * subscription requests from a given user are always replaced by the last subscription request
// * a complete list of who's subscribed to a given group is kept, saved, and regularly updated when new subscribe messages are received, or when admin list is changed.
// * getGroupDetails reads this list in order to respond who's subscribed to a group. The list of
//
// - compatibility with self-restricted circles:
// * subscription should be based on admin list, so that non subscribed peers still receive the invitation
//
// - Use cases
// * user sees group (not self restricted) and requests to subscribe => RS subscribes the group and the user can propagate the response
//
// - Threat model
// * a malicious user forges a new subscription request: NP-hard as it needs to break the RSA key of the GXS id.
// * a malicious corrupts a subscription request: NP-hard. Messages are signed.
// * a malicious user copies an old subscription of someone else and inserts it in the system.
// => not possible. Either this existing old susbscription already exists, or it has been replaced by a more recent one, which
// will always replace the old one because of the date.
// * a malicious user removes someone's subscription messages. This is possible, but the mesh nature of the network will allow the message to propagate anyway.
bool p3GxsCircles::requestCircleMembership(const RsGxsCircleId& id) bool p3GxsCircles::pushCircleMembershipRequest(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id,uint32_t request_type)
{ {
#warning code missing here !!! // check for some consistency
if(request_type != RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE && request_type != RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE)
return false ;
std::list<RsGxsId> own_ids ;
if(!rsIdentity->getOwnIds(own_ids))
return false ;
bool found = false ;
for(std::list<RsGxsId>::const_iterator it(own_ids.begin());it!=own_ids.end() && !found;++it)
found = ( (*it) == own_gxsid) ;
if(!found)
return false ;
// Create a subscribe item
RsGxsCircleSubscriptionRequestItem s ;
s.time_stamp = time(NULL) ;
s.subscription_request = RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE ;
s.circle_id = id ;
s.time_out = 0 ; // means never
// Serialise it into a base64 string
uint32_t pktsize = s.serial_size() ;
RsTemporaryMemory mem(s.serial_size()) ;
if(!mem)
return false ;
s.serialise(mem,pktsize) ;
std::string msg ;
Radix64::encode(mem,pktsize,msg) ;
// Create the group message to store and publish it
RsTemporaryMemory tmpmem(RsGxsCircleId::SIZE_IN_BYTES + RsGxsId::SIZE_IN_BYTES) ;
if(!tmpmem)
return false ;
circle_id.serialise(tmpmem,tmpmem.size()) ;
own_gxsid.serialise(tmpmem+RsGxsCircleId::SIZE_IN_BYTES,(int)tmpmem.size()-(int)RsGxsCircleId::SIZE_IN_BYTES) ;
RsGxsCircleMsgItem* msgItem = new RsGxsCircleMsgItem();
msgItem->mMsg = msg;
msgItem->meta.mGroupId = id ;
msgItem->meta.mMsgId.clear();
msgItem->meta.mThreadId = sha1sum(tmpmem,tmpmem.size()); // make the ID from the hash of the cirle ID and the author ID
msgItem->meta.mAuthorId = own_id;
// msgItem->meta.mParentId = ; // leave these blank
// msgItem->meta.mOrigMsgId= ;
std::cerr << "p3GxsCircles::publishSubscribeRequest()" << std::endl;
std::cerr << " GroupId : " << circle_id << std::endl;
std::cerr << " AuthorId : " << msgItem->meta.mAuthorId << std::endl;
std::cerr << " ThreadId : " << msgItem->meta.mThreadId << std::endl;
#warning Would be nice to wait for a few seconds before publishing, so that the user can potentially cancel a wrong request before it gets piped into the system
//RsGenExchange::publishMsg(token, msgItem);
return true;
} }
bool p3GxsCircles::cancelCircleMembership(const RsGxsCircleId& id) bool p3GxsCircles::requestCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id)
{ {
#warning code missing here !!! return pushCircleMembershipRequest(own_id,circle_id,RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE) ;
}
bool p3GxsCircles::cancelCircleMembership(const RsGxsId& own_id,const RsGxsCircleId& id)
{
return pushCircleMembershipRequest(own_id,circle_id,RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE) ;
} }

View File

@ -194,8 +194,8 @@ virtual RsServiceInfo getServiceInfo();
/* membership management for external circles */ /* membership management for external circles */
virtual bool requestCircleMembership(const RsGxsCircleId& id) ; virtual bool requestCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) ;
virtual bool cancelCircleMembership(const RsGxsCircleId& id) ; virtual bool cancelCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) ;
/**********************************************/ /**********************************************/
@ -204,6 +204,7 @@ virtual RsServiceInfo getServiceInfo();
protected: protected:
bool pushCircleMembershipRequest(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id,uint32_t request_type) ;
static uint32_t circleAuthenPolicy(); static uint32_t circleAuthenPolicy();
/** Notifications **/ /** Notifications **/

View File

@ -436,7 +436,7 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
if(am_I_in_circle && item->parent() != mExternalBelongingCircleItem) if(am_I_in_circle && item->parent() != mExternalBelongingCircleItem)
{ {
#ifdef ID_DEBUG #ifdef ID_DEBUG
std::cerr << " Existing group is not in subscribed items although it is subscribed. Removing." << std::endl; std::cerr << " Existing circle is not in subscribed items although it is subscribed. Removing." << std::endl;
#endif #endif
delete item ; delete item ;
item = NULL ; item = NULL ;
@ -444,7 +444,7 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
else if(!am_I_in_circle && item->parent() != mExternalOtherCircleItem) else if(!am_I_in_circle && item->parent() != mExternalOtherCircleItem)
{ {
#ifdef ID_DEBUG #ifdef ID_DEBUG
std::cerr << " Existing group is not in subscribed items although it is subscribed. Removing." << std::endl; std::cerr << " Existing circle is not in subscribed items although it is subscribed. Removing." << std::endl;
#endif #endif
delete item ; delete item ;
item = NULL ; item = NULL ;
@ -467,14 +467,14 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
if(am_I_in_circle) if(am_I_in_circle)
{ {
#ifdef ID_DEBUG #ifdef ID_DEBUG
std::cerr << " adding item for group " << vit->mGroupId << " to own circles"<< std::endl; std::cerr << " adding item for circle " << vit->mGroupId << " to own circles"<< std::endl;
#endif #endif
mExternalBelongingCircleItem->addChild(item); mExternalBelongingCircleItem->addChild(item);
} }
else else
{ {
#ifdef ID_DEBUG #ifdef ID_DEBUG
std::cerr << " adding item for group " << vit->mGroupId << " to others"<< std::endl; std::cerr << " adding item for circle " << vit->mGroupId << " to others"<< std::endl;
#endif #endif
mExternalOtherCircleItem->addChild(item); mExternalOtherCircleItem->addChild(item);
} }
@ -482,7 +482,7 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
else if(item->text(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) != QString::fromUtf8(vit->mGroupName.c_str())) else if(item->text(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) != QString::fromUtf8(vit->mGroupName.c_str()))
{ {
#ifdef ID_DEBUG #ifdef ID_DEBUG
std::cerr << " Existing group has a new name. Updating it in the tree." << std::endl; std::cerr << " Existing circle has a new name. Updating it in the tree." << std::endl;
#endif #endif
item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str())); item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str()));
} }
@ -504,17 +504,17 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
{ {
case GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED: case GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED:
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_yellow_128.png")) ; item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_yellow_128.png")) ;
item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tr("Your request to be in this group is still pending. You need to wait the administrator to validate it.")) ; item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tr("Your request to be in this circle is pending. You need to wait for the administrator to validate it.")) ;
break ; break ;
case GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST: case GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST:
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_blue_128.png")) ; item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_blue_128.png")) ;
item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tr("You are invited to this group by the administrator. Right click to join the group.")) ; item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tr("You are invited to this circle by the administrator. Right click to join the circle.")) ;
break ; break ;
case GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST | GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED: case GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST | GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED:
item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_green_128.png")) ; item->setIcon(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,QIcon(":icons/bullet_green_128.png")) ;
item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tr("You are a member of this group.")) ; item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tr("You are a validated member of this circle.")) ;
break ; break ;
default: default: