diff --git a/cmd/new.go b/cmd/new.go index bab3253..72a0952 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -51,7 +51,6 @@ var ( srcRoot string // mercurius related paths - mercuriusPkg *build.Package appPath string appName string basePath string @@ -103,6 +102,13 @@ func initGoPaths() { } func setApplicationPath() { + // set base project path + // skeletonPath = filepath.Join(mercuriusPkg.Dir, "skeleton") + if os.Getenv("GOPATH") == "" && os.Getenv("MERCURIUSPATH") == "" { + printColored("Abort: neither GOPATH or MERCURIUSPATH are set. You need to define them to mercurius be able to access skeleton (template) files\n", color.New(color.FgHiRed).PrintlnFunc()) + os.Exit(-1) + } + var err error appName = terminal("What is your application name?", "go-myapp") gitPath := terminal("What is your git source host? github.com, bitbucket.org or gitlab.com?", "github.com") @@ -147,15 +153,16 @@ func setApplicationPath() { // is a subdirectory such as $GOROOT/src/path/to/mercurius basePath += "/" } - // set base project path - // skeletonPath = filepath.Join(mercuriusPkg.Dir, "skeleton") - skeletonPath = filepath.Join(os.Getenv("GOPATH"), "/src/", "github.com/novatrixtech/mercurius", "skeleton") - if debug { + if len(os.Getenv("GOPATH")) > 0 { + skeletonPath = filepath.Join(os.Getenv("GOPATH"), "/src/", "github.com/novatrixtech/mercurius", "skeleton") + } else { + skeletonPath = filepath.Join(os.Getenv("MERCURIUSPATH"), "/", "skeleton") + } + if debug { color.Set(color.FgHiMagenta) defer color.Unset() - fmt.Println("1 - Your runtime is: ", runtime.GOOS) // if runtime.GOOS == "windows" { fmt.Printf(" skeletonPath: %s \n", skeletonPath) @@ -164,14 +171,15 @@ func setApplicationPath() { fmt.Printf(" gitUser: %s \n", gitUser) fmt.Printf(" import-Path: %s \n", importPath) fmt.Printf(" app-Path: %s \n", appPath) - fmt.Printf(" base-Path: %s \n\n", basePath) + fmt.Printf(" base-Path: %s \n", basePath) + fmt.Printf(" gopath: %s\n", gopath) + fmt.Printf(" srcRoot: %s\n\n", srcRoot) // } } } func copyNewAppFiles(cfgs map[string]interface{}) { - var err error - err = os.MkdirAll(appPath, 0777) + err := os.MkdirAll(appPath, 0o777) if err != nil { printColored(fmt.Sprintf("Abort: Could not generate app %s\n", err), color.New(color.FgHiRed).PrintlnFunc()) os.Exit(-1) @@ -221,9 +229,9 @@ func confValues() map[string]interface{} { } func packageStateCheck() { - cd(os.Getenv("GOPATH") + "/src/" + importPath) + cd(appPath) if debug { - printColored(fmt.Sprintf("pkg.Dir: %q", os.Getenv("GOPATH")+"/src/"+importPath), color.New(color.FgHiMagenta).PrintlnFunc()) + printColored(fmt.Sprintf("pkg.Dir: %q", appPath), color.New(color.FgHiMagenta).PrintlnFunc()) } printColored("Generating go modules.", color.New(color.FgHiMagenta).PrintlnFunc()) cmdGoMod := exec.Command("go", "mod", "tidy") @@ -270,18 +278,6 @@ func getGeneratedCode() *build.Package { return pkg } -func getGodep() { - _, err := build.Import(godepPath, "", build.FindOnly) - if err != nil { - cmd := exec.Command("go", "get", godepPath) - err = cmd.Run() - if err != nil { - printColored(fmt.Sprintf("Abort: %s\n", err), color.New(color.FgHiRed).PrintlnFunc()) - os.Exit(-1) - } - } -} - func getDependencies() { cmd := exec.Command("go", "get", "./...") printColored("Getting all dependencies and waiting Go finishes the job...", color.New(color.FgHiYellow).PrintlnFunc()) @@ -292,6 +288,7 @@ func getDependencies() { } } +// TODO: update vendorize to usenew go mod's vendorize methodology func vendorize() { v := terminal("Your App is ready to go. Do you also want to vendorize it using Godep?", "y") if v == "y" { diff --git a/cmd/version.go b/cmd/version.go index 39219b0..f40d19e 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -const VERSION = "1.0.5" +const VERSION = "1.1.0" // versionCmd represents the version command var versionCmd = &cobra.Command{ @@ -14,7 +14,7 @@ var versionCmd = &cobra.Command{ Short: "Version of Mercurius", Long: `Version of Mercurius`, Run: func(cmd *cobra.Command, args []string) { - //print version of mercurius + // print version of mercurius fmt.Println("Mercurius version", VERSION) }, } diff --git a/go.mod b/go.mod index 391bc5e..9fd6b02 100644 --- a/go.mod +++ b/go.mod @@ -1,29 +1,31 @@ module github.com/novatrixtech/mercurius -go 1.17 +go 1.19 require ( github.com/fatih/color v1.13.0 - github.com/spf13/cobra v1.3.0 - github.com/spf13/viper v1.10.1 + github.com/spf13/cobra v1.5.0 + github.com/spf13/viper v1.13.0 ) require ( - github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/magiconair/properties v1.8.5 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mitchellh/mapstructure v1.4.3 // indirect - github.com/pelletier/go-toml v1.9.4 // indirect - github.com/spf13/afero v1.6.0 // indirect - github.com/spf13/cast v1.4.1 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/spf13/afero v1.9.2 // indirect + github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.2.0 // indirect - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + github.com/subosito/gotenv v1.4.1 // indirect + golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 // indirect golang.org/x/text v0.3.7 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/skeleton/app.yaml.template b/skeleton/app.yaml.template index eb1cfe8..c037c28 100644 --- a/skeleton/app.yaml.template +++ b/skeleton/app.yaml.template @@ -1 +1 @@ -runtime: go114 \ No newline at end of file +runtime: go119 \ No newline at end of file diff --git a/skeleton/conf/dbconfig.go.template b/skeleton/conf/dbconfig.go.template index 052465a..26e9951 100644 --- a/skeleton/conf/dbconfig.go.template +++ b/skeleton/conf/dbconfig.go.template @@ -106,7 +106,7 @@ func DSN() string { LoadDbConfig - Loads specific database connection information */ func LoadDbConfig() (dbConnectionInfo *DbConnInfo) { - if len(os.Getenv("db_type")) < 1 { + if !isDbConnParamsInEnvVariables() { dbConnectionInfo = &DbConnInfo{ DBType: Cfg.Section("").Key("db_type").Value(), User: Cfg.Section("").Key("db_user").Value(), @@ -128,10 +128,7 @@ func LoadDbConfig() (dbConnectionInfo *DbConnInfo) { return } -//checks if db config data is coming from environment variables +// checks if db config data is coming from environment variables func isDbConnParamsInEnvVariables() bool { - if len(os.Getenv("db_type")) > 1 { - return true - } - return false -} \ No newline at end of file + return len(os.Getenv("db_type")) > 1 +} diff --git a/skeleton/conf/env.go.template b/skeleton/conf/env.go.template index bcaae46..13d68f7 100644 --- a/skeleton/conf/env.go.template +++ b/skeleton/conf/env.go.template @@ -12,7 +12,10 @@ var Cfg *ini.File // find configuration file func init() { var err error - Cfg, err = macaron.SetConfig("conf/app.ini") + var appIniLocation string + flag.StringVar(&appIniLocation, "appIni", "conf/app.ini", "defines where the app initialization config location (app.ini) is") + flag.Parse() + Cfg, err = macaron.SetConfig(appIniLocation) if err != nil { if isDbConnParamsInEnvVariables() { log.Printf("[conf/Init] Error during app.ini reading. Error: %s\n", err.Error()) @@ -20,4 +23,4 @@ func init() { log.Fatalf("[conf/Init] Error during app.ini reading. Error: %s\n", err.Error()) } } -} +} \ No newline at end of file diff --git a/skeleton/go.mod.template b/skeleton/go.mod.template index 49c5b66..7884de6 100644 --- a/skeleton/go.mod.template +++ b/skeleton/go.mod.template @@ -1,3 +1,3 @@ module {{.AppPath}} -go 1.17 +go 1.19 diff --git a/skeleton/lib/auth/handler.go.template b/skeleton/lib/auth/handler.go.template index b409f72..1db4a41 100644 --- a/skeleton/lib/auth/handler.go.template +++ b/skeleton/lib/auth/handler.go.template @@ -141,7 +141,6 @@ func GetOauthUserCredentials(ctx *contx.Context) { user.ClientID = clientID user.Secret = secret ctx.JSON(http.StatusCreated, user) - return } //CheckFormUserCredentials handle user's authentication via Login Form diff --git a/skeleton/lib/auth/helper.go.template b/skeleton/lib/auth/helper.go.template index 44380d0..b77ba5a 100644 --- a/skeleton/lib/auth/helper.go.template +++ b/skeleton/lib/auth/helper.go.template @@ -14,9 +14,9 @@ import ( "github.com/novatrixtech/cryptonx" ) -func decodeClientID(origem string) (texto string, err error) { +func decodeClientID(origin string) (texto string, err error) { err = nil - tmp, err := hex.DecodeString(origem) + tmp, err := hex.DecodeString(origin) if err != nil { log.Println("[decodeClientID] Error decoding clientID: ", origin, " - Error: ", err.Error()) return @@ -28,7 +28,7 @@ func decodeClientID(origem string) (texto string, err error) { func getDataFromClientID(clientIDDecoded string) (contactName string, nonce string, err error) { err = nil if !strings.Contains(clientIDDecoded, "|") { - err = errors.New("ClientID inválido. Não há o pipe, portanto não há como obter o nonce") + err = errors.New("Invalid ClientID. Não há o pipe, portanto não há como obter o nonce") return } tmpClientID := strings.Split(clientIDDecoded, "|") @@ -37,9 +37,9 @@ func getDataFromClientID(clientIDDecoded string) (contactName string, nonce stri return } -func decodeSecret(origem string, nonce string) (texto string, err error) { +func decodeSecret(origin string, nonce string) (texto string, err error) { err = nil - texto, err = cryptonx.Decrypter(conf.Cfg.Section("").Key("oauth_key").Value(), nonce, origem) + texto, err = cryptonx.Decrypter(conf.Cfg.Section("").Key("oauth_key").Value(), nonce, origin) if err != nil { log.Println("[decodeSecret] Error decoding the secret: ", origin, " - Error: ", err.Error()) return @@ -50,50 +50,55 @@ func decodeSecret(origem string, nonce string) (texto string, err error) { func getAndValidateDataFromSecret(secret string) (data time.Time, contatoID int, IP string, err error) { err = nil if !strings.Contains(secret, "|") { - err = errors.New("Secret inválido. Não há o pipe, portanto não há como obter o nonce") + err = errors.New("[getAndValidateDataFromSecret] invalid secret. No pipe, then there is no way to get the nonce") return } tmp := strings.Split(secret, "|") if len(tmp) < 3 { - err = errors.New("Secret inválido. Não há elementos suficientes nos dados") + err = errors.New("[getAndValidateDataFromSecret] invalid secret. Não há elementos suficientes nos dados") return } dataNum, err := strconv.ParseInt(tmp[0], 10, 64) if err != nil { - log.Println("[getInfoFromSecret] Error parsing timestamp: ", tmp[0], " - Error: ", err.Error()) + log.Println("[getAndValidateDataFromSecret] Error parsing timestamp: ", tmp[0], " - Error: ", err.Error()) return } - if dataNum < 1505740412 { - err = errors.New("Secret inválido. Data definida é menor que 2017-09-17") + threeDaysLimit, err := time.ParseDuration("36h") + if err != nil { + log.Println("[getAndValidateDataFromSecret] Error parsing 36h duation. Error: ", err.Error()) + return + } + if dataNum < int64(threeDaysLimit) { + err = errors.New("[getAndValidateDataFromSecret] invalid secret. Data definida é menor que 2017-09-17") return } data, err = parseDateFromUnixTimestamp(tmp[0]) if err != nil { - log.Println("[getInfoFromSecret] Error parsing data: ", tmp[0], " - Error: ", err.Error()) + log.Println("[getAndValidateDataFromSecret] Error parsing data: ", tmp[0], " - Error: ", err.Error()) return } contatoID, err = strconv.Atoi(tmp[1]) if err != nil { - log.Println("[getInfoFromSecret] Error parsing contatoID: ", tmp[1], " - Error: ", err.Error()) + log.Println("[getAndValidateDataFromSecret] Error parsing contatoID: ", tmp[1], " - Error: ", err.Error()) return } if contatoID < 1 { - err = errors.New("ContatoID inválido") + err = errors.New("[getAndValidateDataFromSecret] invalid contatoID") return } if len(tmp[2]) < 3 { - err = errors.New("IP invalid. Not enough items") - log.Println("[getInfoFromSecret] ", tmp[2], " - Error: ", err.Error()) + err = errors.New("[getAndValidateDataFromSecret] IP invalid. Not enough items") + log.Println("[getAndValidateDataFromSecret] ", tmp[2], " - Error: ", err.Error()) return } IP = tmp[2] return } -func parseDateFromUnixTimestamp(origem string) (data time.Time, err error) { +func parseDateFromUnixTimestamp(origin string) (data time.Time, err error) { err = nil - i, err := strconv.ParseInt(origem, 10, 64) + i, err := strconv.ParseInt(origin, 10, 64) if err != nil { log.Println("[parseDateFromUnixTimestamp] Error parsing timestamp: ", origin, " - Error: ", err.Error()) return @@ -130,27 +135,27 @@ func decodeClientIDAndSecret(clientID string, secret string) { func generateUserCredentials(user User, remoteAddr string) (clientID string, secret string, err error) { err = nil - nomeContatoOrigem := strings.Replace(user.Name, " ", "", -1) - dataOrigem := time.Now().Unix() + nomeContatoorigin := strings.Replace(user.Name, " ", "", -1) + dataorigin := time.Now().Unix() ip, _, err := net.SplitHostPort(remoteAddr) if err != nil { //return nil, fmt.Errorf("userip: %q is not IP:port", req.RemoteAddr) log.Printf("[generateUserCredentials] Error splitting host and port. userip: %q is not IP:port", remoteAddr) } - ipRemotoOrigem := net.ParseIP(ip) - if ipRemotoOrigem == nil { + ipRemotoorigin := net.ParseIP(ip) + if ipRemotoorigin == nil { errStr := fmt.Sprintf("[generateUserCredentials] Error parsing userip: %q is not IP:port", ip) log.Println(errStr) err = errors.New(errStr) return } - secretAntesCrypto := strconv.Itoa(int(dataOrigem)) + "|" + strconv.Itoa(user.ID) + "|" + ipRemotoOrigem.String() + secretAntesCrypto := strconv.Itoa(int(dataorigin)) + "|" + strconv.Itoa(user.ID) + "|" + ipRemotoorigin.String() secret, nonce, err := cryptonx.Encrypter(conf.Cfg.Section("").Key("oauth_key").Value(), secretAntesCrypto) if err != nil { log.Println("[GenerateCredentials] Error encrypting text: ", err.Error()) return } - clientIDOrigem := nomeContatoOrigem + "|" + nonce - clientID = hex.EncodeToString([]byte(clientIDOrigem)) + clientIDorigin := nomeContatoorigin + "|" + nonce + clientID = hex.EncodeToString([]byte(clientIDorigin)) return } diff --git a/skeleton/lib/auth/token.go.template b/skeleton/lib/auth/token.go.template index 7b47dc1..1db5062 100644 --- a/skeleton/lib/auth/token.go.template +++ b/skeleton/lib/auth/token.go.template @@ -81,7 +81,7 @@ func ClientEncrypter(key, appName, appID string) (clientID, clientSecret string, func parse(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, errors.New("Unexpected Signing method") + return nil, errors.New("[parse] unexpected Signing method") } return []byte(conf.Cfg.Section("").Key("oauth_key").Value()), nil } diff --git a/skeleton/lib/auth/verfier.go.template b/skeleton/lib/auth/verfier.go.template index 68a807b..72a9e12 100644 --- a/skeleton/lib/auth/verfier.go.template +++ b/skeleton/lib/auth/verfier.go.template @@ -15,13 +15,13 @@ func ValidateAuthorizationHeader(authHeader http.Header, funcName string, rolesA var ac string items, ok := authHeader["Authorization"] if !ok || len(items) < 1 { - err = errors.New("Cabeçalho de autorização não encontrado") + err = errors.New("[ValidateAuthorizationHeader] Authorization header not found") return } ac = strings.TrimSpace(items[0]) //log.Printf("[ValidateAuthorizationHeader] AccessToken Completo: [%s]\n", ac) if !strings.Contains(ac, "Bearer") { - err = errors.New("Formato de cabeçalho de autorização invalido. Sem Bearer") + err = errors.New("[ValidateAuthorizationHeader] Authorization header invalid. No Bearer") return } ac = strings.TrimPrefix(ac, "Bearer ") @@ -29,7 +29,7 @@ func ValidateAuthorizationHeader(authHeader http.Header, funcName string, rolesA //log.Println("[ValidateAuthorizationHeader] AccessToken: ", ac) acObj, ok := AccessTokenCache[ac] if !ok { - err = errors.New("Access Token não encontrado no cache") + err = errors.New("[ValidateAuthorizationHeader] Access Token not found in cache") return } allowed := false @@ -40,11 +40,11 @@ func ValidateAuthorizationHeader(authHeader http.Header, funcName string, rolesA } } if !allowed { - err = errors.New("Access Token não tem permissão") + err = errors.New("[ValidateAuthorizationHeader] Access Token does not have permission") return } if acObj.ValidUntil < int(time.Now().Local().Unix()) { - err = errors.New("Access Token expirado") + err = errors.New("[ValidateAuthorizationHeader] Access Token is expired") return } go AddAccessTokenAccessLog(ac, funcName)