Skip to content

Commit

Permalink
FEAT: Added a debug handler to show the OWIDs as JSON.
Browse files Browse the repository at this point in the history
Added JSON marshal and unmarshal functions to the creator structure.
Simplified local to use the new marshal and unmarshal methods rather than a shadow structure.
  • Loading branch information
jwrosewell committed Jun 20, 2021
1 parent 424a907 commit c913b57
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 32 deletions.
5 changes: 5 additions & 0 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func (c *common) init() {
c.mutex = &sync.Mutex{}
}

// GetCreators return a map of all the known creators keyed on domain.
func (c *common) GetCreators() map[string]*Creator {
return c.creators
}

// getCreator takes a domain name and returns the associated creator. If a
// creator does not exist then nil is returned.
func (c *common) getCreator(domain string) (*Creator, error) {
Expand Down
28 changes: 28 additions & 0 deletions creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package owid

import (
"encoding/json"
"fmt"
"time"
)
Expand Down Expand Up @@ -118,6 +119,33 @@ func (c *Creator) SubjectPublicKeyInfo() (string, error) {
// Domain associated with the creator.
func (c *Creator) Domain() string { return c.domain }

// MarshalJSON marshals a node to JSON without having to expose the fields in
// the node struct. This is achieved by converting a node to a map.
func (c *Creator) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"domain": c.domain,
"privateKey": c.privateKey,
"publicKey": c.publicKey,
"name": c.name})
}

// UnmarshalJSON called by json.Unmarshall unmarshals a node from JSON and turns
// it into a new node. As the node is marshalled to JSON by converting it to a
// map, the unmarshalling from JSON needs to handle the type of each field
// correctly.
func (c *Creator) UnmarshalJSON(b []byte) error {
var d map[string]string
err := json.Unmarshal(b, &d)
if err != nil {
return err
}
c.domain = d["domain"]
c.privateKey = d["privateKey"]
c.publicKey = d["publicKey"]
c.name = d["name"]
return nil
}

func newCreator(
domain string,
privateKey string,
Expand Down
43 changes: 43 additions & 0 deletions handlerOwids.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* ****************************************************************************
* Copyright 2020 51 Degrees Mobile Experts Limited (51degrees.com)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
* ***************************************************************************/

package owid

import (
"encoding/json"
"net/http"
)

// HandlerNodesJSON is a handler that returns a list of all the alive nodes
// which is then used to serialize to JSON.
func HandlerOwidsJSON(s *Services) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
j, err := getJSON(s)
if err != nil {
returnAPIError(s, w, err, http.StatusInternalServerError)
return
}
sendResponse(s, w, "application/json", j)
}
}

func getJSON(s *Services) ([]byte, error) {
j, err := json.Marshal(s.store.GetCreators())
if err != nil {
return nil, err
}
return j, nil
}
3 changes: 3 additions & 0 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ func AddHandlers(s *Services) {
http.HandleFunc(b+"public-key", HandlerPublicKey(s))
http.HandleFunc(b+"creator", HandlerCreator(s))
http.HandleFunc(b+"verify", HandlerVerify(s))
if s.config.Debug {
http.HandleFunc(b+"owids", HandlerOwidsJSON(s))
}
}
}

Expand Down
28 changes: 2 additions & 26 deletions local.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ type Local struct {
common
}

// item is the internal JSON representation of a Creator.
type item struct {
Domain string
PrivateKey string
PublicKey string
Name string
}

