From dc029505d7266ca33a45a56a9030232b7d036c9a Mon Sep 17 00:00:00 2001 From: sunface Date: Fri, 9 Apr 2021 10:25:56 +0800 Subject: [PATCH] add init tags --- pages/login/onboard.tsx | 11 +++++++ server/internal/api/admin.go | 5 +++ server/internal/storage/init.go | 9 +++++- server/internal/storage/init_tags.go | 47 ++++++++++++++++++++++++++++ server/pkg/models/user.go | 27 ++++++++++++++++ src/utils/user.ts | 6 +++- 6 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 server/internal/storage/init_tags.go diff --git a/pages/login/onboard.tsx b/pages/login/onboard.tsx index 0f52e6c1..d33d016e 100644 --- a/pages/login/onboard.tsx +++ b/pages/login/onboard.tsx @@ -10,6 +10,7 @@ import Link from "next/link" import { ReserveUrls } from "src/data/reserve-urls" import { Tag } from "src/types/tag" import Follow from "components/interaction/follow" +import { validateUsername } from "utils/user" const OnboardPage = () => { const [step,setStep] = useState(1) @@ -50,6 +51,16 @@ const OnboardPage = () => { }) return } + const res0 = await validateUsername(username) + if (res0) { + toast({ + description: res0, + status: "error", + duration: 2000, + isClosable: true, + }) + return + } const res = await requestApi.post("/user/register", { code: code, nickname: nickname,username: username }) saveToken(res.data.token) storage.set('session', res.data) diff --git a/server/internal/api/admin.go b/server/internal/api/admin.go index 801f9539..b7062c0f 100644 --- a/server/internal/api/admin.go +++ b/server/internal/api/admin.go @@ -29,6 +29,11 @@ func AdminSubmitUser(c *gin.Context) { return } + err0 := models.IsUsernameValid(u.Username) + if err0 != nil { + c.JSON(http.StatusBadRequest, common.RespError(err0.Error())) + return + } err := user.SubmitUser(u) if err != nil { c.JSON(err.Status, common.RespError(err.Message)) diff --git a/server/internal/storage/init.go b/server/internal/storage/init.go index abcb3e2e..7c7a27ea 100644 --- a/server/internal/storage/init.go +++ b/server/internal/storage/init.go @@ -63,8 +63,9 @@ func initTables() error { } now := time.Now() + adminID := utils.GenID(models.IDTypeUser) _, err := db.Conn.Exec(`INSERT INTO user (id,type,username,nickname,email,role,nickname,avatar,created,updated) VALUES (?,?,?,?,?,?,?,?,?,?)`, - utils.GenID(models.IDTypeUser), models.IDTypeUser, config.Data.User.SuperAdminUsername, "Admin", config.Data.User.SuperAdminEmail, models.ROLE_SUPER_ADMIN, "", "", now, now) + adminID, models.IDTypeUser, config.Data.User.SuperAdminUsername, "Admin", config.Data.User.SuperAdminEmail, models.ROLE_SUPER_ADMIN, "", "", now, now) if err != nil { log.RootLogger.Crit("init super admin error", "error:", err) return err @@ -77,6 +78,12 @@ func initTables() error { return err } + // insert tags + err = initTags(adminID) + if err != nil { + log.RootLogger.Crit("init tags error", "error:", err) + return err + } // init online configs c := map[string]interface{}{ "posts": map[string]interface{}{ diff --git a/server/internal/storage/init_tags.go b/server/internal/storage/init_tags.go new file mode 100644 index 00000000..34e5947e --- /dev/null +++ b/server/internal/storage/init_tags.go @@ -0,0 +1,47 @@ +package storage + +import ( + "github.com/imdotdev/im.dev/server/internal/tags" + "github.com/imdotdev/im.dev/server/pkg/models" +) + +var tagsList = []*models.Tag{ + &models.Tag{Title: "Javascript", Name: "javascript", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1607082785538/EryuLRriM.png?w=400&h=400&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "", Name: "", Icon: ""}, + &models.Tag{Title: "React", Name: "reactjs", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1513321478077/ByCWNxZMf.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Nodejs", Name: "nodejs", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1607322143407/LsbeyUL86.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Python", Name: "python", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1607321670861/lG265gIUp.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "CSS", Name: "css", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1513316949083/By6UMkbfG.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Java", Name: "java", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1534512378322/H1gM-pH4UQ.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Go", Name: "go", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1534512687168/S1D40rVLm.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "PHP", Name: "php", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1513177307594/rJ4Jba0-G.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "React Native", Name: "react-native", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/rkij45wit50lfpkbte5q/1475235386.jpg?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Angular", Name: "angular", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1513839958045/HJ0LTRdMz.jpeg?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Android", Name: "android", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/qbj34hxd8981nfdugyph/1450468271.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Machine Learning", Name: "machine-learning", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1513321644252/Sk43El-fz.png?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Developer", Name: "developer", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1554321431158/MqVqSHr8Q.jpeg?w=180&h=180&fit=crop&crop=entropy&auto=compress"}, + &models.Tag{Title: "Docker", Name: "docker", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--7L1txQC1--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/87/docker-badge.png"}, + &models.Tag{Title: "Kubernetes", Name: "kubernetes", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--XXaJdQCT--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/88/kubernetes-badge.png"}, + &models.Tag{Title: "Rust", Name: "rust", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--4RD0-X0v--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/35/rust-badge.png"}, + &models.Tag{Title: "Web Development", Name: "webdev", Icon: "https://i.postimg.cc/RVP8fWFz/web-dev-logo.png"}, + &models.Tag{Title: "Testing", Name: "testing", Icon: "https://i.postimg.cc/0ygM0fzs/testing-image.png"}, + &models.Tag{Title: "VueJS", Name: "vue", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--KflrVC4o--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/27/vue-sticker.png"}, + &models.Tag{Title: "Discuss", Name: "discuss", Icon: "https://i.postimg.cc/jScTwK9B/disscuss-image.png"}, + &models.Tag{Title: "News", Name: "news", Icon: "https://i.postimg.cc/yxm5MyC2/news-image.png"}, + &models.Tag{Title: "Typescript", Name: "typescript", Icon: "https://i.postimg.cc/PJTKwG0F/typescript-image.png"}, + &models.Tag{Title: "Linux", Name: "linux", Icon: "https://i.postimg.cc/BnL5tQXn/linux-image.jpg"}, + &models.Tag{Title: "Mysql", Name: "mysql", Icon: "https://i.postimg.cc/fyytFBdR/mysql-image.png"}, + &models.Tag{Title: "Flutter", Name: "flutter", Icon: "https://i.postimg.cc/dtp7D2bz/flutter-image.png"}, + &models.Tag{Title: "IOS", Name: "ios", Icon: "https://i.postimg.cc/z3ZFCsLg/ios-image.png"}, + &models.Tag{Title: "CPP", Name: "cpp", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--lRZA1qmc--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/95/cpp_logo.png"}, + &models.Tag{Title: "APM", Name: "apm", Icon: "https://i.postimg.cc/8cYwcyg7/apm-image.png"}, + &models.Tag{Title: "Algorithms", Name: "algorithms", Icon: "https://i.postimg.cc/yYBQtRpC/algorithms-image.png"}, +} + +func initTags(u string) error { + for _, tag := range tagsList { + tag.Creator = u + tags.SubmitTag(tag) + } + return nil +} diff --git a/server/pkg/models/user.go b/server/pkg/models/user.go index c01af69f..5c23bfa4 100644 --- a/server/pkg/models/user.go +++ b/server/pkg/models/user.go @@ -1,6 +1,7 @@ package models import ( + "errors" "time" "github.com/imdotdev/im.dev/server/pkg/db" @@ -76,3 +77,29 @@ func (user *UserSimple) Query() error { return err } + +const usernameInvalidTips = "Username may only contain alphanumeric characters or single hyphens, and cannot begin or end with a hyphen." + +func IsUsernameValid(u string) error { + if len(u) == 0 { + return errors.New("用户名不能为空") + } + + if u[0] == '-' { + return errors.New(usernameInvalidTips) + } + + if u[len(u)-1] == '-' { + return errors.New(usernameInvalidTips) + } + + for _, c := range u { + if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '-') { + continue + } + + return errors.New(usernameInvalidTips) + } + + return nil +} diff --git a/src/utils/user.ts b/src/utils/user.ts index 14852968..e6734f1e 100644 --- a/src/utils/user.ts +++ b/src/utils/user.ts @@ -8,7 +8,7 @@ export function getUserName(user:User) { } export function isUsernameChar(c) { - if ((c >= "A" && "c<=Z") || (c >= "a" && "c<=z") || (c >= "0" && c <= "9") || (c === "-")) { + if ((c >= "A" && c<="Z") || (c >= "a" && c<="z") || (c >= "0" && c <= "9") || (c === "-")) { return true } @@ -28,6 +28,10 @@ export const validateUsername = async value => { return `长度不能超过${config.user.usernameMaxLen}` } + if (value[0] ==='-' || value[value.length-1]==='-') { + return usernameInvalidTips + } + for (const c of value) { if (!isUsernameChar(c)) { return usernameInvalidTips