Merge branch 'main' into mobile_face
4
.github/workflows/auth-crowdin.yml
vendored
|
@ -9,8 +9,8 @@ on:
|
|||
- ".github/workflows/auth-crowdin.yml"
|
||||
branches: [main]
|
||||
schedule:
|
||||
# See: [Note: Run every 24 hours]
|
||||
- cron: "50 1 * * *"
|
||||
# See: [Note: Run workflow on specific days of the week]
|
||||
- cron: "50 1 * * 2,5"
|
||||
# Also allow manually running the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
|
|
4
.github/workflows/mobile-crowdin.yml
vendored
|
@ -9,8 +9,8 @@ on:
|
|||
- ".github/workflows/mobile-crowdin.yml"
|
||||
branches: [main]
|
||||
schedule:
|
||||
# See: [Note: Run every 24 hours]
|
||||
- cron: "40 1 * * *"
|
||||
# See: [Note: Run workflow on specific days of the week]
|
||||
- cron: "40 1 * * 2,5"
|
||||
# Also allow manually running the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
|
|
2
.github/workflows/mobile-lint.yml
vendored
|
@ -3,7 +3,7 @@ name: "Lint (mobile)"
|
|||
on:
|
||||
# Run on every push to a branch other than main that changes mobile/
|
||||
push:
|
||||
branches-ignore: [main]
|
||||
branches-ignore: [main, f-droid]
|
||||
paths:
|
||||
- "mobile/**"
|
||||
- ".github/workflows/mobile-lint.yml"
|
||||
|
|
2
.github/workflows/mobile-release.yml
vendored
|
@ -49,7 +49,7 @@ jobs:
|
|||
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD_PHOTOS }}
|
||||
|
||||
- name: Checksum
|
||||
run: sha256sum build/app/outputs/flutter-apk/ente.apk > build/app/outputs/flutter-apk/sha256sum
|
||||
run: sha256sum build/app/outputs/flutter-apk/ente-${{ github.ref_name }}.apk > build/app/outputs/flutter-apk/sha256sum
|
||||
|
||||
- name: Create a draft GitHub release
|
||||
uses: ncipollo/release-action@v1
|
||||
|
|
10
.github/workflows/web-crowdin.yml
vendored
|
@ -9,8 +9,14 @@ on:
|
|||
- ".github/workflows/web-crowdin.yml"
|
||||
branches: [main]
|
||||
schedule:
|
||||
# See: [Note: Run every 24 hours]
|
||||
- cron: "20 1 * * *"
|
||||
# [Note: Run workflow on specific days of the week]
|
||||
#
|
||||
# The last (5th) component of the cron syntax denotes the day of the
|
||||
# week, with 0 == SUN and 6 == SAT. So, for example, to run on every TUE
|
||||
# and FRI, this can be set to `2,5`.
|
||||
#
|
||||
# See also: [Note: Run workflow every 24 hours]
|
||||
- cron: "20 1 * * 2,5"
|
||||
# Also allow manually running the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
|
|
2
.github/workflows/web-nightly.yml
vendored
|
@ -2,7 +2,7 @@ name: "Nightly (web)"
|
|||
|
||||
on:
|
||||
schedule:
|
||||
# [Note: Run every 24 hours]
|
||||
# [Note: Run workflow every 24 hours]
|
||||
#
|
||||
# Run every 24 hours - First field is minute, second is hour of the day
|
||||
# This runs 23:15 UTC everyday - 1 and 15 are just arbitrary offset to
|
||||
|
|
7
.gitmodules
vendored
|
@ -9,16 +9,9 @@
|
|||
[submodule "auth/assets/simple-icons"]
|
||||
path = auth/assets/simple-icons
|
||||
url = https://github.com/simple-icons/simple-icons.git
|
||||
[submodule "mobile/thirdparty/flutter"]
|
||||
path = mobile/thirdparty/flutter
|
||||
url = https://github.com/flutter/flutter.git
|
||||
branch = stable
|
||||
[submodule "mobile/plugins/clip_ggml"]
|
||||
path = mobile/plugins/clip_ggml
|
||||
url = https://github.com/ente-io/clip-ggml.git
|
||||
[submodule "mobile/thirdparty/isar"]
|
||||
path = mobile/thirdparty/isar
|
||||
url = https://github.com/isar/isar
|
||||
[submodule "web/apps/photos/thirdparty/ffmpeg-wasm"]
|
||||
path = web/apps/photos/thirdparty/ffmpeg-wasm
|
||||
url = https://github.com/abhinavkgrd/ffmpeg.wasm.git
|
||||
|
|
3
auth/.gitignore
vendored
|
@ -9,6 +9,9 @@
|
|||
.history
|
||||
.svn/
|
||||
|
||||
# Editors
|
||||
.vscode/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
# Releases
|
||||
|
||||
Create a PR to bump up the version in `pubspec.yaml`. Once that is merged, tag
|
||||
main, and push the tag.
|
||||
Create a PR to bump up the version in `pubspec.yaml`.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Use [semver](https://semver.org/) for the tags, with `auth-` as a prefix.
|
||||
> Multiple beta releases for the same upcoming version can be done by adding
|
||||
> build metadata at the end, e.g. `auth-v1.2.3-beta+3`.
|
||||
|
||||
Once that is merged, tag main, and push the tag.
|
||||
|
||||
```sh
|
||||
git tag auth-v1.2.3
|
||||
|
@ -16,6 +23,11 @@ This'll trigger a GitHub workflow that:
|
|||
* Creates a new release in the internal track on Play Store.
|
||||
|
||||
Once the workflow completes, go to the draft GitHub release that was created.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Keep the title of the release same as the tag.
|
||||
|
||||
Set "Previous tag" to the last release of auth and press "Generate release
|
||||
notes". The generated release note will contain all PRs and new contributors
|
||||
from all the releases in the monorepo, so you'll need to filter them to keep
|
||||
|
|
1
auth/lib/l10n/arb/app_bg.arb
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -144,6 +144,7 @@
|
|||
"enterCodeHint": "Geben Sie den 6-stelligen Code \naus Ihrer Authentifikator-App ein.",
|
||||
"lostDeviceTitle": "Gerät verloren?",
|
||||
"twoFactorAuthTitle": "Zwei-Faktor-Authentifizierung",
|
||||
"passkeyAuthTitle": "Passkey Authentifizierung",
|
||||
"recoverAccount": "Konto wiederherstellen",
|
||||
"enterRecoveryKeyHint": "Geben Sie Ihren Wiederherstellungsschlüssel ein",
|
||||
"recover": "Wiederherstellen",
|
||||
|
@ -404,5 +405,14 @@
|
|||
"signOutOtherDevices": "Andere Geräte abmelden",
|
||||
"doNotSignOut": "Nicht abmelden",
|
||||
"hearUsWhereTitle": "Wie hast du von Ente erfahren? (optional)",
|
||||
"hearUsExplanation": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!"
|
||||
"hearUsExplanation": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!",
|
||||
"waitingForBrowserRequest": "Warten auf Browseranfrage...",
|
||||
"passkey": "Passkey",
|
||||
"developerSettingsWarning": "Sind Sie sicher, dass Sie die Entwicklereinstellungen ändern möchten?",
|
||||
"developerSettings": "Entwicklereinstellungen",
|
||||
"serverEndpoint": "Server Endpunkt",
|
||||
"invalidEndpoint": "Ungültiger Endpunkt",
|
||||
"invalidEndpointMessage": "Der eingegebene Endpunkt ist ungültig. Bitte geben Sie einen gültigen Endpunkt ein und versuchen Sie es erneut.",
|
||||
"endpointUpdatedMessage": "Endpunkt erfolgreich aktualisiert",
|
||||
"customEndpoint": "Mit {endpoint} verbunden"
|
||||
}
|
|
@ -144,6 +144,8 @@
|
|||
"enterCodeHint": "認証アプリに表示された 6 桁のコードを入力してください",
|
||||
"lostDeviceTitle": "デバイスを紛失しましたか?",
|
||||
"twoFactorAuthTitle": "2 要素認証",
|
||||
"passkeyAuthTitle": "パスキー認証",
|
||||
"verifyPasskey": "パスキーの認証",
|
||||
"recoverAccount": "アカウントを回復",
|
||||
"enterRecoveryKeyHint": "回復キーを入力",
|
||||
"recover": "回復",
|
||||
|
@ -404,5 +406,15 @@
|
|||
"signOutOtherDevices": "他のデバイスからサインアウトする",
|
||||
"doNotSignOut": "サインアウトしない",
|
||||
"hearUsWhereTitle": "Ente についてどのようにお聞きになりましたか?(任意)",
|
||||
"hearUsExplanation": "私たちはアプリのインストールを追跡していません。私たちをお知りになった場所を教えてください!"
|
||||
"hearUsExplanation": "私たちはアプリのインストールを追跡していません。私たちをお知りになった場所を教えてください!",
|
||||
"waitingForBrowserRequest": "ブラウザのリクエストを待っています...",
|
||||
"waitingForVerification": "認証を待っています...",
|
||||
"passkey": "パスキー",
|
||||
"developerSettingsWarning": "開発者向け設定を変更してもよろしいですか?",
|
||||
"developerSettings": "開発者向け設定",
|
||||
"serverEndpoint": "サーバーエンドポイント",
|
||||
"invalidEndpoint": "無効なエンドポイントです",
|
||||
"invalidEndpointMessage": "入力されたエンドポイントは無効です。有効なエンドポイントを入力して再試行してください。",
|
||||
"endpointUpdatedMessage": "エンドポイントの更新に成功しました",
|
||||
"customEndpoint": "{endpoint} に接続しました"
|
||||
}
|
|
@ -144,6 +144,7 @@
|
|||
"enterCodeHint": "Digite o código de 6 dígitos de\nseu aplicativo autenticador",
|
||||
"lostDeviceTitle": "Perdeu seu dispositivo?",
|
||||
"twoFactorAuthTitle": "Autenticação de dois fatores",
|
||||
"passkeyAuthTitle": "Autenticação via Chave de acesso",
|
||||
"recoverAccount": "Recuperar conta",
|
||||
"enterRecoveryKeyHint": "Digite sua chave de recuperação",
|
||||
"recover": "Recuperar",
|
||||
|
@ -404,5 +405,14 @@
|
|||
"signOutOtherDevices": "Terminar sessão em outros dispositivos",
|
||||
"doNotSignOut": "Não encerrar sessão",
|
||||
"hearUsWhereTitle": "Como você ouviu sobre o Ente? (opcional)",
|
||||
"hearUsExplanation": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!"
|
||||
"hearUsExplanation": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!",
|
||||
"waitingForBrowserRequest": "Aguardando solicitação do navegador...",
|
||||
"passkey": "Chave de acesso",
|
||||
"developerSettingsWarning": "Tem certeza de que deseja modificar as configurações de Desenvolvedor?",
|
||||
"developerSettings": "Configurações de desenvolvedor",
|
||||
"serverEndpoint": "Endpoint do servidor",
|
||||
"invalidEndpoint": "Endpoint inválido",
|
||||
"invalidEndpointMessage": "Desculpe, o endpoint que você inseriu é inválido. Por favor, insira um endpoint válido e tente novamente.",
|
||||
"endpointUpdatedMessage": "Endpoint atualizado com sucesso",
|
||||
"customEndpoint": "Conectado a {endpoint}"
|
||||
}
|
|
@ -131,6 +131,16 @@
|
|||
"about": "Om",
|
||||
"terms": "Villkor",
|
||||
"warning": "Varning",
|
||||
"importSuccessDesc": "Du har importerat {count} koder!",
|
||||
"@importSuccessDesc": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"description": "The number of codes imported",
|
||||
"type": "int",
|
||||
"example": "1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pendingSyncs": "Varning",
|
||||
"activeSessions": "Aktiva sessioner",
|
||||
"enterPassword": "Ange lösenord",
|
||||
|
@ -143,5 +153,7 @@
|
|||
"iOSOkButton": "OK",
|
||||
"@iOSOkButton": {
|
||||
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters."
|
||||
}
|
||||
},
|
||||
"noInternetConnection": "Ingen internetanslutning",
|
||||
"pleaseCheckYourInternetConnectionAndTryAgain": "Kontrollera din internetanslutning och försök igen."
|
||||
}
|
|
@ -407,6 +407,12 @@
|
|||
"hearUsWhereTitle": "您是如何知道Ente的? (可选的)",
|
||||
"hearUsExplanation": "我们不跟踪应用程序安装情况。如果您告诉我们您是在哪里找到我们的,将会有所帮助!",
|
||||
"waitingForBrowserRequest": "正在等待浏览器请求...",
|
||||
"launchPasskeyUrlAgain": "再次启动 通行密钥 URL",
|
||||
"passkey": "通行密钥"
|
||||
"passkey": "通行密钥",
|
||||
"developerSettingsWarning": "您确定要修改开发者设置吗?",
|
||||
"developerSettings": "开发者设置",
|
||||
"serverEndpoint": "服务器端点",
|
||||
"invalidEndpoint": "端点无效",
|
||||
"invalidEndpointMessage": "抱歉,您输入的端点无效。请输入有效的端点,然后重试。",
|
||||
"endpointUpdatedMessage": "端点更新成功",
|
||||
"customEndpoint": "已连接至 {endpoint}"
|
||||
}
|
4
auth/migration-guides/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
Migration guides have moved to the [help
|
||||
docs](https://help.ente.io/auth/migration-guides/). This folder just contains
|
||||
redirects for old links.
|
||||
|
|
@ -1,62 +1,2 @@
|
|||
# Migrating from Authy
|
||||
A guide written by Green, an ente.io lover
|
||||
|
||||
---
|
||||
|
||||
Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. But do not fear, as there is a much simpler way to migrate from Authy to ente!
|
||||
|
||||
A user on GitHub has written a guide to export our data from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration.
|
||||
|
||||
## Exporting from Authy
|
||||
To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). This will create a new JSON file with all your Authy TOTP data in it. **Do not share this file with anyone!**
|
||||
|
||||
Or, you can [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator.
|
||||
### *Do note that these tools may not export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account!*
|
||||
|
||||
## Converting the export for ente Authenticator
|
||||
### Update: You can now directly import from Bitwarden JSON export, meaning you can skip this step! If it doesn't work for some reason, though, then continue with this step.
|
||||
So now that you have the JSON file, does that mean it can be imported into ente Authenticator? Yes, but if it doesn't work for some reason, then nope. (If you have a TXT file in the format ente Authenticator asked you for instead, then you probably used Neeraj's tool, so you can skip this step.)
|
||||
|
||||
This is because the code in the guide exports your Authy data for Bitwarden, not ente Authenticator. If you have opened the JSON file, you might have noticed that the file created is not in a format that ente Authenticator asks for:
|
||||
|
||||
<img width="454" alt="ente Authenticator Screenshot" src="https://github.com/gweeeen/auth/assets/41323182/30566a69-cfa0-4de0-9f0d-95967d4c5cad">
|
||||
|
||||
So, this means that even if you try to import this file, nothing will happen. But don't worry, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use! (It's definitely not written **professionaly**, but hey it gets the job done so I'm happy with that.)
|
||||
|
||||
You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py). Or if you **really like making life hard**, then you can make a new Python file and copy this code to it:
|
||||
|
||||
```py
|
||||
import json
|
||||
import os
|
||||
|
||||
totp = []
|
||||
|
||||
accounts = json.load(open('authy-to-bitwarden-export.json','r',encoding='utf-8'))
|
||||
|
||||
for account in accounts['items']:
|
||||
totp.append(account['login']['totp']+'\n')
|
||||
|
||||
writer = open('auth_codes.txt','w+',encoding='utf-8')
|
||||
writer.writelines(totp)
|
||||
writer.close()
|
||||
|
||||
print('Saved to ' + os.getcwd() + '/auth_codes.txt')
|
||||
```
|
||||
|
||||
To convert the file with this program, you will need to install [Python](https://www.python.org/downloads/) on your computer.
|
||||
|
||||
Before you run the program, make sure that both the Python program and the JSON file are in the same directory, otherwise this will not work!
|
||||
|
||||
To run the Python program, open it in IDLE and press F5, or open your terminal and type `python3 authy_to_ente.py` or `py -3 authy_to_ente.py`, depending on which OS you have. Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator!
|
||||
|
||||
## Importing to ente Authenticator
|
||||
Now that we have the TXT file, let's import it. This should be the easiest part of the entire migration process.
|
||||
|
||||
1. Copy the TXT file to one of your devices with ente Authenticator.
|
||||
2. Log in to your account (if you haven't already).
|
||||
3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes".
|
||||
4. Select the TXT file that was made earlier.
|
||||
|
||||
And that's it! You have now successfully migrated from Authy to ente Authenticator.
|
||||
|
||||
Just one more thing: Now that your secrets are safely stored, I recommend you delete the unencrypted JSON and TXT files that were made during the migration process for security.
|
||||
Moved to
|
||||
[help.ente.io/auth/migration-guides/authy](https://help.ente.io/auth/migration-guides/authy/)
|
||||
|
|
|
@ -1,63 +1,2 @@
|
|||
# Auth Encrypted Export format
|
||||
|
||||
## Overview
|
||||
|
||||
When we export the auth codes, the data is encrypted using a key derived from the user's password.
|
||||
This document describes the JSON structure used to organize exported data, including versioning and key derivation
|
||||
parameters.
|
||||
|
||||
## Export JSON Sample
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"kdfParams": {
|
||||
"memLimit": 4096,
|
||||
"opsLimit": 3,
|
||||
"salt": "example_salt"
|
||||
},
|
||||
"encryptedData": "encrypted_data_here",
|
||||
"encryptionNonce": "nonce_here"
|
||||
}
|
||||
```
|
||||
|
||||
The main object used to represent the export data. It contains the following key-value pairs:
|
||||
|
||||
- `version`: The version of the export format.
|
||||
- `kdfParams`: Key derivation function parameters.
|
||||
- `encryptedData"`: The encrypted authentication data.
|
||||
- `encryptionNonce`: The nonce used for encryption.
|
||||
|
||||
### Version
|
||||
|
||||
Export version is used to identify the format of the export data.
|
||||
|
||||
#### Ver: 1
|
||||
|
||||
* KDF Algorithm: `ARGON2ID`
|
||||
* Decrypted data format: `otpauth://totp/...`, separated by a new line.
|
||||
* Encryption Algo: `XChaCha20-Poly1305`
|
||||
|
||||
#### Key Derivation Function Params (KDF)
|
||||
|
||||
This section contains the parameters that were using during KDF operation:
|
||||
|
||||
- `memLimit`: Memory limit for the algorithm.
|
||||
- `opsLimit`: Operations limit for the algorithm.
|
||||
- `salt`: The salt used in the derivation process.
|
||||
|
||||
#### Encrypted Data
|
||||
|
||||
As mentioned above, the auth data is encrypted using a key that's derived by using user provided password & kdf params.
|
||||
For encryption, we are using `XChaCha20-Poly1305` algorithm.
|
||||
|
||||
## How to use the exported data
|
||||
|
||||
* **Ente Authenticator app**: You can directly import the codes in the Ente Authenticator app.
|
||||
> Settings -> Data -> Import Codes -> ente Encrypted export.
|
||||
|
||||
* **Decrypt using Ente CLI** : Download the latest version of [Ente CLI](https://github.com/ente-io/ente/releases?q=CLI&expanded=false), and run the following command
|
||||
|
||||
```
|
||||
./ente auth decrypt <export_file> <output_file>
|
||||
```
|
||||
Moved to
|
||||
[help.ente.io/auth/migration-guides/export](https://help.ente.io/auth/migration-guides/export/)
|
||||
|
|
1
cli/.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
docs/generated/*.md linguist-generated=true
|
|
@ -7,7 +7,7 @@ use it to decrypting the export from Ente Auth.
|
|||
## Install
|
||||
|
||||
The easiest way is to download a pre-built binary from the [GitHub
|
||||
releases](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0&expanded=true).
|
||||
releases](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0).
|
||||
|
||||
You can also build these binaries yourself
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ var _userDetailsCmd = &cobra.Command{
|
|||
flags.UserEmail = f.Value.String()
|
||||
}
|
||||
})
|
||||
if flags.UserEmail == "" {
|
||||
return fmt.Errorf("user email is required")
|
||||
}
|
||||
return ctrl.GetUserId(context.Background(), *flags)
|
||||
},
|
||||
}
|
||||
|
@ -47,14 +50,55 @@ var _disable2faCmd = &cobra.Command{
|
|||
flags.UserEmail = f.Value.String()
|
||||
}
|
||||
})
|
||||
fmt.Println("Not supported yet")
|
||||
return nil
|
||||
if flags.UserEmail == "" {
|
||||
return fmt.Errorf("user email is required")
|
||||
}
|
||||
return ctrl.Disable2FA(context.Background(), *flags)
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
var _deleteUser = &cobra.Command{
|
||||
Use: "delete-user",
|
||||
Short: "Delete a user",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
recoverWithLog()
|
||||
var flags = &model.AdminActionForUser{}
|
||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
||||
if f.Name == "admin-user" {
|
||||
flags.AdminEmail = f.Value.String()
|
||||
}
|
||||
if f.Name == "user" {
|
||||
flags.UserEmail = f.Value.String()
|
||||
}
|
||||
})
|
||||
if flags.UserEmail == "" {
|
||||
return fmt.Errorf("user email is required")
|
||||
}
|
||||
return ctrl.DeleteUser(context.Background(), *flags)
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
var _listUsers = &cobra.Command{
|
||||
Use: "list-users",
|
||||
Short: "List all users",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
recoverWithLog()
|
||||
var flags = &model.AdminActionForUser{}
|
||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
||||
if f.Name == "admin-user" {
|
||||
flags.AdminEmail = f.Value.String()
|
||||
}
|
||||
})
|
||||
return ctrl.ListUsers(context.Background(), *flags)
|
||||
},
|
||||
}
|
||||
|
||||
var _updateFreeUserStorage = &cobra.Command{
|
||||
Use: "update-subscription",
|
||||
Short: "Update subscription for the free user",
|
||||
Short: "Update subscription for user",
|
||||
Long: "Update subscription for the free user. If you want to apply specific limits, use the `--no-limit False` flag",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
recoverWithLog()
|
||||
var flags = &model.AdminActionForUser{}
|
||||
|
@ -70,6 +114,9 @@ var _updateFreeUserStorage = &cobra.Command{
|
|||
noLimit = strings.ToLower(f.Value.String()) == "true"
|
||||
}
|
||||
})
|
||||
if flags.UserEmail == "" {
|
||||
return fmt.Errorf("user email is required")
|
||||
}
|
||||
return ctrl.UpdateFreeStorage(context.Background(), *flags, noLimit)
|
||||
},
|
||||
}
|
||||
|
@ -78,13 +125,16 @@ func init() {
|
|||
rootCmd.AddCommand(_adminCmd)
|
||||
_ = _userDetailsCmd.MarkFlagRequired("admin-user")
|
||||
_ = _userDetailsCmd.MarkFlagRequired("user")
|
||||
_userDetailsCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)")
|
||||
_userDetailsCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. ")
|
||||
_userDetailsCmd.Flags().StringP("user", "u", "", "The email of the user to fetch details for. (required)")
|
||||
_disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)")
|
||||
_listUsers.Flags().StringP("admin-user", "a", "", "The email of the admin user. ")
|
||||
_disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. ")
|
||||
_disable2faCmd.Flags().StringP("user", "u", "", "The email of the user to disable 2FA for. (required)")
|
||||
_updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)")
|
||||
_deleteUser.Flags().StringP("admin-user", "a", "", "The email of the admin user. ")
|
||||
_deleteUser.Flags().StringP("user", "u", "", "The email of the user to delete. (required)")
|
||||
_updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user.")
|
||||
_updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)")
|
||||
// add a flag with no value --no-limit
|
||||
_updateFreeUserStorage.Flags().String("no-limit", "True", "When true, sets 100TB as storage limit, and expiry to current date + 100 years")
|
||||
_adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage)
|
||||
_adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage, _listUsers, _deleteUser)
|
||||
}
|
||||
|
|
2
cli/docs/generated/ente.md
generated
|
@ -25,4 +25,4 @@ ente [flags]
|
|||
* [ente export](ente_export.md) - Starts the export process
|
||||
* [ente version](ente_version.md) - Prints the current version
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_account.md
generated
|
@ -16,4 +16,4 @@ Manage account settings
|
|||
* [ente account list](ente_account_list.md) - list configured accounts
|
||||
* [ente account update](ente_account_update.md) - Update an existing account's export directory
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_account_add.md
generated
|
@ -16,4 +16,4 @@ ente account add [flags]
|
|||
|
||||
* [ente account](ente_account.md) - Manage account settings
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_account_get-token.md
generated
|
@ -18,4 +18,4 @@ ente account get-token [flags]
|
|||
|
||||
* [ente account](ente_account.md) - Manage account settings
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_account_list.md
generated
|
@ -16,4 +16,4 @@ ente account list [flags]
|
|||
|
||||
* [ente account](ente_account.md) - Manage account settings
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_account_update.md
generated
|
@ -19,4 +19,4 @@ ente account update [flags]
|
|||
|
||||
* [ente account](ente_account.md) - Manage account settings
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
6
cli/docs/generated/ente_admin.md
generated
|
@ -15,8 +15,10 @@ Commands for admin actions like disable or enabling 2fa, bumping up the storage
|
|||
### SEE ALSO
|
||||
|
||||
* [ente](ente.md) - CLI tool for exporting your photos from ente.io
|
||||
* [ente admin delete-user](ente_admin_delete-user.md) - Delete a user
|
||||
* [ente admin disable-2fa](ente_admin_disable-2fa.md) - Disable 2fa for a user
|
||||
* [ente admin get-user-id](ente_admin_get-user-id.md) - Get user id
|
||||
* [ente admin update-subscription](ente_admin_update-subscription.md) - Update subscription for the free user
|
||||
* [ente admin list-users](ente_admin_list-users.md) - List all users
|
||||
* [ente admin update-subscription](ente_admin_update-subscription.md) - Update subscription for user
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
21
cli/docs/generated/ente_admin_delete-user.md
generated
Normal file
|
@ -0,0 +1,21 @@
|
|||
## ente admin delete-user
|
||||
|
||||
Delete a user
|
||||
|
||||
```
|
||||
ente admin delete-user [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-a, --admin-user string The email of the admin user.
|
||||
-h, --help help for delete-user
|
||||
-u, --user string The email of the user to delete. (required)
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [ente admin](ente_admin.md) - Commands for admin actions
|
||||
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
4
cli/docs/generated/ente_admin_disable-2fa.md
generated
|
@ -9,7 +9,7 @@ ente admin disable-2fa [flags]
|
|||
### Options
|
||||
|
||||
```
|
||||
-a, --admin-user string The email of the admin user. (required)
|
||||
-a, --admin-user string The email of the admin user.
|
||||
-h, --help help for disable-2fa
|
||||
-u, --user string The email of the user to disable 2FA for. (required)
|
||||
```
|
||||
|
@ -18,4 +18,4 @@ ente admin disable-2fa [flags]
|
|||
|
||||
* [ente admin](ente_admin.md) - Commands for admin actions
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
4
cli/docs/generated/ente_admin_get-user-id.md
generated
|
@ -9,7 +9,7 @@ ente admin get-user-id [flags]
|
|||
### Options
|
||||
|
||||
```
|
||||
-a, --admin-user string The email of the admin user. (required)
|
||||
-a, --admin-user string The email of the admin user.
|
||||
-h, --help help for get-user-id
|
||||
-u, --user string The email of the user to fetch details for. (required)
|
||||
```
|
||||
|
@ -18,4 +18,4 @@ ente admin get-user-id [flags]
|
|||
|
||||
* [ente admin](ente_admin.md) - Commands for admin actions
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
20
cli/docs/generated/ente_admin_list-users.md
generated
Normal file
|
@ -0,0 +1,20 @@
|
|||
## ente admin list-users
|
||||
|
||||
List all users
|
||||
|
||||
```
|
||||
ente admin list-users [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-a, --admin-user string The email of the admin user.
|
||||
-h, --help help for list-users
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [ente admin](ente_admin.md) - Commands for admin actions
|
||||
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
10
cli/docs/generated/ente_admin_update-subscription.md
generated
|
@ -1,6 +1,10 @@
|
|||
## ente admin update-subscription
|
||||
|
||||
Update subscription for the free user
|
||||
Update subscription for user
|
||||
|
||||
### Synopsis
|
||||
|
||||
Update subscription for the free user. If you want to apply specific limits, use the `--no-limit False` flag
|
||||
|
||||
```
|
||||
ente admin update-subscription [flags]
|
||||
|
@ -9,7 +13,7 @@ ente admin update-subscription [flags]
|
|||
### Options
|
||||
|
||||
```
|
||||
-a, --admin-user string The email of the admin user. (required)
|
||||
-a, --admin-user string The email of the admin user.
|
||||
-h, --help help for update-subscription
|
||||
--no-limit string When true, sets 100TB as storage limit, and expiry to current date + 100 years (default "True")
|
||||
-u, --user string The email of the user to update subscription for. (required)
|
||||
|
@ -19,4 +23,4 @@ ente admin update-subscription [flags]
|
|||
|
||||
* [ente admin](ente_admin.md) - Commands for admin actions
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_auth.md
generated
|
@ -13,4 +13,4 @@ Authenticator commands
|
|||
* [ente](ente.md) - CLI tool for exporting your photos from ente.io
|
||||
* [ente auth decrypt](ente_auth_decrypt.md) - Decrypt authenticator export
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_auth_decrypt.md
generated
|
@ -16,4 +16,4 @@ ente auth decrypt [input] [output] [flags]
|
|||
|
||||
* [ente auth](ente_auth.md) - Authenticator commands
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_export.md
generated
|
@ -16,4 +16,4 @@ ente export [flags]
|
|||
|
||||
* [ente](ente.md) - CLI tool for exporting your photos from ente.io
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
2
cli/docs/generated/ente_version.md
generated
|
@ -16,4 +16,4 @@ ente version [flags]
|
|||
|
||||
* [ente](ente.md) - CLI tool for exporting your photos from ente.io
|
||||
|
||||
###### Auto generated by spf13/cobra on 13-Mar-2024
|
||||
###### Auto generated by spf13/cobra on 14-Mar-2024
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
Tag main, and push the tag.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> See [auth/docs/release](../../auth/docs/release.md) for more details about the
|
||||
> tag format. The prefix for cli releases should be `cli-`.
|
||||
|
||||
```sh
|
||||
git tag cli-v1.2.3
|
||||
git push origin cli-v1.2.3
|
||||
|
|
|
@ -25,6 +25,69 @@ func (c *Client) GetUserIdFromEmail(ctx context.Context, email string) (*models.
|
|||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListUsers(ctx context.Context) ([]models.User, error) {
|
||||
var res struct {
|
||||
Users []models.User `json:"users"`
|
||||
}
|
||||
r, err := c.restClient.R().
|
||||
SetContext(ctx).
|
||||
SetQueryParam("sinceTime", "0").
|
||||
SetResult(&res).
|
||||
Get("/admin/users/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.IsError() {
|
||||
return nil, &ApiError{
|
||||
StatusCode: r.StatusCode(),
|
||||
Message: r.String(),
|
||||
}
|
||||
}
|
||||
return res.Users, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteUser(ctx context.Context, email string) error {
|
||||
|
||||
r, err := c.restClient.R().
|
||||
SetContext(ctx).
|
||||
SetQueryParam("email", email).
|
||||
Delete("/admin/user/delete")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r.IsError() {
|
||||
return &ApiError{
|
||||
StatusCode: r.StatusCode(),
|
||||
Message: r.String(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Disable2Fa(ctx context.Context, userID int64) error {
|
||||
var res interface{}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"userID": userID,
|
||||
}
|
||||
r, err := c.restClient.R().
|
||||
SetContext(ctx).
|
||||
SetResult(&res).
|
||||
SetBody(payload).
|
||||
Post("/admin/user/disable-2fa")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r.IsError() {
|
||||
return &ApiError{
|
||||
StatusCode: r.StatusCode(),
|
||||
Message: r.String(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) UpdateFreePlanSub(ctx context.Context, userDetails *models.UserDetails, storageInBytes int64, expiryTimeInMicro int64) error {
|
||||
var res interface{}
|
||||
if userDetails.Subscription.ProductID != "free" {
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package models
|
||||
|
||||
type UserDetails struct {
|
||||
User struct {
|
||||
ID int64 `json:"id"`
|
||||
} `json:"user"`
|
||||
User User `json:"user"`
|
||||
Usage int64 `json:"usage"`
|
||||
Email string `json:"email"`
|
||||
|
||||
|
@ -14,3 +12,10 @@ type UserDetails struct {
|
|||
PaymentProvider string `json:"paymentProvider"`
|
||||
} `json:"subscription"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID int64
|
||||
Email string `json:"email"`
|
||||
Hash string `json:"hash"`
|
||||
CreationTime int64 `json:"creationTime"`
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"github.com/ente-io/cli/internal"
|
||||
"github.com/ente-io/cli/internal/api"
|
||||
"github.com/ente-io/cli/pkg/model"
|
||||
"github.com/ente-io/cli/utils"
|
||||
"log"
|
||||
|
@ -24,6 +25,63 @@ func (c *ClICtrl) GetUserId(ctx context.Context, params model.AdminActionForUser
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *ClICtrl) ListUsers(ctx context.Context, params model.AdminActionForUser) error {
|
||||
accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
users, err := c.Client.ListUsers(accountCtx)
|
||||
if err != nil {
|
||||
if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") {
|
||||
fmt.Printf("Error: old admin token, please re-authenticate using `ente account add` \n")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
for _, user := range users {
|
||||
fmt.Printf("Email: %s, ID: %d, Created: %s\n", user.Email, user.ID, time.UnixMicro(user.CreationTime).Format("2006-01-02"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ClICtrl) DeleteUser(ctx context.Context, params model.AdminActionForUser) error {
|
||||
accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.Client.DeleteUser(accountCtx, params.UserEmail)
|
||||
if err != nil {
|
||||
if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") {
|
||||
fmt.Printf("Error: old admin token, please re-authenticate using `ente account add` \n")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
fmt.Println("Successfully deleted user")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ClICtrl) Disable2FA(ctx context.Context, params model.AdminActionForUser) error {
|
||||
accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userDetails, err := c.Client.GetUserIdFromEmail(accountCtx, params.UserEmail)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.Client.Disable2Fa(accountCtx, userDetails.User.ID)
|
||||
if err != nil {
|
||||
if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") {
|
||||
fmt.Printf("Error: Old admin token, please re-authenticate using `ente account add` \n")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
fmt.Println("Successfully disabled 2FA for user")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActionForUser, noLimit bool) error {
|
||||
accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail)
|
||||
if err != nil {
|
||||
|
@ -82,6 +140,9 @@ func (c *ClICtrl) buildAdminContext(ctx context.Context, adminEmail string) (con
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(accounts) == 0 {
|
||||
return nil, fmt.Errorf("no accounts found, use `account add` to add an account")
|
||||
}
|
||||
var acc *model.Account
|
||||
for _, a := range accounts {
|
||||
if a.Email == adminEmail {
|
||||
|
@ -89,6 +150,14 @@ func (c *ClICtrl) buildAdminContext(ctx context.Context, adminEmail string) (con
|
|||
break
|
||||
}
|
||||
}
|
||||
if (len(accounts) > 1) && (acc == nil) {
|
||||
return nil, fmt.Errorf("multiple accounts found, specify the admin email using --admin-user")
|
||||
}
|
||||
if acc == nil && len(accounts) == 1 {
|
||||
acc = &accounts[0]
|
||||
fmt.Printf("Assuming %s as the Admin \n------------\n", acc.Email)
|
||||
}
|
||||
|
||||
if acc == nil {
|
||||
return nil, fmt.Errorf("account not found for %s, use `account list` to list accounts", adminEmail)
|
||||
}
|
||||
|
|
|
@ -69,9 +69,17 @@ export const sidebar = [
|
|||
{ text: "FAQ", link: "/auth/faq/" },
|
||||
{
|
||||
text: "Migration guides",
|
||||
collapsed: true,
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: "Introduction", link: "/auth/migration-guides/" },
|
||||
{
|
||||
text: "From Authy",
|
||||
link: "/auth/migration-guides/authy/",
|
||||
},
|
||||
{
|
||||
text: "Exporting your data",
|
||||
link: "/auth/migration-guides/export",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -86,9 +94,14 @@ export const sidebar = [
|
|||
items: [
|
||||
{ text: "Introduction", link: "/self-hosting/guides/" },
|
||||
{
|
||||
text: "Configure custom server",
|
||||
text: "Connect to custom server",
|
||||
link: "/self-hosting/guides/custom-server/",
|
||||
},
|
||||
{
|
||||
text: "Administering your server",
|
||||
link: "/self-hosting/guides/admin",
|
||||
},
|
||||
|
||||
{
|
||||
text: "Mobile build",
|
||||
link: "/self-hosting/guides/mobile-build",
|
||||
|
@ -110,6 +123,10 @@ export const sidebar = [
|
|||
text: "Verification code",
|
||||
link: "/self-hosting/faq/otp",
|
||||
},
|
||||
{
|
||||
text: "Increase storage space",
|
||||
link: "/self-hosting/faq/storage-space",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,21 +1,33 @@
|
|||
|
||||
---
|
||||
title: FAQ - Auth
|
||||
description: Frequently asked questions about Ente Auth
|
||||
---
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
### How secure is ente Auth?
|
||||
All codes you backup via Ente is stored end-to-end encrypted. This means only you can access your codes. Our apps are open source and our cryptography has been externally audited.
|
||||
### How secure is Ente Auth?
|
||||
|
||||
All codes you backup via Ente is stored end-to-end encrypted. This means only
|
||||
you can access your codes. Our apps are open source and our cryptography has
|
||||
been externally audited.
|
||||
|
||||
### Can I access my codes on desktop?
|
||||
You can access your codes on the web @ [auth.ente.io](https://auth.ente.io).
|
||||
|
||||
You can access your codes on the web at [auth.ente.io](https://auth.ente.io).
|
||||
|
||||
### How can I delete or edit codes?
|
||||
|
||||
You can delete or edit a code by swiping left on that item.
|
||||
|
||||
### How can I support this project?
|
||||
You can support the development of this project by subscribing to our Photos app @ [ente.io](https://ente.io).
|
||||
|
||||
You can support the development of this project by subscribing to our Photos app
|
||||
at [ente.io](https://ente.io).
|
||||
|
||||
### How can I enable FaceID lock in Ente Auth?
|
||||
|
||||
You can enable FaceID lock under Settings → Security → Lockscreen.
|
||||
|
||||
### Why does the desktop and mobile app displays different code?
|
||||
|
||||
Please verify that the time on both your mobile and desktop is same.
|
||||
|
|
|
@ -7,8 +7,3 @@ description: User guide for Ente Auth
|
|||
|
||||
Ente Auth is a free, cross-platform, end-to-end encrypted authenticator app. You
|
||||
can use it to safely store your 2FA codes (second-factor authentication codes).
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> These docs are still incomplete. If you feel like documenting an issue you ran
|
||||
> into and then found a solution to, help us [fill them in](/about/contribute).
|
||||
|
|
179
docs/docs/auth/migration-guides/authy/index.md
Normal file
|
@ -0,0 +1,179 @@
|
|||
---
|
||||
title: Migrating from Authy
|
||||
description: Guide for importing your existing Authy 2FA tokens into Ente Auth
|
||||
---
|
||||
|
||||
# Migrating from Authy
|
||||
|
||||
A guide written by Green, an ente.io lover
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Authy will soon be dropping support for its desktop apps in the near future.
|
||||
> If you are looking to switch to ente Authenticator from Authy, I heavily
|
||||
> recommend you export your codes as soon as you can.
|
||||
|
||||
---
|
||||
|
||||
Migrating from Authy can be tiring, as you cannot export your 2FA codes through
|
||||
the app, meaning that you would have to reconfigure 2FA for all of your accounts
|
||||
for your new 2FA authenticator. However, easier ways exist to export your codes
|
||||
out of Authy. This guide will cover two of the most used methods for mograting
|
||||
from Authy to ente Authenticator.
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Under any circumstances, do **NOT** share any JSON and TXT files generated
|
||||
> using this guide, as they contain your **unencrypted** TOTP secrets!
|
||||
>
|
||||
> Also, there is **NO GUARANTEE** that these methods will export ALL of your
|
||||
> codes. Make sure that all your accounts have been imported successfully before
|
||||
> deleting any codes from your Authy account!
|
||||
|
||||
---
|
||||
|
||||
## Method 1: Use Neeraj's export tool
|
||||
|
||||
**Who should use this?** General users who want to save time by skipping the
|
||||
hard (and rather technical) parts of the process.<br><br>
|
||||
|
||||
One way to export is to
|
||||
[use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4)
|
||||
to simplify the process and skip directly to importing to ente Authenticator.
|
||||
|
||||
To export from Authy, download the tool for your specific OS, then type the
|
||||
following in your terminal:
|
||||
|
||||
```
|
||||
./<binary-name> <path_to_export_file>
|
||||
```
|
||||
|
||||
Assuming the filename of the binary remains unmodified and the working directory
|
||||
of the terminal is the location of the binary, you should type this for MacOS:
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> On Apple Silicon devices, Rosetta 2 may be required to run the binary.
|
||||
|
||||
```
|
||||
./authy-export-darwin-amd64 authy_codes.txt
|
||||
```
|
||||
|
||||
For Linux:
|
||||
|
||||
```
|
||||
./authy-export-linux-amd64 authy_codes.txt
|
||||
```
|
||||
|
||||
For Windows:
|
||||
|
||||
```
|
||||
./authy-export-windows-amd64.exe authy_codes.txt
|
||||
```
|
||||
|
||||
This will generate a text file called `authy_codes.txt`, which contains your
|
||||
Authy codes in ente's plaintext export format. You can now import this to ente
|
||||
Authenticator!
|
||||
|
||||
## Method 2: Use gboudreau's GitHub guide
|
||||
|
||||
**Who should use this?** Power users who have spare time on their hands and
|
||||
prefer a more "known and established" solution to exporting Authy codes.<br><br>
|
||||
|
||||
A user on GitHub (gboudreau) wrote a guide to export codes from Authy (morpheus
|
||||
on Discord found this and showed it to us), so we are going to be using that for
|
||||
the migration.
|
||||
|
||||
To export your data, please follow
|
||||
[this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93).
|
||||
|
||||
This will create a JSON file called `authy-to-bitwarden-export.json`, which
|
||||
contains your Authy codes in Bitwarden's export format. You can now import this
|
||||
to ente Authenticator!
|
||||
|
||||
### Method 2.1: If the export worked, but the import didn't
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> This is intended only for users who successfully exported their codes using the
|
||||
> guide in method 2, but could not import it to ente Authenticator for whatever
|
||||
> reason. If the import was successful, or you haven't tried to import the codes
|
||||
> yet, ignore this section.
|
||||
>
|
||||
> If the export itself failed, try using
|
||||
> [**method 1**](#method-1-use-neerajs-export-tool) instead.
|
||||
|
||||
Usually, you should be able to import Bitwarden exports directly into ente
|
||||
Authenticator. In case this didn't work for whatever reason, I've written a
|
||||
program in Python that converts the JSON file into a TXT file that ente
|
||||
Authenticator can use, so you can try importing using plain text import instead.
|
||||
|
||||
You can download my program
|
||||
[here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py),
|
||||
or you can copy the program below:
|
||||
|
||||
```py
|
||||
import json
|
||||
import os
|
||||
|
||||
totp = []
|
||||
|
||||
accounts = json.load(open('authy-to-bitwarden-export.json','r',encoding='utf-8'))
|
||||
|
||||
for account in accounts['items']:
|
||||
totp.append(account['login']['totp']+'\n')
|
||||
|
||||
writer = open('auth_codes.txt','w+',encoding='utf-8')
|
||||
writer.writelines(totp)
|
||||
writer.close()
|
||||
|
||||
print('Saved to ' + os.getcwd() + '/auth_codes.txt')
|
||||
```
|
||||
|
||||
To convert the file with this program, you will need to install
|
||||
[Python](https://www.python.org/downloads/) on your computer.
|
||||
|
||||
Before you run the program, make sure that both the Python program and the JSON
|
||||
file are in the same directory, otherwise this will not work!
|
||||
|
||||
To run the Python program, open it in your IDE and run the program, or open your
|
||||
terminal and type `python3 authy_to_ente.py` (MacOS/Linux, or any other OS that
|
||||
uses bash) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT
|
||||
file called `auth_codes.txt` will be generated. You can now import your data to
|
||||
ente Authenticator!
|
||||
|
||||
---
|
||||
|
||||
You should now have a TXT file (method 1, method 2.1) or a JSON file (method 2)
|
||||
that countains your TOTP secrets, which can now be imported into ente
|
||||
Authenticator. To import your codes, please follow one of the steps below,
|
||||
depending on which method you used to export your codes.
|
||||
|
||||
## Importing to ente Authenticator (Method 1, method 2.1)
|
||||
|
||||
1. Copy the TXT file to one of your devices with ente Authenticator.
|
||||
2. Log in to your account (if you haven't already), or press "Use without
|
||||
backups".
|
||||
3. Open the navigation menu (hamburger button on the top left), then press
|
||||
"Data", then press "Import codes".
|
||||
4. Select the "Plain text" option.
|
||||
5. Select the TXT file that was made earlier.
|
||||
|
||||
## Importing to ente Authenticator (Method 2)
|
||||
|
||||
1. Copy the JSON file to one of your devices with ente Authenticator.
|
||||
2. Log in to your account (if you haven't already), or press "Use without
|
||||
backups".
|
||||
3. Open the navigation menu (hamburger button on the top left), then press
|
||||
"Data", then press "Import codes".
|
||||
4. Select the "Bitwarden" option.
|
||||
5. Select the JSON file that was made earlier.
|
||||
|
||||
If this didn't work, refer to
|
||||
[**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt).<br><br>
|
||||
|
||||
And that's it! You have now successfully migrated from Authy to ente
|
||||
Authenticator.
|
||||
|
||||
Now that your secrets are safely stored, I recommend you delete the unencrypted
|
||||
JSON and TXT files that were made during the migration process for security.
|
76
docs/docs/auth/migration-guides/export.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
title: Exporting your data from Ente Auth
|
||||
description: Guide for exporting your 2FA codes out from Ente Auth
|
||||
---
|
||||
|
||||
# Exporting your data out of Ente Auth
|
||||
|
||||
## Auth Encrypted Export format
|
||||
|
||||
### Overview
|
||||
|
||||
When we export the auth codes, the data is encrypted using a key derived from
|
||||
the user's password. This document describes the JSON structure used to organize
|
||||
exported data, including versioning and key derivation parameters.
|
||||
|
||||
### Export JSON Sample
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"kdfParams": {
|
||||
"memLimit": 4096,
|
||||
"opsLimit": 3,
|
||||
"salt": "example_salt"
|
||||
},
|
||||
"encryptedData": "encrypted_data_here",
|
||||
"encryptionNonce": "nonce_here"
|
||||
}
|
||||
```
|
||||
|
||||
The main object used to represent the export data. It contains the following
|
||||
key-value pairs:
|
||||
|
||||
- `version`: The version of the export format.
|
||||
- `kdfParams`: Key derivation function parameters.
|
||||
- `encryptedData"`: The encrypted authentication data.
|
||||
- `encryptionNonce`: The nonce used for encryption.
|
||||
|
||||
#### Version
|
||||
|
||||
Export version is used to identify the format of the export data.
|
||||
|
||||
##### Ver: 1
|
||||
|
||||
- KDF Algorithm: `ARGON2ID`
|
||||
- Decrypted data format: `otpauth://totp/...`, separated by a new line.
|
||||
- Encryption Algo: `XChaCha20-Poly1305`
|
||||
|
||||
##### Key Derivation Function Params (KDF)
|
||||
|
||||
This section contains the parameters that were using during KDF operation:
|
||||
|
||||
- `memLimit`: Memory limit for the algorithm.
|
||||
- `opsLimit`: Operations limit for the algorithm.
|
||||
- `salt`: The salt used in the derivation process.
|
||||
|
||||
##### Encrypted Data
|
||||
|
||||
As mentioned above, the auth data is encrypted using a key that's derived by
|
||||
using user provided password & kdf params. For encryption, we are using
|
||||
`XChaCha20-Poly1305` algorithm.
|
||||
|
||||
## How to use the exported data
|
||||
|
||||
- **Ente Authenticator app**: You can directly import the codes in the Ente
|
||||
Authenticator app.
|
||||
|
||||
> Settings -> Data -> Import Codes -> ente Encrypted export.
|
||||
|
||||
- **Decrypt using Ente CLI** : Download the latest version of
|
||||
[Ente CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0), and run
|
||||
the following command
|
||||
|
||||
```
|
||||
./ente auth decrypt <export_file> <output_file>
|
||||
```
|
|
@ -1,11 +1,10 @@
|
|||
---
|
||||
title: Migrating to Ente Auth
|
||||
description:
|
||||
Guides for migrating your existing 2FA tokens from other products into Ente
|
||||
Auth
|
||||
Guides for migrating your existing 2FA tokens into or out of Ente Auth
|
||||
---
|
||||
|
||||
# Migrating to Ente Auth
|
||||
# Migrating to/from Ente Auth
|
||||
|
||||
_Coming soon_. This section will contain guides for migrating your existing 2FA
|
||||
tokens from other products into Ente Auth.
|
||||
- [Migrating from Authy](authy/)
|
||||
- [Exporting your data out of Ente Auth](export)
|
||||
|
|
|
@ -3,9 +3,7 @@ title: FAQ
|
|||
description: Frequently asked questions about Ente Photos
|
||||
---
|
||||
|
||||
|
||||
# FAQ
|
||||
|
||||
|
||||
_Coming soon_. On this page we'll document some help items in a question and answer format.
|
||||
|
||||
_Coming soon_. On this page we'll document some help items in a question and
|
||||
answer format.
|
||||
|
|
|
@ -17,3 +17,11 @@ locally by creating a `museum.yaml` and adding the `internal.hardcoded-ott`
|
|||
configuration setting to it. See
|
||||
[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml)
|
||||
in the server source code for details about how to define this.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you're not able to get the OTP with the above methods, make sure that you
|
||||
> are actually connecting to your self hosted instance and not to Ente's
|
||||
> production servers. e.g. you can use the network requests tab in the browser
|
||||
> console to verify that the API requests are going to your server instead of
|
||||
> `api.ente.io`.
|
||||
|
|
12
docs/docs/self-hosting/faq/storage-space.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
title: Increase storage space
|
||||
description: Increasing the storage quota for users on your self hosted instance
|
||||
---
|
||||
|
||||
# Increase storage space
|
||||
|
||||
See the [guide for administering your server](/self-hosting/guides/admin). In
|
||||
particular, you can use the `ente admin update-subscription` CLI command to
|
||||
increase the
|
||||
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md)
|
||||
of accounts on your instance.
|
43
docs/docs/self-hosting/guides/admin.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
title: Server admin
|
||||
description: Administering your custom self-hosted Ente instance using the CLI
|
||||
---
|
||||
|
||||
# Administering your custom server
|
||||
|
||||
You can use
|
||||
[Ente's CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0) to
|
||||
administer your self hosted server.
|
||||
|
||||
First we need to get your CLI to connect to your custom server. Define a
|
||||
config.yaml and put it either in the same directory as CLI or path defined in
|
||||
env variable `ENTE_CLI_CONFIG_PATH`
|
||||
|
||||
```yaml
|
||||
endpoint:
|
||||
api: "http://localhost:8080"
|
||||
```
|
||||
|
||||
Now you should be able to
|
||||
[add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md),
|
||||
and subsequently increase the
|
||||
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md)
|
||||
using the CLI.
|
||||
|
||||
For the admin actions, you can create `server/museum.yaml`, and whitelist add
|
||||
the admin userID `internal.admins`. See
|
||||
[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1)
|
||||
in the server source code for details about how to define this.
|
||||
|
||||
```yaml
|
||||
....
|
||||
internal:
|
||||
admins:
|
||||
# - 1580559962386440
|
||||
|
||||
....
|
||||
```
|
||||
|
||||
You can use
|
||||
[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md)
|
||||
command to find the user id of any account.
|
|
@ -1,9 +1,14 @@
|
|||
---
|
||||
title: Custom server
|
||||
description: Using a custom self-hosted server with frontend apps
|
||||
description: Using a custom self-hosted server with Ente client apps and CLI
|
||||
---
|
||||
|
||||
# Custom server for mobile apps
|
||||
# Connecting to a custom server
|
||||
|
||||
You can modify various Ente client apps and CLI to connect to a self hosted
|
||||
custom server endpoint.
|
||||
|
||||
## Mobile apps
|
||||
|
||||
The pre-built Ente apps from GitHub / App Store / Play Store / F-Droid can be
|
||||
easily configured to use a custom server.
|
||||
|
@ -18,32 +23,17 @@ configure the endpoint the app should be connecting to.
|
|||
> This is only supported by the Ente Auth app currently. We'll add this same
|
||||
> functionality to the Ente Photos app soon.
|
||||
|
||||
---
|
||||
## CLI
|
||||
|
||||
# CLI
|
||||
> [!NOTE]
|
||||
>
|
||||
> You can download the CLI from
|
||||
> [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0)
|
||||
|
||||
> [!WARNING]
|
||||
> The new version of CLI that supports connecting to custom server is still in beta.
|
||||
> You can download the beta version from [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0&expanded=true)
|
||||
|
||||
Define a config.yaml and put it either in the same directory as CLI or path defined in env variable `ENTE_CLI_CONFIG_PATH`
|
||||
Define a config.yaml and put it either in the same directory as CLI or path
|
||||
defined in env variable `ENTE_CLI_CONFIG_PATH`
|
||||
|
||||
```yaml
|
||||
endpoint:
|
||||
api: "http://localhost:8080"
|
||||
api: "http://localhost:8080"
|
||||
```
|
||||
|
||||
You should be able to [add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), and subsequently increase the [storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) using the CLI.
|
||||
|
||||
For the admin actions, you can create `server/museum.yaml`, and whitelist add the admin userID `internal.admins`. See [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) in the server source code for details about how to define this.
|
||||
|
||||
You can use [account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) command to find the user id of any account.
|
||||
|
||||
```yaml
|
||||
....
|
||||
internal:
|
||||
admins:
|
||||
# - 1580559962386440
|
||||
|
||||
....
|
||||
```
|
|
@ -10,9 +10,11 @@ walkthroughs, tutorials and other FAQ pages in this directory.
|
|||
|
||||
See the sidebar for existing guides. In particular:
|
||||
|
||||
* If you're just looking to get started, see [configure custom
|
||||
server](custom-server/).
|
||||
- If you're just looking to get started, see
|
||||
[configure custom server](custom-server/).
|
||||
|
||||
* For self hosting both the server and web app using external S3 buckets for
|
||||
object storage, see [using external S3](external-s3).
|
||||
- For various admin related tasks, e.g. increasing the storage quota on your
|
||||
self hosted instance, see [administering your custom server](admin).
|
||||
|
||||
- For self hosting both the server and web app using external S3 buckets for
|
||||
object storage, see [using external S3](external-s3).
|
||||
|
|
|
@ -30,8 +30,6 @@ flutter run --dart-define=endpoint=http://localhost:8080 --flavor independent --
|
|||
flutter run --dart-define=endpoint=http://localhost:8080
|
||||
```
|
||||
|
||||
|
||||
|
||||
Or for the auth app:
|
||||
|
||||
```sh
|
||||
|
@ -46,9 +44,11 @@ flutter run --dart-define=endpoint=http://localhost:8080
|
|||
```
|
||||
|
||||
## How to build non-debug builds
|
||||
For building APK, [setup your
|
||||
keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore)
|
||||
and run
|
||||
```sh
|
||||
|
||||
For building APK,
|
||||
[setup your keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore)
|
||||
and run
|
||||
|
||||
```sh
|
||||
flutter build apk --release --flavor independent -t lib/main.dart
|
||||
```
|
||||
```
|
||||
|
|
5
mobile/.gitignore
vendored
|
@ -9,6 +9,9 @@
|
|||
.history
|
||||
.svn/
|
||||
|
||||
# Editors
|
||||
.vscode/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
|
@ -25,7 +28,6 @@
|
|||
.pub/
|
||||
/build/
|
||||
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
|
@ -37,6 +39,5 @@ android/app/.settings/*
|
|||
android/.settings/
|
||||
.env
|
||||
|
||||
|
||||
fastlane/report.xml
|
||||
TensorFlowLiteC.framework
|
||||
|
|
|
@ -45,8 +45,7 @@ You can alternatively install the build from PlayStore or F-Droid.
|
|||
|
||||
## 🧑💻 Building from source
|
||||
|
||||
1. [Install Flutter v3.13.4](https://flutter.dev/docs/get-started/install) or
|
||||
set the Path of Flutter SDK to `thirdparty/flutter/bin`.
|
||||
1. [Install Flutter v3.13.4](https://flutter.dev/docs/get-started/install).
|
||||
|
||||
2. Pull in all submodules with `git submodule update --init --recursive`
|
||||
|
||||
|
|
32
mobile/docs/release.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Releases
|
||||
|
||||
Create a PR to bump up the version in `pubspec.yaml`.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Use [semver](https://semver.org/) for the tags, with `photos-` as a prefix.
|
||||
> Multiple beta releases for the same upcoming version can be done by adding
|
||||
> build metadata at the end, e.g. `photos-v1.2.3-beta+3`.
|
||||
|
||||
Once that is merged, tag main, and push the tag.
|
||||
|
||||
```sh
|
||||
git tag photos-v1.2.3
|
||||
git push origin photos-v1.2.3
|
||||
```
|
||||
|
||||
This'll trigger a GitHub workflow that:
|
||||
|
||||
* Creates a new draft GitHub release and attaches the build artifacts to it
|
||||
(mobile APKs),
|
||||
|
||||
Once the workflow completes, go to the draft GitHub release that was created.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Keep the title of the release same as the tag.
|
||||
|
||||
Set "Previous tag" to the last release of auth and press "Generate release
|
||||
notes". The generated release note will contain all PRs and new contributors
|
||||
from all the releases in the monorepo, so you'll need to filter them to keep
|
||||
only the things that relate to the Photos mobile app.
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"dart.flutterSdkPath": "thirdparty/flutter/bin"
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos.
|
||||
|
||||
Se você está procurando uma alternativa ao Google Photos com foco em privacidade, veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los.
|
||||
Se você está procurando uma alternativa ao Google Fotos com foco em privacidade, você veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los.
|
||||
|
||||
Temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
ente 是一个简单的应用程序来备份和分享您的照片和视频。
|
||||
|
||||
如果你一直在寻找一个隐私友好的Google Photos替代品,那么你就来对地方了。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。
|
||||
如果你一直在寻找一个隐私友好的Google Photos替代品,那么你就来对地方了。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。
|
||||
|
||||
我们在Android、iOS、web 和桌面上有开源应用, 和您的照片将以端到端加密方式 (e2ee) 无缝同步。
|
||||
|
||||
ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。
|
||||
ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。 ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。 权限
|
||||
|
||||
您的加密数据已复制到三个不同的地点,包括巴黎的一个安全屋。 我们认真对待子孙后代,并确保您的回忆比您长寿。
|
||||
您的加密数据已复制到三个不同的地点,包括巴黎的一个安全屋。 我们认真对待子孙后代,并确保您的回忆比您长寿。 我们认真对待子孙后代,并确保您的回忆比您长寿。
|
||||
|
||||
我们来这里是为了打造有史以来最安全的照片应用,来和我们一起前行!
|
||||
|
||||
|
@ -30,7 +30,7 @@ ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他
|
|||
ente需要特定权限以执行作为图像存储提供商的职责,相关内容可以在此链接查阅:https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md
|
||||
|
||||
价格
|
||||
我们不会提供永久免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。
|
||||
我们不会提供永久免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。
|
||||
|
||||
支持
|
||||
我们对提供真人支持感到自豪。 如果您是我们的付费客户,您可以联系 team@ente.io 并在24小时内收到来自我们团队的回复。
|
||||
我们对提供真人支持感到自豪。 我们对提供真人支持感到自豪。 如果您是我们的付费客户,您可以联系 team@ente.io 并在24小时内收到来自我们团队的回复。
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos.
|
||||
|
||||
Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los.
|
||||
Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las.
|
||||
|
||||
Temos aplicativos de código aberto em Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos.
|
||||
|
||||
Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com ente, eles são armazenados com criptografados de ponta a ponta (e2ee). Isso significa que só você pode vê-los.
|
||||
Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las.
|
||||
|
||||
Temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
|
||||
|
||||
|
|
|
@ -406,6 +406,15 @@
|
|||
},
|
||||
"photoGridSize": "Fotorastergröße",
|
||||
"manageDeviceStorage": "Gerätespeicher verwalten",
|
||||
"machineLearning": "Maschinelles Lernen",
|
||||
"magicSearch": "Magische Suche",
|
||||
"magicSearchDescription": "Bitte beachten Sie, dass dies mehr Bandbreite nutzt und zu einem höheren Akkuverbrauch führt, bis alle Elemente indiziert sind.",
|
||||
"loadingModel": "Lade Modelle herunter...",
|
||||
"waitingForWifi": "Warte auf WLAN...",
|
||||
"status": "Status",
|
||||
"indexedItems": "Indizierte Elemente",
|
||||
"pendingItems": "Ausstehende Elemente",
|
||||
"clearIndexes": "Indexe löschen",
|
||||
"selectFoldersForBackup": "Ordner für Sicherung auswählen",
|
||||
"selectedFoldersWillBeEncryptedAndBackedUp": "Ausgewählte Ordner werden verschlüsselt und gesichert",
|
||||
"unselectAll": "Alle demarkieren",
|
||||
|
@ -1178,9 +1187,19 @@
|
|||
"changeLocationOfSelectedItems": "Standort der gewählten Elemente ändern?",
|
||||
"editsToLocationWillOnlyBeSeenWithinEnte": "Änderungen des Standorts werden nur in ente sichtbar sein",
|
||||
"cleanUncategorized": "Unkategorisiert leeren",
|
||||
"joinDiscord": "Join Discord",
|
||||
"locations": "Locations",
|
||||
"descriptions": "Descriptions",
|
||||
"addAName": "Add a name",
|
||||
"findPeopleByName": "Find people quickly by searching by name"
|
||||
"findPeopleByName": "Find people quickly by searching by name",
|
||||
"cleanUncategorizedDescription": "Entferne alle Dateien von \"Unkategorisiert\" die in anderen Alben vorhanden sind",
|
||||
"waitingForVerification": "Warte auf Bestätigung...",
|
||||
"passkey": "Passkey",
|
||||
"passkeyAuthTitle": "Passkey-Verifizierung",
|
||||
"verifyPasskey": "Passkey verifizieren",
|
||||
"playOnTv": "Album auf dem Fernseher wiedergeben",
|
||||
"pair": "Koppeln",
|
||||
"deviceNotFound": "Gerät nicht gefunden",
|
||||
"castInstruction": "Besuche cast.ente.io auf dem Gerät, das du verbinden möchtest.\n\nGib den unten angegebenen Code ein, um das Album auf deinem Fernseher abzuspielen.",
|
||||
"deviceCodeHint": "Code eingeben",
|
||||
"joinDiscord": "Discord beitreten",
|
||||
"locations": "Orte",
|
||||
"descriptions": "Beschreibungen"
|
||||
}
|
|
@ -1187,18 +1187,18 @@
|
|||
"changeLocationOfSelectedItems": "Alterar o local dos itens selecionados?",
|
||||
"editsToLocationWillOnlyBeSeenWithinEnte": "Edições para local só serão vistas dentro do Ente",
|
||||
"cleanUncategorized": "Limpar Sem Categoria",
|
||||
"waitingForBrowserRequest": "Aguardando solicitação do navegador...",
|
||||
"launchPasskeyUrlAgain": "Iniciar a URL de chave de acesso novamente",
|
||||
"cleanUncategorizedDescription": "Remover todos os arquivos de Não Categorizados que estão presentes em outros álbuns",
|
||||
"waitingForVerification": "Esperando por verificação...",
|
||||
"passkey": "Chave de acesso",
|
||||
"passkeyAuthTitle": "Autenticação via Chave de acesso",
|
||||
"verifyPasskey": "Verificar chave de acesso",
|
||||
"playOnTv": "Reproduzir álbum na TV",
|
||||
"pair": "Parear",
|
||||
"deviceNotFound": "Dispositivo não encontrado",
|
||||
"castInstruction": "Visite cast.ente.io no dispositivo que você deseja parear.\n\ndigite o código abaixo para reproduzir o álbum em sua TV.",
|
||||
"deviceCodeHint": "Insira o código",
|
||||
"joinDiscord": "Junte-se ao Discord",
|
||||
"locations": "Locations",
|
||||
"descriptions": "Descriptions",
|
||||
"addAName": "Add a name",
|
||||
"findPeopleByName": "Find people quickly by searching by name"
|
||||
"findPeopleByName": "Find people quickly by searching by name",
|
||||
"locations": "Locais",
|
||||
"descriptions": "Descrições"
|
||||
}
|
|
@ -1187,18 +1187,17 @@
|
|||
"changeLocationOfSelectedItems": "确定要更改所选项目的位置吗?",
|
||||
"editsToLocationWillOnlyBeSeenWithinEnte": "对位置的编辑只能在 Ente 内看到",
|
||||
"cleanUncategorized": "清除未分类的",
|
||||
"waitingForBrowserRequest": "正在等待浏览器请求...",
|
||||
"launchPasskeyUrlAgain": "再次启动 通行密钥 URL",
|
||||
"cleanUncategorizedDescription": "从“未分类”中删除其他相册中存在的所有文件",
|
||||
"waitingForVerification": "等待验证...",
|
||||
"passkey": "通行密钥",
|
||||
"passkeyAuthTitle": "通行密钥认证",
|
||||
"verifyPasskey": "验证通行密钥",
|
||||
"playOnTv": "在电视上播放相册",
|
||||
"pair": "配对",
|
||||
"deviceNotFound": "未发现设备",
|
||||
"castInstruction": "在您要配对的设备上访问 cast.ente.io。\n输入下面的代码即可在电视上播放相册。",
|
||||
"deviceCodeHint": "输入代码",
|
||||
"joinDiscord": "加入 Discord",
|
||||
"locations": "Locations",
|
||||
"descriptions": "Descriptions",
|
||||
"addAName": "Add a name",
|
||||
"findPeopleByName": "Find people quickly by searching by name"
|
||||
}
|
|
@ -68,6 +68,7 @@ class GalleryFileWidget extends StatelessWidget {
|
|||
: _onLongPressNoSelectionLimit(context, file);
|
||||
},
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1),
|
||||
|
|
|
@ -12,7 +12,7 @@ description: ente photos application
|
|||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
|
||||
version: 0.8.68+588
|
||||
version: 0.8.71+591
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
# Eclipse
|
||||
.metadata
|
||||
|
||||
# Xcode
|
||||
#
|
||||
.DS_Store
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
|
||||
#
|
||||
#Pods/
|
||||
|
||||
# Eclipse
|
||||
|
||||
# built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
|
||||
# files for the dex VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# generated files
|
||||
bin/
|
||||
gen/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Intellij project files
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
Copyright (c) 2017 Transistor Software <info@transistorsoft.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -1,22 +0,0 @@
|
|||
Transistor Background Fetch
|
||||
===========================================================================
|
||||
|
||||
Copyright (c) 2017 Transistor Software <info@transistorsoft.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -1,28 +0,0 @@
|
|||
#
|
||||
# Be sure to run `pod lib lint TSBackgroundFetch.podspec' to ensure this is a
|
||||
# valid spec before submitting.
|
||||
#
|
||||
# Any lines starting with a # are optional, but their use is encouraged
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'TSBackgroundFetch'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'iOS Background Fetch API Manager'
|
||||
|
||||
s.description = <<-DESC
|
||||
iOS Background Fetch API Manager with ability to handle multiple listeners.
|
||||
DESC
|
||||
|
||||
s.homepage = 'http://www.transistorsoft.com'
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
s.author = { 'christocracy' => 'christocracy@gmail.com' }
|
||||
s.source = { :git => 'https://github.com/transistorsoft/transistor-background-fetch.git', :tag => s.version.to_s }
|
||||
s.social_media_url = 'https://twitter.com/christocracy'
|
||||
|
||||
s.ios.deployment_target = '8.0'
|
||||
|
||||
s.source_files = 'ios/TSBackgroundFetch/TSBackgroundFetch/*.{h,m}'
|
||||
s.vendored_frameworks = 'ios/TSBackgroundFetch/TSBackgroundFetch.framework'
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -1,29 +0,0 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
defaultConfig {
|
||||
applicationId "com.transistorsoft.backgroundfetch"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -1,27 +0,0 @@
|
|||
package com.transistorsoft.backgroundfetch;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.transistorsoft.backgroundfetch", appContext.getPackageName());
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.transistorsoft.backgroundfetch">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme" />
|
||||
</manifest>
|
|
@ -1,34 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
|
@ -1,170 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 9 KiB |
Before Width: | Height: | Size: 15 KiB |
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
</resources>
|
|
@ -1,3 +0,0 @@
|
|||
<resources>
|
||||
<string name="app_name">BackgroundFetch</string>
|
||||
</resources>
|
|
@ -1,11 +0,0 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -1,17 +0,0 @@
|
|||
package com.transistorsoft.backgroundfetch;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
||||
ext {
|
||||
compileSdkVersion = 29
|
||||
targetSdkVersion = 29
|
||||
buildToolsVersion = "29.0.6"
|
||||
appCompatVersion = "1.1.0"
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
VERSION_NAME=0.5.0
|
||||
VERSION_CODE=15
|
||||
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
|
@ -1,7 +0,0 @@
|
|||
#Thu Feb 09 18:40:48 IST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
distributionSha256Sum=10065868c78f1207afb3a92176f99a37d753a513dff453abb6b5cceda4058cda
|
|
@ -1,160 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|