add new random hashtag func and add hashtag login check
parent
8ad6b6e623
commit
932a4d6675
|
@ -9,7 +9,7 @@ POST http://localhost:3000/api/v1/users
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"username": "ben4",
|
"username": "145",
|
||||||
"email": "ben4@roese.dev",
|
"email": "145@roese.dev",
|
||||||
"password": "teksmkamsdkasdmaskdmaskdm"
|
"password": "teksmkamsdkasdmaskdmaskdm"
|
||||||
}
|
}
|
2
go.mod
2
go.mod
|
@ -10,8 +10,10 @@ require (
|
||||||
github.com/gofiber/fiber/v2 v2.8.0
|
github.com/gofiber/fiber/v2 v2.8.0
|
||||||
github.com/google/uuid v1.2.0
|
github.com/google/uuid v1.2.0
|
||||||
github.com/klauspost/compress v1.12.2 // indirect
|
github.com/klauspost/compress v1.12.2 // indirect
|
||||||
|
github.com/satori/go.uuid v1.2.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.24.0 // indirect
|
github.com/valyala/fasthttp v1.24.0 // indirect
|
||||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
|
github.com/zhengxiaowai/shortuuid v0.0.0-20181208145701-0c38c76c12b3 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf
|
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf
|
||||||
golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 // indirect
|
golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 // indirect
|
||||||
)
|
)
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -424,6 +424,8 @@ github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
@ -486,6 +488,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/zhengxiaowai/shortuuid v0.0.0-20181208145701-0c38c76c12b3 h1:03r8Xo0XhTGIMuyJ9x3yrYCumC+T4ycXShfW+Le3Sts=
|
||||||
|
github.com/zhengxiaowai/shortuuid v0.0.0-20181208145701-0c38c76c12b3/go.mod h1:bxh5+Ghwiy6UJxDAPpoOB/L+dq0To9dky7x92nWeSKU=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||||
|
|
|
@ -3,15 +3,16 @@ package user
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"git.umbach.dev/app-idea/rest-api/modules/database"
|
"git.umbach.dev/app-idea/rest-api/modules/database"
|
||||||
"git.umbach.dev/app-idea/rest-api/modules/debug"
|
"git.umbach.dev/app-idea/rest-api/modules/debug"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/zhengxiaowai/shortuuid"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ func NewUser(c *fiber.Ctx) error {
|
||||||
// required: true
|
// required: true
|
||||||
// - name: hashtag
|
// - name: hashtag
|
||||||
// in: query
|
// in: query
|
||||||
// description: hashtag of the client (length 1-6, UPPERCASE)
|
// description: hashtag of the client (length 2-6, UPPERCASE)
|
||||||
// type: string
|
// type: string
|
||||||
// - name: avatar_url
|
// - name: avatar_url
|
||||||
// in: query
|
// in: query
|
||||||
|
@ -58,11 +59,12 @@ func NewUser(c *fiber.Ctx) error {
|
||||||
// '400':
|
// '400':
|
||||||
// description: format is not correct
|
// description: format is not correct
|
||||||
// '422':
|
// '422':
|
||||||
// description: username or/and email already already assigned
|
// description: username, email or/and hashtag already assigned
|
||||||
type LoginInput struct {
|
type LoginInput struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
|
Hashtag string `json:"hashtag"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var input LoginInput
|
var input LoginInput
|
||||||
|
@ -83,12 +85,17 @@ func NewUser(c *fiber.Ctx) error {
|
||||||
|
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
if !isValueAvailable(db, "email", input.Email) {
|
if !isEmailAvailable(db, input.Email) {
|
||||||
|
return c.SendStatus(fiber.StatusUnprocessableEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.Hashtag == "" {
|
||||||
|
input.Hashtag = RandomHashtag(db, 6)
|
||||||
|
} else if !isHashtagValid(db, input.Hashtag) {
|
||||||
return c.SendStatus(fiber.StatusUnprocessableEntity)
|
return c.SendStatus(fiber.StatusUnprocessableEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
password := []byte(input.Password)
|
password := []byte(input.Password)
|
||||||
|
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
|
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -97,38 +104,29 @@ func NewUser(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
user_id := strings.Replace(uuid.New().String(), "-", "", -1)
|
user_id := strings.Replace(uuid.New().String(), "-", "", -1)
|
||||||
user_hashtag := RandomHashtag(db, 6)
|
|
||||||
created := time.Now().Format("2006-02-01 15:04:05")
|
created := time.Now().Format("2006-02-01 15:04:05")
|
||||||
|
|
||||||
stmt, err := db.Prepare("INSERT INTO users (user_id, user_hashtag, username, email, password, created) VALUES (?, ?, ?, ?, ?, ?);")
|
stmt, err := db.Prepare("INSERT INTO users (user_id, user_hashtag, username, email, password, created) VALUES (?, ?, ?, ?, ?, ?);")
|
||||||
stmt.Exec(user_id, user_hashtag, input.Username, input.Email, hashedPassword, created)
|
stmt.Exec(user_id, input.Hashtag, input.Username, input.Email, hashedPassword, created)
|
||||||
|
|
||||||
stmt.Close()
|
stmt.Close()
|
||||||
|
|
||||||
debug.Msg("user created", user_id, user_hashtag, input.Username, input.Email)
|
debug.Msg("user created", user_id, input.Hashtag, input.Username, input.Email)
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusCreated)
|
return c.SendStatus(fiber.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandomHashtag(db *sql.DB, n int) string {
|
func RandomHashtag(db *sql.DB, n int) string {
|
||||||
var letters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
||||||
|
|
||||||
s := make([]rune, n)
|
|
||||||
c := make(chan bool)
|
c := make(chan bool)
|
||||||
|
var s string
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// TODO: randomness is very bad -> always the same
|
su := shortuuid.NewShortUUID()
|
||||||
for i := range s {
|
su.SetAlphabet("ABCDEFGHJKLMNPQRSTUVWXYZ")
|
||||||
s[i] = letters[rand.Intn(len(letters))]
|
s = su.Random(n)
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(s))
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
fmt.Println("conncur", string(s))
|
err := db.QueryRow("SELECT user_hashtag FROM users WHERE user_hashtag = ?", s).Scan(&s)
|
||||||
err := db.QueryRow("SELECT user_hashtag FROM users WHERE user_hashtag = ?", string(s)).Scan(&s)
|
|
||||||
|
|
||||||
fmt.Println("ErrNoRows?", err == sql.ErrNoRows)
|
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
c <- true
|
c <- true
|
||||||
|
@ -137,26 +135,36 @@ func RandomHashtag(db *sql.DB, n int) string {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
msg := <-c
|
if msg := <-c; msg {
|
||||||
|
|
||||||
fmt.Println("msg", msg)
|
|
||||||
|
|
||||||
if msg {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("r string", string(s))
|
return s
|
||||||
return string(s)
|
}
|
||||||
/*
|
|
||||||
err := db.QueryRow("SELECT user_hashtag FROM users WHERE user_hashtag = ?", s).Scan(&s)
|
func isHashtagValid(db *sql.DB, h string) bool {
|
||||||
|
if !isUpper(h) || len(h) < 2 || len(h) > 6 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
err := db.QueryRow("SELECT user_hashtag FROM users WHERE user_hashtag = ?", h).Scan(&h)
|
||||||
|
|
||||||
|
fmt.Println("isHashtagValid", err == sql.ErrNoRows)
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return string(s) */
|
func isUpper(s string) bool {
|
||||||
|
for _, r := range s {
|
||||||
|
if !unicode.IsUpper(r) && unicode.IsLetter(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func isValid(s string, min int, max int) bool {
|
func isValid(s string, min int, max int) bool {
|
||||||
|
@ -175,56 +183,13 @@ func isEmailValid(e string) bool {
|
||||||
return emailRegex.MatchString(e)
|
return emailRegex.MatchString(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isValueAvailable(db *sql.DB, t string, v string) bool {
|
func isEmailAvailable(db *sql.DB, e string) bool {
|
||||||
q := fmt.Sprintf("SELECT %s FROM users WHERE %s = ?", t, t)
|
err := db.QueryRow("SELECT email FROM users WHERE email = ?", e).Scan(&e)
|
||||||
|
|
||||||
err := db.QueryRow(q, v).Scan(&v)
|
|
||||||
|
|
||||||
fmt.Println(err == sql.ErrNoRows)
|
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
||||||
/*
|
|
||||||
if email == "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false */
|
|
||||||
|
|
||||||
/*
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
tsql := fmt.Sprintf("SELECT email FROM users WHERE email = '%s'", e)
|
|
||||||
|
|
||||||
rows, err := db.QueryContext(ctx, tsql)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("rows", rows)
|
|
||||||
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var count int
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var email string
|
|
||||||
|
|
||||||
err := rows.Scan(&email)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Email: %s \n", email)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(count)
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUser(c *fiber.Ctx) error {
|
func GetUser(c *fiber.Ctx) error {
|
||||||
|
|
Loading…
Reference in New Issue