2018-03-24 14:38:05 -04:00
< ? php
/**
* @ file src / Core / Acl . php
*/
namespace Friendica\Core ;
2019-11-28 12:42:12 -05:00
use Friendica\App\Page ;
2018-07-20 08:19:26 -04:00
use Friendica\Database\DBA ;
2019-12-15 16:34:11 -05:00
use Friendica\DI ;
2018-03-24 14:38:05 -04:00
use Friendica\Model\Contact ;
2019-11-28 12:33:00 -05:00
use Friendica\Model\Group ;
2018-03-24 14:38:05 -04:00
/**
* Handle ACL management and display
*
2018-09-15 19:28:38 -04:00
* @ author Hypolite Petovan < hypolite @ mrpetovan . com >
2018-03-24 14:38:05 -04:00
*/
2019-12-15 17:28:01 -05:00
class ACL
2018-03-24 14:38:05 -04:00
{
/**
* Returns a select input tag with all the contact of the local user
*
* @ param string $selname Name attribute of the select input tag
* @ param string $selclass Class attribute of the select input tag
* @ param array $preselected Contact IDs that should be already selected
* @ param int $size Length of the select box
* @ param int $tabindex Select input tag tabindex attribute
* @ return string
2019-01-06 16:06:53 -05:00
* @ throws \Exception
2018-03-24 14:38:05 -04:00
*/
public static function getMessageContactSelectHTML ( $selname , $selclass , array $preselected = [], $size = 4 , $tabindex = null )
{
2019-12-15 16:34:11 -05:00
$a = DI :: app ();
2018-03-24 14:38:05 -04:00
$o = '' ;
// When used for private messages, we limit correspondence to mutual DFRN/Friendica friends and the selector
// to one recipient. By default our selector allows multiple selects amongst all contacts.
2018-07-24 22:53:46 -04:00
$sql_extra = sprintf ( " AND `rel` = %d " , intval ( Contact :: FRIEND ));
2018-08-11 16:40:44 -04:00
$sql_extra .= sprintf ( " AND `network` IN ('%s' , '%s') " , Protocol :: DFRN , Protocol :: DIASPORA );
2018-03-24 14:38:05 -04:00
$tabindex_attr = ! empty ( $tabindex ) ? ' tabindex="' . intval ( $tabindex ) . '"' : '' ;
$hidepreselected = '' ;
if ( $preselected ) {
$sql_extra .= " AND `id` IN ( " . implode ( " , " , $preselected ) . " ) " ;
$hidepreselected = ' style="display: none;"' ;
}
$o .= " <select name= \" $selname\ " id = \ " $selclass\ " class = \ " $selclass\ " size = \ " $size\ " $tabindex_attr $hidepreselected > \r\n " ;
2018-07-20 08:19:26 -04:00
$stmt = DBA :: p ( " SELECT `id`, `name`, `url`, `network` FROM `contact`
2019-01-09 08:23:11 -05:00
WHERE `uid` = ? AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND NOT `deleted` AND `notify` != ''
2018-03-24 14:38:05 -04:00
$sql_extra
ORDER BY `name` ASC " , intval(local_user())
);
2018-07-20 22:03:40 -04:00
$contacts = DBA :: toArray ( $stmt );
2018-03-24 14:38:05 -04:00
$arr = [ 'contact' => $contacts , 'entry' => $o ];
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
2019-12-15 19:35:26 -05:00
Hook :: callAll ( DI :: module () -> getName () . '_pre_' . $selname , $arr );
2018-03-24 14:38:05 -04:00
$receiverlist = [];
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $contacts )) {
2018-03-24 14:38:05 -04:00
foreach ( $contacts as $contact ) {
if ( in_array ( $contact [ 'id' ], $preselected )) {
$selected = ' selected="selected"' ;
} else {
$selected = '' ;
}
$trimmed = Protocol :: formatMention ( $contact [ 'url' ], $contact [ 'name' ]);
$receiverlist [] = $trimmed ;
$o .= " <option value= \" { $contact [ 'id' ] } \" $selected title= \" { $contact [ 'name' ] } | { $contact [ 'url' ] } \" > $trimmed </option> \r \n " ;
}
}
$o .= '</select>' . PHP_EOL ;
if ( $preselected ) {
$o .= implode ( ', ' , $receiverlist );
}
2019-12-15 19:35:26 -05:00
Hook :: callAll ( DI :: module () -> getName () . '_post_' . $selname , $o );
2018-03-24 14:38:05 -04:00
return $o ;
}
/**
* Return the default permission of the provided user array
*
* @ param array $user
* @ return array Hash of contact id lists
2019-01-06 16:06:53 -05:00
* @ throws \Exception
2018-03-24 14:38:05 -04:00
*/
public static function getDefaultUserPermissions ( array $user = null )
{
2020-01-05 17:07:33 -05:00
$aclFormatter = DI :: aclFormatter ();
2018-03-24 14:38:05 -04:00
return [
2020-01-05 17:07:33 -05:00
'allow_cid' => Contact :: pruneUnavailable ( $aclFormatter -> expand ( $user [ 'allow_cid' ] ? ? '' )),
'allow_gid' => $aclFormatter -> expand ( $user [ 'allow_gid' ] ? ? '' ),
'deny_cid' => $aclFormatter -> expand ( $user [ 'deny_cid' ] ? ? '' ),
'deny_gid' => $aclFormatter -> expand ( $user [ 'deny_gid' ] ? ? '' ),
2018-03-24 14:38:05 -04:00
];
}
2019-11-28 12:33:00 -05:00
/**
* Returns the ACL list of contacts for a given user id
*
2020-01-13 21:58:01 -05:00
* @ param int $user_id
* @ param array $condition Additional contact lookup table conditions
2019-11-28 12:33:00 -05:00
* @ return array
* @ throws \Exception
*/
2020-01-13 21:58:01 -05:00
public static function getContactListByUserId ( int $user_id , array $condition = [])
2019-11-28 12:33:00 -05:00
{
2019-12-06 02:25:21 -05:00
$fields = [ 'id' , 'name' , 'addr' , 'micro' ];
$params = [ 'order' => [ 'name' ]];
2020-01-13 21:58:01 -05:00
$acl_contacts = Contact :: selectToArray (
$fields ,
array_merge ([
'uid' => $user_id ,
'self' => false ,
'blocked' => false ,
'archive' => false ,
'deleted' => false ,
'pending' => false ,
'rel' => [ Contact :: FOLLOWER , Contact :: FRIEND ]
], $condition ),
$params
2019-11-28 12:33:00 -05:00
);
2019-12-06 02:25:21 -05:00
2020-01-13 21:58:01 -05:00
$acl_yourself = Contact :: selectFirst ( $fields , [ 'uid' => $user_id , 'self' => true ]);
2020-01-13 22:20:18 -05:00
$acl_yourself [ 'name' ] = DI :: l10n () -> t ( 'Yourself' );
2020-01-13 21:58:01 -05:00
$acl_contacts [] = $acl_yourself ;
2019-12-06 02:25:21 -05:00
$acl_forums = Contact :: selectToArray ( $fields ,
[ 'uid' => $user_id , 'self' => false , 'blocked' => false , 'archive' => false , 'deleted' => false ,
'pending' => false , 'contact-type' => Contact :: TYPE_COMMUNITY ], $params
);
$acl_contacts = array_merge ( $acl_forums , $acl_contacts );
2019-11-28 12:33:00 -05:00
array_walk ( $acl_contacts , function ( & $value ) {
$value [ 'type' ] = 'contact' ;
});
return $acl_contacts ;
}
/**
* Returns the ACL list of groups ( including meta - groups ) for a given user id
*
* @ param int $user_id
* @ return array
*/
public static function getGroupListByUserId ( int $user_id )
{
$acl_groups = [
[
'id' => Group :: FOLLOWERS ,
2020-01-18 14:52:34 -05:00
'name' => DI :: l10n () -> t ( 'Followers' ),
2019-11-28 12:33:00 -05:00
'addr' => '' ,
'micro' => 'images/twopeople.png' ,
'type' => 'group' ,
],
[
'id' => Group :: MUTUALS ,
2020-01-18 14:52:34 -05:00
'name' => DI :: l10n () -> t ( 'Mutuals' ),
2019-11-28 12:33:00 -05:00
'addr' => '' ,
'micro' => 'images/twopeople.png' ,
'type' => 'group' ,
]
];
foreach ( Group :: getByUserId ( $user_id ) as $group ) {
$acl_groups [] = [
'id' => $group [ 'id' ],
'name' => $group [ 'name' ],
'addr' => '' ,
'micro' => 'images/twopeople.png' ,
'type' => 'group' ,
];
}
return $acl_groups ;
}
2018-03-24 14:38:05 -04:00
/**
* Return the full jot ACL selector HTML
*
2020-01-13 21:58:01 -05:00
* @ param Page $page
* @ param array $user User array
* @ param bool $for_federation
* @ param array $default_permissions Static defaults permission array :
* [
2019-11-28 12:42:12 -05:00
* 'allow_cid' => [],
* 'allow_gid' => [],
* 'deny_cid' => [],
* 'deny_gid' => [],
* 'hidewall' => true / false
2020-01-13 21:58:01 -05:00
* ]
* @ param array $condition
* @ param string $form_prefix
2018-03-24 14:38:05 -04:00
* @ return string
2019-01-06 16:06:53 -05:00
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
2018-03-24 14:38:05 -04:00
*/
2020-01-13 21:58:01 -05:00
public static function getFullSelectorHTML (
Page $page ,
array $user = null ,
bool $for_federation = false ,
array $default_permissions = [],
array $condition = [],
$form_prefix = ''
) {
2019-12-13 13:29:06 -05:00
if ( empty ( $user [ 'uid' ])) {
return '' ;
}
2020-01-13 21:58:01 -05:00
static $input_group_id = 0 ;
$input_group_id ++ ;
2019-11-28 12:42:12 -05:00
$page -> registerFooterScript ( Theme :: getPathForFile ( 'asset/typeahead.js/dist/typeahead.bundle.js' ));
$page -> registerFooterScript ( Theme :: getPathForFile ( 'js/friendica-tagsinput/friendica-tagsinput.js' ));
$page -> registerStylesheet ( Theme :: getPathForFile ( 'js/friendica-tagsinput/friendica-tagsinput.css' ));
$page -> registerStylesheet ( Theme :: getPathForFile ( 'js/friendica-tagsinput/friendica-tagsinput-typeahead.css' ));
2018-08-14 18:43:27 -04:00
// Defaults user permissions
if ( empty ( $default_permissions )) {
$default_permissions = self :: getDefaultUserPermissions ( $user );
2018-07-20 14:07:54 -04:00
}
2019-12-03 06:59:51 -05:00
$default_permissions = [
'allow_cid' => $default_permissions [ 'allow_cid' ] ? ? [],
'allow_gid' => $default_permissions [ 'allow_gid' ] ? ? [],
'deny_cid' => $default_permissions [ 'deny_cid' ] ? ? [],
'deny_gid' => $default_permissions [ 'deny_gid' ] ? ? [],
'hidewall' => $default_permissions [ 'hidewall' ] ? ? false ,
];
2019-11-28 12:42:12 -05:00
if ( count ( $default_permissions [ 'allow_cid' ])
+ count ( $default_permissions [ 'allow_gid' ])
+ count ( $default_permissions [ 'deny_cid' ])
+ count ( $default_permissions [ 'deny_gid' ])) {
$visibility = 'custom' ;
} else {
$visibility = 'public' ;
// Default permission display for custom panel
$default_permissions [ 'allow_gid' ] = [ Group :: FOLLOWERS ];
}
2019-03-24 22:40:50 -04:00
$jotnets_fields = [];
2019-11-28 12:42:12 -05:00
if ( $for_federation ) {
2018-03-24 14:38:05 -04:00
$mail_enabled = false ;
$pubmail_enabled = false ;
2020-01-19 15:21:13 -05:00
if ( function_exists ( 'imap_open' ) && ! DI :: config () -> get ( 'system' , 'imap_disabled' )) {
2019-11-29 15:55:52 -05:00
$mailacct = DBA :: selectFirst ( 'mailacct' , [ 'pubmail' ], [ '`uid` = ? AND `server` != ""' , $user [ 'uid' ]]);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $mailacct )) {
2018-03-24 14:38:05 -04:00
$mail_enabled = true ;
$pubmail_enabled = ! empty ( $mailacct [ 'pubmail' ]);
}
}
2019-12-05 20:05:47 -05:00
if ( ! $default_permissions [ 'hidewall' ]) {
2018-03-24 14:38:05 -04:00
if ( $mail_enabled ) {
2019-03-24 22:40:50 -04:00
$jotnets_fields [] = [
'type' => 'checkbox' ,
'field' => [
'pubmail_enable' ,
2020-01-18 14:52:34 -05:00
DI :: l10n () -> t ( 'Post to Email' ),
2019-03-24 22:40:50 -04:00
$pubmail_enabled
]
];
2018-03-24 14:38:05 -04:00
}
2019-03-24 22:40:50 -04:00
Hook :: callAll ( 'jot_networks' , $jotnets_fields );
2018-03-24 14:38:05 -04:00
}
}
2019-03-24 22:40:50 -04:00
2020-01-13 21:58:01 -05:00
$acl_contacts = self :: getContactListByUserId ( $user [ 'uid' ], $condition );
2019-11-28 12:42:12 -05:00
$acl_groups = self :: getGroupListByUserId ( $user [ 'uid' ]);
$acl_list = array_merge ( $acl_groups , $acl_contacts );
2020-01-13 21:58:01 -05:00
$input_names = [
'visibility' => $form_prefix ? $form_prefix . '[visibility]' : 'visibility' ,
'group_allow' => $form_prefix ? $form_prefix . '[group_allow]' : 'group_allow' ,
'contact_allow' => $form_prefix ? $form_prefix . '[contact_allow]' : 'contact_allow' ,
'group_deny' => $form_prefix ? $form_prefix . '[group_deny]' : 'group_deny' ,
'contact_deny' => $form_prefix ? $form_prefix . '[contact_deny]' : 'contact_deny' ,
'emailcc' => $form_prefix ? $form_prefix . '[emailcc]' : 'emailcc' ,
];
2018-10-31 10:44:06 -04:00
$tpl = Renderer :: getMarkupTemplate ( 'acl_selector.tpl' );
2018-10-31 10:35:50 -04:00
$o = Renderer :: replaceMacros ( $tpl , [
2020-01-18 14:52:34 -05:00
'$public_title' => DI :: l10n () -> t ( 'Public' ),
'$public_desc' => DI :: l10n () -> t ( 'This content will be shown to all your followers and can be seen in the community pages and by anyone with its link.' ),
'$custom_title' => DI :: l10n () -> t ( 'Limited/Private' ),
'$custom_desc' => DI :: l10n () -> t ( 'This content will be shown only to the people in the first box, to the exception of the people mentioned in the second box. It won\'t appear anywhere public.' ),
'$allow_label' => DI :: l10n () -> t ( 'Show to:' ),
'$deny_label' => DI :: l10n () -> t ( 'Except to:' ),
'$emailcc' => DI :: l10n () -> t ( 'CC: email addresses' ),
'$emtitle' => DI :: l10n () -> t ( 'Example: bob@example.com, mary@example.com' ),
'$jotnets_summary' => DI :: l10n () -> t ( 'Connectors' ),
'$jotnets_disabled_label' => DI :: l10n () -> t ( 'Connectors disabled, since "%s" is enabled.' , DI :: l10n () -> t ( 'Hide your profile details from unknown viewers?' )),
2019-11-28 12:42:12 -05:00
'$visibility' => $visibility ,
'$acl_contacts' => $acl_contacts ,
'$acl_groups' => $acl_groups ,
'$acl_list' => $acl_list ,
'$contact_allow' => implode ( ',' , $default_permissions [ 'allow_cid' ]),
'$group_allow' => implode ( ',' , $default_permissions [ 'allow_gid' ]),
'$contact_deny' => implode ( ',' , $default_permissions [ 'deny_cid' ]),
'$group_deny' => implode ( ',' , $default_permissions [ 'deny_gid' ]),
'$for_federation' => $for_federation ,
'$jotnets_fields' => $jotnets_fields ,
2019-12-03 06:59:51 -05:00
'$user_hidewall' => $default_permissions [ 'hidewall' ],
2020-01-13 21:58:01 -05:00
'$input_names' => $input_names ,
'$input_group_id' => $input_group_id ,
2018-03-24 14:38:05 -04:00
]);
return $o ;
}
}