2018-03-24 14:38:05 -04:00
< ? php
/**
2021-03-29 02:40:20 -04:00
* @ copyright Copyright ( C ) 2010 - 2021 , the Friendica project
2020-02-09 09:45:36 -05:00
*
* @ license GNU AGPL version 3 or any later version
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*
2018-03-24 14:38:05 -04:00
*/
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
*/
2019-12-15 17:28:01 -05:00
class ACL
2018-03-24 14:38:05 -04:00
{
/**
2020-09-03 10:01:58 -04:00
* Returns a select input tag for private message recipient
2018-03-24 14:38:05 -04:00
*
2020-09-03 10:01:58 -04:00
* @ param int $selected Existing recipien contact ID
2018-03-24 14:38:05 -04:00
* @ return string
2019-01-06 16:06:53 -05:00
* @ throws \Exception
2018-03-24 14:38:05 -04:00
*/
2020-09-03 10:01:58 -04:00
public static function getMessageContactSelectHTML ( int $selected = null )
2018-03-24 14:38:05 -04:00
{
$o = '' ;
2020-09-03 10:01:58 -04:00
$page = DI :: page ();
2018-03-24 14:38:05 -04:00
2020-09-03 10:01:58 -04: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-03-24 14:38:05 -04:00
2020-09-03 10:01:58 -04:00
// 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.
$condition = [
'uid' => local_user (),
'self' => false ,
'blocked' => false ,
'pending' => false ,
'archive' => false ,
'deleted' => false ,
'rel' => [ Contact :: FOLLOWER , Contact :: SHARING , Contact :: FRIEND ],
'network' => Protocol :: FEDERATED ,
];
$contacts = Contact :: selectToArray (
[ 'id' , 'name' , 'addr' , 'micro' ],
DBA :: mergeConditions ( $condition , [ " `notify` != '' " ])
2018-03-24 14:38:05 -04:00
);
$arr = [ 'contact' => $contacts , 'entry' => $o ];
2020-09-03 10:01:58 -04:00
Hook :: callAll ( DI :: module () -> getName () . '_pre_recipient' , $arr );
2018-03-24 14:38:05 -04:00
2020-09-03 10:01:58 -04:00
$tpl = Renderer :: getMarkupTemplate ( 'acl/message_recipient.tpl' );
$o = Renderer :: replaceMacros ( $tpl , [
'$contacts' => $contacts ,
'$selected' => $selected ,
]);
2018-03-24 14:38:05 -04:00
2020-09-03 10:01:58 -04:00
Hook :: callAll ( DI :: module () -> getName () . '_post_recipient' , $o );
2018-03-24 14:38:05 -04:00
return $o ;
}
2020-09-07 19:27:32 -04:00
/**
* Returns a minimal ACL block for self - only permissions
*
* @ param int $localUserId
* @ param string $explanation
* @ return string
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function getSelfOnlyHTML ( int $localUserId , string $explanation )
{
$selfPublicContactId = Contact :: getPublicIdByUserId ( $localUserId );
$tpl = Renderer :: getMarkupTemplate ( 'acl/self_only.tpl' );
$o = Renderer :: replaceMacros ( $tpl , [
'$selfPublicContactId' => $selfPublicContactId ,
'$explanation' => $explanation ,
]);
return $o ;
}
2018-03-24 14:38:05 -04:00
/**
* 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 ,
2021-02-17 13:59:19 -05:00
'network' => Protocol :: FEDERATED ,
2020-01-13 21:58:01 -05:00
'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 ,
2021-02-17 13:59:19 -05:00
'network' => Protocol :: FEDERATED , 'pending' => false , 'contact-type' => Contact :: TYPE_COMMUNITY ], $params
2019-12-06 02:25:21 -05:00
);
$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' => [],
2020-02-22 03:54:28 -05:00
* 'deny_gid' => []
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' ] ? ? [],
];
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 ) {
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 )) {
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' ),
2020-02-22 03:54:28 -05:00
! empty ( $mailacct [ 'pubmail' ])
2019-03-24 22:40:50 -04:00
]
];
2020-02-22 03:54:28 -05:00
2018-03-24 14:38:05 -04:00
}
}
2020-02-22 03:54:28 -05: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' ,
];
2020-09-03 09:58:07 -04:00
$tpl = Renderer :: getMarkupTemplate ( 'acl/full_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' ),
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 ,
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 ;
}
}