diff --git a/service/api/api-context-wrapper.go b/service/api/api-context-wrapper.go index 5c732be..fb81fe0 100644 --- a/service/api/api-context-wrapper.go +++ b/service/api/api-context-wrapper.go @@ -28,7 +28,6 @@ func (rt *_router) wrap(fn httpRouterHandler) func(http.ResponseWriter, *http.Re if err != nil { rt.baseLogger.WithError(err).Info("User not authorized") - w.WriteHeader(http.StatusUnauthorized) return } diff --git a/service/api/api-handler.go b/service/api/api-handler.go index 49ad354..06c5972 100644 --- a/service/api/api-handler.go +++ b/service/api/api-handler.go @@ -8,6 +8,9 @@ import ( func (rt *_router) Handler() http.Handler { // Register routes rt.router.POST("/session", rt.wrap(rt.PostSession)) + + rt.router.PUT("/users/:user_id/username", rt.wrap(rt.UpdateUsername)) + rt.router.GET("/", rt.getHelloWorld) rt.router.GET("/context", rt.wrap(rt.getContextReply)) diff --git a/service/api/authorization/auth-bearer.go b/service/api/authorization/auth-bearer.go index eeb7f2a..037f131 100644 --- a/service/api/authorization/auth-bearer.go +++ b/service/api/authorization/auth-bearer.go @@ -4,6 +4,7 @@ import ( "errors" "strings" + "github.com/notherealmarco/WASAPhoto/service/api/reqcontext" "github.com/notherealmarco/WASAPhoto/service/database" ) @@ -42,9 +43,19 @@ func (b *BearerAuth) Authorized(db database.AppDatabase) (bool, error) { return state, nil } -func (b *BearerAuth) UserAuthorized(db database.AppDatabase, uid string) (bool, error) { +func (b *BearerAuth) UserAuthorized(db database.AppDatabase, uid string) (reqcontext.AuthStatus, error) { if b.token == uid { - return b.Authorized(db) + auth, err := b.Authorized(db) + + if err != nil { + return -1, err + } + + if auth { + return reqcontext.AUTHORIZED, nil + } else { + return reqcontext.UNAUTHORIZED, nil + } } - return false, nil + return reqcontext.FORBIDDEN, nil } diff --git a/service/api/authorization/auth-manager.go b/service/api/authorization/auth-manager.go index 9be6f9a..f6c4f2d 100644 --- a/service/api/authorization/auth-manager.go +++ b/service/api/authorization/auth-manager.go @@ -2,8 +2,10 @@ package authorization import ( "errors" + "net/http" "github.com/notherealmarco/WASAPhoto/service/api/reqcontext" + "github.com/notherealmarco/WASAPhoto/service/database" ) func BuildAuth(header string) (reqcontext.Authorization, error) { @@ -16,3 +18,21 @@ func BuildAuth(header string) (reqcontext.Authorization, error) { } return auth, nil } + +func SendAuthorizationError(f func(db database.AppDatabase, uid string) (reqcontext.AuthStatus, error), uid string, db database.AppDatabase, w http.ResponseWriter) bool { + auth, err := f(db, uid) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + // todo: log error and write it to the response + return false + } + if auth == reqcontext.UNAUTHORIZED { + w.WriteHeader(http.StatusUnauthorized) + return false + } + if auth == reqcontext.FORBIDDEN { + w.WriteHeader(http.StatusForbidden) + return false + } + return true +} diff --git a/service/api/post-session.go b/service/api/post-session.go index 87e812c..3d2761b 100644 --- a/service/api/post-session.go +++ b/service/api/post-session.go @@ -14,7 +14,7 @@ type _reqbody struct { } type _respbody struct { - UID string `json:"uid"` + UID string `json:"user_id"` } // getContextReply is an example of HTTP endpoint that returns "Hello World!" as a plain text. The signature of this diff --git a/service/api/put-updateusername.go b/service/api/put-updateusername.go index dafb16f..dbc002a 100644 --- a/service/api/put-updateusername.go +++ b/service/api/put-updateusername.go @@ -1,14 +1,35 @@ package api import ( + "encoding/json" "net/http" "github.com/julienschmidt/httprouter" + "github.com/notherealmarco/WASAPhoto/service/api/authorization" "github.com/notherealmarco/WASAPhoto/service/api/reqcontext" + "github.com/notherealmarco/WASAPhoto/service/structures" ) func (rt *_router) UpdateUsername(w http.ResponseWriter, r *http.Request, ps httprouter.Params, ctx reqcontext.RequestContext) { - auth, err := ctx.Auth.UserAuthorized(rt.db, r.URL.Path // todo: prendere il coso giusto dal path) + uid := ps.ByName("user_id") + if !authorization.SendAuthorizationError(ctx.Auth.UserAuthorized, uid, rt.db, w) { + return + } + var req structures.UserDetails + 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) + + if err != nil { + w.WriteHeader(http.StatusInternalServerError) // todo: is not ok, maybe let's use a helper + return + } + + w.WriteHeader(http.StatusNoContent) // todo: change to 204 also in API spec } diff --git a/service/api/reqcontext/request-context.go b/service/api/reqcontext/request-context.go index df1c7e7..b0be6c8 100644 --- a/service/api/reqcontext/request-context.go +++ b/service/api/reqcontext/request-context.go @@ -12,6 +12,14 @@ import ( "github.com/sirupsen/logrus" ) +type AuthStatus int + +const ( + AUTHORIZED = 0 + UNAUTHORIZED = 1 + FORBIDDEN = 2 +) + // RequestContext is the context of the request, for request-dependent parameters type RequestContext struct { // ReqUUID is the request unique ID @@ -26,5 +34,5 @@ type RequestContext struct { type Authorization interface { GetType() string Authorized(db database.AppDatabase) (bool, error) - UserAuthorized(db database.AppDatabase, uid string) (bool, error) + UserAuthorized(db database.AppDatabase, uid string) (AuthStatus, error) } diff --git a/service/database/database.go b/service/database/database.go index 93f69f5..c8f53e7 100644 --- a/service/database/database.go +++ b/service/database/database.go @@ -40,7 +40,7 @@ import ( type AppDatabase interface { UserExists(uid string) (bool, error) GetUserID(name string) (string, error) - SetName(name string) error + UpdateUsername(uid, name string) error CreateUser(name string) (string, error) FollowUser(uid string, follow string) error UnfollowUser(uid string, unfollow string) error diff --git a/service/database/db-users.go b/service/database/db-users.go index 4ac22a2..472619b 100644 --- a/service/database/db-users.go +++ b/service/database/db-users.go @@ -11,7 +11,7 @@ import ( // Check if user exists func (db *appdbimpl) UserExists(uid string) (bool, error) { var name string - err := db.c.QueryRow(`SELECT "name" FROM "users" WHERE "uid" = ?`, name).Scan(&name) + err := db.c.QueryRow(`SELECT "name" FROM "users" WHERE "uid" = ?`, uid).Scan(&name) if db_errors.EmptySet(err) { return false, nil @@ -38,6 +38,12 @@ func (db *appdbimpl) CreateUser(name string) (string, error) { return uid.String(), err } +// Update username +func (db *appdbimpl) UpdateUsername(uid string, name string) error { + _, err := db.c.Exec(`UPDATE "users" SET "name" = ? WHERE "uid" = ?`, name, uid) + return err +} + // Follow a user func (db *appdbimpl) FollowUser(uid string, follow string) error { _, err := db.c.Exec(`INSERT INTO "follows" ("follower", "followed") VALUES (?, ?)`, uid, follow) diff --git a/service/structures/api-structures.go b/service/structures/api-structures.go new file mode 100644 index 0000000..c5020df --- /dev/null +++ b/service/structures/api-structures.go @@ -0,0 +1,5 @@ +package structures + +type UserDetails struct { + Name string `json:"name"` +}