package hwsauth import ( "context" ) type authenticatedModel[T Model] struct { model T fresh int64 } func getNil[T Model]() T { var result T return result } // Model represents an authenticated user model. // User types must implement this interface to be used with the authenticator. type Model interface { GetID() int // Returns the unique identifier for the user } // ContextLoader is a function type that loads a model from a context. // Deprecated: Use CurrentModel method instead. type ContextLoader[T Model] func(ctx context.Context) T // LoadFunc is a function type that loads a user model from the database. // It receives a context for cancellation, a transaction for database operations, // and the user ID to load. // // Example: // // loadUser := func(ctx context.Context, tx *sql.Tx, id int) (User, error) { // var user User // err := tx.QueryRowContext(ctx, // "SELECT id, username, email FROM users WHERE id = $1", id). // Scan(&user.ID, &user.Username, &user.Email) // return user, err // } type LoadFunc[T Model, TX DBTransaction] func(ctx context.Context, tx TX, id int) (T, error) // Return a new context with the user added in func setAuthenticatedModel[T Model](ctx context.Context, m authenticatedModel[T]) context.Context { return context.WithValue(ctx, "hwsauth context key authenticated-model", m) } // Retrieve a user from the given context. Returns nil if not set func getAuthorizedModel[T Model](ctx context.Context) (model authenticatedModel[T], ok bool) { defer func() { if r := recover(); r != nil { // panic happened, return ok = false ok = false model = authenticatedModel[T]{} } }() model, cok := ctx.Value("hwsauth context key authenticated-model").(authenticatedModel[T]) if !cok { return authenticatedModel[T]{}, false } return model, true } // CurrentModel retrieves the authenticated user from the request context. // Returns a zero-value T if no user is authenticated or context is nil. // // Example: // // func handler(w http.ResponseWriter, r *http.Request) { // user := auth.CurrentModel(r.Context()) // if user.ID() == 0 { // http.Error(w, "Not authenticated", http.StatusUnauthorized) // return // } // fmt.Fprintf(w, "Hello, %s!", user.Username) // } func (auth *Authenticator[T, TX]) CurrentModel(ctx context.Context) T { if ctx == nil { return getNil[T]() } model, ok := getAuthorizedModel[T](ctx) if !ok { result := getNil[T]() return result } return model.model }