mirror of
https://github.com/notherealmarco/WASAPhoto.git
synced 2025-03-14 06:06:15 +01:00
Fixed a lot of bad queries
This commit is contained in:
parent
a3cf4f17f8
commit
233217beb9
15 changed files with 48 additions and 30 deletions
BIN
cmd/webapi/__debug_bin
Executable file
BIN
cmd/webapi/__debug_bin
Executable file
Binary file not shown.
Binary file not shown.
|
@ -22,6 +22,7 @@ func (rt *_router) Handler() http.Handler {
|
||||||
rt.router.PUT("/users/:user_id/bans/:ban_uid", rt.wrap(rt.PutBan))
|
rt.router.PUT("/users/:user_id/bans/:ban_uid", rt.wrap(rt.PutBan))
|
||||||
rt.router.DELETE("/users/:user_id/bans/:ban_uid", rt.wrap(rt.DeleteBan))
|
rt.router.DELETE("/users/:user_id/bans/:ban_uid", rt.wrap(rt.DeleteBan))
|
||||||
|
|
||||||
|
rt.router.GET("/users/:user_id/photos", rt.wrap(rt.GetUserPhotos))
|
||||||
rt.router.POST("/users/:user_id/photos", rt.wrap(rt.PostPhoto))
|
rt.router.POST("/users/:user_id/photos", rt.wrap(rt.PostPhoto))
|
||||||
rt.router.GET("/users/:user_id/photos/:photo_id", rt.wrap(rt.GetPhoto))
|
rt.router.GET("/users/:user_id/photos/:photo_id", rt.wrap(rt.GetPhoto))
|
||||||
rt.router.DELETE("/users/:user_id/photos/:photo_id", rt.wrap(rt.DeletePhoto))
|
rt.router.DELETE("/users/:user_id/photos/:photo_id", rt.wrap(rt.DeletePhoto))
|
||||||
|
@ -36,7 +37,7 @@ func (rt *_router) Handler() http.Handler {
|
||||||
|
|
||||||
rt.router.GET("/users/:user_id", rt.wrap(rt.GetUserProfile))
|
rt.router.GET("/users/:user_id", rt.wrap(rt.GetUserProfile))
|
||||||
|
|
||||||
rt.router.GET("/stream", rt.wrap(rt.GetUserStream)) //todo: why not "/users/:user_id/stream"?
|
rt.router.GET("/stream", rt.wrap(rt.GetUserStream))
|
||||||
|
|
||||||
rt.router.GET("/", rt.getHelloWorld)
|
rt.router.GET("/", rt.getHelloWorld)
|
||||||
rt.router.GET("/context", rt.wrap(rt.getContextReply))
|
rt.router.GET("/context", rt.wrap(rt.getContextReply))
|
||||||
|
|
|
@ -37,7 +37,7 @@ func SendAuthorizationError(f func(db database.AppDatabase, uid string) (reqcont
|
||||||
}
|
}
|
||||||
// requested user is not found -> 404 as the resource is not found
|
// requested user is not found -> 404 as the resource is not found
|
||||||
if auth == reqcontext.USER_NOT_FOUND {
|
if auth == reqcontext.USER_NOT_FOUND {
|
||||||
helpers.SendStatus(notFoundStatus, w, "Resource not found", l)
|
helpers.SendStatus(notFoundStatus, w, "User not found", l)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -15,6 +15,10 @@ import (
|
||||||
|
|
||||||
func (rt *_router) GetFollowersFollowing(w http.ResponseWriter, r *http.Request, ps httprouter.Params, ctx reqcontext.RequestContext) {
|
func (rt *_router) GetFollowersFollowing(w http.ResponseWriter, r *http.Request, ps httprouter.Params, ctx reqcontext.RequestContext) {
|
||||||
|
|
||||||
|
if !authorization.SendErrorIfNotLoggedIn(ctx.Auth.Authorized, rt.db, w, rt.baseLogger) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
uid := ps.ByName("user_id")
|
uid := ps.ByName("user_id")
|
||||||
|
|
||||||
if !helpers.VerifyUserOrNotFound(rt.db, uid, w, rt.baseLogger) {
|
if !helpers.VerifyUserOrNotFound(rt.db, uid, w, rt.baseLogger) {
|
||||||
|
|
|
@ -64,7 +64,7 @@ func (rt *_router) GetUserPhotos(w http.ResponseWriter, r *http.Request, ps http
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user photos
|
// Get user photos
|
||||||
photos, err := rt.db.GetUserPhotos(uid, start_index, limit)
|
photos, err := rt.db.GetUserPhotos(uid, ctx.Auth.GetUserID(), start_index, limit)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helpers.SendInternalError(err, "Database error: GetUserPhotos", w, rt.baseLogger)
|
helpers.SendInternalError(err, "Database error: GetUserPhotos", w, rt.baseLogger)
|
||||||
|
|
|
@ -41,7 +41,6 @@ func SendStatus(httpStatus int, w http.ResponseWriter, description string, l log
|
||||||
err := json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
err := json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithError(err).Error("Error encoding json")
|
l.WithError(err).Error("Error encoding json")
|
||||||
//todo: empty response?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +49,6 @@ func SendNotFound(w http.ResponseWriter, description string, l logrus.FieldLogge
|
||||||
err := json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
err := json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithError(err).Error("Error encoding json")
|
l.WithError(err).Error("Error encoding json")
|
||||||
//todo: empty response?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +57,6 @@ func SendBadRequest(w http.ResponseWriter, description string, l logrus.FieldLog
|
||||||
err := json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
err := json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithError(err).Error("Error encoding json")
|
l.WithError(err).Error("Error encoding json")
|
||||||
//todo: empty response?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +66,6 @@ func SendBadRequestError(err error, description string, w http.ResponseWriter, l
|
||||||
err = json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
err = json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithError(err).Error("Error encoding json")
|
l.WithError(err).Error("Error encoding json")
|
||||||
//todo: empty response?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +75,6 @@ func SendInternalError(err error, description string, w http.ResponseWriter, l l
|
||||||
err = json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
err = json.NewEncoder(w).Encode(structures.GenericResponse{Status: description})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithError(err).Error("Error encoding json")
|
l.WithError(err).Error("Error encoding json")
|
||||||
//todo: empty response?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@ import (
|
||||||
|
|
||||||
func (rt *_router) GetLikes(w http.ResponseWriter, r *http.Request, ps httprouter.Params, ctx reqcontext.RequestContext) {
|
func (rt *_router) GetLikes(w http.ResponseWriter, r *http.Request, ps httprouter.Params, ctx reqcontext.RequestContext) {
|
||||||
|
|
||||||
|
if !authorization.SendErrorIfNotLoggedIn(ctx.Auth.Authorized, rt.db, w, rt.baseLogger) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// get the user id from the url
|
// get the user id from the url
|
||||||
uid := ps.ByName("user_id")
|
uid := ps.ByName("user_id")
|
||||||
photo_id, err := strconv.ParseInt(ps.ByName("photo_id"), 10, 64)
|
photo_id, err := strconv.ParseInt(ps.ByName("photo_id"), 10, 64)
|
||||||
|
|
|
@ -23,7 +23,7 @@ type _respbody struct {
|
||||||
func (rt *_router) PostSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params, ctx reqcontext.RequestContext) {
|
func (rt *_router) PostSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params, ctx reqcontext.RequestContext) {
|
||||||
|
|
||||||
var request _reqbody
|
var request _reqbody
|
||||||
err := json.NewDecoder(r.Body).Decode(&request) //todo: capire se serve close
|
err := json.NewDecoder(r.Body).Decode(&request)
|
||||||
|
|
||||||
var uid string
|
var uid string
|
||||||
if err == nil { // test if user exists
|
if err == nil { // test if user exists
|
||||||
|
|
|
@ -21,19 +21,12 @@ func (rt *_router) UpdateUsername(w http.ResponseWriter, r *http.Request, ps htt
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//err := json.NewDecoder(r.Body).Decode(&req) //todo: capire se serve close
|
|
||||||
|
|
||||||
//if err != nil {
|
|
||||||
// w.WriteHeader(http.StatusBadRequest) // todo: move to DecodeOrBadRequest helper
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
err := rt.db.UpdateUsername(uid, req.Name)
|
err := rt.db.UpdateUsername(uid, req.Name)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError) // todo: is not ok, maybe let's use a helper
|
helpers.SendInternalError(err, "Database error: UpdateUsername", w, rt.baseLogger)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent) // todo: change to 204 also in API spec
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import (
|
||||||
type AppDatabase interface {
|
type AppDatabase interface {
|
||||||
CreateUser(name string) (string, error)
|
CreateUser(name string) (string, error)
|
||||||
UserExists(uid string) (bool, error)
|
UserExists(uid string) (bool, error)
|
||||||
|
UserExistsNotBanned(uid string, requesting_uid string) (bool, error)
|
||||||
GetUserID(name string) (string, error)
|
GetUserID(name string) (string, error)
|
||||||
|
|
||||||
SearchByName(name string, requesting_uid string, start_index int, limit int) (*[]structures.UIDName, error)
|
SearchByName(name string, requesting_uid string, start_index int, limit int) (*[]structures.UIDName, error)
|
||||||
|
@ -67,7 +68,7 @@ type AppDatabase interface {
|
||||||
UnlikePhoto(uid string, photo int64, liker_uid string) (QueryResult, error)
|
UnlikePhoto(uid string, photo int64, liker_uid string) (QueryResult, error)
|
||||||
|
|
||||||
GetUserProfile(uid string, requesting_uid string) (QueryResult, *structures.UserProfile, error)
|
GetUserProfile(uid string, requesting_uid string) (QueryResult, *structures.UserProfile, error)
|
||||||
GetUserPhotos(uid string, start_index int, limit int) (*[]structures.UserPhoto, error)
|
GetUserPhotos(uid string, requesting_uid string, start_index int, limit int) (*[]structures.UserPhoto, error)
|
||||||
GetUserStream(uid string, start_index int, limit int) (*[]structures.Photo, error)
|
GetUserStream(uid string, start_index int, limit int) (*[]structures.Photo, error)
|
||||||
|
|
||||||
GetComments(uid string, photo_id int64, requesting_uid string, start_index int, offset int) (QueryResult, *[]structures.Comment, error)
|
GetComments(uid string, photo_id int64, requesting_uid string, start_index int, offset int) (QueryResult, *[]structures.Comment, error)
|
||||||
|
|
|
@ -23,8 +23,9 @@ func (db *appdbimpl) PostComment(uid string, photo_id int64, comment_user string
|
||||||
_, err = db.c.Exec(`PRAGMA foreign_keys = ON;
|
_, err = db.c.Exec(`PRAGMA foreign_keys = ON;
|
||||||
INSERT INTO "comments" ("user", "photo", "comment", "date") VALUES (?, ?, ?, ?)`, comment_user, photo_id, comment, time.Now().Format(time.RFC3339))
|
INSERT INTO "comments" ("user", "photo", "comment", "date") VALUES (?, ?, ?, ?)`, comment_user, photo_id, comment, time.Now().Format(time.RFC3339))
|
||||||
|
|
||||||
// todo: we don't actually need it, it's already done before
|
|
||||||
if db_errors.ForeignKeyViolation(err) {
|
if db_errors.ForeignKeyViolation(err) {
|
||||||
|
// trying to post a comment on a photo that does not exist
|
||||||
|
// (actually this should never happen, as we checked if the photo exists before)
|
||||||
return ERR_NOT_FOUND, nil
|
return ERR_NOT_FOUND, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ func (db *appdbimpl) GetUserProfile(uid string, requesting_uid string) (QueryRes
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *appdbimpl) GetUserPhotos(uid string, start_index int, limit int) (*[]structures.UserPhoto, error) {
|
func (db *appdbimpl) GetUserPhotos(uid string, requesting_uid string, start_index int, limit int) (*[]structures.UserPhoto, error) {
|
||||||
|
|
||||||
// Get photos
|
// Get photos
|
||||||
rows, err := db.c.Query(`SELECT "p"."id", "p"."date",
|
rows, err := db.c.Query(`SELECT "p"."id", "p"."date",
|
||||||
|
@ -83,8 +83,9 @@ func (db *appdbimpl) GetUserPhotos(uid string, start_index int, limit int) (*[]s
|
||||||
)
|
)
|
||||||
FROM "photos" AS "p"
|
FROM "photos" AS "p"
|
||||||
WHERE "p"."user" = ?
|
WHERE "p"."user" = ?
|
||||||
OFFSET ?
|
|
||||||
LIMIT ?`, uid, uid, start_index, limit)
|
LIMIT ?
|
||||||
|
OFFSET ?`, requesting_uid, uid, limit, start_index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Return the error
|
// Return the error
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -20,6 +20,24 @@ func (db *appdbimpl) UserExists(uid string) (bool, error) {
|
||||||
return cnt > 0, nil
|
return cnt > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User exists and is not banned
|
||||||
|
func (db *appdbimpl) UserExistsNotBanned(uid string, requesting_uid string) (bool, error) {
|
||||||
|
|
||||||
|
var cnt int
|
||||||
|
err := db.c.QueryRow(`SELECT COUNT(*) FROM "users"
|
||||||
|
WHERE "uid" = ?
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT "bans"."user" FROM "bans"
|
||||||
|
WHERE "bans"."user" = "users"."uid"
|
||||||
|
AND "bans"."ban" = ?
|
||||||
|
)`, uid, requesting_uid).Scan(&cnt)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return cnt > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get user id by username
|
// Get user id by username
|
||||||
func (db *appdbimpl) GetUserID(name string) (string, error) {
|
func (db *appdbimpl) GetUserID(name string) (string, error) {
|
||||||
var uid string
|
var uid string
|
||||||
|
@ -47,7 +65,7 @@ func (db *appdbimpl) UpdateUsername(uid string, name string) error {
|
||||||
func (db *appdbimpl) GetUserFollowers(uid string, requesting_uid string, start_index int, limit int) (QueryResult, *[]structures.UIDName, error) {
|
func (db *appdbimpl) GetUserFollowers(uid string, requesting_uid string, start_index int, limit int) (QueryResult, *[]structures.UIDName, error) {
|
||||||
|
|
||||||
// user may exist but have no followers
|
// user may exist but have no followers
|
||||||
exists, err := db.UserExists(uid)
|
exists, err := db.UserExistsNotBanned(uid, requesting_uid)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ERR_INTERNAL, nil, err
|
return ERR_INTERNAL, nil, err
|
||||||
|
@ -57,7 +75,7 @@ func (db *appdbimpl) GetUserFollowers(uid string, requesting_uid string, start_i
|
||||||
return ERR_NOT_FOUND, nil, nil
|
return ERR_NOT_FOUND, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := db.c.Query(`SELECT "follower", "user"."name" FROM "follows", "users"
|
rows, err := db.c.Query(`SELECT "follower", "users"."name" FROM "follows", "users"
|
||||||
WHERE "follows"."follower" = "users"."uid"
|
WHERE "follows"."follower" = "users"."uid"
|
||||||
|
|
||||||
AND "follows"."follower" NOT IN (
|
AND "follows"."follower" NOT IN (
|
||||||
|
@ -67,8 +85,8 @@ func (db *appdbimpl) GetUserFollowers(uid string, requesting_uid string, start_i
|
||||||
)
|
)
|
||||||
|
|
||||||
AND "followed" = ?
|
AND "followed" = ?
|
||||||
OFFSET ?
|
LIMIT ?
|
||||||
LIMIT ?`, uid, requesting_uid, start_index, limit)
|
OFFSET ?`, uid, requesting_uid, limit, start_index)
|
||||||
|
|
||||||
followers, err := db.uidNameQuery(rows, err)
|
followers, err := db.uidNameQuery(rows, err)
|
||||||
|
|
||||||
|
@ -83,7 +101,7 @@ func (db *appdbimpl) GetUserFollowers(uid string, requesting_uid string, start_i
|
||||||
func (db *appdbimpl) GetUserFollowing(uid string, requesting_uid string, start_index int, offset int) (QueryResult, *[]structures.UIDName, error) {
|
func (db *appdbimpl) GetUserFollowing(uid string, requesting_uid string, start_index int, offset int) (QueryResult, *[]structures.UIDName, error) {
|
||||||
|
|
||||||
// user may exist but have no followers
|
// user may exist but have no followers
|
||||||
exists, err := db.UserExists(uid)
|
exists, err := db.UserExistsNotBanned(uid, requesting_uid)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ERR_INTERNAL, nil, err
|
return ERR_INTERNAL, nil, err
|
||||||
|
|
|
@ -21,7 +21,7 @@ type Comment struct {
|
||||||
Date string `json:"date"`
|
Date string `json:"date"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Photo struct { //todo: move to structures
|
type Photo struct {
|
||||||
UID string `json:"user_id"`
|
UID string `json:"user_id"`
|
||||||
ID int64 `json:"photo_id"`
|
ID int64 `json:"photo_id"`
|
||||||
Likes int64 `json:"likes"`
|
Likes int64 `json:"likes"`
|
||||||
|
@ -44,5 +44,5 @@ type UserProfile struct {
|
||||||
Following int64 `json:"following"`
|
Following int64 `json:"following"`
|
||||||
Followers int64 `json:"followers"`
|
Followers int64 `json:"followers"`
|
||||||
Followed bool `json:"followed"`
|
Followed bool `json:"followed"`
|
||||||
Photos int64 `json:"photos"` //todo: check json names
|
Photos int64 `json:"photos"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue