Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions features/golang_ledger/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module msudenver.edu/ledger

go 1.15

require (
github.com/Rhymond/go-money v1.0.2
github.com/corpix/uarand v0.1.1 // indirect
github.com/cucumber/godog v0.11.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gin-gonic/gin v1.6.3
github.com/go-pg/pg/v10 v10.7.7
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/gorilla/mux v1.8.0
github.com/gorilla/securecookie v1.1.1
github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428
github.com/joho/godotenv v1.3.0
github.com/json-iterator/go v1.1.10 // indirect
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/echo/v4 v4.2.0
github.com/leodido/go-urn v1.2.1 // indirect
github.com/plaid/plaid-go v0.0.0-20210216195344-700b8cfc627d
github.com/sirupsen/logrus v1.2.0
github.com/ugorji/go v1.2.4 // indirect
github.com/unrolled/render v1.0.3
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
golang.org/x/sys v0.0.0-20210308170721-88b6017d0656 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
42 changes: 42 additions & 0 deletions features/golang_ledger/repos/account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package repos

import (
"time"

"github.com/Rhymond/go-money"
"github.com/go-pg/pg/v10"
)

type AccountRepo struct {
db *pg.DB
}

type Account struct {
ID uint64
UserID uint64
User *User
AccountID string `pg:",notnull"`
Name string `pg:",notnull"`
Mask string `pg:",notnull"`
Balance money.Money
Type string
Subtype string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
}

func (r *AccountRepo) CreateAccount(accountId, name, mask string, balance money.Money) (*Account, error) {
account := &Account{
AccountID: accountId,
Name: name,
Mask: mask,
Type: "depository",
Subtype: "checking",
}
_, err := r.db.Model(account).Insert()
if err != nil {
return nil, err
}
return account, nil
}
49 changes: 49 additions & 0 deletions features/golang_ledger/repos/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package repos

import (
"os"

"github.com/go-pg/pg/v10"
"github.com/go-pg/pg/v10/orm"
)

var tables = []interface{}{
(*User)(nil),
(*PlaidItem)(nil),
(*Account)(nil),
}

type Repo struct {
db *pg.DB
Users interface {
CreateUser(name string, email string, password string) (*User, error)
FetchUserbyID(id int64) (*User, error)
SaveUserbyID(u *User) (*User, error)
}
Accounts interface {
}
}

func CreateRepo(db *pg.DB) *Repo {
repo := &Repo{
db: db,
Users: &UserRepo{db: db},
Accounts: &AccountRepo{db: db},
}
return repo
}

// CreateSchema creates the tables in the database
func (r *Repo) CreateSchema(db *pg.DB) error {
temp := os.Getenv("POSTGRES_TEMP") == "true"
for _, table := range tables {
opts := &orm.CreateTableOptions{
IfNotExists: true,
Temp: temp,
}
if err := db.Model(table).CreateTable(opts); err != nil {
return err
}
}
return nil
}
40 changes: 40 additions & 0 deletions features/golang_ledger/repos/middleware/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package middleware

import (
"errors"
"fmt"
"net/http"
"os"
"strings"

"github.com/dgrijalva/jwt-go"
u "msudenver.edu/ledger/repos/utility"
)

// IsLogin ...
func IsLogin(r http.Header) ([]byte, error) {

tokenString := r.Get("Authorization")
if len(tokenString) == 0 {
return nil, errors.New("UnAuthorized")
}
tokenString = strings.Replace(tokenString, "Bearer ", "", 1)
claims, err := verifyToken(tokenString)
if err != nil {

return nil, err
}
return u.Marshal(claims), nil
}

func verifyToken(tokenString string) (jwt.Claims, error) {
signingKey := []byte(os.Getenv("jwt"))
fmt.Println("key", string(signingKey))
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return signingKey, nil
})
if err != nil {
return nil, err
}
return token.Claims, err
}
40 changes: 40 additions & 0 deletions features/golang_ledger/repos/plaid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package repos

import "time"

