feat: remove user wx_open_id key

pull/5/head
steven 3 years ago
parent 1edf40ef69
commit 50c8947ad5

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

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

@ -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 { func CorsMiddleWare(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Origin", "*")

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

@ -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) user, err := store.UpdateUser(userId, &userPatch)
if err != nil { if err != nil {
@ -145,6 +133,7 @@ func handleValidPassword(w http.ResponseWriter, r *http.Request) {
func RegisterUserRoutes(r *mux.Router) { func RegisterUserRoutes(r *mux.Router) {
userRouter := r.PathPrefix("/api/user").Subrouter() userRouter := r.PathPrefix("/api/user").Subrouter()
userRouter.Use(JSONResponseMiddleWare)
userRouter.Use(AuthCheckerMiddleWare) userRouter.Use(AuthCheckerMiddleWare)
userRouter.HandleFunc("/me", handleGetMyUserInfo).Methods("GET") userRouter.HandleFunc("/me", handleGetMyUserInfo).Methods("GET")

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

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

@ -11,26 +11,24 @@ type User struct {
Id string `json:"id"` Id string `json:"id"`
Username string `json:"username"` Username string `json:"username"`
Password string `json:"password"` Password string `json:"password"`
WxOpenId string `json:"wxOpenId"`
GithubName string `json:"githubName"` GithubName string `json:"githubName"`
CreatedAt string `json:"createdAt"` CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"` 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() nowDateTimeStr := utils.GetNowDateTimeStr()
newUser := User{ newUser := User{
Id: utils.GenUUID(), Id: utils.GenUUID(),
Username: username, Username: username,
Password: password, Password: password,
WxOpenId: wxOpenId,
GithubName: githubName, GithubName: githubName,
CreatedAt: nowDateTimeStr, CreatedAt: nowDateTimeStr,
UpdatedAt: nowDateTimeStr, UpdatedAt: nowDateTimeStr,
} }
query := `INSERT INTO users (id, username, password, wx_open_id, github_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)` 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.WxOpenId, newUser.GithubName, newUser.CreatedAt, newUser.UpdatedAt) _, err := DB.Exec(query, newUser.Id, newUser.Username, newUser.Password, newUser.GithubName, newUser.CreatedAt, newUser.UpdatedAt)
return newUser, err return newUser, err
} }
@ -39,7 +37,6 @@ type UserPatch struct {
Username *string Username *string
Password *string Password *string
GithubName *string GithubName *string
WxOpenId *string
} }
func UpdateUser(id string, userPatch *UserPatch) (User, error) { func UpdateUser(id string, userPatch *UserPatch) (User, error) {
@ -58,10 +55,6 @@ func UpdateUser(id string, userPatch *UserPatch) (User, error) {
user.GithubName = *v user.GithubName = *v
set, args = append(set, "github_name=?"), append(args, *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()) set, args = append(set, "updated_at=?"), append(args, utils.GetNowDateTimeStr())
args = append(args, id) args = append(args, id)
@ -72,30 +65,23 @@ func UpdateUser(id string, userPatch *UserPatch) (User, error) {
} }
func GetUserById(id string) (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{} 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 return user, err
} }
func GetUserByUsernameAndPassword(username string, password string) (User, error) { 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{} 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 return user, err
} }
func GetUserByGithubName(githubName string) (User, error) { 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{} 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 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) { func CheckPasswordValid(id string, password string) (bool, error) {
query := `SELECT * FROM users WHERE id=? AND password=?` query := `SELECT * FROM users WHERE id=? AND password=?`
query = fmt.Sprintf("SELECT COUNT(*) FROM (%s)", query) query = fmt.Sprintf("SELECT COUNT(*) FROM (%s)", query)

@ -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;

@ -6,7 +6,6 @@ import { validate, ValidatorConfig } from "../helpers/validator";
import Only from "./common/OnlyWhen"; import Only from "./common/OnlyWhen";
import toastHelper from "./Toast"; import toastHelper from "./Toast";
import showChangePasswordDialog from "./ChangePasswordDialog"; import showChangePasswordDialog from "./ChangePasswordDialog";
import showBindWxOpenIdDialog from "./BindWxOpenIdDialog";
import "../less/my-account-section.less"; import "../less/my-account-section.less";
const validateConfig: ValidatorConfig = { 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) => { const handlePreventDefault = (e: React.MouseEvent) => {
e.preventDefault(); e.preventDefault();
}; };
@ -155,33 +140,6 @@ const MyAccountSection: React.FC<Props> = () => {
<Only when={window.location.origin.includes("justsven.top")}> <Only when={window.location.origin.includes("justsven.top")}>
<div className="section-container connect-section-container"> <div className="section-container connect-section-container">
<p className="title-text"></p> <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"> <label className="form-label input-form-label">
<span className="normal-text">GitHub</span> <span className="normal-text">GitHub</span>
{user.githubName ? ( {user.githubName ? (

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

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

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

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

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

Loading…
Cancel
Save