diff options
author | friendica <info@friendica.com> | 2012-10-28 18:50:35 -0700 |
---|---|---|
committer | friendica <info@friendica.com> | 2012-10-28 18:50:35 -0700 |
commit | 4bcf19632bc5158095a5d2d5d63dea1b25b146b7 (patch) | |
tree | 362ccfbd661b779bd864fa6c7416c9a7b1c15069 | |
parent | 1a9ab127482ee4eb17e3d2bd0ffa222f7053715b (diff) | |
download | volse-hubzilla-4bcf19632bc5158095a5d2d5d63dea1b25b146b7.tar.gz volse-hubzilla-4bcf19632bc5158095a5d2d5d63dea1b25b146b7.tar.bz2 volse-hubzilla-4bcf19632bc5158095a5d2d5d63dea1b25b146b7.zip |
Now have a solid permissions model. Create a few functions to enumerate them and then we're off to the races.
-rw-r--r-- | boot.php | 27 | ||||
-rw-r--r-- | include/Contact.php | 93 | ||||
-rw-r--r-- | include/permissions.php | 338 | ||||
-rw-r--r-- | include/security.php | 6 | ||||
-rw-r--r-- | mod/item.php | 2 | ||||
-rw-r--r-- | version.inc | 2 |
6 files changed, 367 insertions, 101 deletions
@@ -8,6 +8,7 @@ require_once('include/datetime.php'); require_once('include/language.php'); require_once('include/nav.php'); require_once('include/cache.php'); +require_once('include/permissions.php'); require_once('library/Mobile_Detect/Mobile_Detect.php'); require_once('include/BaseObject.php'); @@ -182,6 +183,14 @@ define ( 'PERMS_CONTACTS' , 0x0008 ); define ( 'PERMS_SPECIFIC' , 0x0080 ); +// Address book flags + +define ( 'ABOOK_FLAG_BLOCKED' , 0x0001); +define ( 'ABOOK_FLAG_IGNORED' , 0x0002); +define ( 'ABOOK_FLAG_HIDDEN' , 0x0004); + + + /** * Maximum number of "people who like (or don't like) this" that we will list by name */ @@ -394,11 +403,11 @@ if(! class_exists('App')) { class App { - public $account = null; // account record - - private $channel = null; // channel record - private $observer = null; // xchan record - private $widgets = array(); // widgets for this page + public $account = null; // account record + private $channel = null; // channel record + private $observer = null; // xchan record + private $perms = null; // observer permissions + private $widgets = array(); // widgets for this page @@ -654,6 +663,14 @@ if(! class_exists('App')) { return $this->observer; } + function set_perms($perms) { + $this->perms = $perms; + } + + function get_perms() { + return $this->perms; + } + function get_apps() { return $this->apps; } diff --git a/include/Contact.php b/include/Contact.php index fc0a6dd25..f442f112c 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -1,100 +1,7 @@ <?php -function map_perms($channel,$zguid,$zsig) { - $is_contact = false; - $is_site = false; - $is_network = false; - $is_anybody = true; - - - // To avoid sending the lengthy target_sig with each request, - // We should provide an array of results for each target - // and let the sender match the signature. - - if(strlen($zguid) && strlen($zsig)) { - - $is_network = true; - - $r = q("select * from contact where guid = '%s' and uid = %d limit 1", - dbesc($zguid), - intval($channel['channel_id']) - ); - if($r && count($r)) { - $is_contact = true; - $contact = $r[0]; - } - $r = q("select * from channel where channel_guid = '%s'", - dbesc($zguid) - ); - if($r && count($r)) { - foreach($r as $rr) { - if(base64url_encode(rsa_sign($rr['channel_guid'],$rr['channel_prvkey'])) === $zsig) { - $is_site = true; - break; - } - } - } - } - - $perms = array( - 'view_stream' => array('channel_r_stream', PERMS_R_STREAM ), - 'view_profile' => array('channel_r_profile', PERMS_R_PROFILE), - 'view_photos' => array('channel_r_photos', PERMS_R_PHOTOS), - 'view_contacts' => array('channel_r_abook', PERMS_R_ABOOK), - - 'send_stream' => array('channel_w_stream', PERMS_W_STREAM), - 'post_wall' => array('channel_w_wall', PERMS_W_WALL), - 'tag_deliver' => array('channel_w_tagwall', PERMS_W_TAGWALL), - 'post_comments' => array('channel_w_comment', PERMS_W_COMMENT), - 'post_mail' => array('channel_w_mail', PERMS_W_MAIL), - 'post_photos' => array('channel_w_photos', PERMS_W_PHOTOS), - 'chat' => array('channel_w_chat', PERMS_W_CHAT), - ); - - - $ret = array(); - - foreach($perms as $k => $v) { - $ret[$k] = z_check_perms($k,$v,$channel,$contact,$is_contact,$is_site,$is_network,$is_anybody); - - } - - return $ret; - -} - -function z_check_perms($k,$v,$channel,$contact,$is_contact,$is_site,$is_network,$is_anybody) { - - $allow = (($contact['self']) ? true : false); - - switch($channel[$v[0]]) { - case PERMS_PUBLIC: - if($is_anybody) - $allow = true; - break; - case PERMS_NETWORK: - if($is_network) - $allow = true; - break; - case PERMS_SITE: - if($is_site) - $allow = true; - break; - case PERMS_CONTACTS: - if($is_contact) - $allow = true; - break; - case PERMS_SPECIFIC: - if($is_contact && is_array($contact) && ($contact['my_perms'] & $v[1])) - $allow = true; - break; - default: - break; - } - return $allow; -} diff --git a/include/permissions.php b/include/permissions.php new file mode 100644 index 000000000..162f8a71c --- /dev/null +++ b/include/permissions.php @@ -0,0 +1,338 @@ +<?php + + + + $global_perms = array( + // Read only permissions + 'view_stream' => array('channel_r_stream', PERMS_R_STREAM, true), + 'view_profile' => array('channel_r_profile', PERMS_R_PROFILE, true), + 'view_photos' => array('channel_r_photos', PERMS_R_PHOTOS, true), + 'view_contacts' => array('channel_r_abook', PERMS_R_ABOOK, true), + + // Write permissions + 'send_stream' => array('channel_w_stream', PERMS_W_STREAM, false), + 'post_wall' => array('channel_w_wall', PERMS_W_WALL, false), + 'tag_deliver' => array('channel_w_tagwall', PERMS_W_TAGWALL, false), + 'post_comments' => array('channel_w_comment', PERMS_W_COMMENT, false), + 'post_mail' => array('channel_w_mail', PERMS_W_MAIL, false), + 'post_photos' => array('channel_w_photos', PERMS_W_PHOTOS, false), + 'chat' => array('channel_w_chat', PERMS_W_CHAT, false), + ); + + + +function get_all_perms($uid,$observer) { + + global $global_perms; + + // Save lots of individual lookups + + $r = null; + $c = null; + $x = null; + + $channel_checked = false; + $onsite_checked = false; + $abook_checked = false; + + $ret = array(); + + foreach($global_perms as $perm_name => $permission) { + + // First find out what the channel owner declared permissions to be. + + $channel_perm = $permission[0]; + + if(! $channel_checked) { + $r = q("select %s, channel_hash from channel where channel_id = %d limit 1", + dbesc($channel_perm), + intval($uid) + ); + + $channel_checked = true; + } + + if(! $r) { + $ret[$perm_name] = 0; + continue; + } + + // Check if this $uid is actually the $observer + + if($r[0]['channel_hash'] === $observer) { + $ret[$perm_name] = 1; + continue; + } + + // If it's an unauthenticated observer, we only need to see if PERMS_PUBLIC is set + + if(! $observer) { + $ret[$perm_name] = (($r[0][$channel_perm] & PERMS_PUBLIC) ? 1 : 0); + continue; + } + + + // If we're still here, we have an observer, which means they're in the network. + + if($r[0][$channel_perm] & PERMS_NETWORK) { + $ret[$perm_name] = 1; + continue; + } + + // If PERMS_SITE is specified, find out if they've got an account on this hub + + if($r[0][$channel_perm] & PERMS_SITE) { + if(! $onsite_checked) { + $c = q("select channel_hash from channel where channel_hash = '%s' limit 1", + dbesc($observer) + ); + + $onsite_checked = true; + } + + if($c) + $ret[$perm_name] = 1; + else + $ret[$perm_name] = 0; + + continue; + } + + // If PERMS_CONTACTS or PERMS_SPECIFIC, they need to be in your address book + // and not blocked/ignored + + if(! $abook_checked) { + $x = q("select abook_my_perms, abook_flags from abook + where abook_channel = %d and abook_xchan = '%s' limit 1", + intval($uid), + dbesc($observer) + ); + $abook_checked = true; + } + + + // If they're blocked - they can't read or write + + if((! $x) || ($x[0]['abook_flags'] & ABOOK_FLAG_BLOCKED)) { + $ret[$perm_name] = 0; + continue; + } + + // If we're still going, they are a contact + + if($r && $r[0][$channel_perm] & PERMS_CONTACTS) { + + // Check if this is a write permission and they are being ignored + + if((! $global_perms[$permission][2]) && ($x[0]['abook_flags'] & ABOOK_FLAG_IGNORED)) { + $ret[$perm_name] = 0; + continue; + } + + // Otherwise they're a contact, so they have permission + + $ret[$perm_name] = 1; + continue; + } + + // Permission granted to certain channels. Let's see if the observer is one of them + + if(($r) && ($r[0][$channel_perm] & PERMS_SPECIFIC)) { + if(($x) && ($x[0]['abook_my_perms'] & $global_perms[$permission][1])) { + $ret[$perm_name] = 1; + continue; + } + } + + // No permissions allowed. + + $ret[$perm_name] = 0; + continue; + + } + + return $ret; +} + + +function perm_is_allowed($uid,$observer,$perm_to_check) { + + global $global_perms; + + // First find out what the channel owner declared permissions to be. + + $channel_perm = $global_perms[$permission][0]; + + $r = q("select %s, channel_hash from channel where channel_id = %d limit 1", + dbesc($channel_perm), + intval($uid) + ); + if(! $r) + return false; + + // Check if this $uid is actually the $observer + + if($r[0]['channel_hash'] === $observer) + return true; + + // If it's an unauthenticated observer, we only need to see if PERMS_PUBLIC is set + + if(! $observer) { + return(($r[0][$channel_perm] & PERMS_PUBLIC) ? true : false); + } + + // If we're still here, we have an observer, which means they're in the network. + + if($r[0][$channel_perm] & PERMS_NETWORK) + return true; + + + // If PERMS_SITE is specified, find out if they've got an account on this hub + + if($r[0][$channel_perm] & PERMS_SITE) { + $c = q("select channel_hash from channel where channel_hash = '%s' limit 1", + dbesc($observer) + ); + if($c) + return true; + return false; + } + + // If PERMS_CONTACTS or PERMS_SPECIFIC, they need to be in your address book + // and not blocked/ignored + + $x = q("select abook_my_perms, abook_flags from abook where abook_channel = %d and abook_xchan = '%s' limit 1", + intval($uid), + dbesc($observer) + ); + + // If they're blocked - they can't read or write + + if((! $x) || ($x[0]['abook_flags'] & ABOOK_FLAG_BLOCKED)) + return false; + + // If we're still going, they are a contact + + if($r[0][$channel_perm] & PERMS_CONTACTS) { + + // Check if this is a write permission and they are being ignored + + if((! $global_perms[$permission][2]) && ($x[0]['abook_flags'] & ABOOK_FLAG_IGNORED)) + return false; + + // Otherwise they're a contact, so they have permission + + return true; + } + + // Permission granted to certain channels. Let's see if the observer is one of them + + if($r[0][$channel_perm] & PERMS_SPECIFIC) { + if($x[0]['abook_my_perms'] & $global_perms[$permission][1]) + return true; + } + + // No permissions allowed. + + return false; + +} + + + + +function map_perms($channel,$zguid,$zsig) { + + $is_contact = false; + $is_site = false; + $is_network = false; + $is_anybody = true; + + + // To avoid sending the lengthy target_sig with each request, + // We should provide an array of results for each target + // and let the sender match the signature. + + if(strlen($zguid) && strlen($zsig)) { + + $is_network = true; + + $r = q("select * from contact where guid = '%s' and uid = %d limit 1", + dbesc($zguid), + intval($channel['channel_id']) + ); + if($r && count($r)) { + $is_contact = true; + $contact = $r[0]; + } + $r = q("select * from channel where channel_guid = '%s'", + dbesc($zguid) + ); + if($r && count($r)) { + foreach($r as $rr) { + if(base64url_encode(rsa_sign($rr['channel_guid'],$rr['channel_prvkey'])) === $zsig) { + $is_site = true; + break; + } + } + } + } + + $perms = array( + 'view_stream' => array('channel_r_stream', PERMS_R_STREAM ), + 'view_profile' => array('channel_r_profile', PERMS_R_PROFILE), + 'view_photos' => array('channel_r_photos', PERMS_R_PHOTOS), + 'view_contacts' => array('channel_r_abook', PERMS_R_ABOOK), + + 'send_stream' => array('channel_w_stream', PERMS_W_STREAM), + 'post_wall' => array('channel_w_wall', PERMS_W_WALL), + 'tag_deliver' => array('channel_w_tagwall', PERMS_W_TAGWALL), + 'post_comments' => array('channel_w_comment', PERMS_W_COMMENT), + 'post_mail' => array('channel_w_mail', PERMS_W_MAIL), + 'post_photos' => array('channel_w_photos', PERMS_W_PHOTOS), + 'chat' => array('channel_w_chat', PERMS_W_CHAT), + ); + + + $ret = array(); + + foreach($perms as $k => $v) { + $ret[$k] = z_check_perms($k,$v,$channel,$contact,$is_contact,$is_site,$is_network,$is_anybody); + + } + + return $ret; + +} + +function z_check_perms($k,$v,$channel,$contact,$is_contact,$is_site,$is_network,$is_anybody) { + + $allow = (($contact['self']) ? true : false); + + switch($channel[$v[0]]) { + case PERMS_PUBLIC: + if($is_anybody) + $allow = true; + break; + case PERMS_NETWORK: + if($is_network) + $allow = true; + break; + case PERMS_SITE: + if($is_site) + $allow = true; + break; + case PERMS_CONTACTS: + if($is_contact) + $allow = true; + break; + case PERMS_SPECIFIC: + if($is_contact && is_array($contact) && ($contact['my_perms'] & $v[1])) + $allow = true; + break; + default: + break; + } + return $allow; +} + diff --git a/include/security.php b/include/security.php index 50c2337bf..dbeeb9177 100644 --- a/include/security.php +++ b/include/security.php @@ -210,7 +210,7 @@ function change_channel($change_channel) { intval($change_channel), intval(get_account_id()) ); - if($r && count($r)) { + if($r) { $hash = $r[0]['channel_hash']; $_SESSION['uid'] = intval($r[0]['channel_id']); get_app()->set_channel($r[0]); @@ -221,8 +221,10 @@ function change_channel($change_channel) { $x = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($hash) ); - if($x && count($x)) + if($x) { get_app()->set_observer($x[0]); + get_app()->set_perms(get_all_perms(local_user(),$hash)); + } } return $ret; diff --git a/mod/item.php b/mod/item.php index 98541b570..1373f48b6 100644 --- a/mod/item.php +++ b/mod/item.php @@ -28,6 +28,8 @@ function item_post(&$a) { if((! local_user()) && (! remote_user()) && (! x($_REQUEST,'commenter'))) return; + logger('get_perms: ' . print_r($a->get_perms(),true)); + require_once('include/security.php'); $uid = local_user(); diff --git a/version.inc b/version.inc index 1c422ffa2..860f87211 100644 --- a/version.inc +++ b/version.inc @@ -1 +1 @@ -2012-10-26.119 +2012-10-28.121 |