package webdebug import ( "crypto/rand" "database/sql" "encoding/json" "encoding/pem" "fmt" "net/http" "strconv" "time" webutils "git.mstar.dev/mstar/goutils/http" "git.mstar.dev/mstar/goutils/other" "git.mstar.dev/mstar/goutils/sliceutils" "github.com/rs/zerolog/hlog" "git.mstar.dev/mstar/linstrom/activitypub" "git.mstar.dev/mstar/linstrom/shared" "git.mstar.dev/mstar/linstrom/storage-new/dbgen" "git.mstar.dev/mstar/linstrom/storage-new/models" webshared "git.mstar.dev/mstar/linstrom/web/shared" ) func getNonDeletedUsers(w http.ResponseWriter, r *http.Request) { log := hlog.FromRequest(r) pageStr := r.FormValue("page") page := 0 if pageStr != "" { var err error page, err = strconv.Atoi(pageStr) if err != nil { webutils.ProblemDetails( w, http.StatusBadRequest, "/errors/bad-page", "bad page number", other.IntoPointer("page number must be an uint"), nil, ) return } if page < 0 { webutils.ProblemDetails( w, http.StatusBadRequest, "/errors/bad-page", "bad page number", other.IntoPointer("page number must be >= 0"), nil, ) return } } users, err := dbgen.User.GetPagedAllNonDeleted(uint(page)) if err != nil { log.Error().Err(err).Int("page", page).Msg("Failed to get non-deleted users") webutils.ProblemDetails( w, http.StatusInternalServerError, "/errors/db-failure", "database failure", nil, nil, ) return } webutils.SendJson(w, sliceutils.Map(users, func(t models.User) webshared.User { u := webshared.User{} u.FromModel(&t) return u })) } func createLocalUser(w http.ResponseWriter, r *http.Request) { type Inbound struct { Username string `json:"username"` Displayname string `json:"displayname"` Description string `json:"description"` Birthday *time.Time `json:"birthday"` Location *string `json:"location"` IsBot bool `json:"is_bot"` } log := hlog.FromRequest(r) jsonDecoder := json.NewDecoder(r.Body) data := Inbound{} err := jsonDecoder.Decode(&data) if err != nil { webutils.ProblemDetails( w, http.StatusBadRequest, "/errors/bad-request-data", "bad request data", nil, map[string]any{ "sample": Inbound{ Username: "bob", Displayname: "Bob Bobbington", Description: "Bobbing Bobs bop to Bobs bobbing beats", Birthday: other.IntoPointer(time.Now()), Location: nil, IsBot: false, }, }, ) return } publicKeyEdBytes, privateKeyEdBytes, err := shared.GenerateKeypair(true) if err != nil { log.Error().Err(err).Msg("Failed to generate and marshal public key") webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError) return } publicKeyRsaBytes, privateKeyRsaBytes, err := shared.GenerateKeypair(false) if err != nil { log.Error().Err(err).Msg("Failed to generate and marshal public key") webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError) return } pkeyId := make([]byte, 64) _, err = rand.Read(pkeyId) if err != nil { log.Error().Err(err).Msg("Failed to generate passkey id") webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError) return } u := dbgen.User query := u.Select( u.Username, u.DisplayName, u.Description, u.IsBot, u.ServerId, u.PrivateKeyEd, u.PublicKeyEd, u.PrivateKeyRsa, u.PublicKeyRsa, u.PasskeyId, ) if data.Birthday != nil { query = query.Select(u.Birthday) } if data.Location != nil { query = query.Select(u.Location) } user := models.User{ Username: data.Username, DisplayName: data.Displayname, Description: data.Description, IsBot: data.IsBot, ServerId: 1, // Hardcoded, Self is always first ID PublicKeyRsa: publicKeyRsaBytes, PublicKeyEd: publicKeyEdBytes, PrivateKeyRsa: privateKeyRsaBytes, PrivateKeyEd: privateKeyEdBytes, PasskeyId: pkeyId, } if data.Birthday != nil { user.Birthday = sql.NullTime{Valid: true, Time: *data.Birthday} } if data.Location != nil { user.Location = sql.NullString{Valid: true, String: *data.Location} } if err = u.Create(&user); err != nil { log.Error().Err(err).Msg("failed to create new local user") webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError) } } func deleteUser(w http.ResponseWriter, r *http.Request) { id := r.FormValue("id") dbgen.User.Where(dbgen.User.ID.Eq(id)).Delete() w.WriteHeader(http.StatusOK) } func returnKeypair(w http.ResponseWriter, r *http.Request) { id := r.FormValue("id") user, err := dbgen.User.Where(dbgen.User.ID.Eq(id)).First() if err != nil { return } err = shared.SanityCheckX509dRsaKeys(user.PublicKeyRsa, user.PrivateKeyRsa) if err != nil { hlog.FromRequest(r).Error().Err(err).Msg("Sanity check failed") } privKeyBlock := pem.Block{ Type: "RSA PRIVATE KEY", Bytes: user.PrivateKeyRsa, } if err != nil { hlog.FromRequest(r).Error().Err(err).Msg("Sanity check failed") } privKeyPem := pem.EncodeToMemory(&privKeyBlock) pubKeyPen := []byte(shared.KeyBytesToPem(user.PublicKeyRsa)) err = shared.SanityCheckPemdRsaKeys(pubKeyPen, privKeyPem) if err != nil { hlog.FromRequest(r).Error().Err(err).Msg("Pem Sanity check failed") } fmt.Fprintf(w, "%s\n\n%s", privKeyPem, pubKeyPen) } func issueUserImport(w http.ResponseWriter, r *http.Request) { target := r.FormValue("target") _, err := activitypub.ImportRemoteAccount(target) hlog.FromRequest(r).Info().Err(err).Msg("Err from import request") } func kickoffFollow(w http.ResponseWriter, r *http.Request) { type Inbound struct { Id string Target string } var data Inbound dec := json.NewDecoder(r.Body) dec.Decode(&data) }