@rivascva/dt-idl 1.1.68 → 1.1.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/go/{utils/jwt → jwt}/jwt.go +2 -2
- package/go/log/log.go +88 -0
- package/go/log/utils.go +22 -0
- package/go/{utils/middlewares → middlewares}/middlewares.go +10 -8
- package/go/models/constants.go +5 -3
- package/go/{utils/fetch/fetch.go → request/request.go} +7 -4
- package/go/utils/maps.go +10 -0
- package/go/utils/{url/url.go → url.go} +4 -5
- package/go/{utils/responder → write}/models.go +3 -4
- package/go/write/write.go +75 -0
- package/package.json +1 -1
- package/go/utils/fetch/models.go +0 -6
- package/go/utils/logger/logger.go +0 -56
- package/go/utils/maps/maps.go +0 -10
- package/go/utils/responder/responder.go +0 -76
|
@@ -6,7 +6,7 @@ import (
|
|
|
6
6
|
"github.com/golang-jwt/jwt/v5"
|
|
7
7
|
)
|
|
8
8
|
|
|
9
|
-
//
|
|
9
|
+
// ValidateToken validates the given JWT token using the provided secret.
|
|
10
10
|
func ValidateToken(token string, secret string) (*jwt.Token, error) {
|
|
11
11
|
// create a JWT parser with the HS256 signing method
|
|
12
12
|
parser := jwt.NewParser(jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}))
|
|
@@ -14,7 +14,7 @@ func ValidateToken(token string, secret string) (*jwt.Token, error) {
|
|
|
14
14
|
// validate the JWT token
|
|
15
15
|
parsedToken, err := parser.Parse(token, func(t *jwt.Token) (any, error) { return []byte(secret), nil })
|
|
16
16
|
if err != nil {
|
|
17
|
-
return nil, fmt.Errorf("
|
|
17
|
+
return nil, fmt.Errorf("unable to validate the JWT token: %w", err)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
return parsedToken, nil
|
package/go/log/log.go
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
package log
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"log"
|
|
6
|
+
"maps"
|
|
7
|
+
"os"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
type Logger interface {
|
|
11
|
+
// Info prints an info log message.
|
|
12
|
+
Info(m any)
|
|
13
|
+
// Warn prints a warning log message.
|
|
14
|
+
Warn(m any)
|
|
15
|
+
// Error prints an error log message.
|
|
16
|
+
Error(m any)
|
|
17
|
+
// Fatal prints an error log message and exits the program.
|
|
18
|
+
Fatal(m any)
|
|
19
|
+
// With returns a new log with the given key-value pairs.
|
|
20
|
+
With(kvs ...any) Logger
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type Log struct {
|
|
24
|
+
kvs map[string]any
|
|
25
|
+
prefix string
|
|
26
|
+
info *log.Logger
|
|
27
|
+
warn *log.Logger
|
|
28
|
+
error *log.Logger
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// NewLog creates a new log.
|
|
32
|
+
func NewLog() *Log {
|
|
33
|
+
return NewLogWithPrefix("")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// NewLogWithPrefix creates a new log with a custom prefix.
|
|
37
|
+
func NewLogWithPrefix(prefix string) *Log {
|
|
38
|
+
return &Log{
|
|
39
|
+
kvs: make(map[string]any, 10),
|
|
40
|
+
prefix: prefix,
|
|
41
|
+
info: log.New(os.Stdout, "[INFO] ", log.LstdFlags),
|
|
42
|
+
warn: log.New(os.Stdout, "[WARN] ", log.LstdFlags),
|
|
43
|
+
error: log.New(os.Stdout, "[ERROR] ", log.LstdFlags),
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func (l *Log) Info(m any) {
|
|
48
|
+
l.info.Println(l.prefix, ToJson(m, l.kvs))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func (l *Log) Warn(m any) {
|
|
52
|
+
l.warn.Println(l.prefix, ToJson(m, l.kvs))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func (l *Log) Error(m any) {
|
|
56
|
+
l.error.Println(l.prefix, ToJson(m, l.kvs))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func (l *Log) Fatal(m any) {
|
|
60
|
+
l.error.Fatal(l.prefix, ToJson(m, l.kvs))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func (l *Log) With(kvs ...any) Logger {
|
|
64
|
+
// copy the existing key-value pairs into a new map
|
|
65
|
+
newkvs := make(map[string]any, len(l.kvs)+len(kvs))
|
|
66
|
+
maps.Copy(newkvs, l.kvs)
|
|
67
|
+
|
|
68
|
+
// add the new key-value pairs into the new map
|
|
69
|
+
for i := 0; i < len(kvs); i += 2 {
|
|
70
|
+
k := fmt.Sprintf("%v", kvs[i])
|
|
71
|
+
v := ""
|
|
72
|
+
if i+1 < len(kvs) {
|
|
73
|
+
v = fmt.Sprintf("%v", kvs[i+1])
|
|
74
|
+
}
|
|
75
|
+
newkvs[k] = v
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return &Log{
|
|
79
|
+
kvs: newkvs,
|
|
80
|
+
prefix: l.prefix,
|
|
81
|
+
info: l.info,
|
|
82
|
+
warn: l.warn,
|
|
83
|
+
error: l.error,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//exhaustruct:ignore - check for interface implementation
|
|
88
|
+
var _ Logger = &Log{}
|
package/go/log/utils.go
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package log
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"maps"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// ToJson converts the message and key-value pairs to a JSON string.
|
|
9
|
+
func ToJson(m any, kvs map[string]any) string {
|
|
10
|
+
// copy the key-value pairs into a new map and add the message
|
|
11
|
+
out := make(map[string]any, len(kvs)+1)
|
|
12
|
+
maps.Copy(out, kvs)
|
|
13
|
+
out["msg"] = m
|
|
14
|
+
|
|
15
|
+
// marshal the map to a JSON byte array
|
|
16
|
+
data, err := json.Marshal(out)
|
|
17
|
+
if err != nil {
|
|
18
|
+
return err.Error()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return string(data)
|
|
22
|
+
}
|
|
@@ -6,16 +6,18 @@ import (
|
|
|
6
6
|
"slices"
|
|
7
7
|
"strings"
|
|
8
8
|
|
|
9
|
+
"github.com/RivasCVA/dt-idl/go/jwt"
|
|
10
|
+
"github.com/RivasCVA/dt-idl/go/log"
|
|
9
11
|
"github.com/RivasCVA/dt-idl/go/models"
|
|
10
|
-
"github.com/RivasCVA/dt-idl/go/
|
|
11
|
-
"github.com/RivasCVA/dt-idl/go/utils/logger"
|
|
12
|
-
"github.com/RivasCVA/dt-idl/go/utils/responder"
|
|
12
|
+
"github.com/RivasCVA/dt-idl/go/write"
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
-
//
|
|
15
|
+
// GetAuthMiddleware returns a middleware function that authenticates all requests, except for the login endpoints.
|
|
16
16
|
// It attaches the token to the request context.
|
|
17
17
|
func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
|
|
18
|
-
|
|
18
|
+
log := log.NewLog().With("method", "GetAuthMiddleware")
|
|
19
|
+
write := write.NewWrite("ERROR", log)
|
|
20
|
+
|
|
19
21
|
return func(next http.Handler) http.Handler {
|
|
20
22
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
21
23
|
// check if the request is a login endpoint
|
|
@@ -28,14 +30,14 @@ func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
|
|
|
28
30
|
authorizationHeader := r.Header.Get("Authorization")
|
|
29
31
|
arr := strings.Split(authorizationHeader, " ")
|
|
30
32
|
if len(arr) != 2 || arr[0] != "Bearer" {
|
|
31
|
-
|
|
33
|
+
write.ResponseWithError(w, http.StatusUnauthorized, "invalid authorization header")
|
|
32
34
|
return
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
// validate the token
|
|
36
38
|
token, err := jwt.ValidateToken(arr[1], secret)
|
|
37
39
|
if err != nil {
|
|
38
|
-
|
|
40
|
+
write.ResponseWithError(w, http.StatusUnauthorized, "invalid token")
|
|
39
41
|
return
|
|
40
42
|
}
|
|
41
43
|
|
|
@@ -48,7 +50,7 @@ func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
|
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
//
|
|
53
|
+
// CommonHeaders adds shared headers to all responses.
|
|
52
54
|
func CommonHeaders(next http.Handler) http.Handler {
|
|
53
55
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
54
56
|
w.Header().Add("content-type", "application/json")
|
package/go/models/constants.go
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
package models
|
|
2
2
|
|
|
3
|
-
// ContextKey is
|
|
3
|
+
// ContextKey is a type used to define keys for a request context.
|
|
4
4
|
type ContextKey string
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const (
|
|
7
|
+
// TokenKey is the key used to set/get the JWT token in the request context.
|
|
8
|
+
TokenKey = ContextKey("token")
|
|
9
|
+
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
package
|
|
1
|
+
package request
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"encoding/json"
|
|
@@ -6,9 +6,12 @@ import (
|
|
|
6
6
|
"net/http"
|
|
7
7
|
)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
type Response struct {
|
|
10
|
+
StatusCode int
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Get makes a GET request to the given url.
|
|
14
|
+
// It parses the JSON-encoded response and stores the result into v.
|
|
12
15
|
func Get(url string, v any) (*Response, error) {
|
|
13
16
|
// make the GET request
|
|
14
17
|
resp, err := http.Get(url)
|
package/go/utils/maps.go
ADDED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
package
|
|
1
|
+
package utils
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"fmt"
|
|
5
5
|
"net/url"
|
|
6
6
|
)
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
func Build(base string, path string, params map[string]any) (string, error) {
|
|
8
|
+
// BuildUrl builds a url string from the given base and path.
|
|
9
|
+
// It encodes any given query parameters into the url.
|
|
10
|
+
func BuildUrl(base string, path string, params map[string]any) (string, error) {
|
|
12
11
|
// parse the combined base and path
|
|
13
12
|
url, err := url.Parse(base + path)
|
|
14
13
|
if err != nil {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
package
|
|
1
|
+
package write
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// The struct should match the base "Error" schema in all services.
|
|
3
|
+
// Error is a shared error schema.
|
|
4
|
+
// The struct should match the base Error schema in all services.
|
|
6
5
|
type Error[T ~string] struct {
|
|
7
6
|
Status int64 `json:"status"`
|
|
8
7
|
Code T `json:"code"`
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package write
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"net/http"
|
|
6
|
+
|
|
7
|
+
"github.com/RivasCVA/dt-idl/go/log"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
type Writer[T ~string] interface {
|
|
11
|
+
// Response writes a JSON response to the given response writer.
|
|
12
|
+
// The given data is converted to JSON. An error response is written if the marshal fails.
|
|
13
|
+
Response(w http.ResponseWriter, status int, data any)
|
|
14
|
+
// ResponseWithError writes a JSON error response to the given response writer.
|
|
15
|
+
// The response is based on the shared Error schema.
|
|
16
|
+
ResponseWithError(w http.ResponseWriter, status int, message string)
|
|
17
|
+
// ResponseWithErrorCode writes a JSON error response with a specific code to the given response writer.
|
|
18
|
+
// The response is based on the shared Error schema.
|
|
19
|
+
ResponseWithErrorCode(w http.ResponseWriter, status int, code T, message string)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type Write[T ~string] struct {
|
|
23
|
+
baseError T
|
|
24
|
+
log log.Logger
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func NewWrite[T ~string](baseError T, log log.Logger) *Write[T] {
|
|
28
|
+
return &Write[T]{
|
|
29
|
+
baseError: baseError,
|
|
30
|
+
log: log,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func (r *Write[T]) Response(w http.ResponseWriter, status int, data any) {
|
|
35
|
+
// encode the given data object
|
|
36
|
+
out, err := json.Marshal(data)
|
|
37
|
+
if err != nil {
|
|
38
|
+
r.log.With("err", err).Error("failed to marshal the data")
|
|
39
|
+
r.ResponseWithError(w, http.StatusInternalServerError, "error encoding the data")
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// write the data to the given writer
|
|
44
|
+
w.WriteHeader(status)
|
|
45
|
+
_, err = w.Write(out)
|
|
46
|
+
if err != nil {
|
|
47
|
+
r.log.With("err", err).Fatal("failed to write the response")
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func (r *Write[T]) ResponseWithError(w http.ResponseWriter, status int, message string) {
|
|
52
|
+
r.ResponseWithErrorCode(w, status, r.baseError, message)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func (r *Write[T]) ResponseWithErrorCode(w http.ResponseWriter, status int, code T, message string) {
|
|
56
|
+
// encode an error object with the given message
|
|
57
|
+
out, err := json.Marshal(Error[T]{
|
|
58
|
+
Status: int64(status),
|
|
59
|
+
Code: code,
|
|
60
|
+
Message: message,
|
|
61
|
+
})
|
|
62
|
+
if err != nil {
|
|
63
|
+
r.log.With("err", err).Fatal("failed to marshal the error")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// write the data to the given writer
|
|
67
|
+
w.WriteHeader(status)
|
|
68
|
+
_, err = w.Write(out)
|
|
69
|
+
if err != nil {
|
|
70
|
+
r.log.With("err", err).Fatal("failed to write the response")
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//exhaustruct:ignore - check for interface implementation
|
|
75
|
+
var _ Writer[string] = &Write[string]{}
|
package/package.json
CHANGED
package/go/utils/fetch/models.go
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
package logger
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"log"
|
|
6
|
-
"os"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
type Logger interface {
|
|
10
|
-
// Prints an info log message.
|
|
11
|
-
Info(v ...any)
|
|
12
|
-
// Prints a warning log message.
|
|
13
|
-
Warn(v ...any)
|
|
14
|
-
// Prints an error log message.
|
|
15
|
-
Error(v ...any)
|
|
16
|
-
// Prints an error log message and exits the program.
|
|
17
|
-
Fatal(v ...any)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type ConsoleLogger struct {
|
|
21
|
-
prefix string
|
|
22
|
-
info *log.Logger
|
|
23
|
-
warn *log.Logger
|
|
24
|
-
error *log.Logger
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Creates a new console logger.
|
|
28
|
-
func NewConsoleLogger() *ConsoleLogger {
|
|
29
|
-
return NewConsoleLoggerWithPrefix("")
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Creates a new logger with a custom prefix.
|
|
33
|
-
func NewConsoleLoggerWithPrefix(prefix string) *ConsoleLogger {
|
|
34
|
-
return &ConsoleLogger{
|
|
35
|
-
prefix: prefix,
|
|
36
|
-
info: log.New(os.Stdout, "[INFO] ", log.LstdFlags),
|
|
37
|
-
warn: log.New(os.Stdout, "[WARN] ", log.LstdFlags),
|
|
38
|
-
error: log.New(os.Stdout, "[ERROR] ", log.LstdFlags),
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
func (l *ConsoleLogger) Info(v ...any) {
|
|
43
|
-
l.info.Println(l.prefix, fmt.Sprint(v...))
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
func (l *ConsoleLogger) Warn(v ...any) {
|
|
47
|
-
l.warn.Println(l.prefix, fmt.Sprint(v...))
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
func (l *ConsoleLogger) Error(v ...any) {
|
|
51
|
-
l.error.Println(l.prefix, fmt.Sprint(v...))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
func (l *ConsoleLogger) Fatal(v ...any) {
|
|
55
|
-
l.error.Fatal(l.prefix, fmt.Sprint(v...))
|
|
56
|
-
}
|
package/go/utils/maps/maps.go
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
package responder
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"encoding/json"
|
|
5
|
-
"fmt"
|
|
6
|
-
"net/http"
|
|
7
|
-
|
|
8
|
-
"github.com/RivasCVA/dt-idl/go/utils/logger"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
type Responder[T ~string] interface {
|
|
12
|
-
// Writes a JSON response to the given response writer.
|
|
13
|
-
//
|
|
14
|
-
// The given data is converted to JSON. An error response is written if the marshal fails.
|
|
15
|
-
Write(w http.ResponseWriter, status int, data any)
|
|
16
|
-
// Writes a JSON error response to the given response writer.
|
|
17
|
-
//
|
|
18
|
-
// The response is based on the shared "Error" schema.
|
|
19
|
-
WriteError(w http.ResponseWriter, status int, message string)
|
|
20
|
-
// Writes a JSON error response with a specific code to the given response writer.
|
|
21
|
-
//
|
|
22
|
-
// The response is based on the shared "Error" schema.
|
|
23
|
-
WriteErrorWithCode(w http.ResponseWriter, status int, code T, message string)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type StandardResponder[T ~string] struct {
|
|
27
|
-
logger logger.Logger
|
|
28
|
-
defaultCode T
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
func NewStandardResponder[T ~string](logger logger.Logger, defaultCode T) *StandardResponder[T] {
|
|
32
|
-
return &StandardResponder[T]{
|
|
33
|
-
logger: logger,
|
|
34
|
-
defaultCode: defaultCode,
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
func (r *StandardResponder[T]) Write(w http.ResponseWriter, status int, data any) {
|
|
39
|
-
// encode the given data object
|
|
40
|
-
out, err := json.Marshal(data)
|
|
41
|
-
if err != nil {
|
|
42
|
-
r.logger.Error(fmt.Errorf("Write: failed to marshal the data: %w", err))
|
|
43
|
-
r.WriteError(w, http.StatusInternalServerError, "error encoding the data")
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// write the data to the given writer
|
|
48
|
-
w.WriteHeader(status)
|
|
49
|
-
_, err = w.Write(out)
|
|
50
|
-
if err != nil {
|
|
51
|
-
r.logger.Fatal(fmt.Errorf("Write: failed to write a response: %w", err))
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
func (r *StandardResponder[T]) WriteError(w http.ResponseWriter, status int, message string) {
|
|
56
|
-
r.WriteErrorWithCode(w, status, r.defaultCode, message)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
func (r *StandardResponder[T]) WriteErrorWithCode(w http.ResponseWriter, status int, code T, message string) {
|
|
60
|
-
// encode an error object with the given message
|
|
61
|
-
out, err := json.Marshal(Error[T]{
|
|
62
|
-
Status: int64(status),
|
|
63
|
-
Code: code,
|
|
64
|
-
Message: message,
|
|
65
|
-
})
|
|
66
|
-
if err != nil {
|
|
67
|
-
r.logger.Fatal(fmt.Errorf("WriteErrorWithCode: failed to marshal the error: %w", err))
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// write the data to the given writer
|
|
71
|
-
w.WriteHeader(status)
|
|
72
|
-
_, err = w.Write(out)
|
|
73
|
-
if err != nil {
|
|
74
|
-
r.logger.Fatal(fmt.Errorf("WriteErrorWithCode: failed to write a response: %w", err))
|
|
75
|
-
}
|
|
76
|
-
}
|