[MAINT] initial work on linter setup (#16)

* initial work on linter setup

* simple linter rules fixed
This commit is contained in:
Enver Bisevac 2022-09-13 00:08:43 +02:00 committed by GitHub
parent f58ceac474
commit ca8aa47e05
31 changed files with 234 additions and 226 deletions

View File

@ -35,7 +35,7 @@ tools: $(tools) ## Install tools required for the build
mocks: $(mocks)
@echo "Generating Test Mocks"
generate: $(mocks) wire_gen.go mocks/mock_client.go
generate: $(mocks) cli/server/wire_gen.go mocks/mock_client.go
@echo "Generating Code"
build: generate ## Build the gitness service binary
@ -114,7 +114,7 @@ lint: tools generate # lint the golang code
# Some code generation can be slow, so we only run it if
# the source file has changed.
###########################################
wire_gen.go: cli/server/wire.go ## Update the wire dependency injection if wire.go has changed.
cli/server/wire_gen.go: cli/server/wire.go ## Update the wire dependency injection if wire.go has changed.
@echo "Updating wire_gen.go"
go generate ./cli/server/wire_gen.go

View File

@ -5,7 +5,6 @@
package cli
import (
"context"
"os"
"github.com/harness/gitness/cli/server"
@ -17,9 +16,6 @@ import (
"gopkg.in/alecthomas/kingpin.v2"
)
// empty context
var nocontext = context.Background()
// application name
var application = "gitness"

View File

@ -25,7 +25,10 @@ type command struct {
func (c *command) run(*kingpin.ParseContext) error {
// load environment variables from file.
godotenv.Load(c.envfile)
err := godotenv.Load(c.envfile)
if err != nil {
return err
}
// create the system configuration store by loading
// data from the environment.

View File

@ -51,7 +51,9 @@ func (c *listCommand) run(*kingpin.ParseContext) error {
return enc.Encode(list)
}
for _, item := range list {
tmpl.Execute(os.Stdout, item)
if err = tmpl.Execute(os.Stdout, item); err != nil {
return err
}
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"golang.org/x/term"
"io/ioutil"
"os"
"path/filepath"
@ -20,7 +21,6 @@ import (
"github.com/harness/gitness/types"
"github.com/adrg/xdg"
"golang.org/x/crypto/ssh/terminal"
)
// Client returns a client that is configured from file.
@ -72,7 +72,7 @@ func Username() string {
// Password returns the password from stdin.
func Password() string {
fmt.Print("Enter Password: ")
passwordb, _ := terminal.ReadPassword(int(syscall.Stdin))
passwordb, _ := term.ReadPassword(int(syscall.Stdin))
password := string(passwordb)
return strings.TrimSpace(password)

View File

@ -8,6 +8,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/rs/zerolog/log"
"io"
"net/http"
"net/http/httputil"
@ -150,11 +151,6 @@ func (c *HTTPClient) post(rawurl string, in, out interface{}) error {
return c.do(rawurl, "POST", in, out)
}
// helper function for making an http PUT request.
func (c *HTTPClient) put(rawurl string, in, out interface{}) error {
return c.do(rawurl, "PUT", in, out)
}
// helper function for making an http PATCH request.
func (c *HTTPClient) patch(rawurl string, in, out interface{}) error {
return c.do(rawurl, "PATCH", in, out)
@ -199,7 +195,9 @@ func (c *HTTPClient) stream(rawurl, method string, in, out interface{}) (io.Read
buf = new(bytes.Buffer)
// if posting form data, encode the form values.
if form, ok := in.(*url.Values); ok {
io.WriteString(buf, form.Encode())
if _, err := io.WriteString(buf, form.Encode()); err != nil {
log.Err(err).Msg("in stream method")
}
} else {
if err := json.NewEncoder(buf).Encode(in); err != nil {
return nil, err
@ -239,7 +237,9 @@ func (c *HTTPClient) stream(rawurl, method string, in, out interface{}) (io.Read
if resp.StatusCode > 299 {
defer resp.Body.Close()
err := new(remoteError)
json.NewDecoder(resp.Body).Decode(err)
if decodeErr := json.NewDecoder(resp.Body).Decode(err); decodeErr != nil {
return nil, decodeErr
}
return nil, err
}
return resp.Body, nil

View File

@ -33,7 +33,9 @@ func TestFind(t *testing.T) {
}
got, want := &types.User{}, mockUser
json.NewDecoder(w.Body).Decode(got)
if err := json.NewDecoder(w.Body).Decode(got); err != nil {
t.Error(err)
}
if diff := cmp.Diff(got, want); len(diff) != 0 {
t.Errorf(diff)
}

View File

@ -38,7 +38,9 @@ func TestToken(t *testing.T) {
}
result := &types.Token{}
json.NewDecoder(w.Body).Decode(&result)
if err := json.NewDecoder(w.Body).Decode(&result); err != nil {
t.Error(err)
}
_, err := jwt.Parse(result.Value, func(token *jwt.Token) (interface{}, error) {
return []byte(mockUser.Salt), nil

View File

@ -56,7 +56,7 @@ func TestUpdate(t *testing.T) {
users.EXPECT().Update(gomock.Any(), before)
in := new(bytes.Buffer)
json.NewEncoder(in).Encode(userInput)
_ = json.NewEncoder(in).Encode(userInput)
w := httptest.NewRecorder()
r := httptest.NewRequest("PATCH", "/api/v1/user", in)
r = r.WithContext(
@ -81,7 +81,9 @@ func TestUpdate(t *testing.T) {
// Password hash is not exposecd to JSON
}
got, want := new(types.User), after
json.NewDecoder(w.Body).Decode(got)
if err := json.NewDecoder(w.Body).Decode(got); err != nil {
t.Error(err)
}
if diff := cmp.Diff(got, want); len(diff) != 0 {
t.Errorf(diff)
}
@ -108,7 +110,7 @@ func TestUpdate_HashError(t *testing.T) {
}
in := new(bytes.Buffer)
json.NewEncoder(in).Encode(userInput)
_ = json.NewEncoder(in).Encode(userInput)
w := httptest.NewRecorder()
r := httptest.NewRequest("PATCH", "/api/v1/user", in)
r = r.WithContext(
@ -121,7 +123,9 @@ func TestUpdate_HashError(t *testing.T) {
}
got := new(render.Error)
json.NewDecoder(w.Body).Decode(got)
if err := json.NewDecoder(w.Body).Decode(got); err != nil {
t.Error(err)
}
if diff := cmp.Diff(got.Message, render.ErrInternal.Message); len(diff) != 0 {
t.Errorf(diff)
}
@ -152,7 +156,9 @@ func TestUpdate_BadRequest(t *testing.T) {
}
got := new(render.Error)
json.NewDecoder(w.Body).Decode(got)
if err := json.NewDecoder(w.Body).Decode(got); err != nil {
t.Error(err)
}
if diff := cmp.Diff(got.Message, "Invalid request body: EOF."); len(diff) != 0 {
t.Errorf(diff)
}
@ -176,7 +182,7 @@ func TestUpdate_ServerError(t *testing.T) {
users.EXPECT().Update(gomock.Any(), user).Return(render.ErrNotFound)
in := new(bytes.Buffer)
json.NewEncoder(in).Encode(userInput)
_ = json.NewEncoder(in).Encode(userInput)
w := httptest.NewRecorder()
r := httptest.NewRequest("PATCH", "/api/v1/user", in)
r = r.WithContext(
@ -189,7 +195,9 @@ func TestUpdate_ServerError(t *testing.T) {
}
got, want := new(render.Error), render.ErrInternal
json.NewDecoder(w.Body).Decode(got)
if err := json.NewDecoder(w.Body).Decode(got); err != nil {
t.Error(err)
}
if diff := cmp.Diff(got, want); len(diff) != 0 {
t.Errorf(diff)
}

View File

@ -32,19 +32,19 @@ func buildAccount(reflector *openapi3.Reflector) {
onLogin := openapi3.Operation{}
onLogin.WithTags("account")
onLogin.WithMapOfAnything(map[string]interface{}{"operationId": "onLogin"})
reflector.SetRequest(&onLogin, new(loginRequest), http.MethodPost)
reflector.SetJSONResponse(&onLogin, new(types.Token), http.StatusOK)
reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodPost, "/login", onLogin)
_ = reflector.SetRequest(&onLogin, new(loginRequest), http.MethodPost)
_ = reflector.SetJSONResponse(&onLogin, new(types.Token), http.StatusOK)
_ = reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodPost, "/login", onLogin)
onRegister := openapi3.Operation{}
onRegister.WithTags("account")
onRegister.WithMapOfAnything(map[string]interface{}{"operationId": "onRegister"})
reflector.SetRequest(&onRegister, new(registerRequest), http.MethodPost)
reflector.SetJSONResponse(&onRegister, new(types.Token), http.StatusOK)
reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusBadRequest)
reflector.Spec.AddOperation(http.MethodPost, "/register", onRegister)
_ = reflector.SetRequest(&onRegister, new(registerRequest), http.MethodPost)
_ = reflector.SetJSONResponse(&onRegister, new(types.Token), http.StatusOK)
_ = reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusBadRequest)
_ = reflector.Spec.AddOperation(http.MethodPost, "/register", onRegister)
}

View File

@ -5,10 +5,6 @@
package openapi
import (
"bytes"
"net/http"
"strings"
"github.com/harness/gitness/version"
"github.com/swaggest/openapi-go/openapi3"
@ -29,37 +25,38 @@ type (
Size int `query:"per_page" default:"100"`
}
// base response for pagination
paginationResponse struct {
Total int `header:"x-total"`
Pagelen int `header:"x-total-pages"`
Page int `header:"x-page"`
Size int `header:"x-per-page"`
Next int `header:"x-next"`
Prev int `header:"x-prev"`
Link []string `header:"Link"`
}
// TODO: base response for pagination
//paginationResponse struct {
// Total int `header:"x-total"`
// Pagelen int `header:"x-total-pages"`
// Page int `header:"x-page"`
// Size int `header:"x-per-page"`
// Next int `header:"x-next"`
// Prev int `header:"x-prev"`
// Link []string `header:"Link"`
//}
)
// Handler returns an http.HandlerFunc that writes the openapi v3
// specification file to the http.Response body.
func Handler() http.HandlerFunc {
spec := Generate()
yaml, _ := spec.MarshalYAML()
json, _ := spec.MarshalJSON()
yaml = normalize(yaml)
json = normalize(json)
return func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.URL.Path, ".json"):
w.Write(json)
default:
w.Write(yaml)
}
}
}
// TODO: unused function
//func Handler() http.HandlerFunc {
// spec := Generate()
// yaml, _ := spec.MarshalYAML()
// json, _ := spec.MarshalJSON()
//
// yaml = normalize(yaml)
// json = normalize(json)
//
// return func(w http.ResponseWriter, r *http.Request) {
// switch {
// case strings.HasSuffix(r.URL.Path, ".json"):
// w.Write(json)
// default:
// w.Write(yaml)
// }
// }
//}
// Generate is a helper function that constructs the
// openapi specification object, which can be marshaled
@ -108,10 +105,11 @@ func Generate() *openapi3.Spec {
// helper function normalizes the output to ensure
// automatically-generated names are more user friendly.
func normalize(data []byte) []byte {
data = bytes.ReplaceAll(data, []byte("Types"), []byte(""))
data = bytes.ReplaceAll(data, []byte("Openapi"), []byte(""))
data = bytes.ReplaceAll(data, []byte("FormData"), []byte(""))
data = bytes.ReplaceAll(data, []byte("RenderError"), []byte("Error"))
return data
}
// TODO: unused function
//func normalize(data []byte) []byte {
// data = bytes.ReplaceAll(data, []byte("Types"), []byte(""))
// data = bytes.ReplaceAll(data, []byte("Openapi"), []byte(""))
// data = bytes.ReplaceAll(data, []byte("FormData"), []byte(""))
// data = bytes.ReplaceAll(data, []byte("RenderError"), []byte("Error"))
// return data
//}

View File

@ -25,32 +25,32 @@ func buildUser(reflector *openapi3.Reflector) {
opFind := openapi3.Operation{}
opFind.WithTags("user")
opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUser"})
reflector.SetRequest(&opFind, nil, http.MethodGet)
reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodGet, "/user", opFind)
_ = reflector.SetRequest(&opFind, nil, http.MethodGet)
_ = reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK)
_ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError)
_ = reflector.Spec.AddOperation(http.MethodGet, "/user", opFind)
opUpdate := openapi3.Operation{}
opUpdate.WithTags("user")
opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUser"})
reflector.SetRequest(&opUpdate, new(types.UserInput), http.MethodPatch)
reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodPatch, "/user", opUpdate)
_ = reflector.SetRequest(&opUpdate, new(types.UserInput), http.MethodPatch)
_ = reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK)
_ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError)
_ = reflector.Spec.AddOperation(http.MethodPatch, "/user", opUpdate)
opToken := openapi3.Operation{}
opToken.WithTags("user")
opToken.WithMapOfAnything(map[string]interface{}{"operationId": "createToken"})
reflector.SetRequest(&opToken, new(types.Token), http.MethodPost)
reflector.SetJSONResponse(&opToken, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opToken, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodPost, "/user/token", opToken)
_ = reflector.SetRequest(&opToken, new(types.Token), http.MethodPost)
_ = reflector.SetJSONResponse(&opToken, new(types.User), http.StatusOK)
_ = reflector.SetJSONResponse(&opToken, new(render.Error), http.StatusInternalServerError)
_ = reflector.Spec.AddOperation(http.MethodPost, "/user/token", opToken)
opCurrent := openapi3.Operation{}
opCurrent.WithTags("user")
opCurrent.WithMapOfAnything(map[string]interface{}{"operationId": "getCurrentUser"})
reflector.SetRequest(&opFind, new(baseRequest), http.MethodGet)
reflector.SetJSONResponse(&opCurrent, new(currentUserResponse), http.StatusOK)
reflector.SetJSONResponse(&opCurrent, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodGet, "/api/user/currentUser", opCurrent)
_ = reflector.SetRequest(&opFind, new(baseRequest), http.MethodGet)
_ = reflector.SetJSONResponse(&opCurrent, new(currentUserResponse), http.StatusOK)
_ = reflector.SetJSONResponse(&opCurrent, new(render.Error), http.StatusInternalServerError)
_ = reflector.Spec.AddOperation(http.MethodGet, "/api/user/currentUser", opCurrent)
}

View File

@ -44,49 +44,49 @@ func buildUsers(reflector *openapi3.Reflector) {
opFind := openapi3.Operation{}
opFind.WithTags("users")
opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUserEmail"})
reflector.SetRequest(&opFind, new(userRequest), http.MethodGet)
reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodGet, "/users/{email}", opFind)
_ = reflector.SetRequest(&opFind, new(userRequest), http.MethodGet)
_ = reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK)
_ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodGet, "/users/{email}", opFind)
opList := openapi3.Operation{}
opList.WithTags("users")
opList.WithMapOfAnything(map[string]interface{}{"operationId": "listUsers"})
reflector.SetRequest(&opList, new(userListRequest), http.MethodGet)
reflector.SetJSONResponse(&opList, new([]*types.User), http.StatusOK)
reflector.SetJSONResponse(&opList, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opList, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opList, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodGet, "/users", opList)
_ = reflector.SetRequest(&opList, new(userListRequest), http.MethodGet)
_ = reflector.SetJSONResponse(&opList, new([]*types.User), http.StatusOK)
_ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodGet, "/users", opList)
opCreate := openapi3.Operation{}
opCreate.WithTags("users")
opCreate.WithMapOfAnything(map[string]interface{}{"operationId": "createUser"})
reflector.SetRequest(&opCreate, new(types.UserInput), http.MethodPost)
reflector.SetJSONResponse(&opCreate, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodPost, "/users", opCreate)
_ = reflector.SetRequest(&opCreate, new(types.UserInput), http.MethodPost)
_ = reflector.SetJSONResponse(&opCreate, new(types.User), http.StatusOK)
_ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodPost, "/users", opCreate)
opUpdate := openapi3.Operation{}
opUpdate.WithTags("users")
opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUsers"})
reflector.SetRequest(&opUpdate, new(userUpdateRequest), http.MethodPatch)
reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodPatch, "/users/{email}", opUpdate)
_ = reflector.SetRequest(&opUpdate, new(userUpdateRequest), http.MethodPatch)
_ = reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK)
_ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodPatch, "/users/{email}", opUpdate)
opDelete := openapi3.Operation{}
opDelete.WithTags("users")
opDelete.WithMapOfAnything(map[string]interface{}{"operationId": "deleteUser"})
reflector.SetRequest(&opDelete, new(userRequest), http.MethodDelete)
reflector.SetJSONResponse(&opDelete, nil, http.StatusNoContent)
reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodDelete, "/users/{email}", opDelete)
_ = reflector.SetRequest(&opDelete, new(userRequest), http.MethodDelete)
_ = reflector.SetJSONResponse(&opDelete, nil, http.StatusNoContent)
_ = reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(http.MethodDelete, "/users/{email}", opDelete)
}

