Updated groups to be public

• Updated:
- groups to be public
- routes for /group and /groups/id to be public
- GroupTimeline to ignore relationships for loading
- Group fetching to be a where with is_archived: false
- GroupControllers to have if current_user, else

• Added:
- Meta and og information for view
- Group fetch
- public route api for featured groups, group timelines

• Removed:
- Doorkeeper for read:groups
This commit is contained in:
mgabdev 2020-07-21 23:05:54 -05:00
parent 49c6e323fa
commit 3b0ec6a270
9 changed files with 69 additions and 20 deletions

View File

@ -7,7 +7,7 @@ class Api::V1::Groups::RelationshipsController < Api::BaseController
respond_to :json respond_to :json
def index def index
groups = Group.where(id: group_ids).select('id') groups = Group.where(id: group_ids, is_archived: false).select('id')
# .where doesn't guarantee that our results are in the same order # .where doesn't guarantee that our results are in the same order
# we requested them, so return the "right" order to the requestor. # we requested them, so return the "right" order to the requestor.
@groups = groups.index_by(&:id).values_at(*group_ids).compact @groups = groups.index_by(&:id).values_at(*group_ids).compact

View File

@ -3,10 +3,10 @@
class Api::V1::GroupsController < Api::BaseController class Api::V1::GroupsController < Api::BaseController
include Authorization include Authorization
before_action -> { doorkeeper_authorize! :read, :'read:groups' }, only: [:index, :show] # before_action -> { doorkeeper_authorize! :read, :'read:groups' }, only: [:index, :show]
before_action -> { doorkeeper_authorize! :write, :'write:groups' }, except: [:index, :show] before_action -> { doorkeeper_authorize! :write, :'write:groups' }, except: [:index, :show]
before_action :require_user! before_action :require_user!, except: [:index, :show]
before_action :set_group, except: [:index, :create] before_action :set_group, except: [:index, :create]
def index def index
@ -14,10 +14,19 @@ class Api::V1::GroupsController < Api::BaseController
when 'featured' when 'featured'
@groups = Group.where(is_featured: true, is_archived: false).limit(100).all @groups = Group.where(is_featured: true, is_archived: false).limit(100).all
when 'new' when 'new'
if !current_user
render json: { error: 'This method requires an authenticated user' }, status: 422
end
@groups = Group.where(is_archived: false).limit(24).order('created_at DESC').all @groups = Group.where(is_archived: false).limit(24).order('created_at DESC').all
when 'member' when 'member'
if !current_user
render json: { error: 'This method requires an authenticated user' }, status: 422
end
@groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).order('group_accounts.id DESC').all @groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).order('group_accounts.id DESC').all
when 'admin' when 'admin'
if !current_user
render json: { error: 'This method requires an authenticated user' }, status: 422
end
@groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account, role: :admin }).all @groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account, role: :admin }).all
end end
@ -75,7 +84,7 @@ class Api::V1::GroupsController < Api::BaseController
private private
def set_group def set_group
@group = Group.find(params[:id]) @group = Group.where(id: params[:id], is_archived: false).first
end end
def group_params def group_params

View File

@ -1,23 +1,25 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Timelines::GroupController < Api::BaseController class Api::V1::Timelines::GroupController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:groups' }
before_action :require_user!
before_action :set_group before_action :set_group
before_action :set_statuses before_action :set_statuses
after_action :insert_pagination_headers, unless: -> { @statuses.empty? } after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
def show def show
if current_user
render json: @statuses, render json: @statuses,
each_serializer: REST::StatusSerializer, each_serializer: REST::StatusSerializer,
relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id) relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id)
else
render json: @statuses, each_serializer: REST::StatusSerializer
end
end end
private private
def set_group def set_group
@group = Group.find(params[:id]) @group = Group.where(id: params[:id], is_archived: false).first
end end
def set_statuses def set_statuses
@ -29,10 +31,18 @@ class Api::V1::Timelines::GroupController < Api::BaseController
end end
def group_statuses def group_statuses
statuses = nil
if current_account
statuses = group_timeline_statuses.without_replies.paginate_by_id( statuses = group_timeline_statuses.without_replies.paginate_by_id(
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id) params_slice(:max_id, :since_id, :min_id)
).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
else
statuses = group_timeline_statuses.without_replies.paginate_by_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)
end
if truthy_param?(:only_media) if truthy_param?(:only_media)
# `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids. # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids.

View File

