Work on following relations api and small docs
This commit is contained in:
parent
526b5c2fef
commit
f656757710
3 changed files with 217 additions and 22 deletions
|
@ -1,6 +1,11 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import "net/http"
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"gitlab.com/mstarongitlab/goutils/other"
|
||||||
|
"gitlab.com/mstarongitlab/linstrom/storage"
|
||||||
|
)
|
||||||
|
|
||||||
func setupLinstromApiRouter() http.Handler {
|
func setupLinstromApiRouter() http.Handler {
|
||||||
router := http.NewServeMux()
|
router := http.NewServeMux()
|
||||||
|
@ -12,25 +17,50 @@ func setupLinstromApiRouter() http.Handler {
|
||||||
|
|
||||||
func setupLinstromApiV1Router() http.Handler {
|
func setupLinstromApiV1Router() http.Handler {
|
||||||
router := http.NewServeMux()
|
router := http.NewServeMux()
|
||||||
|
|
||||||
// Notes
|
// Notes
|
||||||
|
|
||||||
|
// Get a note
|
||||||
router.HandleFunc("GET /notes/{noteId}", linstromGetNote)
|
router.HandleFunc("GET /notes/{noteId}", linstromGetNote)
|
||||||
|
// Send a new note
|
||||||
router.HandleFunc("POST /notes", linstromNewNote)
|
router.HandleFunc("POST /notes", linstromNewNote)
|
||||||
|
// Update a note
|
||||||
router.HandleFunc("PATCH /notes/{noteId}", linstromUpdateNote)
|
router.HandleFunc("PATCH /notes/{noteId}", linstromUpdateNote)
|
||||||
|
// Delete a note
|
||||||
router.HandleFunc("DELETE /notes/{noteId}", linstromDeleteNote)
|
router.HandleFunc("DELETE /notes/{noteId}", linstromDeleteNote)
|
||||||
|
|
||||||
// Reactions
|
// Reactions
|
||||||
|
|
||||||
|
// Get all reactions for a note
|
||||||
router.HandleFunc("GET /notes/{noteId}/reactions", linstromGetReactions)
|
router.HandleFunc("GET /notes/{noteId}/reactions", linstromGetReactions)
|
||||||
|
// Send a new reaction to a note
|
||||||
router.HandleFunc("POST /notes/{noteId}/reactions", linstromAddReaction)
|
router.HandleFunc("POST /notes/{noteId}/reactions", linstromAddReaction)
|
||||||
|
// Update own reaction on a note
|
||||||
router.HandleFunc("PATCH /notes/{noteId}/reactions", linstromUpdateReaction)
|
router.HandleFunc("PATCH /notes/{noteId}/reactions", linstromUpdateReaction)
|
||||||
|
// Remove own reaction on a note
|
||||||
router.HandleFunc("DELETE /notes/{noteId}/reactions", linstromDeleteReaction)
|
router.HandleFunc("DELETE /notes/{noteId}/reactions", linstromDeleteReaction)
|
||||||
|
|
||||||
// Boosts
|
// Boosts
|
||||||
|
|
||||||
|
// Get all boosters of a note
|
||||||
router.HandleFunc("GET /notes/{noteId}/boosts", linstromGetBoosts)
|
router.HandleFunc("GET /notes/{noteId}/boosts", linstromGetBoosts)
|
||||||
|
// Boost a note
|
||||||
router.HandleFunc("POST /notes/{noteId}/boosts", linstromAddBoost)
|
router.HandleFunc("POST /notes/{noteId}/boosts", linstromAddBoost)
|
||||||
|
// Unboost a note
|
||||||
router.HandleFunc("DELETE /notes/{noteId}/boosts", linstromRemoveBoost)
|
router.HandleFunc("DELETE /notes/{noteId}/boosts", linstromRemoveBoost)
|
||||||
|
|
||||||
// Quotes
|
// Quotes
|
||||||
|
|
||||||
|
// Get all quotes of a note
|
||||||
router.HandleFunc("GET /notes/{noteId}/quotes", linstromGetQuotes)
|
router.HandleFunc("GET /notes/{noteId}/quotes", linstromGetQuotes)
|
||||||
|
// Create a new quote message of a given note
|
||||||
router.HandleFunc("POST /notes/{noteId}/quotes", linstromAddQuote)
|
router.HandleFunc("POST /notes/{noteId}/quotes", linstromAddQuote)
|
||||||
|
|
||||||
// Pinning
|
// Pinning
|
||||||
|
|
||||||
|
// Pin a note to account profile
|
||||||
router.HandleFunc("POST /notes/{noteId}/pin", linstromPinNote)
|
router.HandleFunc("POST /notes/{noteId}/pin", linstromPinNote)
|
||||||
|
// Unpin a note from account profile
|
||||||
router.HandleFunc("DELETE /notes/{noteId}/pin", linstromUnpinNote)
|
router.HandleFunc("DELETE /notes/{noteId}/pin", linstromUnpinNote)
|
||||||
// Reports
|
// Reports
|
||||||
router.HandleFunc("POST /notes/{noteId}/report", linstromReportNote)
|
router.HandleFunc("POST /notes/{noteId}/report", linstromReportNote)
|
||||||
|
@ -40,7 +70,10 @@ func setupLinstromApiV1Router() http.Handler {
|
||||||
|
|
||||||
// Accounts
|
// Accounts
|
||||||
// Creating a new account happens either during fetch of a remote one or during registration with a passkey
|
// Creating a new account happens either during fetch of a remote one or during registration with a passkey
|
||||||
|
|
||||||
|
// Get an account
|
||||||
router.HandleFunc("GET /accounts/{accountId}", linstromGetAccount)
|
router.HandleFunc("GET /accounts/{accountId}", linstromGetAccount)
|
||||||
|
// Update own account
|
||||||
// Technically also requires authenticated account to also be owner or correct admin perms,
|
// Technically also requires authenticated account to also be owner or correct admin perms,
|
||||||
// but that's annoying to handle in a general sense. So leaving that to the function
|
// but that's annoying to handle in a general sense. So leaving that to the function
|
||||||
// though figuring out a nice generic-ish way to handle those checks would be nice too
|
// though figuring out a nice generic-ish way to handle those checks would be nice too
|
||||||
|
@ -48,6 +81,7 @@ func setupLinstromApiV1Router() http.Handler {
|
||||||
"PATCH /accounts/{accountId}",
|
"PATCH /accounts/{accountId}",
|
||||||
requireValidSessionMiddleware(linstromUpdateAccount),
|
requireValidSessionMiddleware(linstromUpdateAccount),
|
||||||
)
|
)
|
||||||
|
// Delete own account
|
||||||
// Technically also requires authenticated account to also be owner or correct admin perms,
|
// Technically also requires authenticated account to also be owner or correct admin perms,
|
||||||
// but that's annoying to handle in a general sense. So leaving that to the function
|
// but that's annoying to handle in a general sense. So leaving that to the function
|
||||||
router.HandleFunc(
|
router.HandleFunc(
|
||||||
|
@ -55,38 +89,87 @@ func setupLinstromApiV1Router() http.Handler {
|
||||||
requireValidSessionMiddleware(linstromDeleteAccount),
|
requireValidSessionMiddleware(linstromDeleteAccount),
|
||||||
)
|
)
|
||||||
// Follow
|
// Follow
|
||||||
router.HandleFunc("GET /accounts/{accountId}/follow", linstromIsFollowingAccount)
|
// Is logged in following accountId
|
||||||
router.HandleFunc("POST /accounts/{accountId}/follow", linstromFollowAccount)
|
|
||||||
router.HandleFunc("DELETE /accounts/{accountId}/follow", linstromUnfollowAccount)
|
|
||||||
// Block
|
|
||||||
router.HandleFunc("GET /accounts/{accountId}/block", linstromIsBlockingAccount)
|
|
||||||
router.HandleFunc("POST /accounts/{accountId}/block", linstromBlockAccount)
|
|
||||||
router.HandleFunc("DELETE /accounts/{accountId}/block", linstromUnblockAccount)
|
|
||||||
// Mute
|
|
||||||
router.HandleFunc("GET /accounts/{accountId}/mute", linstromIsMutedAccount)
|
|
||||||
router.HandleFunc("POST /accounts/{accountId}/mute", linstromMuteAccount)
|
|
||||||
router.HandleFunc("DELETE /accounts/{accountId}/mute", linstromUnmuteAccount)
|
|
||||||
// Report
|
|
||||||
router.HandleFunc("POST /accounts/{accountId}/reports", linstromReportAccount)
|
|
||||||
router.HandleFunc("DELETE /accounts/{accountId}/reports", linstromRetractReportAccount)
|
|
||||||
// Admin
|
|
||||||
router.HandleFunc("POST /accounts/{accountId}/admin/roles", linstromAdminAddRoleAccount)
|
|
||||||
router.HandleFunc(
|
router.HandleFunc(
|
||||||
"DELETE /accounts/{accountId}/admin/roles/{roleName}",
|
"GET /accounts/{accountId}/follow/to",
|
||||||
linstromAdminRemoveRoleAccount,
|
requireValidSessionMiddleware(linstromIsFollowingToAccount),
|
||||||
)
|
)
|
||||||
|
// Is accountId following logged in
|
||||||
|
router.HandleFunc(
|
||||||
|
"GET /accounts/{accountId}/follow/from",
|
||||||
|
requireValidSessionMiddleware(linstromIsFollowingFromAccount),
|
||||||
|
)
|
||||||
|
// Send follow request to accountId
|
||||||
|
router.HandleFunc("POST /accounts/{accountId}/follow", linstromFollowAccount)
|
||||||
|
// Undo follow request to accountId
|
||||||
|
router.HandleFunc("DELETE /accounts/{accountId}/follow", linstromUnfollowAccount)
|
||||||
|
|
||||||
|
// Block
|
||||||
|
|
||||||
|
// Is logged in account blocking target account
|
||||||
|
router.HandleFunc("GET /accounts/{accountId}/block", linstromIsBlockingAccount)
|
||||||
|
// Block target account
|
||||||
|
router.HandleFunc("POST /accounts/{accountId}/block", linstromBlockAccount)
|
||||||
|
// Unblock target account
|
||||||
|
router.HandleFunc("DELETE /accounts/{accountId}/block", linstromUnblockAccount)
|
||||||
|
|
||||||
|
// Mute
|
||||||
|
|
||||||
|
// Has logged in account muted target account?
|
||||||
|
router.HandleFunc("GET /accounts/{accountId}/mute", linstromIsMutedAccount)
|
||||||
|
// Mute target account
|
||||||
|
router.HandleFunc("POST /accounts/{accountId}/mute", linstromMuteAccount)
|
||||||
|
// Unmute target account
|
||||||
|
router.HandleFunc("DELETE /accounts/{accountId}/mute", linstromUnmuteAccount)
|
||||||
|
|
||||||
|
// Report
|
||||||
|
|
||||||
|
// Report a target account
|
||||||
|
router.HandleFunc("POST /accounts/{accountId}/reports", linstromReportAccount)
|
||||||
|
// Undo report on target account
|
||||||
|
router.HandleFunc("DELETE /accounts/{accountId}/reports", linstromRetractReportAccount)
|
||||||
|
|
||||||
|
// Admin
|
||||||
|
|
||||||
|
// Add new role to account
|
||||||
|
router.Handle(
|
||||||
|
"POST /accounts/{accountId}/admin/roles",
|
||||||
|
buildRequirePermissionsMiddleware(
|
||||||
|
&storage.Role{CanAssignRoles: other.IntoPointer(true)},
|
||||||
|
)(
|
||||||
|
http.HandlerFunc(linstromAdminAddRoleAccount),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// Remove role from account
|
||||||
|
router.Handle(
|
||||||
|
"DELETE /accounts/{accountId}/admin/roles/{roleName}",
|
||||||
|
buildRequirePermissionsMiddleware(&storage.Role{CanAssignRoles: other.IntoPointer(true)})(
|
||||||
|
http.HandlerFunc(linstromAdminRemoveRoleAccount),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// Send a warning to account
|
||||||
router.HandleFunc("POST /accounts/{accountId}/admin/warn", linstromAdminWarnAccount)
|
router.HandleFunc("POST /accounts/{accountId}/admin/warn", linstromAdminWarnAccount)
|
||||||
|
|
||||||
// Roles
|
// Roles
|
||||||
|
|
||||||
|
// Get a role
|
||||||
router.HandleFunc("GET /roles/{roleId}", linstromGetRole)
|
router.HandleFunc("GET /roles/{roleId}", linstromGetRole)
|
||||||
|
// Create a new role
|
||||||
router.HandleFunc("POST /roles", linstromCreateRole)
|
router.HandleFunc("POST /roles", linstromCreateRole)
|
||||||
|
// Update a role. Builtin roles cannot be edited
|
||||||
router.HandleFunc("PATCH /roles/{roleId}", linstromUpdateRole)
|
router.HandleFunc("PATCH /roles/{roleId}", linstromUpdateRole)
|
||||||
|
// Delete a role. Builtin roles cannot be deleted
|
||||||
router.HandleFunc("DELETE /roles/{roleId}", linstromDeleteRole)
|
router.HandleFunc("DELETE /roles/{roleId}", linstromDeleteRole)
|
||||||
|
|
||||||
// Media metadata
|
// Media metadata
|
||||||
|
|
||||||
|
// Get the metadata for some media
|
||||||
router.HandleFunc("GET /media/{mediaId}", linstromGetMediaMetadata)
|
router.HandleFunc("GET /media/{mediaId}", linstromGetMediaMetadata)
|
||||||
|
// Upload new media
|
||||||
router.HandleFunc("POST /media", linstromNewMediaMetadata)
|
router.HandleFunc("POST /media", linstromNewMediaMetadata)
|
||||||
|
// Update the metadata for some media
|
||||||
router.HandleFunc("PATCH /media/{mediaId}", linstromUpdateMediaMetadata)
|
router.HandleFunc("PATCH /media/{mediaId}", linstromUpdateMediaMetadata)
|
||||||
|
// Delete a media entry
|
||||||
router.HandleFunc("DELETE /media/{mediaId}", linstromDeleteMediaMetadata)
|
router.HandleFunc("DELETE /media/{mediaId}", linstromDeleteMediaMetadata)
|
||||||
|
|
||||||
// Event streams
|
// Event streams
|
||||||
|
|
|
@ -165,6 +165,7 @@ func linstromUpdateAccount(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Error().Err(err).Msg("Failed to marshal and write updated account")
|
log.Error().Err(err).Msg("Failed to marshal and write updated account")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func linstromDeleteAccount(w http.ResponseWriter, r *http.Request) {
|
func linstromDeleteAccount(w http.ResponseWriter, r *http.Request) {
|
||||||
actorId, _ := ActorIdFromRequest(r)
|
actorId, _ := ActorIdFromRequest(r)
|
||||||
log := hlog.FromRequest(r)
|
log := hlog.FromRequest(r)
|
||||||
|
@ -238,9 +239,119 @@ func linstromDeleteAccount(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func linstromIsFollowingAccount(w http.ResponseWriter, r *http.Request) {}
|
// Is logged in following accountId
|
||||||
func linstromFollowAccount(w http.ResponseWriter, r *http.Request) {}
|
func linstromIsFollowingToAccount(w http.ResponseWriter, r *http.Request) {
|
||||||
func linstromUnfollowAccount(w http.ResponseWriter, r *http.Request) {}
|
store := StorageFromRequest(r)
|
||||||
|
log := hlog.FromRequest(r)
|
||||||
|
actorId, _ := ActorIdFromRequest(r)
|
||||||
|
targetId := AccountIdFromRequest(r)
|
||||||
|
|
||||||
|
relation, err := store.GetRelationBetween(actorId, targetId)
|
||||||
|
var outData linstromRelation
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
outData = linstromRelation{
|
||||||
|
Id: relation.ID,
|
||||||
|
CreatedAt: relation.CreatedAt,
|
||||||
|
UpdatedAt: relation.UpdatedAt,
|
||||||
|
FromId: relation.FromId,
|
||||||
|
ToId: relation.ToId,
|
||||||
|
Accepted: relation.Accepted,
|
||||||
|
Requested: true,
|
||||||
|
}
|
||||||
|
case storage.ErrEntryNotFound:
|
||||||
|
outData = linstromRelation{
|
||||||
|
Id: relation.ID,
|
||||||
|
CreatedAt: relation.CreatedAt,
|
||||||
|
UpdatedAt: relation.UpdatedAt,
|
||||||
|
FromId: relation.FromId,
|
||||||
|
ToId: relation.ToId,
|
||||||
|
Accepted: false,
|
||||||
|
Requested: false,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Str("from-id", actorId).
|
||||||
|
Str("to-id", targetId).
|
||||||
|
Msg("Failed to get follow relation")
|
||||||
|
other.HttpErr(
|
||||||
|
w,
|
||||||
|
HttpErrIdDbFailure,
|
||||||
|
"Failed to get relation",
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = jsonapi.MarshalPayload(w, outData)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Err(err).Msg("Failed to marshal response")
|
||||||
|
other.HttpErr(
|
||||||
|
w,
|
||||||
|
HttpErrIdJsonMarshalFail,
|
||||||
|
"Failed to marshal response",
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func linstromIsFollowingFromAccount(w http.ResponseWriter, r *http.Request) {
|
||||||
|
store := StorageFromRequest(r)
|
||||||
|
log := hlog.FromRequest(r)
|
||||||
|
actorId, _ := ActorIdFromRequest(r)
|
||||||
|
targetId := AccountIdFromRequest(r)
|
||||||
|
|
||||||
|
relation, err := store.GetRelationBetween(targetId, actorId)
|
||||||
|
var outData linstromRelation
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
outData = linstromRelation{
|
||||||
|
Id: relation.ID,
|
||||||
|
CreatedAt: relation.CreatedAt,
|
||||||
|
UpdatedAt: relation.UpdatedAt,
|
||||||
|
FromId: relation.FromId,
|
||||||
|
ToId: relation.ToId,
|
||||||
|
Accepted: relation.Accepted,
|
||||||
|
Requested: true,
|
||||||
|
}
|
||||||
|
case storage.ErrEntryNotFound:
|
||||||
|
outData = linstromRelation{
|
||||||
|
Id: relation.ID,
|
||||||
|
CreatedAt: relation.CreatedAt,
|
||||||
|
UpdatedAt: relation.UpdatedAt,
|
||||||
|
FromId: relation.FromId,
|
||||||
|
ToId: relation.ToId,
|
||||||
|
Accepted: false,
|
||||||
|
Requested: false,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Str("from-id", targetId).
|
||||||
|
Str("to-id", actorId).
|
||||||
|
Msg("Failed to get follow relation")
|
||||||
|
other.HttpErr(
|
||||||
|
w,
|
||||||
|
HttpErrIdDbFailure,
|
||||||
|
"Failed to get relation",
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = jsonapi.MarshalPayload(w, outData)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Err(err).Msg("Failed to marshal response")
|
||||||
|
other.HttpErr(
|
||||||
|
w,
|
||||||
|
HttpErrIdJsonMarshalFail,
|
||||||
|
"Failed to marshal response",
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func linstromFollowAccount(w http.ResponseWriter, r *http.Request) {}
|
||||||
|
func linstromUnfollowAccount(w http.ResponseWriter, r *http.Request) {}
|
||||||
|
|
||||||
func linstromIsBlockingAccount(w http.ResponseWriter, r *http.Request) {}
|
func linstromIsBlockingAccount(w http.ResponseWriter, r *http.Request) {}
|
||||||
func linstromBlockAccount(w http.ResponseWriter, r *http.Request) {}
|
func linstromBlockAccount(w http.ResponseWriter, r *http.Request) {}
|
||||||
|
|
|
@ -96,6 +96,7 @@ type linstromRelation struct {
|
||||||
UpdatedAt time.Time `jsonapi:"attr,updated-at"`
|
UpdatedAt time.Time `jsonapi:"attr,updated-at"`
|
||||||
FromId string `jsonapi:"attr,from-id"`
|
FromId string `jsonapi:"attr,from-id"`
|
||||||
ToId string `jsonapi:"attr,to-id"`
|
ToId string `jsonapi:"attr,to-id"`
|
||||||
|
Requested bool `jsonapi:"attr,requested"`
|
||||||
Accepted bool `jsonapi:"attr,accepted"`
|
Accepted bool `jsonapi:"attr,accepted"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue