package api_impl import ( "database/sql" "net/http" "atlas9.dev/c/core" "atlas9.dev/c/core/dbi" "atlas9.dev/c/core/iam" "atlas9.dev/c/demo/api" "atlas9.dev/c/demo/store" ) type ProfilesImpl struct { DB *sql.DB Users dbi.Factory[iam.UserStore] Profiles dbi.Factory[*store.ProfileStore] } func (s *ProfilesImpl) ServeMux(mux *http.ServeMux) { mux.HandleFunc(api.Path_Profiles_Get, s.Get) mux.HandleFunc(api.Path_Profiles_Save, s.Save) } func (s *ProfilesImpl) Get(w http.ResponseWriter, r *http.Request) { ctx := r.Context() userID, err := core.ParseID(iam.GetPrincipal(ctx).Subject) if err != nil { write(ctx, w, err, nil) return } var resUser iam.User var resProfile *store.Profile err = dbi.ReadOnly(ctx, s.DB, func(tx dbi.DBI) error { if err := s.Users(tx).Get(ctx, userID, &resUser); err != nil { return err } profile, err := s.Profiles(tx).Get(ctx, userID) if err == core.ErrNotFound { profile = &store.Profile{UserID: userID} } else if err != nil { return err } resProfile = profile return nil }) write(ctx, w, err, &api.Profiles_GetRes{User: &resUser, Profile: resProfile}) } func (s *ProfilesImpl) Save(w http.ResponseWriter, r *http.Request) { var req api.Profiles_SaveReq if read(w, r, &req) { return } ctx := r.Context() userID, err := core.ParseID(iam.GetPrincipal(ctx).Subject) if err != nil { write(ctx, w, err, nil) return } err = dbi.ReadWrite(ctx, s.DB, func(tx dbi.DBI) error { // Name lives on the user record, not the profile. Self-save is // allowed by the user store without extra caps. var user iam.User if err := s.Users(tx).Get(ctx, userID, &user); err != nil { return err } user.Name = req.Name if err := s.Users(tx).Save(ctx, &user); err != nil { return err } return s.Profiles(tx).Save(ctx, &store.Profile{ UserID: userID, Bio: req.Bio, Location: req.Location, Website: req.Website, PictureURL: req.PictureURL, }) }) write(ctx, w, err, nil) }