diff --git a/briar-api/src/org/briarproject/api/blogs/Blog.java b/briar-api/src/org/briarproject/api/blogs/Blog.java index c97e42be2aae72185845fa2b5ea05ee257ebd17c..4e6827891a67ebde4d63d842fa7e0e5bce2c1269 100644 --- a/briar-api/src/org/briarproject/api/blogs/Blog.java +++ b/briar-api/src/org/briarproject/api/blogs/Blog.java @@ -11,13 +11,16 @@ public class Blog extends Forum { private final String description; @NotNull private final Author author; + private final boolean permanent; 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); this.description = description; this.author = author; + this.permanent = permanent; } @NotNull @@ -29,4 +32,8 @@ public class Blog extends Forum { public Author getAuthor() { return author; } + + public boolean isPermanent() { + return permanent; + } } diff --git a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java b/briar-api/src/org/briarproject/api/blogs/BlogConstants.java index 5e483ffc6ee155c1c48e2ab140026bdceb617af4..3c8e8baf839a84e8e13ec848c157e75ee90669f2 100644 --- a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java +++ b/briar-api/src/org/briarproject/api/blogs/BlogConstants.java @@ -19,6 +19,9 @@ public interface BlogConstants { /** The maximum length of a blog post's body in bytes. */ 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 */ String BLOG_TITLE = "blogTitle"; String BLOG_DESC = "blogDescription"; diff --git a/briar-api/src/org/briarproject/api/blogs/BlogFactory.java b/briar-api/src/org/briarproject/api/blogs/BlogFactory.java index 8da9db1926f11d4dc31ed633fb61d794aa1444fb..190236bae1f5ae92efc79f535fa1c36e4a02c0e3 100644 --- a/briar-api/src/org/briarproject/api/blogs/BlogFactory.java +++ b/briar-api/src/org/briarproject/api/blogs/BlogFactory.java @@ -1,6 +1,7 @@ package org.briarproject.api.blogs; import org.briarproject.api.FormatException; +import org.briarproject.api.contact.Contact; import org.briarproject.api.identity.Author; import org.briarproject.api.sync.Group; import org.jetbrains.annotations.NotNull; @@ -11,6 +12,9 @@ public interface BlogFactory { Blog createBlog(@NotNull String name, @NotNull String description, @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 */ Blog parseBlog(@NotNull Group g, @NotNull String description) throws FormatException; diff --git a/briar-api/src/org/briarproject/api/blogs/BlogManager.java b/briar-api/src/org/briarproject/api/blogs/BlogManager.java index 0effcfee4d4b3c698d59a6d08f0f135acb5bfbf7..7d6188feda24f7c3fdaf06b28460c0878c467676 100644 --- a/briar-api/src/org/briarproject/api/blogs/BlogManager.java +++ b/briar-api/src/org/briarproject/api/blogs/BlogManager.java @@ -2,6 +2,7 @@ package org.briarproject.api.blogs; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; +import org.briarproject.api.identity.Author; import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.GroupId; @@ -31,9 +32,12 @@ public interface BlogManager { /** Returns the blog with the given ID. */ 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; + /** Returns only the personal blog of the given author. */ + Blog getPersonalBlog(Author author) throws DbException; + /** Returns all blogs to which the user subscribes. */ Collection<Blog> getBlogs() throws DbException; diff --git a/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java b/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java index b04401f5d1297854af0e45c6694afa5f26edc796..9a3e0583aa1f04952920139ea626f43d44e72de3 100644 --- a/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java +++ b/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java @@ -4,6 +4,7 @@ import org.briarproject.api.FormatException; import org.briarproject.api.blogs.Blog; import org.briarproject.api.blogs.BlogFactory; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.contact.Contact; import org.briarproject.api.data.BdfList; import org.briarproject.api.identity.Author; import org.briarproject.api.identity.AuthorFactory; @@ -13,6 +14,8 @@ import org.jetbrains.annotations.NotNull; import javax.inject.Inject; +import static org.briarproject.api.blogs.BlogConstants.PERSONAL_BLOG_NAME; + class BlogFactoryImpl implements BlogFactory { private final GroupFactory groupFactory; @@ -31,6 +34,16 @@ class BlogFactoryImpl implements BlogFactory { @Override public Blog createBlog(@NotNull String name, @NotNull String description, @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 { BdfList blog = BdfList.of( name, @@ -40,7 +53,7 @@ class BlogFactoryImpl implements BlogFactory { byte[] descriptor = clientHelper.toByteArray(blog); Group g = groupFactory .createGroup(BlogManagerImpl.CLIENT_ID, descriptor); - return new Blog(g, name, description, author); + return new Blog(g, name, description, author, permanent); } catch (FormatException e) { throw new RuntimeException(e); } @@ -55,7 +68,9 @@ class BlogFactoryImpl implements BlogFactory { BdfList blog = clientHelper.toList(descriptor, 0, descriptor.length); Author a = 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); } } diff --git a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java index 70abde036f4f01cbec184ca1037bf5238f345065..45b3bbe84729a75f48745421c0c8def1e8d97f55 100644 --- a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java +++ b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java @@ -6,7 +6,10 @@ import org.briarproject.api.blogs.BlogFactory; import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogPost; import org.briarproject.api.blogs.BlogPostHeader; +import org.briarproject.api.clients.Client; 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.BdfEntry; 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.AuthorId; 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.sync.ClientId; 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_TIMESTAMP; 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 = Logger.getLogger(BlogManagerImpl.class.getName()); @@ -83,6 +92,68 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager { 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 protected void incomingMessage(Transaction txn, Message m, BdfList list, BdfDictionary meta) throws DbException, FormatException { @@ -208,6 +279,11 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager { return Collections.unmodifiableList(blogs); } + @Override + public Blog getPersonalBlog(Author author) throws DbException { + return blogFactory.createPersonalBlog(author); + } + @Override public Collection<Blog> getBlogs() throws DbException { try { @@ -291,7 +367,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager { private String getBlogDescription(Transaction txn, GroupId g) throws DbException, FormatException { BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g); - return d.getString(KEY_DESCRIPTION); + return d.getString(KEY_DESCRIPTION, ""); } private BlogPostHeader getPostHeaderFromMetadata(@Nullable Transaction txn, @@ -321,5 +397,4 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager { return new BlogPostHeader(title, id, parentId, timestamp, author, authorStatus, contentType, read); } - } diff --git a/briar-core/src/org/briarproject/blogs/BlogsModule.java b/briar-core/src/org/briarproject/blogs/BlogsModule.java index 4cf7894d1b608b2557a8098f5509a1ebb6ec7b18..055328ad9cbb664f7e027bb6bb46ce70a5309f8b 100644 --- a/briar-core/src/org/briarproject/blogs/BlogsModule.java +++ b/briar-core/src/org/briarproject/blogs/BlogsModule.java @@ -4,11 +4,12 @@ import org.briarproject.api.blogs.BlogFactory; import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogPostFactory; import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.contact.ContactManager; import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.data.MetadataEncoder; -import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.IdentityManager; +import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.sync.GroupFactory; import org.briarproject.api.sync.ValidationManager; import org.briarproject.api.system.Clock; @@ -19,17 +20,31 @@ import javax.inject.Singleton; import dagger.Module; import dagger.Provides; +import static org.briarproject.blogs.BlogManagerImpl.CLIENT_ID; + @Module public class BlogsModule { public static class EagerSingletons { @Inject BlogPostValidator blogPostValidator; + @Inject + BlogManager blogManager; } @Provides @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; } @@ -54,8 +69,7 @@ public class BlogsModule { BlogPostValidator validator = new BlogPostValidator(crypto, blogFactory, clientHelper, metadataEncoder, clock); - validationManager.registerMessageValidator( - BlogManagerImpl.CLIENT_ID, validator); + validationManager.registerMessageValidator(CLIENT_ID, validator); return validator; } diff --git a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java index 0d55b4a3cef39ef2fdb61609485968f343975c03..e4929fb7948d7a9d492782b15bd35223875c6896 100644 --- a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java +++ b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java @@ -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) { removeFromList(txn, groupId, SHARED_WITH_US, f); } 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.setVisibleToContact(txn, contactId, f.getId(), true); } else if (task == TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US) {