diff --git a/.editorconfig b/.editorconfig index e13f9b9..ece50d4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,6 +6,6 @@ root = true # Unix-style newlines with a newline ending every file [*] indent_style = space -indent_size = 2 +indent_size = 4 end_of_line = lf insert_final_newline = true \ No newline at end of file diff --git a/src/accounts/account.go b/src/accounts/account.go new file mode 100644 index 0000000..f41f7e5 --- /dev/null +++ b/src/accounts/account.go @@ -0,0 +1,7 @@ +package accounts + +type account struct { + AccountID string `json:"accountId"` + AccountType AccountType `json:"accountType"` + Balance float64 `json:"balance"` +} diff --git a/src/accounts/account_types.go b/src/accounts/account_types.go new file mode 100644 index 0000000..4567ce3 --- /dev/null +++ b/src/accounts/account_types.go @@ -0,0 +1,9 @@ +package accounts + +type AccountType int + +const ( + Cheque AccountType = iota + Savings + Credit +) diff --git a/src/accounts/accounts.go b/src/accounts/accounts.go new file mode 100644 index 0000000..50b82bf --- /dev/null +++ b/src/accounts/accounts.go @@ -0,0 +1,95 @@ +package accounts + +import ( + "encoding/json" + "net/http" + + dapr "github.com/dapr/go-sdk/client" + "github.com/gin-gonic/gin" +) + +const state = "accounts-state" +const validationFailureErrorMessage = "model validation failure while attempting to map request to type" +const notFoundErrorMessage = "reesource not found" +const internalServerErrorMessage = "an environmental, non-specific error has occurred" + +func GetAccountsForUser(c *gin.Context) { + userId := c.Param("userId") + + accounts, err := getAccountsForUser(userId, c) + if err != nil { + c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": internalServerErrorMessage}) + return + } + + if accounts == nil || len(accounts) == 0 { + c.IndentedJSON(http.StatusNotFound, gin.H{"message": notFoundErrorMessage}) + return + } + + c.IndentedJSON(http.StatusOK, accounts) +} + +func CreateAccountForUser(c *gin.Context) { + userId := c.Param("userId") + var account account + + accounts, err := getAccountsForUser(userId, c) + if err != nil { + c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": internalServerErrorMessage}) + return + } + + if err := c.ShouldBindJSON(&account); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"message": validationFailureErrorMessage}) + return + } + + accounts = append(accounts, account) + if err := saveAccountsForUser(userId, accounts, c); err != nil { + c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": internalServerErrorMessage}) + return + } + + c.IndentedJSON(http.StatusCreated, nil) +} + +func getAccountsForUser(userId string, c *gin.Context) (accounts []account, err error) { + client, err := dapr.NewClient() + if err != nil { + return nil, err + } + defer client.Close() + + daprStateItem, err := client.GetState(c, state, userId, nil) + if err != nil { + return nil, err + } + + err = json.Unmarshal(daprStateItem.Value, &accounts) + if err != nil { + return nil, err + } + + return accounts, nil +} + +func saveAccountsForUser(userId string, accounts []account, c *gin.Context) (err error) { + client, err := dapr.NewClient() + if err != nil { + return err + } + defer client.Close() + + accountBytes, err := json.Marshal(accounts) + if err != nil { + return err + } + + err = client.SaveState(c, state, userId, accountBytes, nil) + if err != nil { + return err + } + + return nil +} diff --git a/src/controllers/accounts.go b/src/controllers/accounts.go deleted file mode 100644 index d9b0bcb..0000000 --- a/src/controllers/accounts.go +++ /dev/null @@ -1,28 +0,0 @@ -package controllers - -import ( - "net/http" - - dapr "github.com/dapr/go-sdk/client" - "github.com/gin-gonic/gin" -) - -const state = "accounts-state" - -func GetAccounts(c *gin.Context) { - client, err := dapr.NewClient() - if err != nil { - panic(err) - } - defer client.Close() - - accountId := c.Param("id") - - accounts, err := client.GetState(c, state, accountId, nil) - if err != nil { - c.IndentedJSON(http.StatusNotFound, gin.H{"message": "account not found"}) - return - } - - c.IndentedJSON(http.StatusOK, accounts) -} diff --git a/src/dapr/state.accounts.yaml b/src/dapr/state.accounts.yaml new file mode 100644 index 0000000..8ff083d --- /dev/null +++ b/src/dapr/state.accounts.yaml @@ -0,0 +1,10 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: accounts-state +spec: + type: state.redis + version: v1 + metadata: + - name: redisHost + value: redis:6379 \ No newline at end of file diff --git a/src/main.go b/src/main.go index fac6b09..4d10fd3 100644 --- a/src/main.go +++ b/src/main.go @@ -1,13 +1,14 @@ package main import ( - "github.com/KrylixZA/bank-with-dapr/controllers" + "github.com/KrylixZA/bank-with-dapr/accounts" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() - router.GET("/accounts/:id", controllers.GetAccounts) + router.GET("/accounts/:userId", accounts.GetAccountsForUser) + router.POST("/accounts/:userId", accounts.CreateAccountForUser) router.Run("localhost:8080") }