You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

261 lines
7.8 KiB

package user
import (
"encoding/json"
"errors"
"net/http"
"strings"
"time"
"unicode/utf8"
"github.com/labstack/echo"
"go.uber.org/zap"
"github.com/thinkindev/im.dev/internal/ecode"
"github.com/thinkindev/im.dev/internal/misc"
"github.com/thinkindev/im.dev/internal/utils"
"github.com/thinkindev/im.dev/internal/utils/validate"
)
// InitUser insert preserve users
func InitUser() {
err := misc.CQL.Query(`INSERT INTO user (id,name,nickname,avatar,create_date,edit_date) VALUES (?,?,?,?,?,?)`,
"13269", "sunface", "Sunface", "https://avatars2.githubusercontent.com/u/7036754?s=460&v=4", time.Now().Unix(), 0).Exec()
if err != nil {
misc.Log.Warn("access database error", zap.Error(err))
}
}
// CheckUserExist checks user exist by given user id
func CheckUserExist(n string) bool {
var name string
err := misc.CQL.Query(`SELECT name FROM user where name=?`, n).Scan(&name)
if err != nil && err.Error() != misc.CQLNotFound {
misc.Log.Warn("access database error", zap.Error(err))
return false
}
if name != "" {
return true
}
return false
}
// Card returns user detail card info
func Card(c echo.Context) error {
uid := c.FormValue("uid")
if uid == "" {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: ecode.ParamInvalidMsg,
})
}
user := &User{}
q := misc.CQL.Query(`SELECT name,nickname,avatar,website,about,location,bg_color,text_color,looking_for_work,education,employer,
create_date FROM user WHERE id=?`, uid)
err := q.Scan(&user.Name, &user.NickName,
&user.Avatar, &user.Website, &user.About, &user.Location, &user.BgColor, &user.TextColor, &user.LookingForWork,
&user.Education, &user.Employer, &user.createDate)
if err != nil {
if err.Error() == misc.CQLNotFound {
return c.JSON(http.StatusNotFound, misc.HTTPResp{
ErrCode: ecode.NotFound,
Message: ecode.NotFoundMsg,
})
}
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
user.CreateDate = utils.Time2ReadableString(time.Unix(user.createDate, 0))
if user.BgColor == "" {
user.BgColor = "#000"
}
if user.TextColor == "" {
user.TextColor = "#000"
}
return c.JSON(http.StatusOK, misc.HTTPResp{
Data: user,
})
}
// GetUserByID return the user info by user id
func GetUserByID(uid string) *Session {
sess := &Session{ID: uid}
err := misc.CQL.Query(`SELECT name,nickname,avatar FROM user WHERE id=?`, uid).Scan(&sess.Name, &sess.NickName, &sess.Avatar)
if err != nil && err.Error() != misc.CQLNotFound {
misc.Log.Warn("access database error", zap.Error(err))
return nil
}
return sess
}
// User holds all info of one user
type User struct {
//----account-----
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"`
//----profile-----
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
Website string `json:"website"`
About string `json:"about"`
Location string `json:"location"`
BgColor string `json:"bg_color"`
TextColor string `json:"text_color"`
LookingForWork bool `json:"lfw"`
Education string `json:"education"`
Employer string `json:"employer"`
Skills string `json:"skills"`
AvailableFor string `json:"available_for"`
WorkingExp string `json:"working_exp"`
CreateDate string `json:"create_date"`
EditDate string `json:"edit_date"`
createDate int64
editDate int64
}
// Profile return user's detail profile
func Profile(c echo.Context) error {
sess := GetSession(c)
user := &User{}
q := misc.CQL.Query(`SELECT id,name,email,nickname,avatar,website,about,location,bg_color,text_color,looking_for_work,education,employer,skills,
available_for,working_exp,create_date,edit_date FROM user WHERE id=?`, sess.ID)
err := q.Scan(&user.ID, &user.Name, &user.Email, &user.NickName,
&user.Avatar, &user.Website, &user.About, &user.Location, &user.BgColor, &user.TextColor, &user.LookingForWork,
&user.Education, &user.Employer, &user.Skills, &user.AvailableFor, &user.WorkingExp, &user.createDate, &user.editDate)
if err != nil {
if err.Error() == misc.CQLNotFound {
return c.JSON(http.StatusNotFound, misc.HTTPResp{
ErrCode: ecode.NotFound,
Message: ecode.NotFoundMsg,
})
}
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
user.CreateDate = utils.Time2ReadableString(time.Unix(user.createDate, 0))
if user.BgColor == "" {
user.BgColor = "#000"
}
if user.TextColor == "" {
user.TextColor = "#000"
}
return c.JSON(http.StatusOK, misc.HTTPResp{
Data: user,
})
}
// SetProfile set user profile
func SetProfile(c echo.Context) error {
u := c.FormValue("user")
user := &User{}
err := json.Unmarshal([]byte(u), &user)
if err != nil {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: ecode.ParamInvalidMsg,
})
}
err = validateProfile(user)
sess := GetSession(c)
q := misc.CQL.Query(`UPDATE user SET nickname=?,avatar=?,website=?,about=?,location=?,bg_color=?,
text_color=?,looking_for_work=?,education=?,employer=?,skills=?,available_for=?,working_exp=?,edit_date=? WHERE id=?`, user.NickName,
user.Avatar, user.Website, user.About, user.Location, user.BgColor, user.TextColor, user.LookingForWork, user.Education, user.Employer,
user.Skills, user.AvailableFor, user.WorkingExp, time.Now().Unix(), sess.ID)
err = q.Exec()
if err != nil {
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
if err != nil {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: err.Error(),
})
}
return c.JSON(http.StatusOK, misc.HTTPResp{})
}
func validateProfile(user *User) error {
user.NickName = misc.Sanitizer.Sanitize(strings.TrimSpace(user.NickName))
if utf8.RuneCountInString(user.NickName) > 30 {
return errors.New("Display name too long")
}
user.About = misc.Sanitizer.Sanitize(strings.TrimSpace(user.About))
if utf8.RuneCountInString(user.About) > 500 {
return errors.New("About too long")
}
user.Website = misc.Sanitizer.Sanitize(strings.TrimSpace(user.Website))
if utf8.RuneCountInString(user.Website) > 30 || !validate.IsURL(user.Website) {
return errors.New("Website invalid or too long")
}
user.Location = misc.Sanitizer.Sanitize(strings.TrimSpace(user.Location))
if utf8.RuneCountInString(user.Location) > 30 {
return errors.New("About too long")
}
user.BgColor = strings.TrimSpace(user.BgColor)
if !validate.IsColor(user.BgColor) {
return errors.New("Invalid background color")
}
user.TextColor = strings.TrimSpace(user.TextColor)
if !validate.IsColor(user.TextColor) {
return errors.New("Invalid text color")
}
user.Education = misc.Sanitizer.Sanitize(strings.TrimSpace(user.Education))
if utf8.RuneCountInString(user.Education) > 500 {
return errors.New("Education too long")
}
user.Employer = misc.Sanitizer.Sanitize(strings.TrimSpace(user.Employer))
if utf8.RuneCountInString(user.Employer) > 500 {
return errors.New("Employer too long")
}
user.Skills = misc.Sanitizer.Sanitize(strings.TrimSpace(user.Skills))
if utf8.RuneCountInString(user.Skills) > 500 {
return errors.New("Skills too long")
}
user.AvailableFor = misc.Sanitizer.Sanitize(strings.TrimSpace(user.AvailableFor))
if utf8.RuneCountInString(user.Employer) > 500 {
return errors.New("Available for too long")
}
user.WorkingExp = misc.Sanitizer.Sanitize(strings.TrimSpace(user.WorkingExp))
if utf8.RuneCountInString(user.Employer) > 500 {
return errors.New("Working experience too long")
}
return nil
}