1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2025-08-08 22:36:41 +02:00

updates from review, WIP

This commit is contained in:
Lee Brown
2019-08-22 17:33:47 -08:00
parent d3b97a6608
commit 998d1bf13e
15 changed files with 158 additions and 25 deletions

12
cmd/README.md Normal file
View File

@ -0,0 +1,12 @@
# `/cmd`
Main applications for this project.
The directory name for each application should match the name of the executable you want to have (e.g., `/cmd/myapp`).
Don't put a lot of code in the application directory. If you think the code can be imported and used in other projects,
then it should live in the `/pkg` directory. If the code is not reusable or if you don't want others to reuse it,
put that code in the `/internal` directory. You'll be surprised what others will do, so be explicit about your intentions!
It's common to have a small `main` function that imports and invokes the code from the `/internal` and `/pkg`
directories and nothing else.

View File

@ -567,11 +567,13 @@ func main() {
// Need defined functions below since they require config values, able to add additional functions
// here to extend functionality.
tmplFuncs := template.FuncMap{
// BuildInfo returns the specific key from BuildInfo set in the current config.
"BuildInfo": func(k string) string {
r := reflect.ValueOf(cfg.BuildInfo)
f := reflect.Indirect(r).FieldByName(k)
return f.String()
},
// SiteBaseUrl returns the absolute URL for a relative path using the base site URL set in the config.
"SiteBaseUrl": func(p string) string {
u, err := url.Parse(cfg.Service.BaseUrl)
if err != nil {
@ -580,21 +582,10 @@ func main() {
u.Path = p
return u.String()
},
"AssetUrl": func(p string) string {
var u string
if staticUrlFormatter != nil {
u = staticUrlFormatter(p)
} else {
if !strings.HasPrefix(p, "/") {
p = "/" + p
}
u = p
}
u = browserCacheBusterFunc(u)
return u
},
// SiteAssetUrl returns the absolute URL for a relative path that either served locally, from the public S3
// bucket or from Cloudfront depending on the current config settings for StaticFiles. The defined static asset
// prefix to the path defined in the current config settings for StaticFiles. The response URL includes a cache
// busting query param based on the current commit.
"SiteAssetUrl": func(p string) string {
var u string
if staticUrlFormatter != nil {
@ -610,6 +601,8 @@ func main() {
return u
},
// SiteS3Url returns the URL that for an S3 Key path that has been uploaded to S3 to the specific public s3 key
// prefix that returns the absolute S3 URL or the CloudFront equivalent if enabled.
"SiteS3Url": func(p string) string {
var u string
if staticUrlFormatter != nil {
@ -619,6 +612,8 @@ func main() {
}
return u
},
// S3Url returns the URL that for an S3 Key path that has been uploaded to S3 to the public s3 key
// prefix that returns the absolute S3 URL or the CloudFront equivalent if enabled.
"S3Url": func(p string) string {
var u string
if staticUrlFormatter != nil {
@ -628,6 +623,7 @@ func main() {
}
return u
},
// ValidationErrorHasField checks if the error is a validation error and has an error for the specified field.
"ValidationErrorHasField": func(err interface{}, fieldName string) bool {
if err == nil {
return false
@ -643,6 +639,7 @@ func main() {
}
return false
},
// ValidationFieldErrors returns the list of validation field errors.
"ValidationFieldErrors": func(err interface{}, fieldName string) []weberror.FieldError {
if err == nil {
return []weberror.FieldError{}
@ -659,6 +656,7 @@ func main() {
}
return l
},
// ValidationFieldClass returns a CSS class for validation if the field exists in the validation errors.
"ValidationFieldClass": func(err interface{}, fieldName string) string {
if err == nil {
return ""
@ -675,6 +673,7 @@ func main() {
}
return "is-valid"
},
// ErrorMessage returns the error message that is formatted as a response for end users to consume.
"ErrorMessage": func(ctx context.Context, err error) string {
werr, ok := err.(*weberror.Error)
if ok {
@ -685,6 +684,7 @@ func main() {
}
return fmt.Sprintf("%s", err)
},
// ErrorDetails returns the full error for dev and stage envs to help with debugging.
"ErrorDetails": func(ctx context.Context, err error) string {
var displayFullError bool
switch webcontext.ContextEnv(ctx) {
@ -707,8 +707,7 @@ func main() {
return fmt.Sprintf("%+v", err)
},
// Returns the current user from the session.
// @TODO: Need to add logging for the errors.
// ContextUser returns the current user and caches the result.
"ContextUser": func(ctx context.Context) *user.UserResponse {
sess := webcontext.ContextSession(ctx)
@ -716,6 +715,7 @@ func main() {
u := &user.UserResponse{}
if err := redisClient.Get(cacheKey).Scan(u); err != nil && err != redis.Nil {
log.Printf("main : ContextUser : Redis Get failed - %+v ", err.Error())
return nil
}
@ -737,13 +737,13 @@ func main() {
err = redisClient.Set(cacheKey, u, time.Hour).Err()
if err != nil {
log.Printf("main : ContextAccount : Redis Set failed - %+v ", err.Error())
return nil
}
return u
},
// Returns the current account from the session.
// @TODO: Need to add logging for the errors.
// ContextAccount returns the account for current context user with auth is using and caches the result.
"ContextAccount": func(ctx context.Context) *account.AccountResponse {
sess := webcontext.ContextSession(ctx)
@ -751,6 +751,7 @@ func main() {
a := &account.AccountResponse{}
if err := redisClient.Get(cacheKey).Scan(a); err != nil && err != redis.Nil {
log.Printf("main : ContextAccount : Redis Get failed - %+v ", err.Error())
return nil
}
@ -772,11 +773,13 @@ func main() {
err = redisClient.Set(cacheKey, a, time.Hour).Err()
if err != nil {
log.Printf("main : ContextAccount : Redis Set failed - %+v ", err.Error())
return nil
}
return a
},
// ContextCanSwitchAccount returns if the current context user has multiple accounts.
"ContextCanSwitchAccount": func(ctx context.Context) bool {
claims, err := auth.ClaimsFromContext(ctx)
if err != nil || len(claims.AccountIDs) < 2 {
@ -784,6 +787,7 @@ func main() {
}
return true
},
// ContextIsVirtualSession returns true if the current context user with auth is in a virtual session.
"ContextIsVirtualSession": func(ctx context.Context) bool {
claims, err := auth.ClaimsFromContext(ctx)
if err != nil {
@ -797,6 +801,63 @@ func main() {
}
return false
},
// T creates the translation for the locale given the 'key' and params passed in.
"T": func(ctx context.Context, key string, params ...string) string {
trns := webcontext.ContextTranslator(ctx)
if trns == nil {
return key
}
res, err := trns.T(key, params...)
if err != nil {
log.Printf("main : Translate.T : Failed to translate %s with '%s' - %+v", trns.Locale(), key, err.Error())
return key
}
return res
},
// C creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments and param passed in
"C": func(ctx context.Context, key string, num float64, digits uint64, param string) string {
trns := webcontext.ContextTranslator(ctx)
if trns == nil {
return key
}
res, err := trns.C(key, num, digits, param)
if err != nil {
log.Printf("main : Translate.C : Failed to translate %s with '%s' - %+v", trns.Locale(), key, err.Error())
return key
}
return res
},
// O creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments and param passed in
"O": func(ctx context.Context, key string, num float64, digits uint64, param string) string {
trns := webcontext.ContextTranslator(ctx)
if trns == nil {
return key
}
res, err := trns.O(key, num, digits, param)
if err != nil {
log.Printf("main : Translate.O : Failed to translate %s with '%s' - %+v", trns.Locale(), key, err.Error())
return key
}
return res
},
// R creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and 'digit2'
// arguments and 'param1' and 'param2' passed in
"R": func(ctx context.Context, key string, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) string {
trns := webcontext.ContextTranslator(ctx)
if trns == nil {
return key
}
res, err := trns.R(key, num1, digits1, num2, digits2, param1, param2)
if err != nil {
log.Printf("main : Translate.R : Failed to translate %s with '%s' - %+v", trns.Locale(), key, err.Error())
return key
}
return res
},
}
imgUrlFormatter := staticUrlFormatter