Skip to content

Commit

Permalink
Add document service layer
Browse files Browse the repository at this point in the history
  • Loading branch information
alexblockfactory committed Feb 20, 2020
1 parent 89b77bc commit ff40435
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 151 deletions.
118 changes: 17 additions & 101 deletions main/handlers/api/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"time"
Expand All @@ -35,9 +34,7 @@ import (
"github.com/ProxeusApp/proxeus-core/sys/email"
"github.com/ProxeusApp/proxeus-core/sys/file"
"github.com/ProxeusApp/proxeus-core/sys/model"
"github.com/ProxeusApp/proxeus-core/sys/utils"
"github.com/ProxeusApp/proxeus-core/sys/validate"
workflow2 "github.com/ProxeusApp/proxeus-core/sys/workflow"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand All @@ -50,16 +47,16 @@ var (
paymentService service.PaymentService
userService service.UserService
workflowService service.WorkflowService

filenameRegex = regexp.MustCompile(`^[^\s][\p{L}\d.,_\-&: ]{3,}[^\s]$`)
documentService service.DocumentService
)

func Init(paymentS service.PaymentService, userS service.UserService,
workflowS service.WorkflowService) {
workflowS service.WorkflowService, documentS service.DocumentService) {

paymentService = paymentS
userService = userS
workflowService = workflowS
documentService = documentS
}

func html(c echo.Context, p string) error {
Expand Down Expand Up @@ -482,7 +479,7 @@ func LoginWithWallet(c *www.Context, challenge, signature string) (bool, *model.
created = true
usr, err = c.System().DB.User.GetByBCAddress(address)
if err == nil {
copyWorkflows(c, usr)
workflowService.CopyWorkflows(root, usr)
if c.System().GetSettings().BlockchainNet == "ropsten" && c.System().GetSettings().AirdropEnabled == "true" {
go func() {
defer func() {
Expand Down Expand Up @@ -658,7 +655,7 @@ func Register(e echo.Context) error {
return c.NoContent(http.StatusExpectationFailed)
}

copyWorkflows(c, newUser)
workflowService.CopyWorkflows(root, newUser)

err = c.System().DB.User.PutPw(newUser.ID, p.Password)
if err != nil {
Expand Down Expand Up @@ -1061,26 +1058,10 @@ func DocumentEditHandler(e echo.Context) error {
if err != nil {
return err
}
if n, ok := formInput["name"]; ok {
if fname, ok := n.(string); ok {
if len(fname) < 80 && filenameRegex.MatchString(fname) {
usrDataItem, err := c.System().DB.UserData.Get(sess, ID)
if err != nil {
return c.String(http.StatusBadRequest, err.Error())
}
if n, ok := formInput["detail"]; ok {
if fdetail, ok := n.(string); ok {
usrDataItem.Detail = fdetail
}
}
usrDataItem.Name = fname
err = c.System().DB.UserData.Put(sess, usrDataItem)
if err != nil {
return c.String(http.StatusBadRequest, err.Error())
}
return c.NoContent(http.StatusOK)
}
}
err = documentService.Edit(sess, ID, formInput)
if err != nil {
log.Println("[api][handlers] DocumentEditHandler Edit err: ", err.Error())
return c.String(http.StatusBadRequest, err.Error())
}
}
return c.NoContent(http.StatusUnprocessableEntity)
Expand Down Expand Up @@ -1897,19 +1878,21 @@ func WorkflowSchema(e echo.Context) error {
if sess == nil {
return c.NoContent(http.StatusUnauthorized)
}

id := c.Param("ID")
wf, err := c.System().DB.Workflow.Get(sess, id)
workflowItem, fieldsAndRules, err := documentService.GetWorkflowSchema(sess, id)
if err != nil {
log.Println("[apiHandler][WorkflowSchema] GetWorkflowSchema err: ", err.Error())
return c.NoContent(http.StatusNotFound)
}
fieldsAndRules := utils.GetAllFormFieldsWithRulesOf(wf.Data, sess, c.System())
wfDetails := &struct {
*model.WorkflowItem
Data interface{} `json:"data"`
}{wf, fieldsAndRules}
}{workflowItem, fieldsAndRules}
result := &struct {
Workflow interface{} `json:"workflow"`
}{Workflow: wfDetails}

return c.JSON(http.StatusOK, result)
}

Expand All @@ -1924,7 +1907,7 @@ func WorkflowExecuteAtOnce(e echo.Context) error {
return c.NoContent(http.StatusBadRequest)
}
id := c.Param("ID")
wItem, err := c.System().DB.Workflow.Get(sess, id)
wItem, err := workflowService.Get(sess, id)
if err != nil || wItem.Data == nil {
return c.NoContent(http.StatusNotFound)
}
Expand Down Expand Up @@ -1952,7 +1935,7 @@ func CreateApiKeyHandler(e echo.Context) error {
if name == "" {
return c.String(http.StatusBadRequest, "please provide a name for your key")
}
apiKey, err := c.System().DB.User.CreateApiKey(sess, id, name)
apiKey, err := userService.CreateApiKeyHandler(sess, id, name)
if err != nil {
return c.String(http.StatusBadRequest, err.Error())
}
Expand All @@ -1970,7 +1953,7 @@ func DeleteApiKeyHandler(e echo.Context) error {
}
id := c.Param("ID")
hiddenApiKey := c.QueryParam("hiddenApiKey")
err := c.System().DB.User.DeleteApiKey(sess, id, hiddenApiKey)
err := userService.DeleteApiKey(sess, id, hiddenApiKey)
if err != nil {
return c.String(http.StatusBadRequest, err.Error())
}
Expand All @@ -1980,73 +1963,6 @@ func DeleteApiKeyHandler(e echo.Context) error {
return c.NoContent(http.StatusOK)
}

func copyWorkflows(c *www.Context, newUser *model.User) {
log.Println("Copy workflows to new user, if any...")
// If some default workflows have to be assigned to the user, then clone them
workflowIds := strings.Split(c.System().GetSettings().DefaultWorkflowIds, ",")
workflows, err := c.System().DB.Workflow.GetList(root, workflowIds)
if err != nil {
log.Printf("Can't retrieve list of workflows (%v). Please check the ids exist. Error: %s", workflowIds, err.Error())
}
for _, workflow := range workflows {
w := workflow.Clone()
w.OwnerEthAddress = newUser.EthereumAddr
w.Owner = newUser.ID
newNodes := make(map[string]*workflow2.Node)
oldToNewIdsMap := make(map[string]string)
for oldId, node := range w.Data.Flow.Nodes {
if node.Type == "form" {
form, er := c.System().DB.Form.Get(root, node.ID)
if er != nil {
log.Println(err.Error())
}
f := form.Clone()
er = c.System().DB.Form.Put(newUser, &f)
if er != nil {
log.Println("can't put form" + err.Error())
}

oldToNewIdsMap[node.ID] = f.ID
node.ID = f.ID
newNodes[node.ID] = node
delete(w.Data.Flow.Nodes, oldId)

} else if node.Type == "template" {
template, er := c.System().DB.Template.Get(root, node.ID)
if er != nil {
log.Println(err.Error())
}
t := template.Clone()
er = c.System().DB.Template.Put(newUser, &t)
if er != nil {
log.Println("can't put template" + err.Error())
}
oldToNewIdsMap[node.ID] = t.ID
node.ID = t.ID
newNodes[node.ID] = node
delete(w.Data.Flow.Nodes, oldId)
} else {
newNodes[node.ID] = node
}
}
oldStartNodeId := w.Data.Flow.Start.NodeID
if _, ok := oldToNewIdsMap[oldStartNodeId]; ok {
w.Data.Flow.Start.NodeID = oldToNewIdsMap[oldStartNodeId]
}

// Now go through all connections and map them with the new ids
for _, node := range newNodes {
for _, connection := range node.Connections {
if _, ok := oldToNewIdsMap[connection.NodeID]; ok {
connection.NodeID = oldToNewIdsMap[connection.NodeID]
}
}
}
w.Data.Flow.Nodes = newNodes
c.System().DB.Workflow.Put(newUser, &w)
}
}

func ExternalConfigurationPage(e echo.Context) error {
c := e.(*www.Context)
sess := c.Session(false)
Expand Down
3 changes: 2 additions & 1 deletion main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ func main() {
paymentService := service.NewPaymentService(system, userService)
workflowService := service.NewWorkflowService(system, userService)
nodeService := service.NewNodeService(system, workflowService)
documentService := service.NewDocumentService(system)

payment.Init(paymentService, userService)
api.Init(paymentService, userService, workflowService)
api.Init(paymentService, userService, workflowService, documentService)
workflow.Init(workflowService, userService, nodeService)

www.SetSystem(system)
Expand Down
4 changes: 4 additions & 0 deletions service/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ func (me *baseService) formDB() storage.FormIF {
func (me *baseService) templateDB() storage.TemplateIF {
return me.system.DB.Template
}

func (me *baseService) settingsDB() storage.SettingsIF {
return me.system.DB.Settings
}
99 changes: 99 additions & 0 deletions service/document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package service

import (
"github.com/ProxeusApp/proxeus-core/sys"
"github.com/ProxeusApp/proxeus-core/sys/form"
"github.com/ProxeusApp/proxeus-core/sys/model"
"github.com/ProxeusApp/proxeus-core/sys/workflow"
"regexp"
)

type (
DocumentService interface {
GetWorkflowSchema(auth model.Auth, workflowId string) (*model.WorkflowItem, map[string]interface{}, error)
Edit(auth model.Auth, userId string, formInput map[string]interface{}) error
}

DefaultDocumentService struct {
*baseService
}
)

func NewDocumentService(system *sys.System) *DefaultDocumentService {
return &DefaultDocumentService{&baseService{system: system}}
}

func (me *DefaultDocumentService) GetWorkflowSchema(auth model.Auth, workflowId string) (*model.WorkflowItem, map[string]interface{}, error) {

wf, err := me.workflowDB().Get(auth, workflowId)
if err != nil {
return nil, nil, err
}
fieldsAndRules := me.getAllFormFieldsWithRulesOf(wf.Data, auth)

return wf, fieldsAndRules, nil
}

func (me *DefaultDocumentService) Edit(auth model.Auth, userId string, formInput map[string]interface{}) error {
filenameRegex := regexp.MustCompile(`^[^\s][\p{L}\d.,_\-&: ]{3,}[^\s]$`)

if n, ok := formInput["name"]; ok {
if fname, ok := n.(string); ok {
if len(fname) < 80 && filenameRegex.MatchString(fname) {
usrDataItem, err := me.userDataDB().Get(auth, userId)
if err != nil {
return err
}
if n, ok := formInput["detail"]; ok {
if fdetail, ok := n.(string); ok {
usrDataItem.Detail = fdetail
}
}
usrDataItem.Name = fname
return me.userDataDB().Put(auth, usrDataItem)
}
}
}
return nil
}

func (me *DefaultDocumentService) getAllFormFieldsWithRulesOf(wf *workflow.Workflow, auth model.Auth) map[string]interface{} {
marshaledForms := me.marshaledFormsOf(wf, auth)
fieldsAndRules := map[string]interface{}{}
//collect all form fields
for _, formItem := range marshaledForms {
vars := form.Vars(formItem.Data)
for _, v := range vars {
fieldsAndRules[v] = form.RulesOf(formItem.Data, v)
}
}
return fieldsAndRules
}

func (me *DefaultDocumentService) marshaledFormsOf(wf *workflow.Workflow, a model.Auth) map[string]*model.FormItem {
if wf == nil {
return nil
}
marshaledForms := map[string]*model.FormItem{}
loop := &workflow.Looper{}
//loop recursively and collect all forms
wf.Loop(loop, func(l *workflow.Looper, node *workflow.Node) bool {
if node.Type == "form" {
if _, ok := marshaledForms[node.ID]; !ok {
it, er := me.formDB().Get(a, node.ID)
if er != nil {
return true //continue
}
marshaledForms[it.ID] = it
}
} else if node.Type == "workflow" { // deep dive...
it, er := me.workflowDB().Get(a, node.ID)
if er != nil {
return true //continue
}
it.LoopNodes(l, nil)
}
return true //continue
})
return marshaledForms
}
10 changes: 10 additions & 0 deletions service/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type (
UserService interface {
GetUser(auth model.Auth) (*model.User, error)
GetById(auth model.Auth, id string) (*model.User, error)
CreateApiKeyHandler(auth model.Auth, userId, apiKeyName string) (string, error)
DeleteApiKey(auth model.Auth, userId, hiddenApiKey string) error
}
defaultUserService struct {
*baseService
Expand All @@ -25,3 +27,11 @@ func (me *defaultUserService) GetUser(auth model.Auth) (*model.User, error) {
func (me *defaultUserService) GetById(auth model.Auth, id string) (*model.User, error) {
return me.userDB().Get(auth, id)
}

func (me *defaultUserService) CreateApiKeyHandler(auth model.Auth, userId, apiKeyName string) (string, error) {
return me.userDB().CreateApiKey(auth, userId, apiKeyName)
}

func (me *defaultUserService) DeleteApiKey(auth model.Auth, userId, hiddenApiKey string) error {
return me.userDB().DeleteApiKey(auth, userId, hiddenApiKey)
}
Loading

0 comments on commit ff40435

Please sign in to comment.