diff --git a/api/controllers/PostController.js b/api/controllers/PostController.js index 58c00d458..7ac12da81 100644 --- a/api/controllers/PostController.js +++ b/api/controllers/PostController.js @@ -44,11 +44,14 @@ const PostController = { } })) .then(stop => stop || createPost(userId, attributes) - .tap(() => Analytics.track({ - userId, - event: 'Add Post by Email Form', - properties: {group: group.get('name')} - })) + .then(post => { + Analytics.track({ + userId, + event: 'Add Post by Email Form', + properties: {group: group.get('name')} + }) + return post + }) .then(post => res.redirect(Frontend.Route.post(post, group)))) .catch(res.serverError) }, diff --git a/api/graphql/filters.js b/api/graphql/filters.js index 1f30f788c..4d9408d5f 100644 --- a/api/graphql/filters.js +++ b/api/graphql/filters.js @@ -25,6 +25,8 @@ export const groupFilter = userId => relation => { // non authenticated queries can only see public groups if (!userId) { q.where('groups.visibility', Group.Visibility.PUBLIC) + // Only show groups that are allowed to be show in public + q.andWhere('allow_in_public', true) } else { // the effect of using `where` like this is to wrap everything within its // callback in parentheses -- this is necessary to keep `or` from "leaking" @@ -38,7 +40,7 @@ export const groupFilter = userId => relation => { // Can see groups you are a member of... q2.whereIn('groups.id', selectIdsForMember) - // + their parent group + // + their parent groups q2.orWhereIn('groups.id', parentGroupIds) // + child groups that are not hidden, except moderators of a group can see its hidden children q2.orWhere(q3 => { @@ -49,7 +51,11 @@ export const groupFilter = userId => relation => { q3.orWhereIn('groups.id', childrenOfModeratedGroupIds) }) // + all public groups - q2.orWhere('groups.visibility', Group.Visibility.PUBLIC) + q2.orWhere(q5 => { + q5.where('groups.visibility', Group.Visibility.PUBLIC) + // Only show groups that are allowed to be show in public + q5.andWhere('allow_in_public', true) + }) }) } }) diff --git a/api/models/Group.js b/api/models/Group.js index afb3f586c..bf8b0f175 100644 --- a/api/models/Group.js +++ b/api/models/Group.js @@ -534,7 +534,7 @@ module.exports = bookshelf.Model.extend(merge({ throw new GraphQLYogaError("A group with that URL slug already exists") } - var attrs = defaults( + let attrs = defaults( pick(data, 'about_video_uri', 'accessibility', 'avatar_url', 'description', 'slug', 'category', 'access_code', 'banner_url', 'location_id', 'location', 'group_data_type', 'moderator_descriptor', @@ -549,6 +549,11 @@ module.exports = bookshelf.Model.extend(merge({ } ) + // XXX: temporary, by default show all farms in public. These can only be created via API right now + if (attrs.type === 'farm') { + attrs.allow_in_public = true + } + // eslint-disable-next-line camelcase const access_code = attrs.access_code || await Group.getNewAccessCode() const group = new Group(merge(attrs, { diff --git a/api/models/post/createPost.js b/api/models/post/createPost.js index 82b158825..a2251044a 100644 --- a/api/models/post/createPost.js +++ b/api/models/post/createPost.js @@ -3,18 +3,25 @@ import setupPostAttrs from './setupPostAttrs' import updateChildren from './updateChildren' import { groupRoom, pushToSockets } from '../../services/Websockets' -export default function createPost (userId, params) { +export default async function createPost (userId, params) { + if (params.isPublic) { + // Don't allow creating a public post unless at least one of the post's groups has allow_in_public set to true + const groups = await Group.query(q => q.whereIn('id', params.group_ids)).fetchAll() + const allowedToMakePublic = groups.find(g => g.get('allow_in_public')) + if (!allowedToMakePublic) params.isPublic = false + } + return setupPostAttrs(userId, merge(Post.newPostAttrs(), params)) - .then(attrs => bookshelf.transaction(transacting => - Post.create(attrs, { transacting }) - .tap(post => afterCreatingPost(post, merge( - pick(params, 'group_ids', 'imageUrl', 'videoUrl', 'docs', 'topicNames', 'memberIds', 'eventInviteeIds', 'imageUrls', 'fileUrls', 'announcement', 'location', 'location_id'), - {children: params.requests, transacting} - )))).then(function(inserts) { - return inserts - }).catch(function(error) { - throw error - }) + .then(attrs => bookshelf.transaction(transacting => + Post.create(attrs, { transacting }) + .tap(post => afterCreatingPost(post, merge( + pick(params, 'group_ids', 'imageUrl', 'videoUrl', 'docs', 'topicNames', 'memberIds', 'eventInviteeIds', 'imageUrls', 'fileUrls', 'announcement', 'location', 'location_id'), + {children: params.requests, transacting} + )))).then(function(inserts) { + return inserts + }).catch(function(error) { + throw error + }) ) } diff --git a/api/models/post/setupPostAttrs.js b/api/models/post/setupPostAttrs.js index 1270d91a8..e5eee1fb3 100644 --- a/api/models/post/setupPostAttrs.js +++ b/api/models/post/setupPostAttrs.js @@ -4,7 +4,6 @@ import { getOr } from 'lodash/fp' export default function setupPostAttrs (userId, params) { const attrs = merge({ user_id: userId, - visibility: params.public ? Post.Visibility.PUBLIC_READABLE : Post.Visibility.DEFAULT, link_preview_id: params.link_preview_id || getOr(null, 'id', params.linkPreview), parent_post_id: params.parent_post_id, updated_at: new Date(), diff --git a/migrations/20221110125837_show-in-public-flag-to-groups.js b/migrations/20221110125837_show-in-public-flag-to-groups.js new file mode 100644 index 000000000..45d4d1f2c --- /dev/null +++ b/migrations/20221110125837_show-in-public-flag-to-groups.js @@ -0,0 +1,11 @@ +exports.up = function (knex) { + return knex.schema.table('groups', table => { + table.boolean('allow_in_public').defaultTo(false) + }) +} + +exports.down = function (knex) { + return knex.schema.table('groups', table => { + table.dropColumn('allow_in_public') + }) +} diff --git a/migrations/schema.sql b/migrations/schema.sql index c6cf6c594..18dcb55ca 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -1042,7 +1042,8 @@ CREATE TABLE public.groups ( type_descriptor_plural character varying(255) DEFAULT NULL::character varying, moderator_descriptor character varying(255) DEFAULT NULL::character varying, moderator_descriptor_plural character varying(255) DEFAULT NULL::character varying, - about_video_uri character varying(255) + about_video_uri character varying(255), + allow_in_public boolean DEFAULT false );