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.
This commit is contained in:
Gabriel Simmer 2020-03-21 00:31:24 +00:00
parent 7450d229f4
commit 49dba732d3
No known key found for this signature in database
GPG key ID: 33BA4D83B160A0A9
6 changed files with 77 additions and 42 deletions

View file

@ -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]
}

View file

@ -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)

View file

@ -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 ""
}

36
files/fileutils.go Normal file
View file

@ -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)
}
}
}

View file

@ -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"] != "" {

View file

@ -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")