Simplify customform handling in backend (let the frontend handle it)

This commit is contained in:
nemunaire 2022-12-22 12:56:24 +01:00
parent 1712d0c81d
commit 8b4f9fe3ed
6 changed files with 43 additions and 77 deletions

View File

@ -32,8 +32,6 @@
package api package api
import ( import (
"fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"git.happydns.org/happydomain/config" "git.happydns.org/happydomain/config"
@ -42,28 +40,15 @@ import (
) )
type FormState struct { type FormState struct {
Id interface{} `json:"_id,omitempty"` Id *happydns.Identifier `json:"_id,omitempty"`
Name string `json:"_comment"` Name string `json:"_comment"`
State int32 `json:"state"` State int32 `json:"state"`
Recall *int64 `json:"recall,omitempty"` Recall string `json:"recall,omitempty"`
Redirect *string `json:"redirect,omitempty"`
} }
type FormResponse struct { func formDoState(cfg *config.Options, c *gin.Context, fs *FormState, data interface{}, defaultForm func(interface{}) *forms.CustomForm) (form *forms.CustomForm, d map[string]interface{}, err error) {
From *forms.CustomForm `json:"form,omitempty"`
Redirect *string `json:"redirect,omitempty"`
}
func formDoState(cfg *config.Options, c *gin.Context, fs *FormState, data interface{}, defaultForm func(interface{}) *forms.CustomForm) (form *forms.CustomForm, err error) {
session := c.MustGet("MySession").(*happydns.Session) session := c.MustGet("MySession").(*happydns.Session)
if fs.Recall != nil {
session.GetValue(fmt.Sprintf("form-%d", *fs.Recall), data)
session.GetValue(fmt.Sprintf("form-%d-name", *fs.Recall), &fs.Name)
session.GetValue(fmt.Sprintf("form-%d-id", *fs.Recall), &fs.Id)
session.GetValue(fmt.Sprintf("form-%d-next", *fs.Recall), &fs.Redirect)
}
csf, ok := data.(forms.CustomSettingsForm) csf, ok := data.(forms.CustomSettingsForm)
if !ok { if !ok {
if fs.State == 1 { if fs.State == 1 {
@ -73,14 +58,8 @@ func formDoState(cfg *config.Options, c *gin.Context, fs *FormState, data interf
} }
return return
} else { } else {
return csf.DisplaySettingsForm(fs.State, cfg, session, func() int64 { return csf.DisplaySettingsForm(fs.State, cfg, session, func() string {
key, recallid := session.FindNewKey("form-") return fs.Recall
session.SetValue(key, data)
session.SetValue(key+"-id", fs.Id)
if fs.Redirect != nil {
session.SetValue(key+"-next", *fs.Redirect)
}
return recallid
}) })
} }
} }

View File

@ -58,8 +58,9 @@ type ProviderSettingsState struct {
} }
type ProviderSettingsResponse struct { type ProviderSettingsResponse struct {
FormResponse Provider *happydns.Provider `json:"Provider,omitempty"`
happydns.Provider `json:"Provider,omitempty"` Values map[string]interface{} `json:"values,omitempty"`
Form *forms.CustomForm `json:"form,omitempty"`
} }
func getProviderSettingsState(cfg *config.Options, c *gin.Context) { func getProviderSettingsState(cfg *config.Options, c *gin.Context) {
@ -87,7 +88,7 @@ func getProviderSettingsState(cfg *config.Options, c *gin.Context) {
} }
form, err := formDoState(cfg, c, &uss.FormState, src, forms.GenDefaultSettingsForm) form, p, err := formDoState(cfg, c, &uss.FormState, src, forms.GenDefaultSettingsForm)
if err != nil { if err != nil {
if err != forms.DoneForm { if err != forms.DoneForm {
@ -104,14 +105,11 @@ func getProviderSettingsState(cfg *config.Options, c *gin.Context) {
return return
} }
c.JSON(http.StatusOK, ProviderSettingsResponse{ c.JSON(http.StatusOK, s)
Provider: s,
FormResponse: FormResponse{Redirect: uss.Redirect},
})
return return
} else { } else {
// Update an existing Provider // Update an existing Provider
s, err := storage.MainStore.GetProvider(user, uss.Id.(happydns.Identifier)) s, err := storage.MainStore.GetProvider(user, *uss.Id)
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return return
@ -125,15 +123,13 @@ func getProviderSettingsState(cfg *config.Options, c *gin.Context) {
return return
} }
c.JSON(http.StatusOK, ProviderSettingsResponse{ c.JSON(http.StatusOK, s)
Provider: s,
FormResponse: FormResponse{Redirect: uss.Redirect},
})
return return
} }
} }
c.JSON(http.StatusOK, ProviderSettingsResponse{ c.JSON(http.StatusOK, ProviderSettingsResponse{
FormResponse: FormResponse{From: form}, Form: form,
Values: p,
}) })
} }

