Skip to content

Commit ad836d0

Browse files
committed
[attachments] add module an API
1 parent 7f79126 commit ad836d0

29 files changed

Lines changed: 1056 additions & 55 deletions

.golangci.yml

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ formatters:
2323
- goimports # checks if the code and import statements are formatted according to the 'goimports' command
2424
- golines # checks if code is formatted, and fixes long lines
2525
- swaggo # formats swaggo comments
26-
2726
## you may want to enable
2827
#- gci # checks if code and import statements are formatted, with additional rules
2928
#- gofmt # checks if the code is formatted according to 'gofmt' command
3029
#- gofumpt # enforces a stricter format than 'gofmt', while being backwards compatible
3130

32-
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
31+
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
3332
settings:
3433
golines:
3534
# Target maximum line length.
@@ -118,7 +117,6 @@ linters:
118117
- wastedassign # finds wasted assignment statements
119118
- whitespace # detects leading and trailing whitespace
120119
- wrapcheck # checks that errors returned from external packages are wrapped
121-
122120
## you may want to enable
123121
#- arangolint # opinionated best practices for arangodb client
124122
#- decorder # checks declaration order and count of types, constants, variables and functions
@@ -155,7 +153,7 @@ linters:
155153
#- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines
156154
#- wsl_v5 # [too strict and mostly code is not more readable] add or remove empty lines
157155

158-
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
156+
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
159157
settings:
160158
cyclop:
161159
# The maximal code complexity to report.
@@ -196,7 +194,8 @@ linters:
196194
# Default: []
197195
deny:
198196
- pkg: github.com/golang/protobuf
199-
desc: Use google.golang.org/protobuf instead, see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules
197+
desc: Use google.golang.org/protobuf instead, see
198+
https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules
200199
- pkg: github.com/satori/go.uuid
201200
desc: Use github.com/google/uuid instead, satori's package is not maintained
202201
- pkg: github.com/gofrs/uuid$
@@ -262,6 +261,7 @@ linters:
262261
- ^github.com/go-telegram/bot/models.+$
263262
- ^github.com/gofiber/.+Config$
264263
- ^github.com/golang-jwt/jwt/v5.+Claims$
264+
- ^github.com/minio/minio-go/.+Options$
265265
- ^github.com/mitchellh/mapstructure.DecoderConfig$
266266
- ^github.com/mymmrac/telego.+Params$
267267
- ^github.com/prometheus/client_golang/.+Opts$
@@ -395,7 +395,7 @@ linters:
395395
nolintlint:
396396
# Exclude following linters from requiring an explanation.
397397
# Default: []
398-
allow-no-explanation: [funlen, gocognit, golines]
398+
allow-no-explanation: [ funlen, gocognit, golines ]
399399
# Enable to require an explanation of nonzero length after each nolint directive.
400400
# Default: false
401401
require-explanation: true
@@ -475,20 +475,21 @@ linters:
475475
# Excluding configuration per-path, per-linter, per-text and per-source.
476476
rules:
477477
- source: "TODO"
478-
linters: [godot]
478+
linters: [ godot ]
479479
- text: "should have a package comment"
480-
linters: [revive]
480+
linters: [ revive ]
481481
- text: "avoid package names that conflict with Go standard library package names"
482-
linters: [revive]
483-
- text: 'exported \S+ \S+ should have comment( \(or a comment on this block\))? or be unexported'
484-
linters: [revive]
485-
- text: 'package comment should be of the form ".+"'
482+
linters: [ revive ]
483+
- text: "exported \\S+ \\S+ should have comment( \\(or a comment on this
484+
block\\))? or be unexported"
485+
linters: [ revive ]
486+
- text: "package comment should be of the form \".+\""
486487
source: "// ?(nolint|TODO)"
487-
linters: [revive]
488-
- text: 'comment on exported \S+ \S+ should be of the form ".+"'
488+
linters: [ revive ]
489+
- text: "comment on exported \\S+ \\S+ should be of the form \".+\""
489490
source: "// ?(nolint|TODO)"
490-
linters: [revive, staticcheck]
491-
- path: '_test\.go'
491+
linters: [ revive, staticcheck ]
492+
- path: "_test\\.go"
492493
linters:
493494
- bodyclose
494495
- dupl

