function new_access_token($token, $consumer, $verifier = null)
 {
     common_debug(sprintf("New access token from request token %s, consumer %s and verifier %s ", $token, $consumer, $verifier), __FILE__);
     $rt = new Token();
     $rt->consumer_key = $consumer->key;
     $rt->tok = $token->key;
     $rt->type = 0;
     // request
     $app = Oauth_application::getByConsumerKey($consumer->key);
     assert(!empty($app));
     if ($rt->find(true) && $rt->state == 1 && $rt->verifier == $verifier) {
         // authorized
         common_debug('Request token found.', __FILE__);
         // find the app and profile associated with this token
         $tokenAssoc = Oauth_token_association::getKV('token', $rt->tok);
         if (!$tokenAssoc) {
             throw new Exception(_('Could not find a profile and application associated with the request token.'));
         }
         // Check to see if we have previously issued an access token for
         // this application and profile; if so we can just return the
         // existing access token. That seems to be the best practice. It
         // makes it so users only have to authorize the app once per
         // machine.
         $appUser = new Oauth_application_user();
         $appUser->application_id = $app->id;
         $appUser->profile_id = $tokenAssoc->profile_id;
         $result = $appUser->find(true);
         if (!empty($result)) {
             common_log(LOG_INFO, sprintf("Existing access token found for application %s, profile %s.", $app->id, $tokenAssoc->profile_id));
             $at = null;
             // Special case: we used to store request tokens in the
             // Oauth_application_user record, and the access_type would
             // always be 0 (no access) as a failsafe until an access
             // token was issued and replaced the request token. There could
             // be a few old Oauth_application_user records storing request
             // tokens still around, and we don't want to accidentally
             // return a useless request token instead of a new access
             // token. So if we find one, we generate a new access token
             // and update the existing Oauth_application_user record before
             // returning the new access token. This should be rare.
             if ($appUser->access_type == 0) {
                 $at = $this->generateNewAccessToken($consumer, $rt, $verifier);
                 $this->updateAppUser($appUser, $app, $at);
             } else {
                 $at = new Token();
                 // fetch the full access token
                 $at->consumer_key = $consumer->key;
                 $at->tok = $appUser->token;
                 $result = $at->find(true);
                 if (!$result) {
                     throw new Exception(_('Could not issue access token.'));
                 }
             }
             // Yay, we can re-issue the access token
             return new OAuthToken($at->tok, $at->secret);
         } else {
             common_log(LOG_INFO, sprintf("Creating new access token for application %s, profile %s.", $app->id, $tokenAssoc->profile_id));
             $at = $this->generateNewAccessToken($consumer, $rt, $verifier);
             $this->newAppUser($tokenAssoc, $app, $at);
             // Okay, good
             return new OAuthToken($at->tok, $at->secret);
         }
     } else {
         // the token was not authorized or not verfied
         common_log(LOG_INFO, sprintf("API OAuth - Attempt to exchange unauthorized or unverified request token %s for an access token.", $rt->tok));
         return null;
     }
 }
