github.com/jancarloviray/community@v0.41.1-0.20170124221257-33a66c87cf2f/core/api/endpoint/router.go (about) 1 // Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved. 2 // 3 // This software (Documize Community Edition) is licensed under 4 // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html 5 // 6 // You can operate outside the AGPL restrictions by purchasing 7 // Documize Enterprise Edition and obtaining a commercial license 8 // by contacting <sales@documize.com>. 9 // 10 // https://documize.com 11 12 package endpoint 13 14 import ( 15 "encoding/json" 16 "net/http" 17 "sort" 18 "strings" 19 20 "github.com/documize/community/core/log" 21 "github.com/documize/community/core/web" 22 "github.com/gorilla/mux" 23 ) 24 25 const ( 26 // RoutePrefixPublic used for the unsecured api 27 RoutePrefixPublic = "/api/public/" 28 // RoutePrefixPrivate used for secured api (requiring api) 29 RoutePrefixPrivate = "/api/" 30 // RoutePrefixRoot used for unsecured endpoints at root (e.g. robots.txt) 31 RoutePrefixRoot = "/" 32 ) 33 34 type routeDef struct { 35 Prefix string 36 Path string 37 Methods []string 38 Queries []string 39 } 40 41 // RouteFunc describes end-point functions 42 type RouteFunc func(http.ResponseWriter, *http.Request) 43 44 type routeMap map[string]RouteFunc 45 46 var routes = make(routeMap) 47 48 func routesKey(prefix, path string, methods, queries []string) (string, error) { 49 rd := routeDef{ 50 Prefix: prefix, 51 Path: path, 52 Methods: methods, 53 Queries: queries, 54 } 55 b, e := json.Marshal(rd) 56 return string(b), e 57 } 58 59 // Add an endpoint to those that will be processed when Serve() is called. 60 func Add(prefix, path string, methods, queries []string, endPtFn RouteFunc) error { 61 k, e := routesKey(prefix, path, methods, queries) 62 if e != nil { 63 return e 64 } 65 routes[k] = endPtFn 66 return nil 67 } 68 69 // Remove an endpoint. 70 func Remove(prefix, path string, methods, queries []string) error { 71 k, e := routesKey(prefix, path, methods, queries) 72 if e != nil { 73 return e 74 } 75 delete(routes, k) 76 return nil 77 } 78 79 type routeSortItem struct { 80 def routeDef 81 fun RouteFunc 82 ord int 83 } 84 85 type routeSorter []routeSortItem 86 87 func (s routeSorter) Len() int { return len(s) } 88 func (s routeSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 89 func (s routeSorter) Less(i, j int) bool { 90 if s[i].def.Prefix == s[j].def.Prefix && s[i].def.Path == s[j].def.Path { 91 return len(s[i].def.Queries) > len(s[j].def.Queries) 92 } 93 return s[i].ord < s[j].ord 94 } 95 96 func buildRoutes(prefix string) *mux.Router { 97 var rs routeSorter 98 for k, v := range routes { 99 var rd routeDef 100 if err := json.Unmarshal([]byte(k), &rd); err != nil { 101 log.Error("buildRoutes json.Unmarshal", err) 102 } else { 103 if rd.Prefix == prefix { 104 order := strings.Index(rd.Path, "{") 105 if order == -1 { 106 order = len(rd.Path) 107 } 108 order = -order 109 rs = append(rs, routeSortItem{def: rd, fun: v, ord: order}) 110 } 111 } 112 } 113 sort.Sort(rs) 114 router := mux.NewRouter() 115 for _, it := range rs { 116 //fmt.Printf("DEBUG buildRoutes: %d %#v\n", it.ord, it.def) 117 118 x := router.HandleFunc(it.def.Prefix+it.def.Path, it.fun) 119 if len(it.def.Methods) > 0 { 120 y := x.Methods(it.def.Methods...) 121 if len(it.def.Queries) > 0 { 122 y.Queries(it.def.Queries...) 123 } 124 } 125 } 126 return router 127 } 128 129 func init() { 130 //************************************************** 131 // Non-secure routes 132 //************************************************** 133 134 log.IfErr(Add(RoutePrefixPublic, "meta", []string{"GET", "OPTIONS"}, nil, GetMeta)) 135 log.IfErr(Add(RoutePrefixPublic, "authenticate", []string{"POST", "OPTIONS"}, nil, Authenticate)) 136 log.IfErr(Add(RoutePrefixPublic, "validate", []string{"GET", "OPTIONS"}, nil, ValidateAuthToken)) 137 log.IfErr(Add(RoutePrefixPublic, "forgot", []string{"POST", "OPTIONS"}, nil, ForgotUserPassword)) 138 log.IfErr(Add(RoutePrefixPublic, "reset/{token}", []string{"POST", "OPTIONS"}, nil, ResetUserPassword)) 139 log.IfErr(Add(RoutePrefixPublic, "share/{folderID}", []string{"POST", "OPTIONS"}, nil, AcceptSharedFolder)) 140 log.IfErr(Add(RoutePrefixPublic, "attachments/{orgID}/{attachmentID}", []string{"GET", "OPTIONS"}, nil, AttachmentDownload)) 141 log.IfErr(Add(RoutePrefixPublic, "version", []string{"GET", "OPTIONS"}, nil, version)) 142 143 //************************************************** 144 // Secure routes 145 //************************************************** 146 147 // Import & Convert Document 148 log.IfErr(Add(RoutePrefixPrivate, "import/folder/{folderID}", []string{"POST", "OPTIONS"}, nil, UploadConvertDocument)) 149 150 // Document 151 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/export", []string{"GET", "OPTIONS"}, nil, GetDocumentAsDocx)) 152 log.IfErr(Add(RoutePrefixPrivate, "documents", []string{"GET", "OPTIONS"}, []string{"filter", "tag"}, GetDocumentsByTag)) 153 log.IfErr(Add(RoutePrefixPrivate, "documents", []string{"GET", "OPTIONS"}, nil, GetDocumentsByFolder)) 154 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}", []string{"GET", "OPTIONS"}, nil, GetDocument)) 155 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}", []string{"PUT", "OPTIONS"}, nil, UpdateDocument)) 156 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}", []string{"DELETE", "OPTIONS"}, nil, DeleteDocument)) 157 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/meta", []string{"GET", "OPTIONS"}, nil, GetDocumentMeta)) 158 159 // Document Page 160 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/level", []string{"POST", "OPTIONS"}, nil, ChangeDocumentPageLevel)) 161 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/sequence", []string{"POST", "OPTIONS"}, nil, ChangeDocumentPageSequence)) 162 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/batch", []string{"POST", "OPTIONS"}, nil, GetDocumentPagesBatch)) 163 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}/revisions", []string{"GET", "OPTIONS"}, nil, GetDocumentPageRevisions)) 164 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}/revisions/{revisionID}", []string{"GET", "OPTIONS"}, nil, GetDocumentPageDiff)) 165 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}/revisions/{revisionID}", []string{"POST", "OPTIONS"}, nil, RollbackDocumentPage)) 166 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/revisions", []string{"GET", "OPTIONS"}, nil, GetDocumentRevisions)) 167 168 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages", []string{"GET", "OPTIONS"}, nil, GetDocumentPages)) 169 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}", []string{"PUT", "OPTIONS"}, nil, UpdateDocumentPage)) 170 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}", []string{"DELETE", "OPTIONS"}, nil, DeleteDocumentPage)) 171 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages", []string{"DELETE", "OPTIONS"}, nil, DeleteDocumentPages)) 172 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}", []string{"GET", "OPTIONS"}, nil, GetDocumentPage)) 173 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages", []string{"POST", "OPTIONS"}, nil, AddDocumentPage)) 174 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/attachments", []string{"GET", "OPTIONS"}, nil, GetAttachments)) 175 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/attachments/{attachmentID}", []string{"DELETE", "OPTIONS"}, nil, DeleteAttachment)) 176 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/attachments", []string{"POST", "OPTIONS"}, nil, AddAttachments)) 177 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}/meta", []string{"GET", "OPTIONS"}, nil, GetDocumentPageMeta)) 178 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/{pageID}/copy/{targetID}", []string{"POST", "OPTIONS"}, nil, CopyPage)) 179 180 // Organization 181 log.IfErr(Add(RoutePrefixPrivate, "organizations/{orgID}", []string{"GET", "OPTIONS"}, nil, GetOrganization)) 182 log.IfErr(Add(RoutePrefixPrivate, "organizations/{orgID}", []string{"PUT", "OPTIONS"}, nil, UpdateOrganization)) 183 184 // Folder 185 log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/move/{moveToId}", []string{"DELETE", "OPTIONS"}, nil, RemoveFolder)) 186 log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"PUT", "OPTIONS"}, nil, SetFolderPermissions)) 187 log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"GET", "OPTIONS"}, nil, GetFolderPermissions)) 188 log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/invitation", []string{"POST", "OPTIONS"}, nil, InviteToFolder)) 189 log.IfErr(Add(RoutePrefixPrivate, "folders", []string{"GET", "OPTIONS"}, []string{"filter", "viewers"}, GetFolderVisibility)) 190 log.IfErr(Add(RoutePrefixPrivate, "folders", []string{"POST", "OPTIONS"}, nil, AddFolder)) 191 log.IfErr(Add(RoutePrefixPrivate, "folders", []string{"GET", "OPTIONS"}, nil, GetFolders)) 192 log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}", []string{"GET", "OPTIONS"}, nil, GetFolder)) 193 log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}", []string{"PUT", "OPTIONS"}, nil, UpdateFolder)) 194 195 // Users 196 log.IfErr(Add(RoutePrefixPrivate, "users/{userID}/password", []string{"POST", "OPTIONS"}, nil, ChangeUserPassword)) 197 log.IfErr(Add(RoutePrefixPrivate, "users/{userID}/permissions", []string{"GET", "OPTIONS"}, nil, GetUserFolderPermissions)) 198 log.IfErr(Add(RoutePrefixPrivate, "users", []string{"POST", "OPTIONS"}, nil, AddUser)) 199 log.IfErr(Add(RoutePrefixPrivate, "users/folder/{folderID}", []string{"GET", "OPTIONS"}, nil, GetFolderUsers)) 200 log.IfErr(Add(RoutePrefixPrivate, "users", []string{"GET", "OPTIONS"}, nil, GetOrganizationUsers)) 201 log.IfErr(Add(RoutePrefixPrivate, "users/{userID}", []string{"GET", "OPTIONS"}, nil, GetUser)) 202 log.IfErr(Add(RoutePrefixPrivate, "users/{userID}", []string{"PUT", "OPTIONS"}, nil, UpdateUser)) 203 log.IfErr(Add(RoutePrefixPrivate, "users/{userID}", []string{"DELETE", "OPTIONS"}, nil, DeleteUser)) 204 205 // Search 206 log.IfErr(Add(RoutePrefixPrivate, "search", []string{"GET", "OPTIONS"}, nil, SearchDocuments)) 207 208 // Templates 209 log.IfErr(Add(RoutePrefixPrivate, "templates", []string{"POST", "OPTIONS"}, nil, SaveAsTemplate)) 210 log.IfErr(Add(RoutePrefixPrivate, "templates", []string{"GET", "OPTIONS"}, nil, GetSavedTemplates)) 211 log.IfErr(Add(RoutePrefixPrivate, "templates/stock", []string{"GET", "OPTIONS"}, nil, GetStockTemplates)) 212 log.IfErr(Add(RoutePrefixPrivate, "templates/{templateID}/folder/{folderID}", []string{"POST", "OPTIONS"}, []string{"type", "stock"}, StartDocumentFromStockTemplate)) 213 log.IfErr(Add(RoutePrefixPrivate, "templates/{templateID}/folder/{folderID}", []string{"POST", "OPTIONS"}, []string{"type", "saved"}, StartDocumentFromSavedTemplate)) 214 215 // Sections 216 log.IfErr(Add(RoutePrefixPrivate, "sections", []string{"GET", "OPTIONS"}, nil, GetSections)) 217 log.IfErr(Add(RoutePrefixPrivate, "sections", []string{"POST", "OPTIONS"}, nil, RunSectionCommand)) 218 log.IfErr(Add(RoutePrefixPrivate, "sections/refresh", []string{"GET", "OPTIONS"}, nil, RefreshSections)) 219 log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/space/{folderID}", []string{"GET", "OPTIONS"}, nil, GetBlocksForSpace)) 220 log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/{blockID}", []string{"GET", "OPTIONS"}, nil, GetBlock)) 221 log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/{blockID}", []string{"PUT", "OPTIONS"}, nil, UpdateBlock)) 222 log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/{blockID}", []string{"DELETE", "OPTIONS"}, nil, DeleteBlock)) 223 log.IfErr(Add(RoutePrefixPrivate, "sections/blocks", []string{"POST", "OPTIONS"}, nil, AddBlock)) 224 log.IfErr(Add(RoutePrefixPrivate, "sections/targets", []string{"GET", "OPTIONS"}, nil, GetPageMoveCopyTargets)) 225 226 // Links 227 log.IfErr(Add(RoutePrefixPrivate, "links/{folderID}/{documentID}/{pageID}", []string{"GET", "OPTIONS"}, nil, GetLinkCandidates)) 228 log.IfErr(Add(RoutePrefixPrivate, "links", []string{"GET", "OPTIONS"}, nil, SearchLinkCandidates)) 229 log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/links", []string{"GET", "OPTIONS"}, nil, GetDocumentLinks)) 230 231 // Global installation-wide config 232 log.IfErr(Add(RoutePrefixPrivate, "global", []string{"GET", "OPTIONS"}, nil, GetGlobalConfig)) 233 log.IfErr(Add(RoutePrefixPrivate, "global", []string{"PUT", "OPTIONS"}, nil, SaveGlobalConfig)) 234 235 // Pinned items 236 log.IfErr(Add(RoutePrefixPrivate, "pin/{userID}", []string{"POST", "OPTIONS"}, nil, AddPin)) 237 log.IfErr(Add(RoutePrefixPrivate, "pin/{userID}", []string{"GET", "OPTIONS"}, nil, GetUserPins)) 238 log.IfErr(Add(RoutePrefixPrivate, "pin/{userID}/sequence", []string{"POST", "OPTIONS"}, nil, UpdatePinSequence)) 239 log.IfErr(Add(RoutePrefixPrivate, "pin/{userID}/{pinID}", []string{"DELETE", "OPTIONS"}, nil, DeleteUserPin)) 240 241 // Single page app handler 242 log.IfErr(Add(RoutePrefixRoot, "robots.txt", []string{"GET", "OPTIONS"}, nil, GetRobots)) 243 log.IfErr(Add(RoutePrefixRoot, "sitemap.xml", []string{"GET", "OPTIONS"}, nil, GetSitemap)) 244 log.IfErr(Add(RoutePrefixRoot, "{rest:.*}", nil, nil, web.EmberHandler)) 245 }