apiKey = config('fileservers.secret_key'); $this->servers = config('fileservers.servers'); } public function generateZeusToken( int $user_id, string $to, string $action ){ $info = [ 'user_id' => $user_id, 'to' => $to, 'action' => $action, 'generated_at' => time(), 'expires_at' => time() + self::ZEUS_TOKEN_EXPIRATION, 'romhackplaza' => bin2hex(random_bytes(16)), ]; $json = json_encode( $info ); $sig = hash_hmac( 'sha256', $json, $this->apiKey ); $end = base64_encode( $json ) . "|" . $sig; return $end; } public function getRandomServerKey(): string { $keys = array_keys($this->servers); return $keys[array_rand($keys)]; } public function getEntryFileServerKey( EntryFile $file ): string { $serverKey = null; if( $file->favorite_server !== null && $file->favorite_at !== null ) { if( time() < $file->favorite_at + static::FAVORITE_SERVER_TIME ) { $serverKey = $file->favorite_server; } } if( $serverKey === null || !isset( $this->servers[$serverKey] ) ) { $serverKey = $this->getRandomServerKey(); } return $serverKey; } /** * Download URL requires 'filepath' and 'filename'. * * @param EntryFile $file * @return string */ public function getDownloadFileUrl( EntryFile $file ): string { $serverKey = $this->getEntryFileServerKey( $file ); $url = $this->servers[$serverKey]['download'] ?? "#"; if( $url === "#" ) return $url; return $url . "&" . http_build_query( [ 'filename' => $file->filename, 'filepath' => $file->filepath ] ); } /** * @throws ConnectionException */ public function uploadChunk( UploadedFile $chunk, string $fileUUID, int $currentChunk, int $totalChunks, string $filename, string $type ){ // Define or get favorite server. if( $currentChunk === 0 ){ $serverKey = $this->getRandomServerKey(); Cache::put("favorite_server_{$fileUUID}", $serverKey, now()->addHours(2) ); } else { $serverKey = Cache::get( "favorite_server_{$fileUUID}" ); abort_if( !$serverKey, 422, "File upload expired, please retry." ); } $server = $this->servers[$serverKey]; $filepath = $type . '/' . $fileUUID; $response = Http::withHeaders([]) ->attach( 'file', file_get_contents( $chunk->getRealPath() ), $fileUUID ) ->post( $server['upload_chunk'], [ 'filepath' => $filepath, 'filename' => $filename, 'current_chunk' => $currentChunk, 'total_chunks' => $totalChunks, // TODO : Must replace User ID 'zeus' => $this->generateZeusToken( \Auth::user()->user_id, $server['base_url'], "Uploadchunk" ), ]); if (!$response->successful()) { throw new \RuntimeException( $response->body() ); } $data = $response->json(); if( isset( $data['file'] ) && $data['file'] !== false ){ Cache::forget( "favorite_server_{$fileUUID}" ); } $data['favorite_server'] = $serverKey; $data['file_uuid'] = $fileUUID; $data['file_path'] = $filepath; return $data; } }