More API progress

This time mainly helper functions for converting an account and
associated types into their API representation
This commit is contained in:
Melody Becker 2024-11-04 07:48:46 +01:00
parent 873f52d64f
commit a653477e7f
8 changed files with 201 additions and 7 deletions

View file

@ -3,7 +3,10 @@ package server
import (
"net/http"
"github.com/google/jsonapi"
"github.com/rs/zerolog/hlog"
"gitlab.com/mstarongitlab/goutils/other"
"gitlab.com/mstarongitlab/linstrom/storage"
)
// No create account. That happens during passkey registration
@ -11,8 +14,45 @@ import (
func linstromGetAccount(w http.ResponseWriter, r *http.Request) {
store := StorageFromRequest(r)
log := hlog.FromRequest(r)
accId := AccountIdFromRequest(r)
acc, err := store.FindAccountById(accId)
switch err {
case nil:
// Ok, do nothing
case storage.ErrEntryNotFound:
other.HttpErr(w, HttpErrIdNotFound, "account not found", http.StatusNotFound)
return
default:
log.Error().Err(err).Str("account-id", accId).Msg("Failed to get account from storage")
other.HttpErr(
w,
HttpErrIdDbFailure,
"Failed to get account from storage",
http.StatusInternalServerError,
)
return
}
// TODO: Check if caller is actually allowed to view the account requested.
outAccount, err := convertAccountStorageToLinstrom(acc, store)
if err != nil {
log.Error().
Err(err).
Msg("Failed to convert storage account (and attached data) into linstrom API representation")
other.HttpErr(
w,
HttpErrIdConverionFailure,
"Failed to convert storage account and attached data into API representation",
http.StatusInternalServerError,
)
return
}
err = jsonapi.MarshalPayload(w, outAccount)
if err != nil {
log.Error().Err(err).Any("account", outAccount).Msg("Failed to marshal and write account")
}
}
func linstromUpdateAccount(w http.ResponseWriter, r *http.Request) {}
func linstromDeleteAccount(w http.ResponseWriter, r *http.Request) {}

View file

@ -0,0 +1,109 @@
package server
import (
"gitlab.com/mstarongitlab/goutils/sliceutils"
"gitlab.com/mstarongitlab/linstrom/storage"
)
func convertAccountStorageToLinstrom(
acc *storage.Account,
store *storage.Storage,
) (*linstromAccount, error) {
storageServer, err := store.FindRemoteServerById(acc.ServerId)
if err != nil {
return nil, err
}
apiServer, err := convertServerStorageToLinstrom(storageServer, store)
if err != nil {
return nil, err
}
storageIcon, err := store.GetMediaMetadataById(acc.Icon)
if err != nil {
return nil, err
}
storageBanner, err := store.GetMediaMetadataById(acc.Banner)
if err != nil {
return nil, err
}
storageFields, err := store.FindMultipleUserFieldsById(acc.CustomFields)
if err != nil {
return nil, err
}
return &linstromAccount{
Id: acc.ID,
CreatedAt: acc.CreatedAt,
UpdatedAt: &acc.UpdatedAt,
Username: acc.Username,
OriginServer: apiServer,
OriginServerId: int(acc.ServerId),
DisplayName: acc.DisplayName,
CustomFields: sliceutils.Map(
storageFields,
func(t storage.UserInfoField) *linstromCustomAccountField {
return convertInfoFieldStorageToLinstrom(t)
},
),
CustomFieldIds: acc.CustomFields,
IsBot: acc.IsBot,
Description: acc.Description,
Icon: convertMediaMetadataStorageToLinstrom(storageIcon),
Banner: convertMediaMetadataStorageToLinstrom(storageBanner),
FollowerIds: acc.Followers,
FollowingIds: acc.Follows,
Indexable: acc.Indexable,
RestrictedFollow: acc.RestrictedFollow,
IdentifiesAs: sliceutils.Map(
acc.IdentifiesAs,
func(t storage.Being) string { return string(t) },
),
Pronouns: acc.Gender,
Roles: acc.Roles,
}, nil
}
func convertServerStorageToLinstrom(
server *storage.RemoteServer,
store *storage.Storage,
) (*linstromOriginServer, error) {
storageMeta, err := store.GetMediaMetadataById(server.Icon)
if err != nil {
return nil, err
}
return &linstromOriginServer{
Id: server.ID,
CreatedAt: server.CreatedAt,
UpdatedAt: &server.UpdatedAt,
ServerType: string(server.ServerType),
Domain: server.Domain,
DisplayName: server.Name,
Icon: convertMediaMetadataStorageToLinstrom(storageMeta),
IsSelf: server.IsSelf,
}, nil
}
func convertMediaMetadataStorageToLinstrom(metadata *storage.MediaMetadata) *linstromMediaMetadata {
return &linstromMediaMetadata{
Id: metadata.ID,
CreatedAt: metadata.CreatedAt,
UpdatedAt: &metadata.UpdatedAt,
IsRemote: metadata.Remote,
Url: metadata.Location,
MimeType: metadata.Type,
Name: metadata.Name,
AltText: metadata.AltText,
Blurred: metadata.Blurred,
}
}
func convertInfoFieldStorageToLinstrom(field storage.UserInfoField) *linstromCustomAccountField {
return &linstromCustomAccountField{
Id: field.ID,
CreatedAt: field.CreatedAt,
UpdatedAt: &field.UpdatedAt,
Key: field.Name,
Value: field.Value,
Verified: &field.Confirmed,
BelongsToId: field.BelongsTo,
}
}

View file

@ -35,7 +35,7 @@ type linstromNote struct {
}
type linstromOriginServer struct {
Id int `jsonapi:"primary,origins"`
Id uint `jsonapi:"primary,origins"`
CreatedAt time.Time `jsonapi:"attr,created_at"`
UpdatedAt *time.Time `jsonapi:"attr,updated_at,omitempty"`
ServerType string `jsonapi:"attr,server_type"` // one of "Linstrom", "Mastodon", "Plemora", "Misskey" or "Wafrn"

View file

@ -18,4 +18,5 @@ const (
HttpErrIdBadRequest
HttpErrIdAlreadyExists
HttpErrIdNotFound
HttpErrIdConverionFailure
)