router.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  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(
  30. "GET",
  31. "/users/{user_id}",
  32. auth.DoesUserIDMatch(
  33. requestlog.NewHandler(a.HandleReadUser, l),
  34. mw.URLParam,
  35. ),
  36. )
  37. r.Method(
  38. "GET",
  39. "/users/{user_id}/projects",
  40. auth.DoesUserIDMatch(
  41. requestlog.NewHandler(a.HandleListUserProjects, l),
  42. mw.URLParam,
  43. ),
  44. )
  45. r.Method(
  46. "POST",
  47. "/users",
  48. requestlog.NewHandler(a.HandleCreateUser, l),
  49. )
  50. r.Method(
  51. "DELETE",
  52. "/users/{user_id}",
  53. auth.DoesUserIDMatch(
  54. requestlog.NewHandler(a.HandleDeleteUser, l),
  55. mw.URLParam,
  56. ),
  57. )
  58. r.Method(
  59. "POST",
  60. "/login",
  61. requestlog.NewHandler(a.HandleLoginUser, l),
  62. )
  63. r.Method(
  64. "GET",
  65. "/auth/check",
  66. auth.BasicAuthenticate(
  67. requestlog.NewHandler(a.HandleAuthCheck, l),
  68. ),
  69. )
  70. r.Method(
  71. "POST",
  72. "/logout",
  73. auth.BasicAuthenticate(
  74. requestlog.NewHandler(a.HandleLogoutUser, l),
  75. ),
  76. )
  77. // /api/integrations routes
  78. r.Method(
  79. "GET",
  80. "/integrations/cluster",
  81. auth.BasicAuthenticate(
  82. requestlog.NewHandler(a.HandleListClusterIntegrations, l),
  83. ),
  84. )
  85. r.Method(
  86. "GET",
  87. "/integrations/registry",
  88. auth.BasicAuthenticate(
  89. requestlog.NewHandler(a.HandleListRegistryIntegrations, l),
  90. ),
  91. )
  92. r.Method(
  93. "GET",
  94. "/integrations/repo",
  95. auth.BasicAuthenticate(
  96. requestlog.NewHandler(a.HandleListRepoIntegrations, l),
  97. ),
  98. )
  99. // /api/templates routes
  100. r.Method(
  101. "GET",
  102. "/templates",
  103. auth.BasicAuthenticate(
  104. requestlog.NewHandler(a.HandleListTemplates, l),
  105. ),
  106. )
  107. r.Method(
  108. "GET",
  109. "/templates/{name}/{version}",
  110. auth.BasicAuthenticate(
  111. requestlog.NewHandler(a.HandleReadTemplate, l),
  112. ),
  113. )
  114. // /api/oauth routes
  115. // r.Method(
  116. // "GET",
  117. // "/oauth/projects/{project_id}/github",
  118. // auth.DoesUserHaveProjectAccess(
  119. // requestlog.NewHandler(a.HandleGithubOAuthStartProject, l),
  120. // mw.URLParam,
  121. // mw.WriteAccess,
  122. // ),
  123. // )
  124. // r.Method(
  125. // "GET",
  126. // "/oauth/github/callback",
  127. // requestlog.NewHandler(a.HandleGithubOAuthCallback, l),
  128. // )
  129. // /api/projects routes
  130. r.Method(
  131. "GET",
  132. "/projects/{project_id}",
  133. auth.DoesUserHaveProjectAccess(
  134. requestlog.NewHandler(a.HandleReadProject, l),
  135. mw.URLParam,
  136. mw.ReadAccess,
  137. ),
  138. )
  139. r.Method(
  140. "POST",
  141. "/projects",
  142. auth.BasicAuthenticate(
  143. requestlog.NewHandler(a.HandleCreateProject, l),
  144. ),
  145. )
  146. r.Method(
  147. "DELETE",
  148. "/projects/{project_id}",
  149. auth.DoesUserHaveProjectAccess(
  150. requestlog.NewHandler(a.HandleDeleteProject, l),
  151. mw.URLParam,
  152. mw.WriteAccess,
  153. ),
  154. )
  155. // /api/projects/{project_id}/clusters routes
  156. r.Method(
  157. "GET",
  158. "/projects/{project_id}/clusters",
  159. auth.DoesUserHaveProjectAccess(
  160. requestlog.NewHandler(a.HandleListProjectClusters, l),
  161. mw.URLParam,
  162. mw.ReadAccess,
  163. ),
  164. )
  165. r.Method(
  166. "POST",
  167. "/projects/{project_id}/clusters",
  168. auth.DoesUserHaveProjectAccess(
  169. requestlog.NewHandler(a.HandleCreateProjectCluster, l),
  170. mw.URLParam,
  171. mw.ReadAccess,
  172. ),
  173. )
  174. r.Method(
  175. "GET",
  176. "/projects/{project_id}/clusters/{cluster_id}",
  177. auth.DoesUserHaveProjectAccess(
  178. auth.DoesUserHaveClusterAccess(
  179. requestlog.NewHandler(a.HandleReadProjectCluster, l),
  180. mw.URLParam,
  181. mw.URLParam,
  182. ),
  183. mw.URLParam,
  184. mw.ReadAccess,
  185. ),
  186. )
  187. r.Method(
  188. "POST",
  189. "/projects/{project_id}/clusters/{cluster_id}",
  190. auth.DoesUserHaveProjectAccess(
  191. auth.DoesUserHaveClusterAccess(
  192. requestlog.NewHandler(a.HandleUpdateProjectCluster, l),
  193. mw.URLParam,
  194. mw.URLParam,
  195. ),
  196. mw.URLParam,
  197. mw.WriteAccess,
  198. ),
  199. )
  200. r.Method(
  201. "DELETE",
  202. "/projects/{project_id}/clusters/{cluster_id}",
  203. auth.DoesUserHaveProjectAccess(
  204. auth.DoesUserHaveClusterAccess(
  205. requestlog.NewHandler(a.HandleDeleteProjectCluster, l),
  206. mw.URLParam,
  207. mw.URLParam,
  208. ),
  209. mw.URLParam,
  210. mw.WriteAccess,
  211. ),
  212. )
  213. // /api/projects/{project_id}/clusters/candidates routes
  214. r.Method(
  215. "POST",
  216. "/projects/{project_id}/clusters/candidates",
  217. auth.DoesUserHaveProjectAccess(
  218. requestlog.NewHandler(a.HandleCreateProjectClusterCandidates, l),
  219. mw.URLParam,
  220. mw.WriteAccess,
  221. ),
  222. )
  223. r.Method(
  224. "GET",
  225. "/projects/{project_id}/clusters/candidates",
  226. auth.DoesUserHaveProjectAccess(
  227. requestlog.NewHandler(a.HandleListProjectClusterCandidates, l),
  228. mw.URLParam,
  229. mw.WriteAccess,
  230. ),
  231. )
  232. r.Method(
  233. "POST",
  234. "/projects/{project_id}/clusters/candidates/{candidate_id}/resolve",
  235. auth.DoesUserHaveProjectAccess(
  236. requestlog.NewHandler(a.HandleResolveClusterCandidate, l),
  237. mw.URLParam,
  238. mw.WriteAccess,
  239. ),
  240. )
  241. // /api/projects/{project_id}/integrations routes
  242. r.Method(
  243. "POST",
  244. "/projects/{project_id}/integrations/gcp",
  245. auth.DoesUserHaveProjectAccess(
  246. requestlog.NewHandler(a.HandleCreateGCPIntegration, l),
  247. mw.URLParam,
  248. mw.WriteAccess,
  249. ),
  250. )
  251. r.Method(
  252. "POST",
  253. "/projects/{project_id}/integrations/aws",
  254. auth.DoesUserHaveProjectAccess(
  255. requestlog.NewHandler(a.HandleCreateAWSIntegration, l),
  256. mw.URLParam,
  257. mw.WriteAccess,
  258. ),
  259. )
  260. // /api/projects/{project_id}/registries routes
  261. r.Method(
  262. "POST",
  263. "/projects/{project_id}/registries",
  264. auth.DoesUserHaveProjectAccess(
  265. requestlog.NewHandler(a.HandleCreateRegistry, l),
  266. mw.URLParam,
  267. mw.WriteAccess,
  268. ),
  269. )
  270. r.Method(
  271. "GET",
  272. "/projects/{project_id}/registries",
  273. auth.DoesUserHaveProjectAccess(
  274. requestlog.NewHandler(a.HandleListProjectRegistries, l),
  275. mw.URLParam,
  276. mw.WriteAccess,
  277. ),
  278. )
  279. r.Method(
  280. "POST",
  281. "/projects/{project_id}/registries/{registry_id}",
  282. auth.DoesUserHaveProjectAccess(
  283. auth.DoesUserHaveRegistryAccess(
  284. requestlog.NewHandler(a.HandleUpdateProjectRegistry, l),
  285. mw.URLParam,
  286. mw.URLParam,
  287. ),
  288. mw.URLParam,
  289. mw.WriteAccess,
  290. ),
  291. )
  292. r.Method(
  293. "DELETE",
  294. "/projects/{project_id}/registries/{registry_id}",
  295. auth.DoesUserHaveProjectAccess(
  296. auth.DoesUserHaveRegistryAccess(
  297. requestlog.NewHandler(a.HandleDeleteProjectRegistry, l),
  298. mw.URLParam,
  299. mw.URLParam,
  300. ),
  301. mw.URLParam,
  302. mw.WriteAccess,
  303. ),
  304. )
  305. // /api/projects/{project_id}/registries/{registry_id}/repositories routes
  306. r.Method(
  307. "GET",
  308. "/projects/{project_id}/registries/{registry_id}/repositories",
  309. auth.DoesUserHaveProjectAccess(
  310. auth.DoesUserHaveRegistryAccess(
  311. requestlog.NewHandler(a.HandleListRepositories, l),
  312. mw.URLParam,
  313. mw.URLParam,
  314. ),
  315. mw.URLParam,
  316. mw.WriteAccess,
  317. ),
  318. )
  319. r.Method(
  320. "GET",
  321. // * is the repo name, which can itself be nested
  322. // for example, for GCR this is project-id/repo
  323. // need to use wildcard, see https://github.com/go-chi/chi/issues/243
  324. "/projects/{project_id}/registries/{registry_id}/repositories/*",
  325. auth.DoesUserHaveProjectAccess(
  326. auth.DoesUserHaveRegistryAccess(
  327. requestlog.NewHandler(a.HandleListImages, l),
  328. mw.URLParam,
  329. mw.URLParam,
  330. ),
  331. mw.URLParam,
  332. mw.WriteAccess,
  333. ),
  334. )
  335. // /api/projects/{project_id}/releases routes
  336. r.Method(
  337. "GET",
  338. "/projects/{project_id}/releases",
  339. auth.DoesUserHaveProjectAccess(
  340. auth.DoesUserHaveClusterAccess(
  341. requestlog.NewHandler(a.HandleListReleases, l),
  342. mw.URLParam,
  343. mw.QueryParam,
  344. ),
  345. mw.URLParam,
  346. mw.ReadAccess,
  347. ),
  348. )
  349. r.Method(
  350. "GET",
  351. "/projects/{project_id}/releases/{name}/{revision}/components",
  352. auth.DoesUserHaveProjectAccess(
  353. auth.DoesUserHaveClusterAccess(
  354. requestlog.NewHandler(a.HandleGetReleaseComponents, l),
  355. mw.URLParam,
  356. mw.QueryParam,
  357. ),
  358. mw.URLParam,
  359. mw.ReadAccess,
  360. ),
  361. )
  362. r.Method(
  363. "GET",
  364. "/projects/{project_id}/releases/{name}/{revision}/controllers",
  365. auth.DoesUserHaveProjectAccess(
  366. auth.DoesUserHaveClusterAccess(
  367. requestlog.NewHandler(a.HandleGetReleaseControllers, l),
  368. mw.URLParam,
  369. mw.QueryParam,
  370. ),
  371. mw.URLParam,
  372. mw.ReadAccess,
  373. ),
  374. )
  375. r.Method(
  376. "GET",
  377. "/projects/{project_id}/releases/{name}/history",
  378. auth.DoesUserHaveProjectAccess(
  379. auth.DoesUserHaveClusterAccess(
  380. requestlog.NewHandler(a.HandleListReleaseHistory, l),
  381. mw.URLParam,
  382. mw.QueryParam,
  383. ),
  384. mw.URLParam,
  385. mw.ReadAccess,
  386. ),
  387. )
  388. r.Method(
  389. "POST",
  390. "/projects/{project_id}/releases/{name}/upgrade",
  391. auth.DoesUserHaveProjectAccess(
  392. auth.DoesUserHaveClusterAccess(
  393. requestlog.NewHandler(a.HandleUpgradeRelease, l),
  394. mw.URLParam,
  395. mw.QueryParam,
  396. ),
  397. mw.URLParam,
  398. mw.ReadAccess,
  399. ),
  400. )
  401. r.Method(
  402. "GET",
  403. "/projects/{project_id}/releases/{name}/{revision}",
  404. auth.DoesUserHaveProjectAccess(
  405. auth.DoesUserHaveClusterAccess(
  406. requestlog.NewHandler(a.HandleGetRelease, l),
  407. mw.URLParam,
  408. mw.QueryParam,
  409. ),
  410. mw.URLParam,
  411. mw.ReadAccess,
  412. ),
  413. )
  414. r.Method(
  415. "POST",
  416. "/projects/{project_id}/releases/{name}/rollback",
  417. auth.DoesUserHaveProjectAccess(
  418. auth.DoesUserHaveClusterAccess(
  419. requestlog.NewHandler(a.HandleRollbackRelease, l),
  420. mw.URLParam,
  421. mw.QueryParam,
  422. ),
  423. mw.URLParam,
  424. mw.ReadAccess,
  425. ),
  426. )
  427. // /api/projects/{project_id}/repos routes
  428. // r.Method(
  429. // "GET",
  430. // "/projects/{project_id}/repos",
  431. // auth.DoesUserHaveProjectAccess(
  432. // requestlog.NewHandler(a.HandleListRepos, l),
  433. // mw.URLParam,
  434. // mw.ReadAccess,
  435. // ),
  436. // )
  437. // r.Method(
  438. // "GET",
  439. // "/projects/{project_id}/repos/{kind}/{name}/branches",
  440. // auth.DoesUserHaveProjectAccess(
  441. // requestlog.NewHandler(a.HandleGetBranches, l),
  442. // mw.URLParam,
  443. // mw.ReadAccess,
  444. // ),
  445. // )
  446. // r.Method(
  447. // "GET",
  448. // "/projects/{project_id}/repos/{kind}/{name}/{branch}/contents",
  449. // auth.DoesUserHaveProjectAccess(
  450. // requestlog.NewHandler(a.HandleGetBranchContents, l),
  451. // mw.URLParam,
  452. // mw.ReadAccess,
  453. // ),
  454. // )
  455. // /api/projects/{project_id}/deploy routes
  456. r.Method(
  457. "POST",
  458. "/projects/{project_id}/deploy/{name}/{version}",
  459. auth.DoesUserHaveProjectAccess(
  460. auth.DoesUserHaveClusterAccess(
  461. requestlog.NewHandler(a.HandleDeployTemplate, l),
  462. mw.URLParam,
  463. mw.QueryParam,
  464. ),
  465. mw.URLParam,
  466. mw.ReadAccess,
  467. ),
  468. )
  469. // /api/projects/{project_id}/k8s routes
  470. r.Method(
  471. "GET",
  472. "/projects/{project_id}/k8s/namespaces",
  473. auth.DoesUserHaveProjectAccess(
  474. auth.DoesUserHaveClusterAccess(
  475. requestlog.NewHandler(a.HandleListNamespaces, l),
  476. mw.URLParam,
  477. mw.QueryParam,
  478. ),
  479. mw.URLParam,
  480. mw.ReadAccess,
  481. ),
  482. )
  483. r.Method(
  484. "GET",
  485. "/projects/{project_id}/k8s/{namespace}/pod/{name}/logs",
  486. auth.DoesUserHaveProjectAccess(
  487. auth.DoesUserHaveClusterAccess(
  488. requestlog.NewHandler(a.HandleGetPodLogs, l),
  489. mw.URLParam,
  490. mw.QueryParam,
  491. ),
  492. mw.URLParam,
  493. mw.ReadAccess,
  494. ),
  495. )
  496. r.Method(
  497. "GET",
  498. "/projects/{project_id}/k8s/{kind}/status",
  499. auth.DoesUserHaveProjectAccess(
  500. auth.DoesUserHaveClusterAccess(
  501. requestlog.NewHandler(a.HandleStreamControllerStatus, l),
  502. mw.URLParam,
  503. mw.QueryParam,
  504. ),
  505. mw.URLParam,
  506. mw.ReadAccess,
  507. ),
  508. )
  509. r.Method(
  510. "GET",
  511. "/projects/{project_id}/k8s/pods",
  512. auth.DoesUserHaveProjectAccess(
  513. auth.DoesUserHaveClusterAccess(
  514. requestlog.NewHandler(a.HandleListPods, l),
  515. mw.URLParam,
  516. mw.QueryParam,
  517. ),
  518. mw.URLParam,
  519. mw.ReadAccess,
  520. ),
  521. )
  522. })
  523. fs := http.FileServer(http.Dir(staticFilePath))
  524. r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
  525. if _, err := os.Stat(staticFilePath + r.RequestURI); os.IsNotExist(err) {
  526. http.StripPrefix(r.URL.Path, fs).ServeHTTP(w, r)
  527. } else {
  528. fs.ServeHTTP(w, r)
  529. }
  530. })
  531. return r
  532. }