]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/OAuthTokens/OAuthToken.php
Release 6.5.0
[Github/sugarcrm.git] / modules / OAuthTokens / OAuthToken.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38
39
40 require_once 'Zend/Oauth/Provider.php';
41 require_once 'modules/OAuthKeys/OAuthKey.php';
42
43 /**
44  * OAuth token
45  */
46 class OAuthToken extends SugarBean
47 {
48         public $module_dir = 'OAuthTokens';
49         public $object_name = 'OAuthToken';
50         public $table_name = 'oauth_tokens';
51         public $disable_row_level_security = true;
52
53         public $token;
54     public $secret;
55     public $tstate;
56     public $token_ts;
57     public $verify;
58     public $consumer;
59     public $assigned_user_id;
60     public $consumer_obj;
61     public $callback_url;
62     // authdata is not preserved so far since we don't have any useful data yet
63     // so it's an extension point for the future
64     public $authdata;
65
66     const REQUEST = 1;
67     const ACCESS = 2;
68     const INVALID = 3;
69
70     function __construct($token='', $secret='')
71         {
72             parent::SugarBean();
73         $this->token = $token;
74         $this->secret = $secret;
75         $this->setState(self::REQUEST);
76         }
77
78         /**
79          * Set token state
80          * @param int $s
81          * @return OAuthToken
82          */
83         public function setState($s)
84         {
85             $this->tstate = $s;
86             return $this;
87         }
88
89         /**
90          * Associate the token with the consumer key
91          * @param OAuthKey $consumer
92          * @return OAuthToken
93          */
94         public function setConsumer($consumer)
95         {
96             $this->consumer = $consumer->id;
97             $this->consumer_obj = $consumer;
98             return $this;
99         }
100
101         /**
102          * Set callback URL for request token
103          * @param string $url
104          * @return OAuthToken
105          */
106     public function setCallbackURL($url)
107     {
108         $this->callback_url = $url;
109         return $this;
110     }
111
112     /**
113          * Generate random token
114          * @return string
115          */
116         protected static function randomValue()
117         {
118             return bin2hex(Zend_Oauth_Provider::generateToken(6));
119         }
120
121         /**
122          * Generate random token/secret pair and create token
123          * @return OAuthToken
124          */
125     static function generate()
126     {
127         $t = self::randomValue();
128         $s = self::randomValue();
129         return new self($t, $s);
130     }
131
132     public function save()
133     {
134         $this->token_ts = time();
135         if(!isset($this->id)) {
136             $this->new_with_id = true;
137             $this->id = $this->token;
138         }
139         parent::save();
140     }
141
142     /**
143      * Load token by ID
144      * @param string $token
145          * @return OAuthToken
146      */
147     static function load($token)
148         {
149             $ltoken = new self();
150             $ltoken->retrieve($token);
151         if(empty($ltoken->id)) return null;
152         $ltoken->token = $ltoken->id;
153         if(!empty($ltoken->consumer)) {
154             $ltoken->consumer_obj = BeanFactory::getBean("OAuthKeys", $ltoken->consumer);
155             if(empty($ltoken->consumer_obj->id)) {
156                 return null;
157             }
158         }
159         return $ltoken;
160         }
161
162         /**
163          * Invalidate token
164          */
165         public function invalidate()
166         {
167             $this->setState(self::INVALID);
168             $this->verify = false;
169             return $this->save();
170         }
171
172         /**
173          * Create a new authorized token for specific user
174          * This bypasses normal OAuth process and creates a ready-made access token
175          * @param OAuthKey $consumer
176          * @param User $user
177          * @return OAuthToken
178          */
179         public static function createAuthorized($consumer, $user)
180         {
181             $token = self::generate();
182             $token->setConsumer($consumer);
183             $token->setState(self::ACCESS);
184             $token->assigned_user_id = $user->id;
185         $token->save();
186         return $token;
187         }
188
189         /**
190          * Authorize request token
191          * @param mixed $authdata
192          * @return string Validation token
193          */
194         public function authorize($authdata)
195         {
196             if($this->tstate != self::REQUEST) {
197                 return false;
198             }
199             $this->verify = self::randomValue();
200             $this->authdata = $authdata;
201             if(isset($authdata['user'])) {
202                 $this->assigned_user_id = $authdata['user'];
203             }
204             $this->save();
205             return $this->verify;
206         }
207
208         /**
209          * Copy auth data between tokens
210          * @param OAuthToken $token
211          * @return OAuthToken
212          */
213         public function copyAuthData(OAuthToken $token)
214         {
215             $this->authdata = $token->authdata;
216             $this->assigned_user_id = $token->assigned_user_id;
217             return $this;
218         }
219
220         /**
221          * Get query string for the token
222          */
223         public function queryString()
224         {
225             return "oauth_token={$this->token}&oauth_token_secret={$this->secret}";
226         }
227
228         /**
229          * Clean up stale tokens
230          */
231     static public function cleanup()
232         {
233             global $db;
234             // delete invalidated tokens older than 1 day
235             $db->query("DELETE FROM oauth_token WHERE status = ".self::INVALID." AND token_ts < ".time()-60*60*24);
236             // delete request tokens older than 1 day
237             $db->query("DELETE FROM oauth_token WHERE status = ".self::REQUEST." AND token_ts < ".time()-60*60*24);
238         }
239
240         /**
241          * Check if the nonce is valid
242          * @param string $key
243          * @param string $nonce
244          * @param string $ts
245          */
246         public static function checkNonce($key, $nonce, $ts)
247         {
248             global $db;
249
250             $res = $db->query(sprintf("SELECT * FROM oauth_nonce WHERE conskey='%s' AND nonce_ts > %d", $db->quote($key), $ts));
251             if($res && $db->fetchByAssoc($res)) {
252                 // we have later ts
253                 return Zend_Oauth_Provider::BAD_TIMESTAMP;
254             }
255
256             $res = $db->query(sprintf("SELECT * FROM oauth_nonce WHERE conskey='%s' AND nonce='%s' AND nonce_ts = %d", $db->quote($key), $db->quote($nonce), $ts));
257             if($res && $db->fetchByAssoc($res)) {
258                 // Already seen this one
259                 return Zend_Oauth_Provider::BAD_NONCE;
260         }
261         $db->query(sprintf("DELETE FROM oauth_nonce WHERE conskey='%s' AND nonce_ts < %d", $db->quote($key), $ts));
262         $db->query(sprintf("INSERT INTO oauth_nonce(conskey, nonce, nonce_ts) VALUES('%s', '%s', %d)", $db->quote($key), $db->quote($nonce), $ts));
263             return Zend_Oauth_Provider::OK;
264         }
265
266         /**
267          * Delete token by ID
268          * @param string id
269          * @see SugarBean::mark_deleted($id)
270          */
271         public function mark_deleted($id)
272         {
273             $this->db->query("DELETE from {$this->table_name} WHERE id='".$this->db->quote($id)."'");
274         }
275
276         /**
277          * Delete tokens by consumer ID
278          * @param string $user
279          */
280         public static function deleteByConsumer($consumer_id)
281         {
282            global $db;
283            $db->query("DELETE FROM oauth_tokens WHERE consumer='".$db->quote($consumer_id) ."'");
284         }
285
286         /**
287          * Delete tokens by user ID
288          * @param string $user
289          */
290         public static function deleteByUser($user_id)
291         {
292            global $db;
293            $db->query("DELETE FROM oauth_tokens WHERE assigned_user_id='".$db->quote($user_id) ."'");
294         }
295
296
297 }
298
299 function displayDateFromTs($focus, $field, $value, $view='ListView')
300 {
301     $field = strtoupper($field);
302     if(!isset($focus[$field])) return '';
303     global $timedate;
304     return $timedate->asUser($timedate->fromTimestamp($focus[$field]));
305 }