aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorr <r@freesoftwareextremist.com>2020-04-19 08:18:36 +0000
committerr <r@freesoftwareextremist.com>2020-04-19 08:18:36 +0000
commit55ed6a480ea049f789d778e4bae06ffa4d790ee1 (patch)
tree0c9e32e565c9a5bed27b018579f06573846ca511
parent5abbadfa622e58a4951cf0b2f96fbf8094641be8 (diff)
downloadbloat-55ed6a480ea049f789d778e4bae06ffa4d790ee1.tar.gz
bloat-55ed6a480ea049f789d778e4bae06ffa4d790ee1.zip
Add single instance mode
-rw-r--r--bloat.conf7
-rw-r--r--config/config.go23
-rw-r--r--main.go2
-rw-r--r--service/service.go44
-rw-r--r--service/transport.go49
5 files changed, 82 insertions, 43 deletions
diff --git a/bloat.conf b/bloat.conf
index e4ea384..ae2f007 100644
--- a/bloat.conf
+++ b/bloat.conf
@@ -25,6 +25,13 @@ client_scope=read write follow
# Example: "http://localhost:8080", "https://mydomain.com"
client_website=http://localhost:8080
+# In single instance mode, bloat will not ask for instance domain name and
+# user will be directly redirected to login form. User login from other
+# instances is not allowed in this mode.
+# Empty value disables single instance mode.
+# Example: "mydomain.com"
+single_instance=
+
# Path of database directory. It's used to store session information.
database_path=database
diff --git a/config/config.go b/config/config.go
index 2d4fb8d..d6140e5 100644
--- a/config/config.go
+++ b/config/config.go
@@ -11,16 +11,17 @@ import (
)
type config struct {
- ListenAddress string
- ClientName string
- ClientScope string
- ClientWebsite string
- StaticDirectory string
- TemplatesPath string
- DatabasePath string
- CustomCSS string
- PostFormats []model.PostFormat
- LogFile string
+ ListenAddress string
+ ClientName string
+ ClientScope string
+ ClientWebsite string
+ SingleInstance string
+ StaticDirectory string
+ TemplatesPath string
+ DatabasePath string
+ CustomCSS string
+ PostFormats []model.PostFormat
+ LogFile string
}
func (c *config) IsValid() bool {
@@ -68,6 +69,8 @@ func Parse(r io.Reader) (c *config, err error) {
c.ClientScope = val
case "client_website":
c.ClientWebsite = val
+ case "single_instance":
+ c.SingleInstance = val
case "static_directory":
c.StaticDirectory = val
case "templates_path":
diff --git a/main.go b/main.go
index aac7741..99adb7c 100644
--- a/main.go
+++ b/main.go
@@ -101,7 +101,7 @@ func main() {
s := service.NewService(config.ClientName, config.ClientScope,
config.ClientWebsite, customCSS, config.PostFormats, renderer,
- sessionRepo, appRepo)
+ sessionRepo, appRepo, config.SingleInstance)
s = service.NewAuthService(sessionRepo, appRepo, s)
s = service.NewLoggingService(logger, s)
handler := service.NewHandler(s, config.StaticDirectory)
diff --git a/service/service.go b/service/service.go
index be83bd0..02c55cb 100644
--- a/service/service.go
+++ b/service/service.go
@@ -35,6 +35,7 @@ type Service interface {
ServeSearchPage(ctx context.Context, c *model.Client, q string, qType string, offset int) (err error)
ServeUserSearchPage(ctx context.Context, c *model.Client, id string, q string, offset int) (err error)
ServeSettingsPage(ctx context.Context, c *model.Client) (err error)
+ SingleInstance(ctx context.Context) (instance string, ok bool)
NewSession(ctx context.Context, instance string) (redirectUrl string, sessionID string, err error)
Signin(ctx context.Context, c *model.Client, sessionID string,
code string) (token string, userID string, err error)
@@ -62,14 +63,15 @@ type Service interface {
}
type service struct {
- clientName string
- clientScope string
- clientWebsite string
- customCSS string
- postFormats []model.PostFormat
- renderer renderer.Renderer
- sessionRepo model.SessionRepo
- appRepo model.AppRepo
+ clientName string
+ clientScope string
+ clientWebsite string
+ customCSS string
+ postFormats []model.PostFormat
+ renderer renderer.Renderer
+ sessionRepo model.SessionRepo
+ appRepo model.AppRepo
+ singleInstance string
}
func NewService(clientName string,
@@ -80,16 +82,18 @@ func NewService(clientName string,
renderer renderer.Renderer,
sessionRepo model.SessionRepo,
appRepo model.AppRepo,
+ singleInstance string,
) Service {
return &service{
- clientName: clientName,
- clientScope: clientScope,
- clientWebsite: clientWebsite,
- customCSS: customCSS,
- postFormats: postFormats,
- renderer: renderer,
- sessionRepo: sessionRepo,
- appRepo: appRepo,
+ clientName: clientName,
+ clientScope: clientScope,
+ clientWebsite: clientWebsite,
+ customCSS: customCSS,
+ postFormats: postFormats,
+ renderer: renderer,
+ sessionRepo: sessionRepo,
+ appRepo: appRepo,
+ singleInstance: singleInstance,
}
}
@@ -622,6 +626,14 @@ func (svc *service) ServeSettingsPage(ctx context.Context, c *model.Client) (err
return svc.renderer.Render(rCtx, c.Writer, renderer.SettingsPage, data)
}
+func (svc *service) SingleInstance(ctx context.Context) (instance string, ok bool) {
+ if len(svc.singleInstance) > 0 {
+ instance = svc.singleInstance
+ ok = true
+ }
+ return
+}
+
func (svc *service) NewSession(ctx context.Context, instance string) (
redirectUrl string, sessionID string, err error) {
diff --git a/service/transport.go b/service/transport.go
index 69b28ec..f52cca0 100644
--- a/service/transport.go
+++ b/service/transport.go
@@ -14,12 +14,24 @@ import (
"github.com/gorilla/mux"
)
+const (
+ sessionExp = 365 * 24 * time.Hour
+)
+
func newClient(w io.Writer) *model.Client {
return &model.Client{
Writer: w,
}
}
+func setSessionCookie(w http.ResponseWriter, sessionID string, exp time.Duration) {
+ http.SetCookie(w, &http.Cookie{
+ Name: "session_id",
+ Value: sessionID,
+ Expires: time.Now().Add(exp),
+ })
+}
+
func newCtxWithSesion(req *http.Request) context.Context {
ctx := context.Background()
sessionID, err := req.Cookie("session_id")
@@ -93,11 +105,25 @@ func NewHandler(s Service, staticDir string) http.Handler {
signinPage := func(w http.ResponseWriter, req *http.Request) {
c := newClient(w)
ctx := context.Background()
- err := s.ServeSigninPage(ctx, c)
- if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
- s.ServeErrorPage(ctx, c, err)
- return
+ instance, ok := s.SingleInstance(ctx)
+ if ok {
+ url, sessionID, err := s.NewSession(ctx, instance)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ s.ServeErrorPage(ctx, c, err)
+ return
+ }
+
+ setSessionCookie(w, sessionID, sessionExp)
+ w.Header().Add("Location", url)
+ w.WriteHeader(http.StatusFound)
+ } else {
+ err := s.ServeSigninPage(ctx, c)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ s.ServeErrorPage(ctx, c, err)
+ return
+ }
}
}
@@ -291,12 +317,7 @@ func NewHandler(s Service, staticDir string) http.Handler {
return
}
- http.SetCookie(w, &http.Cookie{
- Name: "session_id",
- Value: sessionID,
- Expires: time.Now().Add(365 * 24 * time.Hour),
- })
-
+ setSessionCookie(w, sessionID, sessionExp)
w.Header().Add("Location", url)
w.WriteHeader(http.StatusFound)
}
@@ -689,12 +710,8 @@ func NewHandler(s Service, staticDir string) http.Handler {
ctx := newCtxWithSesionCSRF(req, req.FormValue("csrf_token"))
s.Signout(ctx, c)
- http.SetCookie(w, &http.Cookie{
- Name: "session_id",
- Value: "",
- Expires: time.Now(),
- })
+ setSessionCookie(w, "", 0)
w.Header().Add("Location", "/")
w.WriteHeader(http.StatusFound)
}