Skip to content
Snippets Groups Projects
Commit 24b7a283 authored by Ophestra's avatar Ophestra
Browse files

private mode

parent 0dace376
Branches
Tags v1.1.0
No related merge requests found
......@@ -28,11 +28,23 @@ func registerAPI() {
context.JSON(http.StatusOK, instance.SingleUser)
})
router.GET(api.Private, func(context *gin.Context) {
context.JSON(http.StatusOK, instance.Private)
})
router.GET(api.User, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
context.JSON(http.StatusOK, instance.Users())
})
router.PUT(api.User, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
user, ok := getUser(context)
if !instance.Register {
if !ok {
......@@ -73,6 +85,10 @@ func registerAPI() {
})
router.GET(api.UserField, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
info := instance.User(context.Param("flake"))
context.JSON(http.StatusOK, api.UserPayload{
Username: info.Username,
......@@ -176,6 +192,10 @@ func registerAPI() {
})
router.GET(api.UsernameField, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
info := instance.UserUsername(context.Param("name"))
payload := api.UserPayload{
Username: info.Username,
......@@ -212,6 +232,7 @@ func registerAPI() {
return
}
// Only allow lookup if user is current user or privileged
flake := context.Param("flake")
if !info.Privileged && (info.Snowflake != flake) {
context.JSON(http.StatusForbidden, api.Denied)
......@@ -229,6 +250,7 @@ func registerAPI() {
return
}
// Only allow set if user is current user or privileged
flake := context.Param("flake")
if !info.Privileged && (info.Snowflake != flake) {
context.JSON(http.StatusForbidden, api.Denied)
......@@ -238,10 +260,18 @@ func registerAPI() {
})
router.GET(api.UserImage, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
context.JSON(http.StatusOK, instance.UserImages(context.Param("flake")))
})
router.GET(api.SearchField, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
tagsPayload := context.Param("tags")
tags := strings.Split(tagsPayload, "!")
context.JSON(http.StatusOK, instance.ImageSearch(tags))
......@@ -294,10 +324,18 @@ func registerAPI() {
})
router.GET(api.ImagePage, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
context.String(http.StatusOK, strconv.Itoa(instance.PageTotal(store.ImageRootPageVariant)))
})
router.GET(api.ImagePageField, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
param := context.Param("entry")
entry, err := strconv.Atoi(param)
if err != nil {
......@@ -308,6 +346,10 @@ func registerAPI() {
})
router.GET(api.ImagePageImage, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
param := context.Param("entry")
entry, err := strconv.Atoi(param)
if err != nil {
......@@ -318,6 +360,10 @@ func registerAPI() {
})
router.GET(api.ImageField, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
context.JSON(http.StatusOK, instance.ImageSnowflake(context.Param("flake")))
})
......@@ -364,6 +410,10 @@ func registerAPI() {
})
router.GET(api.ImageFile, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
flake := context.Param("flake")
image, data := instance.ImageData(instance.ImageSnowflakeHash(flake), false)
if image.Snowflake != flake {
......@@ -374,6 +424,10 @@ func registerAPI() {
})
router.GET(api.ImagePreview, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
flake := context.Param("flake")
image, data := instance.ImageData(instance.ImageSnowflakeHash(flake), true)
if image.Snowflake != flake {
......@@ -384,6 +438,10 @@ func registerAPI() {
})
router.GET(api.ImageTag, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
context.JSON(http.StatusOK, instance.ImageTags(context.Param("flake")))
})
......@@ -422,6 +480,10 @@ func registerAPI() {
})
router.GET(api.Tag, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
context.JSON(http.StatusOK, instance.Tags())
})
......@@ -474,6 +536,10 @@ func registerAPI() {
})
router.GET(api.TagPage, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
tag := context.Param("tag")
if !instance.MatchName(tag) {
context.JSON(http.StatusBadRequest, api.Denied)
......@@ -483,6 +549,10 @@ func registerAPI() {
})
router.GET(api.TagPageField, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
tag := context.Param("tag")
if !instance.MatchName(tag) {
context.JSON(http.StatusBadRequest, api.Denied)
......@@ -499,6 +569,10 @@ func registerAPI() {
})
router.GET(api.TagPageImage, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
tag := context.Param("tag")
if !instance.MatchName(tag) {
context.JSON(http.StatusBadRequest, api.Denied)
......@@ -515,6 +589,10 @@ func registerAPI() {
})
router.GET(api.TagInfo, func(context *gin.Context) {
if !privateAccessible(context) {
return
}
context.JSON(http.StatusOK, instance.TagInfo(context.Param("tag")))
})
......@@ -541,6 +619,19 @@ func registerAPI() {
})
}
func privateAccessible(context *gin.Context) bool {
if !instance.Private {
return true
}
if _, ok := getUser(context); !ok {
context.JSON(http.StatusForbidden, api.Denied)
return false
}
return true
}
func getUser(context *gin.Context) (store.User, bool) {
if instance.SingleUser {
return instance.User(instance.InitialUser), true
......
......@@ -3,6 +3,7 @@ package api
const (
Base = "/api"
SingleUser = Base + "/single_user"
Private = Base + "/private"
Image = Base + "/image"
ImagePage = Image + "/page"
ImagePageField = ImagePage + "/:entry"
......
......@@ -11,6 +11,7 @@ import (
type Remote struct {
url string
single bool
private bool
secret string
client *http.Client
user *api.UserPayload
......@@ -33,11 +34,19 @@ func (r *Remote) SingleUser() bool {
return r.single
}
// Private returns whether the Remote is running in private mode.
func (r *Remote) Private() bool {
return r.private
}
// Handshake checks if the server is still online and updates Remote.
func (r *Remote) Handshake() error {
if err := r.fetch(http.MethodGet, api.SingleUser, &r.single, nil); err != nil {
return err
}
if err := r.fetch(http.MethodGet, api.Private, &r.private, nil); err != nil {
return err
}
return r.fetch(http.MethodGet, api.Base, r, nil)
}
......
......@@ -5,6 +5,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
"random.chars.jp/git/image-board/store"
"strconv"
)
var instance *store.Store
......@@ -23,6 +24,7 @@ func configSetup() {
"loglevel": "info",
"store": "./db",
"single-user": true,
"private": false,
})
viper.SetDefault("server", map[string]interface{}{
"host": "127.0.0.1",
......@@ -58,7 +60,8 @@ func configSetup() {
if viper.GetStringMap("server")["unix"] != serverConfig["unix"] ||
viper.GetStringMap("server")["host"] != serverConfig["host"] ||
viper.GetStringMap("server")["port"] != serverConfig["port"] ||
viper.GetStringMap("system")["single-user"] != systemConfig["single-user"] {
viper.GetStringMap("system")["single-user"] != systemConfig["single-user"] ||
viper.GetStringMap("system")["private"] != systemConfig["private"] {
log.Warn("Configuration change requires restart.")
cleanup(true)
return
......@@ -76,12 +79,11 @@ func configSetup() {
}
func openStore() {
path := viper.GetStringMap("system")["store"].(string)
single, ok := viper.GetStringMap("system")["single-user"].(bool)
if !ok {
single = false
}
instance = store.New(path, single)
path := systemConfig["store"].(string)
single := parseBool(systemConfig["single-user"])
private := parseBool(systemConfig["private"])
instance = store.New(path, single, private)
if instance == nil {
log.Fatalf("Error initializing store.")
}
......@@ -98,6 +100,26 @@ func openStore() {
}
}
if single {
log.Infof("Server running in single user mode, all operations are performed as the initial user.")
log.Info("Server running in single user mode, all operations are performed as the initial user.")
} else if private {
log.Info("Server running in private mode, all operations will require authentication.")
}
}
func parseBool(v interface{}) bool {
if s, ok := v.(bool); !ok {
var sS string
if sS, ok = v.(string); !ok {
return false
} else {
if b, err := strconv.ParseBool(sS); err != nil {
log.Warnf("Error parsing boolean value, %s", err)
return false
} else {
return b
}
}
} else {
return s
}
}
......@@ -33,6 +33,7 @@ type Info struct {
type Store struct {
Path string
SingleUser bool
Private bool
Revision int
Compat bool
Register bool
......@@ -58,7 +59,7 @@ func init() {
}
// New initialises a new store instance.
func New(path string, single bool) *Store {
func New(path string, single, private bool) *Store {
var store *Store
if stat, err := os.Stat(path); err != nil {
log.Infof("Initializing new store at %s.", path)
......@@ -66,6 +67,7 @@ func New(path string, single bool) *Store {
store = &Store{
Path: path,
SingleUser: single,
Private: private,
Revision: revision,
Compat: runtime.GOOS == "windows",
Register: false,
......@@ -101,6 +103,7 @@ func New(path string, single bool) *Store {
store = &Store{
Path: path,
SingleUser: single,
Private: private,
Revision: info.Revision,
Compat: info.Compat,
Register: info.Register,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment