checkAuthorship events, Ostatus_profile rewrite to handle it
Lost dependency of OStatus plugin for lib/microappplugin.php, whoo! also noting which plugins should be upgraded to new saveActivity support. Favorite plugin won't work with the new system just yet, it doesn't have the necessary functions to extract activity objects, but that's coming in the next (few) commits.
This commit is contained in:
parent
acb07ef52f
commit
9f4bcbad8a
|
@ -109,19 +109,8 @@ abstract class ActivityHandlerPlugin extends Plugin
|
||||||
* gets to figure out how to actually save it into a notice
|
* gets to figure out how to actually save it into a notice
|
||||||
* and any additional data structures you require.
|
* and any additional data structures you require.
|
||||||
*
|
*
|
||||||
* This will handle things received via AtomPub, OStatus
|
* This function is deprecated and in the future, Notice::saveActivity
|
||||||
* (PuSH and Salmon transports), or ActivityStreams-based
|
* should be called from onStartHandleFeedEntryWithProfile in this class.
|
||||||
* backup/restore of account data.
|
|
||||||
*
|
|
||||||
* You should be able to accept as input the output from your
|
|
||||||
* $this->activityObjectFromNotice(). Where applicable, try to
|
|
||||||
* use existing ActivityStreams structures and object types,
|
|
||||||
* and be liberal in accepting input from what might be other
|
|
||||||
* compatible apps.
|
|
||||||
*
|
|
||||||
* All micro-app classes must override this method.
|
|
||||||
*
|
|
||||||
* @fixme are there any standard options?
|
|
||||||
*
|
*
|
||||||
* @param Activity $activity
|
* @param Activity $activity
|
||||||
* @param Profile $actor
|
* @param Profile $actor
|
||||||
|
@ -129,7 +118,36 @@ abstract class ActivityHandlerPlugin extends Plugin
|
||||||
*
|
*
|
||||||
* @return Notice the resulting notice
|
* @return Notice the resulting notice
|
||||||
*/
|
*/
|
||||||
abstract function saveNoticeFromActivity(Activity $activity, Profile $actor, array $options=array());
|
public function saveNoticeFromActivity(Activity $activity, Profile $actor, array $options=array())
|
||||||
|
{
|
||||||
|
// Any plugin which has not implemented saveObjectFromActivity _must_
|
||||||
|
// override this function (which will be deleted when all plugins are migrated).
|
||||||
|
|
||||||
|
if (isset($this->oldSaveNew)) {
|
||||||
|
throw new ServerException('A function has been called for new saveActivity functionality, but is still set with an oldSaveNew configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Notice::saveActivity($activity, $actor, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This usually gets called from Notice::saveActivity after a Notice object has been created,
|
||||||
|
* so it contains a proper id and a uri for the object to be saved.
|
||||||
|
*/
|
||||||
|
public function onStoreActivityObject(Activity $act, Notice $stored, array $options=array(), &$object) {
|
||||||
|
// $this->oldSaveNew is there during a migration period of plugins, to start using
|
||||||
|
// Notice::saveActivity instead of Notice::saveNew
|
||||||
|
if (!$this->isMyActivity($act) || isset($this->oldSaveNew)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$object = $this->saveObjectFromActivity($act, $stored, $options);
|
||||||
|
try {
|
||||||
|
$act->context->attention = array_merge($act->context->attention, $object->getAttentionArray());
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_debug('WARNING: Could not get attention list from object '.get_class($object).'!');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an existing Notice object, your plugin gets to
|
* Given an existing Notice object, your plugin gets to
|
||||||
|
@ -242,22 +260,18 @@ abstract class ActivityHandlerPlugin extends Plugin
|
||||||
* Handle a posted object from PuSH
|
* Handle a posted object from PuSH
|
||||||
*
|
*
|
||||||
* @param Activity $activity activity to handle
|
* @param Activity $activity activity to handle
|
||||||
* @param Ostatus_profile $oprofile Profile for the feed
|
* @param Profile $actor Profile for the feed
|
||||||
*
|
*
|
||||||
* @return boolean hook value
|
* @return boolean hook value
|
||||||
*/
|
*/
|
||||||
function onStartHandleFeedEntryWithProfile(Activity $activity, $oprofile, &$notice)
|
function onStartHandleFeedEntryWithProfile(Activity $activity, Profile $profile, &$notice)
|
||||||
{
|
{
|
||||||
if (!$this->isMyActivity($activity)) {
|
if (!$this->isMyActivity($activity)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$actor = $oprofile->checkAuthorship($activity);
|
// We are guaranteed to get a Profile back from checkAuthorship (or it throws an exception)
|
||||||
|
$profile = ActivityUtils::checkAuthorship($activity, $profile);
|
||||||
if (!$actor instanceof Ostatus_profile) {
|
|
||||||
// TRANS: Client exception thrown when no author for an activity was found.
|
|
||||||
throw new ClientException(_('Cannot get author for activity.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$object = $activity->objects[0];
|
$object = $activity->objects[0];
|
||||||
|
|
||||||
|
@ -266,8 +280,7 @@ abstract class ActivityHandlerPlugin extends Plugin
|
||||||
'is_local' => Notice::REMOTE,
|
'is_local' => Notice::REMOTE,
|
||||||
'source' => 'ostatus');
|
'source' => 'ostatus');
|
||||||
|
|
||||||
// $actor is an ostatus_profile
|
$notice = $this->saveNoticeFromActivity($activity, $profile, $options);
|
||||||
$notice = $this->saveNoticeFromActivity($activity, $actor->localProfile(), $options);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -402,4 +402,35 @@ class ActivityUtils
|
||||||
}
|
}
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check authorship by supplying a Profile as a default and letting plugins
|
||||||
|
// set it to something else if the activity's author is actually someone
|
||||||
|
// else (like with a group or peopletag feed as handled in OStatus).
|
||||||
|
//
|
||||||
|
// NOTE: Returned is not necessarily the supplied profile! For example,
|
||||||
|
// the "feed author" may be a group, but the "activity author" is a person!
|
||||||
|
static function checkAuthorship(Activity $activity, Profile $profile)
|
||||||
|
{
|
||||||
|
if (Event::handle('CheckActivityAuthorship', array($activity, &$profile))) {
|
||||||
|
// if (empty($activity->actor)), then we generated this Activity ourselves and can trust $profile
|
||||||
|
|
||||||
|
$actor_uri = $profile->getUri();
|
||||||
|
|
||||||
|
if (!in_array($actor_uri, array($activity->actor->id, $activity->actor->link))) {
|
||||||
|
// A mismatch between our locally stored URI and the supplied author?
|
||||||
|
// Probably not more than a blog feed or something (with multiple authors or so)
|
||||||
|
// but log it for future inspection.
|
||||||
|
common_log(LOG_WARNING, "Got an actor '{$activity->actor->title}' ({$activity->actor->id}) on single-user feed for " . $actor_uri);
|
||||||
|
} elseif (empty($activity->actor->id)) {
|
||||||
|
// Plain <author> without ActivityStreams actor info.
|
||||||
|
// We'll just ignore this info for now and save the update under the feed's identity.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$profile instanceof Profile) {
|
||||||
|
throw new ServerException('Could not get an author Profile for activity');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $profile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ if (!defined('STATUSNET')) {
|
||||||
|
|
||||||
class BlogPlugin extends MicroAppPlugin
|
class BlogPlugin extends MicroAppPlugin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var $oldSaveNew = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database schema setup
|
* Database schema setup
|
||||||
*
|
*
|
||||||
|
|
|
@ -48,6 +48,8 @@ class BookmarkPlugin extends MicroAppPlugin
|
||||||
const VERSION = '0.1';
|
const VERSION = '0.1';
|
||||||
const IMPORTDELICIOUS = 'BookmarkPlugin:IMPORTDELICIOUS';
|
const IMPORTDELICIOUS = 'BookmarkPlugin:IMPORTDELICIOUS';
|
||||||
|
|
||||||
|
var $oldSaveNew = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorization for importing delicious bookmarks
|
* Authorization for importing delicious bookmarks
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,6 +33,8 @@ if (!defined('STATUSNET')) {
|
||||||
class GNUsocialPhotoPlugin extends MicroAppPlugin
|
class GNUsocialPhotoPlugin extends MicroAppPlugin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var $oldSaveNew = true;
|
||||||
|
|
||||||
function onCheckSchema()
|
function onCheckSchema()
|
||||||
{
|
{
|
||||||
$schema = Schema::get();
|
$schema = Schema::get();
|
||||||
|
|
|
@ -33,6 +33,8 @@ if (!defined('STATUSNET')) {
|
||||||
class GNUsocialVideoPlugin extends MicroAppPlugin
|
class GNUsocialVideoPlugin extends MicroAppPlugin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var $oldSaveNew = true;
|
||||||
|
|
||||||
function onCheckSchema()
|
function onCheckSchema()
|
||||||
{
|
{
|
||||||
$schema = Schema::get();
|
$schema = Schema::get();
|
||||||
|
|
|
@ -1365,4 +1365,19 @@ class OStatusPlugin extends Plugin
|
||||||
{
|
{
|
||||||
list($mentions, $groups) = Ostatus_profile::filterAttention($actor, $attention_uris);
|
list($mentions, $groups) = Ostatus_profile::filterAttention($actor, $attention_uris);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Maybe this shouldn't be so authoritative that it breaks other remote profile lookups?
|
||||||
|
static public function onCheckActivityAuthorship(Activity $activity, Profile &$profile)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$oprofile = Ostatus_profile::getFromProfile($profile);
|
||||||
|
$oprofile = $oprofile->checkAuthorship($activity);
|
||||||
|
$profile = $oprofile->localProfile();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log(LOG_ERR, 'Could not get a profile or check authorship ('.get_class($e).': "'.$e->getMessage().'")');
|
||||||
|
$profile = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -478,7 +478,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
|
|
||||||
// The "WithProfile" events were added later.
|
// The "WithProfile" events were added later.
|
||||||
|
|
||||||
if (Event::handle('StartHandleFeedEntryWithProfile', array($activity, $this, &$notice)) &&
|
if (Event::handle('StartHandleFeedEntryWithProfile', array($activity, $this->localProfile(), &$notice)) &&
|
||||||
Event::handle('StartHandleFeedEntry', array($activity))) {
|
Event::handle('StartHandleFeedEntry', array($activity))) {
|
||||||
|
|
||||||
switch ($activity->verb) {
|
switch ($activity->verb) {
|
||||||
|
@ -516,10 +516,9 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
{
|
{
|
||||||
$notice = null;
|
$notice = null;
|
||||||
|
|
||||||
$oprofile = $this->checkAuthorship($activity);
|
try {
|
||||||
|
$profile = ActivityUtils::checkAuthorship($activity, $this->localProfile());
|
||||||
if (!$oprofile instanceof Ostatus_profile) {
|
} catch (ServerException $e) {
|
||||||
common_log(LOG_INFO, "No author matched share activity");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,7 +669,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
if ($activity->context) {
|
if ($activity->context) {
|
||||||
// TODO: context->attention
|
// TODO: context->attention
|
||||||
list($options['groups'], $options['replies'])
|
list($options['groups'], $options['replies'])
|
||||||
= self::filterAttention($oprofile->localProfile(), $activity->context->attention);
|
= self::filterAttention($profile, $activity->context->attention);
|
||||||
|
|
||||||
// Maintain direct reply associations
|
// Maintain direct reply associations
|
||||||
// @todo FIXME: What about conversation ID?
|
// @todo FIXME: What about conversation ID?
|
||||||
|
@ -713,7 +712,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
$options['urls'][] = $href;
|
$options['urls'][] = $href;
|
||||||
}
|
}
|
||||||
|
|
||||||
$notice = Notice::saveNew($oprofile->profile_id,
|
$notice = Notice::saveNew($profile->id,
|
||||||
$content,
|
$content,
|
||||||
'ostatus',
|
'ostatus',
|
||||||
$options);
|
$options);
|
||||||
|
@ -732,11 +731,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
{
|
{
|
||||||
$notice = null;
|
$notice = null;
|
||||||
|
|
||||||
$oprofile = $this->checkAuthorship($activity);
|
$profile = $this->checkAuthorship($activity, $this->localProfile());
|
||||||
|
|
||||||
if (!$oprofile instanceof Ostatus_profile) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's not always an ActivityObject::NOTE, but... let's just say it is.
|
// It's not always an ActivityObject::NOTE, but... let's just say it is.
|
||||||
|
|
||||||
|
@ -839,7 +834,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
if ($activity->context) {
|
if ($activity->context) {
|
||||||
// TODO: context->attention
|
// TODO: context->attention
|
||||||
list($options['groups'], $options['replies'])
|
list($options['groups'], $options['replies'])
|
||||||
= self::filterAttention($oprofile->localProfile(), $activity->context->attention);
|
= self::filterAttention($profile, $activity->context->attention);
|
||||||
|
|
||||||
// Maintain direct reply associations
|
// Maintain direct reply associations
|
||||||
// @todo FIXME: What about conversation ID?
|
// @todo FIXME: What about conversation ID?
|
||||||
|
@ -882,7 +877,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$saved = Notice::saveNew($oprofile->profile_id,
|
$saved = Notice::saveNew($profile->id,
|
||||||
$content,
|
$content,
|
||||||
'ostatus',
|
'ostatus',
|
||||||
$options);
|
$options);
|
||||||
|
@ -1077,17 +1072,17 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a known Ostatus profile?
|
try {
|
||||||
$oprofile = Ostatus_profile::getKV('profile_id', $profile->id);
|
$oprofile = self::getFromProfile($profile);
|
||||||
if ($oprofile instanceof Ostatus_profile) {
|
// We found the profile, return it!
|
||||||
return $oprofile;
|
return $oprofile;
|
||||||
}
|
} catch (NoResultException $e) {
|
||||||
|
// Could not find an OStatus profile, is it instead a local user?
|
||||||
// Is it a local user?
|
$user = User::getKV('id', $profile->id);
|
||||||
$user = User::getKV('id', $profile->id);
|
if ($user instanceof User) {
|
||||||
if ($user instanceof User) {
|
// @todo i18n FIXME: use sprintf and add i18n (?)
|
||||||
// @todo i18n FIXME: use sprintf and add i18n (?)
|
throw new OStatusShadowException($profile, "'$profile_url' is the profile for local user '{$user->nickname}'.");
|
||||||
throw new OStatusShadowException($profile, "'$profile_url' is the profile for local user '{$user->nickname}'.");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue discovery; it's a remote profile
|
// Continue discovery; it's a remote profile
|
||||||
|
@ -1097,6 +1092,16 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function getFromProfile(Profile $profile)
|
||||||
|
{
|
||||||
|
$oprofile = new Ostatus_profile();
|
||||||
|
$oprofile->profile_id = $profile->id;
|
||||||
|
if (!$oprofile->find(true)) {
|
||||||
|
throw new NoResultException($oprofile);
|
||||||
|
}
|
||||||
|
return $oprofile;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up and if necessary create an Ostatus_profile for remote entity
|
* Look up and if necessary create an Ostatus_profile for remote entity
|
||||||
* with the given update feed. This should never return null -- you will
|
* with the given update feed. This should never return null -- you will
|
||||||
|
@ -2130,7 +2135,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
return $oprofile;
|
return $oprofile;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkAuthorship($activity)
|
public function checkAuthorship(Activity $activity)
|
||||||
{
|
{
|
||||||
if ($this->isGroup() || $this->isPeopletag()) {
|
if ($this->isGroup() || $this->isPeopletag()) {
|
||||||
// A group or propletag feed will contain posts from multiple authors.
|
// A group or propletag feed will contain posts from multiple authors.
|
||||||
|
@ -2165,7 +2170,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||||
$oprofile = $this;
|
$oprofile = $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $oprofile;
|
return $oprofile->localProfile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ class PollPlugin extends MicroAppPlugin
|
||||||
const POLL_OBJECT = 'http://activityschema.org/object/poll';
|
const POLL_OBJECT = 'http://activityschema.org/object/poll';
|
||||||
const POLL_RESPONSE_OBJECT = 'http://activityschema.org/object/poll-response';
|
const POLL_RESPONSE_OBJECT = 'http://activityschema.org/object/poll-response';
|
||||||
|
|
||||||
|
var $oldSaveNew = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database schema setup
|
* Database schema setup
|
||||||
*
|
*
|
||||||
|
|
|
@ -46,6 +46,9 @@ if (!defined('STATUSNET')) {
|
||||||
*/
|
*/
|
||||||
class QnAPlugin extends MicroAppPlugin
|
class QnAPlugin extends MicroAppPlugin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var $oldSaveNew = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up our tables (question and answer)
|
* Set up our tables (question and answer)
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue
Block a user