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 }