Add configuration discovery to publish handler.

This permits metadata edits on the publish page if the
viewer is the owner.

(e.g. tagging, titling photos...)

Change-Id: I08b098eaae92f5b629b02707d67bec23a705c29f
This commit is contained in:
Brad Fitzpatrick 2011-07-08 15:05:46 -07:00
parent 711bcfbd44
commit 16cc888842
4 changed files with 60 additions and 7 deletions

View File

@ -31,6 +31,8 @@ type Loader interface {
// Returns either a Storage or an http.Handler
GetHandler(prefix string) (interface{}, os.Error)
FindHandlerByTypeIfLoaded(htype string) (prefix string, handler interface{}, err os.Error)
}
type StorageConstructor func(Loader, jsonconfig.Obj) (Storage, os.Error)

View File

@ -226,6 +226,15 @@ func main() {
ws.Serve()
}
func (hl *handlerLoader) FindHandlerByTypeIfLoaded(htype string) (prefix string, handler interface{}, err os.Error) {
for prefix, config := range hl.config {
if config.htype == htype {
return prefix, hl.handler[prefix], nil
}
}
return "", nil, os.ENOENT
}
func (hl *handlerLoader) setupAll() {
for prefix := range hl.config {
hl.setupHandler(prefix)

View File

@ -46,6 +46,7 @@ type PublishHandler struct {
JSFiles, CSSFiles []string
bsLoader blobserver.Loader
staticHandler http.Handler
}
@ -54,7 +55,9 @@ func init() {
}
func newPublishFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err os.Error) {
ph := &PublishHandler{}
ph := &PublishHandler{
bsLoader: ld,
}
ph.RootName = conf.RequiredString("rootName")
ph.JSFiles = conf.OptionalList("js")
ph.CSSFiles = conf.OptionalList("css")
@ -138,7 +141,29 @@ func (ph *PublishHandler) lookupPathTarget(root *blobref.BlobRef, suffix string)
return path.Target, nil
}
func (ph *PublishHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) {
if !ph.ViewerIsOwner(req) {
discoveryHelper(rw, req, map[string]interface{}{
"error": "viewer isn't owner",
})
return
}
_, handler, err := ph.bsLoader.FindHandlerByTypeIfLoaded("ui")
if err != nil {
discoveryHelper(rw, req, map[string]interface{}{
"error": "no admin handler running",
})
return
}
ui := handler.(*UIHandler)
ui.serveDiscovery(rw, req)
}
func (ph *PublishHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if req.URL.Query().Get("camli.mode") == "config" {
ph.serveDiscovery(rw, req)
return
}
preq := ph.NewRequest(rw, req)
preq.serveHTTP()
}
@ -184,6 +209,16 @@ func (ph *PublishHandler) NewRequest(rw http.ResponseWriter, req *http.Request)
}
}
func (ph *PublishHandler) ViewerIsOwner(req *http.Request) bool {
// TODO: better check later
return strings.HasPrefix(req.RemoteAddr, "127.") ||
strings.HasPrefix(req.RemoteAddr, "localhost:")
}
func (pr *publishRequest) ViewerIsOwner() bool {
return pr.ph.ViewerIsOwner(pr.req)
}
func (pr *publishRequest) Debug() bool {
return pr.req.FormValue("debug") == "1"
}
@ -359,8 +394,12 @@ func (pr *publishRequest) serveSubject() {
}
for _, filename := range pr.ph.JSFiles {
pr.pf(" <script src='%s'></script>\n", pr.staticPath(filename))
if filename == "camli.js" && pr.ViewerIsOwner() {
pr.pf(" <script src='%s'></script>\n", pr.base+"?camli.mode=config&cb=onConfiguration")
}
}
pr.pf(" <script>\n")
pr.pf("var camliViewIsOwner = %v;\n", pr.ViewerIsOwner())
pr.pf("var camliPagePermanode = %q;\n", pr.subject)
pr.pf("var camliPageMeta = \n")
json, _ := json.MarshalIndent(jm, "", " ")

View File

@ -213,14 +213,21 @@ func (ui *UIHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
}
func (ui *UIHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) {
func discoveryHelper(rw http.ResponseWriter, req *http.Request, m map[string]interface{}) {
rw.Header().Set("Content-Type", "text/javascript")
inCb := false
if cb := req.FormValue("cb"); identPattern.MatchString(cb) {
fmt.Fprintf(rw, "%s(", cb)
inCb = true
}
bytes, _ := json.MarshalIndent(m, "", " ")
rw.Write(bytes)
if inCb {
rw.Write([]byte{')'})
}
}
func (ui *UIHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) {
pubRoots := map[string]interface{}{}
for key, pubh := range ui.PublishRoots {
m := map[string]interface{}{
@ -237,7 +244,7 @@ func (ui *UIHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) {
pubRoots[pubh.RootName] = m
}
bytes, _ := json.Marshal(map[string]interface{}{
discoveryHelper(rw, req, map[string]interface{}{
"blobRoot": ui.BlobRoot,
"searchRoot": ui.SearchRoot,
"jsonSignRoot": ui.JSONSignRoot,
@ -245,10 +252,6 @@ func (ui *UIHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) {
"downloadHelper": "./download/",
"publishRoots": pubRoots,
})
rw.Write(bytes)
if inCb {
rw.Write([]byte{')'})
}
}
func (ui *UIHandler) serveDownload(rw http.ResponseWriter, req *http.Request) {