mirror of
				https://github.com/usememos/memos.git
				synced 2025-10-31 00:38:08 +08:00 
			
		
		
		
	init project
This commit is contained in:
		
						commit
						2f72bfa946
					
				
					 19 changed files with 677 additions and 0 deletions
				
			
		
							
								
								
									
										28
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| # Binaries for programs and plugins | ||||
| *.exe | ||||
| *.exe~ | ||||
| *.dll | ||||
| *.so | ||||
| *.dylib | ||||
| 
 | ||||
| # Test binary, built with `go test -c` | ||||
| *.test | ||||
| 
 | ||||
| # Temp output | ||||
| *.out | ||||
| *.log | ||||
| tmp | ||||
| 
 | ||||
| # Air (hot reload) generated | ||||
| .air | ||||
| 
 | ||||
| # Frontend asset | ||||
| dist | ||||
| 
 | ||||
| # Dev database | ||||
| data | ||||
| 
 | ||||
| # build folder | ||||
| build | ||||
| 
 | ||||
| .DS_Store | ||||
							
								
								
									
										3
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| # ✍️ Memos | ||||
| 
 | ||||
| 🏗 In heavily development. | ||||
							
								
								
									
										82
									
								
								api/auth.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								api/auth.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,82 @@ | |||
| package api | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"memos/common/error" | ||||
| 	"memos/store" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gorilla/mux" | ||||
| ) | ||||
| 
 | ||||
| type UserSignUp struct { | ||||
| 	Username string `json:"username"` | ||||
| 	Password string `json:"password"` | ||||
| } | ||||
| 
 | ||||
| func handleUserSignUp(w http.ResponseWriter, r *http.Request) { | ||||
| 	var userSignup UserSignUp | ||||
| 	err := json.NewDecoder(r.Body).Decode(&userSignup) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "REQUEST_BODY_ERROR") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user, err := store.CreateNewUser(userSignup.Username, userSignup.Password, "", "") | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	json.NewEncoder(w).Encode(user) | ||||
| } | ||||
| 
 | ||||
| type UserSignin struct { | ||||
| 	Username string `json:"username"` | ||||
| 	Password string `json:"password"` | ||||
| } | ||||
| 
 | ||||
| func handleUserSignIn(w http.ResponseWriter, r *http.Request) { | ||||
| 	var userSignin UserSignin | ||||
| 	err := json.NewDecoder(r.Body).Decode(&userSignin) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user, err := store.GetUserByUsernameAndPassword(userSignin.Username, userSignin.Password) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	userIdCookie := &http.Cookie{ | ||||
| 		Name:   "user_id", | ||||
| 		Value:  user.Id, | ||||
| 		MaxAge: 3600 * 24 * 30, | ||||
| 	} | ||||
| 	http.SetCookie(w, userIdCookie) | ||||
| 
 | ||||
| 	json.NewEncoder(w).Encode(user) | ||||
| } | ||||
| 
 | ||||
| func handleUserSignOut(w http.ResponseWriter, r *http.Request) { | ||||
| 	userIdCookie := &http.Cookie{ | ||||
| 		Name:   "user_id", | ||||
| 		Value:  "", | ||||
| 		MaxAge: 0, | ||||
| 	} | ||||
| 	http.SetCookie(w, userIdCookie) | ||||
| } | ||||
| 
 | ||||
| func RegisterAuthRoutes(r *mux.Router) { | ||||
| 	authRouter := r.PathPrefix("/api/auth").Subrouter() | ||||
| 
 | ||||
| 	authRouter.HandleFunc("/signup", handleUserSignUp).Methods("POST") | ||||
| 	authRouter.HandleFunc("/signin", handleUserSignIn).Methods("POST") | ||||
| 	authRouter.HandleFunc("/signout", handleUserSignOut).Methods("POST") | ||||
| } | ||||
							
								
								
									
										82
									
								
								api/memo.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								api/memo.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,82 @@ | |||
| package api | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"memos/common/error" | ||||
| 	"memos/store" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gorilla/mux" | ||||
| ) | ||||
| 
 | ||||
| func handleGetMyMemos(w http.ResponseWriter, r *http.Request) { | ||||
| 	userId, _ := GetUserIdInCookie(r) | ||||
| 
 | ||||
| 	memos, err := store.GetMemosByUserId(userId) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "DATABASE_ERROR") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	json.NewEncoder(w).Encode(memos) | ||||
| } | ||||
| 
 | ||||
| type CreateMemo struct { | ||||
| 	Content string `json:"content"` | ||||
| } | ||||
| 
 | ||||
