integration_handler.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. package api
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "net/url"
  6. "strconv"
  7. "github.com/go-chi/chi"
  8. "github.com/porter-dev/porter/internal/forms"
  9. "github.com/porter-dev/porter/internal/models/integrations"
  10. ints "github.com/porter-dev/porter/internal/models/integrations"
  11. )
  12. // HandleListClusterIntegrations lists the cluster integrations available to the
  13. // instance
  14. func (app *App) HandleListClusterIntegrations(w http.ResponseWriter, r *http.Request) {
  15. clusters := ints.PorterClusterIntegrations
  16. w.WriteHeader(http.StatusOK)
  17. if err := json.NewEncoder(w).Encode(&clusters); err != nil {
  18. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  19. return
  20. }
  21. }
  22. // HandleListRegistryIntegrations lists the image registry integrations available to the
  23. // instance
  24. func (app *App) HandleListRegistryIntegrations(w http.ResponseWriter, r *http.Request) {
  25. registries := ints.PorterRegistryIntegrations
  26. w.WriteHeader(http.StatusOK)
  27. if err := json.NewEncoder(w).Encode(&registries); err != nil {
  28. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  29. return
  30. }
  31. }
  32. // HandleListHelmRepoIntegrations lists the Helm repo integrations available to the
  33. // instance
  34. func (app *App) HandleListHelmRepoIntegrations(w http.ResponseWriter, r *http.Request) {
  35. hrs := ints.PorterHelmRepoIntegrations
  36. w.WriteHeader(http.StatusOK)
  37. if err := json.NewEncoder(w).Encode(&hrs); err != nil {
  38. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  39. return
  40. }
  41. }
  42. // HandleListRepoIntegrations lists the repo integrations available to the
  43. // instance
  44. func (app *App) HandleListRepoIntegrations(w http.ResponseWriter, r *http.Request) {
  45. repos := ints.PorterGitRepoIntegrations
  46. w.WriteHeader(http.StatusOK)
  47. if err := json.NewEncoder(w).Encode(&repos); err != nil {
  48. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  49. return
  50. }
  51. }
  52. // HandleCreateGCPIntegration creates a new GCP integration in the DB
  53. func (app *App) HandleCreateGCPIntegration(w http.ResponseWriter, r *http.Request) {
  54. userID, err := app.getUserIDFromRequest(r)
  55. if err != nil {
  56. http.Error(w, err.Error(), http.StatusInternalServerError)
  57. return
  58. }
  59. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  60. if err != nil || projID == 0 {
  61. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  62. return
  63. }
  64. form := &forms.CreateGCPIntegrationForm{
  65. UserID: userID,
  66. ProjectID: uint(projID),
  67. }
  68. // decode from JSON to form value
  69. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  70. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  71. return
  72. }
  73. // validate the form
  74. if err := app.validator.Struct(form); err != nil {
  75. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  76. return
  77. }
  78. // convert the form to a gcp integration
  79. gcp, err := form.ToGCPIntegration()
  80. if err != nil {
  81. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  82. return
  83. }
  84. // handle write to the database
  85. gcp, err = app.Repo.GCPIntegration.CreateGCPIntegration(gcp)
  86. if err != nil {
  87. app.handleErrorDataWrite(err, w)
  88. return
  89. }
  90. app.Logger.Info().Msgf("New gcp integration created: %d", gcp.ID)
  91. w.WriteHeader(http.StatusCreated)
  92. gcpExt := gcp.Externalize()
  93. if err := json.NewEncoder(w).Encode(gcpExt); err != nil {
  94. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  95. return
  96. }
  97. }
  98. // HandleCreateAWSIntegration creates a new AWS integration in the DB
  99. func (app *App) HandleCreateAWSIntegration(w http.ResponseWriter, r *http.Request) {
  100. userID, err := app.getUserIDFromRequest(r)
  101. if err != nil {
  102. http.Error(w, err.Error(), http.StatusInternalServerError)
  103. return
  104. }
  105. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  106. if err != nil || projID == 0 {
  107. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  108. return
  109. }
  110. form := &forms.CreateAWSIntegrationForm{
  111. UserID: userID,
  112. ProjectID: uint(projID),
  113. }
  114. // decode from JSON to form value
  115. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  116. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  117. return
  118. }
  119. // validate the form
  120. if err := app.validator.Struct(form); err != nil {
  121. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  122. return
  123. }
  124. // convert the form to a aws integration
  125. aws, err := form.ToAWSIntegration()
  126. if err != nil {
  127. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  128. return
  129. }
  130. // handle write to the database
  131. aws, err = app.Repo.AWSIntegration.CreateAWSIntegration(aws)
  132. if err != nil {
  133. app.handleErrorDataWrite(err, w)
  134. return
  135. }
  136. app.Logger.Info().Msgf("New aws integration created: %d", aws.ID)
  137. w.WriteHeader(http.StatusCreated)
  138. awsExt := aws.Externalize()
  139. if err := json.NewEncoder(w).Encode(awsExt); err != nil {
  140. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  141. return
  142. }
  143. }
  144. // HandleOverwriteAWSIntegration overwrites the ID of an AWS integration in the DB
  145. func (app *App) HandleOverwriteAWSIntegration(w http.ResponseWriter, r *http.Request) {
  146. userID, err := app.getUserIDFromRequest(r)
  147. if err != nil {
  148. http.Error(w, err.Error(), http.StatusInternalServerError)
  149. return
  150. }
  151. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  152. if err != nil || projID == 0 {
  153. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  154. return
  155. }
  156. awsIntegrationID, err := strconv.ParseUint(chi.URLParam(r, "aws_integration_id"), 0, 64)
  157. if err != nil || awsIntegrationID == 0 {
  158. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  159. return
  160. }
  161. form := &forms.OverwriteAWSIntegrationForm{
  162. UserID: userID,
  163. ProjectID: uint(projID),
  164. }
  165. // decode from JSON to form value
  166. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  167. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  168. return
  169. }
  170. // validate the form
  171. if err := app.validator.Struct(form); err != nil {
  172. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  173. return
  174. }
  175. // read the aws integration by ID and overwrite the access id/secret
  176. awsIntegration, err := app.Repo.AWSIntegration.ReadAWSIntegration(uint(awsIntegrationID))
  177. if err != nil {
  178. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  179. return
  180. }
  181. awsIntegration.AWSAccessKeyID = []byte(form.AWSAccessKeyID)
  182. awsIntegration.AWSSecretAccessKey = []byte(form.AWSSecretAccessKey)
  183. // handle write to the database
  184. awsIntegration, err = app.Repo.AWSIntegration.OverwriteAWSIntegration(awsIntegration)
  185. if err != nil {
  186. app.handleErrorDataWrite(err, w)
  187. return
  188. }
  189. // clear the cluster token cache if cluster_id exists
  190. vals, err := url.ParseQuery(r.URL.RawQuery)
  191. if err != nil {
  192. app.handleErrorDataWrite(err, w)
  193. return
  194. }
  195. if len(vals["cluster_id"]) > 0 {
  196. clusterID, err := strconv.ParseUint(vals["cluster_id"][0], 10, 64)
  197. if err != nil {
  198. app.handleErrorDataWrite(err, w)
  199. return
  200. }
  201. cluster, err := app.Repo.Cluster.ReadCluster(uint(clusterID))
  202. // clear the token
  203. cluster.TokenCache.Token = []byte("")
  204. cluster, err = app.Repo.Cluster.UpdateClusterTokenCache(&cluster.TokenCache)
  205. if err != nil {
  206. app.handleErrorDataWrite(err, w)
  207. return
  208. }
  209. }
  210. app.Logger.Info().Msgf("AWS integration overwritten: %d", awsIntegration.ID)
  211. w.WriteHeader(http.StatusCreated)
  212. awsExt := awsIntegration.Externalize()
  213. if err := json.NewEncoder(w).Encode(awsExt); err != nil {
  214. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  215. return
  216. }
  217. }
  218. // HandleCreateBasicAuthIntegration creates a new basic auth integration in the DB
  219. func (app *App) HandleCreateBasicAuthIntegration(w http.ResponseWriter, r *http.Request) {
  220. userID, err := app.getUserIDFromRequest(r)
  221. if err != nil {
  222. http.Error(w, err.Error(), http.StatusInternalServerError)
  223. return
  224. }
  225. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  226. if err != nil || projID == 0 {
  227. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  228. return
  229. }
  230. form := &forms.CreateBasicAuthIntegrationForm{
  231. UserID: userID,
  232. ProjectID: uint(projID),
  233. }
  234. // decode from JSON to form value
  235. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  236. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  237. return
  238. }
  239. // validate the form
  240. if err := app.validator.Struct(form); err != nil {
  241. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  242. return
  243. }
  244. // convert the form to a gcp integration
  245. basic, err := form.ToBasicIntegration()
  246. if err != nil {
  247. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  248. return
  249. }
  250. // handle write to the database
  251. basic, err = app.Repo.BasicIntegration.CreateBasicIntegration(basic)
  252. if err != nil {
  253. app.handleErrorDataWrite(err, w)
  254. return
  255. }
  256. app.Logger.Info().Msgf("New basic integration created: %d", basic.ID)
  257. w.WriteHeader(http.StatusCreated)
  258. basicExt := basic.Externalize()
  259. if err := json.NewEncoder(w).Encode(basicExt); err != nil {
  260. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  261. return
  262. }
  263. }
  264. // HandleListProjectOAuthIntegrations lists the oauth integrations for the project
  265. func (app *App) HandleListProjectOAuthIntegrations(w http.ResponseWriter, r *http.Request) {
  266. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  267. if err != nil || projID == 0 {
  268. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  269. return
  270. }
  271. oauthInts, err := app.Repo.OAuthIntegration.ListOAuthIntegrationsByProjectID(uint(projID))
  272. if err != nil {
  273. app.handleErrorDataRead(err, w)
  274. return
  275. }
  276. res := make([]*integrations.OAuthIntegrationExternal, 0)
  277. for _, oauthInt := range oauthInts {
  278. res = append(res, oauthInt.Externalize())
  279. }
  280. w.WriteHeader(http.StatusOK)
  281. if err := json.NewEncoder(w).Encode(res); err != nil {
  282. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  283. return
  284. }
  285. }