Browse Source

Add API handler to fetch user by username

Frédéric Guillot 8 years ago
parent
commit
c3c27e3637

+ 1 - 1
Gopkg.lock

@@ -41,7 +41,7 @@
   branch = "master"
   name = "github.com/miniflux/miniflux-go"
   packages = ["."]
-  revision = "60d72460e62282aa90cb43fa3a87596900b87678"
+  revision = "3d654932d84b6afdbd5e66b34b08392f62229e61"
 
 [[projects]]
   name = "github.com/tdewolff/minify"

+ 60 - 4
integration_test.go

@@ -17,7 +17,7 @@ import (
 )
 
 const (
-	testBaseURL          = "http://127.0.0.1:8080"
+	testBaseURL          = "http://127.0.0.1:8080/"
 	testAdminUsername    = "admin"
 	testAdminPassword    = "test123"
 	testStandardPassword = "secret"
@@ -136,7 +136,7 @@ func TestRemoveUser(t *testing.T) {
 	}
 }
 
-func TestGetUser(t *testing.T) {
+func TestGetUserByID(t *testing.T) {
 	username := getRandomUsername()
 	client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
 	user, err := client.CreateUser(username, testStandardPassword, false)
@@ -144,7 +144,63 @@ func TestGetUser(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	user, err = client.User(user.ID)
+	_, err = client.UserByID(99999)
+	if err == nil {
+		t.Fatal(`Should returns a 404`)
+	}
+
+	user, err = client.UserByID(user.ID)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if user.ID == 0 {
+		t.Fatalf(`Invalid userID, got "%v"`, user.ID)
+	}
+
+	if user.Username != username {
+		t.Fatalf(`Invalid username, got "%v" instead of "%v"`, user.Username, username)
+	}
+
+	if user.Password != "" {
+		t.Fatalf(`Invalid password, got "%v"`, user.Password)
+	}
+
+	if user.Language != "en_US" {
+		t.Fatalf(`Invalid language, got "%v"`, user.Language)
+	}
+
+	if user.Theme != "default" {
+		t.Fatalf(`Invalid theme, got "%v"`, user.Theme)
+	}
+
+	if user.Timezone != "UTC" {
+		t.Fatalf(`Invalid timezone, got "%v"`, user.Timezone)
+	}
+
+	if user.IsAdmin {
+		t.Fatalf(`Invalid role, got "%v"`, user.IsAdmin)
+	}
+
+	if user.LastLoginAt != nil {
+		t.Fatalf(`Invalid last login date, got "%v"`, user.LastLoginAt)
+	}
+}
+
+func TestGetUserByUsername(t *testing.T) {
+	username := getRandomUsername()
+	client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
+	user, err := client.CreateUser(username, testStandardPassword, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = client.UserByUsername("missinguser")
+	if err == nil {
+		t.Fatal(`Should returns a 404`)
+	}
+
+	user, err = client.UserByUsername(username)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -256,7 +312,7 @@ func TestCannotGetUserAsNonAdmin(t *testing.T) {
 	}
 
 	client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
-	_, err = client.User(user.ID)
+	_, err = client.UserByID(user.ID)
 	if err == nil {
 		t.Fatal(`Standard users should not be able to get any users`)
 	}

+ 26 - 4
server/api/controller/user.go

@@ -88,8 +88,8 @@ func (c *Controller) UpdateUser(ctx *core.Context, request *core.Request, respon
 	response.JSON().Created(originalUser)
 }
 
-// GetUsers is the API handler to get the list of users.
-func (c *Controller) GetUsers(ctx *core.Context, request *core.Request, response *core.Response) {
+// Users is the API handler to get the list of users.
+func (c *Controller) Users(ctx *core.Context, request *core.Request, response *core.Response) {
 	if !ctx.IsAdminUser() {
 		response.JSON().Forbidden()
 		return
@@ -104,8 +104,8 @@ func (c *Controller) GetUsers(ctx *core.Context, request *core.Request, response
 	response.JSON().Standard(users)
 }
 
-// GetUser is the API handler to fetch the given user.
-func (c *Controller) GetUser(ctx *core.Context, request *core.Request, response *core.Response) {
+// UserByID is the API handler to fetch the given user by the ID.
+func (c *Controller) UserByID(ctx *core.Context, request *core.Request, response *core.Response) {
 	if !ctx.IsAdminUser() {
 		response.JSON().Forbidden()
 		return
@@ -131,6 +131,28 @@ func (c *Controller) GetUser(ctx *core.Context, request *core.Request, response
 	response.JSON().Standard(user)
 }
 
+// UserByUsername is the API handler to fetch the given user by the username.
+func (c *Controller) UserByUsername(ctx *core.Context, request *core.Request, response *core.Response) {
+	if !ctx.IsAdminUser() {
+		response.JSON().Forbidden()
+		return
+	}
+
+	username := request.StringParam("username", "")
+	user, err := c.store.UserByUsername(username)
+	if err != nil {
+		response.JSON().BadRequest(errors.New("Unable to fetch this user from the database"))
+		return
+	}
+
+	if user == nil {
+		response.JSON().NotFound(errors.New("User not found"))
+		return
+	}
+
+	response.JSON().Standard(user)
+}
+
 // RemoveUser is the API handler to remove an existing user.
 func (c *Controller) RemoveUser(ctx *core.Context, request *core.Request, response *core.Response) {
 	if !ctx.IsAdminUser() {

+ 5 - 4
server/routes.go

@@ -49,10 +49,11 @@ func getRoutes(cfg *config.Config, store *storage.Storage, feedHandler *feed.Han
 	router.Handle("/fever/", feverHandler.Use(feverController.Handler))
 
 	router.Handle("/v1/users", apiHandler.Use(apiController.CreateUser)).Methods("POST")
-	router.Handle("/v1/users", apiHandler.Use(apiController.GetUsers)).Methods("GET")
-	router.Handle("/v1/users/{userID}", apiHandler.Use(apiController.GetUser)).Methods("GET")
-	router.Handle("/v1/users/{userID}", apiHandler.Use(apiController.UpdateUser)).Methods("PUT")
-	router.Handle("/v1/users/{userID}", apiHandler.Use(apiController.RemoveUser)).Methods("DELETE")
+	router.Handle("/v1/users", apiHandler.Use(apiController.Users)).Methods("GET")
+	router.Handle("/v1/users/{userID:[0-9]+}", apiHandler.Use(apiController.UserByID)).Methods("GET")
+	router.Handle("/v1/users/{userID:[0-9]+}", apiHandler.Use(apiController.UpdateUser)).Methods("PUT")
+	router.Handle("/v1/users/{userID:[0-9]+}", apiHandler.Use(apiController.RemoveUser)).Methods("DELETE")
+	router.Handle("/v1/users/{username}", apiHandler.Use(apiController.UserByUsername)).Methods("GET")
 
 	router.Handle("/v1/categories", apiHandler.Use(apiController.CreateCategory)).Methods("POST")
 	router.Handle("/v1/categories", apiHandler.Use(apiController.GetCategories)).Methods("GET")

+ 19 - 2
vendor/github.com/miniflux/miniflux-go/client.go

@@ -33,8 +33,8 @@ func (c *Client) Users() (Users, error) {
 	return users, nil
 }
 
-// User returns a single user.
-func (c *Client) User(userID int64) (*User, error) {
+// UserByID returns a single user.
+func (c *Client) UserByID(userID int64) (*User, error) {
 	body, err := c.request.Get(fmt.Sprintf("/v1/users/%d", userID))
 	if err != nil {
 		return nil, err
@@ -50,6 +50,23 @@ func (c *Client) User(userID int64) (*User, error) {
 	return &user, nil
 }
 
+// UserByUsername returns a single user.
+func (c *Client) UserByUsername(username string) (*User, error) {
+	body, err := c.request.Get(fmt.Sprintf("/v1/users/%s", username))
+	if err != nil {
+		return nil, err
+	}
+	defer body.Close()
+
+	var user User
+	decoder := json.NewDecoder(body)
+	if err := decoder.Decode(&user); err != nil {
+		return nil, fmt.Errorf("miniflux: response error (%v)", err)
+	}
+
+	return &user, nil
+}
+
 // CreateUser creates a new user in the system.
 func (c *Client) CreateUser(username, password string, isAdmin bool) (*User, error) {
 	body, err := c.request.Post("/v1/users", &User{Username: username, Password: password, IsAdmin: isAdmin})

+ 4 - 8
vendor/github.com/miniflux/miniflux-go/request.go

@@ -55,6 +55,10 @@ func (r *request) Delete(path string) (io.ReadCloser, error) {
 }
 
 func (r *request) execute(method, path string, data interface{}) (io.ReadCloser, error) {
+	if r.endpoint[len(r.endpoint)-1:] == "/" {
+		r.endpoint = r.endpoint[:len(r.endpoint)-1]
+	}
+
 	u, err := url.Parse(r.endpoint + path)
 	if err != nil {
 		return nil, err
@@ -126,11 +130,3 @@ func (r *request) toJSON(v interface{}) []byte {
 
 	return b
 }
-
-func newRequest(endpoint, username, password string) *request {
-	return &request{
-		endpoint: endpoint,
-		username: username,
-		password: password,
-	}
-}