@ -5,6 +5,7 @@ class ReactController < ApplicationController
before_action :set_referrer_policy_header, only: :react before_action :set_referrer_policy_header, only: :react
before_action :set_initial_state_json, only: :react before_action :set_initial_state_json, only: :react
before_action :set_data_for_meta, only: :react before_action :set_data_for_meta, only: :react
before_action :set_instance_presenter
def react def react
# #
@ -13,9 +14,12 @@ class ReactController < ApplicationController
private private
def set_data_for_meta def set_data_for_meta
return if find_route_matches return if find_route_matches && current_account
if find_public_route_matches if request.path.include?("/groups/")
groupIdFromPath = request.path.sub("/groups", "").gsub("/", "")
@group = Group.where(id: groupIdFromPath, is_archived: false).first
elsif find_public_route_matches
return return
elsif request.path.count("/") == 1 && !request.path.include?("@") elsif request.path.count("/") == 1 && !request.path.include?("@")
acctFromPath = request.path.sub("/", "") acctFromPath = request.path.sub("/", "")
@ -40,7 +44,7 @@ class ReactController < ApplicationController
end end
def find_public_route_matches def find_public_route_matches
request.path.match(/\A\/(about|search|explore)/) request.path.match(/\A\/(about|search|groups|explore)/)
end end
def set_initial_state_json def set_initial_state_json
@ -67,4 +71,8 @@ class ReactController < ApplicationController
def set_referrer_policy_header def set_referrer_policy_header
response.headers['Referrer-Policy'] = 'origin' response.headers['Referrer-Policy'] = 'origin'
end end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
end end

View File

@ -68,6 +68,10 @@ module StreamEntriesHelper
return "The latest Gabs from #{display_name(account)} (@#{account.username}). #{account.note}" return "The latest Gabs from #{display_name(account)} (@#{account.username}). #{account.note}"
end end
def group_description(group)
return "#{group.title} on Gab. #{group.description}"
end
def media_summary(status) def media_summary(status)
attachments = { image: 0, video: 0 } attachments = { image: 0, video: 0 }

View File

@ -78,7 +78,7 @@ class GroupTimeline extends ImmutablePureComponent {
const { collapsed } = this.state const { collapsed } = this.state
const { id } = this.props.params const { id } = this.props.params
if (typeof group === 'undefined' || !relationships) { if (typeof group === 'undefined') {
return <ColumnIndicator type='loading' /> return <ColumnIndicator type='loading' />
} else if (group === false) { } else if (group === false) {
return <ColumnIndicator type='missing' /> return <ColumnIndicator type='missing' />

View File

@ -175,7 +175,7 @@ class SwitchingArea extends PureComponent {
<WrappedRoute path='/timeline/all' exact page={CommunityPage} component={CommunityTimeline} content={children} componentParams={{ title: 'Community Feed' }} /> <WrappedRoute path='/timeline/all' exact page={CommunityPage} component={CommunityTimeline} content={children} componentParams={{ title: 'Community Feed' }} />
<WrappedRoute path='/timeline/pro' exact page={ProPage} component={ProTimeline} content={children} componentParams={{ title: 'Pro Feed' }} /> <WrappedRoute path='/timeline/pro' exact page={ProPage} component={ProTimeline} content={children} componentParams={{ title: 'Pro Feed' }} />
<WrappedRoute path='/groups' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'featured' }} /> <WrappedRoute path='/groups' publicRoute exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'featured' }} />
<WrappedRoute path='/groups/new' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'new' }} /> <WrappedRoute path='/groups/new' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'new' }} />
<WrappedRoute path='/groups/browse/member' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'member' }} /> <WrappedRoute path='/groups/browse/member' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'member' }} />
<WrappedRoute path='/groups/browse/admin' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'admin' }} /> <WrappedRoute path='/groups/browse/admin' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'admin' }} />
@ -184,7 +184,7 @@ class SwitchingArea extends PureComponent {
{ /* <WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} /> { /* <WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
<WrappedRoute path='/groups/:id/removed-accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} /> */} <WrappedRoute path='/groups/:id/removed-accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} /> */}
<WrappedRoute path='/groups/:id/edit' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Edit Group', page: 'edit-group' }} /> <WrappedRoute path='/groups/:id/edit' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Edit Group', page: 'edit-group' }} />
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} /> <WrappedRoute path='/groups/:id' publicRoute page={GroupPage} component={GroupTimeline} content={children} />
<WrappedRoute path='/tags/:id' publicRoute page={HashtagPage} component={HashtagTimeline} content={children} componentParams={{ title: 'Hashtag' }} /> <WrappedRoute path='/tags/:id' publicRoute page={HashtagPage} component={HashtagTimeline} content={children} componentParams={{ title: 'Hashtag' }} />

View File

@ -0,0 +1,6 @@
- content_for :page_title do
= "#{group.title} / Group • #{site_hostname}"
- content_for :header_tags do
= opengraph 'og:type', 'website'
= render 'groups/og', group: group, url: "https://gab.com/groups/#{group.id}"

View File

@ -0,0 +1,12 @@
- description = group_description(group)
%meta{ name: 'description', content: description }/
= opengraph 'og:url', url
= opengraph 'og:site_name', site_title
= opengraph 'og:title', "#{group.title} / Group • #{site_hostname}"
= opengraph 'og:description', description
= opengraph 'og:image', full_asset_url(group.cover_image.url(:original))
= opengraph 'og:image:width', '120'
= opengraph 'og:image:height', '120'
= opengraph 'twitter:card', 'summary'