feat(api/v2): store user agent details in the session (#6711)

This change adds the ability to set and get user agent data, such as fingerprint, IP, request headers and a description to the session. All fields are optional.

Closes #6028
This commit is contained in:
Tim Möhlmann
2023-10-12 15:16:59 +03:00
committed by GitHub
parent a272b1201f
commit c71bf85b7a
16 changed files with 634 additions and 147 deletions

View File

@@ -4,6 +4,8 @@ import (
"context"
"database/sql"
errs "errors"
"net"
"net/http"
"time"
sq "github.com/Masterminds/squirrel"
@@ -38,6 +40,7 @@ type Session struct {
OTPSMSFactor SessionOTPFactor
OTPEmailFactor SessionOTPFactor
Metadata map[string][]byte
UserAgent domain.UserAgent
}
type SessionUserFactor struct {
@@ -163,6 +166,22 @@ var (
name: projection.SessionColumnTokenID,
table: sessionsTable,
}
SessionColumnUserAgentFingerprintID = Column{
name: projection.SessionColumnUserAgentFingerprintID,
table: sessionsTable,
}
SessionColumnUserAgentIP = Column{
name: projection.SessionColumnUserAgentIP,
table: sessionsTable,
}
SessionColumnUserAgentDescription = Column{
name: projection.SessionColumnUserAgentDescription,
table: sessionsTable,
}
SessionColumnUserAgentHeader = Column{
name: projection.SessionColumnUserAgentHeader,
table: sessionsTable,
}
)
func (q *Queries) SessionByID(ctx context.Context, shouldTriggerBulk bool, id, sessionToken string) (session *Session, err error) {
@@ -261,6 +280,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
SessionColumnOTPEmailCheckedAt.identifier(),
SessionColumnMetadata.identifier(),
SessionColumnToken.identifier(),
SessionColumnUserAgentFingerprintID.identifier(),
SessionColumnUserAgentIP.identifier(),
SessionColumnUserAgentDescription.identifier(),
SessionColumnUserAgentHeader.identifier(),
).From(sessionsTable.identifier()).
LeftJoin(join(LoginNameUserIDCol, SessionColumnUserID)).
LeftJoin(join(HumanUserIDCol, SessionColumnUserID)).
@@ -283,6 +306,8 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
otpEmailCheckedAt sql.NullTime
metadata database.Map[[]byte]
token sql.NullString
userAgentIP sql.NullString
userAgentHeader database.Map[[]string]
)
err := row.Scan(
@@ -307,6 +332,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
&otpEmailCheckedAt,
&metadata,
&token,
&session.UserAgent.FingerprintID,
&userAgentIP,
&session.UserAgent.Description,
&userAgentHeader,
)
if err != nil {
@@ -329,7 +358,11 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
session.OTPSMSFactor.OTPCheckedAt = otpSMSCheckedAt.Time
session.OTPEmailFactor.OTPCheckedAt = otpEmailCheckedAt.Time
session.Metadata = metadata
session.UserAgent.Header = http.Header(userAgentHeader)
if userAgentIP.Valid {
session.UserAgent.IP = net.ParseIP(userAgentIP.String)
}
return session, token.String, nil
}
}