From e52cbd896ed27e49028d66b43ecf49a803d2aa44 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 12 Jan 2023 15:51:46 -0300 Subject: [PATCH] Introduce SharingStatus to report more fine-grained status --- .../BaseContactSelectorAdapter.java | 4 +- .../BaseContactSelectorFragment.java | 2 +- .../BaseSelectableContactHolder.java | 2 +- .../BaseSelectableContactItem.java | 32 ++++++++++ .../ContactSelectorController.java | 2 +- .../ContactSelectorControllerImpl.java | 7 +-- .../SelectableContactHolder.java | 14 +++++ .../SelectableContactItem.java | 27 ++++----- .../creation/CreateGroupControllerImpl.java | 5 +- .../reveal/RevealContactsControllerImpl.java | 2 +- .../reveal/RevealableContactItem.java | 14 +++-- .../sharing/ShareBlogControllerImpl.java | 6 +- .../sharing/ShareForumControllerImpl.java | 6 +- briar-android/src/main/res/values/strings.xml | 2 + .../invitation/GroupInvitationManager.java | 3 +- .../briar/api/sharing/SharingManager.java | 8 ++- .../GroupInvitationManagerImpl.java | 13 ++-- .../briar/sharing/SharingManagerImpl.java | 19 +++--- .../org/briarproject/briar/sharing/State.java | 4 ++ .../invitation/AutoDeleteIntegrationTest.java | 14 +++-- .../GroupInvitationIntegrationTest.java | 23 +++---- .../GroupInvitationManagerImplTest.java | 28 +++++---- .../AbstractAutoDeleteIntegrationTest.java | 9 +-- .../sharing/BlogSharingIntegrationTest.java | 60 ++++++++++--------- .../sharing/ForumSharingIntegrationTest.java | 38 +++++++----- 25 files changed, 219 insertions(+), 125 deletions(-) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactItem.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorAdapter.java index 94319ec34..8c74a7fdb 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorAdapter.java @@ -12,7 +12,7 @@ import java.util.ArrayList; import java.util.Collection; @NotNullByDefault -public abstract class BaseContactSelectorAdapter> +public abstract class BaseContactSelectorAdapter> extends BaseContactListAdapter { public BaseContactSelectorAdapter(Context context, Class c, @@ -24,7 +24,7 @@ public abstract class BaseContactSelectorAdapter selected = new ArrayList<>(); for (int i = 0; i < items.size(); i++) { - SelectableContactItem item = items.get(i); + BaseSelectableContactItem item = items.get(i); if (item.isSelected()) selected.add(item.getContact().getId()); } return selected; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorFragment.java index dcfb52c19..637c00125 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorFragment.java @@ -33,7 +33,7 @@ import static org.briarproject.briar.android.contactselection.ContactSelectorAct @MethodsNotNullByDefault @ParametersNotNullByDefault -public abstract class BaseContactSelectorFragment>> +public abstract class BaseContactSelectorFragment>> extends BaseFragment implements OnContactClickListener { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactHolder.java index 57cc644ef..dfe4d832c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactHolder.java @@ -17,7 +17,7 @@ import static org.briarproject.briar.android.util.UiUtils.GREY_OUT; @UiThread @NotNullByDefault -public class BaseSelectableContactHolder +public abstract class BaseSelectableContactHolder extends ContactItemViewHolder { private final CheckBox checkBox; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactItem.java new file mode 100644 index 000000000..9218f64ba --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactItem.java @@ -0,0 +1,32 @@ +package org.briarproject.briar.android.contactselection; + +import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.briar.android.contact.ContactItem; +import org.briarproject.briar.api.identity.AuthorInfo; +import org.briarproject.nullsafety.NotNullByDefault; + +import javax.annotation.concurrent.NotThreadSafe; + +@NotThreadSafe +@NotNullByDefault +public abstract class BaseSelectableContactItem extends ContactItem { + + private boolean selected; + + public BaseSelectableContactItem(Contact contact, AuthorInfo authorInfo, + boolean selected) { + super(contact, authorInfo); + this.selected = selected; + } + + boolean isSelected() { + return selected; + } + + void toggleSelected() { + selected = !selected; + } + + public abstract boolean isDisabled(); + +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java index a472995b7..319830600 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java @@ -10,7 +10,7 @@ import org.briarproject.nullsafety.NotNullByDefault; import java.util.Collection; @NotNullByDefault -public interface ContactSelectorController +public interface ContactSelectorController extends DbController { void loadContacts(GroupId g, Collection selection, diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorControllerImpl.java index 054ac6cd5..03d24df62 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorControllerImpl.java @@ -11,6 +11,7 @@ import org.briarproject.briar.android.controller.DbControllerImpl; import org.briarproject.briar.android.controller.handler.ResultExceptionHandler; import org.briarproject.briar.api.identity.AuthorInfo; import org.briarproject.briar.api.identity.AuthorManager; +import org.briarproject.briar.api.sharing.SharingManager.SharingStatus; import org.briarproject.nullsafety.NotNullByDefault; import java.util.ArrayList; @@ -53,10 +54,8 @@ public abstract class ContactSelectorControllerImpl AuthorInfo authorInfo = authorManager.getAuthorInfo(c); // was this contact already selected? boolean selected = selection.contains(c.getId()); - // can this contact be selected? - boolean disabled = isDisabled(g, c); contacts.add(new SelectableContactItem(c, authorInfo, - selected, disabled)); + selected, getSharingStatus(g, c))); } handler.onResult(contacts); } catch (DbException e) { @@ -67,7 +66,7 @@ public abstract class ContactSelectorControllerImpl } @DatabaseExecutor - protected abstract boolean isDisabled(GroupId g, Contact c) + protected abstract SharingStatus getSharingStatus(GroupId g, Contact c) throws DbException; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactHolder.java index cc3902393..21d5c7c52 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactHolder.java @@ -2,15 +2,20 @@ package org.briarproject.briar.android.contactselection; import android.view.View; +import org.briarproject.briar.R; import org.briarproject.briar.android.contact.OnContactClickListener; import org.briarproject.nullsafety.NotNullByDefault; import javax.annotation.Nullable; +import androidx.annotation.StringRes; import androidx.annotation.UiThread; import static android.view.View.GONE; import static android.view.View.VISIBLE; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.INVITED; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.NOT_SUPPORTED; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING; @UiThread @NotNullByDefault @@ -27,6 +32,15 @@ class SelectableContactHolder super.bind(item, listener); if (item.isDisabled()) { + @StringRes int strRes; + if (item.getSharingStatus() == SHARING) { + strRes = R.string.forum_invitation_already_sharing; + } else if (item.getSharingStatus() == INVITED) { + strRes = R.string.forum_invitation_already_invited; + } else if (item.getSharingStatus() == NOT_SUPPORTED) { + strRes = R.string.forum_invitation_not_supported; + } else throw new AssertionError("Unhandled SharingStatus"); + info.setText(strRes); info.setVisibility(VISIBLE); } else { info.setVisibility(GONE); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactItem.java index 29f4aa809..efd2e1bb6 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactItem.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactItem.java @@ -1,36 +1,33 @@ package org.briarproject.briar.android.contactselection; import org.briarproject.bramble.api.contact.Contact; -import org.briarproject.briar.android.contact.ContactItem; import org.briarproject.briar.api.identity.AuthorInfo; +import org.briarproject.briar.api.sharing.SharingManager.SharingStatus; import org.briarproject.nullsafety.NotNullByDefault; import javax.annotation.concurrent.NotThreadSafe; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; + @NotThreadSafe @NotNullByDefault -public class SelectableContactItem extends ContactItem { +public class SelectableContactItem extends BaseSelectableContactItem { - private boolean selected; - private final boolean disabled; + private final SharingStatus sharingStatus; public SelectableContactItem(Contact contact, AuthorInfo authorInfo, - boolean selected, boolean disabled) { - super(contact, authorInfo); - this.selected = selected; - this.disabled = disabled; + boolean selected, SharingStatus sharingStatus) { + super(contact, authorInfo, selected); + this.sharingStatus = sharingStatus; } - boolean isSelected() { - return selected; - } - - void toggleSelected() { - selected = !selected; + public SharingStatus getSharingStatus() { + return sharingStatus; } + @Override public boolean isDisabled() { - return disabled; + return sharingStatus != SHAREABLE; } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java index 35c707fd2..b311ce54e 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java @@ -26,6 +26,7 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import org.briarproject.briar.api.privategroup.PrivateGroupManager; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; +import org.briarproject.briar.api.sharing.SharingManager.SharingStatus; import org.briarproject.nullsafety.NotNullByDefault; import java.util.ArrayList; @@ -140,8 +141,8 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl } @Override - protected boolean isDisabled(GroupId g, Contact c) throws DbException { - return !groupInvitationManager.isInvitationAllowed(c, g); + protected SharingStatus getSharingStatus(GroupId g, Contact c) throws DbException { + return groupInvitationManager.getSharingStatus(c, g); } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java index 50e7c06b0..9be05861f 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java @@ -92,7 +92,7 @@ class RevealContactsControllerImpl extends DbControllerImpl boolean selected = disabled || selection.contains(c.getId()); items.add(new RevealableContactItem(c, authorInfo, selected, - disabled, m.getVisibility())); + m.getVisibility())); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java index e298f30f5..45d83a524 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java @@ -1,22 +1,24 @@ package org.briarproject.briar.android.privategroup.reveal; import org.briarproject.bramble.api.contact.Contact; -import org.briarproject.briar.android.contactselection.SelectableContactItem; +import org.briarproject.briar.android.contactselection.BaseSelectableContactItem; import org.briarproject.briar.api.identity.AuthorInfo; import org.briarproject.briar.api.privategroup.Visibility; import org.briarproject.nullsafety.NotNullByDefault; import javax.annotation.concurrent.NotThreadSafe; +import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE; + @NotThreadSafe @NotNullByDefault -class RevealableContactItem extends SelectableContactItem { +class RevealableContactItem extends BaseSelectableContactItem { private final Visibility visibility; RevealableContactItem(Contact contact, AuthorInfo authorInfo, - boolean selected, boolean disabled, Visibility visibility) { - super(contact, authorInfo, selected, disabled); + boolean selected, Visibility visibility) { + super(contact, authorInfo, selected); this.visibility = visibility; } @@ -24,4 +26,8 @@ class RevealableContactItem extends SelectableContactItem { return visibility; } + @Override + public boolean isDisabled() { + return visibility != INVISIBLE; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogControllerImpl.java index abb14de67..716ddc606 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogControllerImpl.java @@ -13,6 +13,7 @@ import org.briarproject.briar.android.contactselection.ContactSelectorController import org.briarproject.briar.android.controller.handler.ExceptionHandler; import org.briarproject.briar.api.blog.BlogSharingManager; import org.briarproject.briar.api.identity.AuthorManager; +import org.briarproject.briar.api.sharing.SharingManager.SharingStatus; import org.briarproject.nullsafety.NotNullByDefault; import java.util.Collection; @@ -47,8 +48,9 @@ class ShareBlogControllerImpl extends ContactSelectorControllerImpl } @Override - protected boolean isDisabled(GroupId g, Contact c) throws DbException { - return !blogSharingManager.canBeShared(g, c); + protected SharingStatus getSharingStatus(GroupId g, Contact c) + throws DbException { + return blogSharingManager.getSharingStatus(g, c); } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumControllerImpl.java index 92d8eb8a3..72fdeac1f 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumControllerImpl.java @@ -13,6 +13,7 @@ import org.briarproject.briar.android.contactselection.ContactSelectorController import org.briarproject.briar.android.controller.handler.ExceptionHandler; import org.briarproject.briar.api.forum.ForumSharingManager; import org.briarproject.briar.api.identity.AuthorManager; +import org.briarproject.briar.api.sharing.SharingManager.SharingStatus; import org.briarproject.nullsafety.NotNullByDefault; import java.util.Collection; @@ -47,8 +48,9 @@ class ShareForumControllerImpl extends ContactSelectorControllerImpl } @Override - protected boolean isDisabled(GroupId g, Contact c) throws DbException { - return !forumSharingManager.canBeShared(g, c); + protected SharingStatus getSharingStatus(GroupId g, Contact c) + throws DbException { + return forumSharingManager.getSharingStatus(g, c); } @Override diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index 44c9adf03..3f6d4a93a 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -461,6 +461,8 @@ Invitation declined Shared by %s Already sharing + Already invited + Not supported by this contact You accepted the forum invitation from %s. You declined the forum invitation from %s. The forum invitation from %s was automatically declined. diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java index f552d4859..201835ca4 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java @@ -9,6 +9,7 @@ import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.conversation.ConversationManager.ConversationClient; import org.briarproject.briar.api.privategroup.PrivateGroup; +import org.briarproject.briar.api.sharing.SharingManager.SharingStatus; import org.briarproject.nullsafety.NotNullByDefault; import java.util.Collection; @@ -82,5 +83,5 @@ public interface GroupInvitationManager extends ConversationClient { * Returns true if the given contact can be invited to the given private * group. */ - boolean isInvitationAllowed(Contact c, GroupId g) throws DbException; + SharingStatus getSharingStatus(Contact c, GroupId g) throws DbException; } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java index ae81f9aa8..b71f23da3 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java @@ -17,6 +17,10 @@ import javax.annotation.Nullable; public interface SharingManager extends ConversationClient { + enum SharingStatus { + SHAREABLE, INVITED, SHARING, NOT_SUPPORTED + } + /** * Sends an invitation to share the given group with the given contact, * including optional text. @@ -80,12 +84,12 @@ public interface SharingManager /** * Returns true if the group not already shared and no invitation is open */ - boolean canBeShared(GroupId g, Contact c) throws DbException; + SharingStatus getSharingStatus(GroupId g, Contact c) throws DbException; /** * Returns true if the group not already shared and no invitation is open */ - boolean canBeShared(Transaction txn, GroupId g, Contact c) + SharingStatus getSharingStatus(Transaction txn, GroupId g, Contact c) throws DbException; } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java index 40d1733f9..4f1ca7e9b 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java @@ -37,6 +37,7 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse; +import org.briarproject.briar.api.sharing.SharingManager.SharingStatus; import org.briarproject.briar.client.ConversationClientImpl; import org.briarproject.nullsafety.NotNullByDefault; @@ -56,6 +57,7 @@ import javax.inject.Inject; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; +import static org.briarproject.briar.privategroup.invitation.CreatorState.JOINED; import static org.briarproject.briar.privategroup.invitation.CreatorState.START; import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT; import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE; @@ -511,7 +513,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } @Override - public boolean isInvitationAllowed(Contact c, GroupId privateGroupId) + public SharingStatus getSharingStatus(Contact c, GroupId privateGroupId) throws DbException { GroupId contactGroupId = getContactGroup(c).getId(); SessionId sessionId = getSessionId(privateGroupId); @@ -523,13 +525,16 @@ class GroupInvitationManagerImpl extends ConversationClientImpl StoredSession ss = getSession(txn, contactGroupId, sessionId); db.commitTransaction(txn); // The group can't be shared unless the contact supports the client - if (client != SHARED) return false; + if (client != SHARED) return SharingStatus.NOT_SUPPORTED; // If there's no session, the contact can be invited - if (ss == null) return true; + if (ss == null) return SharingStatus.SHAREABLE; // If the session's in the start state, the contact can be invited CreatorSession session = sessionParser .parseCreatorSession(contactGroupId, ss.bdfSession); - return session.getState() == START; + CreatorState state = session.getState(); + if (state == START) return SharingStatus.SHAREABLE; + if (state == JOINED) return SharingStatus.SHARING; + return SharingStatus.INVITED; } catch (FormatException e) { throw new DbException(e); } finally { diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java index 940cae1cb..a7c6854a3 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java @@ -51,6 +51,7 @@ import javax.annotation.Nullable; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; import static org.briarproject.briar.sharing.MessageType.ABORT; import static org.briarproject.briar.sharing.MessageType.ACCEPT; import static org.briarproject.briar.sharing.MessageType.DECLINE; @@ -269,7 +270,7 @@ abstract class SharingManagerImpl SessionId sessionId = getSessionId(shareableId); try { Contact contact = db.getContact(txn, contactId); - if (!canBeShared(txn, shareableId, contact)) + if (getSharingStatus(txn, shareableId, contact) != SHAREABLE) // we might have received an invitation in the meantime return; // Look up the session, if there is one @@ -467,34 +468,36 @@ abstract class SharingManagerImpl } @Override - public boolean canBeShared(GroupId g, Contact c) throws DbException { + public SharingStatus getSharingStatus(GroupId g, Contact c) throws DbException { Transaction txn = db.startTransaction(true); try { - boolean canBeShared = canBeShared(txn, g, c); + SharingStatus sharingStatus = getSharingStatus(txn, g, c); db.commitTransaction(txn); - return canBeShared; + return sharingStatus; } finally { db.endTransaction(txn); } } @Override - public boolean canBeShared(Transaction txn, GroupId g, Contact c) + public SharingStatus getSharingStatus(Transaction txn, GroupId g, Contact c) throws DbException { // The group can't be shared unless the contact supports the client Visibility client = clientVersioningManager.getClientVisibility(txn, c.getId(), getShareableClientId(), getShareableMajorVersion()); - if (client != SHARED) return false; + if (client != SHARED) return SharingStatus.NOT_SUPPORTED; GroupId contactGroupId = getContactGroup(c).getId(); SessionId sessionId = getSessionId(g); try { StoredSession ss = getSession(txn, contactGroupId, sessionId); // If there's no session, we can share the group with the contact - if (ss == null) return true; + if (ss == null) return SharingStatus.SHAREABLE; // If the session's in the right state, the contact can be invited Session session = sessionParser.parseSession(contactGroupId, ss.bdfSession); - return session.getState().canInvite(); + if (session.getState().canInvite()) return SharingStatus.SHAREABLE; + if (session.getState().isSharing()) return SharingStatus.SHARING; + return SharingStatus.INVITED; } catch (FormatException e) { throw new DbException(e); } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/State.java b/briar-core/src/main/java/org/briarproject/briar/sharing/State.java index 4d8c47f78..1f4bba1fd 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/State.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/State.java @@ -50,6 +50,10 @@ enum State { return this == START; } + public boolean isSharing() { + return this == SHARING; + } + public boolean isAwaitingResponse() { return this == LOCAL_INVITED || this == REMOTE_INVITED; } diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AutoDeleteIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AutoDeleteIntegrationTest.java index d7e090866..089876b06 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AutoDeleteIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AutoDeleteIntegrationTest.java @@ -23,6 +23,8 @@ import javax.annotation.Nullable; import static org.briarproject.bramble.api.cleanup.CleanupManager.BATCH_DELAY_MS; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING; import static org.briarproject.briar.test.TestEventListener.assertEvent; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -157,8 +159,8 @@ public class AutoDeleteIntegrationTest extends AbstractAutoDeleteTest { waitForEvents(c1); // 0 can invite 1 again - assertTrue(groupInvitationManager0 - .isInvitationAllowed(contact1From0, privateGroup.getId())); + assertEquals(SHAREABLE, groupInvitationManager0 + .getSharingStatus(contact1From0, privateGroup.getId())); // Before 1's timer elapses, 1 should still see the auto-decline message c0.getTimeTravel().addCurrentTimeMillis(timerLatency - 1); @@ -194,8 +196,8 @@ public class AutoDeleteIntegrationTest extends AbstractAutoDeleteTest { assertEquals(0, getMessageHeaders(c0, contactId1From0).size()); // 0 can invite 1 again and really does invite - assertTrue(groupInvitationManager0 - .isInvitationAllowed(contact1From0, privateGroup.getId())); + assertEquals(SHAREABLE, groupInvitationManager0 + .getSharingStatus(contact1From0, privateGroup.getId())); sendInvitation(privateGroup, contact1From0.getId(), "Join this faster please!"); sync0To1(1, true); @@ -395,8 +397,8 @@ public class AutoDeleteIntegrationTest extends AbstractAutoDeleteTest { // 1 joined the PrivateGroup assertEquals(pg, c1.getPrivateGroupManager().getPrivateGroup(pg.getId())); - assertFalse(groupInvitationManager0 - .isInvitationAllowed(contact1From0, pg.getId())); + assertEquals(SHARING, groupInvitationManager0 + .getSharingStatus(contact1From0, pg.getId())); } @Test diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java index daca3e771..de7209497 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java @@ -29,6 +29,9 @@ import javax.annotation.Nullable; import static java.util.Collections.emptySet; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.INVITED; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING; import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -319,8 +322,8 @@ public class GroupInvitationIntegrationTest sendInvitation(c0.getClock().currentTimeMillis(), null); // invitation is not allowed before the first hasn't been answered - assertFalse(groupInvitationManager0 - .isInvitationAllowed(contact1From0, privateGroup.getId())); + assertEquals(INVITED, groupInvitationManager0 + .getSharingStatus(contact1From0, privateGroup.getId())); // deliver invitation and response sync0To1(1, true); @@ -329,8 +332,8 @@ public class GroupInvitationIntegrationTest sync1To0(1, true); // after invitation was declined, inviting again is possible - assertTrue(groupInvitationManager0 - .isInvitationAllowed(contact1From0, privateGroup.getId())); + assertEquals(SHAREABLE, groupInvitationManager0 + .getSharingStatus(contact1From0, privateGroup.getId())); // send and accept the second invitation sendInvitation(c0.getClock().currentTimeMillis(), "Second Invitation"); @@ -340,8 +343,8 @@ public class GroupInvitationIntegrationTest sync1To0(1, true); // invitation is not allowed since the member joined the group now - assertFalse(groupInvitationManager0 - .isInvitationAllowed(contact1From0, privateGroup.getId())); + assertEquals(SHARING, groupInvitationManager0 + .getSharingStatus(contact1From0, privateGroup.getId())); // don't allow another invitation request try { @@ -723,8 +726,8 @@ public class GroupInvitationIntegrationTest sync1To0(1, true); // inviting again is not possible - assertFalse(groupInvitationManager0 - .isInvitationAllowed(contact1From0, privateGroup.getId())); + assertEquals(SHARING, groupInvitationManager0 + .getSharingStatus(contact1From0, privateGroup.getId())); // contacts remove each other removeAllContacts(); @@ -737,8 +740,8 @@ public class GroupInvitationIntegrationTest addDefaultContacts(); // creator can still not invite again - assertFalse(groupInvitationManager0 - .isInvitationAllowed(contact1From0, privateGroup.getId())); + assertEquals(INVITED, groupInvitationManager0 + .getSharingStatus(contact1From0, privateGroup.getId())); // finally invitee can remove group without issues groupManager1.removePrivateGroup(privateGroup.getId()); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java index 183173d65..aaa445f63 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java @@ -62,12 +62,14 @@ import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROU import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH; import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID; import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.MAJOR_VERSION; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.INVITED; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING; import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT; import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE; import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN; import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class GroupInvitationManagerImplTest extends BrambleMockTestCase { @@ -871,31 +873,31 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { @Test public void testIsInvitationAllowed() throws Exception { expectIsInvitationAllowed(CreatorState.START); - assertTrue(groupInvitationManager - .isInvitationAllowed(contact, privateGroup.getId())); + assertEquals(SHAREABLE, groupInvitationManager + .getSharingStatus(contact, privateGroup.getId())); } @Test public void testIsNotInvitationAllowed() throws Exception { expectIsInvitationAllowed(CreatorState.DISSOLVED); - assertFalse(groupInvitationManager - .isInvitationAllowed(contact, privateGroup.getId())); + assertEquals(INVITED, groupInvitationManager + .getSharingStatus(contact, privateGroup.getId())); expectIsInvitationAllowed(CreatorState.ERROR); - assertFalse(groupInvitationManager - .isInvitationAllowed(contact, privateGroup.getId())); + assertEquals(INVITED, groupInvitationManager + .getSharingStatus(contact, privateGroup.getId())); expectIsInvitationAllowed(CreatorState.INVITED); - assertFalse(groupInvitationManager - .isInvitationAllowed(contact, privateGroup.getId())); + assertEquals(INVITED, groupInvitationManager + .getSharingStatus(contact, privateGroup.getId())); expectIsInvitationAllowed(CreatorState.JOINED); - assertFalse(groupInvitationManager - .isInvitationAllowed(contact, privateGroup.getId())); + assertEquals(SHARING, groupInvitationManager + .getSharingStatus(contact, privateGroup.getId())); expectIsInvitationAllowed(CreatorState.LEFT); - assertFalse(groupInvitationManager - .isInvitationAllowed(contact, privateGroup.getId())); + assertEquals(INVITED, groupInvitationManager + .getSharingStatus(contact, privateGroup.getId())); } private void expectIsInvitationAllowed(CreatorState state) diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/AbstractAutoDeleteIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/AbstractAutoDeleteIntegrationTest.java index 9de9d5421..390c2fc37 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/AbstractAutoDeleteIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/AbstractAutoDeleteIntegrationTest.java @@ -19,6 +19,7 @@ import java.util.Collection; import static org.briarproject.bramble.api.cleanup.CleanupManager.BATCH_DELAY_MS; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; import static org.briarproject.briar.test.TestEventListener.assertEvent; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -146,8 +147,8 @@ public abstract class AbstractAutoDeleteIntegrationTest waitForEvents(c1); // 0 can invite 1 again - assertTrue(getSharingManager0() - .canBeShared(getShareable().getId(), contact1From0)); + assertEquals(SHAREABLE, getSharingManager0().getSharingStatus( + getShareable().getId(), contact1From0)); // Before 1's timer elapses, 1 should still see the auto-decline message c0.getTimeTravel().addCurrentTimeMillis(timerLatency - 1); @@ -183,8 +184,8 @@ public abstract class AbstractAutoDeleteIntegrationTest assertEquals(0, getMessageHeaders(c0, contactId1From0).size()); // 0 can invite 1 again and really does invite - assertTrue(getSharingManager0() - .canBeShared(getShareable().getId(), contact1From0)); + assertEquals(SHAREABLE, getSharingManager0() + .getSharingStatus(getShareable().getId(), contact1From0)); // Send invitation getSharingManager0() .sendInvitation(getShareable().getId(), contactId1From0, diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java index e3578248f..82477e136 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingIntegrationTest.java @@ -33,6 +33,8 @@ import java.util.Collection; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS; import static org.briarproject.briar.api.blog.BlogSharingManager.CLIENT_ID; import static org.briarproject.briar.api.blog.BlogSharingManager.MAJOR_VERSION; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING; import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -106,14 +108,18 @@ public class BlogSharingIntegrationTest public void testPersonalBlogCannotBeSharedWithOwner() throws Exception { listenToEvents(true); - assertFalse(blogSharingManager0.canBeShared(blog1.getId(), - contact1From0)); - assertFalse(blogSharingManager0.canBeShared(blog2.getId(), - contact2From0)); - assertFalse(blogSharingManager1.canBeShared(blog0.getId(), - contact0From1)); - assertFalse(blogSharingManager2.canBeShared(blog0.getId(), - contact0From2)); + assertEquals(SHARING, + blogSharingManager0.getSharingStatus(blog1.getId(), + contact1From0)); + assertEquals(SHARING, + blogSharingManager0.getSharingStatus(blog2.getId(), + contact2From0)); + assertEquals(SHARING, + blogSharingManager1.getSharingStatus(blog0.getId(), + contact0From1)); + assertEquals(SHARING, + blogSharingManager2.getSharingStatus(blog0.getId(), + contact0From2)); } @Test @@ -191,13 +197,13 @@ public class BlogSharingIntegrationTest } // sharer has own invitation message and response assertEquals(2, db0.transactionWithResult(true, txn -> - blogSharingManager0.getMessageHeaders(txn, contactId1From0)) + blogSharingManager0.getMessageHeaders(txn, contactId1From0)) .size()); // blog can not be shared again - assertFalse(blogSharingManager0.canBeShared(blog2.getId(), - contact1From0)); - assertFalse(blogSharingManager1.canBeShared(blog2.getId(), - contact0From1)); + assertEquals(SHARING, blogSharingManager0.getSharingStatus( + blog2.getId(), contact1From0)); + assertEquals(SHARING, blogSharingManager1.getSharingStatus( + blog2.getId(), contact0From1)); // group message count is still correct assertGroupCount(messageTracker0, g, 2, 1); @@ -300,13 +306,13 @@ public class BlogSharingIntegrationTest } // sharer has own invitation message and response assertEquals(2, db0.transactionWithResult(true, txn -> - blogSharingManager0.getMessageHeaders(txn, contactId1From0)) + blogSharingManager0.getMessageHeaders(txn, contactId1From0)) .size()); // blog can not be shared again - assertFalse(blogSharingManager0.canBeShared(rssBlog.getId(), - contact1From0)); - assertFalse(blogSharingManager1.canBeShared(rssBlog.getId(), - contact0From1)); + assertEquals(SHARING, blogSharingManager0.getSharingStatus( + rssBlog.getId(), contact1From0)); + assertEquals(SHARING, blogSharingManager1.getSharingStatus( + rssBlog.getId(), contact0From1)); // group message count is still correct assertGroupCount(messageTracker0, g, 2, 1); @@ -361,11 +367,11 @@ public class BlogSharingIntegrationTest } // sharer has own invitation message and response assertEquals(2, db0.transactionWithResult(true, txn -> - blogSharingManager0.getMessageHeaders(txn, contactId1From0)) + blogSharingManager0.getMessageHeaders(txn, contactId1From0)) .size()); // blog can be shared again - assertTrue( - blogSharingManager0.canBeShared(blog2.getId(), contact1From0)); + assertEquals(SHAREABLE, blogSharingManager0.getSharingStatus( + blog2.getId(), contact1From0)); } @Test @@ -416,8 +422,8 @@ public class BlogSharingIntegrationTest assertEquals(0, blogSharingManager1.getSharedWith(blog2.getId()).size()); // blog can be shared again by sharer - assertTrue( - blogSharingManager0.canBeShared(blog2.getId(), contact1From0)); + assertEquals(SHAREABLE, blogSharingManager0.getSharingStatus( + blog2.getId(), contact1From0)); } @Test @@ -534,8 +540,8 @@ public class BlogSharingIntegrationTest .contains(contact0From1)); // 1 can again share blog 1 with 0 - assertTrue( - blogSharingManager1.canBeShared(blog1.getId(), contact0From1)); + assertEquals(SHAREABLE, blogSharingManager1.getSharingStatus( + blog1.getId(), contact0From1)); } @Test @@ -592,8 +598,8 @@ public class BlogSharingIntegrationTest } // 0 can share blog2 again with 1 - assertTrue( - blogSharingManager0.canBeShared(blog2.getId(), contact1From0)); + assertEquals(SHAREABLE, blogSharingManager0.getSharingStatus( + blog2.getId(), contact1From0)); } @NotNullByDefault diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java index 50f288d1e..bf0a799a7 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java @@ -47,6 +47,9 @@ import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS; import static org.briarproject.briar.api.forum.ForumSharingManager.CLIENT_ID; import static org.briarproject.briar.api.forum.ForumSharingManager.MAJOR_VERSION; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.INVITED; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE; +import static org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING; import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -183,9 +186,11 @@ public class ForumSharingIntegrationTest assertEquals(2, getMessages1From0().size()); // forum can not be shared again Contact c1 = contactManager0.getContact(contactId1From0); - assertFalse(forumSharingManager0.canBeShared(forum.getId(), c1)); + assertEquals(SHARING, + forumSharingManager0.getSharingStatus(forum.getId(), c1)); Contact c0 = contactManager1.getContact(contactId0From1); - assertFalse(forumSharingManager1.canBeShared(forum.getId(), c0)); + assertEquals(SHARING, + forumSharingManager1.getSharingStatus(forum.getId(), c0)); } @Test @@ -271,7 +276,8 @@ public class ForumSharingIntegrationTest assertEquals(2, getMessages1From0().size()); // forum can be shared again Contact c1 = contactManager0.getContact(contactId1From0); - assertTrue(forumSharingManager0.canBeShared(forum.getId(), c1)); + assertEquals(SHAREABLE, + forumSharingManager0.getSharingStatus(forum.getId(), c1)); // sharer un-subscribes from forum forumManager0.removeForum(forum); @@ -340,18 +346,18 @@ public class ForumSharingIntegrationTest assertFalse(forumSharingManager1.getSharedWith(forum.getId()) .contains(contact0)); // forum can be shared again by sharer - assertTrue(forumSharingManager0 - .canBeShared(forum.getId(), contact1From0)); + assertEquals(SHAREABLE, forumSharingManager0 + .getSharingStatus(forum.getId(), contact1From0)); // invitee that left can not yet share again - assertFalse(forumSharingManager1 - .canBeShared(forum.getId(), contact0From1)); + assertEquals(INVITED, forumSharingManager1 + .getSharingStatus(forum.getId(), contact0From1)); // sharer responds with leave message sync0To1(1, true); // invitee that left can now share again - assertTrue(forumSharingManager1 - .canBeShared(forum.getId(), contact0From1)); + assertEquals(SHAREABLE, forumSharingManager1 + .getSharingStatus(forum.getId(), contact0From1)); } @Test @@ -405,13 +411,15 @@ public class ForumSharingIntegrationTest assertFalse(forumSharingManager1.getSharedWith(forum.getId()) .contains(contact0)); // forum can be re-shared by invitee now - assertTrue(forumSharingManager1.canBeShared(forum.getId(), c0)); + assertEquals(SHAREABLE, + forumSharingManager1.getSharingStatus(forum.getId(), c0)); // invitee responds with LEAVE message sync1To0(1, true); // sharer can share forum again as well now - assertTrue(forumSharingManager0.canBeShared(forum.getId(), c1)); + assertEquals(SHAREABLE, + forumSharingManager0.getSharingStatus(forum.getId(), c1)); // invitee also un-subscribes forum without effect forumManager1.removeForum(forum); @@ -621,10 +629,10 @@ public class ForumSharingIntegrationTest addContacts1And2(); // forum can be shared with contacts again - assertTrue(forumSharingManager0 - .canBeShared(forum.getId(), contact1From0)); - assertTrue(forumSharingManager0 - .canBeShared(forum.getId(), contact2From0)); + assertEquals(SHAREABLE, forumSharingManager0 + .getSharingStatus(forum.getId(), contact1From0)); + assertEquals(SHAREABLE, forumSharingManager0 + .getSharingStatus(forum.getId(), contact2From0)); // send invitation forumSharingManager0