#!/usr/bin/perl # # DW::Controller::API::REST::Journals # # API controls for fetching journal-related information # # Authors: # Ruth Hatch # # 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;