Compare commits
No commits in common. 'eb2f42d50a53613e59ea37b890e45651f420e4e0' and '0e5a46f0501c4143dde388f4e6bc4ee7c42d89c8' have entirely different histories.
eb2f42d50a
...
0e5a46f050
@ -1,68 +0,0 @@
|
|||||||
package ratchet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
const INTERNAL_ERROR_MESSAGE = "internal error"
|
|
||||||
|
|
||||||
// Application error codes.
|
|
||||||
//
|
|
||||||
// Note: these are generic codes but map well to HTTP status codes.
|
|
||||||
const (
|
|
||||||
EINTERNAL = "internal"
|
|
||||||
ENOTFOUND = "not_found"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error respresents an application specific-error. Application errors can be
|
|
||||||
// unwrapped by the caller to extract out the code and message
|
|
||||||
//
|
|
||||||
// Any non-application error (like disk error) should be reported as an EINTERNAL
|
|
||||||
// error and the human user should only see "Internal error" as the message.
|
|
||||||
// These low-level internal error details should only be logged and reported to
|
|
||||||
// the operation of the application, not the end user.
|
|
||||||
type Error struct {
|
|
||||||
// Machine-readable error code.
|
|
||||||
Code string
|
|
||||||
|
|
||||||
// Human-readable error message.
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface. Not used by the application otherwise.
|
|
||||||
func (e Error) Error() string {
|
|
||||||
return fmt.Sprintf("ratchet error: code=%s message=%s", e.Code, e.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorCode unwraps an application error and returns its code.
|
|
||||||
// Non-application errors always return EINTERNAL.
|
|
||||||
func ErrorCode(err error) string {
|
|
||||||
var e *Error
|
|
||||||
if err == nil {
|
|
||||||
return ""
|
|
||||||
} else if errors.As(err, &e) {
|
|
||||||
return e.Code
|
|
||||||
}
|
|
||||||
return EINTERNAL
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorMessage unwraps an application error and returns it's message.
|
|
||||||
// Non-application errors always return "Internal error".
|
|
||||||
func ErrorMessage(err error) string {
|
|
||||||
var e *Error
|
|
||||||
if err == nil {
|
|
||||||
return ""
|
|
||||||
} else if errors.As(err, &e) {
|
|
||||||
return e.Message
|
|
||||||
}
|
|
||||||
return INTERNAL_ERROR_MESSAGE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf is a helper function to return an Error with a given code and format
|
|
||||||
func Errorf(code string, format string, args ...interface{}) *Error {
|
|
||||||
return &Error{
|
|
||||||
Code: code,
|
|
||||||
Message: fmt.Sprintf(format, args...),
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
package ratchet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func AssertErrorString(t *testing.T, got, want string) {
|
|
||||||
t.Helper()
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("Incorrect error code/message got %q want %q", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorCode(t *testing.T) {
|
|
||||||
|
|
||||||
t.Run("should return empty", func(t *testing.T) {
|
|
||||||
got := ErrorCode(nil)
|
|
||||||
|
|
||||||
AssertErrorString(t, got, "")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("should return internal error", func(t *testing.T) {
|
|
||||||
want := EINTERNAL
|
|
||||||
got := ErrorCode(errors.New("Mock disk error"))
|
|
||||||
|
|
||||||
AssertErrorString(t, got, want)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("should return my code", func(t *testing.T) {
|
|
||||||
e := &Error{Code: "my_code", Message: "my_message"}
|
|
||||||
got := ErrorCode(e)
|
|
||||||
|
|
||||||
AssertErrorString(t, got, e.Code)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorMessage(t *testing.T) {
|
|
||||||
t.Run("empty error should return empty string", func(t *testing.T) {
|
|
||||||
got := ErrorMessage(nil)
|
|
||||||
|
|
||||||
AssertErrorString(t, got, "")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("should return internal error message", func(t *testing.T) {
|
|
||||||
got := ErrorMessage(errors.New("Mock disk error"))
|
|
||||||
|
|
||||||
AssertErrorString(t, got, INTERNAL_ERROR_MESSAGE)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("should return application error message", func(t *testing.T) {
|
|
||||||
e := Errorf(ENOTFOUND, "Entity %s not found", "dirp")
|
|
||||||
got := ErrorMessage(e)
|
|
||||||
|
|
||||||
AssertErrorString(t, got, e.Message)
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package ratchet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
|
|
||||||
// User prefered name and email
|
|
||||||
Name string `json:"name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
|
|
||||||
// Randomly generated API key for use with the API
|
|
||||||
// "-" omits the key from serialization
|
|
||||||
APIKey string `json:"-"`
|
|
||||||
|
|
||||||
// Timestamps for user creatation and last update
|
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
|
||||||
|
|
||||||
// List of associated Oauth authentication Objects
|
|
||||||
// Not yet implemented
|
|
||||||
// Auths []*Auth `json:"auths"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserService represents a service for managing users.
|
|
||||||
type UserService interface {
|
|
||||||
// Retrieves a user by ID along with their associated auth objects
|
|
||||||
// Returns ENOTFOUND if user does not exist.
|
|
||||||
FindUserByID(ctx context.Context, id int) (*User, error)
|
|
||||||
}
|
|
Loading…
Reference in New Issue