> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Dropbox 同步

> 在 Kubernetes 部署中，讓使用者將專案與其 Dropbox 中的資料夾同步。

Dropbox 同步會使用每個 Ayakaleaf Pro pod 中的三個部分，且三者都只有在設定 `DROPBOX_ENABLED: "true"` 時才會啟動：

* **web**（`dropbox` 模組）：連結、專案的 Dropbox 對話方塊，以及 Dropbox 呼叫的 webhook。
* **third-party-datastore**：pod 內的獨立服務，負責處理要傳送至 Dropbox 或從 Dropbox 擷取的變更佇列。
* **document-updater**：啟用 Dropbox 後，它會在所有人離開專案數分鐘後，於背景將編輯器的變更寫入 MongoDB；只有在此之後，這些變更才會送往 Dropbox。

請在 [Dropbox 同步](https://ayakaleaf-pro.mintlify.site/zh-TW/on-premises/configuration/overleaf-toolkit/integrations/dropbox-synchronisation.md)中建立 Dropbox 應用程式並了解同步的運作方式；本頁說明如何將其放入 Kubernetes。

| | |
| - | - |
| 服務 | web（`dropbox` 模組）、third-party-datastore 與 document-updater，位於每個 Ayakaleaf Pro pod 中 |
| Dropbox → Overleaf | 來自網際網路的 `POST ${OVERLEAF_SITE_URL}/dropbox/webhook`，以應用程式密鑰簽署 |
| Pod → Dropbox | `https://api.dropboxapi.com` 與 `https://content.dropboxapi.com` |
| 瀏覽器 → Dropbox | `https://www.dropbox.com/oauth2/authorize`，然後返回 `${OVERLEAF_SITE_URL}/user/dropbox/oauth/callback` |
| 狀態 | Redis 中的待處理變更佇列及其鎖定；MongoDB 中的同步狀態（`dropboxEntities`、`dropboxProjects`） |
| 背景工作 | third-party-datastore 每秒檢查一次其佇列；document-updater 會寫入 3 分鐘內無人開啟的專案 |

### 設定

**1. ConfigMap**

```yaml title="30-config.yaml (additions)" theme={null}
  DROPBOX_ENABLED: "true"
  DROPBOX_APP_KEY: <app key>
  DROPBOX_APP_NAME: Overleaf      # the folder name under Apps/ in Dropbox
  # optional: send the requests to Dropbox through an HTTP proxy
  # DROPBOX_SYNC_PROXY_URL: http://proxy.example.com:3128
```

必須已設定 `GIT_BRIDGE_ENABLED: "true"` 並部署 [Git 整合](https://ayakaleaf-pro.mintlify.site/zh-TW/on-premises/configuration/kubernetes/integrations/git-integration.md)中的 git-bridge StatefulSet：若缺少這些，帳號設定會隱藏專案同步區段。

**2. Secret**

```bash theme={null}
kubectl -n overleaf patch secret overleaf-secrets --type merge -p '{"stringData":{
  "DROPBOX_APP_SECRET":"<app secret>",
  "DROPBOX_TOKEN_CIPHER_PASSWORD":"'"$(openssl rand -hex 32)"'"}}'
```

`DROPBOX_TOKEN_CIPHER_PASSWORD` 用於加密 MongoDB 中使用者的 Dropbox 權杖。每個副本都必須使用相同的值，且之後變更此值會讓每位使用者都必須重新連結 Dropbox。

**3. 建立資料庫索引**

在副本集的主要節點上，執行一次[建立資料庫索引](https://ayakaleaf-pro.mintlify.site/zh-TW/on-premises/configuration/overleaf-toolkit/integrations/dropbox-synchronisation.md#create-the-database-indexes)中的索引指令：

```bash wrap theme={null}
kubectl -n overleaf exec -i mongo-0 -- mongosh --quiet \
  'mongodb://mongo-0.mongo:27017,mongo-1.mongo:27017,mongo-2.mongo:27017/sharelatex?replicaSet=overleaf' <<'EOF'
db.dropboxEntities.createIndex(
  { 'overleaf.userId': 1, 'dropbox.id': 1 },
  { name: 'overleaf.userId_1_dropbox.id_1', unique: true,
    partialFilterExpression: { 'dropbox.id': { $exists: true } } })
db.dropboxEntities.createIndex(
  { 'overleaf.userId': 1, 'overleaf.id': 1 },
  { name: 'overleaf.userId_1_overleaf.id_1', unique: true,
    partialFilterExpression: { 'overleaf.id': { $exists: true } } })
db.dropboxEntities.createIndex({ 'overleaf.userId': 1, 'dropbox.pathLower': 'hashed' })
db.dropboxProjects.createIndex({ userId: 1, projectId: 1 }, { name: 'projectId_userId_1', unique: true })
db.dropboxProjects.createIndex({ userId: 1, dropboxId: 1 }, { name: 'userId_dropboxId_1', unique: true })
EOF
```

**4. 套用並重新啟動**

```bash theme={null}
kubectl apply -f 30-config.yaml
kubectl -n overleaf rollout restart deployment/overleaf     # or statefulset/overleaf
kubectl -n overleaf exec deploy/overleaf -- tail -n 5 /var/log/overleaf/third-party-datastore.log
```

只有當 `DROPBOX_ENABLED` 為 `"true"` 時，`third-party-datastore.log` 才會存在。

**5. 向網際網路開放 webhook**

Dropbox 必須能從網際網路連線至 `${OVERLEAF_SITE_URL}/dropbox/webhook`。若您的 ingress 或負載平衡器只允許外部存取部分路徑或網路，請允許此路徑；這是 Dropbox 唯一會呼叫的路徑。請從叢集外部進行檢查：

```bash theme={null}
curl "https://overleaf.example.com/dropbox/webhook?challenge=test"   # prints: test
```

接著依照 Toolkit 頁面中的說明，在 Dropbox App Console 中新增 webhook。

### 多個副本

除了共用的 `DROPBOX_TOKEN_CIPHER_PASSWORD` 之外，不需要額外處理：

* webhook 可能抵達任何一個副本。它只會將變更排入 Redis 的佇列中。
* 每個副本都會執行 third-party-datastore，且各自處理共用的佇列。使用者的佇列會透過 Redis 中的鎖定取得，因此同一時間只有一個副本會傳送或擷取特定使用者的變更。
* 每個副本的 document-updater 都會在背景寫入閒置的專案。每個專案都是從 Redis 中的共用清單取得，因此只會被寫入一次。

### 在 Kubernetes 上的測試

針對 Dropbox API 的模擬服務，在 Kubernetes 1.37 上以三個副本置於 HAProxy 之後，我們針對 Dropbox 同步的端對端測試全數通過（59 個案例）：連結與取消連結；將專案、編輯、二進位檔案、重新命名、移動與刪除傳送至 Dropbox，包括在專案關閉後透過背景寫入送達的編輯器編輯，而無需編譯或「sync now」；透過 webhook 套用在 Dropbox 中所做的變更（驗證挑戰與簽章檢查）、由新資料夾建立的新專案、已刪除的專案資料夾；同名的專案；編輯器的 Dropbox 對話方塊以及具有速率限制的「sync now」；Dropbox 的重試、速率限制與逾時；當 Dropbox 空間已滿、拒絕權杖或遭停權時取消連結的帳號；已停權的 Overleaf 帳號；以及 third-party-datastore 停止時 webhook 的回應。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.