user_handler_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. package api_test
  2. // import (
  3. // "encoding/json"
  4. // "fmt"
  5. // "net/http"
  6. // "net/http/httptest"
  7. // "reflect"
  8. // "strings"
  9. // "testing"
  10. // "github.com/go-test/deep"
  11. // "github.com/porter-dev/porter/api/types"
  12. // "github.com/porter-dev/porter/internal/auth/token"
  13. // "github.com/porter-dev/porter/internal/models"
  14. // )
  15. // // ------------------------- TEST TYPES AND MAIN LOOP ------------------------- //
  16. // type userTest struct {
  17. // initializers []func(t *tester)
  18. // msg string
  19. // method string
  20. // endpoint string
  21. // body string
  22. // expStatus int
  23. // expBody string
  24. // useCookie bool
  25. // validators []func(c *userTest, tester *tester, t *testing.T)
  26. // }
  27. // func testUserRequests(t *testing.T, tests []*userTest, canQuery bool) {
  28. // for _, c := range tests {
  29. // // create a new tester
  30. // tester := newTester(canQuery)
  31. // // if there's an initializer, call it
  32. // for _, init := range c.initializers {
  33. // init(tester)
  34. // }
  35. // req, err := http.NewRequest(
  36. // c.method,
  37. // c.endpoint,
  38. // strings.NewReader(c.body),
  39. // )
  40. // tester.req = req
  41. // if c.useCookie {
  42. // req.AddCookie(tester.cookie)
  43. // }
  44. // if err != nil {
  45. // t.Fatal(err)
  46. // }
  47. // tester.execute()
  48. // rr := tester.rr
  49. // // first, check that the status matches
  50. // if status := rr.Code; status != c.expStatus {
  51. // t.Errorf("%s, handler returned wrong status code: got %v want %v",
  52. // c.msg, status, c.expStatus)
  53. // }
  54. // // if there's a validator, call it
  55. // for _, validate := range c.validators {
  56. // validate(c, tester, t)
  57. // }
  58. // }
  59. // }
  60. // // ------------------------- TEST FIXTURES AND FUNCTIONS ------------------------- //
  61. // var authCheckTests = []*userTest{
  62. // {
  63. // initializers: []func(tester *tester){
  64. // initUserDefault,
  65. // },
  66. // msg: "Auth check successful. User is logged in.",
  67. // method: "GET",
  68. // endpoint: "/api/auth/check",
  69. // expStatus: http.StatusOK,
  70. // body: "",
  71. // expBody: `{"id":1,"email":"belanger@getporter.dev","email_verified":false}`,
  72. // useCookie: true,
  73. // validators: []func(c *userTest, tester *tester, t *testing.T){
  74. // userBasicBodyValidator,
  75. // },
  76. // },
  77. // {
  78. // initializers: []func(tester *tester){
  79. // initUserDefault,
  80. // },
  81. // msg: "Auth check failure. User is not logged in.",
  82. // method: "GET",
  83. // endpoint: "/api/auth/check",
  84. // body: "",
  85. // expStatus: http.StatusForbidden,
  86. // expBody: http.StatusText(http.StatusForbidden) + "\n",
  87. // validators: []func(c *userTest, tester *tester, t *testing.T){
  88. // userBasicBodyValidator,
  89. // },
  90. // },
  91. // }
  92. // func TestHandleAuthCheck(t *testing.T) {
  93. // testUserRequests(t, authCheckTests, true)
  94. // }
  95. // func TestHandleAuthCheckToken(t *testing.T) {
  96. // tester := newTester(true)
  97. // initUserDefault(tester)
  98. // initProject(tester)
  99. // // generate a new token
  100. // tokGen, _ := token.GetTokenForAPI(1, 1)
  101. // tok, _ := tokGen.EncodeToken(&token.TokenGeneratorConf{
  102. // TokenSecret: "secret",
  103. // })
  104. // req, err := http.NewRequest(
  105. // "GET",
  106. // "/api/auth/check",
  107. // strings.NewReader(""),
  108. // )
  109. // tester.req = req
  110. // req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tok))
  111. // tester.execute()
  112. // rr := tester.rr
  113. // if err != nil {
  114. // t.Fatal(err)
  115. // }
  116. // // first, check that the status matches
  117. // if status := rr.Code; status != 200 {
  118. // t.Errorf("%s, handler returned wrong status code: got %v want %v",
  119. // "auth check token", status, 200)
  120. // }
  121. // gotBody := &models.UserExternal{}
  122. // expBody := &models.UserExternal{}
  123. // json.Unmarshal(tester.rr.Body.Bytes(), gotBody)
  124. // json.Unmarshal([]byte(`{"id":1,"email":"belanger@getporter.dev"}`), expBody)
  125. // if !reflect.DeepEqual(gotBody, expBody) {
  126. // t.Errorf("%s, handler returned wrong body: got %v want %v",
  127. // "auth check token", gotBody, expBody)
  128. // }
  129. // }
  130. // var createUserTests = []*userTest{
  131. // {
  132. // msg: "Create user",
  133. // method: "POST",
  134. // endpoint: "/api/users",
  135. // body: `{
  136. // "email": "belanger@getporter.dev",
  137. // "password": "hello"
  138. // }`,
  139. // expStatus: http.StatusCreated,
  140. // expBody: `{"id":1,"email":"belanger@getporter.dev"}`,
  141. // validators: []func(c *userTest, tester *tester, t *testing.T){
  142. // userModelBodyValidator,
  143. // },
  144. // },
  145. // {
  146. // msg: "Create user invalid email",
  147. // method: "POST",
  148. // endpoint: "/api/users",
  149. // body: `{
  150. // "email": "notanemail",
  151. // "password": "hello"
  152. // }`,
  153. // expStatus: http.StatusUnprocessableEntity,
  154. // expBody: `{"code":601,"errors":["email validation failed"]}`,
  155. // validators: []func(c *userTest, tester *tester, t *testing.T){
  156. // userBasicBodyValidator,
  157. // },
  158. // },
  159. // {
  160. // msg: "Create user missing field",
  161. // method: "POST",
  162. // endpoint: "/api/users",
  163. // body: `{
  164. // "password": "hello"
  165. // }`,
  166. // expStatus: http.StatusUnprocessableEntity,
  167. // expBody: `{"code":601,"errors":["required validation failed"]}`,
  168. // validators: []func(c *userTest, tester *tester, t *testing.T){
  169. // userBasicBodyValidator,
  170. // },
  171. // },
  172. // {
  173. // initializers: []func(tester *tester){
  174. // initUserDefault,
  175. // },
  176. // msg: "Create user same email",
  177. // method: "POST",
  178. // endpoint: "/api/users",
  179. // body: `{
  180. // "email": "belanger@getporter.dev",
  181. // "password": "hello"
  182. // }`,
  183. // expStatus: http.StatusUnprocessableEntity,
  184. // expBody: `{"code":601,"errors":["email already taken"]}`,
  185. // validators: []func(c *userTest, tester *tester, t *testing.T){
  186. // userBasicBodyValidator,
  187. // },
  188. // },
  189. // {
  190. // msg: "Create user invalid field type",
  191. // method: "POST",
  192. // endpoint: "/api/users",
  193. // body: `{
  194. // "email": "belanger@getporter.dev",
  195. // "password": 0
  196. // }`,
  197. // expStatus: http.StatusBadRequest,
  198. // expBody: `{"code":600,"errors":["could not process request"]}`,
  199. // validators: []func(c *userTest, tester *tester, t *testing.T){
  200. // userBasicBodyValidator,
  201. // },
  202. // },
  203. // }
  204. // func TestHandleCreateUser(t *testing.T) {
  205. // testUserRequests(t, createUserTests, true)
  206. // }
  207. // var createUserTestsWriteFail = []*userTest{
  208. // {
  209. // msg: "Create user db connection down",
  210. // method: "POST",
  211. // endpoint: "/api/users",
  212. // body: `{
  213. // "email": "belanger@getporter.dev",
  214. // "password": "hello"
  215. // }`,
  216. // expStatus: http.StatusInternalServerError,
  217. // expBody: `{"code":500,"errors":["could not read from database"]}`,
  218. // validators: []func(c *userTest, tester *tester, t *testing.T){
  219. // userBasicBodyValidator,
  220. // },
  221. // },
  222. // }
  223. // func TestHandleCreateUserWriteFail(t *testing.T) {
  224. // testUserRequests(t, createUserTestsWriteFail, false)
  225. // }
  226. // var loginUserTests = []*userTest{
  227. // {
  228. // initializers: []func(tester *tester){
  229. // initUserDefault,
  230. // },
  231. // msg: "Login user successful",
  232. // method: "POST",
  233. // endpoint: "/api/login",
  234. // body: `{
  235. // "email": "belanger@getporter.dev",
  236. // "password": "hello"
  237. // }`,
  238. // expStatus: http.StatusOK,
  239. // expBody: `{"id":1,"email":"belanger@getporter.dev","email_verified":false}`,
  240. // validators: []func(c *userTest, tester *tester, t *testing.T){
  241. // userBasicBodyValidator,
  242. // },
  243. // },
  244. // {
  245. // initializers: []func(tester *tester){
  246. // initUserDefault,
  247. // },
  248. // msg: "Login user already logged in",
  249. // method: "POST",
  250. // endpoint: "/api/login",
  251. // body: `{
  252. // "email": "belanger@getporter.dev",
  253. // "password": "hello"
  254. // }`,
  255. // expStatus: http.StatusOK,
  256. // expBody: `{"id":1,"email":"belanger@getporter.dev","email_verified":false}`,
  257. // useCookie: true,
  258. // validators: []func(c *userTest, tester *tester, t *testing.T){
  259. // userBasicBodyValidator,
  260. // },
  261. // },
  262. // {
  263. // msg: "Login user unregistered email",
  264. // method: "POST",
  265. // endpoint: "/api/login",
  266. // body: `{
  267. // "email": "belanger@getporter.dev",
  268. // "password": "hello"
  269. // }`,
  270. // expStatus: http.StatusUnauthorized,
  271. // expBody: `{"code":401,"errors":["email not registered"]}`,
  272. // validators: []func(c *userTest, tester *tester, t *testing.T){
  273. // userBasicBodyValidator,
  274. // },
  275. // },
  276. // {
  277. // initializers: []func(tester *tester){
  278. // initUserDefault,
  279. // },
  280. // msg: "Login user incorrect password",
  281. // method: "POST",
  282. // endpoint: "/api/login",
  283. // body: `{
  284. // "email": "belanger@getporter.dev",
  285. // "password": "notthepassword"
  286. // }`,
  287. // expStatus: http.StatusUnauthorized,
  288. // expBody: `{"code":401,"errors":["incorrect password"]}`,
  289. // useCookie: true,
  290. // validators: []func(c *userTest, tester *tester, t *testing.T){
  291. // userBasicBodyValidator,
  292. // },
  293. // },
  294. // }
  295. // func TestHandleLoginUser(t *testing.T) {
  296. // testUserRequests(t, loginUserTests, true)
  297. // }
  298. // var logoutUserTests = []*userTest{
  299. // {
  300. // initializers: []func(tester *tester){
  301. // initUserDefault,
  302. // },
  303. // msg: "Logout user successful",
  304. // method: "POST",
  305. // endpoint: "/api/logout",
  306. // body: `{
  307. // "email": "belanger@getporter.dev",
  308. // "password": "hello"
  309. // }`,
  310. // expStatus: http.StatusOK,
  311. // expBody: ``,
  312. // useCookie: true,
  313. // validators: []func(c *userTest, tester *tester, t *testing.T){
  314. // func(c *userTest, tester *tester, t *testing.T) {
  315. // req, err := http.NewRequest(
  316. // "GET",
  317. // "/api/users/1",
  318. // strings.NewReader(""),
  319. // )
  320. // req.AddCookie(tester.cookie)
  321. // if err != nil {
  322. // t.Fatal(err)
  323. // }
  324. // rr2 := httptest.NewRecorder()
  325. // tester.router.ServeHTTP(rr2, req)
  326. // if status := rr2.Code; status != http.StatusForbidden {
  327. // t.Errorf("%s, handler returned wrong status: got %v want %v",
  328. // "validator failed", status, http.StatusForbidden)
  329. // }
  330. // },
  331. // },
  332. // },
  333. // }
  334. // func TestHandleLogoutUser(t *testing.T) {
  335. // testUserRequests(t, logoutUserTests, true)
  336. // }
  337. // var readUserTests = []*userTest{
  338. // {
  339. // initializers: []func(tester *tester){
  340. // initUserDefault,
  341. // },
  342. // msg: "Read user successful",
  343. // method: "GET",
  344. // endpoint: "/api/users/1",
  345. // body: "",
  346. // expStatus: http.StatusOK,
  347. // expBody: `{"id":1,"email":"belanger@getporter.dev"}`,
  348. // useCookie: true,
  349. // validators: []func(c *userTest, tester *tester, t *testing.T){
  350. // userModelBodyValidator,
  351. // },
  352. // },
  353. // {
  354. // initializers: []func(tester *tester){
  355. // initUserDefault,
  356. // },
  357. // msg: "Read user unauthorized",
  358. // method: "GET",
  359. // endpoint: "/api/users/2",
  360. // body: "",
  361. // expStatus: http.StatusForbidden,
  362. // expBody: http.StatusText(http.StatusForbidden) + "\n",
  363. // validators: []func(c *userTest, tester *tester, t *testing.T){
  364. // userBasicBodyValidator,
  365. // },
  366. // },
  367. // }
  368. // func TestHandleReadUser(t *testing.T) {
  369. // testUserRequests(t, readUserTests, true)
  370. // }
  371. // var listUserProjectsTests = []*userTest{
  372. // {
  373. // initializers: []func(tester *tester){
  374. // initUserDefault,
  375. // initProject,
  376. // },
  377. // msg: "List user projects successful",
  378. // method: "GET",
  379. // endpoint: "/api/users/1/projects",
  380. // body: "",
  381. // expStatus: http.StatusOK,
  382. // expBody: `[{"id":1,"name":"project-test","roles":[{"id":0,"kind":"admin","user_id":1,"project_id":1}]}]`,
  383. // useCookie: true,
  384. // validators: []func(c *userTest, tester *tester, t *testing.T){
  385. // userProjectsListValidator,
  386. // },
  387. // },
  388. // {
  389. // initializers: []func(tester *tester){
  390. // initUserDefault,
  391. // },
  392. // msg: "List user projects unauthorized",
  393. // method: "GET",
  394. // endpoint: "/api/users/2/projects",
  395. // body: "",
  396. // expStatus: http.StatusForbidden,
  397. // expBody: http.StatusText(http.StatusForbidden) + "\n",
  398. // validators: []func(c *userTest, tester *tester, t *testing.T){
  399. // userBasicBodyValidator,
  400. // },
  401. // },
  402. // }
  403. // func TestHandleListUserProjects(t *testing.T) {
  404. // testUserRequests(t, listUserProjectsTests, true)
  405. // }
  406. // var deleteUserTests = []*userTest{
  407. // {
  408. // initializers: []func(tester *tester){
  409. // initUserDefault,
  410. // },
  411. // msg: "Delete user successful",
  412. // method: "DELETE",
  413. // endpoint: "/api/users/1",
  414. // body: `{"password":"hello"}`,
  415. // expStatus: http.StatusNoContent,
  416. // expBody: "",
  417. // useCookie: true,
  418. // validators: []func(c *userTest, tester *tester, t *testing.T){
  419. // func(c *userTest, tester *tester, t *testing.T) {
  420. // req, err := http.NewRequest(
  421. // "GET",
  422. // "/api/users/1",
  423. // strings.NewReader(""),
  424. // )
  425. // req.AddCookie(tester.cookie)
  426. // if err != nil {
  427. // t.Fatal(err)
  428. // }
  429. // rr2 := httptest.NewRecorder()
  430. // tester.router.ServeHTTP(rr2, req)
  431. // gotBody := &models.UserExternal{}
  432. // expBody := &models.UserExternal{}
  433. // if status := rr2.Code; status != 404 {
  434. // t.Errorf("DELETE user validation, handler returned wrong status code: got %v want %v",
  435. // status, 404)
  436. // }
  437. // json.Unmarshal(rr2.Body.Bytes(), gotBody)
  438. // json.Unmarshal([]byte(`{"code":602,"errors":["could not find requested object"]}`), expBody)
  439. // if !reflect.DeepEqual(gotBody, expBody) {
  440. // t.Errorf("%s, handler returned wrong body: got %v want %v",
  441. // "validator failed", gotBody, expBody)
  442. // }
  443. // },
  444. // },
  445. // },
  446. // {
  447. // initializers: []func(tester *tester){
  448. // initUserDefault,
  449. // },
  450. // msg: "Delete user invalid id",
  451. // method: "DELETE",
  452. // endpoint: "/api/users/aldkjf",
  453. // body: `{"password":"hello"}`,
  454. // expStatus: http.StatusForbidden,
  455. // expBody: http.StatusText(http.StatusForbidden) + "\n",
  456. // validators: []func(c *userTest, tester *tester, t *testing.T){
  457. // userBasicBodyValidator,
  458. // },
  459. // },
  460. // {
  461. // initializers: []func(tester *tester){
  462. // initUserDefault,
  463. // },
  464. // msg: "Delete user missing password",
  465. // method: "DELETE",
  466. // endpoint: "/api/users/1",
  467. // body: `{}`,
  468. // expStatus: http.StatusUnprocessableEntity,
  469. // expBody: `{"code":601,"errors":["required validation failed"]}`,
  470. // useCookie: true,
  471. // validators: []func(c *userTest, tester *tester, t *testing.T){
  472. // userBasicBodyValidator,
  473. // },
  474. // },
  475. // }
  476. // func TestHandleDeleteUser(t *testing.T) {
  477. // testUserRequests(t, deleteUserTests, true)
  478. // }
  479. // // ------------------------- INITIALIZERS AND VALIDATORS ------------------------- //
  480. // func initUserDefault(tester *tester) {
  481. // tester.createUserSession("belanger@getporter.dev", "hello")
  482. // }
  483. // func initUserAlt(tester *tester) {
  484. // tester.createUserSession("test@test.it", "hello")
  485. // }
  486. // func userBasicBodyValidator(c *userTest, tester *tester, t *testing.T) {
  487. // if body := tester.rr.Body.String(); strings.TrimSpace(body) != strings.TrimSpace(c.expBody) {
  488. // t.Errorf("%s, handler returned wrong body: got %v want %v",
  489. // c.msg, body, c.expBody)
  490. // }
  491. // }
  492. // func userModelBodyValidator(c *userTest, tester *tester, t *testing.T) {
  493. // gotBody := &models.UserExternal{}
  494. // expBody := &models.UserExternal{}
  495. // json.Unmarshal(tester.rr.Body.Bytes(), gotBody)
  496. // json.Unmarshal([]byte(c.expBody), expBody)
  497. // if !reflect.DeepEqual(gotBody, expBody) {
  498. // t.Errorf("%s, handler returned wrong body: got %v want %v",
  499. // c.msg, gotBody, expBody)
  500. // }
  501. // }
  502. // func userProjectsListValidator(c *userTest, tester *tester, t *testing.T) {
  503. // gotBody := make([]*types.Project, 0)
  504. // expBody := make([]*types.Project, 0)
  505. // json.Unmarshal(tester.rr.Body.Bytes(), &gotBody)
  506. // json.Unmarshal([]byte(c.expBody), &expBody)
  507. // if diff := deep.Equal(gotBody, expBody); diff != nil {
  508. // t.Errorf("handler returned wrong body:\n")
  509. // t.Error(diff)
  510. // }
  511. // }