github.com/rpdict/ponzu@v0.10.1-0.20190226054626-477f29d6bf5e/system/addon/manager.go (about)

     1  package addon
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"html/template"
     8  	"net/url"
     9  
    10  	"github.com/rpdict/ponzu/management/editor"
    11  
    12  	"github.com/gorilla/schema"
    13  	"github.com/tidwall/gjson"
    14  )
    15  
    16  const defaultInput = `<input type="hidden" name="%s" value="%s"/>`
    17  
    18  const managerHTML = `
    19  <div class="card editor">
    20      <form method="post" action="/admin/addon" enctype="multipart/form-data">
    21  		<div class="card-content">
    22  			<div class="card-title">{{ .AddonName }}</div>
    23  		</div>
    24  		{{ .DefaultInputs }}
    25  		{{ .Editor }}
    26  	</form>
    27  </div>
    28  `
    29  
    30  type manager struct {
    31  	DefaultInputs template.HTML
    32  	Editor        template.HTML
    33  	AddonName     string
    34  }
    35  
    36  // Manage ...
    37  func Manage(data []byte, reverseDNS string) ([]byte, error) {
    38  	a, ok := Types[reverseDNS]
    39  	if !ok {
    40  		return nil, fmt.Errorf("Addon has not been added to addon.Types map")
    41  	}
    42  
    43  	// convert json => map[string]interface{} => url.Values
    44  	var kv map[string]interface{}
    45  	err := json.Unmarshal(data, &kv)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	vals := make(url.Values)
    51  	for k, v := range kv {
    52  		switch v.(type) {
    53  		case []string:
    54  			s := v.([]string)
    55  			for i := range s {
    56  				if i == 0 {
    57  					vals.Set(k, s[i])
    58  				}
    59  
    60  				vals.Add(k, s[i])
    61  			}
    62  		default:
    63  			vals.Set(k, fmt.Sprintf("%v", v))
    64  		}
    65  	}
    66  
    67  	at := a()
    68  
    69  	dec := schema.NewDecoder()
    70  	dec.IgnoreUnknownKeys(true)
    71  	dec.SetAliasTag("json")
    72  	err = dec.Decode(at, vals)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	e, ok := at.(editor.Editable)
    78  	if !ok {
    79  		return nil, fmt.Errorf("Addon is not editable - must implement editor.Editable: %T", at)
    80  	}
    81  
    82  	v, err := e.MarshalEditor()
    83  	if err != nil {
    84  		return nil, fmt.Errorf("Couldn't marshal editor for addon: %s", err.Error())
    85  	}
    86  
    87  	inputs := &bytes.Buffer{}
    88  	fields := []string{
    89  		"addon_name",
    90  		"addon_author",
    91  		"addon_author_url",
    92  		"addon_version",
    93  		"addon_reverse_dns",
    94  		"addon_status",
    95  	}
    96  
    97  	for _, f := range fields {
    98  		input := fmt.Sprintf(defaultInput, f, gjson.GetBytes(data, f).String())
    99  		_, err := inputs.WriteString(input)
   100  		if err != nil {
   101  			return nil, fmt.Errorf("Failed to write input for addon view: %s", f)
   102  		}
   103  	}
   104  
   105  	m := manager{
   106  		DefaultInputs: template.HTML(inputs.Bytes()),
   107  		Editor:        template.HTML(v),
   108  		AddonName:     gjson.GetBytes(data, "addon_name").String(),
   109  	}
   110  
   111  	// execute html template into buffer for func return val
   112  	buf := &bytes.Buffer{}
   113  	tmpl := template.Must(template.New("manager").Parse(managerHTML))
   114  	tmpl.Execute(buf, m)
   115  
   116  	return buf.Bytes(), nil
   117  }