| func handleCreateMemo(w http.ResponseWriter, r *http.Request) { | ||||
| 	userId, _ := GetUserIdInCookie(r) | ||||
| 
 | ||||
| 	var createMemo CreateMemo | ||||
| 	err := json.NewDecoder(r.Body).Decode(&createMemo) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	memo, err := store.CreateNewMemo(createMemo.Content, userId) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	json.NewEncoder(w).Encode(memo) | ||||
| } | ||||
| 
 | ||||
| func handleUpdateMemo(w http.ResponseWriter, r *http.Request) { | ||||
| 	vars := mux.Vars(r) | ||||
| 	memoId := vars["id"] | ||||
| 
 | ||||
| 	userId, _ := GetUserIdInCookie(r) | ||||
| 
 | ||||
| 	var createMemo CreateMemo | ||||
| 	err := json.NewDecoder(r.Body).Decode(&createMemo) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	memo, err := store.UpdateMemo(memoId, createMemo.Content, userId) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	json.NewEncoder(w).Encode(memo) | ||||
| } | ||||
| 
 | ||||
| func RegisterMemoRoutes(r *mux.Router) { | ||||
| 	memoRouter := r.PathPrefix("/api/memo").Subrouter() | ||||
| 
 | ||||
| 	memoRouter.Use(AuthCheckerMiddleWare) | ||||
| 
 | ||||
| 	memoRouter.HandleFunc("/all", handleGetMyMemos).Methods("GET") | ||||
| 	memoRouter.HandleFunc("/", handleCreateMemo).Methods("PUT") | ||||
| 	memoRouter.HandleFunc("/{id}", handleUpdateMemo).Methods("PATCH") | ||||
| } | ||||
							
								
								
									
										19
									
								
								api/middlewares.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								api/middlewares.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| package api | ||||
| 
 | ||||
| import ( | ||||
| 	"memos/common/error" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| func AuthCheckerMiddleWare(next http.Handler) http.Handler { | ||||
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		userId, err := GetUserIdInCookie(r) | ||||
| 
 | ||||
| 		if err != nil || userId == "" { | ||||
| 			error.ErrorHandler(w, "NOT_AUTH") | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		next.ServeHTTP(w, r) | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										60
									
								
								api/user.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								api/user.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| package api | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"memos/common/error" | ||||
| 	"memos/store" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gorilla/mux" | ||||
| ) | ||||
| 
 | ||||
| func handleGetMyUserInfo(w http.ResponseWriter, r *http.Request) { | ||||
| 	userId, _ := GetUserIdInCookie(r) | ||||
| 
 | ||||
| 	user, err := store.GetUserById(userId) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "DATABASE_ERROR") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	json.NewEncoder(w).Encode(user) | ||||
| } | ||||
| 
 | ||||
| type UpdateUser struct { | ||||
| 	Username   string `json:"username"` | ||||
| 	Password   string `json:"password"` | ||||
| 	GithubName string `json:"githubName"` | ||||
| 	WxOpenId   string `json:"wxOpenId"` | ||||
| } | ||||
| 
 | ||||
| func handleUpdateMyUserInfo(w http.ResponseWriter, r *http.Request) { | ||||
| 	userId, _ := GetUserIdInCookie(r) | ||||
| 
 | ||||
| 	user, err := store.GetUserById(userId) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "DATABASE_ERROR") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	var updateUser UpdateUser | ||||
| 	err = json.NewDecoder(r.Body).Decode(&updateUser) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		error.ErrorHandler(w, "REQUEST_BODY_ERROR") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	json.NewEncoder(w).Encode(user) | ||||
| } | ||||
| 
 | ||||
| func RegisterUserRoutes(r *mux.Router) { | ||||
| 	userRouter := r.PathPrefix("/api/user").Subrouter() | ||||
| 
 | ||||
| 	userRouter.Use(AuthCheckerMiddleWare) | ||||
| 
 | ||||
| 	userRouter.HandleFunc("/me", handleGetMyUserInfo).Methods("GET") | ||||
| 	userRouter.HandleFunc("/me", handleUpdateMyUserInfo).Methods("PATCH") | ||||
| } | ||||
							
								
								
									
										11
									
								
								api/utils.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								api/utils.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| package api | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| func GetUserIdInCookie(r *http.Request) (string, error) { | ||||
| 	userIdCookie, err := r.Cookie("user_id") | ||||
| 
 | ||||
| 	return userIdCookie.Value, err | ||||
| } | ||||
							
								
								
									
										9
									
								
								common/error/codes.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								common/error/codes.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| package error | ||||
