Browse Source

structure rewrite ongoing, user/token model added

master
Bernd-René Predota 5 years ago
parent
commit
e7d5c33638
  1. 1
      .gitignore
  2. 2
      README.md
  3. 4
      go.mod
  4. 52
      go.sum
  5. 132
      lib/cmd/cmd.go
  6. 33
      lib/cmd/cmd_test.go
  7. 126
      lib/common/common.go
  8. 2
      lib/config/config.go
  9. 17
      lib/database/database.go
  10. 60
      lib/utils/utils.go
  11. 180
      main.go
  12. 63
      models/token.go
  13. 70
      models/user.go
  14. 31
      pkg/user/database.go
  15. 16
      pkg/user/model.go
  16. 20
      pkg/user/repository.go
  17. 18
      pkg/user/service.go
  18. 53
      repositories/token.go
  19. 42
      repositories/user.go
  20. 35
      services/token.go
  21. 35
      services/user.go

1
.gitignore

@ -14,5 +14,6 @@ _vendor-*/
gin-bin
goAPISkel
goAPISkel.yml
config.yml
gorm.db
coverage.out

2
README.md

@ -1,6 +1,6 @@
# golang API Skeleton
[![Build Status](https://drone.devices.local/api/badges/mawas/golang-api-skeleton/status.svg)](https://drone.devices.local/mawas/golang-api-skeleton)<a href='https://github.com/jpoles1/gopherbadger' target='_blank'>![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-83%25-brightgreen.svg?longCache=true&style=flat)</a>
[![Build Status](https://drone.devices.local/api/badges/mawas/golang-api-skeleton/status.svg)](https://drone.devices.local/mawas/golang-api-skeleton)<a href='https://github.com/jpoles1/gopherbadger' target='_blank'>![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-77%25-brightgreen.svg?longCache=true&style=flat)</a>
refined skeleton future apis should be based on

4
go.mod

@ -3,11 +3,13 @@ module git.devices.local/mawas/golang-api-skeleton
go 1.15
require (
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 // indirect
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
github.com/dgraph-io/badger/v2 v2.2007.2 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
github.com/google/uuid v1.2.0
github.com/magiconair/properties v1.8.4 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/pelletier/go-toml v1.8.1 // indirect

52
go.sum

@ -11,16 +11,18 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
@ -28,16 +30,21 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -45,10 +52,17 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k=
github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA=
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@ -77,7 +91,10 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -86,6 +103,8 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
@ -182,9 +201,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@ -198,7 +215,7 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@ -223,7 +240,6 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@ -232,7 +248,6 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
@ -257,6 +272,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
@ -267,7 +283,6 @@ github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhr
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@ -277,24 +292,23 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg=
github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
@ -309,7 +323,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@ -324,6 +340,7 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@ -366,6 +383,7 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -381,6 +399,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -391,19 +410,18 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -460,9 +478,9 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@ -470,9 +488,7 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

132
lib/cmd/cmd.go

@ -1,61 +1,77 @@
package cmd
import (
"fmt"
"os"
"git.devices.local/mawas/golang-api-skeleton/lib/config"
"github.com/spf13/cobra"
)
var (
Version string
APPName string
APPDescription string
)
// TODO add shell completion
var rootCmd = &cobra.Command{
Use: APPName,
Short: APPDescription,
Long: APPDescription,
// SilenceUsage: true,
// SilenceErrors: true,
Run: func(cmd *cobra.Command, args []string) {
},
func newRootCmd(appName string, appDescription string) *cobra.Command {
return &cobra.Command{
Use: appName,
Short: appDescription,
Long: appDescription,
// SilenceUsage: true,
// SilenceErrors: true,
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
},
}
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number",
Long: "Print the version number",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(APPName, "version:", Version)
os.Exit(0)
},
func newVersionCmd(version string, appName string) *cobra.Command {
return &cobra.Command{
Use: "version",
Aliases: []string{"Version"},
Short: "Print the version number",
Long: "Print the version number",
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
cmd.Println(appName, "version", version)
os.Exit(0)
},
}
}
var sampleCfgCmd = &cobra.Command{
Use: "sample-config",
Short: "Print sample config",
Long: "Print an example configuration file content",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(config.Sample)
os.Exit(0)
},
func newSampleCfgCmd() *cobra.Command {
return &cobra.Command{
Use: "sample-config",
Short: "Print sample config",
Long: "Print an example configuration file content",
Run: func(cmd *cobra.Command, args []string) {
cmd.Println(config.Sample)
os.Exit(0)
},
}
}
func newSampleCLICmd() *cobra.Command {
return &cobra.Command{
Use: "cli",
Short: "Interactive CLI",
Long: "Interactive CLI maybe",
Run: func(cmd *cobra.Command, args []string) {
cmd.Println("here might be an cli")
os.Exit(0)
},
}
}
func Initialize(version string, appName string, appDescription string) error {
func Initialize(version string, appName string, appDescription string) (string, map[string]interface{}, error) {
var cfgFile string
Version = version
APPName = appName
APPDescription = appDescription
rootCmd := newRootCmd(appName, appDescription)
rootCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
if err := cmd.Usage(); err != nil {
os.Exit(1)
}
os.Exit(0)
})
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(sampleCfgCmd)
rootCmd.AddCommand(newVersionCmd(version, appName))
rootCmd.AddCommand(newSampleCfgCmd())
// rootCmd.AddCommand(newSampleCLICmd())
rootCmd.Flags().StringVarP(&cfgFile, "config", "c", "", "config file")
flagCfg := map[string]interface{}{
@ -73,10 +89,44 @@ func Initialize(version string, appName string, appDescription string) error {
"database.maxlifetime": rootCmd.Flags().IntP("database-maxlifetime", "t", 0, "database max connection lifetime"),
}
if err := rootCmd.Execute(); err != nil {
return err
}
if err := config.Initialize(appName, cfgFile, flagCfg); err != nil {
return err
return cfgFile, flagCfg, err
}
return nil
return cfgFile, flagCfg, nil
}
// func Initialize(version string, appName string, appDescription string) error {
// var cfgFile string
// rootCmd := newRootCmd(appName, appDescription)
// rootCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
// if err := cmd.Usage(); err != nil {
// os.Exit(1)
// }
// os.Exit(0)
// })
// rootCmd.AddCommand(newVersionCmd(version, appName))
// rootCmd.AddCommand(newSampleCfgCmd())
// // rootCmd.AddCommand(newSampleCLICmd())
//
// rootCmd.Flags().StringVarP(&cfgFile, "config", "c", "", "config file")
// flagCfg := map[string]interface{}{
// "application.environment": rootCmd.Flags().StringP("environment", "e", "", "application environment"),
// "application.listenaddress": rootCmd.Flags().StringP("listenaddress", "l", "", "application listenaddress or host"),
// "application.port": rootCmd.Flags().IntP("port", "p", 0, "application listenport"),
// "database.host": rootCmd.Flags().StringP("database-host", "H", "", "database host"),
// "database.port": rootCmd.Flags().IntP("database-port", "P", 0, "database port"),
// "database.dialect": rootCmd.Flags().StringP("database-dialect", "D", "", "database dialect"),
// "database.database": rootCmd.Flags().StringP("database-name", "d", "", "database name"),
// "database.user": rootCmd.Flags().StringP("database-user", "u", "", "database user"),
// "database.password": rootCmd.Flags().StringP("database-password", "s", "", "database password"),
// "database.maxopenconn": rootCmd.Flags().IntP("database-maxopen", "o", 0, "database max open connections"),
// "database.maxidleconn": rootCmd.Flags().IntP("database-maxidle", "i", 0, "database max idle connections"),
// "database.maxlifetime": rootCmd.Flags().IntP("database-maxlifetime", "t", 0, "database max connection lifetime"),
// }
// if err := rootCmd.Execute(); err != nil {
// return err
// }
// if err := config.Initialize(appName, cfgFile, flagCfg); err != nil {
// return err
// }
// return nil
// }

33
lib/cmd/cmd_test.go

@ -4,11 +4,34 @@ import (
"testing"
)
// func TestVersion(t *testing.T) {
// // FIXME maybe PanicOnExit0 can help regarding unexpected call to os.Exit(0) during test
// appname := "unittest"
// version := "0.0.1"
// cmd := newVersionCmd(version, appname)
// b := bytes.NewBufferString("")
// cmd.SetOut(b)
// if err := cmd.Execute(); err != nil {
// t.Fatal(err)
// }
// out, err := ioutil.ReadAll(b)
// if err != nil {
// t.Fatal(err)
// }
// expected := appname + " version " + version
// got := strings.TrimSpace(string(out))
// if got != expected {
// t.Fatalf("expected \"%s\" got \"%s\"", expected, got)
// }
// }
func TestInitalize(t *testing.T) {
args := []string{"--database-user", "unittest"}
rootCmd.SetArgs(args)
if err := Initialize("0.0.1", "unittest", ""); err != nil {
t.Errorf("%v\n", err)
_, flagCfg, err := Initialize("0.0.1", "unittest", "")
if err != nil {
t.Fatal(err)
}
if len(flagCfg) == 0 {
t.Fatal("flag configuration missing")
}
}
@ -19,6 +42,6 @@ func TestInitalize(t *testing.T) {
// t.Errorf("%v\n", err)
// }
// if err := Initialize("0.0.1", "unittest", ""); err != nil {
// t.Errorf("%v\n", err)
// t.Errorf("%v\n", err)
// }
// }

126
lib/common/common.go

@ -0,0 +1,126 @@
package common
import (
"database/sql/driver"
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type UsernameContextKey string
// GUID -> new datatype
type GUID uuid.UUID
// StringToGUID -> parse string to GUID
func StringToGUID(s string) (GUID, error) {
id, err := uuid.Parse(s)
return GUID(id), err
}
// String -> String Representation of Binary16
func (guid GUID) String() string {
return uuid.UUID(guid).String()
}
// GormDataType -> sets type to binary(16)
func (guid GUID) GormDataType() string {
return "binary(16)"
}
func (guid GUID) MarshalJSON() ([]byte, error) {
s := uuid.UUID(guid)
str := "\"" + s.String() + "\""
return []byte(str), nil
}
func (guid *GUID) UnmarshalJSON(by []byte) error {
s, err := uuid.ParseBytes(by)
*guid = GUID(s)
return err
}
// Scan --> tells GORM how to receive from the database
func (guid *GUID) Scan(value interface{}) error {
bytes, _ := value.([]byte)
parseByte, err := uuid.FromBytes(bytes)
*guid = GUID(parseByte)
return err
}
// Value -> tells GORM how to save into the database
func (guid GUID) Value() (driver.Value, error) {
return uuid.UUID(guid).MarshalBinary()
}
type BasicFields struct {
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
CreatedByDB GUID `gorm:"column:created_by" json:"-"`
CreatedByJSON string `gorm:"-" json:"created_by"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
UpdatedByDB GUID `gorm:"column:updated_by" json:"-"`
UpdatedByJSON string `gorm:"-" json:"updated_by"`
DeletedAtDB gorm.DeletedAt `gorm:"column:deleted_at" json:"-"`
DeletedAtJSON *time.Time `gorm:"-" json:"deleted_at,omitempty"`
DeletedBy string `gorm:"column:deleted_by" json:"deleted_by,omitempty"`
}
func (basicFields *BasicFields) BeforeCreate(tx *gorm.DB) error {
if userID, ok := tx.Get("userID"); ok {
if guid, ok := userID.(GUID); ok {
basicFields.CreatedByDB = guid
basicFields.UpdatedByDB = guid
}
}
return nil
}
func (basicFields *BasicFields) AfterCreate(tx *gorm.DB) error {
if username, ok := tx.Get("username"); ok {
if name, ok := username.(string); ok {
basicFields.CreatedByJSON = name
basicFields.UpdatedByJSON = name
}
}
return nil
}
type GUIDPKicPK struct {
ID uint64 `gorm:"primaryKey;column:id" json:"id"`
BasicFields
}
type ModelGUIDPK struct {
ID GUID `gorm:"primaryKey;column:id" json:"id"`
BasicFields
}
func (guidPK *ModelGUIDPK) BeforeCreate(tx *gorm.DB) error {
id, err := uuid.NewRandom()
guidPK.ID = GUID(id)
if userID, ok := tx.Get("userID"); ok {
if guid, ok := userID.(GUID); ok {
guidPK.CreatedByDB = guid
guidPK.UpdatedByDB = guid
}
}
return err
}
type ModelHiddenGUIDPK struct {
ID GUID `gorm:"primaryKey;column:id" json:"-"`
BasicFields
}
func (guidPK *ModelHiddenGUIDPK) BeforeCreate(tx *gorm.DB) error {
id, err := uuid.NewRandom()
guidPK.ID = GUID(id)
if userID, ok := tx.Get("userID"); ok {
if guid, ok := userID.(GUID); ok {
guidPK.CreatedByDB = guid
guidPK.UpdatedByDB = guid
}
}
return err
}

2
lib/config/config.go

@ -121,7 +121,7 @@ func validateEnvironment(environment string) error {
func validateDatabaseDialect(dialect string) error {
if err := validation.Validate(
dialect,
validation.In(MYSQL, POSTGRES, MSSQL),
validation.In(MYSQL, POSTGRES, MSSQL, "sqlite"),
); err != nil {
return fmt.Errorf(
"database.dialect (must be one of %s, %s or %s)",

17
lib/database/database.go

@ -1,14 +1,18 @@
package database
import (
"log"
"os"
"strconv"
"strings"
"time"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Credentials struct {
@ -59,13 +63,22 @@ func (c *Credentials) getDSN() gorm.Dialector {
" sslmode=disable connect_timeout=5"
return postgres.Open(dsn)
case "sqlite":
return sqlite.Open("gorm.db")
// return sqlite.Open("gorm.db")
return sqlite.Open("file::memory:?cache=shared")
}
return nil
}
func Connect(c Credentials) (*gorm.DB, error) {
db, err := gorm.Open(c.getDSN(), &gorm.Config{})
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Info, // Log level
Colorful: true, // Disable color
},
)
db, err := gorm.Open(c.getDSN(), &gorm.Config{Logger: newLogger})
if err != nil {
return nil, err
}

60
lib/utils/utils.go

@ -0,0 +1,60 @@
package utils
import (
"encoding/json"
"fmt"
"math/rand"
"strings"
"time"
)
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
func RandString(n int) string {
var src = rand.NewSource(time.Now().UnixNano())
sb := strings.Builder{}
sb.Grow(n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
sb.WriteByte(letterBytes[idx])
i--
}
cache >>= letterIdxBits
remain--
}
return sb.String()
}
func RandInt(s int, e int) int {
var integer int
for {
integer = rand.Intn(e)
if integer > s {
break
}
}
return integer
}
func PrettyPrintJSON(s interface{}) {
switch s.(type) {
case string:
var j map[string]interface{}
json.Unmarshal([]byte(s.(string)), &j)
// jsonString, _ := json.MarshalIndent(j, "", " ")
jsonString, _ := json.Marshal(j)
fmt.Println(string(jsonString))
default:
jsonString, _ := json.MarshalIndent(s, "", " ")
fmt.Println(string(jsonString))
}
}

180
main.go

@ -1,14 +1,37 @@
package main
import (
"fmt"
"os"
"strings"
"time"
"git.devices.local/mawas/golang-api-skeleton/lib/cache"
"git.devices.local/mawas/golang-api-skeleton/lib/cmd"
"git.devices.local/mawas/golang-api-skeleton/lib/common"
"git.devices.local/mawas/golang-api-skeleton/lib/config"
"git.devices.local/mawas/golang-api-skeleton/lib/database"
"git.devices.local/mawas/golang-api-skeleton/lib/utils"
"git.devices.local/mawas/golang-api-skeleton/models"
"git.devices.local/mawas/golang-api-skeleton/repositories"
"git.devices.local/mawas/golang-api-skeleton/services"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
// https://towardsdatascience.com/building-restful-apis-in-golang-e3fe6e3f8f95
// https://www.voile.com/voile-straps.html
// FIXME how to set unique index for username to make soft deletes possible but disallow duplicates... also how to cache a username which got delete and recerated... user ID would get overwritten, maybe pre/suffix deleted username?
// TODO replace uuids with ulids
// TODO use badgerdb for permissions? path:[token1, token2...]
// TODO add database loadbalancing feature... so allow more hosts use first as default and other ones as fallback
// TODO add userid and username to repo
// TODO usrid and username for cli user is hardcoded.. no need to live in database
// TODO get-stats cli command... which means unix socket support to communicate with server
// TODO data versioning which will be used as reference from the log, also with predictive analytics for restore which means versioning of reference objects needs to be considered
// TODO request body store as reference for log
// TODO because their is a badgerdb cache which tokens are existing or which userids are existing make an existence check at uuid generation just do be sure
var (
Version string // allows to set version on build
APPName string // allows to overwrite app name on build
@ -27,16 +50,153 @@ func main() {
"version": Version,
"app": APPName,
})
// config priority: flags > env > config file
// cobra sets env if flag is given so that viper can pick it up
if err := cmd.Initialize(Version, APPName, APPDescription); err != nil {
cfgFile, flagCfg, err := cmd.Initialize(Version, APPName, APPDescription)
if err != nil {
os.Exit(1)
}
// config priority: flags > env > config file
if err := config.Initialize(APPName, cfgFile, flagCfg); err != nil {
contextLogger.WithFields(log.Fields{
"module": "config",
}).Fatal(err)
}
// bootstrap cache
c, err := cache.Bootstrap()
if err != nil {
contextLogger.WithFields(log.Fields{
"module": "cache",
}).Fatal(err)
}
defer c.Close()
db, err := database.Connect(database.Credentials{
Host: viper.GetString("database.host"),
Port: viper.GetInt("database.port"),
Dialect: viper.GetString("database.dialect"),
Database: viper.GetString("database.database"),
User: viper.GetString("database.user"),
Password: viper.GetString("database.password"),
MaxOpenConn: viper.GetInt("database.port"),
MaxIdleConn: viper.GetInt("database.port"),
MaxLifeTime: viper.GetInt("database.port"),
Debug: true,
})
if err != nil {
contextLogger.WithFields(log.Fields{
"module": "database",
}).Fatal(err)
}
db.AutoMigrate(&models.User{})
db.AutoMigrate(&models.Token{})
userRepo := repositories.NewUserRepository(db, common.GUID{}, "", nil)
userService := services.NewUserService(userRepo)
// Prefill cache
// TODO also add deleted users to cache for old references
if userData, err := userService.ReadAll(); err != nil {
contextLogger.WithFields(log.Fields{
"module": "userService",
}).Fatal(err)
} else {
for i := range userData {
if err := c.Set("user:"+userData[i].ID.String(), userData[i].Username); err != nil { // userID -> username mapping
contextLogger.WithFields(log.Fields{
"module": "cache",
}).Fatal(err)
}
if err := c.Set("user:"+userData[i].Username, userData[i].ID.String()); err != nil { // username -> userID mapping
contextLogger.WithFields(log.Fields{
"module": "cache",
}).Fatal(err)
}
}
}
var userID common.GUID
firstname := strings.ToLower(utils.RandString(utils.RandInt(5, 10)))
lastname := strings.ToLower(utils.RandString(utils.RandInt(6, 14)))
username := string([]byte(firstname)[0]) + lastname
user1 := &models.User{
Username: username,
Firstname: strings.ToUpper(string([]byte(firstname)[0])) + string([]byte(firstname)[1:]),
Lastname: strings.ToUpper(string([]byte(lastname)[0])) + string([]byte(lastname)[1:]),
Email: username + "@acme.inc",
}
if result, err := userService.Create(user1); err != nil {
panic(err)
} else {
utils.PrettyPrintJSON(result)
if err := c.Set("user:"+result.ID.String(), result.Username); err != nil { // userID -> username mapping
contextLogger.WithFields(log.Fields{
"module": "cache",
}).Fatal(err)
}
if err := c.Set("user:"+result.Username, result.ID.String()); err != nil { // username -> userID mapping
contextLogger.WithFields(log.Fields{
"module": "cache",
}).Fatal(err)
}
userID = result.ID
}
userRepo = repositories.NewUserRepository(db, userID, username, c)
userService = services.NewUserService(userRepo)
// userID db context?
// k := common.UsernameContextKey("username")
// ctx := context.WithValue(context.Background(), "username", username)
// db = db.WithContext(ctx)
// db = db.Set("username", username)
// fmt.Println(db.Get("username"))
// create example token
tokenRepo := repositories.NewTokenRepository(db, userID, username, c)
tokenService := services.NewTokenService(tokenRepo)
token1 := &models.Token{
ExpiresAt: time.Now().Add(24 * time.Hour),
UserID: userID,
Active: true,
}
if result1, err := tokenService.Create(token1); err != nil {
panic(err)
} else {
utils.PrettyPrintJSON(result1)
}
result1, err := tokenService.ReadAll()
if err != nil {
panic(err)
}
utils.PrettyPrintJSON(result1)
result, err := userService.ReadAll()
if err != nil {
panic(err)
}
utils.PrettyPrintJSON(result)
firstname2 := strings.ToLower(utils.RandString(utils.RandInt(5, 10)))
lastname2 := strings.ToLower(utils.RandString(utils.RandInt(6, 14)))
username2 := string([]byte(firstname2)[0]) + lastname2
user2 := &models.User{
Username: username2,
Firstname: strings.ToUpper(string([]byte(firstname2)[0])) + string([]byte(firstname2)[1:]),
Lastname: strings.ToUpper(string([]byte(lastname2)[0])) + string([]byte(lastname2)[1:]),
Email: username2 + "@acme.inc",
}
if result, err := userService.Create(user2); err != nil {
panic(err)
} else {
utils.PrettyPrintJSON(result)
result3, err := userService.ReadByID(result.Username)
if err != nil {
panic(err)
}
utils.PrettyPrintJSON(result3)
}
// db, _ := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
// db.AutoMigrate(&user.User{})
// userRepo := user.NewRepository(db)
// userService := user.NewService(userRepo)
// user1 := &user.User{
@ -51,8 +211,12 @@ func main() {
// }
// fmt.Println(result)
fmt.Println("main.go --> Environment:", viper.GetString("application.environment"))
fmt.Println("main.go --> Listen:", viper.GetString("application.listenaddress"))
fmt.Println("main.go --> Database Port: ", viper.GetInt("database.port"))
fmt.Println("main.go --> Application Port:", viper.GetInt("application.port"))
// fmt.Println("main.go --> Environment:", viper.GetString("application.environment"))
// fmt.Println("main.go --> Listen:", viper.GetString("application.listenaddress"))
// fmt.Println("main.go --> Database Port: ", viper.GetInt("database.port"))
// fmt.Println("main.go --> Application Port:", viper.GetInt("application.port"))
// contextLogger.WithFields(log.Fields{
// "module": "config",
// }).Fatal("ADSADSASd")
}

63
models/token.go

@ -0,0 +1,63 @@
package models
import (
"database/sql"
"time"
"git.devices.local/mawas/golang-api-skeleton/lib/cache"
"git.devices.local/mawas/golang-api-skeleton/lib/common"
"github.com/google/uuid"
"gorm.io/gorm"
)
// Token data model
type Token struct {
common.BasicFields
Token common.GUID `gorm:"primaryKey" json:"token"`
LastUsedDB sql.NullTime `gorm:"column:last_used" json:"-"`
LastUsedJSON *time.Time `gorm:"-" json:"last_used,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
UserID common.GUID `json:"asd"`
Username string `json:"username"`
Active bool `json:"active"`
}
func (token *Token) BeforeCreate(tx *gorm.DB) error {
id, err := uuid.NewRandom()
token.Token = common.GUID(id)
if userID, ok := tx.Get("userID"); ok {
if guid, ok := userID.(common.GUID); ok {
token.CreatedByDB = guid
token.UpdatedByDB = guid
}
}
return err
}
func (token *Token) AfterFind(tx *gorm.DB) error {
if token.LastUsedDB.Valid {
token.LastUsedJSON = &token.LastUsedDB.Time
}
if token.DeletedAtDB.Valid {
token.DeletedAtJSON = &token.DeletedAtDB.Time
}
if cc, ok := tx.Get("cache"); ok {
if c, ok := cc.(cache.Cache); ok {
if username, err := c.Get("user:" + token.CreatedByDB.String()); err != nil {
return err
} else if username != nil {
token.CreatedByJSON = *username
}
if username, err := c.Get("user:" + token.UpdatedByDB.String()); err != nil {
return err
} else if username != nil {
token.UpdatedByJSON = *username
}
if username, err := c.Get("user:" + token.UserID.String()); err != nil {
} else if username != nil {
token.Username = *username
}
}
}
return nil
}

70
models/user.go

@ -0,0 +1,70 @@
package models
import (
"git.devices.local/mawas/golang-api-skeleton/lib/cache"
"git.devices.local/mawas/golang-api-skeleton/lib/common"
"gorm.io/gorm"
)
// User data model
type User struct {
common.ModelHiddenGUIDPK
Username string `gorm:"unique_index:username" json:"username,omitempty"`
Firstname string `json:"firstname,omitempty"`
Lastname string `json:"lastname,omitempty"`
Email string `json:"email,omitempty"`
TokensRef []Token `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"`
Tokens []string `gorm:"-" json:"tokens"`
PasswordHash string `json:"-"`
Active bool ` json:"active"`
}
func (user *User) AfterCreate(tx *gorm.DB) error {
if username, ok := tx.Get("username"); ok {
if name, ok := username.(string); ok {
user.CreatedByJSON = name
user.UpdatedByJSON = name
}
}
user.Tokens = []string{}
return nil
}
func (user *User) AfterFind(tx *gorm.DB) error {
if user.DeletedAtDB.Valid {
user.DeletedAtJSON = &user.DeletedAtDB.Time
}
for i := range user.TokensRef {
user.Tokens = append(user.Tokens, user.TokensRef[i].Token.String())
}
if len(user.Tokens) == 0 {
user.Tokens = []string{""}
}
if cc, ok := tx.Get("cache"); ok {
if c, ok := cc.(cache.Cache); ok {
if username, err := c.Get("user:" + user.CreatedByDB.String()); err != nil {
return err
} else if username != nil {
user.CreatedByJSON = *username
}
if username, err := c.Get("user:" + user.UpdatedByDB.String()); err != nil {
return err
} else if username != nil {
user.UpdatedByJSON = *username
}
}
}
return nil
}
// func (user *User) BeforeCreate(tx *gorm.DB) error {
// // ctx := tx.Statement.Context
// // username := ctx.Value("username")
// // switch v := username.(type) {
// // case nil:
// // case string:
// // user.CreatedBy = v
// // }
// //
// return nil
// }

31
pkg/user/database.go

@ -1,31 +0,0 @@
package user
import "gorm.io/gorm"
type repo struct {
db *gorm.DB
}
// NewRepository create new repository
func NewRepository(db *gorm.DB) Repository {
return &repo{
db: db,
}
}
func (r *repo) ReadByID(id uint) (*User, error) {
result := User{}
err := r.db.First(&result, id).Error
return &result, err
}
func (r *repo) ReadAll() ([]*User, error) {
var result []*User
err := r.db.Find(&result).Error
return result, err
}
func (r *repo) Create(user *User) (*User, error) {
err := r.db.Create(user).Error
return user, err
}

16
pkg/user/model.go

@ -1,16 +0,0 @@
package user
import (
"gorm.io/gorm"
)
// User data model
type User struct {
gorm.Model
Username string `gorm:"unique_index:username" json:"username,omitempty"`
Firstname string `json:"firstname,omitempty"`
Lastname string `json:"lastname,omitempty"`
Email string `json:"email,omitempty"`
PasswordHash string `json:"-"`
Active bool ` json:"active"`
}

20
pkg/user/repository.go

@ -1,20 +0,0 @@
package user
// Reader
type Reader interface {
ReadByID(id uint) (*User, error)
ReadAll() ([]*User, error)
}
// Writer
type Writer interface {
// Update(user *User) error
Create(user *User) (*User, error)
// Delete(user *User) (uint64, error)
}
// Repository repository interface
type Repository interface {
Reader
Writer
}

18
pkg/user/service.go

@ -1,18 +0,0 @@
package user
// Service service interface
type Service interface {
Reader
Writer
// Register(user *User) (entity.ID, error)
// ForgotPassword(user *User) error
// ChangePassword(user *User, password string) error
// Validate(user *User) error
// Auth(user *User, password string) error
// IsValid(user *User) bool
// GetRepo() Repository
}
func NewService(repo Repository) Service {
return repo
}

53
repositories/token.go

@ -0,0 +1,53 @@
// Data access objects layer of model token
package repositories
import (
"git.devices.local/mawas/golang-api-skeleton/lib/cache"
"git.devices.local/mawas/golang-api-skeleton/lib/common"
model "git.devices.local/mawas/golang-api-skeleton/models"
"gorm.io/gorm"
)
type tokenDAO struct {
repo
}
// NewTokenRepository create new repository for model token
func NewTokenRepository(db *gorm.DB, userID common.GUID, username string, cache cache.Cache) *tokenDAO {
db = db.Set("username", username).Set("userID", userID).Set("cache", cache)
return &tokenDAO{
repo: repo{
db: db,
userID: userID,
username: username,
},
}
}
func (dao *tokenDAO) ReadByKey(key interface{}) (*model.Token, error) {
token := model.Token{}
err := dao.db.Joins("User").First(&token, key).Error
return &token, err
}
func (dao *tokenDAO) ReadAll() ([]*model.Token, error) {
var tokens []*model.Token
err := dao.db.Find(&tokens).Error
return tokens, err
}
func (dao *tokenDAO) Create(token *model.Token) (*model.Token, error) {
err := dao.db.Create(token).Error
if cc, ok := dao.db.Get("cache"); ok {
if c, ok := cc.(cache.Cache); ok {
if username, err := c.Get("user:" + token.UserID.String()); err != nil {
return nil, err
} else {
if username != nil {
token.Username = *username
}
}
}
}
return token, err
}

42
repositories/user.go

@ -0,0 +1,42 @@
// Data access objects layer of model user
package repositories
import (
"git.devices.local/mawas/golang-api-skeleton/lib/cache"
"git.devices.local/mawas/golang-api-skeleton/lib/common"
model "git.devices.local/mawas/golang-api-skeleton/models"
"gorm.io/gorm"
)
type UserDAO struct {
repo
}
// NewUserDAO create new repository for model user
func NewUserRepository(db *gorm.DB, userID common.GUID, username string, cache cache.Cache) *UserDAO {
db = db.Set("username", username).Set("userID", userID).Set("cache", cache)
return &UserDAO{
repo: repo{
db: db,
userID: userID,
username: username,
},
}
}
func (dao *UserDAO) ReadByUsername(username string) (*model.User, error) {
result := model.User{}
err := dao.db.Where(&model.User{Username: username}).First(&result).Error
return &result, err
}
func (dao *UserDAO) ReadAll() ([]*model.User, error) {
var result []*model.User
err := dao.db.Preload("TokensRef").Find(&result).Error
return result, err
}
func (dao *UserDAO) Create(user *model.User) (*model.User, error) {
err := dao.db.Create(user).Error
return user, err
}

35
services/token.go

@ -0,0 +1,35 @@
package services
import (
model "git.devices.local/mawas/golang-api-skeleton/models"
)
type tokenRepository interface {
ReadByKey(key interface{}) (*model.Token, error)
ReadAll() ([]*model.Token, error)
Create(token *model.Token) (*model.Token, error)
}
type TokenService struct {
repo tokenRepository
}
// NewTokenService creates a new TokenService with the given user DAO.
func NewTokenService(repo tokenRepository) *TokenService {
return &TokenService{repo}
}
// ReadByKey just retrieves user using User DAO, here can be additional logic for processing data retrieved by DAOs
func (s *TokenService) ReadByKey(key interface{}) (*model.Token, error) {
return s.repo.ReadByKey(key)
}
// ReadAll just retrieves user using User DAO, here can be additional logic for processing data retrieved by DAOs
func (s *TokenService) ReadAll() ([]*model.Token, error) {
return s.repo.ReadAll()
}
// Create just retrieves user using User DAO, here can be additional logic for processing data retrieved by DAOs
func (s *TokenService) Create(token *model.Token) (*model.Token, error) {
return s.repo.Create(token)
}

35
services/user.go

@ -0,0 +1,35 @@
package services
import (
model "git.devices.local/mawas/golang-api-skeleton/models"
)
type userRepository interface {
ReadByUsername(username string) (*model.User, error)
ReadAll() ([]*model.User, error)
Create(user *model.User) (*model.User, error)
}
type UserService struct {
repo userRepository
}
// NewUserService creates a new UserService with the given user DAO.
func NewUserService(repo userRepository) *UserService {
return &UserService{repo}
}
// ReadByUsername just retrieves user using User DAO, here can be additional logic for processing data retrieved by DAOs
func (s *UserService) ReadByID(id interface{}) (*model.User, error) {
return s.repo.ReadByUsername(id.(string))
}
// ReadAll just retrieves user using User DAO, here can be additional logic for processing data retrieved by DAOs
func (s *UserService) ReadAll() ([]*model.User, error) {
return s.repo.ReadAll()
}
// Create just retrieves user using User DAO, here can be additional logic for processing data retrieved by DAOs
func (s *UserService) Create(user *model.User) (*model.User, error) {
return s.repo.Create(user)
}
Loading…
Cancel
Save