219 lines
5.6 KiB
Go
219 lines
5.6 KiB
Go
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)
|
|
}
|