Path: blob/master/src/applications/conduit/storage/PhabricatorConduitToken.php
12256 views
<?php12final class PhabricatorConduitToken3extends PhabricatorConduitDAO4implements PhabricatorPolicyInterface {56protected $objectPHID;7protected $tokenType;8protected $token;9protected $expires;1011private $object = self::ATTACHABLE;1213const TYPE_STANDARD = 'api';14const TYPE_COMMANDLINE = 'cli';15const TYPE_CLUSTER = 'clr';1617protected function getConfiguration() {18return array(19self::CONFIG_COLUMN_SCHEMA => array(20'tokenType' => 'text32',21'token' => 'text32',22'expires' => 'epoch?',23),24self::CONFIG_KEY_SCHEMA => array(25'key_object' => array(26'columns' => array('objectPHID', 'tokenType'),27),28'key_token' => array(29'columns' => array('token'),30'unique' => true,31),32'key_expires' => array(33'columns' => array('expires'),34),35),36) + parent::getConfiguration();37}3839public static function loadClusterTokenForUser(PhabricatorUser $user) {40if (!$user->isLoggedIn()) {41return null;42}4344if ($user->hasConduitClusterToken()) {45return $user->getConduitClusterToken();46}4748$tokens = id(new PhabricatorConduitTokenQuery())49->setViewer($user)50->withObjectPHIDs(array($user->getPHID()))51->withTokenTypes(array(self::TYPE_CLUSTER))52->withExpired(false)53->execute();5455// Only return a token if it has at least 5 minutes left before56// expiration. Cluster tokens cycle regularly, so we don't want to use57// one that's going to expire momentarily.58$now = PhabricatorTime::getNow();59$must_expire_after = $now + phutil_units('5 minutes in seconds');6061$valid_token = null;62foreach ($tokens as $token) {63if ($token->getExpires() > $must_expire_after) {64$valid_token = $token;65break;66}67}6869// We didn't find any existing tokens (or the existing tokens are all about70// to expire) so generate a new token.71if (!$valid_token) {72$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();73$valid_token = self::initializeNewToken(74$user->getPHID(),75self::TYPE_CLUSTER);76$valid_token->save();77unset($unguarded);78}7980$user->attachConduitClusterToken($valid_token);8182return $valid_token;83}8485public static function initializeNewToken($object_phid, $token_type) {86$token = new PhabricatorConduitToken();87$token->objectPHID = $object_phid;88$token->tokenType = $token_type;89$token->expires = $token->getTokenExpires($token_type);9091$secret = $token_type.'-'.Filesystem::readRandomCharacters(32);92$secret = substr($secret, 0, 32);93$token->token = $secret;9495return $token;96}9798public static function getTokenTypeName($type) {99$map = array(100self::TYPE_STANDARD => pht('Standard API Token'),101self::TYPE_COMMANDLINE => pht('Command Line API Token'),102self::TYPE_CLUSTER => pht('Cluster API Token'),103);104105return idx($map, $type, $type);106}107108public static function getAllTokenTypes() {109return array(110self::TYPE_STANDARD,111self::TYPE_COMMANDLINE,112self::TYPE_CLUSTER,113);114}115116private function getTokenExpires($token_type) {117$now = PhabricatorTime::getNow();118switch ($token_type) {119case self::TYPE_STANDARD:120return null;121case self::TYPE_COMMANDLINE:122return $now + phutil_units('1 hour in seconds');123case self::TYPE_CLUSTER:124return $now + phutil_units('30 minutes in seconds');125default:126throw new Exception(127pht('Unknown Conduit token type "%s"!', $token_type));128}129}130131public function getPublicTokenName() {132switch ($this->getTokenType()) {133case self::TYPE_CLUSTER:134return pht('Cluster API Token');135default:136return substr($this->getToken(), 0, 8).'...';137}138}139140public function getObject() {141return $this->assertAttached($this->object);142}143144public function attachObject(PhabricatorUser $object) {145$this->object = $object;146return $this;147}148149150/* -( PhabricatorPolicyInterface )----------------------------------------- */151152153public function getCapabilities() {154return array(155PhabricatorPolicyCapability::CAN_VIEW,156PhabricatorPolicyCapability::CAN_EDIT,157);158}159160public function getPolicy($capability) {161return $this->getObject()->getPolicy($capability);162}163164public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {165return $this->getObject()->hasAutomaticCapability($capability, $viewer);166}167168public function describeAutomaticCapability($capability) {169return pht(170'Conduit tokens inherit the policies of the user they authenticate.');171}172173}174175176