Add single instance mode

This commit is contained in:
r 2020-04-19 08:18:36 +00:00
parent 5abbadfa62
commit 55ed6a480e
5 changed files with 82 additions and 43 deletions

View file

@ -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

View file

@ -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":

View file

@ -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)

View file

@ -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) {

View file

@ -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)
}