mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Messages in restricted groups should propagate without moderation.
If the group's owner is spamming, unsubscribe.
This commit is contained in:
@@ -234,7 +234,6 @@ implements DatabaseListener, OnClickListener, OnItemClickListener {
|
||||
i.putExtra("net.sf.briar.MESSAGE_ID", item.getId().getBytes());
|
||||
Author author = item.getAuthor();
|
||||
if(author != null) {
|
||||
i.putExtra("net.sf.briar.AUTHOR_ID", author.getId().getBytes());
|
||||
i.putExtra("net.sf.briar.AUTHOR_NAME", author.getName());
|
||||
i.putExtra("net.sf.briar.RATING", item.getRating().toString());
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import net.sf.briar.android.BriarService;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.android.widgets.HorizontalBorder;
|
||||
import net.sf.briar.android.widgets.HorizontalSpace;
|
||||
import net.sf.briar.api.AuthorId;
|
||||
import net.sf.briar.api.android.BundleEncrypter;
|
||||
import net.sf.briar.api.android.DatabaseUiExecutor;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
@@ -66,8 +65,7 @@ implements OnClickListener {
|
||||
private Rating rating = UNRATED;
|
||||
private boolean read;
|
||||
private ImageView thumb = null;
|
||||
private ImageButton goodButton = null, badButton = null, readButton = null;
|
||||
private ImageButton prevButton = null, nextButton = null;
|
||||
private ImageButton readButton = null, prevButton = null, nextButton = null;
|
||||
private ImageButton replyButton = null;
|
||||
private TextView content = null;
|
||||
|
||||
@@ -75,7 +73,6 @@ implements OnClickListener {
|
||||
@Inject private volatile DatabaseComponent db;
|
||||
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
|
||||
private volatile MessageId messageId = null;
|
||||
private volatile AuthorId authorId = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
@@ -92,15 +89,9 @@ implements OnClickListener {
|
||||
b = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
messageId = new MessageId(b);
|
||||
String authorName = null;
|
||||
b = i.getByteArrayExtra("net.sf.briar.AUTHOR_ID");
|
||||
if(b != null) {
|
||||
authorId = new AuthorId(b);
|
||||
authorName = i.getStringExtra("net.sf.briar.AUTHOR_NAME");
|
||||
if(authorName == null) throw new IllegalStateException();
|
||||
String r = i.getStringExtra("net.sf.briar.RATING");
|
||||
if(r != null) rating = Rating.valueOf(r);
|
||||
}
|
||||
String authorName = i.getStringExtra("net.sf.briar.AUTHOR_NAME");
|
||||
String r = i.getStringExtra("net.sf.briar.RATING");
|
||||
if(r != null) rating = Rating.valueOf(r);
|
||||
String contentType = i.getStringExtra("net.sf.briar.CONTENT_TYPE");
|
||||
if(contentType == null) throw new IllegalStateException();
|
||||
long timestamp = i.getLongExtra("net.sf.briar.TIMESTAMP", -1);
|
||||
@@ -177,23 +168,6 @@ implements OnClickListener {
|
||||
footer.setOrientation(HORIZONTAL);
|
||||
footer.setGravity(CENTER);
|
||||
|
||||
goodButton = new ImageButton(this);
|
||||
goodButton.setBackgroundResource(0);
|
||||
goodButton.setImageResource(R.drawable.rating_good);
|
||||
if(authorName == null) goodButton.setEnabled(false);
|
||||
else goodButton.setOnClickListener(this);
|
||||
footer.addView(goodButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
badButton = new ImageButton(this);
|
||||
badButton.setBackgroundResource(0);
|
||||
badButton.setImageResource(R.drawable.rating_bad);
|
||||
badButton.setOnClickListener(this);
|
||||
if(authorName == null) badButton.setEnabled(false);
|
||||
else badButton.setOnClickListener(this);
|
||||
footer.addView(badButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
readButton = new ImageButton(this);
|
||||
readButton.setBackgroundResource(0);
|
||||
if(read) readButton.setImageResource(R.drawable.content_unread);
|
||||
@@ -309,13 +283,7 @@ implements OnClickListener {
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
if(view == goodButton) {
|
||||
if(rating == BAD) setRatingInDatabase(UNRATED);
|
||||
else if(rating == UNRATED) setRatingInDatabase(GOOD);
|
||||
} else if(view == badButton) {
|
||||
if(rating == GOOD) setRatingInDatabase(UNRATED);
|
||||
else if(rating == UNRATED) setRatingInDatabase(BAD);
|
||||
} else if(view == readButton) {
|
||||
if(view == readButton) {
|
||||
setReadInDatabase(!read);
|
||||
} else if(view == prevButton) {
|
||||
setResult(RESULT_PREV);
|
||||
@@ -337,38 +305,4 @@ implements OnClickListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setRatingInDatabase(final Rating r) {
|
||||
dbUiExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
db.setRating(authorId, r);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Setting rating took " + duration + " ms");
|
||||
setRatingInUi(r);
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setRatingInUi(final Rating r) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
rating = r;
|
||||
if(r == GOOD) thumb.setImageResource(R.drawable.rating_good);
|
||||
else if(r == BAD) thumb.setImageResource(R.drawable.rating_bad);
|
||||
else thumb.setImageResource(R.drawable.rating_unrated);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,14 +352,6 @@ interface Database<T> {
|
||||
Collection<PrivateMessageHeader> getPrivateMessageHeaders(T txn,
|
||||
ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs of all messages signed by the given author.
|
||||
* <p>
|
||||
* Locking: message read.
|
||||
*/
|
||||
Collection<MessageId> getMessagesByAuthor(T txn, AuthorId a)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs of some messages received from the given contact that
|
||||
* need to be acknowledged, up to the given number of messages.
|
||||
@@ -554,6 +546,15 @@ interface Database<T> {
|
||||
*/
|
||||
Map<GroupId, Integer> getUnreadMessageCounts(T txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs of all messages posted by the given author to
|
||||
* unrestricted groups.
|
||||
* <p>
|
||||
* Locking: message read.
|
||||
*/
|
||||
Collection<MessageId> getUnrestrictedGroupMessages(T txn, AuthorId a)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the contacts to which the given group is visible.
|
||||
* <p>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1601,27 +1601,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MessageId> getMessagesByAuthor(Connection txn, AuthorId a)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT messageId FROM messages WHERE authorId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, a.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
List<MessageId> ids = new ArrayList<MessageId>();
|
||||
while(rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||
rs.close();
|
||||
ps.close();
|
||||
return Collections.unmodifiableList(ids);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MessageId> getMessagesToAck(Connection txn, ContactId c,
|
||||
int maxMessages) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -2568,6 +2547,32 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MessageId> getUnrestrictedGroupMessages(Connection txn,
|
||||
AuthorId a) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT messageId"
|
||||
+ " FROM messages AS m"
|
||||
+ " JOIN groups AS g"
|
||||
+ " ON m.groupId = g.groupId"
|
||||
+ " WHERE authorId = ?"
|
||||
+ " AND publicKey IS NULL";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, a.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
List<MessageId> ids = new ArrayList<MessageId>();
|
||||
while(rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||
rs.close();
|
||||
ps.close();
|
||||
return Collections.unmodifiableList(ids);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<ContactId> getVisibility(Connection txn, GroupId g)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
|
||||
@@ -59,13 +59,13 @@ import org.junit.Test;
|
||||
public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
|
||||
protected final Object txn = new Object();
|
||||
protected final GroupId groupId;
|
||||
protected final Group group;
|
||||
protected final GroupId groupId, restrictedGroupId;
|
||||
protected final Group group, restrictedGroup;
|
||||
protected final AuthorId authorId;
|
||||
protected final Author author;
|
||||
protected final AuthorId localAuthorId;
|
||||
protected final LocalAuthor localAuthor;
|
||||
protected final MessageId messageId, messageId1;
|
||||
protected final MessageId messageId, messageId1, privateMessageId;
|
||||
protected final String contentType, subject;
|
||||
protected final long timestamp;
|
||||
protected final int size;
|
||||
@@ -81,7 +81,10 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
public DatabaseComponentTest() {
|
||||
super();
|
||||
groupId = new GroupId(TestUtils.getRandomId());
|
||||
restrictedGroupId = new GroupId(TestUtils.getRandomId());
|
||||
group = new Group(groupId, "Group name", null);
|
||||
restrictedGroup = new Group(restrictedGroupId, "Restricted group name",
|
||||
new byte[60]);
|
||||
authorId = new AuthorId(TestUtils.getRandomId());
|
||||
author = new Author(authorId, "Alice", new byte[60]);
|
||||
localAuthorId = new AuthorId(TestUtils.getRandomId());
|
||||
@@ -89,6 +92,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
new byte[60]);
|
||||
messageId = new MessageId(TestUtils.getRandomId());
|
||||
messageId1 = new MessageId(TestUtils.getRandomId());
|
||||
privateMessageId = new MessageId(TestUtils.getRandomId());
|
||||
contentType = "text/plain";
|
||||
subject = "Foo";
|
||||
timestamp = System.currentTimeMillis();
|
||||
@@ -96,7 +100,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
raw = new byte[size];
|
||||
message = new TestMessage(messageId, null, group, author, contentType,
|
||||
subject, timestamp, raw);
|
||||
privateMessage = new TestMessage(messageId, null, null, null,
|
||||
privateMessage = new TestMessage(privateMessageId, null, null, null,
|
||||
contentType, subject, timestamp, raw);
|
||||
transportId = new TransportId(TestUtils.getRandomId());
|
||||
transportProperties = new TransportProperties(Collections.singletonMap(
|
||||
@@ -139,7 +143,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
// setRating(authorId, GOOD)
|
||||
oneOf(database).setRating(txn, authorId, GOOD);
|
||||
will(returnValue(UNRATED));
|
||||
oneOf(database).getMessagesByAuthor(txn, authorId);
|
||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
||||
will(returnValue(Collections.emptyList()));
|
||||
oneOf(listener).eventOccurred(with(any(RatingChangedEvent.class)));
|
||||
// setRating(authorId, GOOD) again
|
||||
@@ -223,6 +227,59 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestrictedGroupMessagesAreAlwaysSendable()
|
||||
throws Exception {
|
||||
final Message groupMessage = new TestMessage(messageId, null,
|
||||
restrictedGroup, author, contentType, subject, timestamp, raw);
|
||||
final Message groupMessage1 = new TestMessage(messageId1, null,
|
||||
restrictedGroup, null, contentType, subject, timestamp, raw);
|
||||
Mockery context = new Mockery();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
||||
context.checking(new Expectations() {{
|
||||
// addLocalGroupMessage(groupMessage)
|
||||
oneOf(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
oneOf(database).containsSubscription(txn, restrictedGroupId);
|
||||
will(returnValue(true));
|
||||
oneOf(database).addGroupMessage(txn, groupMessage, false);
|
||||
will(returnValue(true));
|
||||
oneOf(database).setReadFlag(txn, messageId, true);
|
||||
oneOf(database).getContactIds(txn);
|
||||
will(returnValue(Arrays.asList(contactId)));
|
||||
oneOf(database).addStatus(txn, contactId, messageId, false);
|
||||
oneOf(database).setSendability(txn, messageId, 1);
|
||||
oneOf(database).commitTransaction(txn);
|
||||
// receiveMessage(groupMessage1)
|
||||
oneOf(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
oneOf(database).containsContact(txn, contactId);
|
||||
will(returnValue(true));
|
||||
oneOf(database).containsVisibleSubscription(txn, contactId,
|
||||
restrictedGroupId);
|
||||
will(returnValue(true));
|
||||
oneOf(database).addGroupMessage(txn, groupMessage1, true);
|
||||
will(returnValue(true));
|
||||
oneOf(database).addStatus(txn, contactId, messageId1, true);
|
||||
oneOf(database).getContactIds(txn);
|
||||
will(returnValue(Arrays.asList(contactId)));
|
||||
oneOf(database).setSendability(txn, messageId1, 1);
|
||||
oneOf(database).addMessageToAck(txn, contactId, messageId1);
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown);
|
||||
|
||||
db.addLocalGroupMessage(groupMessage);
|
||||
db.receiveMessage(contactId, groupMessage1);
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullParentStopsBackwardInclusion() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
@@ -237,7 +294,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).setRating(txn, authorId, GOOD);
|
||||
will(returnValue(UNRATED));
|
||||
// The sendability of the author's messages should be incremented
|
||||
oneOf(database).getMessagesByAuthor(txn, authorId);
|
||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
||||
will(returnValue(Arrays.asList(messageId)));
|
||||
oneOf(database).getSendability(txn, messageId);
|
||||
will(returnValue(0));
|
||||
@@ -269,7 +326,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).setRating(txn, authorId, GOOD);
|
||||
will(returnValue(UNRATED));
|
||||
// The sendability of the author's messages should be incremented
|
||||
oneOf(database).getMessagesByAuthor(txn, authorId);
|
||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
||||
will(returnValue(Arrays.asList(messageId)));
|
||||
oneOf(database).getSendability(txn, messageId);
|
||||
will(returnValue(0));
|
||||
@@ -306,7 +363,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).setRating(txn, authorId, GOOD);
|
||||
will(returnValue(UNRATED));
|
||||
// The sendability of the author's messages should be incremented
|
||||
oneOf(database).getMessagesByAuthor(txn, authorId);
|
||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
||||
will(returnValue(Arrays.asList(messageId)));
|
||||
oneOf(database).getSendability(txn, messageId);
|
||||
will(returnValue(0));
|
||||
@@ -497,8 +554,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).addPrivateMessage(txn, privateMessage, contactId,
|
||||
false);
|
||||
will(returnValue(true));
|
||||
oneOf(database).setReadFlag(txn, messageId, true);
|
||||
oneOf(database).addStatus(txn, contactId, messageId, false);
|
||||
oneOf(database).setReadFlag(txn, privateMessageId, true);
|
||||
oneOf(database).addStatus(txn, contactId, privateMessageId, false);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown);
|
||||
@@ -1154,9 +1211,9 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).addPrivateMessage(txn, privateMessage, contactId,
|
||||
true);
|
||||
will(returnValue(true));
|
||||
oneOf(database).addStatus(txn, contactId, messageId, true);
|
||||
oneOf(database).addStatus(txn, contactId, privateMessageId, true);
|
||||
// The message must be acked
|
||||
oneOf(database).addMessageToAck(txn, contactId, messageId);
|
||||
oneOf(database).addMessageToAck(txn, contactId, privateMessageId);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown);
|
||||
@@ -1184,7 +1241,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
true);
|
||||
will(returnValue(false));
|
||||
// The message must still be acked
|
||||
oneOf(database).addMessageToAck(txn, contactId, messageId);
|
||||
oneOf(database).addMessageToAck(txn, contactId, privateMessageId);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown);
|
||||
@@ -1561,8 +1618,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).addPrivateMessage(txn, privateMessage, contactId,
|
||||
false);
|
||||
will(returnValue(true));
|
||||
oneOf(database).setReadFlag(txn, messageId, true);
|
||||
oneOf(database).addStatus(txn, contactId, messageId, false);
|
||||
oneOf(database).setReadFlag(txn, privateMessageId, true);
|
||||
oneOf(database).addStatus(txn, contactId, privateMessageId, false);
|
||||
// The message was added, so the listener should be called
|
||||
oneOf(listener).eventOccurred(with(any(
|
||||
PrivateMessageAddedEvent.class)));
|
||||
|
||||
@@ -534,27 +534,39 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMessagesByAuthor() throws Exception {
|
||||
public void testGetUnrestrictedGroupMessages() throws Exception {
|
||||
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
||||
Author author1 = new Author(authorId1, "Bob", new byte[60]);
|
||||
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||
Message message1 = new TestMessage(messageId1, null, group, author1,
|
||||
contentType, subject, timestamp, raw);
|
||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||
Group group1 = new Group(groupId1, "Restricted group name",
|
||||
new byte[60]);
|
||||
MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
||||
Message message2 = new TestMessage(messageId2, null, group1, author,
|
||||
contentType, subject, timestamp, raw);
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Subscribe to a group and store two messages
|
||||
// Subscribe to an unrestricted group and store two messages
|
||||
db.addSubscription(txn, group);
|
||||
db.addGroupMessage(txn, message, false);
|
||||
db.addGroupMessage(txn, message1, false);
|
||||
|
||||
// Check that each message is retrievable via its author
|
||||
Iterator<MessageId> it =
|
||||
db.getMessagesByAuthor(txn, authorId).iterator();
|
||||
// Subscribe to a restricted group and store a message
|
||||
db.addSubscription(txn, group1);
|
||||
db.addGroupMessage(txn, message2, false);
|
||||
|
||||
// Check that only the messages in the unrestricted group are retrieved
|
||||
Collection<MessageId> ids = db.getUnrestrictedGroupMessages(txn,
|
||||
authorId);
|
||||
Iterator<MessageId> it = ids.iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(messageId, it.next());
|
||||
assertFalse(it.hasNext());
|
||||
it = db.getMessagesByAuthor(txn, authorId1).iterator();
|
||||
ids = db.getUnrestrictedGroupMessages(txn, authorId1);
|
||||
it = ids.iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(messageId1, it.next());
|
||||
assertFalse(it.hasNext());
|
||||
|
||||
Reference in New Issue
Block a user