Beispiel #2
0
 function new_access_token($token, $consumer, $verifier)
 {
     common_debug(sprintf("New access token from request token %s, consumer %s and verifier %s ", $token, $consumer, $verifier), __FILE__);
     $rt = new Token();
     $rt->consumer_key = $consumer->key;
     $rt->tok = $token->key;
     $rt->type = 0;
     // request
     $app = Oauth_application::getByConsumerKey($consumer->key);
     assert(!empty($app));
     if ($rt->find(true) && $rt->state == 1 && $rt->verifier == $verifier) {
         // authorized
         common_debug('Request token found.', __FILE__);
         // find the app and profile associated with this token
         $tokenAssoc = Oauth_token_association::staticGet('token', $rt->tok);
         if (!$tokenAssoc) {
             throw new Exception(_('Could not find a profile and application associated with the request token.'));
         }
         // check to see if we have previously issued an access token for this application
         // and profile
         $appUser = new Oauth_application_user();
         $appUser->application_id = $app->id;
         $appUser->profile_id = $tokenAssoc->profile_id;
         $result = $appUser->find(true);
         if (!empty($result)) {
             common_log(LOG_INFO, sprintf("Existing access token found for application %s, profile %s.", $app->id, $tokenAssoc->profile_id));
             $at = new Token();
             // fetch the full access token
             $at->consumer_key = $consumer->key;
             $at->tok = $appUser->token;
             $result = $at->find(true);
             if (!$result) {
                 throw new Exception(_('Could not issue access token.'));
             }
             // Yay, we can re-issue the access token
             return new OAuthToken($at->tok, $at->secret);
         } else {
             common_log(LOG_INFO, sprintf("Creating new access token for application %s, profile %s.", $app->id, $tokenAssoc->profile_id));
             // make a brand new access token
             $at = new Token();
             $at->consumer_key = $consumer->key;
             $at->tok = common_good_rand(16);
             $at->secret = common_good_rand(16);
             $at->type = 1;
             // access
             $at->verifier = $verifier;
             $at->verified_callback = $rt->verified_callback;
             // 1.0a
             $at->created = common_sql_now();
             if (!$at->insert()) {
                 $e = $at->_lastError;
                 common_debug('access token "' . $at->tok . '" not inserted: "' . $e->message . '"', __FILE__);
                 return null;
             } else {
                 common_debug('access token "' . $at->tok . '" inserted', __FILE__);
                 // burn the old one
                 $orig_rt = clone $rt;
                 $rt->state = 2;
                 // used
                 if (!$rt->update($orig_rt)) {
                     return null;
                 }
                 common_debug('request token "' . $rt->tok . '" updated', __FILE__);
             }
             // insert a new Oauth_application_user record w/access token
             $appUser = new Oauth_application_user();
             $appUser->profile_id = $tokenAssoc->profile_id;
             $appUser->application_id = $app->id;
             $appUser->access_type = $app->access_type;
             $appUser->token = $at->tok;
             $appUser->created = common_sql_now();
             $result = $appUser->insert();
             if (!$result) {
                 common_log_db_error($appUser, 'INSERT', __FILE__);
                 // TRANS: Server error displayed when a database error occurs.
                 $this->serverError(_('Database error inserting OAuth application user.'));
             }
             // Okay, good
             return new OAuthToken($at->tok, $at->secret);
         }
     } else {
         // the token was not authorized or not verfied
         common_log(LOG_INFO, sprintf("API OAuth - Attempt to exchange unauthorized or unverified request token %s for an access token.", $rt->tok));
         return null;
     }
 }
 function handlePost()
 {
     // check session token for CSRF protection.
     $token = $this->trimmed('token');
     if (!$token || $token != common_session_token()) {
         $this->showForm(_('There was a problem with your session token. Try again, please.'));
         return;
     }
     // check creds
     $user = null;
     if (!common_logged_in()) {
         // XXX Force credentials check?
         // @fixme this should probably use a unified login form handler
         $user = null;
         if (Event::handle('StartOAuthLoginCheck', array($this, &$user))) {
             $user = common_check_user($this->nickname, $this->password);
         }
         Event::handle('EndOAuthLoginCheck', array($this, &$user));
         if (empty($user)) {
             // TRANS: Form validation error given when an invalid username and/or password was passed to the OAuth API.
             $this->showForm(_("Invalid nickname / password!"));
             return;
         }
     } else {
         $user = common_current_user();
     }
     // fetch the token
     $this->reqToken = $this->store->getTokenByKey($this->oauthTokenParam);
     assert(!empty($this->reqToken));
     if ($this->arg('allow')) {
         // mark the req token as authorized
         try {
             $this->store->authorize_token($this->oauthTokenParam);
         } catch (Exception $e) {
             $this->serverError($e->getMessage());
         }
         common_log(LOG_INFO, sprintf("API OAuth - User %d (%s) has authorized request token %s for OAuth application %d (%s).", $user->id, $user->nickname, $this->reqToken->tok, $this->app->id, $this->app->name));
         // XXX: Make sure we have a oauth_token_association table. The table
         // is now in the main schema, but because it is being added with
         // a point release, it's unlikely to be there. This code can be
         // removed as of 1.0.
         $this->ensureOauthTokenAssociationTable();
         $tokenAssoc = new Oauth_token_association();
         $tokenAssoc->profile_id = $user->id;
         $tokenAssoc->application_id = $this->app->id;
         $tokenAssoc->token = $this->oauthTokenParam;
         $tokenAssoc->created = common_sql_now();
         $result = $tokenAssoc->insert();
         if (!$result) {
             common_log_db_error($tokenAssoc, 'INSERT', __FILE__);
             // TRANS: Server error displayed when a database action fails.
             $this->serverError(_('Database error inserting oauth_token_association.'));
         }
         $callback = $this->getCallback();
         if (!empty($callback) && $this->reqToken->verified_callback != 'oob') {
             $targetUrl = $this->buildCallbackUrl($callback, array('oauth_token' => $this->oauthTokenParam, 'oauth_verifier' => $this->reqToken->verifier));
             common_log(LOG_INFO, "Redirecting to callback: {$targetUrl}");
             // Redirect the user to the provided OAuth callback
             common_redirect($targetUrl, 303);
         } elseif ($this->app->type == 2) {
             // Strangely, a web application seems to want to do the OOB
             // workflow. Because no callback was specified anywhere.
             common_log(LOG_WARNING, sprintf("API OAuth - No callback provided for OAuth web client ID %s (%s) " . "during authorization step. Falling back to OOB workflow.", $this->app->id, $this->app->name));
         }
         // Otherwise, inform the user that the rt was authorized
         $this->showAuthorized();
     } else {
         if ($this->arg('cancel')) {
             common_log(LOG_INFO, sprintf("API OAuth - User %d (%s) refused to authorize request token %s for OAuth application %d (%s).", $user->id, $user->nickname, $this->reqToken->tok, $this->app->id, $this->app->name));
             try {
                 $this->store->revoke_token($this->oauthTokenParam, 0);
             } catch (Exception $e) {
                 $this->ServerError($e->getMessage());
             }
             $callback = $this->getCallback();
             // If there's a callback available, inform the consumer the user
             // has refused authorization
             if (!empty($callback) && $this->reqToken->verified_callback != 'oob') {
                 $targetUrl = $this->buildCallbackUrl($callback, array('oauth_problem' => 'user_refused'));
                 common_log(LOG_INFO, "Redirecting to callback: {$targetUrl}");
                 // Redirect the user to the provided OAuth callback
                 common_redirect($targetUrl, 303);
             }
             // otherwise inform the user that authorization for the rt was declined
             $this->showCanceled();
         } else {
             // TRANS: Client error given on when invalid data was passed through a form in the OAuth API.
             $this->clientError(_('Unexpected form submission.'));
         }
     }
 }
