package fire import ( "context" "net/http" "strings" firebase "firebase.google.com/go" "git.mokkon.com/sainw/server_helper.git/util" ) // ContextKey to be used as context key type type ContextKey string // UserClaimIDContextKey context key for auth id const UserClaimIDContextKey = ContextKey("User Claim ID") // UserClaim holds user information type UserClaim struct { UserID string AuthID string PhoneNumber string Status string Privileges []string } // User holds user information type User struct { ID string `json:"id"` UserName string `json:"user_name"` PhoneNumber string `json:"phone_number"` Status string `json:"status"` SysAdmin bool `json:"sys_admin"` Privileges []string `json:"privileges"` } // GetUserClaim returns UserClaim from context func GetUserClaim(ctx context.Context) (UserClaim, bool) { userClaim, ok := ctx.Value(UserClaimIDContextKey).(UserClaim) return userClaim, ok } func (c UserClaim) HasPrivileges(ps ...string) bool { for _, p := range ps { if util.Contains(c.Privileges, p) { return true } } return false } func Auth(app *firebase.App, h http.Handler) http.Handler { fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // read token token := r.Header.Get("Token") ctx := r.Context() if token == "" { util.WriteResponse(w, http.StatusUnauthorized, "Error", "invalid token") return } client, err := app.Auth(ctx) if err != nil { util.WriteResponse(w, http.StatusInternalServerError, "Error", err.Error()) return } authToken, err := client.VerifyIDToken(ctx, token) if err != nil { util.WriteResponse(w, http.StatusUnauthorized, "Error", "unverifiable idToken") return } var privileges []string if str, ok := authToken.Claims["pr"].(string); ok { privileges = strings.Split(str, ":") } userID := "" if str, ok := authToken.Claims["cid"].(string); ok { userID = str } phoneNumber := "" if str, ok := authToken.Claims["phone_number"].(string); ok { phoneNumber = str } status := "" if str, ok := authToken.Claims["st"].(string); ok { status = str } userClaim := UserClaim{AuthID: authToken.UID, UserID: userID, PhoneNumber: phoneNumber, Privileges: privileges, Status: status} ctx = context.WithValue(ctx, UserClaimIDContextKey, userClaim) r = r.WithContext(ctx) h.ServeHTTP(w, r) }) return fn }