auth.go 24 KB

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