Beispiel #4
0
$schema['profile_tag_subscription'] = array('fields' => array('profile_tag_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile_tag'), 'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('profile_tag_id', 'profile_id'), 'foreign keys' => array('profile_tag_subscription_profile_list_id_fkey' => array('profile_list', array('profile_tag_id' => 'id')), 'profile_tag_subscription_profile_id_fkey' => array('profile', array('profile_id' => 'id'))), 'indexes' => array('profile_tag_subscription_profile_id_idx' => array('profile_id'), 'profile_tag_subscription_created_idx' => array('created')));
$schema['profile_block'] = array('fields' => array('blocker' => array('type' => 'int', 'not null' => true, 'description' => 'user making the block'), 'blocked' => array('type' => 'int', 'not null' => true, 'description' => 'profile that is blocked'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date of blocking')), 'foreign keys' => array('profile_block_blocker_fkey' => array('user', array('blocker' => 'id')), 'profile_block_blocked_fkey' => array('profile', array('blocked' => 'id'))), 'primary key' => array('blocker', 'blocked'));
$schema['user_group'] = array('fields' => array('id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'), 'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'nickname for addressing'), 'fullname' => array('type' => 'varchar', 'length' => 255, 'description' => 'display name'), 'homepage' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL, cached so we dont regenerate'), 'description' => array('type' => 'text', 'description' => 'group description'), 'location' => array('type' => 'varchar', 'length' => 255, 'description' => 'related physical location, if any'), 'original_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'original size logo'), 'homepage_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'homepage (profile) size logo'), 'stream_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'stream-sized logo'), 'mini_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'mini logo'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), 'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universal identifier'), 'mainpage' => array('type' => 'varchar', 'length' => 255, 'description' => 'page for group info to link to'), 'join_policy' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=open; 1=requires admin approval'), 'force_scope' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=never,1=sometimes,-1=always')), 'primary key' => array('id'), 'unique keys' => array('user_group_uri_key' => array('uri')), 'indexes' => array('user_group_nickname_idx' => array('nickname')));
$schema['group_member'] = array('fields' => array('group_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to user_group'), 'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'), 'is_admin' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'is this user an admin?'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('group_id', 'profile_id'), 'foreign keys' => array('group_member_group_id_fkey' => array('user_group', array('group_id' => 'id')), 'group_member_profile_id_fkey' => array('profile', array('profile_id' => 'id'))), 'indexes' => array('group_member_profile_id_idx' => array('profile_id'), 'group_member_created_idx' => array('created')));
$schema['related_group'] = array('fields' => array('group_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to user_group'), 'related_group_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to user_group'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created')), 'primary key' => array('group_id', 'related_group_id'), 'foreign keys' => array('related_group_group_id_fkey' => array('user_group', array('group_id' => 'id')), 'related_group_related_group_id_fkey' => array('user_group', array('related_group_id' => 'id'))));
$schema['group_inbox'] = array('description' => 'Many-many table listing notices posted to a given group, or which groups a given notice was posted to.', 'fields' => array('group_id' => array('type' => 'int', 'not null' => true, 'description' => 'group receiving the message'), 'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice received'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice was created')), 'primary key' => array('group_id', 'notice_id'), 'foreign keys' => array('group_inbox_group_id_fkey' => array('user_group', array('group_id' => 'id')), 'group_inbox_notice_id_fkey' => array('notice', array('notice_id' => 'id'))), 'indexes' => array('group_inbox_created_idx' => array('created'), 'group_inbox_notice_id_idx' => array('notice_id')));
$schema['file'] = array('fields' => array('id' => array('type' => 'serial', 'not null' => true), 'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'destination URL after following redirections'), 'mimetype' => array('type' => 'varchar', 'length' => 50, 'description' => 'mime type of resource'), 'size' => array('type' => 'int', 'description' => 'size of resource when available'), 'title' => array('type' => 'varchar', 'length' => 255, 'description' => 'title of resource when available'), 'date' => array('type' => 'int', 'description' => 'date of resource according to http query'), 'protected' => array('type' => 'int', 'description' => 'true when URL is private (needs login)'), 'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'if a local file, name of the file'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('id'), 'unique keys' => array('file_url_key' => array('url')));
$schema['file_oembed'] = array('fields' => array('file_id' => array('type' => 'int', 'not null' => true, 'description' => 'oEmbed for that URL/file'), 'version' => array('type' => 'varchar', 'length' => 20, 'description' => 'oEmbed spec. version'), 'type' => array('type' => 'varchar', 'length' => 20, 'description' => 'oEmbed type: photo, video, link, rich'), 'mimetype' => array('type' => 'varchar', 'length' => 50, 'description' => 'mime type of resource'), 'provider' => array('type' => 'varchar', 'length' => 50, 'description' => 'name of this oEmbed provider'), 'provider_url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL of this oEmbed provider'), 'width' => array('type' => 'int', 'description' => 'width of oEmbed resource when available'), 'height' => array('type' => 'int', 'description' => 'height of oEmbed resource when available'), 'html' => array('type' => 'text', 'description' => 'html representation of this oEmbed resource when applicable'), 'title' => array('type' => 'varchar', 'length' => 255, 'description' => 'title of oEmbed resource when available'), 'author_name' => array('type' => 'varchar', 'length' => 50, 'description' => 'author name for this oEmbed resource'), 'author_url' => array('type' => 'varchar', 'length' => 255, 'description' => 'author URL for this oEmbed resource'), 'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL for this oEmbed resource when applicable (photo, link)'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('file_id'), 'foreign keys' => array('file_oembed_file_id_fkey' => array('file', array('file_id' => 'id'))));
$schema['file_redirection'] = array('fields' => array('url' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'short URL (or any other kind of redirect) for file (id)'), 'file_id' => array('type' => 'int', 'description' => 'short URL for what URL/file'), 'redirections' => array('type' => 'int', 'description' => 'redirect count'), 'httpcode' => array('type' => 'int', 'description' => 'HTTP status code (20x, 30x, etc.)'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('url'), 'foreign keys' => array('file_redirection_file_id_fkey' => array('file' => array('file_id' => 'id'))));
$schema['file_thumbnail'] = array('fields' => array('file_id' => array('type' => 'int', 'not null' => true, 'description' => 'thumbnail for what URL/file'), 'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL of thumbnail'), 'width' => array('type' => 'int', 'description' => 'width of thumbnail'), 'height' => array('type' => 'int', 'description' => 'height of thumbnail'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('file_id'), 'foreign keys' => array('file_thumbnail_file_id_fkey' => array('file', array('file_id' => 'id'))), 'unique keys' => array('file_thumbnail_url_key' => array('url')));
$schema['file_to_post'] = array('fields' => array('file_id' => array('type' => 'int', 'not null' => true, 'description' => 'id of URL/file'), 'post_id' => array('type' => 'int', 'not null' => true, 'description' => 'id of the notice it belongs to'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('file_id', 'post_id'), 'foreign keys' => array('file_to_post_file_id_fkey' => array('file', array('file_id' => 'id')), 'file_to_post_post_id_fkey' => array('notice', array('post_id' => 'id'))), 'indexes' => array('post_id_idx' => array('post_id')));
$schema['group_block'] = array('fields' => array('group_id' => array('type' => 'int', 'not null' => true, 'description' => 'group profile is blocked from'), 'blocked' => array('type' => 'int', 'not null' => true, 'description' => 'profile that is blocked'), 'blocker' => array('type' => 'int', 'not null' => true, 'description' => 'user making the block'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date of blocking')), 'primary key' => array('group_id', 'blocked'), 'foreign keys' => array('group_block_group_id_fkey' => array('user_group', array('group_id' => 'id')), 'group_block_blocked_fkey' => array('profile', array('blocked' => 'id')), 'group_block_blocker_fkey' => array('user', array('blocker' => 'id'))));
$schema['group_alias'] = array('fields' => array('alias' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'additional nickname for the group'), 'group_id' => array('type' => 'int', 'not null' => true, 'description' => 'group profile is blocked from'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date alias was created')), 'primary key' => array('alias'), 'foreign keys' => array('group_alias_group_id_fkey' => array('user_group', array('group_id' => 'id'))), 'indexes' => array('group_alias_group_id_idx' => array('group_id')));
$schema['session'] = array('fields' => array('id' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'session ID'), 'session_data' => array('type' => 'text', 'description' => 'session data'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('id'), 'indexes' => array('session_modified_idx' => array('modified')));
$schema['deleted_notice'] = array('fields' => array('id' => array('type' => 'int', 'not null' => true, 'description' => 'identity of notice'), 'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'author of the notice'), 'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier, usually a tag URI'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice record was created'), 'deleted' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice record was created')), 'primary key' => array('id'), 'unique keys' => array('deleted_notice_uri_key' => array('uri')), 'indexes' => array('deleted_notice_profile_id_idx' => array('profile_id')));
$schema['config'] = array('fields' => array('section' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'default' => '', 'description' => 'configuration section'), 'setting' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'default' => '', 'description' => 'configuration setting'), 'value' => array('type' => 'varchar', 'length' => 255, 'description' => 'configuration value')), 'primary key' => array('section', 'setting'));
$schema['profile_role'] = array('fields' => array('profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'account having the role'), 'role' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'string representing the role'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the role was granted')), 'primary key' => array('profile_id', 'role'), 'foreign keys' => array('profile_role_profile_id_fkey' => array('profile', array('profile_id' => 'id'))));
$schema['location_namespace'] = array('fields' => array('id' => array('type' => 'int', 'not null' => true, 'description' => 'identity for this namespace'), 'description' => array('type' => 'varchar', 'length' => 255, 'description' => 'description of the namespace'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('id'));
$schema['login_token'] = array('fields' => array('user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user owning this token'), 'token' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'token useable for logging in'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('user_id'), 'foreign keys' => array('login_token_user_id_fkey' => array('user', array('user_id' => 'id'))));
$schema['user_location_prefs'] = array('fields' => array('user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user who has the preference'), 'share_location' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Whether to share location data'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('user_id'), 'foreign keys' => array('user_location_prefs_user_id_fkey' => array('user', array('user_id' => 'id'))));
$schema['inbox'] = array('fields' => array('user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user receiving the notice'), 'notice_ids' => array('type' => 'blob', 'description' => 'packed list of notice ids')), 'primary key' => array('user_id'), 'foreign keys' => array('inbox_user_id_fkey' => array('user', array('user_id' => 'id'))));
// @fixme possibly swap this for a more general prefs table?
$schema['user_im_prefs'] = array('fields' => array('user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'), 'screenname' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'screenname on this service'), 'transport' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'transport (ex xmpp, aim)'), 'notify' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Notify when a new notice is sent'), 'replies' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Send replies  from people not subscribed to'), 'microid' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 1, 'description' => 'Publish a MicroID'), 'updatefrompresence' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Send replies from people not subscribed to.'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('user_id', 'transport'), 'unique keys' => array('transport_screenname_key' => array('transport', 'screenname')), 'foreign keys' => array('user_im_prefs_user_id_fkey' => array('user', array('user_id' => 'id'))));
$schema['conversation'] = array('fields' => array('id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'), 'uri' => array('type' => 'varchar', 'length' => 225, 'description' => 'URI of the conversation'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('id'), 'unique keys' => array('conversation_uri_key' => array('uri')));
$schema['local_group'] = array('description' => 'Record for a user group on the local site, with some additional info not in user_group', 'fields' => array('group_id' => array('type' => 'int', 'not null' => true, 'description' => 'group represented'), 'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'group represented'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('group_id'), 'foreign keys' => array('local_group_group_id_fkey' => array('user_group', array('group_id' => 'id'))), 'unique keys' => array('local_group_nickname_key' => array('nickname')));
$schema['user_urlshortener_prefs'] = array('fields' => array('user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'), 'urlshorteningservice' => array('type' => 'varchar', 'length' => 50, 'default' => 'internal', 'description' => 'service to use for auto-shortening URLs'), 'maxurllength' => array('type' => 'int', 'not null' => true, 'description' => 'urls greater than this length will be shortened, 0 = always, null = never'), 'maxnoticelength' => array('type' => 'int', 'not null' => true, 'description' => 'notices with content greater than this value will have all urls shortened, 0 = always, null = never'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('user_id'), 'foreign keys' => array('user_urlshortener_prefs_user_id_fkey' => array('user', array('user_id' => 'id'))));
$schema['schema_version'] = array('description' => 'To avoid checking database structure all the time, we store a checksum of the expected schema info for each table here. If it has not changed since the last time we checked the table, we can leave it as is.', 'fields' => array('table_name' => array('type' => 'varchar', 'length' => '64', 'not null' => true, 'description' => 'Table name'), 'checksum' => array('type' => 'varchar', 'length' => '64', 'not null' => true, 'description' => 'Checksum of schema array; a mismatch indicates we should check the table more thoroughly.'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified')), 'primary key' => array('table_name'));
$schema['group_join_queue'] = Group_join_queue::schemaDef();
$schema['subscription_queue'] = Subscription_queue::schemaDef();
$schema['oauth_token_association'] = Oauth_token_association::schemaDef();