View File

@ -57,7 +57,6 @@ type ServiceSettingsState struct {
} }
type ServiceSettingsResponse struct { type ServiceSettingsResponse struct {
FormResponse
Services map[string][]*happydns.ServiceCombined `json:"services,omitempty"` Services map[string][]*happydns.ServiceCombined `json:"services,omitempty"`
} }
@ -87,7 +86,7 @@ func getServiceSettingsState(cfg *config.Options, c *gin.Context) {
return return
} }
form, err := formDoState(cfg, c, &ups.FormState, ups.Service, forms.GenDefaultSettingsForm) form, p, err := formDoState(cfg, c, &ups.FormState, ups.Service, forms.GenDefaultSettingsForm)
if err != nil { if err != nil {
if err != forms.DoneForm { if err != forms.DoneForm {
@ -99,7 +98,7 @@ func getServiceSettingsState(cfg *config.Options, c *gin.Context) {
return return
} else { } else {
// Update an existing Service // Update an existing Service
err = zone.EraseServiceWithoutMeta(subdomain, domain.DomainName, ups.Id.([]byte), ups) err = zone.EraseServiceWithoutMeta(subdomain, domain.DomainName, *ups.Id, ups)
} }
if err != nil { if err != nil {
@ -115,12 +114,12 @@ func getServiceSettingsState(cfg *config.Options, c *gin.Context) {
c.JSON(http.StatusOK, ServiceSettingsResponse{ c.JSON(http.StatusOK, ServiceSettingsResponse{
Services: zone.Services, Services: zone.Services,
FormResponse: FormResponse{Redirect: ups.Redirect},
}) })
return return
} }
c.JSON(http.StatusOK, ProviderSettingsResponse{ c.JSON(http.StatusOK, ProviderSettingsResponse{
FormResponse: FormResponse{From: form}, Form: form,
Values: p,
}) })
} }

View File

@ -33,7 +33,7 @@ package forms // import "happydns.org/forms"
import () import ()
// CustomForm is used to create a form with several steps when creating or updating source's settings. // CustomForm is used to create a form with several steps when creating or updating provider's settings.
type CustomForm struct { type CustomForm struct {
// BeforeText is the text presented before the fields. // BeforeText is the text presented before the fields.
BeforeText string `json:"beforeText,omitempty"` BeforeText string `json:"beforeText,omitempty"`

View File

@ -39,12 +39,12 @@ import (
) )
// GenRecallID // GenRecallID
type GenRecallID func() int64 type GenRecallID func() string
// CustomSettingsForm are functions to declare when we want to display a custom user experience when asking for Source's settings. // CustomSettingsForm are functions to declare when we want to display a custom user experience when asking for Source's settings.
type CustomSettingsForm interface { type CustomSettingsForm interface {
// DisplaySettingsForm generates the CustomForm corresponding to the asked target state. // DisplaySettingsForm generates the CustomForm corresponding to the asked target state.
DisplaySettingsForm(int32, *config.Options, *happydns.Session, GenRecallID) (*CustomForm, error) DisplaySettingsForm(int32, *config.Options, *happydns.Session, GenRecallID) (*CustomForm, map[string]interface{}, error)
} }
var ( var (

View File

@ -42,10 +42,6 @@ import (
"git.happydns.org/happydomain/model" "git.happydns.org/happydomain/model"
) )
const (
SESSION_CKEY = "ovh-consumerkey"
)
func settingsForm(edit bool) *forms.CustomForm { func settingsForm(edit bool) *forms.CustomForm {
srcFields := []*forms.Field{ srcFields := []*forms.Field{
&forms.Field{ &forms.Field{
@ -75,25 +71,22 @@ func settingsForm(edit bool) *forms.CustomForm {
return form return form
} }
func settingsAskCredentials(cfg *config.Options, recallid int64, session *happydns.Session) (*forms.CustomForm, error) { func settingsAskCredentials(cfg *config.Options, recallid string, session *happydns.Session) (*forms.CustomForm, map[string]interface{}, error) {
client, err := ovh.NewClient("ovh-eu", appKey, appSecret, "") client, err := ovh.NewClient("ovh-eu", appKey, appSecret, "")
if err != nil { if err != nil {
return nil, fmt.Errorf("Unable to generate Consumer key, as OVH client can't be created: %w", err) return nil, nil, fmt.Errorf("Unable to generate Consumer key, as OVH client can't be created: %w", err)
} }
// Generate customer key // Generate customer key
ckReq := client.NewCkRequestWithRedirection(cfg.BuildURL_noescape("/providers/new/OVHAPI/2?recall=%d", recallid)) ckReq := client.NewCkRequestWithRedirection(cfg.BuildURL_noescape("/providers/new/OVHAPI/2?nsprvid=%s", recallid))
ckReq.AddRecursiveRules(ovh.ReadWrite, "/domain") ckReq.AddRecursiveRules(ovh.ReadWrite, "/domain")
ckReq.AddRules(ovh.ReadOnly, "/me") ckReq.AddRules(ovh.ReadOnly, "/me")
response, err := ckReq.Do() response, err := ckReq.Do()
if err != nil { if err != nil {
return nil, fmt.Errorf("Unable to generate Consumer key; OVH returns: %w", err) return nil, nil, fmt.Errorf("Unable to generate Consumer key; OVH returns: %w", err)
} }
// Store the key in user's session
session.SetValue(SESSION_CKEY, response.ConsumerKey)
// Return some explanation to the user // Return some explanation to the user
return &forms.CustomForm{ return &forms.CustomForm{
BeforeText: "In order allows happyDomain to get and update yours domains, you have to let us access them. To avoid storing your credentials, we will store a unique token that will be associated with your account. For this purpose, you will be redirected to an OVH login screen. The registration will automatically continue", BeforeText: "In order allows happyDomain to get and update yours domains, you have to let us access them. To avoid storing your credentials, we will store a unique token that will be associated with your account. For this purpose, you will be redirected to an OVH login screen. The registration will automatically continue",
@ -101,30 +94,29 @@ func settingsAskCredentials(cfg *config.Options, recallid int64, session *happyd
PreviousButtonText: "< Previous", PreviousButtonText: "< Previous",
NextButtonLink: response.ValidationURL, NextButtonLink: response.ValidationURL,
PreviousButtonState: 0, PreviousButtonState: 0,
}, map[string]interface{}{
"consumerkey": response.ConsumerKey,
}, nil }, nil
} }
func (s *OVHAPI) DisplaySettingsForm(state int32, cfg *config.Options, session *happydns.Session, genRecallId forms.GenRecallID) (*forms.CustomForm, error) { func (s *OVHAPI) DisplaySettingsForm(state int32, cfg *config.Options, session *happydns.Session, genRecallId forms.GenRecallID) (*forms.CustomForm, map[string]interface{}, error) {
switch state { switch state {
case 0: case 0:
return settingsForm(s.ConsumerKey != ""), nil return settingsForm(s.ConsumerKey != ""), nil, nil
case 1: case 1:
if s.ConsumerKey == "" { if s.ConsumerKey == "" {
recallid := genRecallId() recallid := genRecallId()
return settingsAskCredentials(cfg, recallid, session) return settingsAskCredentials(cfg, recallid, session)
} else { } else {
return nil, forms.DoneForm return nil, nil, forms.DoneForm
} }
case 2: case 2:
var consumerKey string if s.ConsumerKey == "" {
if ok := session.GetValue(SESSION_CKEY, &consumerKey); !ok { return nil, nil, errors.New("Something wierd has happend, as you were not in a consumer key registration process. Please retry.")
return nil, errors.New("Something wierd has happend, as you were not in a consumer key registration process. Please retry.")
} else { } else {
s.ConsumerKey = consumerKey return nil, nil, forms.DoneForm
session.DropKey(SESSION_CKEY)
return nil, forms.DoneForm
} }
default: default:
return nil, forms.CancelForm return nil, nil, forms.CancelForm
} }
} }