type PlaidItem struct {
ID uint64
User *User `pg:",notnull"`
AccessToken string `pg:",unique,notnull"`
ItemID string `pg:",notnull"`
InstitutionID string `pg:",notnull"`
Status string `pg:",notnull"`
CreatedAt time.Time
UpdatedAt time.Time
}

type LinkEvent struct {
ID uint64
Type string
UserID uint64
LinkSessionID string
RequestID string
ErrorType string
ErrorCode string
CreatedAt time.Time `pg:"default:now()"`
}

type ApiEvent struct {
ID uint64
ItemID uint64
PlaidMethd string
Arguments string
RequestID string
ErrorType string
ErrorCode string
CreatedAt time.Time
}

func LinkAccount() {

}
86 changes: 86 additions & 0 deletions features/golang_ledger/repos/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package repos

import (
"fmt"
"regexp"
"time"

"github.com/go-pg/pg/v10"
)

// UserRepo is a custom model type which wraps
// the sql.DB connection pool and other needed types
type UserRepo struct {
db *pg.DB
}

// CreateUser inserts new user records
func (r *UserRepo) CreateUser(name string, email string, password string) (*User, error) {
now := time.Now()
user := &User{
FullName: name,
Email: email,
Password: password,
CreatedAt: now,
UpdatedAt: now,
}
if err := user.isValid(); err != nil {
return nil, err
}
if _, err := r.db.Model(user).Returning("*").Insert(); err != nil {
return nil, err
}
return user, nil
}

func (r *UserRepo) FetchUserbyID(id int64) (*User, error) {
user := &User{ID: id}
err := r.db.Model(user).WherePK().Select()
if err != nil {
return nil, err
}
return user, nil
}

func (r *UserRepo) SaveUserbyID(u *User) (*User, error) {
_, err := r.db.Model(u).WherePK().Update()
if err != nil {
return nil, err
}
return u, nil
}

// Thanks to Edd Turtle https://golangcode.com/validate-an-email-address/
var emailRegex = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")

// User is the struct we use to represent a user of the system
type User struct {
tableName struct{} `pg:"users"`
ID int64 `json:"-"`
FullName string `pg:",notnull"`
Email string `pg:",notnull,unique"`
Password string `pg:"notnull" json:"-"`
CreatedAt time.Time `pg:"default:now()"`
UpdatedAt time.Time
DeletedAt time.Time `pg:",soft_delete"`
}

func (u User) isValid() error {
var errs []error
if u.FullName == "" {
errs = append(errs, fmt.Errorf("Name is required"))
}
if u.Email == "" {
errs = append(errs, fmt.Errorf("Email is required"))
} else if !emailRegex.MatchString(u.Email) {
errs = append(errs, fmt.Errorf("Email is not a valid address"))
}
if len(errs) > 0 {
return fmt.Errorf("Invalid: %s", errs)
}
return nil
}

func UpdatePassword() {

}
48 changes: 48 additions & 0 deletions features/golang_ledger/repos/utility/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package utility

import (
"encoding/json"

"github.com/sirupsen/logrus"

"github.com/unrolled/render"
)

var R *render.Render
var Log *logrus.Entry

//pakcage for adding for utitliy functions

// IsBlank ...
func IsBlank(v interface{}) bool {
if v == 0 {
return true
}
if v == "" {
return true
}
if v == nil {
return true
}
return false
}

// Unmarshal ...
func Unmarshal(body []byte, v interface{}) interface{} {
PrintError(json.Unmarshal(body, v))
return v
}

// Marshal ...
func Marshal(v interface{}) []byte {
data, err := json.Marshal(v)
PrintError(err)
return data
}

// PrintError ...
func PrintError(e error) {
if e != nil {
Log.Println(e)
}
}
20 changes: 20 additions & 0 deletions features/golang_ledger/web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## Landing page .go & .html files

Execute landing.go file

```shell
$ go run landing.go
```

Navigate to: http://localhost:8080/ledger.html

## UI

The User Interface is a [Single Page App](https://en.wikipedia.org/wiki/Single-page_application)
built using the [React](https://reactjs.org) library, and the [Pure CSS](https://purecss.io/) framework.

Bundling assets and building the JavaScript application is managed through [snowpack](https://www.snowpack.dev).

```
task dev
```