// NewLocalStore creates a new instance of Local from a given file path.
func NewLocalStore(file string) (*Local, error) {
var l Local
Expand All @@ -61,18 +53,7 @@ func (l *Local) setCreator(creator *Creator) error {
l.creators[creator.domain] = creator
l.mutex.Unlock()

cs := make(map[string]*item)

for k, v := range l.creators {
cs[k] = &item{
Domain: v.domain,
PrivateKey: v.privateKey,
PublicKey: v.publicKey,
Name: v.name,
}
}

data, err := json.MarshalIndent(&cs, "", "\t")
data, err := json.MarshalIndent(&l.creators, "", "\t")
if err != nil {
return err
}
Expand Down Expand Up @@ -122,22 +103,17 @@ func (l *Local) refresh() error {
// fetch creators reads the Creators from the persistent JSON files and
// converts them from a map of storage items to a map of Creators.
func (l *Local) fetchCreators() (map[string]*Creator, error) {
cis := make(map[string]*item)
cs := make(map[string]*Creator)
data, err := readLocalStore(l.file)
if err != nil {
return nil, err
}

err = json.Unmarshal(data, &cis)
err = json.Unmarshal(data, &cs)
if err != nil && len(data) > 0 {
return nil, err
}

for k, v := range cis {
cs[k] = newCreator(v.Domain, v.PrivateKey, v.PublicKey, v.Name)
}

return cs, nil
}

Expand Down
2 changes: 1 addition & 1 deletion node.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (n *Node) Find(condition func(n *Node) bool) *Node {
}

// AddChild adds the child to the children of this Node returning the index of
// the child.
// the child. Returns the index of the added child.
func (n *Node) AddChild(child *Node) (uint32, error) {
if child == nil {
return uint32(0), fmt.Errorf("child must for a valid array")
Expand Down
28 changes: 23 additions & 5 deletions store.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package owid

import (
"errors"
"fmt"
"log"
"os"
)
Expand All @@ -42,6 +43,9 @@ type Store interface {
// GetCreator returns the creator information for the domain.
GetCreator(domain string) (*Creator, error)

// GetCreators return a map of all the known creators keyed on domain.
GetCreators() map[string]*Creator

// setCreator inserts a new creator.
setCreator(c *Creator) error
}
Expand All @@ -65,35 +69,49 @@ func NewStore(owidConfig Configuration) Store {
panic(errors.New("Either the AZURE_STORAGE_ACCOUNT or " +
"AZURE_STORAGE_ACCESS_KEY environment variable is not set"))
}
log.Printf("OWID: Using Azure Table Storage")
log.Printf("OWID:Using Azure Table Storage")
owidStore, err = NewAzure(
azureAccountName,
azureAccountKey)
if err != nil {
panic(err)
}
} else if len(gcpProject) > 0 && (os == "" || os == "gcp") {
log.Printf("OWID: Using Google Firebase")
log.Printf("OWID:Using Google Firebase")
owidStore, err = NewFirebase(gcpProject)
if err != nil {
panic(err)
}
} else if len(owidFile) > 0 && (os == "" || os == "local") {
log.Printf("OWID: Using local storage")
log.Printf("OWID:Using local storage")
owidStore, err = NewLocalStore(owidFile)
if err != nil {
panic(err)
}
} else if len(awsEnabled) > 0 && (os == "" || os == "aws") {
log.Printf("OWID: Using AWS DynamoDB")
log.Printf("OWID:Using AWS DynamoDB")
owidStore, err = NewAWS()
if err != nil {
panic(err)
}
}

if owidStore == nil {
panic(errors.New("owid store not configured"))
panic(fmt.Errorf("OWID:no store has been configured.\r\n" +
"Provide details for store by specifying one or more sets of " +
"environment variables:\r\n" +
"(1) Azure Storage account details 'AZURE_STORAGE_ACCOUNT' & 'AZURE_STORAGE_ACCESS_KEY'\r\n" +
"(2) GCP project in 'GCP_PROJECT' \r\n" +
"(3) Local storage file paths in 'OWID_FILE'\r\n" +
"(4) AWS Dynamo DB by setting 'AWS_ENABLED' to true\r\n" +
"Refer to https://github.com/SWAN-community/owid-go/blob/main/README.md " +
"for specifics on setting up each storage solution"))
} else if owidConfig.Debug {

// If in debug more log the nodes at startup.
for _, o := range owidStore.GetCreators() {
log.Println(fmt.Sprintf("OWID:\t%s", o.Domain()))
}
}

return owidStore
Expand Down

0 comments on commit c913b57

Please sign in to comment.