feat: remove user wx_open_id key

This commit is contained in:
steven 2021-12-12 21:49:46 +08:00
parent 1edf40ef69
commit 50c8947ad5
15 changed files with 55 additions and 221 deletions

View File

@ -39,7 +39,7 @@ func handleUserSignUp(w http.ResponseWriter, r *http.Request) {
return
}
user, err := store.CreateNewUser(userSignup.Username, userSignup.Password, "", "")
user, err := store.CreateNewUser(userSignup.Username, userSignup.Password, "")
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
@ -225,7 +225,7 @@ func handleGithubAuthCallback(w http.ResponseWriter, r *http.Request) {
username = githubUser.Name + utils.GenUUID()
usernameUsable, _ = store.CheckUsernameUsable(username)
}
user, _ = store.CreateNewUser(username, username, githubUser.Login, "")
user, _ = store.CreateNewUser(username, username, githubUser.Login)
}
session.Values["user_id"] = user.Id
@ -237,6 +237,8 @@ func handleGithubAuthCallback(w http.ResponseWriter, r *http.Request) {
func RegisterAuthRoutes(r *mux.Router) {
authRouter := r.PathPrefix("/api/auth").Subrouter()
authRouter.Use(JSONResponseMiddleWare)
authRouter.HandleFunc("/signup", handleUserSignUp).Methods("POST")
authRouter.HandleFunc("/signin", handleUserSignIn).Methods("POST")
authRouter.HandleFunc("/signout", handleUserSignOut).Methods("POST")

View File

@ -105,6 +105,7 @@ func handleDeleteMemo(w http.ResponseWriter, r *http.Request) {
func RegisterMemoRoutes(r *mux.Router) {
memoRouter := r.PathPrefix("/api/memo").Subrouter()
memoRouter.Use(JSONResponseMiddleWare)
memoRouter.Use(AuthCheckerMiddleWare)
memoRouter.HandleFunc("/all", handleGetMyMemos).Methods("GET")

View File

@ -18,6 +18,14 @@ func AuthCheckerMiddleWare(next http.Handler) http.Handler {
})
}
func JSONResponseMiddleWare(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
}
func CorsMiddleWare(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")

View File

@ -103,6 +103,7 @@ func handleDeleteQuery(w http.ResponseWriter, r *http.Request) {
func RegisterQueryRoutes(r *mux.Router) {
queryRouter := r.PathPrefix("/api/query").Subrouter()
queryRouter.Use(JSONResponseMiddleWare)
queryRouter.Use(AuthCheckerMiddleWare)
queryRouter.HandleFunc("/all", handleGetMyQueries).Methods("GET")

View File

@ -61,18 +61,6 @@ func handleUpdateMyUserInfo(w http.ResponseWriter, r *http.Request) {
}
}
if userPatch.WxOpenId != nil {
wxOpenIdUsable, _ := store.CheckWxOpenIdUsable(*userPatch.GithubName)
if !wxOpenIdUsable {
json.NewEncoder(w).Encode(Response{
Succeed: false,
Message: "Wx open id is existed",
Data: nil,
})
return
}
}
user, err := store.UpdateUser(userId, &userPatch)
if err != nil {
@ -145,6 +133,7 @@ func handleValidPassword(w http.ResponseWriter, r *http.Request) {
func RegisterUserRoutes(r *mux.Router) {
userRouter := r.PathPrefix("/api/user").Subrouter()
userRouter.Use(JSONResponseMiddleWare)
userRouter.Use(AuthCheckerMiddleWare)
userRouter.HandleFunc("/me", handleGetMyUserInfo).Methods("GET")

View File

@ -1,44 +1,46 @@
DROP TABLE IF EXISTS `memos`;
DROP TABLE IF EXISTS `queries`;
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` TEXT NOT NULL PRIMARY KEY,
`username` TEXT NOT NULL,
`password` TEXT NOT NULL,
`github_name` TEXT NOT NULL DEFAULT '',
`created_at` TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')),
`updated_at` TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')),
UNIQUE(`username`, `github_name`)
);
CREATE TABLE `queries` (
`id` TEXT NOT NULL PRIMARY KEY,
`user_id` TEXT NOT NULL,
`title` TEXT NOT NULL,
`querystring` TEXT NOT NULL,
`created_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
`pinned_at` TEXT DEFAULT '',
`created_at` TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')),
`updated_at` TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')),
`pinned_at` TEXT NOT NULL DEFAULT '',
FOREIGN KEY(`user_id`) REFERENCES `users`(`id`)
);
DROP TABLE IF EXISTS `memos`;
CREATE TABLE `memos` (
`id` TEXT NOT NULL PRIMARY KEY,
`content` TEXT NOT NULL,
`user_id` TEXT NOT NULL,
`created_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
`deleted_at` TEXT DEFAULT '',
`created_at` TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')),
`updated_at` TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')),
`deleted_at` TEXT NOT NULL DEFAULT '',
FOREIGN KEY(`user_id`) REFERENCES `users`(`id`)
);
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` TEXT NOT NULL PRIMARY KEY,
`username` TEXT NOT NULL,
`password` TEXT NOT NULL,
`github_name` TEXT DEFAULT '',
`wx_open_id` TEXT DEFAULT '',
`created_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(`username`, `github_name`, `wx_open_id`)
);
INSERT INTO `users`
(`id`, `username`, `password`)
VALUES
('1', 'guest', '123456');
('1', 'guest', '123456'),
('2', 'test', '123456');
INSERT INTO `memos`
(`id`, `content`, `user_id`)
VALUES
('1', '👋 Welcome to memos', '1');
('1', '👋 Welcome to memos', '1'),
('2', '👋 Welcome to memos', '2');

View File

@ -18,12 +18,12 @@ func main() {
api.RegisterMemoRoutes(r)
api.RegisterQueryRoutes(r)
spa := api.SPAHandler{
webServe := api.SPAHandler{
StaticPath: "./web/dist",
IndexPath: "index.html",
}
r.PathPrefix("/").Handler(spa)
r.PathPrefix("/").Handler(webServe)
http.ListenAndServe(":8080", r)
}

View File

@ -11,26 +11,24 @@ type User struct {
Id string `json:"id"`
Username string `json:"username"`
Password string `json:"password"`
WxOpenId string `json:"wxOpenId"`
GithubName string `json:"githubName"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
func CreateNewUser(username string, password string, githubName string, wxOpenId string) (User, error) {
func CreateNewUser(username string, password string, githubName string) (User, error) {
nowDateTimeStr := utils.GetNowDateTimeStr()
newUser := User{
Id: utils.GenUUID(),
Username: username,
Password: password,
WxOpenId: wxOpenId,
GithubName: githubName,
CreatedAt: nowDateTimeStr,
UpdatedAt: nowDateTimeStr,
}
query := `INSERT INTO users (id, username, password, wx_open_id, github_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)`
_, err := DB.Exec(query, newUser.Id, newUser.Username, newUser.Password, newUser.WxOpenId, newUser.GithubName, newUser.CreatedAt, newUser.UpdatedAt)
query := `INSERT INTO users (id, username, password, github_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)`
_, err := DB.Exec(query, newUser.Id, newUser.Username, newUser.Password, newUser.GithubName, newUser.CreatedAt, newUser.UpdatedAt)
return newUser, err
}
@ -39,7 +37,6 @@ type UserPatch struct {
Username *string
Password *string
GithubName *string
WxOpenId *string
}
func UpdateUser(id string, userPatch *UserPatch) (User, error) {
@ -58,10 +55,6 @@ func UpdateUser(id string, userPatch *UserPatch) (User, error) {
user.GithubName = *v
set, args = append(set, "github_name=?"), append(args, *v)
}
if v := userPatch.WxOpenId; v != nil {
user.WxOpenId = *v
set, args = append(set, "wx_open_id=?"), append(args, *v)
}
set, args = append(set, "updated_at=?"), append(args, utils.GetNowDateTimeStr())
args = append(args, id)
@ -72,30 +65,23 @@ func UpdateUser(id string, userPatch *UserPatch) (User, error) {
}
func GetUserById(id string) (User, error) {
query := `SELECT id, username, password, wx_open_id, github_name, created_at, updated_at FROM users WHERE id=?`
query := `SELECT id, username, password, github_name, created_at, updated_at FROM users WHERE id=?`
user := User{}
err := DB.QueryRow(query, id).Scan(&user.Id, &user.Username, &user.Password, &user.WxOpenId, &user.GithubName, &user.CreatedAt, &user.UpdatedAt)
err := DB.QueryRow(query, id).Scan(&user.Id, &user.Username, &user.Password, &user.GithubName, &user.CreatedAt, &user.UpdatedAt)
return user, err
}
func GetUserByUsernameAndPassword(username string, password string) (User, error) {
query := `SELECT id, username, password, wx_open_id, github_name, created_at, updated_at FROM users WHERE username=? AND password=?`
query := `SELECT id, username, password, github_name, created_at, updated_at FROM users WHERE username=? AND password=?`
user := User{}
err := DB.QueryRow(query, username, password).Scan(&user.Id, &user.Username, &user.Password, &user.WxOpenId, &user.GithubName, &user.CreatedAt, &user.UpdatedAt)
err := DB.QueryRow(query, username, password).Scan(&user.Id, &user.Username, &user.Password, &user.GithubName, &user.CreatedAt, &user.UpdatedAt)
return user, err
}
func GetUserByGithubName(githubName string) (User, error) {
query := `SELECT id, username, password, wx_open_id, github_name, created_at, updated_at FROM users WHERE github_name=?`
query := `SELECT id, username, password, github_name, created_at, updated_at FROM users WHERE github_name=?`
user := User{}
err := DB.QueryRow(query, githubName).Scan(&user.Id, &user.Username, &user.Password, &user.WxOpenId, &user.GithubName, &user.CreatedAt, &user.UpdatedAt)
return user, err
}
func GetUserByWxOpenId(wxOpenId string) (User, error) {
query := `SELECT id, username, password, wx_open_id, github_name, created_at, updated_at FROM users WHERE id=?`
user := User{}
err := DB.QueryRow(query, wxOpenId).Scan(&user.Id, &user.Username, &user.Password, &user.WxOpenId, &user.GithubName, &user.CreatedAt, &user.UpdatedAt)
err := DB.QueryRow(query, githubName).Scan(&user.Id, &user.Username, &user.Password, &user.GithubName, &user.CreatedAt, &user.UpdatedAt)
return user, err
}
@ -133,23 +119,6 @@ func CheckGithubNameUsable(githubName string) (bool, error) {
}
}
func CheckWxOpenIdUsable(wxOpenId string) (bool, error) {
query := `SELECT * FROM users WHERE wx_open_id=?`
query = fmt.Sprintf("SELECT COUNT(*) FROM (%s)", query)
var count uint
err := DB.QueryRow(query, wxOpenId).Scan(&count)
if err != nil && err != sql.ErrNoRows {
return false, FormatDBError(err)
}
if count > 0 {
return false, nil
} else {
return true, nil
}
}
func CheckPasswordValid(id string, password string) (bool, error) {
query := `SELECT * FROM users WHERE id=? AND password=?`
query = fmt.Sprintf("SELECT COUNT(*) FROM (%s)", query)

View File

@ -1,79 +0,0 @@
import { useEffect, useState } from "react";
import { userService } from "../services";
import { showDialog } from "./Dialog";
import toastHelper from "./Toast";
import "../less/change-password-dialog.less";
interface Props extends DialogProps {}
const BindWxOpenIdDialog: React.FC<Props> = ({ destroy }: Props) => {
const [wxOpenId, setWxOpenId] = useState("");
useEffect(() => {
// do nth
}, []);
const handleCloseBtnClick = () => {
destroy();
};
const handleWxOpenIdChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value as string;
setWxOpenId(text);
};
const handleSaveBtnClick = async () => {
if (wxOpenId === "") {
toastHelper.error("微信 id 不能为空");
return;
}
try {
await userService.updateWxOpenId(wxOpenId);
userService.doSignIn();
toastHelper.info("绑定成功!");
handleCloseBtnClick();
} catch (error: any) {
toastHelper.error(error);
}
};
return (
<>
<div className="dialog-header-container">
<p className="title-text"> OpenID</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" />
</button>
</div>
<div className="dialog-content-container">
<p className="tip-text">
<strong>OpenID</strong>
</p>
<label className="form-label input-form-label">
<span className={"normal-text " + (wxOpenId === "" ? "" : "not-null")}> OpenID</span>
<input type="text" value={wxOpenId} onChange={handleWxOpenIdChanged} />
</label>
<div className="btns-container">
<span className="btn cancel-btn" onClick={handleCloseBtnClick}>
</span>
<span className="btn confirm-btn" onClick={handleSaveBtnClick}>
</span>
</div>
</div>
</>
);
};
function showBindWxOpenIdDialog() {
showDialog(
{
className: "bind-wxid-dialog",
},
BindWxOpenIdDialog
);
}
export default showBindWxOpenIdDialog;

View File

@ -6,7 +6,6 @@ import { validate, ValidatorConfig } from "../helpers/validator";
import Only from "./common/OnlyWhen";
import toastHelper from "./Toast";
import showChangePasswordDialog from "./ChangePasswordDialog";
import showBindWxOpenIdDialog from "./BindWxOpenIdDialog";
import "../less/my-account-section.less";
const validateConfig: ValidatorConfig = {
@ -88,20 +87,6 @@ const MyAccountSection: React.FC<Props> = () => {
}
};
const handleUnbindWxBtnClick = async () => {
if (showConfirmUnbindWxBtn) {
try {
await userService.updateWxOpenId("");
await userService.doSignIn();
} catch (error: any) {
toastHelper.error(error.message);
}
setShowConfirmUnbindWxBtn(false);
} else {
setShowConfirmUnbindWxBtn(true);
}
};
const handlePreventDefault = (e: React.MouseEvent) => {
e.preventDefault();
};
@ -155,33 +140,6 @@ const MyAccountSection: React.FC<Props> = () => {
<Only when={window.location.origin.includes("justsven.top")}>
<div className="section-container connect-section-container">
<p className="title-text"></p>
<label className="form-label input-form-label hidden">
<span className="normal-text"> OpenID</span>
{user.wxOpenId ? (
<>
<span className="value-text">************</span>
<span
className={`btn-text unbind-btn ${showConfirmUnbindWxBtn ? "final-confirm" : ""}`}
onMouseLeave={() => setShowConfirmUnbindWxBtn(false)}
onClick={handleUnbindWxBtnClick}
>
{showConfirmUnbindWxBtn ? "确定取消绑定!" : "取消绑定"}
</span>
</>
) : (
<>
<span className="value-text"></span>
<span
className="btn-text bind-btn"
onClick={() => {
showBindWxOpenIdDialog();
}}
>
ID
</span>
</>
)}
</label>
<label className="form-label input-form-label">
<span className="normal-text">GitHub</span>
{user.githubName ? (

View File

@ -55,14 +55,7 @@ namespace api {
return request<boolean>("POST", "/api/user/validpassword", { password });
}
interface UserInfoPatch {
username?: string;
password?: string;
githubName?: string;
wxOpenId?: string;
}
export function updateUserinfo(userinfo: UserInfoPatch) {
export function updateUserinfo(userinfo: Partial<{ username: string; password: string; githubName: string }>) {
return request("PATCH", "/api/user/me", userinfo);
}

View File

@ -1,7 +1,6 @@
@import "./mixin.less";
.change-password-dialog,
.bind-wxid-dialog {
.change-password-dialog {
> .dialog-container {
width: 300px;
border-radius: 8px;
@ -92,8 +91,7 @@
}
@media only screen and (max-width: 875px) {
.dialog-wrapper.change-password-dialog,
.dialog-wrapper.bind-wxid-dialog {
.dialog-wrapper.change-password-dialog {
padding: 24px 16px;
padding-top: 64px;

View File

@ -4,4 +4,3 @@ What should service do?
- request data api and throw error;
- dispatch state actions;
- should be a class;

View File

@ -56,12 +56,6 @@ class UserService {
password,
});
}
public async updateWxOpenId(wxOpenId: string): Promise<void> {
await api.updateUserinfo({
wxOpenId,
});
}
}
const userService = new UserService();

View File

@ -7,18 +7,17 @@ declare namespace Model {
interface User extends BaseModel {
username: string;
githubName?: string;
wxOpenId?: string;
githubName: string;
}
interface Memo extends BaseModel {
content: string;
deletedAt?: string;
deletedAt: string;
}
interface Query extends BaseModel {
title: string;
querystring: string;
pinnedAt?: string;
pinnedAt: string;
}
}