| 
 | ||||
| var Codes = map[string]int{ | ||||
| 	"NOT_AUTH": 20001, | ||||
| 
 | ||||
| 	"REQUEST_BODY_ERROR": 40001, | ||||
| 
 | ||||
| 	"DATABASE_ERROR": 50001, | ||||
| } | ||||
							
								
								
									
										48
									
								
								common/error/error.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								common/error/error.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| package error | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| type ServerError struct { | ||||
| 	Code    int | ||||
| 	Message string | ||||
| } | ||||
| 
 | ||||
| type ErrorResponse struct { | ||||
| 	StatusCode    int         `json:"statusCode"` | ||||
| 	StatusMessage string      `json:"statusMessage"` | ||||
| 	Succeed       bool        `json:"succeed"` | ||||
| 	Data          interface{} `json:"data"` | ||||
| } | ||||
| 
 | ||||
| func getServerError(err string) ServerError { | ||||
| 	code, exists := Codes[err] | ||||
| 
 | ||||
| 	if !exists { | ||||
| 		err = "Bad Request" | ||||
| 		code = 40000 | ||||
| 	} | ||||
| 
 | ||||
| 	return ServerError{ | ||||
| 		Code:    code, | ||||
| 		Message: err, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ErrorHandler(w http.ResponseWriter, err string) { | ||||
| 	serverError := getServerError(err) | ||||
| 
 | ||||
| 	res := ErrorResponse{ | ||||
| 		StatusCode:    serverError.Code, | ||||
| 		StatusMessage: serverError.Message, | ||||
| 		Succeed:       false, | ||||
| 		Data:          nil, | ||||
| 	} | ||||
| 
 | ||||
| 	statusCode := int(serverError.Code / 100) | ||||
| 
 | ||||
| 	w.WriteHeader(statusCode) | ||||
| 	json.NewEncoder(w).Encode(res) | ||||
| } | ||||
							
								
								
									
										15
									
								
								common/utils.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								common/utils.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| package common | ||||
| 
 | ||||
| import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/google/uuid" | ||||
| ) | ||||
| 
 | ||||
| func GenUUID() string { | ||||
| 	return uuid.New().String() | ||||
| } | ||||
| 
 | ||||
| func GetNowDateTimeStr() string { | ||||
| 	return time.Now().Format("RFC3339") | ||||
| } | ||||
							
								
								
									
										9
									
								
								go.mod
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| module memos | ||||
| 
 | ||||
| go 1.17 | ||||
| 
 | ||||
| require github.com/gorilla/mux v1.8.0 | ||||
| 
 | ||||
| require github.com/mattn/go-sqlite3 v1.14.9 | ||||
| 
 | ||||
| require github.com/google/uuid v1.3.0 | ||||
							
								
								
									
										6
									
								
								go.sum
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								go.sum
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= | ||||
| github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= | ||||
| github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= | ||||
| github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA= | ||||
| github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= | ||||
							
								
								
									
										20
									
								
								main.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								main.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"memos/api" | ||||
| 	"memos/store" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gorilla/mux" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
| 	store.InitDBConn() | ||||
| 
 | ||||
| 	r := mux.NewRouter().StrictSlash(true) | ||||
| 
 | ||||
| 	api.RegisterUserRoutes(r) | ||||
| 	api.RegisterAuthRoutes(r) | ||||
| 
 | ||||
| 	http.ListenAndServe("localhost:8080", r) | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								resources/memos.db
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/memos.db
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										30
									
								
								resources/sqlite.sql
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								resources/sqlite.sql
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| CREATE TABLE `users` ( | ||||
| 	`id` TEXT NOT NULL PRIMARY KEY, | ||||
| 	`username` TEXT NOT NULL, | ||||
| 	`password` TEXT NOT NULL, | ||||
| 	`github_name` TEXT NULL DEFAULT '', | ||||
|   `wx_open_id` TEXT NULL DEFAULT '', | ||||
| 	`created_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
|   `updated_at` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP | ||||
| ); | ||||
| 
 | ||||
| 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, | ||||
|   FOREIGN KEY(`user_id`) REFERENCES `users`(`id`) | ||||
| ); | ||||
| 
 | ||||
| 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 NULL, | ||||
|   FOREIGN KEY(`user_id`) REFERENCES `users`(`id`) | ||||
| ); | ||||
							
								
								
									
										13
									
								
								scripts/.air.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								scripts/.air.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| root = "." | ||||
| tmp_dir = "tmp" | ||||
| 
 | ||||
| [build] | ||||
|   bin = "./tmp/main" | ||||
|   cmd = "go build -o ./tmp/main ." | ||||
|   delay = 1000 | ||||
|   exclude_dir = ["assets", "tmp", "vendor"] | ||||
|   exclude_file = [] | ||||
|   exclude_regex = [] | ||||
|   exclude_unchanged = false | ||||
|   follow_symlink = false | ||||
|   full_bin = "" | ||||
							
								
								
									
										72
									
								
								store/memo.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								store/memo.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | |||
| package store | ||||
| 
 | ||||
| import "memos/common" | ||||
| 
 | ||||
| type Memo struct { | ||||
| 	Id        string `json:"id"` | ||||
| 	Content   string `json:"content"` | ||||
| 	UserId    string `json:"userId"` | ||||
| 	DeletedAt string `json:"deletedAt"` | ||||
| 	CreatedAt string `json:"createdAt"` | ||||
| 	UpdatedAt string `json:"updatedAt"` | ||||
| } | ||||
| 
 | ||||
| func CreateNewMemo(content string, userId string) (Memo, error) { | ||||
| 	nowDateTimeStr := common.GetNowDateTimeStr() | ||||
| 	newMemo := Memo{ | ||||
| 		Id:        common.GenUUID(), | ||||
| 		Content:   content, | ||||
| 		UserId:    userId, | ||||
| 		DeletedAt: "", | ||||
| 		CreatedAt: nowDateTimeStr, | ||||
| 		UpdatedAt: nowDateTimeStr, | ||||
| 	} | ||||
| 
 | ||||
| 	query := `INSERT INTO memos (id, content, user_id, deleted_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)` | ||||
| 	_, err := DB.Exec(query, newMemo.Id, newMemo.Content, newMemo.UserId, newMemo.DeletedAt, newMemo.CreatedAt, newMemo.UpdatedAt) | ||||
| 
 | ||||
| 	return newMemo, err | ||||
| } | ||||
| 
 | ||||
| func UpdateMemo(id string, content string, deletedAt string) (Memo, error) { | ||||
| 	nowDateTimeStr := common.GetNowDateTimeStr() | ||||
| 	memo, _ := GetMemoById(id) | ||||
| 
 | ||||
| 	if content != "" { | ||||
| 		memo.Content = content | ||||
| 	} | ||||
| 	if deletedAt != "" { | ||||
| 		memo.DeletedAt = deletedAt | ||||
| 	} | ||||
| 
 | ||||
| 	memo.UpdatedAt = nowDateTimeStr | ||||
| 
 | ||||
| 	query := `UPDATE memos SET (content, deleted_at, updated_at) VALUES (?, ?, ?)` | ||||
| 	_, err := DB.Exec(query, memo.Content, memo.DeletedAt, memo.UpdatedAt) | ||||
| 
 | ||||
| 	return memo, err | ||||
| } | ||||
| 
 | ||||
| func GetMemoById(id string) (Memo, error) { | ||||
| 	query := `SELECT id, content, user_id, deleted_at, created_at, updated_at FROM memos WHERE id=?` | ||||
| 	var memo Memo | ||||
| 	err := DB.QueryRow(query, id).Scan(&memo.Id, &memo.Content, &memo.UserId, &memo.DeletedAt, &memo.CreatedAt, &memo.UpdatedAt) | ||||
| 	return memo, err | ||||
| } | ||||
| 
 | ||||
| func GetMemosByUserId(userId string) ([]Memo, error) { | ||||
| 	query := `SELECT id, content, user_id, deleted_at, created_at, updated_at FROM memos WHERE user_id=?` | ||||
| 
 | ||||
| 	rows, err := DB.Query(query, userId) | ||||
| 
 | ||||
| 	var memos []Memo | ||||
| 
 | ||||
| 	for rows.Next() { | ||||
| 		var memo Memo | ||||
| 		err = rows.Scan(&memo.Id, &memo.Content, &memo.UserId, &memo.DeletedAt, &memo.CreatedAt, &memo.UpdatedAt) | ||||
| 
 | ||||
| 		memos = append(memos, memo) | ||||
| 	} | ||||
| 
 | ||||
| 	return memos, err | ||||
| } | ||||
							
								
								
									
										31
									
								
								store/sqlite.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								store/sqlite.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| package store | ||||
| 
 | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	_ "github.com/mattn/go-sqlite3" | ||||
| ) | ||||
| 
 | ||||
| var DB *sql.DB | ||||
| 
 | ||||
| func InitDBConn() { | ||||
| 	db, err := sql.Open("sqlite3", "./resources/memos.db") | ||||
| 	if err != nil { | ||||
| 		fmt.Println("connect failed") | ||||
| 	} else { | ||||
| 		DB = db | ||||
| 		fmt.Println("connect to sqlite succeed") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func FormatDBError(err error) error { | ||||
| 	if err == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	switch err.Error() { | ||||
| 	default: | ||||
| 		return err | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										139
									
								
								store/user.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								store/user.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,139 @@ | |||
| package store | ||||
| 
 | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"fmt" | ||||
| 	"memos/common" | ||||
| ) | ||||
| 
 | ||||
| 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) { | ||||
| 	nowDateTimeStr := common.GetNowDateTimeStr() | ||||
| 	newUser := User{ | ||||
| 		Id:         common.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) | ||||
| 
 | ||||
| 	return newUser, err | ||||
| } | ||||
| 
 | ||||
| func UpdateUser(id string, username string, password string, githubName string, wxOpenId string) (User, error) { | ||||
| 	nowDateTimeStr := common.GetNowDateTimeStr() | ||||
| 	user, _ := GetUserById(id) | ||||
| 
 | ||||
| 	if username != "" { | ||||
| 		user.Username = username | ||||
| 	} | ||||
| 	if password != "" { | ||||
| 		user.Password = password | ||||
| 	} | ||||
| 	if githubName != "" { | ||||
| 		user.GithubName = githubName | ||||
| 	} | ||||
| 	if wxOpenId != "" { | ||||
| 		user.WxOpenId = wxOpenId | ||||
| 	} | ||||
| 
 | ||||
| 	user.UpdatedAt = nowDateTimeStr | ||||
| 
 | ||||
| 	query := `UPDATE users SET (username, password, wx_open_id, github_name, updated_at) VALUES (?, ?, ?, ?, ?)` | ||||
| 	_, err := DB.Exec(query, user.Username, user.Password, user.WxOpenId, user.GithubName, user.UpdatedAt) | ||||
| 
 | ||||
| 	return user, err | ||||
| } | ||||
| 
 | ||||
| func GetUserById(id string) (User, error) { | ||||
| 	query := `SELECT id, username, password, wx_open_id, github_name, created_at, updated_at FROM users WHERE id=?` | ||||
| 	var user User | ||||
| 	err := DB.QueryRow(query, id).Scan(&user.Id, &user.Username, &user.Password, &user.WxOpenId, &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=?` | ||||
| 	var user User | ||||
| 	err := DB.QueryRow(query, username, password).Scan(&user.Id, &user.Username, &user.Password, &user.WxOpenId, &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=?` | ||||
| 	var 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=?` | ||||
| 	var user User | ||||
| 	err := DB.QueryRow(query, wxOpenId).Scan(&user.Id, &user.Username, &user.Password, &user.WxOpenId, &user.GithubName, &user.CreatedAt, &user.UpdatedAt) | ||||
| 	return user, err | ||||
| } | ||||
| 
 | ||||
| func CheckUsernameUsable(username string) (bool, error) { | ||||
| 	query := `SELECT * FROM users WHERE username=?` | ||||
| 	query = fmt.Sprintf("SELECT COUNT(*) FROM (%s)", query) | ||||
| 
 | ||||
| 	var count uint | ||||
| 	err := DB.QueryRow(query, username).Scan(&count) | ||||
| 	if err != nil && err != sql.ErrNoRows { | ||||
| 		return false, FormatDBError(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if count > 0 { | ||||
| 		return false, nil | ||||
| 	} else { | ||||
| 		return true, nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func CheckGithubNameUsable(githubName string) (bool, error) { | ||||
| 	query := `SELECT * FROM users WHERE github_name=?` | ||||
| 	query = fmt.Sprintf("SELECT COUNT(*) FROM (%s)", query) | ||||
| 
 | ||||
| 	var count uint | ||||
| 	err := DB.QueryRow(query, githubName).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) | ||||
| 
 | ||||
| 	var count uint | ||||
| 	err := DB.QueryRow(query, id, password).Scan(&count) | ||||
| 	if err != nil && err != sql.ErrNoRows { | ||||
| 		return false, FormatDBError(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if count > 0 { | ||||
| 		return true, nil | ||||
| 	} else { | ||||
| 		return false, nil | ||||
| 	} | ||||
| } | ||||
		Loading…
	
	Add table
		
		Reference in a new issue