Commit 848d2ac6 authored by MaxGranzow's avatar MaxGranzow Committed by Julien Schröter

Add endpoint to fetch user recommendations

parent 161a15b9
...@@ -47,6 +47,13 @@ func SetupUserRoutes(group *gin.RouterGroup, repository UserQuery, titleReposito ...@@ -47,6 +47,13 @@ func SetupUserRoutes(group *gin.RouterGroup, repository UserQuery, titleReposito
}) })
// endpoint used to search for users by username // endpoint used to search for users by username
group.GET("/search", searchForUsers(repository)) group.GET("/search", searchForUsers(repository))
group.OPTIONS("/recommended", func(ctx *gin.Context) {
ctx.Header("Allow", "GET")
ctx.Status(200)
})
// endpoint to fetch user recommendations
group.GET("/recommended", getRecommendedUsers(repository))
} }
/* /*
...@@ -369,6 +376,44 @@ func searchForUsers(repository UserQuery) gin.HandlerFunc { ...@@ -369,6 +376,44 @@ func searchForUsers(repository UserQuery) gin.HandlerFunc {
} }
} }
func getRecommendedUsers(repository UserQuery) gin.HandlerFunc {
return func(ctx *gin.Context) {
const DefaultCount = 3
const MaxCount = 10
var req struct {
Count int32 `form:"c"`
}
if err := ctx.BindQuery(&req); err != nil {
return
}
// Only accept numbers in range [0-10]
if req.Count <= 0 {
req.Count = DefaultCount
} else if req.Count > MaxCount {
req.Count = MaxCount
}
userID, err := endpoint.GetUserID(ctx)
if err != nil {
return
}
// fetch matching users from database
users, err := repository.SelectUserRecommendations(userID, uint32(req.Count))
if err != nil {
eventID := raven.CaptureError(err, nil)
ctx.String(http.StatusInternalServerError, "Failed fetching data from DB. "+eventID)
return
}
ctx.JSON(http.StatusOK, users)
}
}
func ForgotPassword(repository UserQuery, tokenFactory otp.TokenFactory, templatemail *sendmail.TemplateMail) gin.HandlerFunc { func ForgotPassword(repository UserQuery, tokenFactory otp.TokenFactory, templatemail *sendmail.TemplateMail) gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
var req ForgotPasswordRequest var req ForgotPasswordRequest
......
...@@ -32,6 +32,7 @@ type UserQuery interface { ...@@ -32,6 +32,7 @@ type UserQuery interface {
Select(id uint32) ([]schemas.FullUserSchema, error) Select(id uint32) ([]schemas.FullUserSchema, error)
SelectByUsername(username string) ([]schemas.InfoUserSchema, error) SelectByUsername(username string) ([]schemas.InfoUserSchema, error)
SelectByUsernameLike(username string) ([]schemas.InfoUserSchema, error) SelectByUsernameLike(username string) ([]schemas.InfoUserSchema, error)
SelectUserRecommendations(userID uint32, count uint32) ([]schemas.InfoUserSchema, error)
SelectCredentialsByField(field UserField, value interface{}) (*schemas.CredentialsSchema, error) SelectCredentialsByField(field UserField, value interface{}) (*schemas.CredentialsSchema, error)
Authenticate(name string, password string) (uint32, error) Authenticate(name string, password string) (uint32, error)
Update(userID uint32, params PatchUserRequest, titleRepository title.TitleQuery) error Update(userID uint32, params PatchUserRequest, titleRepository title.TitleQuery) error
...@@ -405,6 +406,55 @@ func (MySQLUserQuery) SelectByUsernameLike(username string) ([]schemas.InfoUserS ...@@ -405,6 +406,55 @@ func (MySQLUserQuery) SelectByUsernameLike(username string) ([]schemas.InfoUserS
return users, nil return users, nil
} }
// SelectUserRecommendations fetches and returns a limited list of userdata for possible recommendations
func (MySQLUserQuery) SelectUserRecommendations(userID uint32, count uint32) ([]schemas.InfoUserSchema, error) {
db, connectionError := dbhandler.GetDBConnection()
if connectionError != nil {
return nil, errors.New("Unable to connect to database. " + connectionError.Error())
}
stmt, prepareError := db.Prepare(`
SELECT iduser, username, idavatar, avatar.image, avatar.level, title.idtitle,
title.name, subject.idsubject, subject.name, subject.shortform,
subject.department, subject.description, title.unlock_score, title.unlock_win
FROM user
LEFT JOIN title ON (title.idtitle=selected_title)
LEFT JOIN subject ON (idsubject=title.subject)
LEFT JOIN avatar ON (idavatar=selected_avatar)
WHERE iduser NOT IN (SELECT friend FROM friend WHERE user = ?)
AND iduser != ? AND verified = 1
ORDER BY RAND()
LIMIT ?`)
if prepareError != nil {
return nil, errors.New(
"An error occurred while preparing database access. " + prepareError.Error())
}
defer stmt.Close()
// execute sql query
rows, queryError := stmt.Query(userID, userID, count)
if queryError != nil {
return nil, errors.New("Cannot execute database query. " + queryError.Error())
}
defer rows.Close()
users := []schemas.InfoUserSchema{}
for rows.Next() {
var tmpUser schemas.InfoUserSchema
scanError := scanUser(rows.Scan, &tmpUser)
if scanError != nil {
return nil, errors.New("Cannot scan db values into users list. " + scanError.Error())
}
users = append(users, tmpUser)
}
return users, nil
}
func scanUser(scanFn func(dest ...interface{}) error, tmpUser *schemas.InfoUserSchema) error { func scanUser(scanFn func(dest ...interface{}) error, tmpUser *schemas.InfoUserSchema) error {
// Temporary subject // Temporary subject
var tmpSubjectID sql.NullInt32 var tmpSubjectID sql.NullInt32
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment