mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 20:29:52 +01:00
Added activities for managing blog and group subscriptions.
This commit is contained in:
@@ -17,6 +17,7 @@ import net.sf.briar.api.db.GroupMessageHeader;
|
||||
import net.sf.briar.api.db.PrivateMessageHeader;
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.GroupStatus;
|
||||
import net.sf.briar.api.messaging.LocalGroup;
|
||||
import net.sf.briar.api.messaging.Message;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
@@ -191,6 +192,14 @@ interface Database<T> {
|
||||
*/
|
||||
boolean containsContact(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the database contains the given restricted group to
|
||||
* which the user can post messages.
|
||||
* <p>
|
||||
* Locking: identity read.
|
||||
*/
|
||||
boolean containsLocalGroup(T txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the database contains the given message.
|
||||
* <p>
|
||||
@@ -222,10 +231,11 @@ interface Database<T> {
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns any groups that contacts have made visible but to which the user
|
||||
* does not subscribe.
|
||||
* Returns the status of all groups to which the user can subscribe.
|
||||
* <p>
|
||||
* Locking: subscription read.
|
||||
*/
|
||||
Collection<Group> getAvailableGroups(T txn) throws DbException;
|
||||
Collection<GroupStatus> getAvailableGroups(T txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the configuration for the given transport.
|
||||
@@ -621,6 +631,13 @@ interface Database<T> {
|
||||
*/
|
||||
void removeContact(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Removes the given restricted group to which the user can post messages.
|
||||
* <p>
|
||||
* Locking: identity write.
|
||||
*/
|
||||
void removeLocalGroup(T txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Removes a message (and all associated state) from the database.
|
||||
* <p>
|
||||
@@ -797,7 +814,7 @@ interface Database<T> {
|
||||
* <p>
|
||||
* Locking: subscription write.
|
||||
*/
|
||||
void setVisibleToAll(T txn, GroupId g, boolean visible) throws DbException;
|
||||
void setVisibleToAll(T txn, GroupId g, boolean all) throws DbException;
|
||||
|
||||
/**
|
||||
* Updates the expiry times of the given messages with respect to the given
|
||||
|
||||
@@ -64,6 +64,7 @@ import net.sf.briar.api.lifecycle.ShutdownManager;
|
||||
import net.sf.briar.api.messaging.Ack;
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.GroupStatus;
|
||||
import net.sf.briar.api.messaging.LocalGroup;
|
||||
import net.sf.briar.api.messaging.Message;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
@@ -887,12 +888,12 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Group> getAvailableGroups() throws DbException {
|
||||
public Collection<GroupStatus> getAvailableGroups() throws DbException {
|
||||
subscriptionLock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
Collection<Group> groups = db.getAvailableGroups(txn);
|
||||
Collection<GroupStatus> groups = db.getAvailableGroups(txn);
|
||||
db.commitTransaction(txn);
|
||||
return groups;
|
||||
} catch(DbException e) {
|
||||
@@ -2051,7 +2052,7 @@ DatabaseCleaner.Callback {
|
||||
callListeners(new LocalSubscriptionsUpdatedEvent(affected));
|
||||
}
|
||||
|
||||
public void setVisibleToAll(GroupId g, boolean visible) throws DbException {
|
||||
public void setVisibleToAll(GroupId g, boolean all) throws DbException {
|
||||
Collection<ContactId> affected = new ArrayList<ContactId>();
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
@@ -2062,8 +2063,8 @@ DatabaseCleaner.Callback {
|
||||
if(!db.containsSubscription(txn, g))
|
||||
throw new NoSuchSubscriptionException();
|
||||
// Make the group visible or invisible to future contacts
|
||||
db.setVisibleToAll(txn, g, visible);
|
||||
if(visible) {
|
||||
db.setVisibleToAll(txn, g, all);
|
||||
if(all) {
|
||||
// Make the group visible to all current contacts
|
||||
Collection<ContactId> before = db.getVisibility(txn, g);
|
||||
before = new HashSet<ContactId>(before);
|
||||
@@ -2111,27 +2112,34 @@ DatabaseCleaner.Callback {
|
||||
|
||||
public void unsubscribe(Group g) throws DbException {
|
||||
Collection<ContactId> affected;
|
||||
messageLock.writeLock().lock();
|
||||
identityLock.writeLock().lock();
|
||||
try {
|
||||
subscriptionLock.writeLock().lock();
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
subscriptionLock.writeLock().lock();
|
||||
try {
|
||||
GroupId id = g.getId();
|
||||
if(!db.containsSubscription(txn, id))
|
||||
throw new NoSuchSubscriptionException();
|
||||
affected = db.getVisibility(txn, id);
|
||||
db.removeSubscription(txn, id);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
GroupId id = g.getId();
|
||||
if(!db.containsSubscription(txn, id))
|
||||
throw new NoSuchSubscriptionException();
|
||||
affected = db.getVisibility(txn, id);
|
||||
db.removeSubscription(txn, id);
|
||||
if(db.containsLocalGroup(txn, id))
|
||||
db.removeLocalGroup(txn, id);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.writeLock().unlock();
|
||||
messageLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
messageLock.writeLock().unlock();
|
||||
identityLock.writeLock().unlock();
|
||||
}
|
||||
callListeners(new SubscriptionRemovedEvent(g));
|
||||
callListeners(new LocalSubscriptionsUpdatedEvent(affected));
|
||||
|
||||
@@ -75,7 +75,9 @@ class H2Database extends JdbcDatabase {
|
||||
|
||||
@Override
|
||||
protected Connection createConnection() throws SQLException {
|
||||
char[] password = encodePassword(config.getEncryptionKey());
|
||||
byte[] key = config.getEncryptionKey();
|
||||
if(key == null) throw new IllegalStateException();
|
||||
char[] password = encodePassword(key);
|
||||
Properties props = new Properties();
|
||||
props.setProperty("user", "user");
|
||||
props.put("password", password);
|
||||
|
||||
@@ -19,10 +19,12 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.api.Author;
|
||||
@@ -40,6 +42,7 @@ import net.sf.briar.api.db.GroupMessageHeader;
|
||||
import net.sf.briar.api.db.PrivateMessageHeader;
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.GroupStatus;
|
||||
import net.sf.briar.api.messaging.LocalGroup;
|
||||
import net.sf.briar.api.messaging.Message;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
@@ -743,8 +746,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void addLocalGroup(Connection txn, LocalGroup g)
|
||||
throws DbException {
|
||||
public void addLocalGroup(Connection txn, LocalGroup g) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "INSERT INTO localGroups"
|
||||
@@ -1053,6 +1055,27 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsLocalGroup(Connection txn, GroupId g)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT NULL FROM localGroups WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
boolean found = rs.next();
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
return found;
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsMessage(Connection txn, MessageId m)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -1139,25 +1162,41 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Group> getAvailableGroups(Connection txn)
|
||||
public Collection<GroupStatus> getAvailableGroups(Connection txn)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT cg.groupId, cg.name, cg.publicKey"
|
||||
+ " FROM contactGroups AS cg"
|
||||
+ " LEFT OUTER JOIN groups AS g"
|
||||
+ " ON cg.groupId = g.groupId"
|
||||
+ " WHERE g.groupId IS NULL"
|
||||
+ " GROUP BY cg.groupId";
|
||||
// Add all subscribed groups to the list
|
||||
String sql = "SELECT groupId, name, publicKey, visibleToAll"
|
||||
+ " FROM groups";
|
||||
ps = txn.prepareStatement(sql);
|
||||
rs = ps.executeQuery();
|
||||
List<Group> groups = new ArrayList<Group>();
|
||||
List<GroupStatus> groups = new ArrayList<GroupStatus>();
|
||||
Set<GroupId> subscribed = new HashSet<GroupId>();
|
||||
while(rs.next()) {
|
||||
GroupId id = new GroupId(rs.getBytes(1));
|
||||
subscribed.add(id);
|
||||
String name = rs.getString(2);
|
||||
byte[] publicKey = rs.getBytes(3);
|
||||
groups.add(new Group(id, name, publicKey));
|
||||
Group group = new Group(id, name, publicKey);
|
||||
boolean visibleToAll = rs.getBoolean(4);
|
||||
groups.add(new GroupStatus(group, true, visibleToAll));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
// Add all contact groups to the list, unless already added
|
||||
sql = "SELECT DISTINCT groupId, name, publicKey"
|
||||
+ " FROM contactGroups";
|
||||
ps = txn.prepareStatement(sql);
|
||||
rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
GroupId id = new GroupId(rs.getBytes(1));
|
||||
if(subscribed.contains(id)) continue;
|
||||
String name = rs.getString(2);
|
||||
byte[] publicKey = rs.getBytes(3);
|
||||
Group group = new Group(id, name, publicKey);
|
||||
groups.add(new GroupStatus(group, false, false));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -2765,6 +2804,21 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void removeLocalGroup(Connection txn, GroupId g) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "DELETE FROM localGroups WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch(SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeMessage(Connection txn, MessageId m) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
@@ -3406,13 +3460,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void setVisibleToAll(Connection txn, GroupId g, boolean visible)
|
||||
public void setVisibleToAll(Connection txn, GroupId g, boolean all)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE groups SET visibleToAll = ? WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBoolean(1, visible);
|
||||
ps.setBoolean(1, all);
|
||||
ps.setBytes(2, g.getBytes());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected > 1) throw new DbStateException();
|
||||
|
||||
Reference in New Issue
Block a user