diff --git a/pkg/login/endpoint.go b/pkg/login/endpoint.go index d52a0a61..4737f9ba 100644 --- a/pkg/login/endpoint.go +++ b/pkg/login/endpoint.go @@ -317,7 +317,7 @@ func (e *Endpoint) enterAppleRegistrationState(w http.ResponseWriter, token, ema } func (e *Endpoint) register(w http.ResponseWriter, r *http.Request) { - err := r.ParseMultipartForm(10 << 20) + err := r.ParseForm() if err != nil { httputil.JsonError(w, http.StatusBadRequest, httputil.ErrorCodeInvalidRequestBody, "") return @@ -347,29 +347,15 @@ func (e *Endpoint) register(w http.ResponseWriter, r *http.Request) { return } - file, _, err := r.FormFile("profile") - if err != nil { - httputil.JsonError(w, http.StatusInternalServerError, httputil.ErrorCodeInvalidRequestBody, "") - return - } - - image, err := e.processProfilePicture(file) - if err != nil { - httputil.JsonError(w, http.StatusInternalServerError, httputil.ErrorCodeInvalidRequestBody, "") - return - } - var lastID int if state.AppleUserID != "" { - lastID, err = e.users.CreateUserWithAppleLogin(state.Email, name, "", image, username, state.AppleUserID) + lastID, err = e.users.CreateUserWithAppleLogin(state.Email, name, "", username, state.AppleUserID) } else { - lastID, err = e.users.CreateUser(state.Email, name, "", image, username) + lastID, err = e.users.CreateUser(state.Email, name, "", username) } // @TODO ALLOW BIO DURING ON-BOARDING if err != nil { - _ = e.ib.Remove(image) - if err.Error() == "pq: duplicate key value violates unique constraint \"idx_username\"" { httputil.JsonError(w, http.StatusBadRequest, httputil.ErrorCodeUsernameAlreadyExists, "username already exists") return @@ -386,13 +372,10 @@ func (e *Endpoint) register(w http.ResponseWriter, r *http.Request) { DisplayName: name, Username: username, Email: &state.Email, - Image: image, } err = e.sessions.NewSession(token, user.ID, expiration) if err != nil { - _ = e.ib.Remove(image) - log.Println("failed to create session: ", err.Error()) httputil.JsonError(w, http.StatusInternalServerError, httputil.ErrorCodeFailedToLogin, "") return diff --git a/pkg/users/backend.go b/pkg/users/backend.go index de0b83db..eac4c437 100644 --- a/pkg/users/backend.go +++ b/pkg/users/backend.go @@ -307,14 +307,14 @@ func (b *Backend) FindByEmail(email string) (*types.User, error) { return user, nil } -func (b *Backend) CreateUser(email, displayName, bio, image, username string) (int, error) { +func (b *Backend) CreateUser(email, displayName, bio, username string) (int, error) { stmt, err := b.db.Prepare("INSERT INTO users (display_name, username, email, bio, image) VALUES ($1, $2, $3, $4, $5) RETURNING id;") if err != nil { return 0, err } var id int - err = stmt.QueryRow(displayName, strings.ToLower(username), email, bio, image).Scan(&id) + err = stmt.QueryRow(displayName, strings.ToLower(username), email, bio, "").Scan(&id) if err != nil { return 0, err } @@ -322,7 +322,7 @@ func (b *Backend) CreateUser(email, displayName, bio, image, username string) (i return id, nil } -func (b *Backend) CreateUserWithAppleLogin(email, displayName, bio, image, username, appleID string) (int, error) { +func (b *Backend) CreateUserWithAppleLogin(email, displayName, bio, username, appleID string) (int, error) { ctx := context.Background() tx, err := b.db.BeginTx(ctx, nil) if err != nil { @@ -331,7 +331,7 @@ func (b *Backend) CreateUserWithAppleLogin(email, displayName, bio, image, usern res := tx.QueryRow( "INSERT INTO users (display_name, username, email, bio, image) VALUES ($1, $2, $3, $4, $5) RETURNING id;", - displayName, strings.ToLower(username), email, bio, image, + displayName, strings.ToLower(username), email, bio, "", ) var id int @@ -373,6 +373,18 @@ func (b *Backend) UpdateUser(id int, displayName, bio, image string) error { return err } +func (b *Backend) UpdateUserPhoto(id int, image string) error { + query := "UPDATE users SET image = $1 WHERE id = $2;" + + stmt, err := b.db.Prepare(query) + if err != nil { + return err + } + + _, err = stmt.Exec(image, id) + return err +} + func (b *Backend) GetProfileImage(id int) (string, error) { stmt, err := b.db.Prepare("SELECT image FROM users WHERE id = $1;") if err != nil { diff --git a/pkg/users/endpoint.go b/pkg/users/endpoint.go index 855bccb9..3f8bc473 100644 --- a/pkg/users/endpoint.go +++ b/pkg/users/endpoint.go @@ -58,7 +58,9 @@ func (e *Endpoint) Router() *mux.Router { r.Path("/follow").Methods("POST").HandlerFunc(e.FollowUser) r.Path("/unfollow").Methods("POST").HandlerFunc(e.UnfollowUser) r.Path("/multi-follow").Methods("POST").HandlerFunc(e.MultiFollowUsers) + // @TODO next 2 functions should be in account? r.Path("/edit").Methods("POST").HandlerFunc(e.EditUser) + r.Path("/upload").Methods("POST").HandlerFunc(e.UploadProfilePhoto) r.Path("/{id:[0-9]+}/stories").Methods("GET").HandlerFunc(e.GetStoriesForUser) return r @@ -358,6 +360,55 @@ func (e *Endpoint) EditUser(w http.ResponseWriter, r *http.Request) { httputil.JsonSuccess(w) } +func (e *Endpoint) UploadProfilePhoto(w http.ResponseWriter, r *http.Request) { + err := r.ParseMultipartForm(10 << 20) + if err != nil { + httputil.JsonError(w, http.StatusBadRequest, httputil.ErrorCodeInvalidRequestBody, "") + return + } + + userID, ok := httputil.GetUserIDFromContext(r.Context()) + if !ok { + httputil.JsonError(w, http.StatusInternalServerError, httputil.ErrorCodeInvalidRequestBody, "invalid id") + return + } + + oldPath, err := e.ub.GetProfileImage(userID) + if err != nil { + httputil.JsonError(w, http.StatusBadRequest, httputil.ErrorCodeInvalidRequestBody, "") + return + } + + file, _, err := r.FormFile("profile") + if err != nil && err != http.ErrMissingFile { + httputil.JsonError(w, http.StatusInternalServerError, httputil.ErrorCodeInvalidRequestBody, "") + return + } + + image := oldPath + if file != nil { + image, err = e.processProfilePicture(file) + if err != nil { + httputil.JsonError(w, http.StatusInternalServerError, httputil.ErrorCodeInvalidRequestBody, "") + return + } + } + + err = e.ub.UpdateUserPhoto(userID, image) + if err != nil { + httputil.JsonError(w, http.StatusInternalServerError, httputil.ErrorCodeInvalidRequestBody, "") + return + } + + if image != oldPath { + _ = e.ib.Remove(oldPath) + } + + // @TODO add image id to success + + httputil.JsonSuccess(w) +} + func (e *Endpoint) GetStoriesForUser(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r)