summaryrefslogtreecommitdiff
path: root/api/profiles
diff options
context:
space:
mode:
authorElizabeth <elizabeth@simponic.xyz>2024-04-09 18:39:14 -0400
committersimponic <simponic@hatecomputers.club>2024-04-09 18:39:14 -0400
commit1d75bf7489527925217bd5611ba7910c0ffe077c (patch)
tree3b6e6056912648a88e1e42c1e42ed7e58e2d4701 /api/profiles
parentee49015cc90e6c136ad94243fffc9241b9506a36 (diff)
downloadhatecomputers.club-1d75bf7489527925217bd5611ba7910c0ffe077c.tar.gz
hatecomputers.club-1d75bf7489527925217bd5611ba7910c0ffe077c.zip
profiles (#7)
Reviewed-on: https://git.hatecomputers.club/hatecomputers/hatecomputers.club/pulls/7 Co-authored-by: Elizabeth <elizabeth@simponic.xyz> Co-committed-by: Elizabeth <elizabeth@simponic.xyz>
Diffstat (limited to 'api/profiles')
-rw-r--r--api/profiles/profiles.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/api/profiles/profiles.go b/api/profiles/profiles.go
new file mode 100644
index 0000000..8e10e5f
--- /dev/null
+++ b/api/profiles/profiles.go
@@ -0,0 +1,118 @@
+package profiles
+
+import (
+ "log"
+ "net/http"
+ "strings"
+
+ "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/files"
+ "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types"
+ "git.hatecomputers.club/hatecomputers/hatecomputers.club/database"
+)
+
+const MaxAvatarSize = 1024 * 1024 * 2 // 2MB
+const AvatarPath = "avatars/"
+const AvatarPrefix = "/uploads/avatars/"
+
+func GetProfileContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
+ return func(success types.Continuation, failure types.Continuation) types.ContinuationChain {
+ if context.User == nil {
+ return failure(context, req, resp)
+ }
+
+ (*context.TemplateData)["Profile"] = context.User
+ return success(context, req, resp)
+ }
+}
+
+func UpdateProfileContinuation(fileAdapter files.FilesAdapter, maxAvatarSize int, avatarPath string, avatarPrefix string) func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
+ return func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
+ return func(success types.Continuation, failure types.Continuation) types.ContinuationChain {
+ formErrors := types.BannerMessages{
+ Messages: []string{},
+ }
+
+ err := req.ParseMultipartForm(int64(maxAvatarSize))
+ if err != nil {
+ formErrors.Messages = append(formErrors.Messages, "avatar file too large")
+ }
+
+ if len(formErrors.Messages) == 0 {
+ file, _, err := req.FormFile("avatar")
+ if file != nil && err != nil {
+ formErrors.Messages = append(formErrors.Messages, "error uploading avatar")
+ } else if file != nil {
+ defer file.Close()
+ reader := http.MaxBytesReader(resp, file, int64(maxAvatarSize))
+ defer reader.Close()
+
+ _, err = fileAdapter.CreateFile(avatarPath+context.User.ID, reader)
+ if err != nil {
+ log.Println(err)
+ formErrors.Messages = append(formErrors.Messages, "error saving avatar (is it too big?)")
+ }
+ }
+ }
+
+ context.User.Bio = strings.Trim(req.FormValue("bio"), "\n")
+ context.User.Pronouns = req.FormValue("pronouns")
+ context.User.Location = req.FormValue("location")
+ context.User.Website = req.FormValue("website")
+ context.User.Avatar = avatarPrefix + context.User.ID
+ formErrors.Messages = append(formErrors.Messages, validateProfileUpdate(context.User)...)
+
+ if len(formErrors.Messages) == 0 {
+ _, err = database.SaveUser(context.DBConn, context.User)
+ if err != nil {
+ formErrors.Messages = append(formErrors.Messages, "error saving profile")
+ }
+ }
+
+ (*context.TemplateData)["Profile"] = context.User
+ (*context.TemplateData)["Error"] = formErrors
+
+ if len(formErrors.Messages) > 0 {
+ log.Println(formErrors.Messages)
+
+ resp.WriteHeader(http.StatusBadRequest)
+ return failure(context, req, resp)
+ }
+
+ formSuccess := types.BannerMessages{
+ Messages: []string{"profile updated"},
+ }
+ (*context.TemplateData)["Success"] = formSuccess
+ return success(context, req, resp)
+ }
+ }
+}
+
+func validateProfileUpdate(user *database.User) []string {
+ errors := []string{}
+
+ if (!strings.HasPrefix(user.Website, "https://") && !strings.HasPrefix(user.Website, "http://")) || len(user.Website) < 8 {
+ errors = append(errors, "website must be a valid URL")
+ }
+ if len(user.Website) > 64 {
+ errors = append(errors, "website cannot be longer than 64 characters")
+ }
+
+ if len(user.Pronouns) > 64 {
+ errors = append(errors, "pronouns cannot be longer than 64 characters")
+ }
+
+ if len(user.Bio) > 128 {
+ errors = append(errors, "bio cannot be longer than 128 characters")
+ }
+
+ newLines := strings.Count(user.Bio, "\n")
+ if newLines > 8 {
+ errors = append(errors, "message cannot contain more than 8 new lines")
+ }
+
+ if len(user.Location) > 32 {
+ errors = append(errors, "location cannot be longer than 64 characters")
+ }
+
+ return errors
+}