utils.go 22 KB

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