package user import ( "crypto/rand" "encoding/json" "errors" "math/big" "regexp" "strings" "unicode" "git.umbach.dev/app-idea/rest-api/modules/config" "git.umbach.dev/app-idea/rest-api/modules/database" "git.umbach.dev/app-idea/rest-api/modules/rabbitmq" "git.umbach.dev/app-idea/rest-api/modules/structs" "github.com/gofiber/fiber/v2" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) var cfg = &config.Cfg func generateRandomString(n int, t int) (string, error) { var letters string if t == 1 { letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" } else { letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" } r := make([]byte, n) for i := 0; i < n; i++ { num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) if err != nil { return "", err } r[i] = letters[num.Int64()] } return string(r), nil } func generateRandomHashtag(db *gorm.DB, n int) (string, error) { c := make(chan bool) var s string var err error for { s, err = generateRandomString(6, 0) if err != nil { log.Warnln("error generating hashtag:", err) return "", err } go func() { c <- isHashtagValid(db, 0, s) }() if msg := <-c; msg { break } } return s, nil } func isHashtagValid(db *gorm.DB, t int, h string) bool { if t == 1 && !isUpper(h) || len(h) < 2 || len(h) > 6 { return false } var res string db.Raw("SELECT hashtag FROM users WHERE hashtag = ?", h).Scan(&res) if res == "" { return true } else { return false } } func isUpper(s string) bool { for _, r := range s { if !unicode.IsUpper(r) && unicode.IsLetter(r) { return false } } return true } func isUsernameValid(u string) bool { if len(u) < int(cfg.Settings.Lengths.UsernameMinLen) || len(u) > int(cfg.Settings.Lengths.UsernameMaxLen) { return false } return true } var emailRegex = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") func isEmailValid(e string) bool { if len(e) < int(cfg.Settings.Lengths.EmailMinLen) || len(e) > int(cfg.Settings.Lengths.EmailMaxLen) { return false } return emailRegex.MatchString(e) } func isPasswordValid(p string) bool { if len(p) < int(cfg.Settings.Lengths.PasswordMinLen) || len(p) > int(cfg.Settings.Lengths.PasswordMaxLen) { return false } return true } func isEmailAvailable(db *gorm.DB, email string) bool { var res string db.Raw("SELECT email FROM users WHERE email = ?", email).Scan(&res) if res == "" { return true } else { return false } } func getUserIdBySessionId(sessionId string) (string, error) { db := database.DB session := structs.Session{} db.Select("user_id").Where(cfg.Settings.Cookies.SessionId+" = ?", sessionId).Find(&session) return session.UserId, nil } func GetUserById(c *fiber.Ctx) error { // swagger:operation GET /users User user // --- // summary: Informations about an user by id (except password) // parameters: // - name: v // in: query // description: Example -> { "v"; ["name", "state", "language_id"] } // type: string // required: true // responses: // '200': // description: User informations // '400': // description: Values wrong format return userInfos(c, c.Params("id")) } func GetUser(c *fiber.Ctx) error { // swagger:operation GET /user User user // --- // summary: Informations about the user (except password) // parameters: // - name: v // in: query // description: Example -> { "v"; ["name", "state", "language_id"] } // type: string // required: true // responses: // '200': // description: User informations // '400': // description: Values wrong format return userInfos(c, "") } func userInfos(c *fiber.Ctx, userId string) error { type Input struct { Values []string `json:"v"` } var input Input if err := c.BodyParser(&input); err != nil { return c.SendStatus(fiber.StatusBadRequest) } value := strings.Join(input.Values, ",") if strings.Contains(value, "password") { return c.SendStatus(fiber.StatusForbidden) } db := database.DB if userId == "" { var err error userId, err = getUserIdBySessionId(c.Cookies(cfg.Settings.Cookies.SessionId)) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } } user := map[string]interface{}{} res := db.Model(&structs.User{}).Select(value).First(&user, "id = ?", userId) if res.Error != nil { return c.SendStatus(fiber.StatusBadRequest) } return c.JSON(&user) } func GetUserBySessionId(sessionId string) (structs.User, error) { db := database.DB user := structs.User{} userId, err := getUserIdBySessionId(sessionId) if err != nil { return user, err } err = db.Where("id = ?", userId).First(&user).Error if errors.Is(err, gorm.ErrRecordNotFound) { return user, err } log.Infoln("getUserBySessionId", user) return user, nil } func deleteUser(c *fiber.Ctx) error { userAction := structs.UserAction{Id: c.Params("actionId")} db := database.DB db.First(&userAction) db.Delete(&structs.User{Id: userAction.UserId}) db.Where("user_id = ?", userAction.UserId).Delete(&structs.Session{}) db.Delete(&userAction) return c.SendStatus(fiber.StatusOK) } func DeleteUser(c *fiber.Ctx) error { user, err := GetUserBySessionId(c.Cookies(cfg.Settings.Cookies.SessionId)) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } userActivationId, err := createUserAction(user.Id) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } user.State = 2 db := database.DB db.Save(&user) rabbitmq.PublishMail(structs.RabbitmqMailMessage{Mail: user.Email, TemplateId: 1, LanguageId: user.LanguageId, BodyData: json.RawMessage(`{"name": "` + user.Name + `", "email": "` + user.Email + `", "url": "http://localhost:3000/api/v1/user/action/1/` + userActivationId + `"}`)}) return c.SendStatus(fiber.StatusOK) } /* func GetUsers(c *fiber.Ctx) error { list := []string{} /* var ( name string )*/ /* rows, err := db.Query("SELECT username FROM users;") fmt.Println("err", err) defer rows.Close() fmt.Println("reading data:") for rows.Next() { err := rows.Scan(&name) fmt.Printf("Data row = (%s, %s)\n", name, err) list = append(list, name) } err = rows.Err()*/ /* return c.JSON(list) } */