[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) mocks: $(mocks)
@echo "Generating Test 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" @echo "Generating Code"
build: generate ## Build the gitness service binary 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 # Some code generation can be slow, so we only run it if
# the source file has changed. # 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" @echo "Updating wire_gen.go"
go generate ./cli/server/wire_gen.go go generate ./cli/server/wire_gen.go

View File

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

View File

@ -25,7 +25,10 @@ type command struct {
func (c *command) run(*kingpin.ParseContext) error { func (c *command) run(*kingpin.ParseContext) error {
// load environment variables from file. // 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 // create the system configuration store by loading
// data from the environment. // data from the environment.

View File

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

View File

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

View File

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

View File

@ -33,7 +33,9 @@ func TestFind(t *testing.T) {
} }
got, want := &types.User{}, mockUser 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 { if diff := cmp.Diff(got, want); len(diff) != 0 {
t.Errorf(diff) t.Errorf(diff)
} }

View File

@ -38,7 +38,9 @@ func TestToken(t *testing.T) {
} }
result := &types.Token{} 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) { _, err := jwt.Parse(result.Value, func(token *jwt.Token) (interface{}, error) {
return []byte(mockUser.Salt), nil return []byte(mockUser.Salt), nil

View File

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

View File

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

View File

@ -5,10 +5,6 @@
package openapi package openapi
import ( import (
"bytes"
"net/http"
"strings"
"github.com/harness/gitness/version" "github.com/harness/gitness/version"
"github.com/swaggest/openapi-go/openapi3" "github.com/swaggest/openapi-go/openapi3"
@ -29,37 +25,38 @@ type (
Size int `query:"per_page" default:"100"` Size int `query:"per_page" default:"100"`
} }
// base response for pagination // TODO: base response for pagination
paginationResponse struct { //paginationResponse struct {
Total int `header:"x-total"` // Total int `header:"x-total"`
Pagelen int `header:"x-total-pages"` // Pagelen int `header:"x-total-pages"`
Page int `header:"x-page"` // Page int `header:"x-page"`
Size int `header:"x-per-page"` // Size int `header:"x-per-page"`
Next int `header:"x-next"` // Next int `header:"x-next"`
Prev int `header:"x-prev"` // Prev int `header:"x-prev"`
Link []string `header:"Link"` // Link []string `header:"Link"`
} //}
) )
// Handler returns an http.HandlerFunc that writes the openapi v3 // Handler returns an http.HandlerFunc that writes the openapi v3
// specification file to the http.Response body. // specification file to the http.Response body.
func Handler() http.HandlerFunc { // TODO: unused function
spec := Generate() //func Handler() http.HandlerFunc {
yaml, _ := spec.MarshalYAML() // spec := Generate()
json, _ := spec.MarshalJSON() // yaml, _ := spec.MarshalYAML()
// json, _ := spec.MarshalJSON()
yaml = normalize(yaml) //
json = normalize(json) // yaml = normalize(yaml)
// json = normalize(json)
return func(w http.ResponseWriter, r *http.Request) { //
switch { // return func(w http.ResponseWriter, r *http.Request) {
case strings.HasSuffix(r.URL.Path, ".json"): // switch {
w.Write(json) // case strings.HasSuffix(r.URL.Path, ".json"):
default: // w.Write(json)
w.Write(yaml) // default:
} // w.Write(yaml)
} // }
} // }
//}
// Generate is a helper function that constructs the // Generate is a helper function that constructs the
// openapi specification object, which can be marshaled // openapi specification object, which can be marshaled
@ -108,10 +105,11 @@ func Generate() *openapi3.Spec {
// helper function normalizes the output to ensure // helper function normalizes the output to ensure
// automatically-generated names are more user friendly. // automatically-generated names are more user friendly.
func normalize(data []byte) []byte { // TODO: unused function
data = bytes.ReplaceAll(data, []byte("Types"), []byte("")) //func normalize(data []byte) []byte {
data = bytes.ReplaceAll(data, []byte("Openapi"), []byte("")) // data = bytes.ReplaceAll(data, []byte("Types"), []byte(""))
data = bytes.ReplaceAll(data, []byte("FormData"), []byte("")) // data = bytes.ReplaceAll(data, []byte("Openapi"), []byte(""))
data = bytes.ReplaceAll(data, []byte("RenderError"), []byte("Error")) // data = bytes.ReplaceAll(data, []byte("FormData"), []byte(""))
return data // 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 := openapi3.Operation{}
opFind.WithTags("user") opFind.WithTags("user")
opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUser"}) opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUser"})
reflector.SetRequest(&opFind, nil, http.MethodGet) _ = reflector.SetRequest(&opFind, nil, http.MethodGet)
reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK) _ = reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodGet, "/user", opFind) _ = reflector.Spec.AddOperation(http.MethodGet, "/user", opFind)
opUpdate := openapi3.Operation{} opUpdate := openapi3.Operation{}
opUpdate.WithTags("user") opUpdate.WithTags("user")
opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUser"}) opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUser"})
reflector.SetRequest(&opUpdate, new(types.UserInput), http.MethodPatch) _ = reflector.SetRequest(&opUpdate, new(types.UserInput), http.MethodPatch)
reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodPatch, "/user", opUpdate) _ = reflector.Spec.AddOperation(http.MethodPatch, "/user", opUpdate)
opToken := openapi3.Operation{} opToken := openapi3.Operation{}
opToken.WithTags("user") opToken.WithTags("user")
opToken.WithMapOfAnything(map[string]interface{}{"operationId": "createToken"}) opToken.WithMapOfAnything(map[string]interface{}{"operationId": "createToken"})
reflector.SetRequest(&opToken, new(types.Token), http.MethodPost) _ = reflector.SetRequest(&opToken, new(types.Token), http.MethodPost)
reflector.SetJSONResponse(&opToken, new(types.User), http.StatusOK) _ = reflector.SetJSONResponse(&opToken, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opToken, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opToken, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodPost, "/user/token", opToken) _ = reflector.Spec.AddOperation(http.MethodPost, "/user/token", opToken)
opCurrent := openapi3.Operation{} opCurrent := openapi3.Operation{}
opCurrent.WithTags("user") opCurrent.WithTags("user")
opCurrent.WithMapOfAnything(map[string]interface{}{"operationId": "getCurrentUser"}) opCurrent.WithMapOfAnything(map[string]interface{}{"operationId": "getCurrentUser"})
reflector.SetRequest(&opFind, new(baseRequest), http.MethodGet) _ = reflector.SetRequest(&opFind, new(baseRequest), http.MethodGet)
reflector.SetJSONResponse(&opCurrent, new(currentUserResponse), http.StatusOK) _ = reflector.SetJSONResponse(&opCurrent, new(currentUserResponse), http.StatusOK)
reflector.SetJSONResponse(&opCurrent, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opCurrent, new(render.Error), http.StatusInternalServerError)
reflector.Spec.AddOperation(http.MethodGet, "/api/user/currentUser", opCurrent) _ = reflector.Spec.AddOperation(http.MethodGet, "/api/user/currentUser", opCurrent)
} }

