auth.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. package middleware
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "io/ioutil"
  7. "net/http"
  8. "net/url"
  9. "strconv"
  10. "strings"
  11. "github.com/go-chi/chi"
  12. "github.com/gorilla/sessions"
  13. "github.com/porter-dev/porter/internal/auth/token"
  14. "github.com/porter-dev/porter/internal/models"
  15. "github.com/porter-dev/porter/internal/repository"
  16. )
  17. // Auth implements the authorization functions
  18. type Auth struct {
  19. store sessions.Store
  20. cookieName string
  21. tokenConf *token.TokenGeneratorConf
  22. repo *repository.Repository
  23. }
  24. // NewAuth returns a new Auth instance
  25. func NewAuth(
  26. store sessions.Store,
  27. cookieName string,
  28. tokenConf *token.TokenGeneratorConf,
  29. repo *repository.Repository,
  30. ) *Auth {
  31. return &Auth{store, cookieName, tokenConf, repo}
  32. }
  33. // BasicAuthenticate just checks that a user is logged in
  34. func (auth *Auth) BasicAuthenticate(next http.Handler) http.Handler {
  35. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  36. if auth.isLoggedIn(w, r) {
  37. next.ServeHTTP(w, r)
  38. } else {
  39. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  40. return
  41. }
  42. return
  43. })
  44. }
  45. // BasicAuthenticateWithRedirect checks that a user is logged in, and if they're not, the
  46. // user is redirected to the login page with the redirect path stored in the session
  47. func (auth *Auth) BasicAuthenticateWithRedirect(next http.Handler) http.Handler {
  48. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  49. if auth.isLoggedIn(w, r) {
  50. next.ServeHTTP(w, r)
  51. } else {
  52. session, err := auth.store.Get(r, auth.cookieName)
  53. if err != nil {
  54. http.Redirect(w, r, "/dashboard", 302)
  55. }
  56. // need state parameter to validate when redirected
  57. if r.URL.RawQuery == "" {
  58. session.Values["redirect"] = r.URL.Path
  59. } else {
  60. session.Values["redirect"] = r.URL.Path + "?" + r.URL.RawQuery
  61. }
  62. session.Save(r, w)
  63. http.Redirect(w, r, "/dashboard", 302)
  64. return
  65. }
  66. return
  67. })
  68. }
  69. // IDLocation represents the location of the ID to use for authentication
  70. type IDLocation uint
  71. const (
  72. // URLParam location looks for a parameter in the URL endpoint
  73. URLParam IDLocation = iota
  74. // BodyParam location looks for a parameter in the body
  75. BodyParam
  76. // QueryParam location looks for a parameter in the query string
  77. QueryParam
  78. )
  79. type bodyUserID struct {
  80. UserID uint64 `json:"user_id"`
  81. }
  82. type bodyProjectID struct {
  83. ProjectID uint64 `json:"project_id"`
  84. }
  85. type bodyClusterID struct {
  86. ClusterID uint64 `json:"cluster_id"`
  87. }
  88. type bodyRegistryID struct {
  89. RegistryID uint64 `json:"registry_id"`
  90. }
  91. type bodyGitRepoID struct {
  92. GitRepoID uint64 `json:"git_repo_id"`
  93. }
  94. type bodyInfraID struct {
  95. InfraID uint64 `json:"infra_id"`
  96. }
  97. type bodyInviteID struct {
  98. InviteID uint64 `json:"invite_id"`
  99. }
  100. type bodyAWSIntegrationID struct {
  101. AWSIntegrationID uint64 `json:"aws_integration_id"`
  102. }
  103. type bodyGCPIntegrationID struct {
  104. GCPIntegrationID uint64 `json:"gcp_integration_id"`
  105. }
  106. type bodyDOIntegrationID struct {
  107. DOIntegrationID uint64 `json:"do_integration_id"`
  108. }
  109. // DoesUserIDMatch checks the id URL parameter and verifies that it matches
  110. // the one stored in the session
  111. func (auth *Auth) DoesUserIDMatch(next http.Handler, loc IDLocation) http.Handler {
  112. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  113. var err error
  114. id, err := findUserIDInRequest(r, loc)
  115. // first check for token
  116. tok := auth.getTokenFromRequest(r)
  117. if err != nil {
  118. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  119. return
  120. } else if tok != nil && tok.IBy == uint(id) {
  121. next.ServeHTTP(w, r)
  122. return
  123. } else if auth.doesSessionMatchID(r, uint(id)) {
  124. next.ServeHTTP(w, r)
  125. } else {
  126. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  127. return
  128. }
  129. return
  130. })
  131. }
  132. // AccessType represents the various access types for a project
  133. type AccessType string
  134. // The various access types
  135. const (
  136. AdminAccess AccessType = "admin"
  137. ReadAccess AccessType = "read"
  138. WriteAccess AccessType = "write"
  139. )
  140. // DoesUserHaveProjectAccess looks for a project_id parameter and checks that the
  141. // user has access via the specified accessType
  142. func (auth *Auth) DoesUserHaveProjectAccess(
  143. next http.Handler,
  144. projLoc IDLocation,
  145. accessType AccessType,
  146. ) http.Handler {
  147. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  148. var err error
  149. projID, err := findProjIDInRequest(r, projLoc)
  150. if err != nil {
  151. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  152. return
  153. }
  154. // first check for token
  155. tok := auth.getTokenFromRequest(r)
  156. var userID uint
  157. if tok != nil && tok.ProjectID != 0 && tok.ProjectID == uint(projID) {
  158. next.ServeHTTP(w, r)
  159. return
  160. } else if tok != nil {
  161. userID = tok.IBy
  162. } else {
  163. session, err := auth.store.Get(r, auth.cookieName)
  164. if err != nil {
  165. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  166. return
  167. }
  168. sessionUserID, ok := session.Values["user_id"]
  169. userID = sessionUserID.(uint)
  170. if !ok {
  171. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  172. return
  173. }
  174. }
  175. // get the project
  176. proj, err := auth.repo.Project.ReadProject(uint(projID))
  177. if err != nil {
  178. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  179. return
  180. }
  181. // look for the user role in the project
  182. for _, role := range proj.Roles {
  183. if role.UserID == userID {
  184. if accessType == AdminAccess {
  185. if role.Kind == models.RoleAdmin {
  186. next.ServeHTTP(w, r)
  187. return
  188. }
  189. } else if accessType == WriteAccess {
  190. if role.Kind == models.RoleAdmin || role.Kind == models.RoleDeveloper {
  191. next.ServeHTTP(w, r)
  192. return
  193. }
  194. } else if accessType == ReadAccess {
  195. next.ServeHTTP(w, r)
  196. return
  197. }
  198. }
  199. }
  200. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  201. return
  202. })
  203. }
  204. // DoesUserHaveClusterAccess looks for a project_id parameter and a
  205. // cluster_id parameter, and verifies that the cluster belongs
  206. // to the project
  207. func (auth *Auth) DoesUserHaveClusterAccess(
  208. next http.Handler,
  209. projLoc IDLocation,
  210. clusterLoc IDLocation,
  211. ) http.Handler {
  212. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  213. clusterID, err := findClusterIDInRequest(r, clusterLoc)
  214. if err != nil {
  215. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  216. return
  217. }
  218. projID, err := findProjIDInRequest(r, projLoc)
  219. if err != nil {
  220. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  221. return
  222. }
  223. // get the service accounts belonging to the project
  224. clusters, err := auth.repo.Cluster.ListClustersByProjectID(uint(projID))
  225. if err != nil {
  226. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  227. return
  228. }
  229. doesExist := false
  230. for _, cluster := range clusters {
  231. if cluster.ID == uint(clusterID) {
  232. doesExist = true
  233. break
  234. }
  235. }
  236. if doesExist {
  237. next.ServeHTTP(w, r)
  238. return
  239. }
  240. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  241. return
  242. })
  243. }
  244. // DoesUserHaveInviteAccess looks for a project_id parameter and a
  245. // invite_id parameter, and verifies that the invite belongs
  246. // to the project
  247. func (auth *Auth) DoesUserHaveInviteAccess(
  248. next http.Handler,
  249. projLoc IDLocation,
  250. inviteLoc IDLocation,
  251. ) http.Handler {
  252. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  253. inviteID, err := findInviteIDInRequest(r, inviteLoc)
  254. if err != nil {
  255. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  256. return
  257. }
  258. projID, err := findProjIDInRequest(r, projLoc)
  259. if err != nil {
  260. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  261. return
  262. }
  263. // get the service accounts belonging to the project
  264. invites, err := auth.repo.Invite.ListInvitesByProjectID(uint(projID))
  265. if err != nil {
  266. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  267. return
  268. }
  269. doesExist := false
  270. for _, invite := range invites {
  271. if invite.ID == uint(inviteID) {
  272. doesExist = true
  273. break
  274. }
  275. }
  276. if doesExist {
  277. next.ServeHTTP(w, r)
  278. return
  279. }
  280. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  281. return
  282. })
  283. }
  284. // DoesUserHaveRegistryAccess looks for a project_id parameter and a
  285. // registry_id parameter, and verifies that the registry belongs
  286. // to the project
  287. func (auth *Auth) DoesUserHaveRegistryAccess(
  288. next http.Handler,
  289. projLoc IDLocation,
  290. registryLoc IDLocation,
  291. ) http.Handler {
  292. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  293. regID, err := findRegistryIDInRequest(r, registryLoc)
  294. if err != nil {
  295. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  296. return
  297. }
  298. projID, err := findProjIDInRequest(r, projLoc)
  299. if err != nil {
  300. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  301. return
  302. }
  303. // get the service accounts belonging to the project
  304. regs, err := auth.repo.Registry.ListRegistriesByProjectID(uint(projID))
  305. if err != nil {
  306. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  307. return
  308. }
  309. doesExist := false
  310. for _, reg := range regs {
  311. if reg.ID == uint(regID) {
  312. doesExist = true
  313. break
  314. }
  315. }
  316. if doesExist {
  317. next.ServeHTTP(w, r)
  318. return
  319. }
  320. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  321. return
  322. })
  323. }
  324. // DoesUserHaveGitRepoAccess looks for a project_id parameter and a
  325. // git_repo_id parameter, and verifies that the git repo belongs
  326. // to the project
  327. func (auth *Auth) DoesUserHaveGitRepoAccess(
  328. next http.Handler,
  329. projLoc IDLocation,
  330. gitRepoLoc IDLocation,
  331. ) http.Handler {
  332. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  333. grID, err := findGitRepoIDInRequest(r, gitRepoLoc)
  334. if err != nil {
  335. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  336. return
  337. }
  338. projID, err := findProjIDInRequest(r, projLoc)
  339. if err != nil {
  340. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  341. return
  342. }
  343. // get the service accounts belonging to the project
  344. grs, err := auth.repo.GitRepo.ListGitReposByProjectID(uint(projID))
  345. if err != nil {
  346. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  347. return
  348. }
  349. doesExist := false
  350. for _, gr := range grs {
  351. if gr.ID == uint(grID) {
  352. doesExist = true
  353. break
  354. }
  355. }
  356. if doesExist {
  357. next.ServeHTTP(w, r)
  358. return
  359. }
  360. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  361. return
  362. })
  363. }
  364. // DoesUserHaveInfraAccess looks for a project_id parameter and an
  365. // infra_id parameter, and verifies that the infra belongs
  366. // to the project
  367. func (auth *Auth) DoesUserHaveInfraAccess(
  368. next http.Handler,
  369. projLoc IDLocation,
  370. infraLoc IDLocation,
  371. ) http.Handler {
  372. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  373. infraID, err := findInfraIDInRequest(r, infraLoc)
  374. if err != nil {
  375. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  376. return
  377. }
  378. projID, err := findProjIDInRequest(r, projLoc)
  379. if err != nil {
  380. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  381. return
  382. }
  383. infras, err := auth.repo.Infra.ListInfrasByProjectID(uint(projID))
  384. if err != nil {
  385. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  386. return
  387. }
  388. doesExist := false
  389. for _, infra := range infras {
  390. if infra.ID == uint(infraID) {
  391. doesExist = true
  392. break
  393. }
  394. }
  395. if doesExist {
  396. next.ServeHTTP(w, r)
  397. return
  398. }
  399. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  400. return
  401. })
  402. }
  403. // DoesUserHaveAWSIntegrationAccess looks for a project_id parameter and an
  404. // aws_integration_id parameter, and verifies that the infra belongs
  405. // to the project
  406. func (auth *Auth) DoesUserHaveAWSIntegrationAccess(
  407. next http.Handler,
  408. projLoc IDLocation,
  409. awsLoc IDLocation,
  410. optional bool,
  411. ) http.Handler {
  412. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  413. awsID, err := findAWSIntegrationIDInRequest(r, awsLoc)
  414. if awsID == 0 && optional {
  415. next.ServeHTTP(w, r)
  416. return
  417. }
  418. if awsID == 0 || err != nil {
  419. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  420. return
  421. }
  422. projID, err := findProjIDInRequest(r, projLoc)
  423. if err != nil {
  424. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  425. return
  426. }
  427. awsInts, err := auth.repo.AWSIntegration.ListAWSIntegrationsByProjectID(uint(projID))
  428. if err != nil {
  429. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  430. return
  431. }
  432. doesExist := false
  433. for _, awsInt := range awsInts {
  434. if awsInt.ID == uint(awsID) {
  435. doesExist = true
  436. break
  437. }
  438. }
  439. if doesExist {
  440. next.ServeHTTP(w, r)
  441. return
  442. }
  443. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  444. return
  445. })
  446. }
  447. // DoesUserHaveGCPIntegrationAccess looks for a project_id parameter and an
  448. // gcp_integration_id parameter, and verifies that the infra belongs
  449. // to the project
  450. func (auth *Auth) DoesUserHaveGCPIntegrationAccess(
  451. next http.Handler,
  452. projLoc IDLocation,
  453. gcpLoc IDLocation,
  454. optional bool,
  455. ) http.Handler {
  456. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  457. gcpID, err := findGCPIntegrationIDInRequest(r, gcpLoc)
  458. if gcpID == 0 && optional {
  459. next.ServeHTTP(w, r)
  460. return
  461. }
  462. if gcpID == 0 || err != nil {
  463. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  464. return
  465. }
  466. projID, err := findProjIDInRequest(r, projLoc)
  467. if err != nil {
  468. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  469. return
  470. }
  471. gcpInts, err := auth.repo.GCPIntegration.ListGCPIntegrationsByProjectID(uint(projID))
  472. if err != nil {
  473. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  474. return
  475. }
  476. doesExist := false
  477. for _, awsInt := range gcpInts {
  478. if awsInt.ID == uint(gcpID) {
  479. doesExist = true
  480. break
  481. }
  482. }
  483. if doesExist {
  484. next.ServeHTTP(w, r)
  485. return
  486. }
  487. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  488. return
  489. })
  490. }
  491. // DoesUserHaveDOIntegrationAccess looks for a project_id parameter and an
  492. // do_integration_id parameter, and verifies that the infra belongs
  493. // to the project
  494. func (auth *Auth) DoesUserHaveDOIntegrationAccess(
  495. next http.Handler,
  496. projLoc IDLocation,
  497. doLoc IDLocation,
  498. optional bool,
  499. ) http.Handler {
  500. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  501. doID, err := findDOIntegrationIDInRequest(r, doLoc)
  502. if doID == 0 && optional {
  503. next.ServeHTTP(w, r)
  504. return
  505. }
  506. if doID == 0 || err != nil {
  507. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  508. return
  509. }
  510. projID, err := findProjIDInRequest(r, projLoc)
  511. if err != nil {
  512. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  513. return
  514. }
  515. oauthInts, err := auth.repo.OAuthIntegration.ListOAuthIntegrationsByProjectID(uint(projID))
  516. if err != nil {
  517. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  518. return
  519. }
  520. doesExist := false
  521. for _, oauthInt := range oauthInts {
  522. if oauthInt.ID == uint(doID) {
  523. doesExist = true
  524. break
  525. }
  526. }
  527. if doesExist {
  528. next.ServeHTTP(w, r)
  529. return
  530. }
  531. http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
  532. return
  533. })
  534. }
  535. // Helpers
  536. func (auth *Auth) doesSessionMatchID(r *http.Request, id uint) bool {
  537. session, _ := auth.store.Get(r, auth.cookieName)
  538. if sessID, ok := session.Values["user_id"].(uint); !ok || sessID != id {
  539. return false
  540. }
  541. return true
  542. }
  543. func (auth *Auth) isLoggedIn(w http.ResponseWriter, r *http.Request) bool {
  544. // first check for Bearer token
  545. tok := auth.getTokenFromRequest(r)
  546. if tok != nil {
  547. return true
  548. }
  549. session, err := auth.store.Get(r, auth.cookieName)
  550. if err != nil {
  551. session.Values["authenticated"] = false
  552. if err := session.Save(r, w); err != nil {
  553. return false
  554. }
  555. return false
  556. }
  557. if auth, ok := session.Values["authenticated"].(bool); !auth || !ok {
  558. return false
  559. }
  560. return true
  561. }
  562. func (auth *Auth) getTokenFromRequest(r *http.Request) *token.Token {
  563. reqToken := r.Header.Get("Authorization")
  564. splitToken := strings.Split(reqToken, "Bearer")
  565. if len(splitToken) != 2 {
  566. return nil
  567. }
  568. reqToken = strings.TrimSpace(splitToken[1])
  569. tok, err := token.GetTokenFromEncoded(reqToken, auth.tokenConf)
  570. if err != nil {
  571. return nil
  572. }
  573. return tok
  574. }
  575. func findUserIDInRequest(r *http.Request, userLoc IDLocation) (uint64, error) {
  576. var userID uint64
  577. var err error
  578. if userLoc == URLParam {
  579. userID, err = strconv.ParseUint(chi.URLParam(r, "user_id"), 0, 64)
  580. if err != nil {
  581. return 0, err
  582. }
  583. } else if userLoc == BodyParam {
  584. form := &bodyUserID{}
  585. body, err := ioutil.ReadAll(r.Body)
  586. if err != nil {
  587. return 0, err
  588. }
  589. err = json.Unmarshal(body, form)
  590. if err != nil {
  591. return 0, err
  592. }
  593. userID = form.UserID
  594. // need to create a new stream for the body
  595. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  596. } else {
  597. vals, err := url.ParseQuery(r.URL.RawQuery)
  598. if err != nil {
  599. return 0, err
  600. }
  601. if userStrArr, ok := vals["user_id"]; ok && len(userStrArr) == 1 {
  602. userID, err = strconv.ParseUint(userStrArr[0], 10, 64)
  603. } else {
  604. return 0, errors.New("user id not found")
  605. }
  606. }
  607. return userID, nil
  608. }
  609. func findProjIDInRequest(r *http.Request, projLoc IDLocation) (uint64, error) {
  610. var projID uint64
  611. var err error
  612. if projLoc == URLParam {
  613. projID, err = strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  614. if err != nil {
  615. return 0, err
  616. }
  617. } else if projLoc == BodyParam {
  618. form := &bodyProjectID{}
  619. body, err := ioutil.ReadAll(r.Body)
  620. if err != nil {
  621. return 0, err
  622. }
  623. err = json.Unmarshal(body, form)
  624. if err != nil {
  625. return 0, err
  626. }
  627. projID = form.ProjectID
  628. // need to create a new stream for the body
  629. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  630. } else {
  631. vals, err := url.ParseQuery(r.URL.RawQuery)
  632. if err != nil {
  633. return 0, err
  634. }
  635. if projStrArr, ok := vals["project_id"]; ok && len(projStrArr) == 1 {
  636. projID, err = strconv.ParseUint(projStrArr[0], 10, 64)
  637. } else {
  638. return 0, errors.New("project id not found")
  639. }
  640. }
  641. return projID, nil
  642. }
  643. func findClusterIDInRequest(r *http.Request, clusterLoc IDLocation) (uint64, error) {
  644. var clusterID uint64
  645. var err error
  646. if clusterLoc == URLParam {
  647. clusterID, err = strconv.ParseUint(chi.URLParam(r, "cluster_id"), 0, 64)
  648. if err != nil {
  649. return 0, err
  650. }
  651. } else if clusterLoc == BodyParam {
  652. form := &bodyClusterID{}
  653. body, err := ioutil.ReadAll(r.Body)
  654. if err != nil {
  655. return 0, err
  656. }
  657. err = json.Unmarshal(body, form)
  658. if err != nil {
  659. return 0, err
  660. }
  661. clusterID = form.ClusterID
  662. // need to create a new stream for the body
  663. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  664. } else {
  665. vals, err := url.ParseQuery(r.URL.RawQuery)
  666. if err != nil {
  667. return 0, err
  668. }
  669. if clStrArr, ok := vals["cluster_id"]; ok && len(clStrArr) == 1 {
  670. clusterID, err = strconv.ParseUint(clStrArr[0], 10, 64)
  671. } else {
  672. return 0, errors.New("cluster id not found")
  673. }
  674. }
  675. return clusterID, nil
  676. }
  677. func findInviteIDInRequest(r *http.Request, inviteLoc IDLocation) (uint64, error) {
  678. var inviteID uint64
  679. var err error
  680. if inviteLoc == URLParam {
  681. inviteID, err = strconv.ParseUint(chi.URLParam(r, "invite_id"), 0, 64)
  682. if err != nil {
  683. return 0, err
  684. }
  685. } else if inviteLoc == BodyParam {
  686. form := &bodyInviteID{}
  687. body, err := ioutil.ReadAll(r.Body)
  688. if err != nil {
  689. return 0, err
  690. }
  691. err = json.Unmarshal(body, form)
  692. if err != nil {
  693. return 0, err
  694. }
  695. inviteID = form.InviteID
  696. // need to create a new stream for the body
  697. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  698. } else {
  699. vals, err := url.ParseQuery(r.URL.RawQuery)
  700. if err != nil {
  701. return 0, err
  702. }
  703. if invStrArr, ok := vals["invite_id"]; ok && len(invStrArr) == 1 {
  704. inviteID, err = strconv.ParseUint(invStrArr[0], 10, 64)
  705. } else {
  706. return 0, errors.New("invite id not found")
  707. }
  708. }
  709. return inviteID, nil
  710. }
  711. func findRegistryIDInRequest(r *http.Request, registryLoc IDLocation) (uint64, error) {
  712. var regID uint64
  713. var err error
  714. if registryLoc == URLParam {
  715. regID, err = strconv.ParseUint(chi.URLParam(r, "registry_id"), 0, 64)
  716. if err != nil {
  717. return 0, err
  718. }
  719. } else if registryLoc == BodyParam {
  720. form := &bodyRegistryID{}
  721. body, err := ioutil.ReadAll(r.Body)
  722. if err != nil {
  723. return 0, err
  724. }
  725. err = json.Unmarshal(body, form)
  726. if err != nil {
  727. return 0, err
  728. }
  729. regID = form.RegistryID
  730. // need to create a new stream for the body
  731. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  732. } else {
  733. vals, err := url.ParseQuery(r.URL.RawQuery)
  734. if err != nil {
  735. return 0, err
  736. }
  737. if regStrArr, ok := vals["registry_id"]; ok && len(regStrArr) == 1 {
  738. regID, err = strconv.ParseUint(regStrArr[0], 10, 64)
  739. } else {
  740. return 0, errors.New("registry id not found")
  741. }
  742. }
  743. return regID, nil
  744. }
  745. func findGitRepoIDInRequest(r *http.Request, gitRepoLoc IDLocation) (uint64, error) {
  746. var grID uint64
  747. var err error
  748. if gitRepoLoc == URLParam {
  749. grID, err = strconv.ParseUint(chi.URLParam(r, "git_repo_id"), 0, 64)
  750. if err != nil {
  751. return 0, err
  752. }
  753. } else if gitRepoLoc == BodyParam {
  754. form := &bodyGitRepoID{}
  755. body, err := ioutil.ReadAll(r.Body)
  756. if err != nil {
  757. return 0, err
  758. }
  759. err = json.Unmarshal(body, form)
  760. if err != nil {
  761. return 0, err
  762. }
  763. grID = form.GitRepoID
  764. // need to create a new stream for the body
  765. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  766. } else {
  767. vals, err := url.ParseQuery(r.URL.RawQuery)
  768. if err != nil {
  769. return 0, err
  770. }
  771. if regStrArr, ok := vals["git_repo_id"]; ok && len(regStrArr) == 1 {
  772. grID, err = strconv.ParseUint(regStrArr[0], 10, 64)
  773. } else {
  774. return 0, errors.New("git repo id not found")
  775. }
  776. }
  777. return grID, nil
  778. }
  779. func findInfraIDInRequest(r *http.Request, infraLoc IDLocation) (uint64, error) {
  780. var infraID uint64
  781. var err error
  782. if infraLoc == URLParam {
  783. infraID, err = strconv.ParseUint(chi.URLParam(r, "infra_id"), 0, 64)
  784. if err != nil {
  785. return 0, err
  786. }
  787. } else if infraLoc == BodyParam {
  788. form := &bodyInfraID{}
  789. body, err := ioutil.ReadAll(r.Body)
  790. if err != nil {
  791. return 0, err
  792. }
  793. err = json.Unmarshal(body, form)
  794. if err != nil {
  795. return 0, err
  796. }
  797. infraID = form.InfraID
  798. // need to create a new stream for the body
  799. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  800. } else {
  801. vals, err := url.ParseQuery(r.URL.RawQuery)
  802. if err != nil {
  803. return 0, err
  804. }
  805. if regStrArr, ok := vals["infra_id"]; ok && len(regStrArr) == 1 {
  806. infraID, err = strconv.ParseUint(regStrArr[0], 10, 64)
  807. } else {
  808. return 0, errors.New("infra id not found")
  809. }
  810. }
  811. return infraID, nil
  812. }
  813. func findAWSIntegrationIDInRequest(r *http.Request, awsLoc IDLocation) (uint64, error) {
  814. var awsID uint64
  815. var err error
  816. if awsLoc == URLParam {
  817. awsID, err = strconv.ParseUint(chi.URLParam(r, "aws_integration_id"), 0, 64)
  818. if err != nil {
  819. return 0, err
  820. }
  821. } else if awsLoc == BodyParam {
  822. form := &bodyAWSIntegrationID{}
  823. body, err := ioutil.ReadAll(r.Body)
  824. if err != nil {
  825. return 0, err
  826. }
  827. err = json.Unmarshal(body, form)
  828. if err != nil {
  829. return 0, err
  830. }
  831. awsID = form.AWSIntegrationID
  832. // need to create a new stream for the body
  833. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  834. } else {
  835. vals, err := url.ParseQuery(r.URL.RawQuery)
  836. if err != nil {
  837. return 0, err
  838. }
  839. if regStrArr, ok := vals["aws_integration_id"]; ok && len(regStrArr) == 1 {
  840. awsID, err = strconv.ParseUint(regStrArr[0], 10, 64)
  841. } else {
  842. return 0, errors.New("aws integration id not found")
  843. }
  844. }
  845. return awsID, nil
  846. }
  847. func findGCPIntegrationIDInRequest(r *http.Request, gcpLoc IDLocation) (uint64, error) {
  848. var gcpID uint64
  849. var err error
  850. if gcpLoc == URLParam {
  851. gcpID, err = strconv.ParseUint(chi.URLParam(r, "gcp_integration_id"), 0, 64)
  852. if err != nil {
  853. return 0, err
  854. }
  855. } else if gcpLoc == BodyParam {
  856. form := &bodyGCPIntegrationID{}
  857. body, err := ioutil.ReadAll(r.Body)
  858. if err != nil {
  859. return 0, err
  860. }
  861. err = json.Unmarshal(body, form)
  862. if err != nil {
  863. return 0, err
  864. }
  865. gcpID = form.GCPIntegrationID
  866. // need to create a new stream for the body
  867. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  868. } else {
  869. vals, err := url.ParseQuery(r.URL.RawQuery)
  870. if err != nil {
  871. return 0, err
  872. }
  873. if regStrArr, ok := vals["gcp_integration_id"]; ok && len(regStrArr) == 1 {
  874. gcpID, err = strconv.ParseUint(regStrArr[0], 10, 64)
  875. } else {
  876. return 0, errors.New("gcp integration id not found")
  877. }
  878. }
  879. return gcpID, nil
  880. }
  881. func findDOIntegrationIDInRequest(r *http.Request, doLoc IDLocation) (uint64, error) {
  882. var doID uint64
  883. var err error
  884. if doLoc == URLParam {
  885. doID, err = strconv.ParseUint(chi.URLParam(r, "do_integration_id"), 0, 64)
  886. if err != nil {
  887. return 0, err
  888. }
  889. } else if doLoc == BodyParam {
  890. form := &bodyDOIntegrationID{}
  891. body, err := ioutil.ReadAll(r.Body)
  892. if err != nil {
  893. return 0, err
  894. }
  895. err = json.Unmarshal(body, form)
  896. if err != nil {
  897. return 0, err
  898. }
  899. doID = form.DOIntegrationID
  900. // need to create a new stream for the body
  901. r.Body = ioutil.NopCloser(bytes.NewReader(body))
  902. } else {
  903. vals, err := url.ParseQuery(r.URL.RawQuery)
  904. if err != nil {
  905. return 0, err
  906. }
  907. if regStrArr, ok := vals["do_integration_id"]; ok && len(regStrArr) == 1 {
  908. doID, err = strconv.ParseUint(regStrArr[0], 10, 64)
  909. } else {
  910. return 0, errors.New("do integration id not found")
  911. }
  912. }
  913. return doID, nil
  914. }