From ab100ad19b8b84c85c441ace80c62dfb6d4cd705 Mon Sep 17 00:00:00 2001
From: Torsten Grote <t@grobox.de>
Date: Wed, 4 Jan 2017 16:12:33 -0200
Subject: [PATCH] Properly remove the blog when deleting a contact and inform
 all peers

Fixes #816
---
 .../briar/blog/BlogManagerImpl.java           | 19 +++---
 .../sharing/BlogSharingIntegrationTest.java   | 62 +++++++++++++++++++
 2 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
index 2178d42326..ab4c1c373e 100644
--- a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
@@ -31,6 +31,7 @@ import org.briarproject.briar.api.blog.BlogPostFactory;
 import org.briarproject.briar.api.blog.BlogPostHeader;
 import org.briarproject.briar.api.blog.MessageType;
 import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
+import org.briarproject.briar.api.client.ProtocolStateException;
 import org.briarproject.briar.client.BdfIncomingMessageHook;
 
 import java.security.GeneralSecurityException;
@@ -119,7 +120,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 	@Override
 	public void removingContact(Transaction txn, Contact c) throws DbException {
 		Blog b = blogFactory.createBlog(c.getAuthor());
-		db.removeGroup(txn, b.getGroup());
+		removeBlog(txn, b, true);
 	}
 
 	@Override
@@ -215,20 +216,24 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 
 	@Override
 	public void removeBlog(Blog b) throws DbException {
-		// TODO if this gets used, check for RSS feeds posting into this blog
 		Transaction txn = db.startTransaction(false);
 		try {
-			if (!canBeRemoved(txn, b.getId()))
-				throw new DbException();
-			for (RemoveBlogHook hook : removeHooks)
-				hook.removingBlog(txn, b);
-			db.removeGroup(txn, b.getGroup());
+			removeBlog(txn, b, false);
 			db.commitTransaction(txn);
 		} finally {
 			db.endTransaction(txn);
 		}
 	}
 
+	private void removeBlog(Transaction txn, Blog b, boolean forced)
+			throws DbException {
+		if (!forced && !canBeRemoved(txn, b.getId()))
+			throw new ProtocolStateException();
+		for (RemoveBlogHook hook : removeHooks)
+			hook.removingBlog(txn, b);
+		db.removeGroup(txn, b.getGroup());
+	}
+
 	@Override
 	public void addLocalPost(BlogPost p) throws DbException {
 		Transaction txn = db.startTransaction(false);
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 5f725591f1..32b3f9d5a5 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
@@ -4,6 +4,7 @@ import net.jodah.concurrentunit.Waiter;
 
 import org.briarproject.bramble.api.contact.Contact;
 import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
 import org.briarproject.bramble.api.event.Event;
 import org.briarproject.bramble.api.event.EventListener;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -34,7 +35,9 @@ import static org.briarproject.briar.api.blog.BlogSharingManager.CLIENT_ID;
 import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 public class BlogSharingIntegrationTest
 		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
@@ -424,6 +427,65 @@ public class BlogSharingIntegrationTest
 		assertFalse(blogManager1.canBeRemoved(blog2.getId()));
 	}
 
+	@Test
+	public void testSharerIsInformedWhenBlogIsRemovedDueToContactDeletion()
+			throws Exception {
+		// initialize and let invitee accept all requests
+		listenToEvents(true);
+
+		// sharer sends invitation for 2's blog to 1
+		blogSharingManager0
+				.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
+						clock.currentTimeMillis());
+
+		// sync first request message
+		sync0To1(1, true);
+		eventWaiter.await(TIMEOUT, 1);
+		assertTrue(listener1.requestReceived);
+
+		// sync response back
+		sync1To0(1, true);
+		eventWaiter.await(TIMEOUT, 1);
+		assertTrue(listener0.responseReceived);
+
+		// 1 and 2 are adding each other
+		addContacts1And2();
+		assertEquals(3, blogManager1.getBlogs().size());
+
+		// make sure blog2 is shared between 0 and 1
+		Collection<Contact> contacts =
+				blogSharingManager1.getSharedWith(blog2.getId());
+		assertEquals(2, contacts.size());
+		assertTrue(contacts.contains(contact0From1));
+		contacts = blogSharingManager0.getSharedWith(blog2.getId());
+		assertEquals(2, contacts.size());
+		assertTrue(contacts.contains(contact1From0));
+
+		// 1 removes contact 2
+		assertNotNull(contactId2From1);
+		contactManager1.removeContact(contactId2From1);
+
+		// sync leave message to 0
+		sync1To0(1, true);
+
+		// make sure blog2 is no longer shared between 0 and 1
+		contacts = blogSharingManager0.getSharedWith(blog2.getId());
+		assertEquals(1, contacts.size());
+		assertFalse(contacts.contains(contact1From0));
+
+		// 1 doesn't even have blog2 anymore
+		try {
+			blogManager1.getBlog(blog2.getId());
+			fail();
+		} catch (NoSuchGroupException e) {
+			// expected
+		}
+
+		// 0 can share blog2 again with 1
+		assertTrue(
+				blogSharingManager0.canBeShared(blog2.getId(), contact1From0));
+	}
+
 	@NotNullByDefault
 	private class SharerListener implements EventListener {
 
-- 
GitLab