auth.go 25 KB

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