mourningdove/cgi-bin/DW/Controller/API/REST/Journals.pm
2026-05-24 01:03:05 +00:00

340 lines
9.4 KiB
Perl

#!/usr/bin/perl
#
# DW::Controller::API::REST::Journals
#
# API controls for fetching journal-related information
#
# Authors:
# Ruth Hatch <ruth.s.hatch@gmail.com>
#
# Copyright (c) 2017 by Dreamwidth Studios, LLC.
#
# This program is free software; you may redistribute it and/or modify it under
# the same terms as Perl itself. For a copy of the license, please reference
# 'perldoc perlartistic' or 'perldoc perlgpl'.
#
package DW::Controller::API::REST::Journals;
use strict;
use warnings;
use DW::Routing;
use DW::Request;
use DW::Controller;
use DW::API::RateLimit;
use JSON;
use Data::Dumper;
################################################
# /journals/{journal}/accesslists
#
# Get a list of accesslists, or create a new accesslist
################################################
my $accesslists_all = DW::Controller::API::REST->path(
'journals/accesslists_all.yaml',
1,
{
get => DW::API::RateLimit->wrap(
\&accesslists_get,
name => 'accesslists_get',
rate => '100/60s'
),
post => DW::API::RateLimit->wrap(
\&accesslists_new,
name => 'accesslists_post',
rate => '10/60s'
),
delete => DW::API::RateLimit->wrap(
\&accesslists_delete,
name => 'accesslists_delete',
rate => '10/60s'
)
}
);
sub accesslists_get {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my @trust_groups = $user->trust_groups;
my @accesslists = ();
#push the names and group ids of the user's trust groups to the list.
foreach my $group (@trust_groups) {
my $group_hash = { "id" => $group->{groupnum}, "name" => $group->{groupname} };
push( @accesslists, $group_hash );
}
return $self->rest_ok( \@accesslists );
}
sub accesslists_new {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my $body = $args->{body};
$body->{sortorder} ||= 0;
my $group = $user->create_trust_group(
groupname => $body->{name},
sortorder => $body->{sortorder}
);
return $self->rest_ok( { id => $group } );
}
sub accesslists_delete {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my $id = $args->{query}{id};
my $group = $user->delete_trust_group( { id => $id } );
return $self->rest_ok();
}
################################################
# /journals/{journal}/accesslists/{id}
#
# Get details about a specific accesslist
################################################
my $accesslists = DW::Controller::API::REST->path(
'journals/accesslists.yaml',
1,
{
get => DW::API::RateLimit->wrap(
\&accesslist_get,
name => 'accesslist_get',
rate => '100/60s'
),
post => DW::API::RateLimit->wrap(
\&accesslist_edit,
name => 'accesslist_edit',
rate => '10/60s'
)
}
);
sub accesslist_get {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my $id = $args->{path}{accesslistid};
my $group_members = $user->trust_group_members( id => $id );
return $self->rest_error( "400", "Access filter doesn't exist." ) unless $group_members;
my @accesslist;
my $members = LJ::load_userids( keys %$group_members );
#push the names and group ids of the user's trust groups to the list.
foreach my $userid ( keys %$members ) {
my $name = $members->{$userid}->user;
push( @accesslist, $name );
}
return $self->rest_ok( \@accesslist );
}
sub accesslist_edit {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my $journals = $args->{body}{journals};
my $id = $args->{path}{accesslistid};
my $trust_group = $user->trust_groups( { id => $id } );
return $self->rest_error( "400", "Access filter doesn't exist." ) unless $trust_group;
foreach my $journal ( @{$journals} ) {
my $trusted_u = LJ::load_user($journal);
# User might have been removed from circle between load and
# submit; don't re-add.
next unless $trusted_u && $user->trusts($trusted_u);
$user->edit_trustmask( $trusted_u, add => $id );
}
return $self->rest_ok();
}
sub accesslist_delete {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my $journals = $args->{query}{journal};
my $id = $args->{path}{accesslistid};
my $trust_group = $user->trust_groups( { id => $id } );
return $self->rest_error( "400", "Access filter doesn't exist." ) unless $trust_group;
foreach my $journal ( @{$journals} ) {
my $trusted_u = LJ::load_user($journal);
# User might have been removed from circle between load and
# submit; don't re-add.
next unless $trusted_u && $user->trusts($trusted_u);
$user->edit_trustmask( $trusted_u, remove => $id );
}
return $self->rest_ok();
}
################################################
# /journals/{journal}/tags
#
# Get a list of tags, create new tags, or delete tags
################################################
my $tags = DW::Controller::API::REST->path(
'journals/tags.yaml',
1,
{
get => DW::API::RateLimit->wrap(
\&tags_get,
name => 'tags_get',
rate => '100/60s'
),
post => DW::API::RateLimit->wrap(
\&tags_post,
name => 'tags_post',
rate => '10/60s'
),
delete => DW::API::RateLimit->wrap(
\&tags_delete,
name => 'tags_delete',
rate => '10/60s'
)
}
);
sub tags_get {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
# get tags for the page to display
my @taglist;
my $tags = LJ::Tags::get_usertags( $user, { remote => $remote } );
foreach my $kwid ( keys %{$tags} ) {
# only show tags for display
next unless $tags->{$kwid}->{display};
my $tag = LJ::S2::TagDetail( $user, $kwid => $tags->{$kwid} );
# delete some fields the enduser doesn't need
delete $tag->{_type};
delete $tag->{_id};
push @taglist, $tag;
}
@taglist = sort { $a->{name} cmp $b->{name} } @taglist;
return $self->rest_ok( \@taglist );
}
sub tags_post {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my $tagerr = "";
my @errors;
my $tags = $args->{body};
#push the usernames for all comms the user has posting access to onto the list.
foreach my $tag ( @{$tags} ) {
my $rv = LJ::Tags::create_usertag( $user, $tag, { display => 1, err_ref => \$tagerr } );
push @errors, $tagerr unless $rv;
}
return $self->rest_error( 'GET', 400 ) if $#errors > 0;
return $self->rest_ok();
}
sub tags_delete {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my $tag = $args->{query}{tag};
LJ::Tags::delete_usertag( $user, 'name', $tag );
return $self->rest_ok();
}
################################################
# /journals/{journal}/xpostaccounts
#
# Get a list of crosspost accounts
################################################
my $xpost = DW::Controller::API::REST->path(
'journals/xpostaccounts.yaml',
1,
{
get => DW::API::RateLimit->wrap(
\&xpost_get,
name => 'xpost_get',
rate => '100/60s'
)
}
);
sub xpost_get {
my ( $self, $args ) = @_;
my $user = LJ::load_user( $args->{path}{username} );
my $remote = $args->{user};
return $self->rest_error("404") unless $user;
return $self->rest_error("403") unless $user == $remote;
my @xpostaccounts = DW::External::Account->get_external_accounts($user);
my @accountlist;
#FIXME: print minsecurity as well? Weird encoding bugs though.
foreach my $account (@xpostaccounts) {
my $accounthash = {
name => $account->displayname,
xpostbydefault => $account->{xpostbydefault}
};
push @accountlist, $accounthash;
}
return $self->rest_ok( \@accountlist );
}
1;