2016-04-19 03:38:38 +00:00
< ? php
2021-12-03 03:01:39 +00:00
2022-02-16 04:08:28 +00:00
namespace Code\Module ;
2016-04-19 03:38:38 +00:00
2019-10-02 00:44:58 +00:00
use App ;
2022-02-16 04:08:28 +00:00
use Code\Web\Controller ;
use Code\Lib\Libsync ;
use Code\Lib\AccessList ;
use Code\Lib\ActivityStreams ;
use Code\Lib\Activity ;
use Code\Web\HTTPSig ;
use Code\Lib\Config ;
use Code\Lib\Channel ;
use Code\Lib\LDSignatures ;
use Code\Lib\Navbar ;
use Code\Render\Theme ;
2022-02-12 20:43:29 +00:00
2016-04-19 03:38:38 +00:00
2021-12-02 23:02:31 +00:00
class Lists extends Controller
{
public function init ()
{
if ( ActivityStreams :: is_as_request ()) {
$item_id = argv ( 1 );
if ( ! $item_id ) {
http_status_exit ( 404 , 'Not found' );
}
2021-12-03 03:01:39 +00:00
$x = q (
" select * from pgrp where hash = '%s' limit 1 " ,
2021-12-02 23:02:31 +00:00
dbesc ( $item_id )
);
if ( ! $x ) {
http_status_exit ( 404 , 'Not found' );
}
$group = array_shift ( $x );
// process an authenticated fetch
$sigdata = HTTPSig :: verify ( EMPTY_STR );
if ( $sigdata [ 'portable_id' ] && $sigdata [ 'header_valid' ]) {
$portable_id = $sigdata [ 'portable_id' ];
if ( ! check_channelallowed ( $portable_id )) {
http_status_exit ( 403 , 'Permission denied' );
}
if ( ! check_siteallowed ( $sigdata [ 'signer' ])) {
http_status_exit ( 403 , 'Permission denied' );
}
observer_auth ( $portable_id );
} elseif ( Config :: get ( 'system' , 'require_authenticated_fetch' , false )) {
http_status_exit ( 403 , 'Permission denied' );
}
if ( ! perm_is_allowed ( $group [ 'uid' ], get_observer_hash (), 'view_contacts' )) {
http_status_exit ( 403 , 'Permission denied' );
}
2022-01-25 01:26:12 +00:00
$channel = Channel :: from_id ( $group [ 'uid' ]);
2021-12-02 23:02:31 +00:00
if ( ! $channel ) {
http_status_exit ( 404 , 'Not found' );
}
if ( ! $group [ 'visible' ]) {
if ( $channel [ 'channel_hash' ] !== get_observer_hash ()) {
http_status_exit ( 403 , 'Permission denied' );
}
}
$total = AccessList :: members ( $group [ 'uid' ], $group [ 'id' ], true );
if ( $total ) {
App :: set_pager_total ( $total );
App :: set_pager_itemspage ( 100 );
}
if ( App :: $pager [ 'unset' ] && $total > 100 ) {
$ret = Activity :: paged_collection_init ( $total , App :: $query_string );
} else {
$members = AccessList :: members ( $group [ 'uid' ], $group [ 'id' ], false , App :: $pager [ 'start' ], App :: $pager [ 'itemspage' ]);
$ret = Activity :: encode_follow_collection ( $members , App :: $query_string , 'OrderedCollection' , $total );
}
as_return_and_die ( $ret , $channel );
}
if ( ! local_channel ()) {
notice ( t ( 'Permission denied.' ) . EOL );
return ;
}
App :: $profile_uid = local_channel ();
2022-01-25 04:16:38 +00:00
Navbar :: set_selected ( 'Access Lists' );
2021-12-02 23:02:31 +00:00
}
public function post ()
{
if ( ! local_channel ()) {
notice ( t ( 'Permission denied.' ) . EOL );
return ;
}
if (( argc () == 2 ) && ( argv ( 1 ) === 'new' )) {
check_form_security_token_redirectOnErr ( '/lists/new' , 'group_edit' );
$name = notags ( trim ( $_POST [ 'groupname' ]));
$public = intval ( $_POST [ 'public' ]);
$r = AccessList :: add ( local_channel (), $name , $public );
if ( $r ) {
info ( t ( 'Access list created.' ) . EOL );
} else {
notice ( t ( 'Could not create access list.' ) . EOL );
}
goaway ( z_root () . '/lists' );
}
if (( argc () == 2 ) && ( intval ( argv ( 1 )))) {
check_form_security_token_redirectOnErr ( '/lists' , 'group_edit' );
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( argv ( 1 )),
intval ( local_channel ())
);
if ( ! $r ) {
2021-12-03 03:01:39 +00:00
$r = q (
" select * from pgrp where id = %d limit 1 " ,
2021-12-02 23:02:31 +00:00
intval ( argv ( 1 ))
);
if ( $r ) {
notice ( t ( 'Permission denied.' ) . EOL );
} else {
notice ( t ( 'Access list not found.' ) . EOL );
}
goaway ( z_root () . '/connections' );
}
$group = array_shift ( $r );
$groupname = notags ( trim ( $_POST [ 'groupname' ]));
$public = intval ( $_POST [ 'public' ]);
if (( strlen ( $groupname )) && (( $groupname != $group [ 'gname' ]) || ( $public != $group [ 'visible' ]))) {
2021-12-03 03:01:39 +00:00
$r = q (
" UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d " ,
2021-12-02 23:02:31 +00:00
dbesc ( $groupname ),
intval ( $public ),
intval ( local_channel ()),
intval ( $group [ 'id' ])
);
if ( $r ) {
info ( t ( 'Access list updated.' ) . EOL );
}
Libsync :: build_sync_packet ( local_channel (), null , true );
}
goaway ( z_root () . '/lists/' . argv ( 1 ) . '/' . argv ( 2 ));
}
return ;
}
public function get ()
{
$change = false ;
2021-12-21 22:03:17 +00:00
// logger('mod_lists: ' . App::$cmd, LOGGER_DEBUG);
2021-12-02 23:02:31 +00:00
// Switch to text mode interface if we have more than 'n' contacts or group members, else loading avatars will lead to poor interactivity
$switchtotext = get_pconfig ( local_channel (), 'system' , 'listedit_image_limit' , get_config ( 'system' , 'listedit_image_limit' , 1000 ));
if (( argc () == 1 ) || (( argc () == 2 ) && ( argv ( 1 ) === 'new' ))) {
2021-12-21 22:03:17 +00:00
if ( ! local_channel ()) {
notice ( t ( 'Permission denied' ) . EOL );
return ;
}
2021-12-02 23:02:31 +00:00
$new = ((( argc () == 2 ) && ( argv ( 1 ) === 'new' )) ? true : false );
2021-12-03 03:01:39 +00:00
$groups = q (
" SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC " ,
2021-12-02 23:02:31 +00:00
intval ( local_channel ())
);
$i = 0 ;
foreach ( $groups as $group ) {
$entries [ $i ][ 'name' ] = $group [ 'gname' ];
$entries [ $i ][ 'id' ] = $group [ 'id' ];
$entries [ $i ][ 'count' ] = count ( AccessList :: members ( local_channel (), $group [ 'id' ]));
$i ++ ;
}
2022-02-12 20:43:29 +00:00
$tpl = Theme :: get_template ( 'privacy_groups.tpl' );
2021-12-02 23:02:31 +00:00
$o = replace_macros ( $tpl , [
'$title' => t ( 'Access Lists' ),
'$add_new_label' => t ( 'Create access list' ),
'$new' => $new ,
// new group form
'$gname' => array ( 'groupname' , t ( 'Access list name' )),
'$public' => array ( 'public' , t ( 'Members are visible to other channels' ), false ),
'$form_security_token' => get_form_security_token ( " group_edit " ),
'$submit' => t ( 'Submit' ),
// groups list
'$title' => t ( 'Access Lists' ),
'$name_label' => t ( 'Name' ),
'$count_label' => t ( 'Members' ),
'$entries' => $entries
]);
return $o ;
}
$context = array ( '$submit' => t ( 'Submit' ));
2022-02-12 20:43:29 +00:00
$tpl = Theme :: get_template ( 'group_edit.tpl' );
2021-12-02 23:02:31 +00:00
if (( argc () == 3 ) && ( argv ( 1 ) === 'drop' )) {
2021-12-21 22:03:17 +00:00
if ( ! local_channel ()) {
notice ( t ( 'Permission denied' ) . EOL );
return ;
}
check_form_security_token_redirectOnErr ( '/lists' , 'group_drop' , 't' );
2021-12-02 23:02:31 +00:00
if ( intval ( argv ( 2 ))) {
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( argv ( 2 )),
intval ( local_channel ())
);
2021-12-03 03:01:39 +00:00
if ( $r ) {
2021-12-02 23:02:31 +00:00
$result = AccessList :: remove ( local_channel (), $r [ 0 ][ 'gname' ]);
2021-12-03 03:01:39 +00:00
}
if ( $result ) {
2021-12-02 23:02:31 +00:00
info ( t ( 'Access list removed.' ) . EOL );
2021-12-03 03:01:39 +00:00
} else {
2021-12-02 23:02:31 +00:00
notice ( t ( 'Unable to remove access list.' ) . EOL );
2021-12-03 03:01:39 +00:00
}
2021-12-02 23:02:31 +00:00
}
goaway ( z_root () . '/lists' );
// NOTREACHED
}
if (( argc () > 2 ) && intval ( argv ( 1 )) && argv ( 2 )) {
2021-12-21 22:03:17 +00:00
if ( ! local_channel ()) {
notice ( t ( 'Permission denied' ) . EOL );
return ;
}
2021-12-02 23:02:31 +00:00
check_form_security_token_ForbiddenOnErr ( 'group_member_change' , 't' );
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1 " ,
2021-12-02 23:02:31 +00:00
dbesc ( base64url_decode ( argv ( 2 ))),
intval ( local_channel ())
);
2021-12-03 03:01:39 +00:00
if ( count ( $r )) {
2021-12-02 23:02:31 +00:00
$change = base64url_decode ( argv ( 2 ));
2021-12-03 03:01:39 +00:00
}
2021-12-02 23:02:31 +00:00
}
if ( argc () > 1 ) {
if ( strlen ( argv ( 1 )) <= 11 && intval ( argv ( 1 ))) {
2021-12-03 03:01:39 +00:00
$r = q (
2021-12-21 22:03:17 +00:00
" SELECT * FROM pgrp WHERE id = %d AND deleted = 0 LIMIT 1 " ,
intval ( argv ( 1 ))
2021-12-02 23:02:31 +00:00
);
} else {
2021-12-03 03:01:39 +00:00
$r = q (
2021-12-21 22:03:17 +00:00
" SELECT * FROM pgrp WHERE hash = '%s' AND deleted = 0 LIMIT 1 " ,
dbesc ( argv ( 1 ))
2021-12-02 23:02:31 +00:00
);
}
2021-12-21 22:03:17 +00:00
if ( ! $r ) {
notice ( t ( 'Access list not found.' ) . EOL );
return ;
}
$group = array_shift ( $r );
$uid = $group [ 'uid' ];
$owner = ( local_channel () && intval ( local_channel ()) === intval ( $group [ 'uid' ]));
if ( ! $owner ) {
// public view of group members if permitted
if ( ! ( $group [ 'visible' ] && perm_is_allowed ( $uid , get_observer_hash (), 'view_contacts' ))) {
notice ( t ( 'Permission denied' ) . EOL );
return ;
2021-12-02 23:02:31 +00:00
}
2021-12-21 22:03:17 +00:00
$members = [];
$memberlist = AccessList :: members ( $uid , $group [ 'id' ]);
if ( $memberlist ) {
foreach ( $memberlist as $member ) {
$members [] = micropro ( $member , true , 'mpgroup' , 'card' );
}
}
2022-02-12 20:43:29 +00:00
$o = replace_macros ( Theme :: get_template ( 'listmembers.tpl' ), [
2021-12-21 22:03:17 +00:00
'$title' => t ( 'List members' ),
'$members' => $members
]);
return $o ;
}
2021-12-02 23:02:31 +00:00
$members = AccessList :: members ( local_channel (), $group [ 'id' ]);
$preselected = [];
if ( count ( $members )) {
2021-12-03 03:01:39 +00:00
foreach ( $members as $member ) {
if ( ! in_array ( $member [ 'xchan_hash' ], $preselected )) {
2021-12-02 23:02:31 +00:00
$preselected [] = $member [ 'xchan_hash' ];
2021-12-03 03:01:39 +00:00
}
}
2021-12-02 23:02:31 +00:00
}
if ( $change ) {
if ( in_array ( $change , $preselected )) {
AccessList :: member_remove ( local_channel (), $group [ 'gname' ], $change );
} else {
AccessList :: member_add ( local_channel (), $group [ 'gname' ], $change );
}
$members = AccessList :: members ( local_channel (), $group [ 'id' ]);
$preselected = [];
if ( count ( $members )) {
2021-12-03 03:01:39 +00:00
foreach ( $members as $member ) {
2021-12-02 23:02:31 +00:00
$preselected [] = $member [ 'xchan_hash' ];
2021-12-03 03:01:39 +00:00
}
2021-12-02 23:02:31 +00:00
}
}
$context = $context + array (
'$title' => sprintf ( t ( 'Access List: %s' ), $group [ 'gname' ]),
'$details_label' => t ( 'Edit' ),
'$gname' => array ( 'groupname' , t ( 'Access list name: ' ), $group [ 'gname' ], '' ),
'$gid' => $group [ 'id' ],
'$drop' => $drop_txt ,
'$public' => array ( 'public' , t ( 'Members are visible to other channels' ), $group [ 'visible' ], '' ),
'$form_security_token_edit' => get_form_security_token ( 'group_edit' ),
'$delete' => t ( 'Delete access list' ),
'$form_security_token_drop' => get_form_security_token ( " group_drop " ),
);
}
2021-12-03 03:01:39 +00:00
if ( ! isset ( $group )) {
2021-12-02 23:02:31 +00:00
return ;
2021-12-03 03:01:39 +00:00
}
2021-12-02 23:02:31 +00:00
$groupeditor = array (
'label_members' => t ( 'List members' ),
'members' => [],
'label_contacts' => t ( 'Not in this list' ),
'contacts' => [],
);
$sec_token = addslashes ( get_form_security_token ( 'group_member_change' ));
$textmode = (( $switchtotext && ( count ( $members ) > $switchtotext )) ? true : 'card' );
foreach ( $members as $member ) {
if ( $member [ 'xchan_url' ]) {
$member [ 'archived' ] = ( intval ( $member [ 'abook_archived' ]) ? true : false );
$member [ 'click' ] = 'groupChangeMember(' . $group [ 'id' ] . ',\'' . base64url_encode ( $member [ 'xchan_hash' ]) . '\',\'' . $sec_token . '\'); return false;' ;
$groupeditor [ 'members' ][] = micropro ( $member , true , 'mpgroup' , $textmode );
2021-12-03 03:01:39 +00:00
} else {
2021-12-02 23:02:31 +00:00
AccessList :: member_remove ( local_channel (), $group [ 'gname' ], $member [ 'xchan_hash' ]);
2021-12-03 03:01:39 +00:00
}
2021-12-02 23:02:31 +00:00
}
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc " ,
2021-12-02 23:02:31 +00:00
intval ( local_channel ())
);
if ( count ( $r )) {
$textmode = (( $switchtotext && ( count ( $r ) > $switchtotext )) ? true : 'card' );
foreach ( $r as $member ) {
if ( ! in_array ( $member [ 'xchan_hash' ], $preselected )) {
$member [ 'archived' ] = ( intval ( $member [ 'abook_archived' ]) ? true : false );
$member [ 'click' ] = 'groupChangeMember(' . $group [ 'id' ] . ',\'' . base64url_encode ( $member [ 'xchan_hash' ]) . '\',\'' . $sec_token . '\'); return false;' ;
$groupeditor [ 'contacts' ][] = micropro ( $member , true , 'mpall' , $textmode );
}
}
}
$context [ '$groupeditor' ] = $groupeditor ;
$context [ '$desc' ] = t ( 'Select a channel to toggle membership' );
if ( $change ) {
2022-02-12 20:43:29 +00:00
$tpl = Theme :: get_template ( 'groupeditor.tpl' );
2021-12-02 23:02:31 +00:00
echo replace_macros ( $tpl , $context );
killme ();
}
return replace_macros ( $tpl , $context );
}
2016-04-19 03:38:38 +00:00
}