go.mod

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
github.com/golang-jwt/jwt/v5 v5.3.1
1818
github.com/google/uuid v1.6.0
1919
github.com/gosimple/slug v1.15.0
20+
github.com/minio/minio-go/v7 v7.0.100
2021
github.com/pressly/goose/v3 v3.27.0
2122
github.com/prometheus/client_golang v1.23.2
2223
github.com/samber/lo v1.52.0
@@ -25,7 +26,7 @@ require (
2526
github.com/uptrace/bun/dialect/mysqldialect v1.2.18
2627
go.uber.org/fx v1.24.0
2728
go.uber.org/zap v1.27.1
28-
golang.org/x/crypto v0.49.0
29+
golang.org/x/crypto v0.50.0
2930
)
3031

3132
require (
@@ -39,9 +40,11 @@ require (
3940
github.com/beorn7/perks v1.0.1 // indirect
4041
github.com/cespare/xxhash/v2 v2.3.0 // indirect
4142
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
43+
github.com/dustin/go-humanize v1.0.1 // indirect
4244
github.com/fsnotify/fsnotify v1.9.0 // indirect
4345
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
4446
github.com/go-core-fx/fxutil v0.0.0-20251027105421-acea37162eb9 // indirect
47+
github.com/go-ini/ini v1.67.0 // indirect
4548
github.com/go-openapi/jsonpointer v0.19.5 // indirect
4649
github.com/go-openapi/jsonreference v0.19.6 // indirect
4750
github.com/go-openapi/spec v0.20.4 // indirect
@@ -56,6 +59,8 @@ require (
5659
github.com/joho/godotenv v1.5.1 // indirect
5760
github.com/josharian/intern v1.0.0 // indirect
5861
github.com/klauspost/compress v1.18.5 // indirect
62+
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
63+
github.com/klauspost/crc32 v1.3.0 // indirect
5964
github.com/knadh/koanf/maps v0.1.2 // indirect
6065
github.com/knadh/koanf/parsers/dotenv v1.1.0 // indirect
6166
github.com/knadh/koanf/parsers/yaml v1.1.0 // indirect
@@ -68,16 +73,21 @@ require (
6873
github.com/mattn/go-isatty v0.0.20 // indirect
6974
github.com/mattn/go-runewidth v0.0.21 // indirect
7075
github.com/mfridman/interpolate v0.0.2 // indirect
76+
github.com/minio/crc64nvme v1.1.1 // indirect
77+
github.com/minio/md5-simd v1.1.2 // indirect
7178
github.com/mitchellh/copystructure v1.2.0 // indirect
7279
github.com/mitchellh/reflectwalk v1.0.2 // indirect
7380
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
81+
github.com/philhofer/fwd v1.2.0 // indirect
7482
github.com/prometheus/client_model v0.6.2 // indirect
7583
github.com/prometheus/common v0.67.5 // indirect
7684
github.com/prometheus/procfs v0.19.2 // indirect
7785
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
7886
github.com/rogpeppe/go-internal v1.14.1 // indirect
87+
github.com/rs/xid v1.6.0 // indirect
7988
github.com/sethvargo/go-retry v0.3.0 // indirect
8089
github.com/swaggo/files/v2 v2.0.2 // indirect
90+
github.com/tinylib/msgp v1.6.4 // indirect
8191
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
8292
github.com/valyala/bytebufferpool v1.0.0 // indirect
8393
github.com/valyala/fasthttp v1.69.0 // indirect
@@ -89,12 +99,12 @@ require (
8999
go.uber.org/multierr v1.11.0 // indirect
90100
go.yaml.in/yaml/v2 v2.4.3 // indirect
91101
go.yaml.in/yaml/v3 v3.0.4 // indirect
92-
golang.org/x/mod v0.33.0 // indirect
93-
golang.org/x/net v0.51.0 // indirect
102+
golang.org/x/mod v0.34.0 // indirect
103+
golang.org/x/net v0.53.0 // indirect
94104
golang.org/x/sync v0.20.0 // indirect
95105
golang.org/x/sys v0.43.0 // indirect
96-
golang.org/x/text v0.35.0 // indirect
97-
golang.org/x/tools v0.42.0 // indirect
106+
golang.org/x/text v0.36.0 // indirect
107+
golang.org/x/tools v0.43.0 // indirect
98108
google.golang.org/protobuf v1.36.11 // indirect
99109
gopkg.in/yaml.v2 v2.4.0 // indirect
100110
)

go.sum

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ github.com/go-core-fx/sqlfx v0.1.0 h1:jWK4oUqvoJhcbLORWZXeRTzjstY6APter1fKsRYJbN
4646
github.com/go-core-fx/sqlfx v0.1.0/go.mod h1:D8fFoIeCUGthMN2nOeYIqs+yYH5CEDJBNJeMP4+Usk8=
4747
github.com/go-core-fx/validatorfx v0.0.2 h1:J+POBsdqyT2Hd3TZHgJ+0eBtCPHhHff8TJLcGowQ0Ew=
4848
github.com/go-core-fx/validatorfx v0.0.2/go.mod h1:1VtQoOEzBo3oapXgRFA65H+zSKvmCvb6yfAcdwpqSlE=
49+
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
50+
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
4951
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
5052
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
5153
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@@ -96,6 +98,11 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
9698
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
9799
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
98100
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
101+
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
102+
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
103+
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
104+
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
105+
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
99106
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
100107
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
101108
github.com/knadh/koanf/parsers/dotenv v1.1.0 h1:dQaM0Jw54zRsqDcaJ27pciNExuKfOXagCJW3K1h0hj0=
@@ -131,6 +138,12 @@ github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEj
131138
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
132139
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
133140
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
141+
github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI=
142+
github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
143+
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
144+
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
145+
github.com/minio/minio-go/v7 v7.0.100 h1:ShkWi8Tyj9RtU57OQB2HIXKz4bFgtVib0bbT1sbtLI8=
146+
github.com/minio/minio-go/v7 v7.0.100/go.mod h1:EtGNKtlX20iL2yaYnxEigaIvj0G0GwSDnifnG8ClIdw=
134147
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
135148
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
136149
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
@@ -140,6 +153,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
140153
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
141154
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
142155
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
156+
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
157+
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
143158
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
144159
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
145160
github.com/pressly/goose/v3 v3.27.0 h1:/D30gVTuQhu0WsNZYbJi4DMOsx1lNq+6SkLe+Wp59BM=
@@ -158,6 +173,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
158173
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
159174
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
160175
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
176+
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
177+
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
161178
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
162179
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
163180
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
@@ -171,6 +188,8 @@ github.com/swaggo/files/v2 v2.0.2 h1:Bq4tgS/yxLB/3nwOMcul5oLEUKa877Ykgz3CJMVbQKU
171188
github.com/swaggo/files/v2 v2.0.2/go.mod h1:TVqetIzZsO9OhHX1Am9sRf9LdrFZqoK49N37KON/jr0=
172189
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
173190
github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
191+
github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ=
192+
github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
174193
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
175194
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
176195
github.com/uptrace/bun v1.2.18 h1:3HnRcMfS6OBPMG1eSOzlbFJ/X/AyMEJb7rMxE6VQvDU=
@@ -213,15 +232,15 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
213232
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
214233
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
215234
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
216-
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
217-
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
235+
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
236+
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
218237
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
219238
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
220-
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
221-
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
239+
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
240+
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
222241
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
223-
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
224-
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
242+
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
243+
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
225244
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
226245
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
227246
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -232,11 +251,11 @@ golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
232251
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
233252
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
234253
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
235-
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
236-
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
254+
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
255+
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
237256
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
238-
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
239-
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
257+
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
258+
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
240259
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
241260
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
242261
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

internal/app.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ package internal
33
import (
44
"context"
55

6+
"github.com/bit-issues/backend/internal/attachments"
67
"github.com/bit-issues/backend/internal/comments"
78
"github.com/bit-issues/backend/internal/config"
89
"github.com/bit-issues/backend/internal/db"
910
"github.com/bit-issues/backend/internal/jwt"
1011
"github.com/bit-issues/backend/internal/projects"
1112
"github.com/bit-issues/backend/internal/server"
13+
"github.com/bit-issues/backend/internal/storage"
1214
"github.com/bit-issues/backend/internal/tasks"
1315
"github.com/bit-issues/backend/internal/users"
16+
"github.com/bit-issues/backend/pkg/miniofx"
1417
"github.com/go-core-fx/bunfx"
1518
"github.com/go-core-fx/fiberfx"
1619
"github.com/go-core-fx/goosefx"
@@ -43,18 +46,21 @@ func Run(version healthfx.Version) {
4346
// telegofx.Module(true),
4447
validatorfx.Module(),
4548
// watermillfx.Module(),
49+
miniofx.Module(),
4650
//
4751
// APP MODULES
4852
config.Module(),
4953
db.Module(),
5054
server.Module(),
55+
storage.Module(),
5156
//
5257
// BUSINESS MODULES
5358
fx.Supply(version),
5459
jwt.Module(),
5560
users.Module(),
5661
projects.Module(),
5762
tasks.Module(),
63+
attachments.Module(),
5864
comments.Module(),
5965
//
6066
fx.Invoke(func(lc fx.Lifecycle, logger *zap.Logger) {

internal/attachments/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package attachments
2+
3+
type Config struct {
4+
MaxSize uint64
5+
}

internal/attachments/doc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Package attachments provides domain, repository and service logic for task attachments.
2+
package attachments

internal/attachments/domain.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package attachments
2+
3+
import (
4+
"fmt"
5+
"time"
6+
)
7+
8+
const (
9+
DefaultMaxFileSizeBytes uint64 = 104857600
10+
MaxFileNameLength int = 255
11+
)
12+
13+
type AttachmentStatus string
14+
15+
const (
16+
StatusPending AttachmentStatus = "pending"
17+
StatusUploaded AttachmentStatus = "uploaded"
18+
)
19+
20+
type Attachment struct {
21+
ID int64
22+
TaskID int64
23+
FileName string
24+
StorageKey string
25+
SizeBytes uint64
26+
Status AttachmentStatus
27+
UploadedBy int64
28+
UploadedAt time.Time
29+
DeletedAt *time.Time
30+
}
31+
32+
type AttachmentInput struct {
33+
TaskID int64
34+
FileName string
35+
SizeBytes uint64
36+
UploaderID int64
37+
}
38+
39+
type UploadResult struct {
40+
Attachment *Attachment
41+
UploadURL string
42+
}
43+
44+
type AttachmentWithURL struct {
45+
Attachment
46+
47+
DownloadURL string
48+
}
49+
50+
func (i AttachmentInput) Validate(maxFileSize uint64) error {
51+
if i.TaskID <= 0 {
52+
return fmt.Errorf("%w: task_id must be positive", ErrValidationFailed)
53+
}
54+
55+
if i.UploaderID <= 0 {
56+
return fmt.Errorf("%w: uploader_id must be positive", ErrValidationFailed)
57+
}
58+
59+
fileName := sanitizeFileName(i.FileName)
60+
if fileName == "" {
61+
return fmt.Errorf("%w: file_name is required", ErrValidationFailed)
62+
}
63+
64+
if len(fileName) > MaxFileNameLength {
65+
return fmt.Errorf("%w: file_name too long (max %d characters)", ErrValidationFailed, MaxFileNameLength)
66+
}
67+
68+
if i.SizeBytes == 0 {
69+
return fmt.Errorf("%w: size_bytes must be positive", ErrValidationFailed)
70+
}
71+
72+
if i.SizeBytes > maxFileSize {
73+
return ErrFileTooLarge
74+
}
75+
76+
return nil
77+
}

0 commit comments

Comments
 (0)