View File

@ -44,49 +44,49 @@ func buildUsers(reflector *openapi3.Reflector) {
opFind := openapi3.Operation{} opFind := openapi3.Operation{}
opFind.WithTags("users") opFind.WithTags("users")
opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUserEmail"}) opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUserEmail"})
reflector.SetRequest(&opFind, new(userRequest), http.MethodGet) _ = reflector.SetRequest(&opFind, new(userRequest), http.MethodGet)
reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK) _ = reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusNotFound) _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodGet, "/users/{email}", opFind) _ = reflector.Spec.AddOperation(http.MethodGet, "/users/{email}", opFind)
opList := openapi3.Operation{} opList := openapi3.Operation{}
opList.WithTags("users") opList.WithTags("users")
opList.WithMapOfAnything(map[string]interface{}{"operationId": "listUsers"}) opList.WithMapOfAnything(map[string]interface{}{"operationId": "listUsers"})
reflector.SetRequest(&opList, new(userListRequest), http.MethodGet) _ = reflector.SetRequest(&opList, new(userListRequest), http.MethodGet)
reflector.SetJSONResponse(&opList, new([]*types.User), http.StatusOK) _ = reflector.SetJSONResponse(&opList, new([]*types.User), http.StatusOK)
reflector.SetJSONResponse(&opList, new(render.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opList, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opList, new(render.Error), http.StatusNotFound) _ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodGet, "/users", opList) _ = reflector.Spec.AddOperation(http.MethodGet, "/users", opList)
opCreate := openapi3.Operation{} opCreate := openapi3.Operation{}
opCreate.WithTags("users") opCreate.WithTags("users")
opCreate.WithMapOfAnything(map[string]interface{}{"operationId": "createUser"}) opCreate.WithMapOfAnything(map[string]interface{}{"operationId": "createUser"})
reflector.SetRequest(&opCreate, new(types.UserInput), http.MethodPost) _ = reflector.SetRequest(&opCreate, new(types.UserInput), http.MethodPost)
reflector.SetJSONResponse(&opCreate, new(types.User), http.StatusOK) _ = reflector.SetJSONResponse(&opCreate, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusNotFound) _ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodPost, "/users", opCreate) _ = reflector.Spec.AddOperation(http.MethodPost, "/users", opCreate)
opUpdate := openapi3.Operation{} opUpdate := openapi3.Operation{}
opUpdate.WithTags("users") opUpdate.WithTags("users")
opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUsers"}) opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUsers"})
reflector.SetRequest(&opUpdate, new(userUpdateRequest), http.MethodPatch) _ = reflector.SetRequest(&opUpdate, new(userUpdateRequest), http.MethodPatch)
reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusBadRequest)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusNotFound) _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodPatch, "/users/{email}", opUpdate) _ = reflector.Spec.AddOperation(http.MethodPatch, "/users/{email}", opUpdate)
opDelete := openapi3.Operation{} opDelete := openapi3.Operation{}
opDelete.WithTags("users") opDelete.WithTags("users")
opDelete.WithMapOfAnything(map[string]interface{}{"operationId": "deleteUser"}) opDelete.WithMapOfAnything(map[string]interface{}{"operationId": "deleteUser"})
reflector.SetRequest(&opDelete, new(userRequest), http.MethodDelete) _ = reflector.SetRequest(&opDelete, new(userRequest), http.MethodDelete)
reflector.SetJSONResponse(&opDelete, nil, http.StatusNoContent) _ = reflector.SetJSONResponse(&opDelete, nil, http.StatusNoContent)
reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusInternalServerError)
reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusNotFound) _ = reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusNotFound)
reflector.Spec.AddOperation(http.MethodDelete, "/users/{email}", opDelete) _ = 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{}) { func JSON(w http.ResponseWriter, code int, v interface{}) {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(code)
enc := json.NewEncoder(w) enc := json.NewEncoder(w)
if indent { if indent { // is this necessary? it will affect performance
enc.SetIndent("", " ") 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{} 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 { if got, want := errjson.Message, e.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got) t.Errorf("Want error message %s, got %s", want, got)
} }
@ -38,7 +40,9 @@ func TestWriteErrorCode(t *testing.T) {
} }
errjson := &Error{} 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 { if got, want := errjson.Message, "pc load letter 1"; got != want {
t.Errorf("Want error message %s, got %s", want, got) t.Errorf("Want error message %s, got %s", want, got)
} }
@ -54,7 +58,9 @@ func TestWriteNotFound(t *testing.T) {
} }
errjson := &Error{} 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 { if got, want := errjson.Message, ErrNotFound.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got) t.Errorf("Want error message %s, got %s", want, got)
} }
@ -70,7 +76,9 @@ func TestWriteUnauthorized(t *testing.T) {
} }
errjson := &Error{} 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 { if got, want := errjson.Message, ErrUnauthorized.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got) t.Errorf("Want error message %s, got %s", want, got)
} }
@ -86,7 +94,9 @@ func TestWriteForbidden(t *testing.T) {
} }
errjson := &Error{} 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 { if got, want := errjson.Message, ErrForbidden.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got) t.Errorf("Want error message %s, got %s", want, got)
} }
@ -102,7 +112,9 @@ func TestWriteBadRequest(t *testing.T) {
} }
errjson := &Error{} 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 { if got, want := errjson.Message, ErrBadRequest.Message; got != want {
t.Errorf("Want error message %s, got %s", want, got) 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 { if got, want := w.Body.String(), "{\"hello\":\"world\"}\n"; got != want {
t.Errorf("Want JSON body %q, got %q", want, got) 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) t.Errorf("Want Content-Type %q, got %q", want, got)
} }
if got, want := w.Code, http.StatusTeapot; got != want { 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 { if err != nil {
return nil, err return nil, err
} }
if parsed.Valid == false { if !parsed.Valid {
return nil, errors.New("Invalid token") 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, 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 * (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) { 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 { if len(permissionChecks) == 0 {
return false, authz.ErrNoPermissionCheckProvided return false, authz.ErrNoPermissionCheckProvided
} }
requestDto, err := createAclRequest(principalType, principalId, permissionChecks) requestDto, err := createAclRequest(principalType, principalId, permissionChecks)
if err != nil {
return false, err
}
byt, err := json.Marshal(requestDto) byt, err := json.Marshal(requestDto)
if err != nil { if err != nil {
return false, err return false, err
@ -91,7 +94,7 @@ func (a *Authorizer) CheckAll(principalType enum.PrincipalType, principalId stri
return checkAclResponse(permissionChecks, responseDto) 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 // Generate ACL req
req := aclRequest{ req := aclRequest{
Permissions: []aclPermission{}, Permissions: []aclPermission{},
@ -123,7 +126,7 @@ func createAclRequest(principalType enum.PrincipalType, principalId string, perm
return &req, nil 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: * We are assuming two things:
* - All permission checks were made for the same principal. * - 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 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 { 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 return true, nil

View File

@ -11,9 +11,6 @@ import (
"github.com/rs/zerolog/log" "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. // Nightly is a sub-routine that periodically purges historical data.
type Nightly struct { type Nightly struct {
// Inject required stores here // Inject required stores here

View File

@ -174,16 +174,16 @@ func setupRoutesV1(
r.Route("/{user}", func(r chi.Router) { r.Route("/{user}", func(r chi.Router) {
r.Get("/", func(w http.ResponseWriter, r *http.Request) { 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) { 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) { 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) { 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()) rep, _ := request.RepoFrom(r.Context())
w.WriteHeader(http.StatusTeapot) w.WriteHeader(http.StatusTeapot)
w.Write([]byte(fmt.Sprintf( _, _ = w.Write([]byte(fmt.Sprintf(
"Oooops, seems you hit a major construction site ... \n"+ "Oooops, seems you hit a major construction site ... \n"+
" Repo: '%s' (%s)\n"+ " Repo: '%s' (%s)\n"+
" Method: '%s'\n"+ " Method: '%s'\n"+

View File

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

View File

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

View File

@ -54,7 +54,9 @@ func (s *RepoStore) Create(ctx context.Context, repo *types.Repository) error {
if err != nil { if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction") 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 // insert repo first so we get id
query, arg, err := s.db.BindNamed(repoInsert, repo) 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 { if err != nil {
return nil, processSqlErrorf(err, "Failed to start a new transaction") 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 // get current path of repo
currentPath, err := FindPathTx(ctx, tx, enum.PathTargetTypeRepo, repoId) 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 { if _, err = s.db.ExecContext(ctx, query, arg...); err != nil {
processSqlErrorf(err, "Update query failed") return processSqlErrorf(err, "Update query failed")
} }
return nil return nil
@ -180,7 +184,9 @@ func (s *RepoStore) Delete(ctx context.Context, id int64) error {
if err != nil { if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction") return processSqlErrorf(err, "Failed to start a new transaction")
} }
defer tx.Rollback() defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// delete all paths // delete all paths
err = DeleteAllPaths(ctx, tx, enum.PathTargetTypeRepo, id) 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 { if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction") 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 // insert space first so we get id
query, arg, err := s.db.BindNamed(spaceInsert, space) 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 { if err != nil {
return nil, processSqlErrorf(err, "Failed to start a new transaction") 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) // always get currentpath (either it didn't change or we need to for validation)
currentPath, err := FindPathTx(ctx, tx, enum.PathTargetTypeSpace, spaceId) 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 { if _, err = s.db.ExecContext(ctx, query, arg...); err != nil {
processSqlErrorf(err, "Update query failed") return processSqlErrorf(err, "Update query failed")
} }
return nil return nil
@ -195,7 +199,9 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error {
if err != nil { if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction") return processSqlErrorf(err, "Failed to start a new transaction")
} }
defer tx.Rollback() defer func(tx *sqlx.Tx) {
_ = tx.Rollback()
}(tx)
// get primary path // get primary path
path, err := FindPathTx(ctx, tx, enum.PathTargetTypeSpace, id) 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 // Get child count and ensure there are none
count, err := CountPrimaryChildPathsTx(ctx, tx, path.Value) count, err := CountPrimaryChildPathsTx(ctx, tx, path.Value)
if err := tx.QueryRow(spaceCount, id).Scan(&count); err != nil { if err != nil {
return errors.Wrap(err, "Failed to count the child paths of the space") return fmt.Errorf("child count error: %w", err)
} else if count > 0 { }
if count > 0 {
// TODO: still returns 500 // TODO: still returns 500
return store.ErrSpaceWithChildsCantBeDeleted return store.ErrSpaceWithChildsCantBeDeleted
} }
@ -219,7 +226,7 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error {
} }
// delete the space // 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") return processSqlErrorf(err, "The delete query failed")
} }

View File

@ -5,14 +5,11 @@
package database package database
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"github.com/jmoiron/sqlx"
"io/ioutil" "io/ioutil"
"os" "os"
"testing"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq" _ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
@ -35,12 +32,12 @@ func connect() (*sqlx.DB, error) {
// seed seed the database state. // seed seed the database state.
func seed(db *sqlx.DB) error { func seed(db *sqlx.DB) error {
db.Exec("DELETE FROM executions") _, _ = db.Exec("DELETE FROM executions")
db.Exec("DELETE FROM pipelines") _, _ = db.Exec("DELETE FROM pipelines")
db.Exec("DELETE FROM users") _, _ = db.Exec("DELETE FROM users")
db.Exec("ALTER SEQUENCE users_user_id_seq RESTART WITH 1") _, _ = 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 pipelines_pipeline_id_seq RESTART WITH 1")
db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1") _, _ = db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1")
return nil return nil
} }
@ -52,12 +49,3 @@ func unmarshal(path string, v interface{}) error {
} }
return json.Unmarshal(out, v) 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 ( import (
"context" "context"
"database/sql"
"strconv" "strconv"
"github.com/harness/gitness/internal/store" "github.com/harness/gitness/internal/store"
@ -136,7 +137,9 @@ func (s *UserStore) Delete(ctx context.Context, user *types.User) error {
if err != nil { if err != nil {
return processSqlErrorf(err, "Failed to start a new transaction") return processSqlErrorf(err, "Failed to start a new transaction")
} }
defer tx.Rollback() defer func(tx *sql.Tx) {
_ = tx.Rollback()
}(tx)
// delete the user // delete the user
if _, err := tx.ExecContext(ctx, userDelete, user.ID); err != nil { if _, err := tx.ExecContext(ctx, userDelete, user.ID); err != nil {
return processSqlErrorf(err, "The delete query failed") return processSqlErrorf(err, "The delete query failed")
@ -188,10 +191,6 @@ const userSelectEmail = userBase + `
WHERE user_email = $1 WHERE user_email = $1
` `
const userSelectToken = userBase + `
WHERE user_salt = $1
`
const userDelete = ` const userDelete = `
DELETE FROM users DELETE FROM users
WHERE user_id = $1 WHERE user_id = $1

View File

@ -15,7 +15,6 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
"github.com/jmoiron/sqlx"
) )
// user fields to ignore in test comparisons // 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 ( var (
ErrNameLength = &CheckError{fmt.Sprintf("Name has to be between %d and %d in length.", minNameLength, maxNameLength)} 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)} 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. // 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 // ensure path is not too deep
segments := strings.Split(path, types.PathSeparator) segments := strings.Split(path, types.PathSeparator)
l := len(segments) l := len(segments)
if l < minPathSegments || (isSpace == false && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) { if l < minPathSegments || (!isSpace && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) {
return ErrPathInvalidSize return ErrPathInvalidSize
} }
@ -100,5 +100,5 @@ func PathParams(path *types.PathParams, currentPath string, isSpace bool) error
*/ */
func PathTooLong(path string, isSpace bool) bool { func PathTooLong(path string, isSpace bool) bool {
l := strings.Count(path, types.PathSeparator) + 1 l := strings.Count(path, types.PathSeparator) + 1
return (isSpace == false && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) return (!isSpace && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace)
} }