package database import ( "context" "encoding/json" "fmt" "strings" "edge-infra.dev/pkg/edge/iam/config" "edge-infra.dev/pkg/edge/iam/profile" "edge-infra.dev/pkg/edge/iam/util" "github.com/pkg/errors" "time" ) func (s *Store) CreateAlias(ctx context.Context, alias, subject string) (err error) { key := keyFrom(KeyPrefixAlias, alias) temp := make(map[string]string) temp["subject"] = strings.ToLower(subject) payload, err := json.Marshal(temp) if err != nil { return errors.WithStack(err) } if err := s.createDoc(ctx, key, payload); err != nil { return errors.Wrap(err, "failed to create alias") } return nil } func (s *Store) GetSubjectFromAlias(ctx context.Context, alias string) (subject string, err error) { key := keyFrom(KeyPrefixAlias, alias) var doc *Doc if doc, err = s.getDoc(ctx, key); err != nil { return "", errors.WithMessage(err, "failed to retrieve subject") } if doc == nil { return "", errors.New("alias not found") } data := doc.Value var value map[string]string err = json.Unmarshal(data, &value) if err != nil { return "", errors.WithMessage(err, "schema not valid") } return strings.ToLower(value["subject"]), nil } func (s *Store) CreateIdentityProfile(ctx context.Context, p profile.Profile) error { key := keyFrom(KeyPrefixProfile, p.Subject) p.LastUpdated = time.Now().Unix() payload, err := json.Marshal(p) if err != nil { return errors.WithStack(err) } if err := s.updateDoc(ctx, key, payload, WithExpiration(config.GetProfileTTL())); err != nil { return errors.Wrap(err, "failed to save profile") } return nil } func (s *Store) GetIdentityProfile(ctx context.Context, subject string) (profile *profile.Profile, err error) { key := keyFrom(KeyPrefixProfile, subject) var doc *Doc if doc, err = s.getDoc(ctx, key); err != nil { return nil, errors.WithMessage(err, "failed to retrieve profile") } if doc == nil { return nil, nil } data := doc.Value err = json.Unmarshal(data, &profile) if err != nil { return nil, errors.WithMessage(err, "profile schema not valid") } return profile, nil } func (s *Store) ExpireIdentityProfile(ctx context.Context, subject string) (err error) { profile, err := s.GetIdentityProfile(ctx, subject) if err != nil { return errors.WithStack(err) } if profile == nil { return fmt.Errorf("no such profile") } // set the profile last updated to a day ago... lastUpdated := time.Unix(profile.LastUpdated, 0) dayBefore := lastUpdated.AddDate(0, 0, -1) profile.LastUpdated = dayBefore.Unix() marshalledProfile, err := json.Marshal(profile) if err != nil { return errors.WithStack(err) } // save the updated profile key := keyFrom(KeyPrefixProfile, subject) if err := s.updateDoc(ctx, key, marshalledProfile); err != nil { return errors.Wrap(err, "failed to save profile") } return nil } func (s *Store) AddAliasToProfile(ctx context.Context, userProfile *profile.Profile) error { alias, _ := util.RandomStringGenerator(8) err := s.CreateAlias(ctx, alias, userProfile.Subject) if err != nil { return errors.Wrap(err, "failed to create alias") } userProfile.Alias = alias err = s.CreateIdentityProfile(ctx, *userProfile) if err != nil { return errors.Wrap(err, "failed to update profile with alias") } return nil } // type UserProfile struct { // Subject string `json:"sub"` // Roles string `json:"rls"` // Organization string `json:"org"` // LastUpdated int64 `json:"last_updated"` // } // type Profile struct { // Subject string `json:"sub"` // Organization string `json:"org"` // Roles string `json:"rls"` // LastUpdated int64 `json:"last_updated"` // } // func (s *Store) SaveProfile(ctx context.Context, p Profile) error { // key := keyFrom(KeyPrefixProfile, p.Subject) // p.LastUpdated = time.Now().Unix() // payload, err := json.Marshal(p) // if err != nil { // return errors.WithStack(err) // } // if err := s.DB.Set(key, payload, 0).Err(); err != nil { // return errors.Wrap(err, "failed to save profile") // } // return nil // } // func (s *Store) IsProfileExists(sub string) (bool, error) { // key := keyFrom(KeyPrefixProfile, sub) // _, err := s.DB.Get(key).Result() // if err == redis.Nil { // return false, fmt.Errorf("profile not exist. %v", err) // } else if err != nil { // return false, errors.WithStack(err) // } // return true, nil // } // func (s *Store) GetProfile(sub string) (*UserProfile, error) { // key := keyFrom(KeyPrefixProfile, sub) // res, err := s.DB.Get(key).Result() // if err != nil { // return nil, fmt.Errorf("failed to get profile. %v", err) // } // var schema UserProfile // if err := json.Unmarshal([]byte(res), &schema); err != nil { // return nil, err // } // return &schema, nil // } // func (s *Store) MarkProfileAsExpired(sub string) error { // key := keyFrom(KeyPrefixProfile, sub) // res, err := s.DB.Get(key).Result() // if err != nil { // return fmt.Errorf("failed to get profile. %v", err) // } // var profile UserProfile // if err := json.Unmarshal([]byte(res), &profile); err != nil { // return err // } // t := time.Unix(profile.LastUpdated, 0) // dayBack := t.AddDate(0, 0, -1) // profile.LastUpdated = dayBack.Unix() // marshalledProfile, err := json.Marshal(profile) // if err != nil { // return errors.WithStack(err) // } // if err := s.DB.Set(key, marshalledProfile, 0).Err(); err != nil { // return errors.Wrap(err, "failed to save profile") // } // return nil // }