Changes in the user package:

- Moves `POST /users` to the users endpoint group where
    authentication is required
    - Renames userLogin to loginRequest
    - Adds userMethods.go source file to the package user
    - Adds type User in the user package which just wrapps the type
    common.User so methods can be added to the type
    - Adds prototypes of methods for setting/validating password and
    updating type User's data
This commit is contained in:
smavros 2019-05-20 12:04:37 +02:00
parent ab0d8dea8b
commit 8216767722
3 changed files with 77 additions and 28 deletions

View file

@ -1,39 +1,36 @@
package user package user
import ( import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common" //"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
) )
type Credentials struct { // `/authenticate` endpoint does not require Authentication
Username string `form:"Username"` func VisitorAuthenticate(r *gin.RouterGroup) {
Password string `form:"Password"` r.POST("", authenticationEp)
Role string `form:"Role"`
Mail string `form:"Mail"`
} }
func UsersRegister(r *gin.RouterGroup) { func UsersRegister(r *gin.RouterGroup) {
r.POST("/authenticate", authenticationEp) r.POST("/users", userRegistrationEp)
r.GET("/", usersReadEp)
r.POST("/", userRegistrationEp)
r.PUT("/:UserID", userUpdateEp) r.PUT("/:UserID", userUpdateEp)
r.GET("/", usersReadEp)
r.GET("/:UserID", userReadEp) r.GET("/:UserID", userReadEp)
r.DELETE("/:UserID", userDeleteEp)
//r.GET("/me", userSelfEp) // TODO: this conflicts with GET /:userID //r.GET("/me", userSelfEp) // TODO: this conflicts with GET /:userID
r.DELETE("/:UserID", userDeleteEp)
} }
func authenticationEp(c *gin.Context) { func authenticationEp(c *gin.Context) {
// Bind the response (context) with the Credentials struct // Bind the response (context) with the Credentials struct
var userLogin Credentials var loginRequest Credentials
err := c.BindJSON(&userLogin) if err := c.BindJSON(&loginRequest); err != nil {
if err != nil { // TODO: do something other than panic ...
panic(err) panic(err)
} }
// Check if the Username or Password are empty // Check if the Username or Password are empty
if userLogin.Username == "" || userLogin.Password == "" { if loginRequest.Username == "" || loginRequest.Password == "" {
c.JSON(http.StatusUnauthorized, gin.H{ c.JSON(http.StatusUnauthorized, gin.H{
"success": false, "success": false,
"message": "Invalid credentials", "message": "Invalid credentials",
@ -42,9 +39,7 @@ func authenticationEp(c *gin.Context) {
} }
// Find the username in the database // Find the username in the database
db := common.GetDB() user, err := FindUserByUsername(loginRequest.Username)
var user common.User
err = db.Find(&user, "Username = ?", userLogin.Username).Error
if err != nil { if err != nil {
c.JSON(http.StatusNotFound, gin.H{ c.JSON(http.StatusNotFound, gin.H{
"success": false, "success": false,
@ -53,7 +48,14 @@ func authenticationEp(c *gin.Context) {
return return
} }
// TODO: Validate password // Validate the password
if user.validatePassword(loginRequest.Password) != nil {
c.JSON(http.StatusUnauthorized, gin.H{
"success": false,
"message": "Invalid password",
})
return
}
// TODO: generate jwt // TODO: generate jwt
@ -61,11 +63,18 @@ func authenticationEp(c *gin.Context) {
"success": true, "success": true,
"message": "Authenticated", "message": "Authenticated",
"token": "NOT yet implemented", "token": "NOT yet implemented",
"Original request": userLogin, // TODO: remove that "Original request": loginRequest, // TODO: remove that
}) })
} }
func usersReadEp(c *gin.Context) { func usersReadEp(c *gin.Context) {
//// dummy TODO: check in the middleware if the user is authorized
//authorized := false
//// TODO: move this redirect in the authentication middleware
//if !authorized {
//c.Redirect(http.StatusSeeOther, "/authenticate")
//return
//}
allUsers, _, _ := FindAllUsers() allUsers, _, _ := FindAllUsers()
serializer := UsersSerializer{c, allUsers} serializer := UsersSerializer{c, allUsers}
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
@ -74,13 +83,7 @@ func usersReadEp(c *gin.Context) {
} }
func userRegistrationEp(c *gin.Context) { func userRegistrationEp(c *gin.Context) {
//// dummy TODO: check in the middleware if the user is authorized
//authorized := false
//// TODO: move this redirect in the authentication middleware
//if !authorized {
//c.Redirect(http.StatusSeeOther, "/authenticate")
//return
//}
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented", "message": "NOT implemented",
}) })

View file

@ -0,0 +1,43 @@
package user
import (
"fmt"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
// TODO: use validator
type Credentials struct {
Username string `form:"Username"`
Password string `form:"Password"`
Role string `form:"Role"`
Mail string `form:"Mail"`
}
// This is ugly but no other way to keep each model on the corresponding
// package since we have circular dependencies. Methods of a type must
// live in the same package.
type User struct {
Model common.User
}
func FindUserByUsername(username string) (User, error) {
db := common.GetDB()
var user User
err := db.Find(&user.Model, "Username = ?", username).Error
return user, err
}
func (u *User) setPassword(password string) error {
// TODO: Not implemented
return nil
}
func (u *User) validatePassword(password string) error {
// TODO: Not implemented
return nil
}
func (u *User) update(data interface{}) error {
// TODO: Not implemented
return nil
}

View file

@ -25,8 +25,11 @@ func main() {
api := r.Group("/api/v1") api := r.Group("/api/v1")
// All endpoints require authentication TODO: except /authenticate // All endpoints require authentication except when someone wants to
//api.Use(user.Authentication(false)) // login (POST /authenticate)
user.VisitorAuthenticate(api.Group("/authenticate"))
api.Use(user.Authentication(true))
user.UsersRegister(api.Group("/users")) user.UsersRegister(api.Group("/users"))
file.FilesRegister(api.Group("/files")) file.FilesRegister(api.Group("/files"))