feat: system api with profiles

This commit is contained in:
email 2022-03-29 20:53:43 +08:00
parent 4f88221bce
commit b3a431570c
9 changed files with 111 additions and 43 deletions

View File

@ -0,0 +1,38 @@
name: build-and-push-docker-image
on:
push:
branches:
# Run on pushing branches like `release/1.0.0`
- "release/v*.*.*"
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Extract build args
# Extract version from branch name
# Example: branch name `release/v1.0.0` sets up env.VERSION=1.0.0
run: |
echo "VERSION=${GITHUB_REF_NAME#release/v}" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_NEOSMEMO_USERNAME }}
password: ${{ secrets.DOCKER_NEOSMEMO_TOKEN }}
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: Build and Push
id: docker_build
uses: docker/build-push-action@v2
with:
context: ./
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKER_NEOSMEMO_USERNAME }}/memos:${{ env.VERSION }}

View File

@ -4,40 +4,28 @@ import (
"fmt"
"os"
"memos/common"
"memos/server"
"memos/store"
)
type Main struct {
profile *Profile
profile *common.Profile
server *server.Server
db *store.DB
}
func Execute() {
m := Main{}
profile := GetProfile()
m.profile = &profile
err := m.Run()
if err != nil {
fmt.Printf("%+v\n", err)
os.Exit(1)
}
}
func (m *Main) Run() error {
db := store.NewDB(m.profile.dsn, m.profile.mode)
db := store.NewDB(m.profile)
if err := db.Open(); err != nil {
return fmt.Errorf("cannot open db: %w", err)
}
m.db = db
s := server.NewServer(m.profile.port, m.profile.mode)
s := server.NewServer(m.profile)
s.ShortcutService = store.NewShortcutService(db)
s.MemoService = store.NewMemoService(db)
@ -53,3 +41,16 @@ func (m *Main) Run() error {
return nil
}
func Execute() {
profile := common.GetProfile()
m := Main{
profile: &profile,
}
err := m.Run()
if err != nil {
fmt.Printf("%+v\n", err)
os.Exit(1)
}
}

View File

@ -1,4 +1,4 @@
package cmd
package common
import (
"fmt"
@ -9,12 +9,12 @@ import (
)
type Profile struct {
// mode can be "release" or "dev"
mode string
// port is the binding port for server.
port int
// dsn points to where Memos stores its own data
dsn string
// Mode can be "release" or "dev"
Mode string `json:"mode"`
// Port is the binding port for server.
Port int `json:"port"`
// DSN points to where Memos stores its own data
DSN string `json:"-"`
}
func checkDSN(dataDir string) (string, error) {
@ -61,8 +61,8 @@ func GetProfile() Profile {
dsn := fmt.Sprintf("file:%s/memos_%s.db", dataDir, mode)
return Profile{
mode: mode,
port: port,
dsn: dsn,
Mode: mode,
Port: port,
DSN: dsn,
}
}

View File

@ -3,6 +3,7 @@ package server
import (
"fmt"
"memos/api"
"memos/common"
"time"
"github.com/gorilla/securecookie"
@ -15,15 +16,15 @@ import (
type Server struct {
e *echo.Echo
Profile *common.Profile
UserService api.UserService
MemoService api.MemoService
ShortcutService api.ShortcutService
ResourceService api.ResourceService
port int
}
func NewServer(port int, mode string) *Server {
func NewServer(profile *common.Profile) *Server {
e := echo.New()
e.Debug = true
e.HideBanner = true
@ -46,17 +47,19 @@ func NewServer(port int, mode string) *Server {
HTML5: true,
}))
// In dev mode, set the const secret key to make login session persistence.
secret := []byte("justmemos")
if mode != "dev" {
if profile.Mode == "release" {
secret = securecookie.GenerateRandomKey(16)
}
e.Use(session.Middleware(sessions.NewCookieStore(secret)))
s := &Server{
e: e,
port: port,
e: e,
Profile: profile,
}
// Webhooks api skips auth checker.
webhookGroup := e.Group("/h")
s.registerWebhookRoutes(webhookGroup)
@ -64,6 +67,7 @@ func NewServer(port int, mode string) *Server {
apiGroup.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return BasicAuthMiddleware(s.UserService, next)
})
s.registerSystemRoutes(apiGroup)
s.registerAuthRoutes(apiGroup)
s.registerUserRoutes(apiGroup)
s.registerMemoRoutes(apiGroup)
@ -74,5 +78,5 @@ func NewServer(port int, mode string) *Server {
}
func (server *Server) Run() error {
return server.e.Start(fmt.Sprintf(":%d", server.port))
return server.e.Start(fmt.Sprintf(":%d", server.Profile.Port))
}

19
server/system.go Normal file
View File

@ -0,0 +1,19 @@
package server
import (
"encoding/json"
"net/http"
"github.com/labstack/echo/v4"
)
func (s *Server) registerSystemRoutes(g *echo.Group) {
g.GET("/ping", func(c echo.Context) error {
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(s.Profile)); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose system profile").SetInternal(err)
}
return nil
})
}

View File

@ -36,7 +36,7 @@ CREATE TABLE memo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
-- allowed row status are 'NORMAL', 'HIDDEN'.
-- allowed row status are 'NORMAL', 'PINNED', 'HIDDEN'.
row_status TEXT NOT NULL DEFAULT 'NORMAL',
content TEXT NOT NULL DEFAULT '',
creator_id INTEGER NOT NULL,
@ -69,7 +69,7 @@ CREATE TABLE shortcut (
title TEXT NOT NULL DEFAULT '',
payload TEXT NOT NULL DEFAULT '',
creator_id INTEGER NOT NULL,
-- allowed row status are 'NORMAL', 'ARCHIVED'.
-- allowed row status are 'NORMAL', 'PINNED'.
row_status TEXT NOT NULL DEFAULT 'NORMAL',
FOREIGN KEY(creator_id) REFERENCES users(id)
);

View File

@ -1,4 +1,10 @@
INSERT INTO memo
(`content`, `creator_id`)
INSERT INTO
memo (
`content`,
`creator_id`
)
VALUES
('👋 Welcome to memos', 101);
(
'#memos 👋 Welcome to memos',
101
);

View File

@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io/fs"
"memos/common"
"sort"
_ "github.com/mattn/go-sqlite3"
@ -19,18 +20,17 @@ var seedFS embed.FS
type DB struct {
Db *sql.DB
// datasource name
DSN string
// mode: release or dev
// mode should be release or dev
mode string
}
// NewDB returns a new instance of DB associated with the given datasource name.
func NewDB(dsn string, mode string) *DB {
func NewDB(profile *common.Profile) *DB {
db := &DB{
DSN: dsn,
mode: mode,
DSN: profile.DSN,
mode: profile.Mode,
}
return db
}