@rivascva/dt-idl 1.1.80 → 1.1.82
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/jwt/constants.go +6 -0
- package/go/jwt/jwt.go +29 -0
- package/go/log/log.go +6 -8
- package/go/log/utils.go +18 -22
- package/go/middlewares/middlewares.go +17 -6
- package/go/models/constants.go +11 -2
- package/go/utils/context.go +22 -12
- package/go.mod +4 -1
- package/go.sum +2 -0
- package/package.json +1 -1
package/go/jwt/jwt.go
CHANGED
|
@@ -2,6 +2,7 @@ package jwt
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"fmt"
|
|
5
|
+
"time"
|
|
5
6
|
|
|
6
7
|
"github.com/golang-jwt/jwt/v5"
|
|
7
8
|
)
|
|
@@ -19,3 +20,31 @@ func ValidateToken(token string, secret string) (*jwt.Token, error) {
|
|
|
19
20
|
|
|
20
21
|
return parsedToken, nil
|
|
21
22
|
}
|
|
23
|
+
|
|
24
|
+
// NewUserToken creates a new JWT token for the given user id.
|
|
25
|
+
func NewUserToken(secret string, issuer string, userId string, duration time.Duration) (string, error) {
|
|
26
|
+
return newToken(secret, "user", issuer, userId, duration)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// NewServiceToken creates a new JWT token for the given service.
|
|
30
|
+
func NewServiceToken(secret string, issuer string, service string, duration time.Duration) (string, error) {
|
|
31
|
+
return newToken(secret, "service", issuer, service, duration)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// newToken creates a new JWT token.
|
|
35
|
+
func newToken(secret string, ttype string, issuer string, subject string, duration time.Duration) (string, error) {
|
|
36
|
+
t := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
|
37
|
+
"type": ttype,
|
|
38
|
+
"iss": issuer,
|
|
39
|
+
"sub": subject,
|
|
40
|
+
"iat": time.Now().UnixMilli(),
|
|
41
|
+
"exp": time.Now().Add(duration).UnixMilli(),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
s, err := t.SignedString([]byte(secret))
|
|
45
|
+
if err != nil {
|
|
46
|
+
return "", fmt.Errorf("unable to sign the JWT token: %w", err)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return s, nil
|
|
50
|
+
}
|
package/go/log/log.go
CHANGED
|
@@ -39,19 +39,19 @@ func NewLog() *Log {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
func (l *Log) Info(ctx context.Context, m any) {
|
|
42
|
-
l.info.Println(toJson(
|
|
42
|
+
l.info.Println(toJson(ctx, m, l.kvs, "info"))
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
func (l *Log) Warn(ctx context.Context, m any) {
|
|
46
|
-
l.warn.Println(toJson(
|
|
46
|
+
l.warn.Println(toJson(ctx, m, l.kvs, "warn"))
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
func (l *Log) Error(ctx context.Context, m any) {
|
|
50
|
-
l.error.Println(toJson(
|
|
50
|
+
l.error.Println(toJson(ctx, m, l.kvs, "error"))
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
func (l *Log) Fatal(ctx context.Context, m any) {
|
|
54
|
-
l.error.Fatal(toJson(
|
|
54
|
+
l.error.Fatal(toJson(ctx, m, l.kvs, "error"))
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
func (l *Log) With(kvs ...any) Logger {
|
|
@@ -62,11 +62,9 @@ func (l *Log) With(kvs ...any) Logger {
|
|
|
62
62
|
// add the new key-value pairs into the new map
|
|
63
63
|
for i := 0; i < len(kvs); i += 2 {
|
|
64
64
|
k := fmt.Sprintf("%v", kvs[i])
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
v = fmt.Sprintf("%v", kvs[i+1])
|
|
65
|
+
if k != "" && i+1 < len(kvs) {
|
|
66
|
+
newkvs[k] = kvs[i+1]
|
|
68
67
|
}
|
|
69
|
-
newkvs[k] = v
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
return &Log{
|
package/go/log/utils.go
CHANGED
|
@@ -10,44 +10,40 @@ import (
|
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
// toJson converts the message and key-value pairs to a JSON string.
|
|
13
|
-
func toJson(m any, kvs map[string]any,
|
|
13
|
+
func toJson(ctx context.Context, m any, kvs map[string]any, lvl string) string {
|
|
14
14
|
// copy the key-value pairs into a new map
|
|
15
|
-
out := make(map[string]any, len(kvs)+
|
|
15
|
+
out := make(map[string]any, len(kvs)+10)
|
|
16
16
|
maps.Copy(out, kvs)
|
|
17
17
|
|
|
18
18
|
// add the message
|
|
19
19
|
out["msg"] = m
|
|
20
20
|
|
|
21
21
|
// add the log level
|
|
22
|
-
out["level"] =
|
|
22
|
+
out["level"] = lvl
|
|
23
23
|
|
|
24
24
|
// add the timestamp
|
|
25
25
|
out["timestamp"] = time.Now().UTC().Format(time.RFC3339)
|
|
26
26
|
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return err.Error()
|
|
27
|
+
// add the actor id
|
|
28
|
+
if actorId, err := utils.GetActorIdFromContext(ctx); err == nil {
|
|
29
|
+
out["actorId"] = actorId
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
func kvsWithContext(ctx context.Context, kvs map[string]any) map[string]any {
|
|
38
|
-
// copy the existing key-value pairs into a new map
|
|
39
|
-
newkvs := make(map[string]any, len(kvs)+2)
|
|
40
|
-
maps.Copy(newkvs, kvs)
|
|
32
|
+
// add the request path
|
|
33
|
+
if requestPath, err := utils.GetRequestPathFromContext(ctx); err == nil {
|
|
34
|
+
out["requestPath"] = requestPath
|
|
35
|
+
}
|
|
41
36
|
|
|
42
|
-
// add the
|
|
43
|
-
if
|
|
44
|
-
|
|
37
|
+
// add the request id
|
|
38
|
+
if requestId, err := utils.GetRequestIdFromContext(ctx); err == nil {
|
|
39
|
+
out["requestId"] = requestId
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
// marshal the map to a JSON byte array
|
|
43
|
+
data, err := json.Marshal(out)
|
|
44
|
+
if err != nil {
|
|
45
|
+
return err.Error()
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
return
|
|
48
|
+
return string(data)
|
|
53
49
|
}
|
|
@@ -10,6 +10,7 @@ import (
|
|
|
10
10
|
"github.com/RivasCVA/dt-idl/go/log"
|
|
11
11
|
"github.com/RivasCVA/dt-idl/go/models"
|
|
12
12
|
"github.com/RivasCVA/dt-idl/go/write"
|
|
13
|
+
"github.com/google/uuid"
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
// GetAuthMiddleware returns a middleware function that authenticates all requests, except for the login endpoints.
|
|
@@ -19,7 +20,7 @@ func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
|
|
|
19
20
|
|
|
20
21
|
return func(next http.Handler) http.Handler {
|
|
21
22
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
22
|
-
// check if the request is a login endpoint
|
|
23
|
+
// check if the request path is a login endpoint
|
|
23
24
|
if slices.Contains([]string{"/v1/login", "/v1/login/provider"}, r.URL.Path) {
|
|
24
25
|
next.ServeHTTP(w, r)
|
|
25
26
|
return
|
|
@@ -49,13 +50,23 @@ func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
|
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
//
|
|
53
|
-
func
|
|
53
|
+
// CommonContext adds shared values to the request context.
|
|
54
|
+
func CommonContext(next http.Handler) http.Handler {
|
|
54
55
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
55
|
-
//
|
|
56
|
-
ctx :=
|
|
57
|
-
|
|
56
|
+
// get the request context
|
|
57
|
+
ctx := r.Context()
|
|
58
|
+
|
|
59
|
+
// set the request id in the request context
|
|
60
|
+
requestId := r.Header.Get("X-Request-Id")
|
|
61
|
+
if requestId == "" {
|
|
62
|
+
requestId = uuid.New().String()
|
|
63
|
+
}
|
|
64
|
+
ctx = context.WithValue(ctx, models.RequestIdKey, requestId)
|
|
58
65
|
|
|
66
|
+
// set the request path in the request context
|
|
67
|
+
ctx = context.WithValue(ctx, models.RequestPathKey, r.URL.Path)
|
|
68
|
+
|
|
69
|
+
r = r.WithContext(ctx)
|
|
59
70
|
next.ServeHTTP(w, r)
|
|
60
71
|
})
|
|
61
72
|
}
|
package/go/models/constants.go
CHANGED
|
@@ -6,6 +6,15 @@ type ContextKey string
|
|
|
6
6
|
const (
|
|
7
7
|
// TokenKey is the key used to set/get the JWT token in the request context.
|
|
8
8
|
TokenKey = ContextKey("token")
|
|
9
|
-
//
|
|
10
|
-
|
|
9
|
+
// RequestPathKey is the key used to set/get the request path in the request context.
|
|
10
|
+
RequestPathKey = ContextKey("requestPath")
|
|
11
|
+
// RequestIdKey is the key used to set/get the request id in the request context.
|
|
12
|
+
RequestIdKey = ContextKey("requestId")
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
type TokenType string
|
|
16
|
+
|
|
17
|
+
const (
|
|
18
|
+
UserToken TokenType = "user"
|
|
19
|
+
ServiceToken TokenType = "service"
|
|
11
20
|
)
|
package/go/utils/context.go
CHANGED
|
@@ -18,31 +18,41 @@ func GetTokenFromContext(ctx context.Context) *jwt.Token {
|
|
|
18
18
|
return token
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
|
|
21
|
+
// GetActorIdFromContext retrieves the actor id from the JTW token in the given context.
|
|
22
|
+
// The actor id is the subject of the JWT token, and it represents the user id or service name that initiated the request.
|
|
23
|
+
func GetActorIdFromContext(ctx context.Context) (string, error) {
|
|
23
24
|
// get the token from the context
|
|
24
25
|
token := GetTokenFromContext(ctx)
|
|
25
26
|
if token == nil {
|
|
26
27
|
return "", errors.New("token not found in the context")
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
// get the subject
|
|
30
|
-
|
|
30
|
+
// get the subject from the token
|
|
31
|
+
subject, err := token.Claims.GetSubject()
|
|
31
32
|
if err != nil {
|
|
32
33
|
return "", fmt.Errorf("failed to get the subject from the token: %w", err)
|
|
33
34
|
}
|
|
34
|
-
if
|
|
35
|
-
return "", errors.New("
|
|
35
|
+
if subject == "" {
|
|
36
|
+
return "", errors.New("subject is empty in the token")
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
return
|
|
39
|
+
return subject, nil
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
//
|
|
42
|
-
func
|
|
43
|
-
|
|
42
|
+
// GetRequestPathFromContext retrieves the request path from the given context.
|
|
43
|
+
func GetRequestPathFromContext(ctx context.Context) (string, error) {
|
|
44
|
+
requestPath, ok := ctx.Value(models.RequestPathKey).(string)
|
|
44
45
|
if !ok {
|
|
45
|
-
return "", errors.New("path not found in the context")
|
|
46
|
+
return "", errors.New("request path not found in the context")
|
|
46
47
|
}
|
|
47
|
-
return
|
|
48
|
+
return requestPath, nil
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// GetRequestIdFromContext retrieves the request id from the given context.
|
|
52
|
+
func GetRequestIdFromContext(ctx context.Context) (string, error) {
|
|
53
|
+
requestId, ok := ctx.Value(models.RequestIdKey).(string)
|
|
54
|
+
if !ok {
|
|
55
|
+
return "", errors.New("request id not found in the context")
|
|
56
|
+
}
|
|
57
|
+
return requestId, nil
|
|
48
58
|
}
|
package/go.mod
CHANGED
package/go.sum
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
|
2
2
|
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
|
3
|
+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|
4
|
+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|