handler.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. package main
  2. import (
  3. "crypto/sha256"
  4. "crypto/tls"
  5. "encoding/json"
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "net/url"
  10. "strings"
  11. "time"
  12. "github.com/dgrijalva/jwt-go"
  13. "github.com/labstack/echo"
  14. )
  15. type handler struct{}
  16. type userInfo struct {
  17. Result struct {
  18. Result struct {
  19. Sshpubkeyfp []string `json:"sshpubkeyfp"`
  20. HasKeytab bool `json:"has_keytab"`
  21. Ipasshpubkey []string `json:"ipasshpubkey"`
  22. Cn []string `json:"cn"`
  23. Krbcanonicalname []string `json:"krbcanonicalname"`
  24. Krbticketflags []string `json:"krbticketflags"`
  25. MemberofGroup []string `json:"memberof_group"`
  26. HasPassword bool `json:"has_password"`
  27. Homedirectory []string `json:"homedirectory"`
  28. Nsaccountlock bool `json:"nsaccountlock"`
  29. UID []string `json:"uid"`
  30. Title []string `json:"title"`
  31. Loginshell []string `json:"loginshell"`
  32. Uidnumber []string `json:"uidnumber"`
  33. Preserved bool `json:"preserved"`
  34. Krbextradata []struct {
  35. Base64 string `json:"__base64__"`
  36. } `json:"krbextradata"`
  37. Mail []string `json:"mail"`
  38. MemberofindirectHbacrule []string `json:"memberofindirect_hbacrule"`
  39. Dn string `json:"dn"`
  40. Displayname []string `json:"displayname"`
  41. Mepmanagedentry []string `json:"mepmanagedentry"`
  42. Ipauniqueid []string `json:"ipauniqueid"`
  43. Krbloginfailedcount []string `json:"krbloginfailedcount"`
  44. Krbpwdpolicyreference []string `json:"krbpwdpolicyreference"`
  45. Krbprincipalname []string `json:"krbprincipalname"`
  46. Givenname []string `json:"givenname"`
  47. Krblastadminunlock []struct {
  48. Datetime string `json:"__datetime__"`
  49. } `json:"krblastadminunlock"`
  50. Krbpasswordexpiration []struct {
  51. Datetime string `json:"__datetime__"`
  52. } `json:"krbpasswordexpiration"`
  53. Krblastfailedauth []struct {
  54. Datetime string `json:"__datetime__"`
  55. } `json:"krblastfailedauth"`
  56. Objectclass []string `json:"objectclass"`
  57. Gidnumber []string `json:"gidnumber"`
  58. Gecos []string `json:"gecos"`
  59. Sn []string `json:"sn"`
  60. MemberofSudorule []string `json:"memberof_sudorule"`
  61. Krblastpwdchange []struct {
  62. Datetime string `json:"__datetime__"`
  63. } `json:"krblastpwdchange"`
  64. Initials []string `json:"initials"`
  65. } `json:"result"`
  66. Value string `json:"value"`
  67. Summary interface{} `json:"summary"`
  68. } `json:"result"`
  69. Version string `json:"version"`
  70. Error interface{} `json:"error"`
  71. ID int `json:"id"`
  72. Principal string `json:"principal"`
  73. }
  74. func (h *handler) login(c echo.Context) error {
  75. username := c.FormValue("username")
  76. password := c.FormValue("password")
  77. _url := URL + "/ipa/session/login_password"
  78. method := "POST"
  79. params := url.Values{}
  80. params.Add("user", username)
  81. params.Add("password", password)
  82. payload := strings.NewReader(params.Encode())
  83. tr := &http.Transport{
  84. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  85. }
  86. client := &http.Client{Transport: tr}
  87. req, err := http.NewRequest(method, _url, payload)
  88. audit("Recieved Login request from: " + RealIP)
  89. if err != nil {
  90. fmt.Println(err)
  91. }
  92. req.Header.Add("Referer", URL+"/ipa")
  93. req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
  94. req.Header.Add("Accept", "text/plain")
  95. res, err := client.Do(req)
  96. cockie := res.Cookies()
  97. token := cockie[0].Raw
  98. defer res.Body.Close()
  99. //fmt.Println(res.StatusCode)
  100. if res.StatusCode == 200 {
  101. user := getUserInfo(token, username)
  102. //fmt.Println(user.Result)
  103. tokens, err := generateTokenPair(user, token)
  104. if err != nil {
  105. return err
  106. }
  107. return c.JSON(http.StatusOK, tokens)
  108. }
  109. return echo.ErrUnauthorized
  110. }
  111. func getUserInfo(token string, username string) userInfo {
  112. fmt.Println("Checking for User: ", username)
  113. url := URL + "/ipa/session/json"
  114. method := "POST"
  115. _json := fmt.Sprintf(`
  116. {
  117. "method": "user_show",
  118. "params": [
  119. [
  120. "%s"
  121. ],
  122. {
  123. "all": true,
  124. "version": "2.215"
  125. }
  126. ],
  127. "id": 0
  128. }
  129. `, username)
  130. payload := strings.NewReader(_json)
  131. tr := &http.Transport{
  132. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  133. }
  134. client := &http.Client{Transport: tr}
  135. req, err := http.NewRequest(method, url, payload)
  136. if err != nil {
  137. fmt.Println(err)
  138. }
  139. req.Header.Add("Referer", URL+"/ipa")
  140. req.Header.Add("Content-Type", "application/json")
  141. req.Header.Add("Accept", "text/plain")
  142. req.Header.Add("Cookie", token)
  143. res, err := client.Do(req)
  144. defer res.Body.Close()
  145. body, err := ioutil.ReadAll(res.Body)
  146. user := userInfo{}
  147. json.Unmarshal(body, &user)
  148. return user
  149. }
  150. func (h *handler) private(c echo.Context) error {
  151. user := c.Get("user").(*jwt.Token)
  152. claims := user.Claims.(jwt.MapClaims)
  153. name := claims["name"].(string)
  154. return c.String(http.StatusOK, "Welcome "+name+"!")
  155. }
  156. func (h *handler) addUser(c echo.Context) error {
  157. type apiErr struct {
  158. Result interface{} `json:"result"`
  159. Error struct {
  160. Code int `json:"code"`
  161. Message string `json:"message"`
  162. Data struct {
  163. } `json:"data"`
  164. Name string `json:"name"`
  165. } `json:"error"`
  166. ID int `json:"id"`
  167. Principal string `json:"principal"`
  168. Version string `json:"version"`
  169. }
  170. type addUser struct {
  171. Result struct {
  172. Result struct {
  173. Displayname []string `json:"displayname"`
  174. UID []string `json:"uid"`
  175. Uidnumber []string `json:"uidnumber"`
  176. Objectclass []string `json:"objectclass"`
  177. Sn []string `json:"sn"`
  178. Telephonenumber []string `json:"telephonenumber"`
  179. Cn []string `json:"cn"`
  180. Krbpasswordexpiration []struct {
  181. Datetime string `json:"__datetime__"`
  182. } `json:"krbpasswordexpiration"`
  183. Mobile []string `json:"mobile"`
  184. Krbprincipalname []string `json:"krbprincipalname"`
  185. Ipauniqueid []string `json:"ipauniqueid"`
  186. Givenname []string `json:"givenname"`
  187. Gidnumber []string `json:"gidnumber"`
  188. Krbcanonicalname []string `json:"krbcanonicalname"`
  189. Mail []string `json:"mail"`
  190. Initials []string `json:"initials"`
  191. Homedirectory []string `json:"homedirectory"`
  192. Loginshell []string `json:"loginshell"`
  193. Gecos []string `json:"gecos"`
  194. Randompassword string `json:"randompassword"`
  195. HasPassword bool `json:"has_password"`
  196. HasKeytab bool `json:"has_keytab"`
  197. MemberofGroup []string `json:"memberof_group"`
  198. Dn string `json:"dn"`
  199. } `json:"result"`
  200. Value string `json:"value"`
  201. Summary string `json:"summary"`
  202. } `json:"result"`
  203. Error string `json:"error"`
  204. ID int `json:"id"`
  205. Principal string `json:"principal"`
  206. Version string `json:"version"`
  207. }
  208. user := c.Get("user").(*jwt.Token)
  209. claims := user.Claims.(jwt.MapClaims)
  210. _sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
  211. var hashChannel_ = make(chan []byte, 1)
  212. hashChannel_ <- _sha256[:]
  213. token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
  214. b, err := json.Marshal(claims)
  215. if err != nil {
  216. fmt.Println("err:", err)
  217. }
  218. fmt.Println("AddUser Claims: ", claims)
  219. fmt.Println("AddUser token: ", token)
  220. username := c.FormValue("Username")
  221. sha256 := sha256.Sum256([]byte(username))
  222. var hashChannel = make(chan []byte, 1)
  223. hashChannel <- sha256[:]
  224. ciphertext := encrypt(<-hashChannel, string(b))
  225. fmt.Println("B: ", string(b))
  226. fmt.Println("Ciphere: ", ciphertext)
  227. sn := c.FormValue("Lname")
  228. cn := c.FormValue("FullName")
  229. givenname := c.FormValue("Fname")
  230. displayname := c.FormValue("displayname")
  231. krbpasswordexpiration := c.FormValue("krbpasswordexpiration")
  232. mail := c.FormValue("mail")
  233. telephonenumber := c.FormValue("telephonenumber")
  234. mobile := c.FormValue("mobile")
  235. _url := URL + "/ipa/session/json"
  236. method := "POST"
  237. _json := fmt.Sprintf(`
  238. {
  239. "id": 0,
  240. "method": "user_add/1",
  241. "params": [
  242. [
  243. "%s"
  244. ],
  245. {
  246. "givenname": "%s",
  247. "sn": "%s",
  248. "cn":"%s",
  249. "displayname":"%s",
  250. "loginshell":"/usr/sbin/nologin",
  251. "krbpasswordexpiration":"%s",
  252. "mail":"%s",
  253. "random":"true",
  254. "gidnumber":"599200001",
  255. "telephonenumber":"%s",
  256. "mobile":"%s",
  257. "version": "2.235"
  258. }
  259. ]
  260. }
  261. `, username, givenname, sn, cn, displayname, krbpasswordexpiration, mail, telephonenumber, mobile)
  262. __json := fmt.Sprintf(`
  263. {
  264. "id": 0,
  265. "method": "group_add_member/1",
  266. "params": [
  267. [
  268. "svcaccounts"
  269. ],
  270. {
  271. "user": [
  272. "%s"
  273. ],
  274. "version": "2.235"
  275. }
  276. ]
  277. }
  278. `, username)
  279. payload := strings.NewReader(_json)
  280. _payload := strings.NewReader(__json)
  281. tr := &http.Transport{
  282. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  283. }
  284. client := &http.Client{Transport: tr}
  285. req, err := http.NewRequest(method, _url, payload)
  286. if err != nil {
  287. fmt.Println(err)
  288. }
  289. req.Header.Add("Referer", URL+"/ipa")
  290. req.Header.Add("Content-Type", "application/json")
  291. req.Header.Add("Accept", "text/plain")
  292. req.Header.Add("Cookie", token)
  293. res, err := client.Do(req)
  294. _req, _ := http.NewRequest(method, _url, _payload)
  295. _req.Header.Add("Referer", URL+"/ipa")
  296. _req.Header.Add("Content-Type", "application/json")
  297. _req.Header.Add("Accept", "text/plain")
  298. _req.Header.Add("Cookie", token)
  299. client.Do(_req)
  300. defer res.Body.Close()
  301. body, err := ioutil.ReadAll(res.Body)
  302. result := addUser{}
  303. _err := json.Unmarshal(body, &result)
  304. // fmt.Println(result)
  305. if _err != nil {
  306. _apiErr := apiErr{}
  307. __err := json.Unmarshal(body, &_apiErr)
  308. if __err != nil {
  309. return c.String(http.StatusBadRequest, "Error of error!!")
  310. }
  311. res2B, _ := json.Marshal(_apiErr)
  312. return c.String(http.StatusBadRequest, string(res2B))
  313. }
  314. go sendMail("Welcome to ZiCloud\r\n Your temporary link is :\r\n https://zicloud.com/reset/"+url.QueryEscape(ciphertext), "Welcome to ZiCloud", mail)
  315. resp := _response{
  316. Origin: "addUser",
  317. Message: "Done, Reset Link was sent to " + mail,
  318. Code: 1000,
  319. }
  320. b, _ = json.MarshalIndent(resp, "", " ")
  321. return c.String(http.StatusOK, string(b))
  322. }
  323. func (h *handler) disableUser(c echo.Context) error {
  324. user := c.Get("user").(*jwt.Token)
  325. claims := user.Claims.(jwt.MapClaims)
  326. _sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
  327. var hashChannel_ = make(chan []byte, 1)
  328. hashChannel_ <- _sha256[:]
  329. token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
  330. username := c.FormValue("Username")
  331. url := URL + "/ipa/session/json"
  332. method := "POST"
  333. _json := fmt.Sprintf(`
  334. {
  335. "id": 0,
  336. "method": "user_disable/1",
  337. "params": [
  338. [
  339. "%s"
  340. ],
  341. {
  342. "version": "2.235"
  343. }
  344. ]
  345. }
  346. `, username)
  347. payload := strings.NewReader(_json)
  348. tr := &http.Transport{
  349. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  350. }
  351. client := &http.Client{Transport: tr}
  352. req, err := http.NewRequest(method, url, payload)
  353. if err != nil {
  354. fmt.Println(err)
  355. }
  356. req.Header.Add("Referer", URL+"/ipa")
  357. req.Header.Add("Content-Type", "application/json")
  358. req.Header.Add("Accept", "text/plain")
  359. req.Header.Add("Cookie", token)
  360. res, err := client.Do(req)
  361. if err != nil {
  362. return c.String(http.StatusBadRequest, "Error"+err.Error())
  363. }
  364. defer res.Body.Close()
  365. resp := _response{
  366. Origin: "disableUser",
  367. Message: "Done",
  368. Code: 1000,
  369. }
  370. b, _ := json.MarshalIndent(resp, "", " ")
  371. return c.String(http.StatusOK, string(b))
  372. }
  373. func (h *handler) resetUser(c echo.Context) error {
  374. type keyJson struct {
  375. IPAToken string `json:"IPAToken"`
  376. Admin bool `json:"admin"`
  377. Exp int `json:"exp"`
  378. Memberof []string `json:"memberof"`
  379. Name string `json:"name"`
  380. Sub int `json:"sub"`
  381. }
  382. t := time.Now() //%Y%m%d%H%M%SZ
  383. t = t.Add(time.Hour * 24 * 60)
  384. username := c.FormValue("Username")
  385. password := c.FormValue("Password")
  386. key := c.FormValue("key")
  387. key, _ = url.QueryUnescape(key)
  388. _sha256 := sha256.Sum256([]byte(username))
  389. var hashChannel = make(chan []byte, 1)
  390. hashChannel <- _sha256[:]
  391. plainkey := decrypt(<-hashChannel, key)
  392. _plainkey := keyJson{}
  393. json.Unmarshal([]byte(plainkey), &_plainkey)
  394. _name := _plainkey.Name
  395. //_sha256 := sha256.Sum256([]byte(string("")))
  396. var hashChannel_ = make(chan []byte, 1)
  397. __sha256 := sha256.Sum256([]byte(_name))
  398. hashChannel_ <- __sha256[:]
  399. token := decrypt(<-hashChannel_, string(_plainkey.IPAToken))
  400. // token := _plainkey.IPAToken
  401. _url := URL + "/ipa/session/json"
  402. method := "POST"
  403. _json := fmt.Sprintf(`
  404. {
  405. "id": 0,
  406. "method": "user_mod/1",
  407. "params": [
  408. [
  409. "%s"
  410. ],
  411. {
  412. "userpassword":"%s",
  413. "version": "2.235"
  414. }
  415. ]
  416. }
  417. `, username, password)
  418. payload := strings.NewReader(_json)
  419. tr := &http.Transport{
  420. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  421. }
  422. client := &http.Client{Transport: tr}
  423. req, err := http.NewRequest(method, _url, payload)
  424. if err != nil {
  425. fmt.Println(err)
  426. }
  427. req.Header.Add("Referer", URL+"/ipa")
  428. req.Header.Add("Content-Type", "application/json")
  429. req.Header.Add("Accept", "text/plain")
  430. req.Header.Add("Cookie", token)
  431. res, err := client.Do(req)
  432. //fmt.Println(token)
  433. //fmt.Println(_json)
  434. //fmt.Println(req)
  435. //fmt.Println(res)
  436. _json = fmt.Sprintf(`
  437. {
  438. "id": 0,
  439. "method": "user_mod/1",
  440. "params": [
  441. [
  442. "%s"
  443. ],
  444. {
  445. "krbpasswordexpiration":"%s",
  446. "version": "2.235"
  447. }
  448. ]
  449. }
  450. `, username, t.Format("2006-01-02")+"Z")
  451. payload = strings.NewReader(_json)
  452. req, err = http.NewRequest(method, _url, payload)
  453. if err != nil {
  454. fmt.Println(err)
  455. }
  456. req.Header.Add("Referer", URL+"/ipa")
  457. req.Header.Add("Content-Type", "application/json")
  458. req.Header.Add("Accept", "text/plain")
  459. req.Header.Add("Cookie", token)
  460. err = nil
  461. res, err = client.Do(req)
  462. //fmt.Println(token)
  463. //fmt.Println(_json)
  464. //fmt.Println(req)
  465. //fmt.Println(res)
  466. if err != nil {
  467. return c.String(http.StatusBadRequest, "Error"+err.Error())
  468. }
  469. defer res.Body.Close()
  470. resp := _response{
  471. Origin: "resetUser",
  472. Message: "Done",
  473. Code: 1000,
  474. }
  475. b, _ := json.MarshalIndent(resp, "", " ")
  476. return c.String(http.StatusOK, string(b))
  477. }
  478. func (h *handler) dnsrecordadd(c echo.Context) error {
  479. user := c.Get("user").(*jwt.Token)
  480. claims := user.Claims.(jwt.MapClaims)
  481. _sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
  482. var hashChannel_ = make(chan []byte, 1)
  483. hashChannel_ <- _sha256[:]
  484. token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
  485. recordName := c.FormValue("recordName")
  486. record := c.FormValue("record")
  487. url := URL + "/ipa/session/json"
  488. method := "POST"
  489. _json := fmt.Sprintf(`
  490. {
  491. "id": 0,
  492. "method": "dnsrecord_add/1",
  493. "params": [
  494. [
  495. "ZI-TEL.COM",
  496. {
  497. "__dns_name__": "%s"
  498. }
  499. ],
  500. {
  501. "a_part_ip_address": "%s",
  502. "raw": true,
  503. "version": "2.235"
  504. }
  505. ]
  506. }
  507. `, recordName, record)
  508. payload := strings.NewReader(_json)
  509. tr := &http.Transport{
  510. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  511. }
  512. client := &http.Client{Transport: tr}
  513. req, err := http.NewRequest(method, url, payload)
  514. if err != nil {
  515. fmt.Println(err)
  516. }
  517. req.Header.Add("Referer", URL+"/ipa")
  518. req.Header.Add("Content-Type", "application/json")
  519. req.Header.Add("Accept", "text/plain")
  520. req.Header.Add("Cookie", token)
  521. res, err := client.Do(req)
  522. if err != nil {
  523. return c.String(http.StatusBadRequest, "Error"+err.Error())
  524. }
  525. //body, err := ioutil.ReadAll(res.Body)
  526. //_res:=result{}
  527. //json.Unmarshal(body, &_res)
  528. //fmt.Println(_res)
  529. defer res.Body.Close()
  530. resp := _response{
  531. Origin: "dnsrecordadd",
  532. Message: "Done",
  533. Code: 1000,
  534. }
  535. b, _ := json.MarshalIndent(resp, "", " ")
  536. return c.String(http.StatusOK, string(b))
  537. }
  538. func (h *handler) token(c echo.Context) error {
  539. user := c.Get("user").(*jwt.Token)
  540. claims := user.Claims.(jwt.MapClaims)
  541. _sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
  542. var hashChannel_ = make(chan []byte, 1)
  543. hashChannel_ <- _sha256[:]
  544. token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
  545. username := claims["name"].(string)
  546. _user := getUserInfo(token, username)
  547. //fmt.Println(user.Result)
  548. newtokens, err := generateTokenPair(_user, token)
  549. if err != nil {
  550. return err
  551. }
  552. return c.JSON(http.StatusOK, newtokens)
  553. }
  554. func (h *handler) verifyUser(c echo.Context) error {
  555. name := c.FormValue("Username")
  556. //fmt.Println("Name: ", name)
  557. if name == "" {
  558. return c.JSON(http.StatusNotFound, "User NOT Found")
  559. }
  560. username := "admin"
  561. password := "h?_QJp5^&9FNc9w="
  562. _url := URL + "/ipa/session/login_password"
  563. method := "POST"
  564. params := url.Values{}
  565. params.Add("user", username)
  566. params.Add("password", password)
  567. payload := strings.NewReader(params.Encode())
  568. tr := &http.Transport{
  569. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  570. }
  571. client := &http.Client{Transport: tr}
  572. req, err := http.NewRequest(method, _url, payload)
  573. audit("Recieved Login request from: " + RealIP)
  574. if err != nil {
  575. fmt.Println(err)
  576. }
  577. req.Header.Add("Referer", URL+"/ipa")
  578. req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
  579. req.Header.Add("Accept", "text/plain")
  580. res, err := client.Do(req)
  581. cockie := res.Cookies()
  582. token := cockie[0].Raw
  583. defer res.Body.Close()
  584. //fmt.Println(token)
  585. if res.StatusCode == 200 {
  586. user := getUserInfo(token, name)
  587. if user.Result.Value != name {
  588. resp := _response{
  589. Origin: "VerifyUser",
  590. Message: "User Not Found",
  591. Code: 1001,
  592. }
  593. b, _errr := json.MarshalIndent(resp, "", " ")
  594. if _errr != nil {
  595. fmt.Println(_errr)
  596. }
  597. fmt.Print(string(b))
  598. return c.JSON(http.StatusNotFound, string(b))
  599. }
  600. }
  601. resp := _response{
  602. Origin: "VerifyUser",
  603. Message: "User Found",
  604. Code: 1002,
  605. }
  606. b, _ := json.MarshalIndent(resp, "", " ")
  607. return c.JSON(http.StatusOK, string(b))
  608. }