From 76a300970abe07afc94e8f04865755077c33c443 Mon Sep 17 00:00:00 2001 From: Tibet Sprague Date: Thu, 10 Nov 2022 22:43:23 -0800 Subject: [PATCH 1/5] Add allow_in_public column to groups When off then people are not allowed to create public posts from that group. Meaning a post that is chosen to be public must also be posted in at least one group that has allow_in_public set to true. Fixes https://github.com/Hylozoic/hylo-node/issues/889 --- api/graphql/filters.js | 10 +++++-- api/models/post/createPost.js | 28 +++++++++++-------- api/models/post/setupPostAttrs.js | 1 - ...110125837_show-in-public-flag-to-groups.js | 11 ++++++++ 4 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 migrations/20221110125837_show-in-public-flag-to-groups.js 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/post/createPost.js b/api/models/post/createPost.js index 82b158825..33607f21b 100644 --- a/api/models/post/createPost.js +++ b/api/models/post/createPost.js @@ -3,18 +3,24 @@ 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) { + 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') + }) +} From 7c297c776442e1d692e031552708918d27d1dd31 Mon Sep 17 00:00:00 2001 From: Tibet Sprague Date: Thu, 10 Nov 2022 22:46:15 -0800 Subject: [PATCH 2/5] Comment --- api/models/post/createPost.js | 1 + 1 file changed, 1 insertion(+) diff --git a/api/models/post/createPost.js b/api/models/post/createPost.js index 33607f21b..a2251044a 100644 --- a/api/models/post/createPost.js +++ b/api/models/post/createPost.js @@ -5,6 +5,7 @@ import { groupRoom, pushToSockets } from '../../services/Websockets' 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 From dfe315c3851be6da6af80c120004d236a7e82902 Mon Sep 17 00:00:00 2001 From: Tibet Sprague Date: Sun, 13 Nov 2022 11:48:58 -0800 Subject: [PATCH 3/5] Add allow_in_public to schema --- migrations/schema.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 ); From 9369452e77bc94bfa2f7766d13e7397645fc91cb Mon Sep 17 00:00:00 2001 From: Tibet Sprague Date: Sun, 13 Nov 2022 13:42:13 -0800 Subject: [PATCH 4/5] Farm groups by default are allowed in public --- api/models/Group.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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, { From 689d21ab5d3cc4d4fde387a8bdd79e30e8b39629 Mon Sep 17 00:00:00 2001 From: Tibet Sprague Date: Sun, 13 Nov 2022 14:08:23 -0800 Subject: [PATCH 5/5] Fix test --- api/controllers/PostController.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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) },