Skip to content

Commit

Permalink
feat: new system info panel in webui settings (#926)
Browse files Browse the repository at this point in the history
* frontend

* fixed Database.DBx return value

* api endpoint

* updated swagger

* fix openbsd variable dereference

* tests

* only load information if user is owner

* memory improvement for other routes
  • Loading branch information
fmartingr authored Jun 8, 2024
1 parent 650f192 commit 72aecd2
Show file tree
Hide file tree
Showing 18 changed files with 371 additions and 27 deletions.
48 changes: 48 additions & 0 deletions docs/swagger/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,29 @@ const docTemplate = `{
}
}
},
"/api/v1/system/info": {
"get": {
"description": "Get general system information like Shiori version, database, and OS",
"produces": [
"application/json"
],
"tags": [
"system"
],
"summary": "Get general system information",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api_v1.infoResponse"
}
},
"403": {
"description": "Only owners can access this endpoint"
}
}
}
},
"/api/v1/tags": {
"get": {
"produces": [
Expand Down Expand Up @@ -228,6 +251,31 @@ const docTemplate = `{
}
},
"definitions": {
"api_v1.infoResponse": {
"type": "object",
"properties": {
"database": {
"type": "string"
},
"os": {
"type": "string"
},
"version": {
"type": "object",
"properties": {
"commit": {
"type": "string"
},
"date": {
"type": "string"
},
"tag": {
"type": "string"
}
}
}
}
},
"api_v1.loginRequestPayload": {
"type": "object",
"required": [
Expand Down
48 changes: 48 additions & 0 deletions docs/swagger/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,29 @@
}
}
},
"/api/v1/system/info": {
"get": {
"description": "Get general system information like Shiori version, database, and OS",
"produces": [
"application/json"
],
"tags": [
"system"
],
"summary": "Get general system information",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api_v1.infoResponse"
}
},
"403": {
"description": "Only owners can access this endpoint"
}
}
}
},
"/api/v1/tags": {
"get": {
"produces": [
Expand Down Expand Up @@ -217,6 +240,31 @@
}
},
"definitions": {
"api_v1.infoResponse": {
"type": "object",
"properties": {
"database": {
"type": "string"
},
"os": {
"type": "string"
},
"version": {
"type": "object",
"properties": {
"commit": {
"type": "string"
},
"date": {
"type": "string"
},
"tag": {
"type": "string"
}
}
}
}
},
"api_v1.loginRequestPayload": {
"type": "object",
"required": [
Expand Down
32 changes: 32 additions & 0 deletions docs/swagger/swagger.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
definitions:
api_v1.infoResponse:
properties:
database:
type: string
os:
type: string
version:
properties:
commit:
type: string
date:
type: string
tag:
type: string
type: object
type: object
api_v1.loginRequestPayload:
properties:
password:
Expand Down Expand Up @@ -239,6 +255,22 @@ paths:
summary: Get readable version of bookmark.
tags:
- Auth
/api/v1/system/info:
get:
description: Get general system information like Shiori version, database, and
OS
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/api_v1.infoResponse'
"403":
description: Only owners can access this endpoint
summary: Get general system information
tags:
- system
/api/v1/tags:
get:
produces:
Expand Down
4 changes: 2 additions & 2 deletions internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func Connect(ctx context.Context, dbURL string) (DB, error) {
// DB is interface for accessing and manipulating data in database.
type DB interface {
// DBx is the underlying sqlx.DB
DBx() sqlx.DB
DBx() *sqlx.DB

// Migrate runs migrations for this database
Migrate(ctx context.Context) error
Expand Down Expand Up @@ -117,7 +117,7 @@ type DB interface {
}

type dbbase struct {
sqlx.DB
*sqlx.DB
}

func (db *dbbase) withTx(ctx context.Context, fn func(tx *sqlx.Tx) error) error {
Expand Down
4 changes: 2 additions & 2 deletions internal/database/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ func OpenMySQLDatabase(ctx context.Context, connString string) (mysqlDB *MySQLDa
db.SetMaxOpenConns(100)
db.SetConnMaxLifetime(time.Second) // in case mysql client has longer timeout (driver issue #674)

mysqlDB = &MySQLDatabase{dbbase: dbbase{*db}}
mysqlDB = &MySQLDatabase{dbbase: dbbase{db}}
return mysqlDB, err
}

// DBX returns the underlying sqlx.DB object
func (db *MySQLDatabase) DBx() sqlx.DB {
func (db *MySQLDatabase) DBx() *sqlx.DB {
return db.DB
}

Expand Down
4 changes: 2 additions & 2 deletions internal/database/pg.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ func OpenPGDatabase(ctx context.Context, connString string) (pgDB *PGDatabase, e
db.SetMaxOpenConns(100)
db.SetConnMaxLifetime(time.Second)

pgDB = &PGDatabase{dbbase: dbbase{*db}}
pgDB = &PGDatabase{dbbase: dbbase{db}}
return pgDB, err
}

// DBX returns the underlying sqlx.DB object
func (db *PGDatabase) DBx() sqlx.DB {
func (db *PGDatabase) DBx() *sqlx.DB {
return db.DB
}

Expand Down
2 changes: 1 addition & 1 deletion internal/database/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ type tagContent struct {
}

// DBX returns the underlying sqlx.DB object
func (db *SQLiteDatabase) DBx() sqlx.DB {
func (db *SQLiteDatabase) DBx() *sqlx.DB {
return db.DB
}

Expand Down
2 changes: 1 addition & 1 deletion internal/database/sqlite_noncgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ func OpenSQLiteDatabase(ctx context.Context, databasePath string) (sqliteDB *SQL
return nil, errors.WithStack(err)
}

sqliteDB = &SQLiteDatabase{dbbase: dbbase{*db}}
sqliteDB = &SQLiteDatabase{dbbase: dbbase{db}}
return sqliteDB, nil
}
2 changes: 1 addition & 1 deletion internal/database/sqlite_openbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ func OpenSQLiteDatabase(ctx context.Context, databasePath string) (sqliteDB *SQL
return nil, errors.WithStack(err)
}

sqliteDB = &SQLiteDatabase{dbbase: dbbase{*db}}
sqliteDB = &SQLiteDatabase{dbbase: dbbase{db}}
return sqliteDB, nil
}
1 change: 1 addition & 0 deletions internal/http/routes/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func (r *APIRoutes) Setup(g *gin.RouterGroup) model.Routes {
r.handle(g, "/auth", NewAuthAPIRoutes(r.logger, r.deps, r.loginHandler))
r.handle(g, "/bookmarks", NewBookmarksAPIRoutes(r.logger, r.deps))
r.handle(g, "/tags", NewTagsPIRoutes(r.logger, r.deps))
r.handle(g, "/system", NewSystemAPIRoutes(r.logger, r.deps))

return r
}
Expand Down
12 changes: 4 additions & 8 deletions internal/http/routes/api/v1/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,11 @@ func (r *AuthAPIRoutes) loginHandler(c *gin.Context) {
return
}

responseMessage := loginResponseMessage{
response.Send(c, http.StatusOK, loginResponseMessage{
Token: token,
SessionID: sessionID,
Expiration: expiration.Unix(),
}

response.Send(c, http.StatusOK, responseMessage)
})
}

// refreshHandler godoc
Expand All @@ -132,11 +130,9 @@ func (r *AuthAPIRoutes) refreshHandler(c *gin.Context) {
return
}

responseMessage := loginResponseMessage{
response.Send(c, http.StatusAccepted, loginResponseMessage{
Token: token,
}

response.Send(c, http.StatusAccepted, responseMessage)
})
}

// meHandler godoc
Expand Down
11 changes: 5 additions & 6 deletions internal/http/routes/api/v1/bookmarks.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ type readableResponseMessage struct {
// @Tags Auth
// @securityDefinitions.apikey ApiKeyAuth
// @Produce json
// @Success 200 {object} readableResponseMessage
// @Success 200 {object} readableResponseMessage
// @Failure 403 {object} nil "Token not provided/invalid"
// @Router /api/v1/bookmarks/id/readable [get]
func (r *BookmarksAPIRoutes) bookmarkReadable(c *gin.Context) {
Expand All @@ -107,20 +107,19 @@ func (r *BookmarksAPIRoutes) bookmarkReadable(c *gin.Context) {
if err != nil {
return
}
responseMessage := readableResponseMessage{

response.Send(c, 200, readableResponseMessage{
Content: bookmark.Content,
Html: bookmark.HTML,
}

response.Send(c, 200, responseMessage)
})
}

// updateCache godoc
//
// @Summary Update Cache and Ebook on server.
// @Tags Auth
// @securityDefinitions.apikey ApiKeyAuth
// @Param payload body updateCachePayload true "Update Cache Payload"`
// @Param payload body updateCachePayload true "Update Cache Payload"`
// @Produce json
// @Success 200 {object} model.BookmarkDTO
// @Failure 403 {object} nil "Token not provided/invalid"
Expand Down
74 changes: 74 additions & 0 deletions internal/http/routes/api/v1/system.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package api_v1

import (
"net/http"
"runtime"

"github.com/gin-gonic/gin"
"github.com/go-shiori/shiori/internal/dependencies"
"github.com/go-shiori/shiori/internal/http/context"
"github.com/go-shiori/shiori/internal/http/middleware"
"github.com/go-shiori/shiori/internal/http/response"
"github.com/go-shiori/shiori/internal/model"
"github.com/sirupsen/logrus"
)

type SystemAPIRoutes struct {
logger *logrus.Logger
deps *dependencies.Dependencies
}

func (r *SystemAPIRoutes) Setup(g *gin.RouterGroup) model.Routes {
g.Use(middleware.AuthenticationRequired())
g.GET("/info", r.infoHandler)
return r
}

type infoResponse struct {
Version struct {
Tag string `json:"tag"`
Commit string `json:"commit"`
Date string `json:"date"`
} `json:"version"`
Database string `json:"database"`
OS string `json:"os"`
}

// System info API endpoint godoc
//
// @Summary Get general system information
// @Description Get general system information like Shiori version, database, and OS
// @Tags system
// @Produce json
// @securityDefinitions.apikey ApiKeyAuth
// @Success 200 {object} infoResponse
// @Failure 403 {object} nil "Only owners can access this endpoint"
// @Router /api/v1/system/info [get]
func (r *SystemAPIRoutes) infoHandler(c *gin.Context) {
ctx := context.NewContextFromGin(c)
if !ctx.GetAccount().Owner {
response.SendError(c, http.StatusForbidden, "Only owners can access this endpoint")
return
}

response.Send(c, 200, infoResponse{
Version: struct {
Tag string `json:"tag"`
Commit string `json:"commit"`
Date string `json:"date"`
}{
Tag: model.BuildVersion,
Commit: model.BuildCommit,
Date: model.BuildDate,
},
Database: r.deps.Database.DBx().DriverName(),
OS: runtime.GOOS + " (" + runtime.GOARCH + ")",
})
}

func NewSystemAPIRoutes(logger *logrus.Logger, deps *dependencies.Dependencies) *SystemAPIRoutes {
return &SystemAPIRoutes{
logger: logger,
deps: deps,
}
}
Loading

0 comments on commit 72aecd2

Please sign in to comment.