@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.
@@ -0,0 +1,6 @@
1
+ package jwt
2
+
3
+ import "time"
4
+
5
+ // DefaultServiceTokenDuration is the default duration for service tokens.
6
+ const DefaultServiceTokenDuration = 30 * time.Minute
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(m, kvsWithContext(ctx, l.kvs), "info"))
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(m, kvsWithContext(ctx, l.kvs), "warn"))
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(m, kvsWithContext(ctx, l.kvs), "error"))
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(m, kvsWithContext(ctx, l.kvs), "error"))
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
- v := ""
66
- if i+1 < len(kvs) {
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, level string) string {
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)+3)
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"] = 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
- // marshal the map to a JSON byte array
28
- data, err := json.Marshal(out)
29
- if err != nil {
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
- return string(data)
34
- }
35
-
36
- // kvsWithContext returns a new kvs map with added context metadata.
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 user id to the key-value pairs
43
- if userId, err := utils.GetUserIdFromContext(ctx); err == nil {
44
- newkvs["userId"] = userId
37
+ // add the request id
38
+ if requestId, err := utils.GetRequestIdFromContext(ctx); err == nil {
39
+ out["requestId"] = requestId
45
40
  }
46
41
 
47
- // add the request path to the key-value pairs
48
- if path, err := utils.GetPathFromContext(ctx); err == nil {
49
- newkvs["path"] = path
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 newkvs
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
- // ContextMiddleware adds helpful information to the request context.
53
- func ContextMiddleware(next http.Handler) http.Handler {
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
- // set the path in the request context
56
- ctx := context.WithValue(r.Context(), models.PathKey, r.URL.Path)
57
- r = r.WithContext(ctx)
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
  }
@@ -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
- // PathKey is the key used to set/get the request path in the request context.
10
- PathKey = ContextKey("path")
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
  )
@@ -18,31 +18,41 @@ func GetTokenFromContext(ctx context.Context) *jwt.Token {
18
18
  return token
19
19
  }
20
20
 
21
- // GetUserIdFromContext retrieves the user id from the JTW token in the given context.
22
- func GetUserIdFromContext(ctx context.Context) (string, error) {
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 (userId) from the token
30
- userId, err := token.Claims.GetSubject()
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 userId == "" {
35
- return "", errors.New("user id not found in the token subject")
35
+ if subject == "" {
36
+ return "", errors.New("subject is empty in the token")
36
37
  }
37
38
 
38
- return userId, nil
39
+ return subject, nil
39
40
  }
40
41
 
41
- // GetPathFromContext retrieves the request path from the given context.
42
- func GetPathFromContext(ctx context.Context) (string, error) {
43
- path, ok := ctx.Value(models.PathKey).(string)
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 path, nil
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
@@ -2,4 +2,7 @@ module github.com/RivasCVA/dt-idl
2
2
 
3
3
  go 1.23
4
4
 
5
- require github.com/golang-jwt/jwt/v5 v5.2.2
5
+ require (
6
+ github.com/golang-jwt/jwt/v5 v5.2.2
7
+ github.com/google/uuid v1.6.0
8
+ )
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=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivascva/dt-idl",
3
- "version": "1.1.80",
3
+ "version": "1.1.82",
4
4
  "description": "Dream Trade - Interface Definition Language",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",