From 49dba732d3e3b18ac9176d4e732776eb31ac9597 Mon Sep 17 00:00:00 2001 From: Gabriel Simmer Date: Sat, 21 Mar 2020 00:31:24 +0000 Subject: [PATCH] Implement Setup() function for providers, cleanup Implemented a much-needed Setup() function for providers to implement, which (as demonstrated in the backblaze provider) allows for authentication in advance of needing to make calls to remote locations. This could also be used to create a directory or perform some other sanity check required for the provider to work. So far, haven't noticed any performance impacts from this approach, besides not needing to auth each time we make a request. --- files/backblaze.go | 37 +++++++++++++++++++++++++++++-------- files/disk.go | 4 ++++ files/fileprovider.go | 30 +++++------------------------- files/fileutils.go | 36 ++++++++++++++++++++++++++++++++++++ router/filerouter.go | 3 +-- webserver.go | 9 ++------- 6 files changed, 77 insertions(+), 42 deletions(-) create mode 100644 files/fileutils.go diff --git a/files/backblaze.go b/files/backblaze.go index 52b97d5..636ab51 100644 --- a/files/backblaze.go +++ b/files/backblaze.go @@ -45,37 +45,42 @@ type BackblazeBucketInfoPayload struct { } // Call Backblaze API endpoint to authorize and gather facts. -func (bp *BackblazeProvider) Authorize(appKeyId string, appKey string) error { +func (bp *BackblazeProvider) Setup(args map[string]string) bool { + applicationKeyId := args["applicationKeyId"] + applicationKey := args["applicationKey"] + client := &http.Client{} req, err := http.NewRequest("GET", "https://api.backblazeb2.com/b2api/v2/b2_authorize_account", nil) if err != nil { - return err + return false } - req.SetBasicAuth(appKeyId, appKey) + req.SetBasicAuth(applicationKeyId, applicationKey) resp, err := client.Do(req) if err != nil { - return err + return false } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) + if err != nil { - return err + return false } var data BackblazeAuthPayload err = json.Unmarshal(body, &data) if err != nil { - return err + return false } + bp.Authentication = data.AuthToken bp.Location = data.ApiUrl bp.Name = data.AccountId bp.DownloadLocation = data.DownloadUrl - - return nil + + return true } func (bp *BackblazeProvider) GetDirectory(path string) Directory { @@ -131,10 +136,22 @@ func (bp *BackblazeProvider) ViewFile(path string, w io.Writer) { req, err := http.NewRequest("POST", bp.Location + "/b2api/v2/b2_list_buckets", bytes.NewBuffer([]byte(bucketIdPayload))) + if err != nil { + fmt.Println(err.Error()) + return + } req.Header.Add("Authorization", bp.Authentication) res, err := client.Do(req) + if err != nil { + fmt.Println(err.Error()) + return + } bucketData, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err.Error()) + return + } var data BackblazeBucketInfoPayload json.Unmarshal(bucketData, &data) @@ -169,4 +186,8 @@ func (bp *BackblazeProvider) SaveFile(contents []byte, path string) bool { func (bp *BackblazeProvider) DetermineType(path string) string { return "file" +} + +func (bp *BackblazeProvider) GetProviderConfig() FileProvider { + return ProviderConfig[bp.Name] } \ No newline at end of file diff --git a/files/disk.go b/files/disk.go index a1902f4..ce2762d 100644 --- a/files/disk.go +++ b/files/disk.go @@ -11,6 +11,10 @@ type DiskProvider struct{ FileProvider } +func (dp *DiskProvider) Setup(args map[string]string) bool { + return true +} + func (dp *DiskProvider) GetDirectory(path string) Directory { rp := strings.Join([]string{dp.Location,path}, "/") fileDir, err := ioutil.ReadDir(rp) diff --git a/files/fileprovider.go b/files/fileprovider.go index 43abf67..16a0ff5 100644 --- a/files/fileprovider.go +++ b/files/fileprovider.go @@ -1,7 +1,6 @@ package files import ( - "fmt" "io" ) @@ -24,44 +23,24 @@ type FileInfo struct { Extension string } -var Providers map[string]FileProvider - type FileContents struct { Content []byte IsUrl bool } type FileProviderInterface interface { + Setup(args map[string]string) bool GetDirectory(path string) Directory ViewFile(path string, w io.Writer) SaveFile(contents []byte, path string) bool DetermineType(path string) string } -func TranslateProvider(codename string, i *FileProviderInterface) { - provider := Providers[codename] - if codename == "disk" { - *i = &DiskProvider{provider,} - return - } - /* - * @TODO: It would be ideal if the authorization with Backblaze was done before - * actually needing to use it, ideally during the startup step. - */ - if codename == "backblaze" { - bbProv := &BackblazeProvider{provider, provider.Config["bucket"], ""} - - err := bbProv.Authorize(provider.Config["appKeyId"], provider.Config["appId"]) - if err != nil { - fmt.Println(err.Error()) - } - *i = bbProv - return - } - *i = FileProvider{} +/** DO NOT USE THESE DEFAULTS **/ +func (f FileProvider) Setup(args map[string]string) bool { + return false } -/** DO NOT USE THESE DEFAULTS **/ func (f FileProvider) GetDirectory(path string) Directory { return Directory{} } @@ -77,3 +56,4 @@ func (f FileProvider) SaveFile(contents []byte, path string) bool { func (f FileProvider) DetermineType(path string) string { return "" } + diff --git a/files/fileutils.go b/files/fileutils.go new file mode 100644 index 0000000..ca100ef --- /dev/null +++ b/files/fileutils.go @@ -0,0 +1,36 @@ +package files + +import "fmt" + +var ProviderConfig map[string]FileProvider +var Providers map[string]*FileProviderInterface + +func TranslateProvider(codename string, i *FileProviderInterface) { + provider := ProviderConfig[codename] + if codename == "disk" { + *i = &DiskProvider{provider,} + return + } + + if codename == "backblaze" { + bbProv := &BackblazeProvider{provider, provider.Config["bucket"], ""} + *i = bbProv + return + } + *i = FileProvider{} +} + +func SetupProviders() { + Providers = make(map[string]*FileProviderInterface) + for name, provider := range ProviderConfig { + var i FileProviderInterface + TranslateProvider(name, &i) + success := i.Setup(provider.Config) + if !success { + fmt.Printf("%s failed to initialize\n", name) + } else { + Providers[name] = &i + fmt.Printf("%s initialized successfully\n", name) + } + } +} \ No newline at end of file diff --git a/router/filerouter.go b/router/filerouter.go index 0beda8d..c385332 100644 --- a/router/filerouter.go +++ b/router/filerouter.go @@ -14,8 +14,7 @@ func HandleProvider() common.Handler { vars := mux.Vars(r) if r.Method == "GET" { providerCodename := vars["provider"] - var provider files.FileProviderInterface - files.TranslateProvider(providerCodename, &provider) + provider := *files.Providers[providerCodename] fileList := provider.GetDirectory("") if vars["file"] != "" { diff --git a/webserver.go b/webserver.go index 4cc8674..94145e7 100644 --- a/webserver.go +++ b/webserver.go @@ -1,9 +1,3 @@ -/* webserver.go - * - * This is the webserver handler for Pogo, and handles - * all incoming connections, including authentication. - */ - package main import ( @@ -34,10 +28,11 @@ func main() { if err != nil { panic(err) } - err = yaml.Unmarshal(file, &files.Providers) + err = yaml.Unmarshal(file, &files.ProviderConfig) if err != nil { panic(err) } + files.SetupProviders() r := router.Init() fmt.Println("Your NAS instance is live on port :3000")