OStatus sub setup code cleanup and partial group fixes (needs more work after the Atom updates are done)

This commit is contained in:
Brion Vibber 2010-02-12 01:11:46 +00:00
parent 525358fa10
commit bc46621af2
3 changed files with 143 additions and 67 deletions

View File

@ -197,6 +197,9 @@ class FeedSubSettingsAction extends ConnectSettingsAction
if ($this->validateFeed()) {
$this->preview = true;
$this->profile = Ostatus_profile::ensureProfile($this->munger);
if (!$this->profile) {
throw new ServerException("Feed profile was not saved properly.");
}
// If not already in use, subscribe to updates via the hub
if ($this->profile->sub_start) {
@ -212,13 +215,10 @@ class FeedSubSettingsAction extends ConnectSettingsAction
// And subscribe the current user to the local profile
$user = common_current_user();
$profile = $this->profile->getLocalProfile();
if (!$profile) {
throw new ServerException("Feed profile was not saved properly.");
}
if ($this->profile->isGroup()) {
if ($user->isMember($profile)) {
$group = $this->profile->localGroup();
if ($user->isMember($group)) {
$this->showForm(_m('Already a member!'));
} elseif (Group_member::join($this->profile->group_id, $user->id)) {
$this->showForm(_m('Joined remote group!'));
@ -226,9 +226,10 @@ class FeedSubSettingsAction extends ConnectSettingsAction
$this->showForm(_m('Remote group join failed!'));
}
} else {
if ($user->isSubscribed($profile)) {
$local = $this->profile->localProfile();
if ($user->isSubscribed($local)) {
$this->showForm(_m('Already subscribed!'));
} elseif ($user->subscribeTo($profile)) {
} elseif ($user->subscribeTo($local)) {
$this->showForm(_m('Feed subscribed!'));
} else {
$this->showForm(_m('Feed subscription failed!'));

View File

@ -84,27 +84,24 @@ class PushCallbackAction extends Action
throw new ServerException("Bogus hub callback: unknown feed", 404);
}
# Can't currently set the token in our sub api
#if ($feedinfo->verify_token !== $verify_token) {
# common_log(LOG_WARNING, __METHOD__ . ": bogus hub callback with bad token \"$verify_token\" for feed $topic");
# throw new ServerError("Bogus hub callback: bad token", 404);
#}
if ($profile->verify_token !== $verify_token) {
common_log(LOG_WARNING, __METHOD__ . ": bogus hub callback with bad token \"$verify_token\" for feed $topic");
throw new ServerError("Bogus hub callback: bad token", 404);
}
if ($mode != $profile->sub_state) {
common_log(LOG_WARNING, __METHOD__ . ": bogus hub callback with bad mode \"$mode\" for feed $topic in state \"{$profile->sub_state}\"");
throw new ServerException("Bogus hub callback: mode doesn't match subscription state.", 404);
}
// OK!
if ($mode == 'subscribe') {
common_log(LOG_INFO, __METHOD__ . ': sub confirmed');
$profile->sub_start = common_sql_date(time());
if ($lease_seconds > 0) {
$profile->sub_end = common_sql_date(time() + $lease_seconds);
} else {
$profile->sub_end = null;
}
$profile->update();
$profile->confirmSubscribe($lease_seconds);
} else {
common_log(LOG_INFO, __METHOD__ . ": unsub confirmed; deleting sub record for $topic");
$profile->delete();
$profile->confirmUnsubscribe();
}
print $challenge;
}
}

View File

@ -182,9 +182,24 @@ class Ostatus_profile extends Memcached_DataObject
* Fetch the StatusNet-side profile for this feed
* @return Profile
*/
public function getLocalProfile()
public function localProfile()
{
return Profile::staticGet('id', $this->profile_id);
if ($this->profile_id) {
return Profile::staticGet('id', $this->profile_id);
}
return null;
}
/**
* Fetch the StatusNet-side profile for this feed
* @return Profile
*/
public function localGroup()
{
if ($this->group_id) {
return User_group::staticGet('id', $this->group_id);
}
return null;
}
/**
@ -194,73 +209,96 @@ class Ostatus_profile extends Memcached_DataObject
*/
public static function ensureProfile($munger)
{
$entity = $munger->ostatusProfile();
$profile = $munger->ostatusProfile();
$current = self::staticGet('feeduri', $entity->feeduri);
$current = self::staticGet('feeduri', $profile->feeduri);
if ($current) {
// @fixme we should probably update info as necessary
return $current;
}
$entity->query('BEGIN');
$profile->query('BEGIN');
// Awful hack! Awful hack!
$entity->verify = common_good_rand(16);
$entity->secret = common_good_rand(32);
$profile->verify = common_good_rand(16);
$profile->secret = common_good_rand(32);
try {
$profile = $munger->profile();
$local = $munger->profile();
if ($entity->isGroup()) {
$group = new User_group();
$group->nickname = $local->nickname . '@remote'; // @fixme
$group->fullname = $local->fullname;
$group->homepage = $local->homepage;
$group->location = $local->location;
$group->created = $local->created;
$group->insert();
if (empty($result)) {
throw new FeedDBException($group);
}
$profile->group_id = $group->id;
} else {
$result = $local->insert();
if (empty($result)) {
throw new FeedDBException($local);
}
$profile->profile_id = $local->id;
}
$profile->created = sql_common_date();
$profile->lastupdate = sql_common_date();
$result = $profile->insert();
if (empty($result)) {
throw new FeedDBException($profile);
}
$avatar = $munger->getAvatar();
if ($avatar) {
// @fixme this should be better encapsulated
// ripped from oauthstore.php (for old OMB client)
$temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
copy($avatar, $temp_filename);
$imagefile = new ImageFile($profile->id, $temp_filename);
$filename = Avatar::filename($profile->id,
image_type_to_extension($imagefile->type),
null,
common_timestamp());
rename($temp_filename, Avatar::path($filename));
$profile->setOriginal($filename);
}
$entity->profile_id = $profile->id;
if ($entity->isGroup()) {
$group = new User_group();
$group->nickname = $profile->nickname . '@remote'; // @fixme
$group->fullname = $profile->fullname;
$group->homepage = $profile->homepage;
$group->location = $profile->location;
$group->created = $profile->created;
$group->insert();
if ($avatar) {
$group->setOriginal($filename);
}
$entity->group_id = $group->id;
}
$result = $entity->insert();
if (empty($result)) {
throw new FeedDBException($entity);
}
$entity->query('COMMIT');
} catch (FeedDBException $e) {
common_log_db_error($e->obj, 'INSERT', __FILE__);
$entity->query('ROLLBACK');
return false;
}
$avatar = $munger->getAvatar();
if ($avatar) {
try {
$this->updateAvatar($avatar);
} catch (Exception $e) {
common_log(LOG_ERR, "Exception setting OStatus avatar: " .
$e->getMessage());
}
}
return $entity;
}
/**
* Download and update given avatar image
* @param string $url
* @throws Exception in various failure cases
*/
public function updateAvatar($url)
{
// @fixme this should be better encapsulated
// ripped from oauthstore.php (for old OMB client)
$temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
copy($url, $temp_filename);
$imagefile = new ImageFile($profile->id, $temp_filename);
$filename = Avatar::filename($profile->id,
image_type_to_extension($imagefile->type),
null,
common_timestamp());
rename($temp_filename, Avatar::path($filename));
if ($this->isGroup()) {
$group = $this->localGroup();
$group->setOriginal($filename);
} else {
$profile = $this->localProfile();
$profile->setOriginal($filename);
}
}
/**
* Damn dirty hack!
*/
@ -318,6 +356,46 @@ class Ostatus_profile extends Memcached_DataObject
}
}
/**
* Save PuSH subscription confirmation.
* Sets approximate lease start and end times and finalizes state.
*
* @param int $lease_seconds provided hub.lease_seconds parameter, if given
*/
public function confirmSubscribe($lease_seconds=0)
{
$original = clone($this);
$this->sub_state = 'active';
$this->sub_start = common_sql_date(time());
if ($lease_seconds > 0) {
$this->sub_end = common_sql_date(time() + $lease_seconds);
} else {
$this->sub_end = null;
}
$this->lastupdate = common_sql_date();
return $this->update($original);
}
/**
* Save PuSH unsubscription confirmation.
* Wipes active PuSH sub info and resets state.
*/
public function confirmUnsubscribe()
{
$original = clone($this);
$this->verify_token = null;
$this->secret = null;
$this->sub_state = null;
$this->sub_start = null;
$this->sub_end = null;
$this->lastupdate = common_sql_date();
return $this->update($original);
}
/**
* Send an unsubscription request to the hub for this feed.
* The hub will later send us a confirmation POST to /main/push/callback.