Make AppVersion a configuration option

Refactor out NewClientWithRefresh in the login function
This commit is contained in:
Chun-Hung Tseng
2023-06-29 22:10:03 +02:00
parent 257ea3c1fe
commit fef42081b3
5 changed files with 23 additions and 44 deletions

View File

@@ -86,6 +86,7 @@ V2 will bring in optimizations and enhancements, such as optimizing uploading an
- [x] Remove delete all's hardcoded string
- [x] Point to the right proton-go-api branch
- [x] Run `go get github.com/henrybear327/go-proton-api@dev` to update go mod
- [x] Pass in AppVersion as a config option
### Known limitations
@@ -102,7 +103,6 @@ V2 will bring in optimizations and enhancements, such as optimizing uploading an
- [ ] Remove e.g. proton.link related exposures in the function signature (this library should abstract them all)
- [ ] Documentation
- [ ] Go through Drive iOS source code and check the logic control flow
- [ ] Use proper AppVersion (we need to be friendly to the Proton servers)
- [ ] Figure out the bottleneck by doing some profiling
- [ ] Proper error handling by looking at the return code instead of the error string
- [ ] Duplicated folder name handling: 422: A file or folder with that name already exists (Code=2500, Status=422)

View File

@@ -3,12 +3,14 @@ package common
import "os"
type Config struct {
/* Constants */
AppVersion string
/* Login */
FirstLoginCredential *FirstLoginCredentialData
ReusableCredential *ReusableCredentialData
UseReusableLogin bool
CredentialCacheFile string // If CredentialCacheFile is empty, no credential will be logged
RefreshAccessToken bool
/* Setting */
DestructiveIntegrationTest bool // CAUTION: the integration test requires a clean proton drive
@@ -33,7 +35,8 @@ type ReusableCredentialData struct {
func NewConfigWithDefaultValues() *Config {
return &Config{
// login
AppVersion: "",
FirstLoginCredential: &FirstLoginCredentialData{
Username: "",
Password: "",
@@ -47,7 +50,6 @@ func NewConfigWithDefaultValues() *Config {
},
UseReusableLogin: false,
CredentialCacheFile: "",
RefreshAccessToken: false,
DestructiveIntegrationTest: false,
EmptyTrashAfterIntegrationTest: false,
@@ -57,6 +59,7 @@ func NewConfigWithDefaultValues() *Config {
}
func NewConfigForIntegrationTests() *Config {
appVersion := os.Getenv("PROTON_API_BRIDGE_APP_VERSION")
username := os.Getenv("PROTON_API_BRIDGE_TEST_USERNAME")
password := os.Getenv("PROTON_API_BRIDGE_TEST_PASSWORD")
twoFA := os.Getenv("PROTON_API_BRIDGE_TEST_TWOFA")
@@ -73,6 +76,8 @@ func NewConfigForIntegrationTests() *Config {
saltedKeyPass := os.Getenv("PROTON_API_BRIDGE_TEST_SALTEDKEYPASS")
return &Config{
AppVersion: appVersion,
FirstLoginCredential: &FirstLoginCredentialData{
Username: username,
Password: password,
@@ -86,7 +91,6 @@ func NewConfigForIntegrationTests() *Config {
},
UseReusableLogin: useReusableLogin,
CredentialCacheFile: ".credential",
RefreshAccessToken: false,
DestructiveIntegrationTest: true,
EmptyTrashAfterIntegrationTest: true,

View File

@@ -4,25 +4,12 @@ import (
"github.com/henrybear327/go-proton-api"
)
// TODO: use proper appname and version
func AppVersion() string {
// return "web-drive@5.0.13.8"
return "ios-drive@1.14.0"
}
func defaultAPIOptions() []proton.Option {
return []proton.Option{
proton.WithAppVersion(AppVersion()),
func getProtonManager(appVersion string) *proton.Manager {
/* Notes on API calls: if the app version is not specified, the api calls will be rejected. */
options := []proton.Option{
proton.WithAppVersion(appVersion),
}
}
func getProtonManager() *proton.Manager {
/*
Notes on API calls
If the app version is not specified, the api calls will be rejected.
*/
m := proton.New(defaultAPIOptions()...)
m := proton.New(options...)
return m
}

View File

@@ -48,28 +48,14 @@ func Login(ctx context.Context, config *Config) (*proton.Manager, *proton.Client
var addr []proton.Address
// get manager
m := getProtonManager()
m := getProtonManager(config.AppVersion)
if config.UseReusableLogin {
/*
Using NewClientWithRefresh so the credential can last longer,
as each run of the program will trigger a access token refresh
*/
var err error
if config.RefreshAccessToken {
c, auth, err = m.NewClientWithRefresh(ctx, config.ReusableCredential.UID, config.ReusableCredential.RefreshToken)
if err != nil {
return nil, nil, nil, nil, nil, err
}
c = m.NewClient(config.ReusableCredential.UID, config.ReusableCredential.AccessToken, config.ReusableCredential.RefreshToken)
config.ReusableCredential.UID = auth.UID
config.ReusableCredential.AccessToken = auth.AccessToken
config.ReusableCredential.RefreshToken = auth.RefreshToken
} else {
c = m.NewClient(config.ReusableCredential.UID, config.ReusableCredential.AccessToken, config.ReusableCredential.RefreshToken)
}
// TODO: register auth/deauth handler
err = cacheCredentialToFile(config)
err := cacheCredentialToFile(config)
if err != nil {
return nil, nil, nil, nil, nil, err
}

View File

@@ -240,6 +240,7 @@ func (protonDrive *ProtonDrive) uploadAndCollectBlockData(ctx context.Context, n
// FIXME: handle partial upload (failed midway)
// FIXME: get block size from the server config instead of hardcoding it
// FIXME: improve memory management
blockSize := UPLOAD_BLOCK_SIZE
type PendingUploadBlocks struct {
blockUploadInfo proton.BlockUploadInfo
@@ -248,11 +249,12 @@ func (protonDrive *ProtonDrive) uploadAndCollectBlockData(ctx context.Context, n
blocks := make([]PendingUploadBlocks, 0)
manifestSignatureData := make([]byte, 0)
for i := 0; i*blockSize < len(fileContent); i++ {
fileLength := len(fileContent)
for i := 0; i*blockSize < fileLength; i++ {
// encrypt data
upperBound := (i + 1) * blockSize
if upperBound > len(fileContent) {
upperBound = len(fileContent)
if upperBound > fileLength {
upperBound = fileLength
}
data := fileContent[i*blockSize : upperBound]