diff --git a/Makefile b/Makefile index 896f23a..5a07e04 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,37 @@ cdir = $(shell pwd) +check-lint: + which golangci-lint || (GO111MODULE=off go get -u github.com/golangci/golangci-lint/cmd/golangci-lint) + +lint: check-lint + @echo "+ $@" + @golangci-lint run -v --timeout 3m \ + --fast \ + --issues-exit-code=0 \ + --print-issued-lines=false \ + --enable=gocognit \ + --enable=gocritic \ + --enable=prealloc \ + --enable=unparam \ + --enable=nakedret \ + --enable=scopelint \ + --disable=deadcode \ + --disable=unused \ + --enable=gocyclo \ + --enable=golint \ + --enable=varcheck \ + --enable=structcheck \ + --enable=maligned \ + --enable=errcheck \ + --enable=dupl \ + --enable=ineffassign \ + --enable=interfacer \ + --enable=unconvert \ + --enable=goconst \ + --enable=gosec \ + --enable=megacheck \ + ./... + app-up: docker-compose -f ./cicd/dc_app.yml up -d --build diff --git a/cmd/main.go b/cmd/main.go index 6ab9dba..9da8201 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,20 +2,22 @@ package main import ( "fmt" - "github.com/codegangsta/martini" - "github.com/codegangsta/martini-contrib/binding" - "github.com/codegangsta/martini-contrib/render" - "github.com/codegangsta/martini-contrib/sessions" - _ "github.com/go-sql-driver/mysql" - "github.com/tiburon-777/OTUS_HighLoad/internal/application" - "github.com/tiburon-777/OTUS_HighLoad/internal/auth" - "github.com/tiburon-777/OTUS_HighLoad/internal/handlers" - "github.com/tiburon-777/OTUS_HighLoad/pkg/dataset" "log" "net" "net/http" "os" "time" + + "github.com/codegangsta/martini" + "github.com/codegangsta/martini-contrib/binding" + "github.com/codegangsta/martini-contrib/render" + "github.com/codegangsta/martini-contrib/sessions" + _ "github.com/go-sql-driver/mysql" + + "github.com/tiburon-777/OTUS_HighLoad/internal/application" + "github.com/tiburon-777/OTUS_HighLoad/internal/auth" + "github.com/tiburon-777/OTUS_HighLoad/internal/handlers" + "github.com/tiburon-777/OTUS_HighLoad/pkg/dataset" ) func init() { @@ -40,7 +42,7 @@ func main() { Extensions: []string{".tmpl"}, })) - auth.RedirectUrl = "/login" + auth.RedirectURL = "/login" auth.RedirectParam = "next" m.Get("/404", func(r render.Render) { diff --git a/internal/application/application.go b/internal/application/application.go index e00f3c6..018b8a8 100755 --- a/internal/application/application.go +++ b/internal/application/application.go @@ -3,9 +3,11 @@ package application import ( "database/sql" "fmt" - "github.com/tiburon-777/OTUS_HighLoad/internal/models" - "github.com/tiburon-777/modules/core/config" "log" + + "github.com/tiburon-777/modules/core/config" + + "github.com/tiburon-777/OTUS_HighLoad/internal/models" ) type App struct { @@ -18,7 +20,7 @@ type App struct { func New(configFile, envPrefix string) (app App, err error) { app.Config, err = configure(configFile, envPrefix) if err != nil { - return App{}, fmt.Errorf("can't apply config: %w\n", err) + return App{}, fmt.Errorf("can't apply config: %w", err) } app.DBMaster, err = sql.Open("mysql", app.Config.DSN.User+":"+app.Config.DSN.Pass+"@tcp("+app.Config.DSN.Master+":"+app.Config.DSN.Port+")/"+app.Config.DSN.Base+"?charset=utf8&collation=utf8_unicode_ci") diff --git a/internal/auth/login.go b/internal/auth/login.go index 87b3793..57ed6a9 100644 --- a/internal/auth/login.go +++ b/internal/auth/login.go @@ -2,19 +2,21 @@ package auth import ( "fmt" + "log" + "net/http" + "github.com/codegangsta/martini" "github.com/codegangsta/martini-contrib/render" "github.com/codegangsta/martini-contrib/sessions" + "github.com/tiburon-777/OTUS_HighLoad/internal/application" - "log" - "net/http" ) // These are the default configuration values for this package. They // can be set at anytime, probably during the initial setup of Martini. var ( - // RedirectUrl should be the relative URL for your login route - RedirectUrl string = "/login" + // RedirectURL should be the relative URL for your login route + RedirectURL string = "/login" // RedirectParam is the query string parameter that will be set // with the page the user was trying to visit before they were @@ -39,10 +41,10 @@ type User interface { Logout() // Return the unique identifier of this user object - UniqueId() interface{} + UniqueID() interface{} // Populate this user object with values - GetById(app application.App, id interface{}) error + GetByID(app application.App, id interface{}) error } // SessionUser will try to read a unique user ID out of the session. Then it tries @@ -53,11 +55,11 @@ type User interface { // user type. func SessionUser(newUser func() User) martini.Handler { return func(s sessions.Session, c martini.Context, l *log.Logger, app application.App) { - userId := s.Get(SessionKey) + userID := s.Get(SessionKey) user := newUser() - if userId != nil { - err := user.GetById(app, userId) + if userID != nil { + err := user.GetByID(app, userID) if err != nil { l.Printf("Login Error: %v\n", err) } else { @@ -88,8 +90,8 @@ func Logout(s sessions.Session, user User) { // authenticated, they will be redirected to /login with the "next" get parameter // set to the attempted URL. func LoginRequired(r render.Render, user User, req *http.Request) { - if user.IsAuthenticated() == false { - path := fmt.Sprintf("%s?%s=%s", RedirectUrl, RedirectParam, req.URL.Path) + if !user.IsAuthenticated() { + path := fmt.Sprintf("%s?%s=%s", RedirectURL, RedirectParam, req.URL.Path) r.Redirect(path, 302) } } @@ -97,6 +99,6 @@ func LoginRequired(r render.Render, user User, req *http.Request) { // UpdateUser updates the User object stored in the session. This is useful incase a change // is made to the user model that needs to persist across requests. func UpdateUser(s sessions.Session, user User) error { - s.Set(SessionKey, user.UniqueId()) + s.Set(SessionKey, user.UniqueID()) return nil } diff --git a/internal/auth/user.go b/internal/auth/user.go index 8650a27..b5e2cee 100644 --- a/internal/auth/user.go +++ b/internal/auth/user.go @@ -2,12 +2,13 @@ package auth import ( "fmt" - "github.com/tiburon-777/OTUS_HighLoad/internal/application" "time" + + "github.com/tiburon-777/OTUS_HighLoad/internal/application" ) type UserModel struct { - Id int64 `db:"id" form:"id"` + ID int64 `db:"id" form:"id"` Username string `db:"username" form:"username"` Password string `db:"password" form:"password"` Name string `db:"name" form:"name"` @@ -45,11 +46,11 @@ func (u *UserModel) IsAuthenticated() bool { return u.authenticated } -func (u *UserModel) UniqueId() interface{} { - return u.Id +func (u *UserModel) UniqueID() interface{} { + return u.ID } -func (u *UserModel) GetById(app application.App, id interface{}) error { +func (u *UserModel) GetByID(app application.App, id interface{}) error { var v string query := fmt.Sprintf("SELECT username, name, surname, birthdate, gender, city, interests FROM users WHERE id=%d", id) err := app.DBMaster.QueryRow(query).Scan(&u.Username, &u.Name, &u.Surname, &v, &u.Gender, &u.City, &u.Interests) @@ -60,6 +61,6 @@ func (u *UserModel) GetById(app application.App, id interface{}) error { if err != nil { return err } - u.Id = id.(int64) + u.ID = id.(int64) return nil } diff --git a/internal/handlers/friends.go b/internal/handlers/friends.go index 02e8168..86fa87d 100644 --- a/internal/handlers/friends.go +++ b/internal/handlers/friends.go @@ -1,10 +1,12 @@ package handlers import ( + "time" + "github.com/codegangsta/martini-contrib/render" + "github.com/tiburon-777/OTUS_HighLoad/internal/application" "github.com/tiburon-777/OTUS_HighLoad/internal/auth" - "time" ) func GetFeed(app application.App, r render.Render, user auth.User) { @@ -16,7 +18,7 @@ func GetFeed(app application.App, r render.Render, user auth.User) { var post Post var posts []Post var results, err = app.DBMaster.Query(`SELECT - posts.Id AS Id, + posts.ID AS Id, users.Username AS Author, posts.Created AS Created, posts.Subject AS Subject, @@ -28,13 +30,13 @@ func GetFeed(app application.App, r render.Render, user auth.User) { AND posts.Author=relations.friendId AND relations.userId=? ORDER by Created DESC`, - user.(*auth.UserModel).Id) + user.(*auth.UserModel).ID) if err != nil || results == nil { err500("can't get feed from DB: ", err, r) } defer results.Close() for results.Next() { - err = results.Scan(&post.Id, &post.Author, &tmpTime, &post.Subject, &post.Body) + err = results.Scan(&post.ID, &post.Author, &tmpTime, &post.Subject, &post.Body) if err != nil { err500("can't scan result from DB: ", err, r) } diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index afb4e99..65cd3a2 100755 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -2,19 +2,22 @@ package handlers import ( "fmt" - "github.com/codegangsta/martini-contrib/render" - "github.com/codegangsta/martini-contrib/sessions" - _ "github.com/go-sql-driver/mysql" - "github.com/tiburon-777/OTUS_HighLoad/internal/application" - "github.com/tiburon-777/OTUS_HighLoad/internal/auth" - "golang.org/x/crypto/bcrypt" "log" "net/http" "time" + + "github.com/codegangsta/martini-contrib/render" + "github.com/codegangsta/martini-contrib/sessions" + "golang.org/x/crypto/bcrypt" + // MySQL driver + _ "github.com/go-sql-driver/mysql" + + "github.com/tiburon-777/OTUS_HighLoad/internal/application" + "github.com/tiburon-777/OTUS_HighLoad/internal/auth" ) type Post struct{ - Id int `db:"Id"` + ID int `db:"Id"` Author string `db:"Author"` Created time.Time `db:"Created"` Subject string `db:"Subject"` @@ -42,13 +45,13 @@ func GetHome(app application.App, r render.Render, user auth.User) { relations.friendId=users.Id AND relations.userId=? GROUP BY users.Id`, - user.(*auth.UserModel).Id) + user.(*auth.UserModel).ID) if err != nil || results == nil { err500("can't get user list from DB: ", err, r) } defer results.Close() for results.Next() { - err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City) + err = results.Scan(&tmp.ID, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City) if err != nil { err500("can't scan result from DB: ", err, r) } @@ -60,13 +63,13 @@ func GetHome(app application.App, r render.Render, user auth.User) { var post Post var posts []Post - results, err = app.DBMaster.Query(`SELECT Id, Created, Subject, Body FROM posts WHERE Author=? ORDER BY Created DESC;`, user.(*auth.UserModel).Id) + results, err = app.DBMaster.Query(`SELECT Id, Created, Subject, Body FROM posts WHERE Author=? ORDER BY Created DESC;`, user.(*auth.UserModel).ID) if err != nil || results == nil { err500("can't get user list from DB: ", err, r) } defer results.Close() for results.Next() { - err = results.Scan(&post.Id, &tmpTime, &post.Subject, &post.Body) + err = results.Scan(&post.ID, &tmpTime, &post.Subject, &post.Body) if err != nil { err500("can't scan result from DB: ", err, r) } @@ -122,25 +125,24 @@ func PostSignup(app application.App, postedUser auth.UserModel, r render.Render) func PostLogin(app application.App, session sessions.Session, postedUser auth.UserModel, r render.Render, req *http.Request) { user := auth.UserModel{} - err1 := app.DBMaster.QueryRow("SELECT id, password FROM users WHERE username=?", postedUser.Username).Scan(&user.Id, &user.Password) + err1 := app.DBMaster.QueryRow("SELECT id, password FROM users WHERE username=?", postedUser.Username).Scan(&user.ID, &user.Password) err2 := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(postedUser.Password)) if err1 != nil || err2 != nil { doc := map[string]interface{}{ "msg": "Wrong user or password. You may sign in.", } r.HTML(200, "login", doc) - r.Redirect(auth.RedirectUrl) - return - } else { - err := auth.AuthenticateSession(session, &user) - if err != nil { - err500("can't auth session: ", err, r) - } - params := req.URL.Query() - redirect := params.Get(auth.RedirectParam) - r.Redirect(redirect) + r.Redirect(auth.RedirectURL) return } + err := auth.AuthenticateSession(session, &user) + if err != nil { + err500("can't auth session: ", err, r) + } + params := req.URL.Query() + redirect := params.Get(auth.RedirectParam) + r.Redirect(redirect) + return } func str2Time(s string, r render.Render) time.Time { @@ -152,7 +154,7 @@ func str2Time(s string, r render.Render) time.Time { } func err500(s string, err error, r render.Render) { - e := fmt.Errorf("s% %w", s, err) + e := fmt.Errorf("%s %w", s, err) log.Println(e) doc := map[string]interface{}{ "Error": e, diff --git a/internal/handlers/postAdd.go b/internal/handlers/postAdd.go index 2343cf8..aca2894 100644 --- a/internal/handlers/postAdd.go +++ b/internal/handlers/postAdd.go @@ -1,11 +1,13 @@ package handlers import ( - "github.com/codegangsta/martini-contrib/render" - "github.com/tiburon-777/OTUS_HighLoad/internal/application" - "github.com/tiburon-777/OTUS_HighLoad/internal/auth" "net/http" "time" + + "github.com/codegangsta/martini-contrib/render" + + "github.com/tiburon-777/OTUS_HighLoad/internal/application" + "github.com/tiburon-777/OTUS_HighLoad/internal/auth" ) func GetAddPost(app application.App, r render.Render) { @@ -17,7 +19,7 @@ func PostAddPost(app application.App, user auth.User, r render.Render, req *http postBody := req.FormValue("body") var results, err = app.DBMaster.Query(`INSERT INTO posts (Author, Created, Subject, Body) VALUES ( ?, ?, ?, ?)`, - user.(*auth.UserModel).Id, + user.(*auth.UserModel).ID, time.Now().Format("2006-01-02 15:04:05"), postSubj, postBody, diff --git a/internal/handlers/userList.go b/internal/handlers/userList.go index 1f0a44e..f8a7190 100644 --- a/internal/handlers/userList.go +++ b/internal/handlers/userList.go @@ -1,11 +1,13 @@ package handlers import ( - "github.com/codegangsta/martini-contrib/render" - "github.com/tiburon-777/OTUS_HighLoad/internal/application" - "github.com/tiburon-777/OTUS_HighLoad/internal/auth" "net/http" "time" + + "github.com/codegangsta/martini-contrib/render" + + "github.com/tiburon-777/OTUS_HighLoad/internal/application" + "github.com/tiburon-777/OTUS_HighLoad/internal/auth" ) func GetUserList(app application.App, r render.Render) { @@ -46,8 +48,8 @@ func PostUserList(app application.App, user auth.User, r render.Render, req *htt WHERE relations.userId=?) AND ( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`, - user.(*auth.UserModel).Id, - user.(*auth.UserModel).Id, + user.(*auth.UserModel).ID, + user.(*auth.UserModel).ID, postName, postSurname, ) @@ -56,7 +58,7 @@ func PostUserList(app application.App, user auth.User, r render.Render, req *htt } defer results.Close() for results.Next() { - err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City) + err = results.Scan(&tmp.ID, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City) if err != nil { err500("can't scan result from DB: ", err, r) } @@ -109,7 +111,7 @@ func PostUserSearch(app application.App, r render.Render, req *http.Request) { } defer results.Close() for results.Next() { - err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City) + err = results.Scan(&tmp.ID, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City) if err != nil { err500("can't scan result from DB: ", err, r) } diff --git a/internal/handlers/userSubscribing.go b/internal/handlers/userSubscribing.go index 6613220..a623855 100644 --- a/internal/handlers/userSubscribing.go +++ b/internal/handlers/userSubscribing.go @@ -1,11 +1,13 @@ package handlers import ( - "github.com/codegangsta/martini-contrib/render" - "github.com/tiburon-777/OTUS_HighLoad/internal/application" - "github.com/tiburon-777/OTUS_HighLoad/internal/auth" "net/http" "strconv" + + "github.com/codegangsta/martini-contrib/render" + + "github.com/tiburon-777/OTUS_HighLoad/internal/application" + "github.com/tiburon-777/OTUS_HighLoad/internal/auth" ) func GetSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) { @@ -17,11 +19,11 @@ func GetSubscribe(app application.App, r render.Render, user auth.User, req *htt if err != nil { err500("can't convert URL query value: ", err, r) } - _, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).Id, did) + _, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).ID, did) if err != nil { err500("can't create relation in DB: ", err, r) } - _, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).Id) + _, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).ID) if err != nil { err500("can't create relation in DB: ", err, r) } @@ -37,7 +39,7 @@ func GetUnSubscribe(app application.App, r render.Render, user auth.User, req *h if err != nil { err500("can't convert URL query value: ", err, r) } - _, err = app.DBMaster.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).Id, did, did, user.(*auth.UserModel).Id) + _, err = app.DBMaster.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).ID, did, did, user.(*auth.UserModel).ID) if err != nil { err500("can't remove relation from DB: ", err, r) } diff --git a/pkg/dataset/generator.go b/pkg/dataset/generator.go index 8ecb784..ab761a9 100644 --- a/pkg/dataset/generator.go +++ b/pkg/dataset/generator.go @@ -2,12 +2,13 @@ package dataset import ( "database/sql" - "github.com/mdigger/translit" "log" "math/rand" "strconv" "strings" "time" + + "github.com/mdigger/translit" ) type Person struct { @@ -53,7 +54,7 @@ func FillDB(db *sql.DB, lim int) { } uCount = lim - uCount if uCount <= 0 { - log.Printf("Ok. We have more users then %s.", lim) + log.Printf("Ok. We have more users then %d.", lim) } log.Printf("Try to generate %d rows and fill the DB...", uCount) for i := 1; i < uCount; i++ {