package server import ( "encoding/json" "local/s2sa/s2sa/server/router" "local/s2sa/s2sa/token" "net/http" "path" "strings" ) const clientsNS = "clients" const accessorsNS = "accessors" const wildcard = "{}" const serverNS = "server" func (s *Server) Routes() error { appendWildcards := func(s string, cnt int) string { s = strings.Trim(s, "/") return path.Join(s, strings.Repeat("/"+wildcard, cnt)) } paths := []struct { base string wildcards int method http.HandlerFunc }{ { base: "admin/register", wildcards: 1, method: s.adminRegister, }, { base: "register", wildcards: 1, method: s.authenticate(s.registerClient), }, { base: "generate", wildcards: 2, method: s.authenticate(s.generateToken), }, { base: "retrieve", wildcards: 3, method: s.authenticate(s.retrieveToken), }, { base: "revoke", wildcards: 2, method: s.authenticate(s.revokeToken), }, { base: "lookup", wildcards: 2, method: s.authenticate(s.lookupToken), }, { base: "policies", wildcards: 0, method: s.authenticate(s.getPolicies), }, } for _, path := range paths { if err := s.Add(appendWildcards(path.base, path.wildcards), path.method); err != nil { return err } } return nil } func (s *Server) authenticate(foo http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { recipient, accessorToken, ok := r.BasicAuth() if !ok { w.WriteHeader(http.StatusUnauthorized) return } accessor := strings.Split(accessorToken, ":")[0] tokenValue := strings.Split(accessorToken, ":")[1] token, err := s.authdb.Get(recipient, accessor) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } if token.Token != tokenValue { w.WriteHeader(http.StatusUnauthorized) return } if token.To != recipient { w.WriteHeader(http.StatusUnauthorized) return } foo(w, r) } } func (s *Server) adminRegister(w http.ResponseWriter, r *http.Request) { var name string if err := router.Params(r, &name); err != nil { w.WriteHeader(http.StatusBadRequest) return } token, err := s.authdb.New(serverNS, name) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } respondWithToken(token, w, r) } func (s *Server) registerClient(w http.ResponseWriter, r *http.Request) { var name string if err := router.Params(r, &name); err != nil { w.WriteHeader(http.StatusBadRequest) return } if err := s.db.Register(name); err != nil { w.WriteHeader(http.StatusInternalServerError) } } func (s *Server) generateToken(w http.ResponseWriter, r *http.Request) { var name, to string if err := router.Params(r, &name, &to); err != nil { w.WriteHeader(http.StatusBadRequest) return } token, err := s.db.New(name, to) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } respondWithToken(token, w, r) } func (s *Server) retrieveToken(w http.ResponseWriter, r *http.Request) { var creator, recipient, accessor string if err := router.Params(r, &creator, &recipient, &accessor); err != nil { w.WriteHeader(http.StatusBadRequest) return } token, err := s.db.Get(recipient, accessor) if err != nil { w.WriteHeader(http.StatusBadRequest) return } respondWithToken(token, w, r) } func respondWithToken(token token.Basic, w http.ResponseWriter, r *http.Request) { if err := json.NewEncoder(w).Encode(token); err != nil { w.WriteHeader(http.StatusInternalServerError) } } func (s *Server) revokeToken(w http.ResponseWriter, r *http.Request) { var name, accessor string if err := router.Params(r, &name, &accessor); err != nil { w.WriteHeader(http.StatusBadRequest) return } if err := s.db.Revoke(name, accessor); err != nil { w.WriteHeader(http.StatusInternalServerError) return } } func (s *Server) lookupToken(w http.ResponseWriter, r *http.Request) { var creator, recipient string if err := router.Params(r, &creator, &recipient); err != nil { w.WriteHeader(http.StatusBadRequest) return } token, err := s.db.Lookup(creator, recipient) if err != nil { w.WriteHeader(http.StatusBadRequest) return } respondWithToken(token, w, r) } func (s *Server) getPolicies(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) }