View File

@ -104,10 +104,12 @@ func ErrorObject(w http.ResponseWriter, code int, err *Error) {
func JSON(w http.ResponseWriter, code int, v interface{}) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(code)
enc := json.NewEncoder(w)
if indent {
if indent { // is this necessary? it will affect performance
enc.SetIndent("", " ")
}
enc.Encode(v)
if err := enc.Encode(v); err != nil {
code = http.StatusInternalServerError
}
w.WriteHeader(code)
}

View File

@ -22,7 +22,9 @@ func TestWriteErrorf(t *testing.T) {
}
errjson := &Error{}
json.NewDecoder(w.Body).Decode(errjson)
if err := json.NewDecoder(w.Body).Decode(errjson); err != nil {
t.Error(err)
}
if got, want := errjson.Message, e.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got)
}
@ -38,7 +40,9 @@ func TestWriteErrorCode(t *testing.T) {
}
errjson := &Error{}
json.NewDecoder(w.Body).Decode(errjson)
if err := json.NewDecoder(w.Body).Decode(errjson); err != nil {
t.Error(err)
}
if got, want := errjson.Message, "pc load letter 1"; got != want {
t.Errorf("Want error message %s, got %s", want, got)
}
@ -54,7 +58,9 @@ func TestWriteNotFound(t *testing.T) {
}
errjson := &Error{}
json.NewDecoder(w.Body).Decode(errjson)
if err := json.NewDecoder(w.Body).Decode(errjson); err != nil {
t.Error(err)
}
if got, want := errjson.Message, ErrNotFound.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got)
}
@ -70,7 +76,9 @@ func TestWriteUnauthorized(t *testing.T) {
}
errjson := &Error{}
json.NewDecoder(w.Body).Decode(errjson)
if err := json.NewDecoder(w.Body).Decode(errjson); err != nil {
t.Error(err)
}
if got, want := errjson.Message, ErrUnauthorized.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got)
}
@ -86,7 +94,9 @@ func TestWriteForbidden(t *testing.T) {
}
errjson := &Error{}
json.NewDecoder(w.Body).Decode(errjson)
if err := json.NewDecoder(w.Body).Decode(errjson); err != nil {
t.Error(err)
}
if got, want := errjson.Message, ErrForbidden.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got)
}
@ -102,7 +112,9 @@ func TestWriteBadRequest(t *testing.T) {
}
errjson := &Error{}
json.NewDecoder(w.Body).Decode(errjson)
if err := json.NewDecoder(w.Body).Decode(errjson); err != nil {
t.Error(err)
}
if got, want := errjson.Message, ErrBadRequest.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got)
}
@ -116,7 +128,7 @@ func TestWriteJSON(t *testing.T) {
if got, want := w.Body.String(), "{\"hello\":\"world\"}\n"; got != want {
t.Errorf("Want JSON body %q, got %q", want, got)
}
if got, want := w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8"; got != want {
if got, want := w.Header().Get("Content-Type"), "application/json; charset=utf-8"; got != want {
t.Errorf("Want Content-Type %q, got %q", want, got)
}
if got, want := w.Code, http.StatusTeapot; got != want {

View File

@ -64,7 +64,7 @@ func (a *TokenAuthenticator) Authenticate(r *http.Request) (*types.User, error)
if err != nil {
return nil, err
}
if parsed.Valid == false {
if !parsed.Valid {
return nil, errors.New("Invalid token")
}

View File

@ -36,5 +36,5 @@ type Authorizer interface {
* (false, nil) - the principal does not have permission to perform all the actions (at least one is not allowed)
* (false, err) - an error occured while performing the permission check and all actions should be denied
*/
CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...*types.PermissionCheck) (bool, error)
CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...types.PermissionCheck) (bool, error)
}

View File

@ -42,15 +42,18 @@ func NewAuthorizer(aclEndpoint, authToken string) (authz.Authorizer, error) {
}
func (a *Authorizer) Check(principalType enum.PrincipalType, principalId string, scope *types.Scope, resource *types.Resource, permission enum.Permission) (bool, error) {
return a.CheckAll(principalType, principalId, &types.PermissionCheck{Scope: *scope, Resource: *resource, Permission: permission})
return a.CheckAll(principalType, principalId, types.PermissionCheck{Scope: *scope, Resource: *resource, Permission: permission})
}
func (a *Authorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...*types.PermissionCheck) (bool, error) {
func (a *Authorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...types.PermissionCheck) (bool, error) {
if len(permissionChecks) == 0 {
return false, authz.ErrNoPermissionCheckProvided
}
requestDto, err := createAclRequest(principalType, principalId, permissionChecks)
if err != nil {
return false, err
}
byt, err := json.Marshal(requestDto)
if err != nil {
return false, err
@ -91,7 +94,7 @@ func (a *Authorizer) CheckAll(principalType enum.PrincipalType, principalId stri
return checkAclResponse(permissionChecks, responseDto)
}
func createAclRequest(principalType enum.PrincipalType, principalId string, permissionChecks []*types.PermissionCheck) (*aclRequest, error) {
func createAclRequest(principalType enum.PrincipalType, principalId string, permissionChecks []types.PermissionCheck) (*aclRequest, error) {
// Generate ACL req
req := aclRequest{
Permissions: []aclPermission{},
@ -123,7 +126,7 @@ func createAclRequest(principalType enum.PrincipalType, principalId string, perm
return &req, nil
}
func checkAclResponse(permissionChecks []*types.PermissionCheck, responseDto aclResponse) (bool, error) {
func checkAclResponse(permissionChecks []types.PermissionCheck, responseDto aclResponse) (bool, error) {
/*
* We are assuming two things:
* - All permission checks were made for the same principal.

View File

@ -35,9 +35,11 @@ func (a *UnsafeAuthorizer) Check(principalType enum.PrincipalType, principalId s
return true, nil
}
func (a *UnsafeAuthorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...*types.PermissionCheck) (bool, error) {
func (a *UnsafeAuthorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...types.PermissionCheck) (bool, error) {
for _, p := range permissionChecks {
a.Check(principalType, principalId, &p.Scope, &p.Resource, p.Permission)
if _, err := a.Check(principalType, principalId, &p.Scope, &p.Resource, p.Permission); err != nil {
return false, err
}
}
return true, nil

View File

@ -11,9 +11,6 @@ import (
"github.com/rs/zerolog/log"
)
// helper function returns the current time.
var now = time.Now
// Nightly is a sub-routine that periodically purges historical data.
type Nightly struct {
// Inject required stores here

View File

@ -174,16 +174,16 @@ func setupRoutesV1(
r.Route("/{user}", func(r chi.Router) {
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf("Get user '%s'", chi.URLParam(r, "rref"))))
_, _ = w.Write([]byte(fmt.Sprintf("Get user '%s'", chi.URLParam(r, "rref"))))
})
r.Post("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf("Create user '%s'", chi.URLParam(r, "rref"))))
_, _ = w.Write([]byte(fmt.Sprintf("Create user '%s'", chi.URLParam(r, "rref"))))
})
r.Put("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf("Update user '%s'", chi.URLParam(r, "rref"))))
_, _ = w.Write([]byte(fmt.Sprintf("Update user '%s'", chi.URLParam(r, "rref"))))
})
r.Delete("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf("Delete user '%s'", chi.URLParam(r, "rref"))))
_, _ = w.Write([]byte(fmt.Sprintf("Delete user '%s'", chi.URLParam(r, "rref"))))
})
})
})

View File

@ -92,7 +92,7 @@ func stubGitHandler(w http.ResponseWriter, r *http.Request) {
rep, _ := request.RepoFrom(r.Context())
w.WriteHeader(http.StatusTeapot)
w.Write([]byte(fmt.Sprintf(
_, _ = w.Write([]byte(fmt.Sprintf(
"Oooops, seems you hit a major construction site ... \n"+
" Repo: '%s' (%s)\n"+
" Method: '%s'\n"+

View File

@ -41,10 +41,8 @@ func (s *Server) listenAndServe(ctx context.Context) error {
Handler: s.Handler,
}
g.Go(func() error {
select {
case <-ctx.Done():
return s1.Shutdown(ctx)
}
<-ctx.Done()
return s1.Shutdown(ctx)
})
g.Go(func() error {
return s1.ListenAndServe()
@ -72,12 +70,14 @@ func (s *Server) listenAndServeTLS(ctx context.Context) error {
)
})
g.Go(func() error {
select {
case <-ctx.Done():
s1.Shutdown(ctx)
s2.Shutdown(ctx)
return nil
<-ctx.Done()
if err := s1.Shutdown(ctx); err != nil {
return err
}
if err := s2.Shutdown(ctx); err != nil {
return err
}
return nil
})
return g.Wait()
}
@ -108,12 +108,14 @@ func (s Server) listenAndServeAcme(ctx context.Context) error {
return s2.ListenAndServeTLS("", "")
})
g.Go(func() error {
select {
case <-ctx.Done():
s1.Shutdown(ctx)
s2.Shutdown(ctx)
return nil
<-ctx.Done()
if err := s1.Shutdown(ctx); err != nil {
return err
}
if err := s2.Shutdown(ctx); err != nil {
return err
}
return nil
})
return g.Wait()
}

View File

@ -199,14 +199,15 @@ func DeletePath(ctx context.Context, db *sqlx.DB, id int64) error {
if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// ensure path is an alias
dst := new(types.Path)
err = tx.GetContext(ctx, dst, pathSelectId, id)
if err != nil {
if err = tx.GetContext(ctx, dst, pathSelectId, id); err != nil {
return processSqlErrorf(err, "Failed to find path with id %d", id)
} else if dst.IsAlias == false {
} else if !dst.IsAlias {
return store.ErrPrimaryPathCantBeDeleted
}
@ -360,10 +361,6 @@ const pathSelectId = pathBase + `
WHERE path_id = $1
`
const pathSelectPath = pathBase + `
WHERE path_value = $1
`
const pathDeleteId = `
DELETE FROM paths
WHERE path_id = $1

View File

@ -54,7 +54,9 @@ func (s *RepoStore) Create(ctx context.Context, repo *types.Repository) error {
if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// insert repo first so we get id
query, arg, err := s.db.BindNamed(repoInsert, repo)
@ -107,7 +109,9 @@ func (s *RepoStore) Move(ctx context.Context, userId int64, repoId int64, newSpa
if err != nil {
return nil, processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sqlx.Tx) {
_ = tx.Rollback() // should we take care about rollbacks errors?
}(tx)
// get current path of repo
currentPath, err := FindPathTx(ctx, tx, enum.PathTargetTypeRepo, repoId)
@ -168,7 +172,7 @@ func (s *RepoStore) Update(ctx context.Context, repo *types.Repository) error {
}
if _, err = s.db.ExecContext(ctx, query, arg...); err != nil {
processSqlErrorf(err, "Update query failed")
return processSqlErrorf(err, "Update query failed")
}
return nil
@ -180,7 +184,9 @@ func (s *RepoStore) Delete(ctx context.Context, id int64) error {
if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// delete all paths
err = DeleteAllPaths(ctx, tx, enum.PathTargetTypeRepo, id)

View File

@ -55,7 +55,9 @@ func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error {
if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// insert space first so we get id
query, arg, err := s.db.BindNamed(spaceInsert, space)
@ -111,7 +113,9 @@ func (s *SpaceStore) Move(ctx context.Context, userId int64, spaceId int64, newP
if err != nil {
return nil, processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// always get currentpath (either it didn't change or we need to for validation)
currentPath, err := FindPathTx(ctx, tx, enum.PathTargetTypeSpace, spaceId)
@ -183,7 +187,7 @@ func (s *SpaceStore) Update(ctx context.Context, space *types.Space) error {
}
if _, err = s.db.ExecContext(ctx, query, arg...); err != nil {
processSqlErrorf(err, "Update query failed")
return processSqlErrorf(err, "Update query failed")
}
return nil
@ -195,7 +199,9 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error {
if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// get primary path
path, err := FindPathTx(ctx, tx, enum.PathTargetTypeSpace, id)
@ -205,9 +211,10 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error {
// Get child count and ensure there are none
count, err := CountPrimaryChildPathsTx(ctx, tx, path.Value)
if err := tx.QueryRow(spaceCount, id).Scan(&count); err != nil {
return errors.Wrap(err, "Failed to count the child paths of the space")
} else if count > 0 {
if err != nil {
return fmt.Errorf("child count error: %w", err)
}
if count > 0 {
// TODO: still returns 500
return store.ErrSpaceWithChildsCantBeDeleted
}
@ -219,7 +226,7 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error {
}
// delete the space
if _, err := tx.Exec(spaceDelete, id); err != nil {
if _, err = tx.Exec(spaceDelete, id); err != nil {
return processSqlErrorf(err, "The delete query failed")
}

View File

@ -5,14 +5,11 @@
package database
import (
"bytes"
"context"
"encoding/json"
"github.com/jmoiron/sqlx"
"io/ioutil"
"os"
"testing"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
@ -35,12 +32,12 @@ func connect() (*sqlx.DB, error) {
// seed seed the database state.
func seed(db *sqlx.DB) error {
db.Exec("DELETE FROM executions")
db.Exec("DELETE FROM pipelines")
db.Exec("DELETE FROM users")
db.Exec("ALTER SEQUENCE users_user_id_seq RESTART WITH 1")
db.Exec("ALTER SEQUENCE pipelines_pipeline_id_seq RESTART WITH 1")
db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1")
_, _ = db.Exec("DELETE FROM executions")
_, _ = db.Exec("DELETE FROM pipelines")
_, _ = db.Exec("DELETE FROM users")
_, _ = db.Exec("ALTER SEQUENCE users_user_id_seq RESTART WITH 1")
_, _ = db.Exec("ALTER SEQUENCE pipelines_pipeline_id_seq RESTART WITH 1")
_, _ = db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1")
return nil
}
@ -52,12 +49,3 @@ func unmarshal(path string, v interface{}) error {
}
return json.Unmarshal(out, v)
}
// dump json data to the test logs.
func debug(t *testing.T, v interface{}) {
buf := new(bytes.Buffer)
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(v)
t.Log(buf.String())
}

View File

@ -6,6 +6,7 @@ package database
import (
"context"
"database/sql"
"strconv"
"github.com/harness/gitness/internal/store"
@ -136,7 +137,9 @@ func (s *UserStore) Delete(ctx context.Context, user *types.User) error {
if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction")
}
defer tx.Rollback()
defer func(tx *sql.Tx) {
_ = tx.Rollback()
}(tx)
// delete the user
if _, err := tx.ExecContext(ctx, userDelete, user.ID); err != nil {
return processSqlErrorf(err, "The delete query failed")
@ -188,10 +191,6 @@ const userSelectEmail = userBase + `
WHERE user_email = $1
`
const userSelectToken = userBase + `
WHERE user_salt = $1
`
const userDelete = `
DELETE FROM users
WHERE user_id = $1

View File

@ -15,7 +15,6 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jmoiron/sqlx"
)
// user fields to ignore in test comparisons
@ -252,20 +251,3 @@ func testUserDelete(s store.UserStore) func(t *testing.T) {
}
}
}
// helper function that returns an user store that is seeded
// with user data loaded from a json file.
func newUserStoreSeeded(db *sqlx.DB) (store.UserStore, error) {
store := NewUserStoreSync(NewUserStore(db))
vv := []*types.User{}
if err := unmarshal("testdata/users.json", &vv); err != nil {
return nil, err
}
for _, v := range vv {
v.Salt = fmt.Sprintf("%x", v.Email)
if err := store.Create(noContext, v); err != nil {
return nil, err
}
}
return store, nil
}

View File

@ -21,10 +21,10 @@ const (
var (
ErrNameLength = &CheckError{fmt.Sprintf("Name has to be between %d and %d in length.", minNameLength, maxNameLength)}
ErrNameRegex = &CheckError{fmt.Sprintf("Name has start with a letter and only contain the following [a-z0-9-_].")}
ErrNameRegex = &CheckError{"Name has start with a letter and only contain the following [a-z0-9-_]."}
ErrDisplayNameLength = &CheckError{fmt.Sprintf("Display name has to be between %d and %d in length.", minDisplayNameLength, maxDisplayNameLength)}
ErrDisplayNameRegex = &CheckError{fmt.Sprintf("Display name has start with a letter and only contain the following [a-zA-Z0-9-_ ].")}
ErrDisplayNameRegex = &CheckError{"Display name has start with a letter and only contain the following [a-zA-Z0-9-_ ]."}
)
// Name checks the provided name and returns an error in it isn't valid.

View File

@ -46,7 +46,7 @@ func Path(path string, isSpace bool) error {
// ensure path is not too deep
segments := strings.Split(path, types.PathSeparator)
l := len(segments)
if l < minPathSegments || (isSpace == false && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) {
if l < minPathSegments || (!isSpace && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) {
return ErrPathInvalidSize
}
@ -100,5 +100,5 @@ func PathParams(path *types.PathParams, currentPath string, isSpace bool) error
*/
func PathTooLong(path string, isSpace bool) bool {
l := strings.Count(path, types.PathSeparator) + 1
return (isSpace == false && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace)
return (!isSpace && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace)
}