Commit 32145484 authored by Evan Prodromou's avatar Evan Prodromou

Disallow repeats (retweets) of private notices

We disallow repeating a notice (or whatever) if the scope of the
notice is too private. So, only notices that are public scope
(available to everyone in the world) or site scope (available to
everyone on the site) can be repeated.

Enforce this rule at a low level in Notice.php, and in the API,
commands, and Web UI. Repeat button doesn't appear on tightly-scoped
notices in the Web UI.
parent 908551ae
......@@ -85,8 +85,27 @@ class ApiStatusesRetweetAction extends ApiAuthAction
return false;
}
// Is it OK to repeat that notice (general enough scope)?
if ($this->original->scope != Notice::SITE_SCOPE &&
$this->original->scope != Notice::PUBLIC_SCOPE) {
$this->clientError(_('You may not repeat a private notice.'),
403,
$this->format);
return false;
}
$profile = $this->user->getProfile();
// Can the profile actually see that notice?
if (!$this->original->inScope($profile)) {
$this->clientError(_('No access to that notice.'),
403,
$this->format);
return false;
}
if ($profile->hasRepeated($id)) {
// TRANS: Client error displayed trying to re-repeat a notice through the API.
$this->clientError(_('Already repeated that notice.'),
......@@ -94,6 +113,7 @@ class ApiStatusesRetweetAction extends ApiAuthAction
return false;
}
return true;
}
......
......@@ -73,6 +73,14 @@ class RepeatAction extends Action
return false;
}
// Is it OK to repeat that notice (general enough scope)?
if ($this->notice->scope != Notice::SITE_SCOPE &&
$this->notice->scope != Notice::PUBLIC_SCOPE) {
$this->clientError(_('You may not repeat a private notice.'),
403);
}
if ($this->user->id == $this->notice->profile_id) {
// TRANS: Client error displayed when trying to repeat an own notice.
$this->clientError(_('You cannot repeat your own notice.'));
......@@ -88,6 +96,13 @@ class RepeatAction extends Action
$profile = $this->user->getProfile();
// Can the profile actually see that notice?
if (!$this->notice->inScope($profile)) {
$this->clientError(_('No access to that notice.'), 403);
}
if ($profile->hasRepeated($id)) {
// TRANS: Client error displayed when trying to repeat an already repeated notice.
$this->clientError(_('You already repeated that notice.'));
......
......@@ -90,6 +90,7 @@ class Notice extends Memcached_DataObject
const LOCAL_NONPUBLIC = -1;
const GATEWAY = -2;
const PUBLIC_SCOPE = 0; // Useful fake constant
const SITE_SCOPE = 1;
const ADDRESSEE_SCOPE = 2;
const GROUP_SCOPE = 4;
......@@ -344,6 +345,19 @@ class Notice extends Memcached_DataObject
// Handle repeat case
if (isset($repeat_of)) {
// Check for a private one
$repeat = Notice::staticGet('id', $repeat_of);
if (!empty($repeat) &&
$repeat->scope != Notice::SITE_SCOPE &&
$repeat->scope != Notice::PUBLIC_SCOPE) {
throw new ClientException(_('Cannot repeat a private notice.'), 403);
}
// XXX: Check for access...?
$notice->repeat_of = $repeat_of;
} else {
$notice->reply_to = self::getReplyTo($reply_to, $profile_id, $source, $final);
......
......@@ -544,7 +544,22 @@ class RepeatCommand extends Command
return;
}
if ($this->user->getProfile()->hasRepeated($notice->id)) {
// Is it OK to repeat that notice (general enough scope)?
if ($notice->scope != Notice::SITE_SCOPE &&
$notice->scope != Notice::PUBLIC_SCOPE) {
$channel->error($this->user, _('You may not repeat a private notice.'));
}
$profile = $this->user->getProfile();
// Can the profile actually see that notice?
if (!$notice->inScope($profile)) {
$channel->error($this->user, _('You have no access to that notice.'));
}
if ($profile->hasRepeated($notice->id)) {
// TRANS: Error text shown when trying to repeat an notice that was already repeated by the user.
$channel->error($this->user, _('Already repeated that notice.'));
return;
......
......@@ -596,17 +596,21 @@ class NoticeListItem extends Widget
function showRepeatForm()
{
$user = common_current_user();
if ($user && $user->id != $this->notice->profile_id) {
$this->out->text(' ');
$profile = $user->getProfile();
if ($profile->hasRepeated($this->notice->id)) {
$this->out->element('span', array('class' => 'repeated',
'title' => _('Notice repeated')),
_('Repeated'));
} else {
$rf = new RepeatForm($this->out, $this->notice);
$rf->show();
if ($this->notice->scope == Notice::PUBLIC_SCOPE ||
$this->notice->scope == Notice::SITE_SCOPE) {
$user = common_current_user();
if (!empty($user) &&
$user->id != $this->notice->profile_id) {
$this->out->text(' ');
$profile = $user->getProfile();
if ($profile->hasRepeated($this->notice->id)) {
$this->out->element('span', array('class' => 'repeated',
'title' => _('Notice repeated')),
_('Repeated'));
} else {
$rf = new RepeatForm($this->out, $this->notice);
$rf->show();
}
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment