router.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. package router
  2. import (
  3. "net/http"
  4. "os"
  5. "github.com/go-chi/chi"
  6. "github.com/gorilla/sessions"
  7. "github.com/porter-dev/porter/internal/repository"
  8. "github.com/porter-dev/porter/server/api"
  9. "github.com/porter-dev/porter/server/requestlog"
  10. mw "github.com/porter-dev/porter/server/router/middleware"
  11. )
  12. // New creates a new Chi router instance
  13. func New(
  14. a *api.App,
  15. store sessions.Store,
  16. cookieName string,
  17. staticFilePath string,
  18. repo *repository.Repository,
  19. ) *chi.Mux {
  20. l := a.Logger()
  21. r := chi.NewRouter()
  22. auth := mw.NewAuth(store, cookieName, repo)
  23. r.Route("/api", func(r chi.Router) {
  24. r.Use(mw.ContentTypeJSON)
  25. // health checks
  26. r.Method("GET", "/livez", http.HandlerFunc(a.HandleLive))
  27. r.Method("GET", "/readyz", http.HandlerFunc(a.HandleReady))
  28. // /api/users routes
  29. r.Method("GET", "/users/{user_id}", auth.DoesUserIDMatch(requestlog.NewHandler(a.HandleReadUser, l), mw.URLParam))
  30. r.Method("GET", "/users/{user_id}/projects", auth.DoesUserIDMatch(requestlog.NewHandler(a.HandleListUserProjects, l), mw.URLParam))
  31. r.Method("POST", "/users", requestlog.NewHandler(a.HandleCreateUser, l))
  32. r.Method("DELETE", "/users/{user_id}", auth.DoesUserIDMatch(requestlog.NewHandler(a.HandleDeleteUser, l), mw.URLParam))
  33. r.Method("POST", "/login", requestlog.NewHandler(a.HandleLoginUser, l))
  34. r.Method("GET", "/auth/check", auth.BasicAuthenticate(requestlog.NewHandler(a.HandleAuthCheck, l)))
  35. r.Method("POST", "/logout", auth.BasicAuthenticate(requestlog.NewHandler(a.HandleLogoutUser, l)))
  36. // /integrations routes
  37. r.Method(
  38. "GET",
  39. "/integrations/cluster",
  40. auth.BasicAuthenticate(
  41. requestlog.NewHandler(a.HandleListClusterIntegrations, l),
  42. ),
  43. )
  44. r.Method(
  45. "GET",
  46. "/integrations/registry",
  47. auth.BasicAuthenticate(
  48. requestlog.NewHandler(a.HandleListRegistryIntegrations, l),
  49. ),
  50. )
  51. r.Method(
  52. "GET",
  53. "/integrations/repo",
  54. auth.BasicAuthenticate(
  55. requestlog.NewHandler(a.HandleListRepoIntegrations, l),
  56. ),
  57. )
  58. // /api/oauth routes
  59. // r.Method(
  60. // "GET",
  61. // "/oauth/projects/{project_id}/github",
  62. // auth.DoesUserHaveProjectAccess(
  63. // requestlog.NewHandler(a.HandleGithubOAuthStartProject, l),
  64. // mw.URLParam,
  65. // mw.WriteAccess,
  66. // ),
  67. // )
  68. // r.Method(
  69. // "GET",
  70. // "/oauth/github/callback",
  71. // requestlog.NewHandler(a.HandleGithubOAuthCallback, l),
  72. // )
  73. // /api/projects routes
  74. r.Method(
  75. "GET",
  76. "/projects/{project_id}",
  77. auth.DoesUserHaveProjectAccess(
  78. requestlog.NewHandler(a.HandleReadProject, l),
  79. mw.URLParam,
  80. mw.ReadAccess,
  81. ),
  82. )
  83. r.Method(
  84. "GET",
  85. "/projects/{project_id}/clusters/{cluster_id}",
  86. auth.DoesUserHaveProjectAccess(
  87. auth.DoesUserHaveClusterAccess(
  88. requestlog.NewHandler(a.HandleReadProjectCluster, l),
  89. mw.URLParam,
  90. mw.URLParam,
  91. ),
  92. mw.URLParam,
  93. mw.ReadAccess,
  94. ),
  95. )
  96. r.Method(
  97. "GET",
  98. "/projects/{project_id}/clusters",
  99. auth.DoesUserHaveProjectAccess(
  100. requestlog.NewHandler(a.HandleListProjectClusters, l),
  101. mw.URLParam,
  102. mw.ReadAccess,
  103. ),
  104. )
  105. r.Method("POST", "/projects", auth.BasicAuthenticate(requestlog.NewHandler(a.HandleCreateProject, l)))
  106. r.Method(
  107. "POST",
  108. "/projects/{project_id}/clusters/candidates",
  109. auth.DoesUserHaveProjectAccess(
  110. requestlog.NewHandler(a.HandleCreateProjectClusterCandidates, l),
  111. mw.URLParam,
  112. mw.WriteAccess,
  113. ),
  114. )
  115. r.Method(
  116. "GET",
  117. "/projects/{project_id}/clusters/candidates",
  118. auth.DoesUserHaveProjectAccess(
  119. requestlog.NewHandler(a.HandleListProjectClusterCandidates, l),
  120. mw.URLParam,
  121. mw.WriteAccess,
  122. ),
  123. )
  124. r.Method(
  125. "POST",
  126. "/projects/{project_id}/clusters/candidates/{candidate_id}/resolve",
  127. auth.DoesUserHaveProjectAccess(
  128. requestlog.NewHandler(a.HandleResolveClusterCandidate, l),
  129. mw.URLParam,
  130. mw.WriteAccess,
  131. ),
  132. )
  133. r.Method(
  134. "DELETE",
  135. "/projects/{project_id}",
  136. auth.DoesUserHaveProjectAccess(
  137. requestlog.NewHandler(a.HandleDeleteProject, l),
  138. mw.URLParam,
  139. mw.WriteAccess,
  140. ),
  141. )
  142. // /api/projects/{project_id}/integrations routes
  143. r.Method(
  144. "POST",
  145. "/projects/{project_id}/integrations/gcp",
  146. auth.DoesUserHaveProjectAccess(
  147. requestlog.NewHandler(a.HandleCreateGCPIntegration, l),
  148. mw.URLParam,
  149. mw.WriteAccess,
  150. ),
  151. )
  152. r.Method(
  153. "POST",
  154. "/projects/{project_id}/integrations/aws",
  155. auth.DoesUserHaveProjectAccess(
  156. requestlog.NewHandler(a.HandleCreateAWSIntegration, l),
  157. mw.URLParam,
  158. mw.WriteAccess,
  159. ),
  160. )
  161. // /api/projects/{project_id}/registries routes
  162. r.Method(
  163. "POST",
  164. "/projects/{project_id}/registries",
  165. auth.DoesUserHaveProjectAccess(
  166. requestlog.NewHandler(a.HandleCreateRegistry, l),
  167. mw.URLParam,
  168. mw.WriteAccess,
  169. ),
  170. )
  171. r.Method(
  172. "GET",
  173. "/projects/{project_id}/registries",
  174. auth.DoesUserHaveProjectAccess(
  175. requestlog.NewHandler(a.HandleListProjectRegistries, l),
  176. mw.URLParam,
  177. mw.WriteAccess,
  178. ),
  179. )
  180. r.Method(
  181. "GET",
  182. "/projects/{project_id}/registries/{registry_id}/repositories",
  183. auth.DoesUserHaveProjectAccess(
  184. auth.DoesUserHaveRegistryAccess(
  185. requestlog.NewHandler(a.HandleListRepositories, l),
  186. mw.URLParam,
  187. mw.URLParam,
  188. ),
  189. mw.URLParam,
  190. mw.WriteAccess,
  191. ),
  192. )
  193. r.Method(
  194. "GET",
  195. // * is the repo name, which can itself be nested
  196. // for example, for GCR this is project-id/repo
  197. // need to use wildcard, see https://github.com/go-chi/chi/issues/243
  198. "/projects/{project_id}/registries/{registry_id}/repositories/*",
  199. auth.DoesUserHaveProjectAccess(
  200. auth.DoesUserHaveRegistryAccess(
  201. requestlog.NewHandler(a.HandleListImages, l),
  202. mw.URLParam,
  203. mw.URLParam,
  204. ),
  205. mw.URLParam,
  206. mw.WriteAccess,
  207. ),
  208. )
  209. // /api/projects/{project_id}/releases routes
  210. r.Method(
  211. "GET",
  212. "/projects/{project_id}/releases",
  213. auth.DoesUserHaveProjectAccess(
  214. auth.DoesUserHaveClusterAccess(
  215. requestlog.NewHandler(a.HandleListReleases, l),
  216. mw.URLParam,
  217. mw.QueryParam,
  218. ),
  219. mw.URLParam,
  220. mw.ReadAccess,
  221. ),
  222. )
  223. r.Method(
  224. "GET",
  225. "/projects/{project_id}/releases/{name}/{revision}/components",
  226. auth.DoesUserHaveProjectAccess(
  227. auth.DoesUserHaveClusterAccess(
  228. requestlog.NewHandler(a.HandleGetReleaseComponents, l),
  229. mw.URLParam,
  230. mw.QueryParam,
  231. ),
  232. mw.URLParam,
  233. mw.ReadAccess,
  234. ),
  235. )
  236. r.Method(
  237. "GET",
  238. "/projects/{project_id}/releases/{name}/{revision}/controllers",
  239. auth.DoesUserHaveProjectAccess(
  240. auth.DoesUserHaveClusterAccess(
  241. requestlog.NewHandler(a.HandleGetReleaseControllers, l),
  242. mw.URLParam,
  243. mw.QueryParam,
  244. ),
  245. mw.URLParam,
  246. mw.ReadAccess,
  247. ),
  248. )
  249. r.Method(
  250. "GET",
  251. "/projects/{project_id}/releases/{name}/history",
  252. auth.DoesUserHaveProjectAccess(
  253. auth.DoesUserHaveClusterAccess(
  254. requestlog.NewHandler(a.HandleListReleaseHistory, l),
  255. mw.URLParam,
  256. mw.QueryParam,
  257. ),
  258. mw.URLParam,
  259. mw.ReadAccess,
  260. ),
  261. )
  262. r.Method(
  263. "POST",
  264. "/projects/{project_id}/releases/{name}/upgrade",
  265. auth.DoesUserHaveProjectAccess(
  266. auth.DoesUserHaveClusterAccess(
  267. requestlog.NewHandler(a.HandleUpgradeRelease, l),
  268. mw.URLParam,
  269. mw.QueryParam,
  270. ),
  271. mw.URLParam,
  272. mw.ReadAccess,
  273. ),
  274. )
  275. r.Method(
  276. "GET",
  277. "/projects/{project_id}/releases/{name}/{revision}",
  278. auth.DoesUserHaveProjectAccess(
  279. auth.DoesUserHaveClusterAccess(
  280. requestlog.NewHandler(a.HandleGetRelease, l),
  281. mw.URLParam,
  282. mw.QueryParam,
  283. ),
  284. mw.URLParam,
  285. mw.ReadAccess,
  286. ),
  287. )
  288. r.Method(
  289. "POST",
  290. "/projects/{project_id}/releases/{name}/rollback",
  291. auth.DoesUserHaveProjectAccess(
  292. auth.DoesUserHaveClusterAccess(
  293. requestlog.NewHandler(a.HandleRollbackRelease, l),
  294. mw.URLParam,
  295. mw.QueryParam,
  296. ),
  297. mw.URLParam,
  298. mw.ReadAccess,
  299. ),
  300. )
  301. // /api/projects/{project_id}/repos routes
  302. // r.Method(
  303. // "GET",
  304. // "/projects/{project_id}/repos",
  305. // auth.DoesUserHaveProjectAccess(
  306. // requestlog.NewHandler(a.HandleListRepos, l),
  307. // mw.URLParam,
  308. // mw.ReadAccess,
  309. // ),
  310. // )
  311. // r.Method(
  312. // "GET",
  313. // "/projects/{project_id}/repos/{kind}/{name}/branches",
  314. // auth.DoesUserHaveProjectAccess(
  315. // requestlog.NewHandler(a.HandleGetBranches, l),
  316. // mw.URLParam,
  317. // mw.ReadAccess,
  318. // ),
  319. // )
  320. // r.Method(
  321. // "GET",
  322. // "/projects/{project_id}/repos/{kind}/{name}/{branch}/contents",
  323. // auth.DoesUserHaveProjectAccess(
  324. // requestlog.NewHandler(a.HandleGetBranchContents, l),
  325. // mw.URLParam,
  326. // mw.ReadAccess,
  327. // ),
  328. // )
  329. // /api/projects/{project_id}/images routes
  330. r.Method(
  331. "POST",
  332. "/projects/{project_id}/deploy",
  333. auth.DoesUserHaveProjectAccess(
  334. auth.DoesUserHaveClusterAccess(
  335. requestlog.NewHandler(a.HandleDeployTemplate, l),
  336. mw.URLParam,
  337. mw.QueryParam,
  338. ),
  339. mw.URLParam,
  340. mw.ReadAccess,
  341. ),
  342. )
  343. // /api/templates routes
  344. r.Method(
  345. "GET",
  346. "/templates",
  347. auth.BasicAuthenticate(
  348. requestlog.NewHandler(a.HandleListTemplates, l),
  349. ),
  350. )
  351. // /api/projects/{project_id}/k8s routes
  352. r.Method(
  353. "GET",
  354. "/projects/{project_id}/k8s/namespaces",
  355. auth.DoesUserHaveProjectAccess(
  356. auth.DoesUserHaveClusterAccess(
  357. requestlog.NewHandler(a.HandleListNamespaces, l),
  358. mw.URLParam,
  359. mw.QueryParam,
  360. ),
  361. mw.URLParam,
  362. mw.ReadAccess,
  363. ),
  364. )
  365. r.Method(
  366. "GET",
  367. "/projects/{project_id}/k8s/{namespace}/pod/{name}/logs",
  368. auth.DoesUserHaveProjectAccess(
  369. auth.DoesUserHaveClusterAccess(
  370. requestlog.NewHandler(a.HandleGetPodLogs, l),
  371. mw.URLParam,
  372. mw.QueryParam,
  373. ),
  374. mw.URLParam,
  375. mw.ReadAccess,
  376. ),
  377. )
  378. r.Method(
  379. "GET",
  380. "/projects/{project_id}/k8s/{kind}/status",
  381. auth.DoesUserHaveProjectAccess(
  382. auth.DoesUserHaveClusterAccess(
  383. requestlog.NewHandler(a.HandleStreamControllerStatus, l),
  384. mw.URLParam,
  385. mw.QueryParam,
  386. ),
  387. mw.URLParam,
  388. mw.ReadAccess,
  389. ),
  390. )
  391. r.Method(
  392. "GET",
  393. "/projects/{project_id}/k8s/pods",
  394. auth.DoesUserHaveProjectAccess(
  395. auth.DoesUserHaveClusterAccess(
  396. requestlog.NewHandler(a.HandleListPods, l),
  397. mw.URLParam,
  398. mw.QueryParam,
  399. ),
  400. mw.URLParam,
  401. mw.ReadAccess,
  402. ),
  403. )
  404. })
  405. fs := http.FileServer(http.Dir(staticFilePath))
  406. r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
  407. if _, err := os.Stat(staticFilePath + r.RequestURI); os.IsNotExist(err) {
  408. http.StripPrefix(r.URL.Path, fs).ServeHTTP(w, r)
  409. } else {
  410. fs.ServeHTTP(w, r)
  411. }
  412. })
  413. return r
  414. }