utils.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. package api
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/url"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
  11. "github.com/davecgh/go-spew/spew"
  12. "github.com/eugeniucarvalho/validator"
  13. "github.com/kataras/iris/v12/context"
  14. "go.mongodb.org/mongo-driver/bson"
  15. "go.mongodb.org/mongo-driver/bson/primitive"
  16. "go.mongodb.org/mongo-driver/mongo"
  17. )
  18. var (
  19. AcceptJson = regexp.MustCompile("^application/json")
  20. Environment = map[string]interface{}{}
  21. ToReference = references{}
  22. )
  23. type references struct {
  24. }
  25. func (this *references) True() *bool {
  26. value := true
  27. return &value
  28. }
  29. func (this *references) False() *bool {
  30. value := false
  31. return &value
  32. }
  33. func (this *references) String(value string) *string {
  34. return &value
  35. }
  36. func (this *references) Bool(value bool) *bool {
  37. return &value
  38. }
  39. type ModeInterface interface {
  40. Mode() string
  41. }
  42. type PatchHistoryRegister struct {
  43. Id primitive.ObjectID `bson:"_id" json:"-"`
  44. CreatedAt int64 `bson:"createdAt" json:"-"`
  45. CreatedBy string `bson:"createdBy" json:"-"`
  46. Parent string `bson:"parent" json:"-"`
  47. ApiTags []string `bson:"apiTags" json:"-"`
  48. }
  49. type EntityModel struct {
  50. Mode string `bson:"-" json:"-"`
  51. ApplicationVersion *string `bson:"appVersion,omitempty" json:"-"`
  52. Deleted *bool `bson:"deleted,omitempty" json:"-"`
  53. DeletedIn *int64 `bson:"deletedIn,omitempty" json:"-"`
  54. }
  55. // type DotNotation struct {
  56. // Rules map[string]interface{} `bson:",inline" json:"-"`
  57. // }
  58. // func (model *DotNotation) DotNotation() map[string]interface{} {
  59. // if model.Rules == nil {
  60. // model.Rules = map[string]interface{}{}
  61. // }
  62. // return model.Rules
  63. // }
  64. func UserIDString(ctx context.Context) (id string, err *errs.Error) {
  65. if user, ok := ctx.Values().Get("$user.ref").(map[string]interface{}); ok {
  66. id = user["id"].(primitive.ObjectID).Hex()
  67. return
  68. }
  69. err = errs.Internal().Details(&errs.Detail{
  70. Message: "Invalid user instance",
  71. })
  72. return
  73. }
  74. func (model *EntityModel) SetMode(mode string) {
  75. model.Mode = mode
  76. switch mode {
  77. case "create":
  78. model.ApplicationVersion = &BuildVersion
  79. deleted := false
  80. model.Deleted = &deleted
  81. case "update":
  82. if model.Deleted == nil {
  83. deleted := false
  84. model.Deleted = &deleted
  85. }
  86. case "patch":
  87. // if model.Deleted == nil {
  88. // deleted := false
  89. // model.Deleted = &deleted
  90. // }
  91. // case "delete":
  92. // case "undelete":
  93. }
  94. }
  95. func GetIDString(input interface{}) (string, *errs.Error) {
  96. if value, converted := input.(string); converted {
  97. return value, nil
  98. }
  99. if value, converted := input.(*primitive.ObjectID); converted {
  100. return value.Hex(), nil
  101. }
  102. if value, converted := input.(primitive.ObjectID); converted {
  103. return value.Hex(), nil
  104. }
  105. return "", errs.Internal().Details(&errs.Detail{
  106. Reason: fmt.Sprintf("Can't convert ID into string. Invalid type '%T", input),
  107. })
  108. }
  109. func NowUnix() int64 {
  110. return time.Now().Unix()
  111. }
  112. func GetUser(ctx context.Context) interface{} {
  113. return ctx.Values().Get("$user.ref")
  114. }
  115. func (model *EntityModel) SetDeleted(deleted bool) {
  116. var deletedIn = int64(0)
  117. model.Deleted = &deleted
  118. if *model.Deleted {
  119. deletedIn = time.Now().Unix()
  120. }
  121. model.DeletedIn = &deletedIn
  122. }
  123. type CorsOptions struct {
  124. ExposeHeaders []string
  125. AllowHeaders []string
  126. AllowMethods []string
  127. AllowOrigin []string
  128. }
  129. type GetManyResponse struct {
  130. ResultSizeEstimate int `json:"resultSizeEstimate"` // Estimativa do numero total de itens.
  131. NextPageToken string `json:"nextPageToken"` // Referência para a proxima pagina de resultados.
  132. Itens interface{} `json:"itens"` // Lista contento os elementos da resposta.
  133. }
  134. var (
  135. // ParamsFlag map[string]*ParamFlag
  136. CorsDefaultOptions = CorsOptions{
  137. AllowOrigin: []string{"*"},
  138. // AllowOrigin: []string{"http://localhost:4200"},
  139. AllowMethods: []string{"OPTIONS", "GET", "POST", "PUT", "DELETE", "PATCH"},
  140. AllowHeaders: []string{"Accept", "Authorization", "Content-Type", "Origin", "Host", "x-api-build"},
  141. ExposeHeaders: []string{"X-total-count"},
  142. }
  143. BuildVersion = "0"
  144. ApiVersion = "0"
  145. // Armazena os mimes dos arquivos consultados
  146. // MimeCache = xmap.NewMS2S()
  147. replaceEmpty = regexp.MustCompile(`\s+`)
  148. // pageTokenRegex = regexp.MustCompile(`(?P<ids>\w+):(?P<idc>\w+):(?P<page>\d{1,6})`)
  149. pageTokenRegex = regexp.MustCompile(`(?P<idc>[\w-]+):(?P<count>\d+)`)
  150. replaceIndex = regexp.MustCompile(`\.\d+\.`)
  151. )
  152. func init() {
  153. // fmt.Println("Register validation functions")
  154. // err := Validator.RegisterValidation("req", func(f validator.FieldLevel) bool {
  155. // fmt.Println("Running req validation")
  156. // spew.Dump(f)
  157. // return true
  158. // })
  159. validator.RegisterValidator("requiredOnCreate", func(i interface{}, o interface{}, v *validator.ValidatorOption) error {
  160. if schema, ok := o.(ModeInterface); ok {
  161. fmt.Println("requiredOnCreate ->", schema.Mode())
  162. switch schema.Mode() {
  163. case "create":
  164. if i == nil {
  165. return fmt.Errorf("")
  166. }
  167. case "update":
  168. }
  169. }
  170. return nil
  171. })
  172. // Validator.RegisterValidation("req",
  173. // func(fl validator.FieldLevel) bool {
  174. // // func(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
  175. // // func(v *validator.Validate, param string) bool {
  176. // // return passwordRegex.MatchString(field.String())
  177. // })
  178. // if err != nil {
  179. // panic(err)
  180. // }
  181. }
  182. func Panic() {
  183. if err := recover(); err != nil {
  184. LogError(0, err.(error).Error())
  185. }
  186. }
  187. func Validate(i interface{}) *errs.Error {
  188. // if err := Validator.Struct(i); err != nil {
  189. // fmt.Println("VALIDATE", result, err)
  190. // spew.Dump(i)
  191. if errors, valid := validator.Struct(i); !valid {
  192. err := errs.InvalidArgument()
  193. // er := Error(ERR_INVALID_PARAM, "Invalid params")
  194. for _, e := range errors {
  195. err.Details(&errs.Detail{
  196. Dominio: "global",
  197. Reason: "invalidParameter",
  198. Message: e.Message,
  199. // Message: fmt.Sprintf("%+v", e.Message),
  200. // LocationType:,
  201. // Location :,
  202. })
  203. }
  204. // if _, ok := err.(*validator.InvalidValidationError); ok {
  205. // fmt.Println("INvalid")
  206. // er.LastDescription().Message = err.Error()
  207. // } else {
  208. // for _, err := range err.(validator.ValidationErrors) {
  209. // switch err.Tag() {
  210. // case "required":
  211. // }
  212. // er.Add(&ErrDescription{
  213. // Dominio: "global",
  214. // Reason: "invalidParameter",
  215. // Message: fmt.Sprintf("%+v", err),
  216. // // LocationType:,
  217. // // Location :,
  218. // })
  219. // // fmt.Println("1", err.Namespace())
  220. // // fmt.Println("2", err.Field())
  221. // // fmt.Println("3", err.StructNamespace()) // can differ when a custom TagNameFunc is registered or
  222. // // fmt.Println("4", err.StructField()) // by passing alt name to ReportError like below
  223. // // fmt.Println("5", err.Tag())
  224. // // fmt.Println("6", err.ActualTag())
  225. // // fmt.Println("7", err.Kind())
  226. // // fmt.Println("8", err.Type())
  227. // // fmt.Println("9", err.Value())
  228. // // fmt.Println("10", err.Param())
  229. // // fmt.Println("-------------")
  230. // }
  231. // }
  232. return err
  233. // from here you can create your own error messages in whatever language you wish
  234. }
  235. return nil
  236. }
  237. // ApiResponse é a estrutura padrão de respostas
  238. // Apenas os campos preenchidos serão retornados
  239. type ApiResponse struct {
  240. Entity interface{} `json:"entity,omitempty"`
  241. List interface{} `json:"list,omitempty"`
  242. NextPageToken string `json:"nextPageToken,omitempty"`
  243. ResultSizeEstimate int `json:"resultSizeEstimate,omitempty"`
  244. }
  245. // func ErroCtxHandler(ctx context.Context, err *errs.Error) {
  246. // if accept := ctx.GetHeader("Accept"); AcceptJson.Match([]byte(accept)) {
  247. // ctx.JSON(err)
  248. // } else {
  249. // ctx.ViewData("", err)
  250. // }
  251. // }
  252. func finalizeRequest(ctx context.Context, resp interface{}, err *errs.Error) {
  253. var (
  254. status = 200
  255. accept = ctx.Request().Header.Get("accept")
  256. types = strings.Split(accept, ",")
  257. )
  258. defer func() {
  259. ctx.StopExecution()
  260. if debug := ctx.Values().Get("#debug"); debug != nil {
  261. debug.(*DebugTaks).Finalize()
  262. }
  263. if err != nil {
  264. ctx.Application().Logger().Error(err.Error())
  265. if description := err.LastDescription(); description != nil {
  266. err.Stack.Print()
  267. // ctx.Application().Logger().Error(fmt.Printf("%s\n%s\n", description.Reason, description.Message))
  268. }
  269. // ctx.Application().Logger().Error()
  270. spew.Dump(err)
  271. }
  272. fmt.Println("defer of finalizeRequest")
  273. if r := recover(); r != nil {
  274. fmt.Println("Recovered in f", r)
  275. }
  276. fmt.Println(string(ctx.Values().Serialize()))
  277. }()
  278. if err != nil {
  279. status = err.HttpStatus
  280. // fmt.Println(status, err.Message, "------------------------------------------\n")
  281. // spew.Dump(err)
  282. // debbug
  283. // err.Stack.Print()
  284. resp = err
  285. abortTransaction(ctx)
  286. // fmt.Println("------------------------------------------\n", status)
  287. // spew.Dump(err)
  288. // fmt.Println("------------------------------------------\n", status)
  289. }
  290. ctx.Values().Set("res", resp)
  291. ctx.Header("x-api-build", BuildVersion)
  292. // fmt.Println("error")
  293. // spew.Dump(resp)
  294. // spew.Dump(types)
  295. // spew.Dump(ctx.Request().Header)
  296. ctx.StatusCode(status)
  297. for _, mime := range types {
  298. switch mime {
  299. case "application/json":
  300. ctx.JSON(resp)
  301. return
  302. }
  303. }
  304. // default response case
  305. ctx.WriteString("invalid accept header value: " + accept)
  306. }
  307. // Call encapsula e trata os erros para cada requisição.
  308. func CallAction(id string, fn func(context.Context) (interface{}, *errs.Error)) func(context.Context) {
  309. return func(ctx context.Context) {
  310. var (
  311. err *errs.Error
  312. resp interface{}
  313. finalize = true
  314. values = ctx.Values()
  315. debug *DebugTaks
  316. )
  317. if interfaceDebug := values.Get("#debug"); interfaceDebug != nil {
  318. debug = interfaceDebug.(*DebugTaks)
  319. } else {
  320. debug = NewDebugTaks()
  321. values.Set("#debug", debug)
  322. }
  323. debug.Stage(id)
  324. defer func() {
  325. if !ctx.IsStopped() {
  326. if _err := recover(); _err != nil {
  327. err = errs.Internal().Details(&errs.Detail{
  328. Message: "",
  329. Location: fmt.Sprintf("call.action.%s", id),
  330. LocationType: "application.pipe.resource.stage",
  331. Reason: _err.(error).Error(),
  332. })
  333. }
  334. if finalize {
  335. finalizeRequest(ctx, resp, err)
  336. }
  337. }
  338. }()
  339. fmt.Println("apply -> ", id)
  340. if resp, err = fn(ctx); err != nil {
  341. return
  342. }
  343. if !ctx.IsStopped() {
  344. if resp != nil {
  345. err = commitTransaction(ctx)
  346. } else {
  347. ctx.Next()
  348. finalize = false
  349. }
  350. }
  351. return
  352. }
  353. }
  354. func abortTransaction(ctx context.Context) (err *errs.Error) {
  355. return transactionHandler(ctx, "abort")
  356. }
  357. func commitTransaction(ctx context.Context) (err *errs.Error) {
  358. return transactionHandler(ctx, "commit")
  359. }
  360. func transactionHandler(ctx context.Context, action string) (err *errs.Error) {
  361. var (
  362. localErr error
  363. operation func() error
  364. )
  365. contextSession := GetSessionContext(ctx)
  366. if contextSession == nil {
  367. return
  368. }
  369. switch action {
  370. case "abort":
  371. operation = func() error { return contextSession.AbortTransaction(contextSession) }
  372. case "commit":
  373. operation = func() error { return contextSession.CommitTransaction(contextSession) }
  374. }
  375. defer func() {
  376. if localErr != nil {
  377. err = errs.Internal().Details(&errs.Detail{
  378. Message: localErr.Error(),
  379. })
  380. }
  381. }()
  382. try := 4
  383. for {
  384. if localErr = operation(); localErr == nil {
  385. fmt.Println(action, "executed ")
  386. return
  387. }
  388. if try == 0 {
  389. return
  390. }
  391. try--
  392. fmt.Println(action, "transaction error loop ")
  393. // time.Sleep(4 * time.Second)
  394. // retry operation when command contains TransientTransactionError
  395. // if cmdErr, ok := localErr.(mongo.CommandError); ok && cmdErr.HasErrorLabel("TransientTransactionError") {
  396. if cmdErr, ok := localErr.(mongo.CommandError); ok {
  397. fmt.Println(action, cmdErr)
  398. if cmdErr.HasErrorLabel("TransientTransactionError") {
  399. continue
  400. }
  401. }
  402. }
  403. }
  404. func ReadJson(ctx context.Context, entity interface{}) (err *errs.Error) {
  405. if err := ctx.ReadJSON(entity); err != nil {
  406. err = errs.DataCaps().Details(&errs.Detail{
  407. Message: err.Error(),
  408. })
  409. }
  410. return
  411. }
  412. func MgoSortBson(fields []string) *bson.M {
  413. order := bson.M{}
  414. for _, field := range fields {
  415. n := 1
  416. if field != "" {
  417. fmt.Printf("sort '%c'\n", field[0])
  418. switch field[0] {
  419. case '+':
  420. field = field[1:]
  421. case '-':
  422. n = -1
  423. field = field[1:]
  424. default:
  425. panic(fmt.Sprintf("Invalid sort field %s.", field))
  426. }
  427. }
  428. if field == "" {
  429. panic("Sort: empty field name")
  430. }
  431. field = string(replaceIndex.ReplaceAll([]byte(field), []byte(".")))
  432. order[field] = n
  433. }
  434. return &order
  435. }
  436. func MgoSort(ctx context.Context, field string) []string {
  437. result := []string{}
  438. if fields := Q(ctx, field, ""); fields != "" {
  439. sort := string(replaceEmpty.ReplaceAll([]byte(fields), []byte("")))
  440. result = strings.Split(sort, ",")
  441. }
  442. // return nil
  443. return result
  444. }
  445. func MgoFieldsCtx(ctx context.Context, field string) *bson.M {
  446. return MgoFields(Q(ctx, field, ""))
  447. }
  448. func MgoFields(fields string) (projection *bson.M) {
  449. // fmt.Printf("MgoFields '%s'\n", fields)
  450. if fields != "" {
  451. projection = &bson.M{}
  452. for _, v := range strings.Split(fields, ",") {
  453. (*projection)[v] = 1
  454. }
  455. // spew.Dump(projection)
  456. }
  457. return
  458. }
  459. func MgoQuery(ctx context.Context, field string) (*bson.M, *errs.Error) {
  460. return MgoQueryString(ctx, Q(ctx, field, ""))
  461. }
  462. func MgoQueryString(ctx context.Context, query string) (*bson.M, *errs.Error) {
  463. var (
  464. selector = make(bson.M)
  465. // id = "_id"
  466. err error
  467. )
  468. // Unmarshal json query if any
  469. if query != "" {
  470. if err = bson.UnmarshalExtJSON([]byte(query), true, &selector); err != nil {
  471. // return nil, Error(ERR_GENERAL, err.Error())
  472. return nil, errs.Internal().Details(&errs.Detail{
  473. Message: err.Error(),
  474. })
  475. }
  476. if query, err = url.QueryUnescape(query); err != nil {
  477. return nil, errs.Internal().Details(&errs.Detail{
  478. Message: err.Error(),
  479. })
  480. // return nil, Error(ERR_GENERAL, err.Error())
  481. }
  482. if err = json.Unmarshal([]byte(query), &selector); err != nil {
  483. // return nil, Error(ERR_GENERAL, err.Error())
  484. return nil, errs.Internal().Details(&errs.Detail{
  485. Message: err.Error(),
  486. })
  487. }
  488. // if selector, err = mejson.Unmarshal(selector); err != nil {
  489. // return nil, Error(ERR_GENERAL, err.Error())
  490. // }
  491. }
  492. // Transform string HexId to ObjectIdHex
  493. // if selid, _ := selector[id].(string); selid != "" {
  494. // if bson.IsObjectIdHex(selid) {
  495. // selector[id] = bson.ObjectIdHex(selid)
  496. // }
  497. // // else {
  498. // // selector[id] = selid
  499. // // }
  500. // }
  501. return &selector, nil
  502. }
  503. func DefaultCorsHandler() func(ctx context.Context) {
  504. return Cors(CorsDefaultOptions)
  505. }
  506. func Cors(opt CorsOptions) func(ctx context.Context) {
  507. return func(ctx context.Context) {
  508. ctx.Header("Access-Control-Allow-Credentials", "true")
  509. if len(opt.AllowOrigin) > 0 {
  510. // ctx.Header("Access-Control-Allow-Origin", strings.Join(opt.AllowOrigin, ","))
  511. // ctx.Header("Access-Control-Allow-Origin", "*")
  512. // ctx.Header("Origin", "*")
  513. ctx.Header("Access-Control-Allow-Origin", ctx.GetHeader("Origin"))
  514. }
  515. if len(opt.AllowMethods) > 0 {
  516. ctx.Header("Access-Control-Allow-Methods", strings.Join(opt.AllowMethods, ","))
  517. }
  518. if len(opt.AllowHeaders) > 0 {
  519. ctx.Header("Access-Control-Allow-Headers", strings.Join(opt.AllowHeaders, ","))
  520. }
  521. if len(opt.ExposeHeaders) > 0 {
  522. ctx.Header("Access-Control-Expose-Headers", strings.Join(opt.ExposeHeaders, ","))
  523. }
  524. ctx.Next()
  525. }
  526. }
  527. // Retorna um valor de um parametro no path da url.
  528. func P(ctx context.Context, name string, def string) string {
  529. val := ctx.Params().Get(name)
  530. if val == "" {
  531. val = def
  532. }
  533. return val
  534. }
  535. //Retorna um valor de um parametro da query. Ex: ?x=1
  536. func Q(ctx context.Context, name string, def string) string {
  537. val := ctx.URLParam(name)
  538. if val == "" {
  539. val = def
  540. }
  541. return val
  542. }
  543. //Retorna um valor de um parametro da query
  544. func QInt(ctx context.Context, name string, def int) int {
  545. val, e := strconv.Atoi(Q(ctx, name, ""))
  546. if e != nil {
  547. val = def
  548. }
  549. return val
  550. }
  551. // Retorna um valor de um parametro do post.
  552. func F(ctx context.Context, name string, def interface{}) interface{} {
  553. var val interface{}
  554. val = ctx.FormValue(name)
  555. if val == "" {
  556. val = def
  557. }
  558. return val
  559. }
  560. func LogError(code int, m string) {
  561. log("31", fmt.Sprintf("[ERROR| %d] %s", code, m))
  562. }
  563. func LogInfo(code int, m string) {
  564. log("34", fmt.Sprintf("[INFO| %d] %s", code, m))
  565. }
  566. func LogWarning(code int, m string) {
  567. log("35", fmt.Sprintf("[WARNING| %d] %s", code, m))
  568. }
  569. func log(color string, m string) {
  570. fmt.Printf("\x1b[%s;1m%s\x1b[0m\n", color, m)
  571. }
  572. // func ParseRequestTest(ctx context.Context) {
  573. // var (
  574. // err error
  575. // filter = &Filter{
  576. // MaxResults: QInt(ctx, "maxResults", 10),
  577. // }
  578. // oid primitive.ObjectID
  579. // )
  580. // // parse parameter of path
  581. // id := P(ctx, "userId", "")
  582. // if oid, err = primitive.ObjectIDFromHex(id); err != nil {
  583. // filter.UserId = oid
  584. // }
  585. // id = P(ctx, "id", "")
  586. // if oid, err = primitive.ObjectIDFromHex(id); err != nil {
  587. // filter.Id = oid
  588. // }
  589. // // filter.PageToken.Parse(Q(ctx, "nextPageToken", ""))
  590. // if filter.Query, err = MgoQuery(ctx, "q"); err != nil {
  591. // goto Error
  592. // }
  593. // filter.Format = Q(ctx, "format", "full")
  594. // filter.Sort = MgoSortBson(MgoSort(ctx, "sort"))
  595. // filter.Fields = MgoFieldsCtx(ctx, "fields")
  596. // Error:
  597. // if err != nil {
  598. // ErroCtxHandler(
  599. // ctx,
  600. // // Error(ERR_INVALID_PARAM, err.Error()),
  601. // errs.Internal().Details(&errs.Detail{
  602. // Message: err.Error(),
  603. // }),
  604. // )
  605. // return
  606. // }
  607. // ctx.Values().Set("$filter", filter)
  608. // ctx.Next()
  609. // }
  610. // func MapError(erro *errs.Error) *errs.Error {
  611. // if strings.Contains(erro.Message, "E11000") {
  612. // return errs.AlreadyExists().Details(&errs.Detail{
  613. // Message: "DUPLICATED_ITEM",
  614. // })
  615. // } else if strings.Contains(erro.Message, "no documents in result") {
  616. // return errs.Internal().Details(&errs.Detail{
  617. // Message: "NOT_FOUND",
  618. // })
  619. // }
  620. // return erro
  621. // }
  622. // type PageToken struct {
  623. // // StartID string
  624. // // CurrentID string
  625. // Cursor string
  626. // NewCursor string
  627. // Page int
  628. // Count int
  629. // }
  630. // // Encode cria um novo token formatado
  631. // func (p *PageToken) Encode() string {
  632. // out := ""
  633. // if p.NewCursor != "" {
  634. // out = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%d", p.NewCursor, p.Count)))
  635. // }
  636. // return out
  637. // // return string([]byte(fmt.Sprintf("%s:%d", p.NewCursor, p.Count)))
  638. // }
  639. // // HasToken determina se a requisição apresenta um token de paginacao
  640. // func (p *PageToken) HasToken() bool {
  641. // return p.Cursor != ""
  642. // }
  643. // // func (p *PageToken) GetBsonID() bson.ObjectId {
  644. // // if !bson.IsObjectIdHex(p.ID) {
  645. // // return nil
  646. // // }
  647. // // return bson.ObjectIdHex(p.ID)
  648. // // }
  649. // func (p *PageToken) Parse(s string) error {
  650. // var (
  651. // decoded []byte
  652. // err error
  653. // )
  654. // if decoded, err = base64.StdEncoding.DecodeString(s); err != nil {
  655. // return err
  656. // }
  657. // match := pageTokenRegex.FindStringSubmatch(string(decoded))
  658. // if len(match) != 3 {
  659. // return fmt.Errorf("Invalid Page Token")
  660. // }
  661. // p.Cursor = match[1]
  662. // // p.Page, err = strconv.Atoi(match[2])
  663. // p.Count, err = strconv.Atoi(match[2])
  664. // return err
  665. // }
  666. // Layout aplica o path do layout
  667. // func Layout(ctx context.Context) {
  668. // ctx.ViewLayout(ViewScript(ctx, "layout/layout.html"))
  669. // ctx.Next()
  670. // }
  671. // // ViewScript devolve o path do arquivo de script a ser renderizaco
  672. // func ViewScript(ctx context.Context, filename string) string {
  673. // var (
  674. // base string
  675. // ok bool
  676. // )
  677. // domain := strings.Split(ctx.Request().Host, ":")[0]
  678. // if base, ok = TemplateDomainMap[domain]; !ok {
  679. // base = "default"
  680. // }
  681. // return base + "/" + filename
  682. // }
  683. // defer func() {
  684. // var (
  685. // erro *errs.Error
  686. // // ok bool
  687. // err error
  688. // )
  689. // if err = recover(); err != nil {
  690. // if erro, ok = err.(*errs.Error); !ok {
  691. // erro = Error(ERR_GENERAL, err.Error())
  692. // }
  693. // ErroCtxHandler(ctx, erro)
  694. // }
  695. // // ctx.Header("Accept", "application/json")
  696. // // spew.Dump(err)
  697. // }()
  698. // func CallAction(f func(context.Context, *ApiResponse) *errs.Error) func(ctx context.Context) {
  699. // return func(ctx context.Context) {
  700. // var (
  701. // err *errs.Error
  702. // response = &ApiResponse{}
  703. // )
  704. // if err = f(ctx, response); err != nil {
  705. // ErroCtxHandler(ctx, err)
  706. // return
  707. // }
  708. // ctx.JSON(response)
  709. // }
  710. // }
  711. // Verifica se existe alguma pagina para ser carragada.
  712. // func UpdateCursorResponse(models *Mongo, f *Filter, resp interface{}) bool {
  713. // count := f.PageToken.Count
  714. // // Se não foi encontrado nenhum registro
  715. // if count > 0 {
  716. // resp.ResultSizeEstimate = count
  717. // resp.NextPageToken = f.PageToken.Encode()
  718. // return true
  719. // }
  720. // return false
  721. // }