Просмотр исходного кода

Ticket #5732 - API: Upload with one-time token.

AntonLV 3 недель назад
Родитель
Сommit
d54507c6b9
2 измененных файлов с 57 добавлено и 3 удалено
  1. 2 1
      template/scripts/BxBaseServices.php
  2. 55 2
      template/scripts/BxBaseUploaderServices.php

+ 2 - 1
template/scripts/BxBaseServices.php

@@ -121,7 +121,8 @@ class BxBaseServices extends BxDol implements iBxDolProfileService
             'GetDataApi' => 'BxBaseCmtsServices',
 
             'GetDataApi' => 'BxBaseUploaderServices',
-            
+            'GetUploadToken' => 'BxBaseUploaderServices',
+
             'GetStatBlock' => 'BxBaseDashboardServices',
             
             'PerfomActionApi' => 'BxBaseServiceGrid',

+ 55 - 2
template/scripts/BxBaseUploaderServices.php

@@ -55,10 +55,20 @@ class BxBaseUploaderServices extends BxDol
 
         $iProfileId = (int)bx_get_logged_profile_id();
         $isPrivate = (int)bx_get('p') ? 1 : 0;
+        $sAction = bx_process_input(bx_get('a'));
 
-        $oUploader = BxDolUploader::getObjectInstance($sUploaderObject, $sStorageObject, $sUniqId);
+        // Direct upload (bypassing the app proxy): the profile comes from a one-time upload token.
+        $sUploadToken = bx_get('ut');
+        if($sUploadToken !== false && $sUploadToken !== '') {
+            $sUploadToken = bx_process_input($sUploadToken);
+            $aToken = BxDolKey::getInstance()->getKeyData($sUploadToken, 'uploader');
+            if($sAction != 'upload' || !$this->isUploadTokenValid($aToken, $sUploaderObject, $sStorageObject))
+                return ['error' => _t('_Access denied'), 'code' => 403];
 
-        $sAction = bx_process_input(bx_get('a'));
+            $iProfileId = (int)$aToken['profile_id'];
+        }
+
+        $oUploader = BxDolUploader::getObjectInstance($sUploaderObject, $sStorageObject, $sUniqId);
 
         switch ($sAction) {
 
@@ -78,6 +88,11 @@ class BxBaseUploaderServices extends BxDol
             case 'upload':
                 if(($aFile = $_FILES['file'] ?? false)) {
                     $aResult = $oUploader->handleUploads($iProfileId, $aFile, $isMultiple, $iContentId, $isPrivate);
+
+                    // One-time token: burn it once the file is stored.
+                    if(!empty($sUploadToken))
+                        BxDolKey::getInstance()->removeKey($sUploadToken);
+
                     if(($iId = (int)($aResult['id'] ?? 0)) && ($sImagesTranscoder = bx_get('img_trans')) !== false) {
                         $aGhosts = $oUploader->getGhosts($iProfileId, 'array', bx_process_input($sImagesTranscoder), $iContentId);
                         if(isset($aGhosts[$iId]))
@@ -114,6 +129,44 @@ class BxBaseUploaderServices extends BxDol
 
         }
     }
+
+    public function serviceGetUploadToken()
+    {
+        $iProfileId = (int)bx_get_logged_profile_id();
+        if(!$iProfileId)
+            return ['error' => _t('_Access denied'), 'code' => 403];
+
+        $sUploaderObject = bx_process_input(bx_get('uo'));
+        $sStorageObject = bx_process_input(bx_get('so'));
+        if(!$sUploaderObject || !$sStorageObject || !BxDolUploader::getObjectInstance($sUploaderObject, $sStorageObject, 'token'))
+            return ['error' => _t('_sys_request_page_not_found_cpt'), 'code' => 404];
+
+        $iLifetime = 900;
+        $sToken = BxDolKey::getInstance()->getNewKey([
+            'profile_id' => $iProfileId,
+            'uo' => $sUploaderObject,
+            'so' => $sStorageObject,
+            'expire' => time() + $iLifetime,
+        ], $iLifetime, 'uploader');
+        if(!$sToken)
+            return ['error' => _t('_error occured'), 'code' => 500];
+
+        return [
+            'token' => $sToken,
+            'url' => BX_DOL_URL_ROOT . 'api.php',
+            'expire' => $iLifetime,
+        ];
+    }
+
+    // sys_keys doesn't check expiration on read (only prune does), so the token keeps its own.
+    public function isUploadTokenValid($aToken, $sUploaderObject, $sStorageObject)
+    {
+        return !empty($aToken) && is_array($aToken)
+            && (int)($aToken['profile_id'] ?? 0) > 0
+            && (int)($aToken['expire'] ?? 0) >= time()
+            && ($aToken['uo'] ?? '') === $sUploaderObject
+            && ($aToken['so'] ?? '') === $sStorageObject;
+    }
 }
 
 /** @} */