Add single instance mode
This commit is contained in:
parent
5abbadfa62
commit
55ed6a480e
@ -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
|
||||
|
||||
|
@ -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":
|
||||
|
2
main.go
2
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)
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user