Two-tier notification system: new_booking (all public bookings) + pending_booking (notes/today). Priority-sorted queue, unread count polling, enriched responses with user_name/booking_start_time. Fix critical bug: edit_requested cleanup was broken (wrong reason string in 3 handlers). Add 15 new tests covering priority ordering, enrichment, and notification creation flows. Update Admin Manual, Technical Manual, and gap backlog docs.
59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/go-chi/jwtauth/v5"
|
|
)
|
|
|
|
var TokenAuth *jwtauth.JWTAuth
|
|
|
|
// AuthResponse is the response structure for login/refresh endpoints
|
|
type AuthResponse struct {
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
func InitJWT(secret string) {
|
|
TokenAuth = jwtauth.New("HS256", []byte(secret), nil)
|
|
}
|
|
|
|
// GenerateToken creates a JWT with user_id and role
|
|
func GenerateToken(userID string, role string) (string, error) {
|
|
_, tokenString, err := TokenAuth.Encode(map[string]interface{}{
|
|
"user_id": userID,
|
|
"role": role,
|
|
"exp": time.Now().Add(30 * 24 * time.Hour).Unix(), // 30 days
|
|
})
|
|
return tokenString, err
|
|
}
|
|
|
|
// VerifyToken validates JWT and returns user_id and role
|
|
func VerifyToken(tokenString string, ctx context.Context) (userID string, role string, err error) {
|
|
token, err := TokenAuth.Decode(tokenString)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
var uidVal interface{}
|
|
if err := token.Get("user_id", &uidVal); err != nil {
|
|
return "", "", fmt.Errorf("invalid user_id claim")
|
|
}
|
|
userID, ok := uidVal.(string)
|
|
if !ok {
|
|
return "", "", fmt.Errorf("invalid user_id claim")
|
|
}
|
|
|
|
var roleVal interface{}
|
|
if err := token.Get("role", &roleVal); err != nil {
|
|
return "", "", fmt.Errorf("invalid role claim")
|
|
}
|
|
role, ok = roleVal.(string)
|
|
if !ok {
|
|
return "", "", fmt.Errorf("invalid role claim")
|
|
}
|
|
|
|
return userID, role, nil
|
|
}
|