Feed insertions and other feed stuff
This commit is contained in:
parent
72e1c67488
commit
5232bb0741
7 changed files with 134 additions and 8 deletions
2
go.mod
2
go.mod
|
@ -3,6 +3,7 @@ module git.mstar.dev/mstar/linstrom
|
||||||
go 1.24.2
|
go 1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
golang.org/x/sync v0.15.0
|
||||||
git.mstar.dev/mstar/goutils v1.16.1
|
git.mstar.dev/mstar/goutils v1.16.1
|
||||||
github.com/BurntSushi/toml v1.5.0
|
github.com/BurntSushi/toml v1.5.0
|
||||||
github.com/PeerDB-io/gluabit32 v1.0.2
|
github.com/PeerDB-io/gluabit32 v1.0.2
|
||||||
|
@ -80,7 +81,6 @@ require (
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
golang.org/x/mod v0.24.0 // indirect
|
golang.org/x/mod v0.24.0 // indirect
|
||||||
golang.org/x/net v0.39.0 // indirect
|
golang.org/x/net v0.39.0 // indirect
|
||||||
golang.org/x/sync v0.15.0 // indirect
|
|
||||||
golang.org/x/text v0.24.0 // indirect
|
golang.org/x/text v0.24.0 // indirect
|
||||||
golang.org/x/tools v0.32.0 // indirect
|
golang.org/x/tools v0.32.0 // indirect
|
||||||
gorm.io/datatypes v1.2.5 // indirect
|
gorm.io/datatypes v1.2.5 // indirect
|
||||||
|
|
|
@ -594,6 +594,7 @@ type IUserToUserRelationDo interface {
|
||||||
GetFollowingApLinksPagedForId(id string, page int) (result []string, err error)
|
GetFollowingApLinksPagedForId(id string, page int) (result []string, err error)
|
||||||
CountFollowersForId(id string) (result int, err error)
|
CountFollowersForId(id string) (result int, err error)
|
||||||
CountFollowingForId(id string) (result int, err error)
|
CountFollowingForId(id string) (result int, err error)
|
||||||
|
GetLocalFollowerIdsOfId(id string) (result []string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all inbox links for accounts following the user with the specified id
|
// Get all inbox links for accounts following the user with the specified id
|
||||||
|
@ -720,6 +721,34 @@ func (u userToUserRelationDo) CountFollowingForId(id string) (result int, err er
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the ids of all local accounts following the user with the target id
|
||||||
|
//
|
||||||
|
// SELECT
|
||||||
|
// r.user_id
|
||||||
|
// FROM
|
||||||
|
//
|
||||||
|
// user_to_user_relations r
|
||||||
|
// LEFT JOIN users u ON r.user_id = u.id
|
||||||
|
// LEFT JOIN remote_servers s ON u.server_id = s.id
|
||||||
|
//
|
||||||
|
// WHERE
|
||||||
|
//
|
||||||
|
// s.is_self = true
|
||||||
|
// AND r.target_user_id = @id;
|
||||||
|
func (u userToUserRelationDo) GetLocalFollowerIdsOfId(id string) (result []string, err error) {
|
||||||
|
var params []interface{}
|
||||||
|
|
||||||
|
var generateSQL strings.Builder
|
||||||
|
params = append(params, id)
|
||||||
|
generateSQL.WriteString("SELECT r.user_id FROM user_to_user_relations r LEFT JOIN users u ON r.user_id = u.id LEFT JOIN remote_servers s ON u.server_id = s.id WHERE s.is_self = true AND r.target_user_id = ?; ")
|
||||||
|
|
||||||
|
var executeSQL *gorm.DB
|
||||||
|
executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert
|
||||||
|
err = executeSQL.Error
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (u userToUserRelationDo) Debug() IUserToUserRelationDo {
|
func (u userToUserRelationDo) Debug() IUserToUserRelationDo {
|
||||||
return u.withDO(u.DO.Debug())
|
return u.withDO(u.DO.Debug())
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,3 +34,4 @@ type Feed struct {
|
||||||
|
|
||||||
// Suffix added to feeds created as the default feed for a user
|
// Suffix added to feeds created as the default feed for a user
|
||||||
const FeedDefaultSuffix = "-default"
|
const FeedDefaultSuffix = "-default"
|
||||||
|
const GlobalFeedName = "global"
|
||||||
|
|
|
@ -71,4 +71,17 @@ type IUserToUserRelation interface {
|
||||||
// r.user_id = @id AND
|
// r.user_id = @id AND
|
||||||
// r.relation = 'follow'
|
// r.relation = 'follow'
|
||||||
CountFollowingForId(id string) (int, error)
|
CountFollowingForId(id string) (int, error)
|
||||||
|
|
||||||
|
// Get the ids of all local accounts following the user with the target id
|
||||||
|
//
|
||||||
|
// SELECT
|
||||||
|
// r.user_id
|
||||||
|
// FROM
|
||||||
|
// user_to_user_relations r
|
||||||
|
// LEFT JOIN users u ON r.user_id = u.id
|
||||||
|
// LEFT JOIN remote_servers s ON u.server_id = s.id
|
||||||
|
// WHERE
|
||||||
|
// s.is_self = true
|
||||||
|
// AND r.target_user_id = @id;
|
||||||
|
GetLocalFollowerIdsOfId(id string) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,9 @@ func InsertSelf() error {
|
||||||
if err = attachUserToRole(user); err != nil {
|
if err = attachUserToRole(user); err != nil {
|
||||||
return other.Error("storage", "failed to save/update self user to full admin role", err)
|
return other.Error("storage", "failed to save/update self user to full admin role", err)
|
||||||
}
|
}
|
||||||
|
if err = insertGlobalFeed(user); err != nil {
|
||||||
|
return other.Error("storage", "failed to ensure that the global feed exists", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,3 +218,26 @@ func attachUserToRole(user *models.User) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func insertGlobalFeed(serverActor *models.User) error {
|
||||||
|
globalFeed, err := dbgen.Feed.Where(dbgen.Feed.Name.Eq(models.GlobalFeedName)).First()
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
|
case gorm.ErrRecordNotFound:
|
||||||
|
globalFeed = &models.Feed{
|
||||||
|
Owner: *serverActor,
|
||||||
|
OwnerId: serverActor.ID,
|
||||||
|
IsDefault: true,
|
||||||
|
Name: models.GlobalFeedName,
|
||||||
|
PublicKey: sql.NullString{Valid: false},
|
||||||
|
}
|
||||||
|
err = dbgen.Feed.Create(globalFeed)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,22 +24,29 @@ type Server struct {
|
||||||
|
|
||||||
func New(addr string) *Server {
|
func New(addr string) *Server {
|
||||||
handler := http.NewServeMux()
|
handler := http.NewServeMux()
|
||||||
handler.HandleFunc("GET /non-deleted", getNonDeletedUsers)
|
|
||||||
handler.HandleFunc("POST /local-user", createLocalUser)
|
handler.HandleFunc("POST /local-user", createLocalUser)
|
||||||
handler.HandleFunc("GET /delete", deleteUser)
|
|
||||||
handler.HandleFunc("POST /post-as", postAs)
|
handler.HandleFunc("POST /post-as", postAs)
|
||||||
handler.HandleFunc("GET /notes-for", notesFrom)
|
|
||||||
handler.HandleFunc("GET /import-user", issueUserImport)
|
|
||||||
handler.HandleFunc("GET /keys-for", returnKeypair)
|
handler.HandleFunc("GET /keys-for", returnKeypair)
|
||||||
handler.HandleFunc("GET /import-server", importServerInfo)
|
handler.HandleFunc("GET /import-user", issueUserImport)
|
||||||
handler.HandleFunc("GET /request-follow", requestFollow)
|
handler.HandleFunc("GET /request-follow", requestFollow)
|
||||||
handler.HandleFunc("POST /send-as", proxyMessageToTarget)
|
handler.HandleFunc("POST /send-as", proxyMessageToTarget)
|
||||||
|
handler.HandleFunc("POST /follow", requestFollow)
|
||||||
|
handler.HandleFunc("POST /update-user", updateUser)
|
||||||
|
|
||||||
|
handler.HandleFunc("GET /non-deleted", getNonDeletedUsers)
|
||||||
|
handler.HandleFunc("GET /delete", deleteUser)
|
||||||
|
handler.HandleFunc("GET /notes-for", notesFrom)
|
||||||
|
handler.HandleFunc("GET /import-server", importServerInfo)
|
||||||
handler.HandleFunc("GET /replies-to/{id}", inReplyTo)
|
handler.HandleFunc("GET /replies-to/{id}", inReplyTo)
|
||||||
handler.HandleFunc("POST /fetch", requestAs)
|
handler.HandleFunc("POST /fetch", requestAs)
|
||||||
handler.HandleFunc("POST /follow", requestFollow)
|
handler.HandleFunc("POST /like-note", likeNote)
|
||||||
|
handler.HandleFunc("POST /boost-note", boostNote)
|
||||||
|
|
||||||
|
handler.HandleFunc("GET /files-owned-by", getOwnedFiles)
|
||||||
handler.HandleFunc("POST /upload-file", uploadMedia)
|
handler.HandleFunc("POST /upload-file", uploadMedia)
|
||||||
handler.HandleFunc("/force-media-sync", forceMediaSync)
|
handler.HandleFunc("/force-media-sync", forceMediaSync)
|
||||||
handler.HandleFunc("GET /files-owned-by", getOwnedFiles)
|
|
||||||
web := http.Server{
|
web := http.Server{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
Handler: webutils.ChainMiddlewares(
|
Handler: webutils.ChainMiddlewares(
|
||||||
|
|
|
@ -448,3 +448,53 @@ func requestAs(w http.ResponseWriter, r *http.Request) {
|
||||||
body, _ := io.ReadAll(res.Body)
|
body, _ := io.ReadAll(res.Body)
|
||||||
_, _ = fmt.Fprint(w, string(body))
|
_, _ = fmt.Fprint(w, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateUser(w http.ResponseWriter, r *http.Request) {
|
||||||
|
type Inbound struct {
|
||||||
|
UserId string
|
||||||
|
Displayname *string
|
||||||
|
Description *string
|
||||||
|
RestrictedFollow *bool
|
||||||
|
}
|
||||||
|
log := hlog.FromRequest(r)
|
||||||
|
var data Inbound
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&data)
|
||||||
|
if err != nil {
|
||||||
|
_ = webutils.ProblemDetailsStatusOnly(w, http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
queryStart := dbgen.User.Where(dbgen.User.ID.Eq(data.UserId))
|
||||||
|
user, err := queryStart.First()
|
||||||
|
switch err {
|
||||||
|
case gorm.ErrRecordNotFound:
|
||||||
|
_ = webutils.ProblemDetailsStatusOnly(w, http.StatusNotFound)
|
||||||
|
return
|
||||||
|
case nil:
|
||||||
|
default:
|
||||||
|
log.Error().Err(err).Msg("Db error while trying to fetch user for updating")
|
||||||
|
_ = webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateNeeded := false
|
||||||
|
if data.Displayname != nil {
|
||||||
|
user.DisplayName = *data.Displayname
|
||||||
|
updateNeeded = true
|
||||||
|
}
|
||||||
|
if data.Description != nil {
|
||||||
|
user.Description = *data.Description
|
||||||
|
updateNeeded = true
|
||||||
|
}
|
||||||
|
if data.RestrictedFollow != nil {
|
||||||
|
user.RestrictedFollow = *data.RestrictedFollow
|
||||||
|
updateNeeded = true
|
||||||
|
}
|
||||||
|
if !updateNeeded {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = queryStart.Save(user)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to update user with new data")
|
||||||
|
_ = webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue