mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 06:39:54 +01:00
Backend for Automatic Personal Blogs
When a contact is added, her personal blog will also be added automatically. Also, when a new identity is added, a personal blog for that identity is created. Part of #436
This commit is contained in:
@@ -11,13 +11,16 @@ public class Blog extends Forum {
|
|||||||
private final String description;
|
private final String description;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Author author;
|
private final Author author;
|
||||||
|
private final boolean permanent;
|
||||||
|
|
||||||
public Blog(@NotNull Group group, @NotNull String name,
|
public Blog(@NotNull Group group, @NotNull String name,
|
||||||
@NotNull String description, @NotNull Author author) {
|
@NotNull String description, @NotNull Author author,
|
||||||
|
boolean permanent) {
|
||||||
super(group, name, null);
|
super(group, name, null);
|
||||||
|
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
|
this.permanent = permanent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -29,4 +32,8 @@ public class Blog extends Forum {
|
|||||||
public Author getAuthor() {
|
public Author getAuthor() {
|
||||||
return author;
|
return author;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPermanent() {
|
||||||
|
return permanent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ public interface BlogConstants {
|
|||||||
/** The maximum length of a blog post's body in bytes. */
|
/** The maximum length of a blog post's body in bytes. */
|
||||||
int MAX_BLOG_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
|
int MAX_BLOG_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
|
||||||
|
|
||||||
|
/** The internal name of personal blogs that are created automatically */
|
||||||
|
String PERSONAL_BLOG_NAME = "briar.PERSONAL_BLOG_NAME";
|
||||||
|
|
||||||
/* Blog Sharing Constants */
|
/* Blog Sharing Constants */
|
||||||
String BLOG_TITLE = "blogTitle";
|
String BLOG_TITLE = "blogTitle";
|
||||||
String BLOG_DESC = "blogDescription";
|
String BLOG_DESC = "blogDescription";
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.api.blogs;
|
package org.briarproject.api.blogs;
|
||||||
|
|
||||||
import org.briarproject.api.FormatException;
|
import org.briarproject.api.FormatException;
|
||||||
|
import org.briarproject.api.contact.Contact;
|
||||||
import org.briarproject.api.identity.Author;
|
import org.briarproject.api.identity.Author;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.sync.Group;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -11,6 +12,9 @@ public interface BlogFactory {
|
|||||||
Blog createBlog(@NotNull String name, @NotNull String description,
|
Blog createBlog(@NotNull String name, @NotNull String description,
|
||||||
@NotNull Author author);
|
@NotNull Author author);
|
||||||
|
|
||||||
|
/** Creates a personal blog for a given author. */
|
||||||
|
Blog createPersonalBlog(@NotNull Author author);
|
||||||
|
|
||||||
/** Parses a blog with the given Group and description */
|
/** Parses a blog with the given Group and description */
|
||||||
Blog parseBlog(@NotNull Group g, @NotNull String description)
|
Blog parseBlog(@NotNull Group g, @NotNull String description)
|
||||||
throws FormatException;
|
throws FormatException;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.api.blogs;
|
|||||||
|
|
||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
import org.briarproject.api.db.Transaction;
|
import org.briarproject.api.db.Transaction;
|
||||||
|
import org.briarproject.api.identity.Author;
|
||||||
import org.briarproject.api.identity.LocalAuthor;
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
import org.briarproject.api.sync.ClientId;
|
import org.briarproject.api.sync.ClientId;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
@@ -31,9 +32,12 @@ public interface BlogManager {
|
|||||||
/** Returns the blog with the given ID. */
|
/** Returns the blog with the given ID. */
|
||||||
Blog getBlog(Transaction txn, GroupId g) throws DbException;
|
Blog getBlog(Transaction txn, GroupId g) throws DbException;
|
||||||
|
|
||||||
/** Returns all blogs to which the localAuthor created. */
|
/** Returns all blogs owned by the given localAuthor. */
|
||||||
Collection<Blog> getBlogs(LocalAuthor localAuthor) throws DbException;
|
Collection<Blog> getBlogs(LocalAuthor localAuthor) throws DbException;
|
||||||
|
|
||||||
|
/** Returns only the personal blog of the given author. */
|
||||||
|
Blog getPersonalBlog(Author author) throws DbException;
|
||||||
|
|
||||||
/** Returns all blogs to which the user subscribes. */
|
/** Returns all blogs to which the user subscribes. */
|
||||||
Collection<Blog> getBlogs() throws DbException;
|
Collection<Blog> getBlogs() throws DbException;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import org.briarproject.api.FormatException;
|
|||||||
import org.briarproject.api.blogs.Blog;
|
import org.briarproject.api.blogs.Blog;
|
||||||
import org.briarproject.api.blogs.BlogFactory;
|
import org.briarproject.api.blogs.BlogFactory;
|
||||||
import org.briarproject.api.clients.ClientHelper;
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
|
import org.briarproject.api.contact.Contact;
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
import org.briarproject.api.identity.Author;
|
import org.briarproject.api.identity.Author;
|
||||||
import org.briarproject.api.identity.AuthorFactory;
|
import org.briarproject.api.identity.AuthorFactory;
|
||||||
@@ -13,6 +14,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.api.blogs.BlogConstants.PERSONAL_BLOG_NAME;
|
||||||
|
|
||||||
class BlogFactoryImpl implements BlogFactory {
|
class BlogFactoryImpl implements BlogFactory {
|
||||||
|
|
||||||
private final GroupFactory groupFactory;
|
private final GroupFactory groupFactory;
|
||||||
@@ -31,6 +34,16 @@ class BlogFactoryImpl implements BlogFactory {
|
|||||||
@Override
|
@Override
|
||||||
public Blog createBlog(@NotNull String name, @NotNull String description,
|
public Blog createBlog(@NotNull String name, @NotNull String description,
|
||||||
@NotNull Author author) {
|
@NotNull Author author) {
|
||||||
|
return createBlog(name, description, author, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Blog createPersonalBlog(@NotNull Author a) {
|
||||||
|
return createBlog(PERSONAL_BLOG_NAME, "", a, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Blog createBlog(@NotNull String name, @NotNull String description,
|
||||||
|
@NotNull Author author, boolean permanent) {
|
||||||
try {
|
try {
|
||||||
BdfList blog = BdfList.of(
|
BdfList blog = BdfList.of(
|
||||||
name,
|
name,
|
||||||
@@ -40,7 +53,7 @@ class BlogFactoryImpl implements BlogFactory {
|
|||||||
byte[] descriptor = clientHelper.toByteArray(blog);
|
byte[] descriptor = clientHelper.toByteArray(blog);
|
||||||
Group g = groupFactory
|
Group g = groupFactory
|
||||||
.createGroup(BlogManagerImpl.CLIENT_ID, descriptor);
|
.createGroup(BlogManagerImpl.CLIENT_ID, descriptor);
|
||||||
return new Blog(g, name, description, author);
|
return new Blog(g, name, description, author, permanent);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -55,7 +68,9 @@ class BlogFactoryImpl implements BlogFactory {
|
|||||||
BdfList blog = clientHelper.toList(descriptor, 0, descriptor.length);
|
BdfList blog = clientHelper.toList(descriptor, 0, descriptor.length);
|
||||||
Author a =
|
Author a =
|
||||||
authorFactory.createAuthor(blog.getString(1), blog.getRaw(2));
|
authorFactory.createAuthor(blog.getString(1), blog.getRaw(2));
|
||||||
return new Blog(g, blog.getString(0), description, a);
|
// TODO change permanent depending on how this will be used
|
||||||
|
boolean permanent = false;
|
||||||
|
return new Blog(g, blog.getString(0), description, a, permanent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import org.briarproject.api.blogs.BlogFactory;
|
|||||||
import org.briarproject.api.blogs.BlogManager;
|
import org.briarproject.api.blogs.BlogManager;
|
||||||
import org.briarproject.api.blogs.BlogPost;
|
import org.briarproject.api.blogs.BlogPost;
|
||||||
import org.briarproject.api.blogs.BlogPostHeader;
|
import org.briarproject.api.blogs.BlogPostHeader;
|
||||||
|
import org.briarproject.api.clients.Client;
|
||||||
import org.briarproject.api.clients.ClientHelper;
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
|
import org.briarproject.api.contact.Contact;
|
||||||
|
import org.briarproject.api.contact.ContactId;
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfEntry;
|
import org.briarproject.api.data.BdfEntry;
|
||||||
import org.briarproject.api.data.BdfList;
|
import org.briarproject.api.data.BdfList;
|
||||||
@@ -19,6 +22,8 @@ import org.briarproject.api.identity.Author;
|
|||||||
import org.briarproject.api.identity.Author.Status;
|
import org.briarproject.api.identity.Author.Status;
|
||||||
import org.briarproject.api.identity.AuthorId;
|
import org.briarproject.api.identity.AuthorId;
|
||||||
import org.briarproject.api.identity.IdentityManager;
|
import org.briarproject.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.api.identity.IdentityManager.AddIdentityHook;
|
||||||
|
import org.briarproject.api.identity.IdentityManager.RemoveIdentityHook;
|
||||||
import org.briarproject.api.identity.LocalAuthor;
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
import org.briarproject.api.sync.ClientId;
|
import org.briarproject.api.sync.ClientId;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.sync.Group;
|
||||||
@@ -51,8 +56,12 @@ import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
|
|||||||
import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
|
import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
|
||||||
import static org.briarproject.api.blogs.BlogConstants.KEY_TIMESTAMP;
|
import static org.briarproject.api.blogs.BlogConstants.KEY_TIMESTAMP;
|
||||||
import static org.briarproject.api.blogs.BlogConstants.KEY_TITLE;
|
import static org.briarproject.api.blogs.BlogConstants.KEY_TITLE;
|
||||||
|
import static org.briarproject.api.contact.ContactManager.AddContactHook;
|
||||||
|
import static org.briarproject.api.contact.ContactManager.RemoveContactHook;
|
||||||
|
|
||||||
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager {
|
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
||||||
|
AddContactHook, RemoveContactHook, Client,
|
||||||
|
AddIdentityHook, RemoveIdentityHook {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(BlogManagerImpl.class.getName());
|
Logger.getLogger(BlogManagerImpl.class.getName());
|
||||||
@@ -83,6 +92,68 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager {
|
|||||||
return CLIENT_ID;
|
return CLIENT_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createLocalState(Transaction txn) throws DbException {
|
||||||
|
// Ensure every identity does have its own personal blog
|
||||||
|
// TODO this can probably be removed once #446 is resolved and all users migrated to a new version
|
||||||
|
for (LocalAuthor a : db.getLocalAuthors(txn)) {
|
||||||
|
Blog b = blogFactory.createPersonalBlog(a);
|
||||||
|
Group g = b.getGroup();
|
||||||
|
if (!db.containsGroup(txn, g.getId())) {
|
||||||
|
db.addGroup(txn, g);
|
||||||
|
for (ContactId c : db.getContacts(txn, a.getId())) {
|
||||||
|
db.setVisibleToContact(txn, c, g.getId(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure that we have the personal blogs of all pre-existing contacts
|
||||||
|
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||||
|
// get personal blog of the contact
|
||||||
|
Blog b = blogFactory.createPersonalBlog(c.getAuthor());
|
||||||
|
Group g = b.getGroup();
|
||||||
|
if (!db.containsGroup(txn, g.getId())) {
|
||||||
|
// add the personal blog of the contact
|
||||||
|
db.addGroup(txn, g);
|
||||||
|
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
||||||
|
|
||||||
|
// share our personal blog with the new contact
|
||||||
|
LocalAuthor a = db.getLocalAuthor(txn, c.getLocalAuthorId());
|
||||||
|
Blog b2 = blogFactory.createPersonalBlog(a);
|
||||||
|
db.setVisibleToContact(txn, c.getId(), b2.getId(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removingContact(Transaction txn, Contact c) throws DbException {
|
||||||
|
if (c != null) {
|
||||||
|
Blog b = blogFactory.createPersonalBlog(c.getAuthor());
|
||||||
|
db.removeGroup(txn, b.getGroup());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addingIdentity(Transaction txn, LocalAuthor a)
|
||||||
|
throws DbException {
|
||||||
|
|
||||||
|
// add a personal blog for the new identity
|
||||||
|
LOG.info("New Personal Blog Added.");
|
||||||
|
Blog b = blogFactory.createPersonalBlog(a);
|
||||||
|
db.addGroup(txn, b.getGroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removingIdentity(Transaction txn, LocalAuthor a)
|
||||||
|
throws DbException {
|
||||||
|
|
||||||
|
// remove the personal blog of that identity
|
||||||
|
Blog b = blogFactory.createPersonalBlog(a);
|
||||||
|
db.removeGroup(txn, b.getGroup());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void incomingMessage(Transaction txn, Message m, BdfList list,
|
protected void incomingMessage(Transaction txn, Message m, BdfList list,
|
||||||
BdfDictionary meta) throws DbException, FormatException {
|
BdfDictionary meta) throws DbException, FormatException {
|
||||||
@@ -208,6 +279,11 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager {
|
|||||||
return Collections.unmodifiableList(blogs);
|
return Collections.unmodifiableList(blogs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Blog getPersonalBlog(Author author) throws DbException {
|
||||||
|
return blogFactory.createPersonalBlog(author);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Blog> getBlogs() throws DbException {
|
public Collection<Blog> getBlogs() throws DbException {
|
||||||
try {
|
try {
|
||||||
@@ -291,7 +367,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager {
|
|||||||
private String getBlogDescription(Transaction txn, GroupId g)
|
private String getBlogDescription(Transaction txn, GroupId g)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
|
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
|
||||||
return d.getString(KEY_DESCRIPTION);
|
return d.getString(KEY_DESCRIPTION, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlogPostHeader getPostHeaderFromMetadata(@Nullable Transaction txn,
|
private BlogPostHeader getPostHeaderFromMetadata(@Nullable Transaction txn,
|
||||||
@@ -321,5 +397,4 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager {
|
|||||||
return new BlogPostHeader(title, id, parentId, timestamp, author,
|
return new BlogPostHeader(title, id, parentId, timestamp, author,
|
||||||
authorStatus, contentType, read);
|
authorStatus, contentType, read);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import org.briarproject.api.blogs.BlogFactory;
|
|||||||
import org.briarproject.api.blogs.BlogManager;
|
import org.briarproject.api.blogs.BlogManager;
|
||||||
import org.briarproject.api.blogs.BlogPostFactory;
|
import org.briarproject.api.blogs.BlogPostFactory;
|
||||||
import org.briarproject.api.clients.ClientHelper;
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
|
import org.briarproject.api.contact.ContactManager;
|
||||||
import org.briarproject.api.crypto.CryptoComponent;
|
import org.briarproject.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.api.data.MetadataEncoder;
|
import org.briarproject.api.data.MetadataEncoder;
|
||||||
import org.briarproject.api.db.DatabaseComponent;
|
|
||||||
import org.briarproject.api.identity.AuthorFactory;
|
import org.briarproject.api.identity.AuthorFactory;
|
||||||
import org.briarproject.api.identity.IdentityManager;
|
import org.briarproject.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.api.sync.GroupFactory;
|
import org.briarproject.api.sync.GroupFactory;
|
||||||
import org.briarproject.api.sync.ValidationManager;
|
import org.briarproject.api.sync.ValidationManager;
|
||||||
import org.briarproject.api.system.Clock;
|
import org.briarproject.api.system.Clock;
|
||||||
@@ -19,17 +20,31 @@ import javax.inject.Singleton;
|
|||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
|
||||||
|
import static org.briarproject.blogs.BlogManagerImpl.CLIENT_ID;
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
public class BlogsModule {
|
public class BlogsModule {
|
||||||
|
|
||||||
public static class EagerSingletons {
|
public static class EagerSingletons {
|
||||||
@Inject
|
@Inject
|
||||||
BlogPostValidator blogPostValidator;
|
BlogPostValidator blogPostValidator;
|
||||||
|
@Inject
|
||||||
|
BlogManager blogManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
BlogManager provideBlogManager(BlogManagerImpl blogManager) {
|
BlogManager provideBlogManager(BlogManagerImpl blogManager,
|
||||||
|
LifecycleManager lifecycleManager, ContactManager contactManager,
|
||||||
|
IdentityManager identityManager,
|
||||||
|
ValidationManager validationManager) {
|
||||||
|
|
||||||
|
lifecycleManager.registerClient(blogManager);
|
||||||
|
contactManager.registerAddContactHook(blogManager);
|
||||||
|
contactManager.registerRemoveContactHook(blogManager);
|
||||||
|
identityManager.registerAddIdentityHook(blogManager);
|
||||||
|
identityManager.registerRemoveIdentityHook(blogManager);
|
||||||
|
validationManager.registerIncomingMessageHook(CLIENT_ID, blogManager);
|
||||||
return blogManager;
|
return blogManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +69,7 @@ public class BlogsModule {
|
|||||||
|
|
||||||
BlogPostValidator validator = new BlogPostValidator(crypto,
|
BlogPostValidator validator = new BlogPostValidator(crypto,
|
||||||
blogFactory, clientHelper, metadataEncoder, clock);
|
blogFactory, clientHelper, metadataEncoder, clock);
|
||||||
validationManager.registerMessageValidator(
|
validationManager.registerMessageValidator(CLIENT_ID, validator);
|
||||||
BlogManagerImpl.CLIENT_ID, validator);
|
|
||||||
|
|
||||||
return validator;
|
return validator;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -792,6 +792,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
|
|||||||
} else if (task == TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US) {
|
} else if (task == TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US) {
|
||||||
removeFromList(txn, groupId, SHARED_WITH_US, f);
|
removeFromList(txn, groupId, SHARED_WITH_US, f);
|
||||||
} else if (task == TASK_ADD_SHARED_SHAREABLE) {
|
} else if (task == TASK_ADD_SHARED_SHAREABLE) {
|
||||||
|
// TODO we might want to call the add() method of the respective
|
||||||
|
// manager here, because blogs add a description for example
|
||||||
db.addGroup(txn, f.getGroup());
|
db.addGroup(txn, f.getGroup());
|
||||||
db.setVisibleToContact(txn, contactId, f.getId(), true);
|
db.setVisibleToContact(txn, contactId, f.getId(), true);
|
||||||
} else if (task == TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US) {
|
} else if (task == TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US) {
|
||||||
|
|||||||
Reference in New Issue
Block a user