add new ledger api
This commit is contained in:
parent
529f60e549
commit
4de286d8f7
22
config.go
22
config.go
|
|
@ -1,22 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/beancount-gs/script"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Title string `json:"title"`
|
||||
DataPath string `json:"dataPath"`
|
||||
OperatingCurrency string `json:"operatingCurrency"`
|
||||
StartDate string `json:"startDate"`
|
||||
IsBak bool `json:"isBak"`
|
||||
}
|
||||
|
||||
func LoadConfig(globalConfig Config) Config {
|
||||
err := json.Unmarshal(script.ReadFile("./config/config.json"), &globalConfig)
|
||||
if err != nil {
|
||||
script.LogError("config file (/config/config.json) unmarshall failed")
|
||||
}
|
||||
return globalConfig
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"title": "我的账本",
|
||||
"dataPath": "/beancount",
|
||||
"dataPath": "D:\\beancount",
|
||||
"operatingCurrency": "CNY",
|
||||
"startDate": "1970-01-01",
|
||||
"isBak": true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
package script
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
var serverConfig Config
|
||||
var ledgerConfigMap ConfigMap
|
||||
var whiteList []string
|
||||
|
||||
type Config struct {
|
||||
Id string `json:"id"`
|
||||
Mail string `json:"mail"`
|
||||
Title string `json:"title"`
|
||||
DataPath string `json:"dataPath"`
|
||||
OperatingCurrency string `json:"operatingCurrency"`
|
||||
StartDate string `json:"startDate"`
|
||||
IsBak bool `json:"isBak"`
|
||||
}
|
||||
|
||||
type ConfigMap map[string]Config
|
||||
|
||||
func GetServerConfig() Config {
|
||||
return serverConfig
|
||||
}
|
||||
|
||||
func GetLedgerConfigMap() map[string]Config {
|
||||
return ledgerConfigMap
|
||||
}
|
||||
|
||||
func GetLedgerConfig(ledgerId string) Config {
|
||||
return ledgerConfigMap[ledgerId]
|
||||
}
|
||||
|
||||
func GetLedgerConfigByMail(mail string) *Config {
|
||||
for _, v := range ledgerConfigMap {
|
||||
if v.Mail == mail {
|
||||
return &v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsInWhiteList(ledgerId string) bool {
|
||||
// ledger white list is empty, return true
|
||||
if whiteList == nil || len(whiteList) == 0 {
|
||||
return true
|
||||
}
|
||||
for i := range whiteList {
|
||||
if whiteList[i] == ledgerId {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func LoadServerConfig() error {
|
||||
fileContent, err := ReadFile("./config/config.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(fileContent, &serverConfig)
|
||||
if err != nil {
|
||||
LogError("Failed unmarshall config file (/config/config.json)")
|
||||
return err
|
||||
}
|
||||
LogInfo("Success load config file (/config/config.json)")
|
||||
// load white list
|
||||
fileContent, err = ReadFile("./config/white_list.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(fileContent, &whiteList)
|
||||
if err != nil {
|
||||
LogError("Failed unmarshal whitelist file (/config/white_list.json)")
|
||||
return err
|
||||
}
|
||||
LogInfo("Success load whitelist file (/config/white_list.json)")
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadLedgerConfigMap() error {
|
||||
path := GetServerLedgerConfigFilePath()
|
||||
fileContent, err := ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(fileContent, &ledgerConfigMap)
|
||||
if err != nil {
|
||||
LogError("Failed unmarshal config file (" + path + ")")
|
||||
return err
|
||||
}
|
||||
LogInfo("Success load ledger_config file (" + path + ")")
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteLedgerConfigMap(newLedgerConfigMap ConfigMap) error {
|
||||
path := GetServerLedgerConfigFilePath()
|
||||
mapBytes, err := json.Marshal(ledgerConfigMap)
|
||||
if err != nil {
|
||||
LogError("Failed marshal ConfigMap")
|
||||
return err
|
||||
}
|
||||
err = WriteFile(path, string(mapBytes))
|
||||
ledgerConfigMap = newLedgerConfigMap
|
||||
LogInfo("Success write ledger_config file (" + path + ")")
|
||||
return err
|
||||
}
|
||||
|
|
@ -16,26 +16,43 @@ func FileIfExist(filePath string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func ReadFile(filePath string) []byte {
|
||||
func ReadFile(filePath string) ([]byte, error) {
|
||||
content, err := ioutil.ReadFile(filePath)
|
||||
if nil != err {
|
||||
LogError(filePath + " read failed")
|
||||
LogError("Failed to read file (" + filePath + ")")
|
||||
return content, err
|
||||
}
|
||||
return content
|
||||
LogInfo("Success read file (" + filePath + ")")
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func CreateFile(filePath string) {
|
||||
func WriteFile(filePath string, content string) error {
|
||||
err := ioutil.WriteFile(filePath, []byte(content), os.ModePerm)
|
||||
if err != nil {
|
||||
LogError("Failed to write file (" + filePath + ")")
|
||||
return err
|
||||
}
|
||||
LogInfo("Success write file (" + filePath + ")")
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateFile(filePath string) error {
|
||||
f, err := os.Create(filePath)
|
||||
if nil != err {
|
||||
LogError(filePath + " create failed")
|
||||
return
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
LogInfo("Success create file " + filePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func MkDir(dirPath string) {
|
||||
func MkDir(dirPath string) error {
|
||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
||||
if nil != err {
|
||||
LogError(dirPath + " mkdir failed")
|
||||
LogError("Failed mkdir " + dirPath)
|
||||
return err
|
||||
}
|
||||
LogInfo("Success mkdir " + dirPath)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import (
|
|||
)
|
||||
|
||||
func LogInfo(message string) {
|
||||
fmt.Printf("[Info] %s System: %s\n", time.Now().Format("2006-01-02 15:04:05"), message)
|
||||
fmt.Printf("[Info] [%s] System: %s\n", time.Now().Format("2006-01-02 15:04:05"), message)
|
||||
}
|
||||
|
||||
func LogError(message string) {
|
||||
fmt.Printf("[Error] %s System: %s\n", time.Now().Format("2006-01-02 15:04:05"), message)
|
||||
fmt.Printf("[Error] [%s] System: %s\n", time.Now().Format("2006-01-02 15:04:05"), message)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
package script
|
||||
|
||||
import "os"
|
||||
|
||||
func GetServerLedgerConfigFilePath() string {
|
||||
return GetServerConfig().DataPath + "/ledger_config.json"
|
||||
}
|
||||
|
||||
func GetExampleLedgerConfigDirPath() string {
|
||||
currentPath, err := os.Getwd()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return currentPath + "/example"
|
||||
}
|
||||
51
server.go
51
server.go
|
|
@ -2,40 +2,55 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/beancount-gs/script"
|
||||
"github.com/beancount-gs/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var GlobalConfig Config
|
||||
|
||||
func InitLedgerFiles() {
|
||||
func InitServerFiles() error {
|
||||
dataPath := script.GetServerConfig().DataPath
|
||||
// 账本目录不存在,则创建
|
||||
if !script.FileIfExist(GlobalConfig.DataPath) {
|
||||
script.MkDir(GlobalConfig.DataPath)
|
||||
script.LogInfo("Success mkdir " + GlobalConfig.DataPath)
|
||||
if !script.FileIfExist(dataPath) {
|
||||
return script.MkDir(dataPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadLedgerCache() {
|
||||
|
||||
func LoadServerCache() error {
|
||||
return script.LoadLedgerConfigMap()
|
||||
}
|
||||
|
||||
func RegisterRoute(route *gin.Engine) {
|
||||
route.StaticFS("/", http.Dir("./public"))
|
||||
func RegisterRouter(router *gin.Engine) {
|
||||
router.StaticFS("/", http.Dir("./public"))
|
||||
router.POST("/api/ledger", service.OpenOrCreateLedger)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 默认端口号
|
||||
var port = ":3001"
|
||||
// 读取配置文件
|
||||
GlobalConfig = LoadConfig(GlobalConfig)
|
||||
err := script.LoadServerConfig()
|
||||
if err != nil {
|
||||
script.LogError("Failed to load server config, " + err.Error())
|
||||
return
|
||||
}
|
||||
// 初始化账本文件结构
|
||||
InitLedgerFiles()
|
||||
err = InitServerFiles()
|
||||
if err != nil {
|
||||
script.LogError("Failed to init server files, " + err.Error())
|
||||
return
|
||||
}
|
||||
// 加载缓存
|
||||
LoadLedgerCache()
|
||||
route := gin.Default()
|
||||
err = LoadServerCache()
|
||||
if err != nil {
|
||||
script.LogError("Failed to load server cache, " + err.Error())
|
||||
return
|
||||
}
|
||||
router := gin.Default()
|
||||
// 注册路由
|
||||
RegisterRoute(route)
|
||||
RegisterRouter(router)
|
||||
// 启动服务
|
||||
_ = http.ListenAndServe(port, nil)
|
||||
var port = ":3001"
|
||||
err = router.Run(port)
|
||||
if err != nil {
|
||||
script.LogError("Failed to start server, " + err.Error())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func OK(c *gin.Context, data string) {
|
||||
c.JSON(http.StatusOK, gin.H{"code": 200, "message": "ok", "data": data})
|
||||
}
|
||||
|
||||
func BadRequest(c *gin.Context, message string) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": message})
|
||||
}
|
||||
|
||||
func InternalError(c *gin.Context, message string) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": message})
|
||||
}
|
||||
|
||||
func LedgerIsNotExist(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"code": 1006, "message": "ledger is not exist"})
|
||||
}
|
||||
|
||||
func LedgerIsNotAllowAccess(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"code": 1006, "message": "ledger is not allow access"})
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/beancount-gs/script"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LoginForm struct {
|
||||
Mail string `form:"mail" binding:"required"`
|
||||
Secret string `form:"secret" binding:"required"`
|
||||
}
|
||||
|
||||
func OpenOrCreateLedger(c *gin.Context) {
|
||||
var loginForm LoginForm
|
||||
if err := c.ShouldBindJSON(&loginForm); err != nil {
|
||||
BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
// is mail exist white list
|
||||
if !script.IsInWhiteList(loginForm.Mail) {
|
||||
LedgerIsNotExist(c)
|
||||
return
|
||||
}
|
||||
|
||||
t := sha1.New()
|
||||
_, err := io.WriteString(t, loginForm.Mail+loginForm.Secret)
|
||||
if err != nil {
|
||||
LedgerIsNotAllowAccess(c)
|
||||
return
|
||||
}
|
||||
|
||||
ledgerId := hex.EncodeToString(t.Sum(nil))
|
||||
fmt.Println(ledgerId)
|
||||
userLedger := script.GetLedgerConfigByMail(loginForm.Mail)
|
||||
if userLedger != nil {
|
||||
if ledgerId != userLedger.Id {
|
||||
LedgerIsNotAllowAccess(c)
|
||||
return
|
||||
}
|
||||
}
|
||||
// create new ledger
|
||||
serverConfig := script.GetServerConfig()
|
||||
ledgerConfigMap := script.GetLedgerConfigMap()
|
||||
ledgerConfig := script.Config{
|
||||
Id: ledgerId,
|
||||
Mail: loginForm.Mail,
|
||||
Title: serverConfig.Title,
|
||||
DataPath: serverConfig.DataPath + "/" + ledgerId,
|
||||
OperatingCurrency: serverConfig.OperatingCurrency,
|
||||
StartDate: serverConfig.StartDate,
|
||||
IsBak: serverConfig.IsBak,
|
||||
}
|
||||
// init ledger files
|
||||
err = initLedgerFiles(script.GetExampleLedgerConfigDirPath(), ledgerConfig.DataPath, ledgerConfig.StartDate)
|
||||
if err != nil {
|
||||
InternalError(c, err.Error())
|
||||
return
|
||||
}
|
||||
// add ledger config to ledger_config.json
|
||||
ledgerConfigMap[ledgerId] = ledgerConfig
|
||||
err = script.WriteLedgerConfigMap(ledgerConfigMap)
|
||||
if err != nil {
|
||||
InternalError(c, err.Error())
|
||||
return
|
||||
}
|
||||
OK(c, ledgerId)
|
||||
}
|
||||
|
||||
func initLedgerFiles(sourceFilePath string, targetFilePath string, startDate string) error {
|
||||
return copyFile(sourceFilePath, targetFilePath, startDate)
|
||||
}
|
||||
|
||||
func copyFile(sourceFilePath string, targetFilePath string, startDate string) error {
|
||||
rd, err := ioutil.ReadDir(sourceFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, fi := range rd {
|
||||
newSourceFilePath := sourceFilePath + "/" + fi.Name()
|
||||
newTargetFilePath := targetFilePath + "/" + fi.Name()
|
||||
if fi.IsDir() {
|
||||
err = script.MkDir(newTargetFilePath)
|
||||
err = copyFile(newSourceFilePath, newTargetFilePath, startDate)
|
||||
} else {
|
||||
fileContent, err := script.ReadFile(newSourceFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = script.WriteFile(newTargetFilePath, strings.Replace(string(fileContent), "%startDate%", startDate, -1))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue