diff options
| author | Bobby <[email protected]> | 2026-03-06 13:14:34 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-03-06 13:14:34 +0530 |
| commit | 6b38ef50818bd8503145ff8ef9651609e88b74f6 (patch) | |
| tree | caa2cfbb261ce17fd60f026da3706b6fd64b079c | |
| parent | b947bd40d50ddc566ee859a20304655f116c9bf8 (diff) | |
| download | pagoda-6b38ef50818bd8503145ff8ef9651609e88b74f6.tar.xz pagoda-6b38ef50818bd8503145ff8ef9651609e88b74f6.zip | |
feat: integrate MinIO storage functionality and update user model for CDN support
| -rw-r--r-- | garden/src/components/Layout.tsx | 18 | ||||
| -rw-r--r-- | garden/src/styles/layout.css | 23 | ||||
| -rw-r--r-- | shrine/config/config.go | 5 | ||||
| -rw-r--r-- | shrine/config/env.go | 9 | ||||
| -rw-r--r-- | shrine/go.mod | 23 | ||||
| -rw-r--r-- | shrine/go.sum | 45 | ||||
| -rw-r--r-- | shrine/models/user.go | 9 | ||||
| -rw-r--r-- | shrine/utils/storage/storage.go | 50 | ||||
| -rw-r--r-- | shrine/utils/validators/username.go | 2 |
9 files changed, 156 insertions, 28 deletions
diff --git a/garden/src/components/Layout.tsx b/garden/src/components/Layout.tsx index 4ff2e8e..3d9fdf0 100644 --- a/garden/src/components/Layout.tsx +++ b/garden/src/components/Layout.tsx @@ -125,7 +125,14 @@ export default function Layout(props: LayoutProps) { <li class="placeholder">Be the first to join!</li> }> <For each={stats.data()?.newest_citizens}> - {(citizen) => <li><A href={`/u/${citizen.username}`}>{citizen.display_name}</A></li>} + {(citizen) => ( + <li class="citizen-item"> + <A href={`/u/${citizen.username}`}> + <img src={citizen.avatar_url} alt="" class="citizen-avatar" /> + {citizen.display_name} + </A> + </li> + )} </For> </Show> </ul> @@ -136,7 +143,14 @@ export default function Layout(props: LayoutProps) { <li class="placeholder">No one online.</li> }> <For each={stats.data()?.online_citizens}> - {(citizen) => <li><A href={`/u/${citizen.username}`}>{citizen.display_name}</A></li>} + {(citizen) => ( + <li class="citizen-item"> + <A href={`/u/${citizen.username}`}> + <img src={citizen.avatar_url} alt="" class="citizen-avatar" /> + {citizen.display_name} + </A> + </li> + )} </For> </Show> </ul> diff --git a/garden/src/styles/layout.css b/garden/src/styles/layout.css index 4e55e9b..f4c4772 100644 --- a/garden/src/styles/layout.css +++ b/garden/src/styles/layout.css @@ -312,16 +312,17 @@ a:hover { } .nav-section-body li { - padding: 3px 8px 3px 16px; + padding: 3px 8px; font-size: 12px; - position: relative; + display: flex; + align-items: center; + gap: 4px; } .nav-section-body li::before { content: "\25B8"; - position: absolute; - left: 6px; font-size: 10px; + flex-shrink: 0; color: var(--color-text-muted); } @@ -409,7 +410,6 @@ a:hover { .nav-section-body li.placeholder { color: var(--color-text-muted); font-style: italic; - padding: 3px 8px; } .nav-section-body li.placeholder::before { @@ -525,4 +525,17 @@ a:hover { .sidebar-logout:hover { color: var(--color-pink); +} + +.citizen-item a { + display: flex; + align-items: center; + gap: 6px; +} + +.citizen-avatar { + width: 20px; + height: 20px; + border-radius: 2px; + object-fit: cover; }
\ No newline at end of file diff --git a/shrine/config/config.go b/shrine/config/config.go index e07f1c6..d59f620 100644 --- a/shrine/config/config.go +++ b/shrine/config/config.go @@ -11,6 +11,7 @@ var ( Server server Database database SMTP smtp + Storage storage ) func init() { @@ -32,6 +33,10 @@ func init() { logger.Fatalf("Config", "Failed to parse SMTP config: %v", err) } + if err := env.Parse(&Storage); err != nil { + logger.Fatalf("Config", "Failed to parse storage config: %v", err) + } + if Server.Debug { logger.SetDebug(true) } diff --git a/shrine/config/env.go b/shrine/config/env.go index 5d803d4..e711493 100644 --- a/shrine/config/env.go +++ b/shrine/config/env.go @@ -24,3 +24,12 @@ type smtp struct { From string `env:"SMTP_FROM" default:"[email protected]"` FrontendURL string `env:"FRONTEND_URL" default:"http://localhost:5173"` } + +type storage struct { + Endpoint string `env:"MINIO_ENDPOINT" default:"localhost:9000"` + AccessKey string `env:"MINIO_ACCESS_KEY" default:""` + SecretKey string `env:"MINIO_SECRET_KEY" default:""` + Bucket string `env:"MINIO_BUCKET" default:"pagoda"` + UseSSL bool `env:"MINIO_USE_SSL" default:"false"` + CDN string `env:"CDN_URL" default:""` +} diff --git a/shrine/go.mod b/shrine/go.mod index f72fca3..28dcfd4 100644 --- a/shrine/go.mod +++ b/shrine/go.mod @@ -6,8 +6,9 @@ require ( github.com/flosch/pongo2/v6 v6.0.0 github.com/gofiber/fiber/v2 v2.52.12 github.com/joho/godotenv v1.5.1 + github.com/minio/minio-go/v7 v7.0.98 go.uber.org/zap v1.27.1 - golang.org/x/crypto v0.31.0 + golang.org/x/crypto v0.46.0 gorm.io/driver/postgres v1.6.0 gorm.io/driver/sqlite v1.6.0 gorm.io/gorm v1.31.1 @@ -15,6 +16,8 @@ require ( require ( github.com/andybalholm/brotli v1.1.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-ini/ini v1.67.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -22,19 +25,27 @@ require ( github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.18.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.11 // indirect + github.com/klauspost/crc32 v1.3.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/minio/crc64nvme v1.1.1 // indirect + github.com/minio/md5-simd v1.1.2 // indirect + github.com/philhofer/fwd v1.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/stretchr/testify v1.9.0 // indirect + github.com/rs/xid v1.6.0 // indirect + github.com/tinylib/msgp v1.6.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.51.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect go.uber.org/multierr v1.10.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect ) diff --git a/shrine/go.sum b/shrine/go.sum index 0ccc7fa..7da097c 100644 --- a/shrine/go.sum +++ b/shrine/go.sum @@ -3,8 +3,12 @@ github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer5 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU= github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/gofiber/fiber/v2 v2.52.12 h1:0LdToKclcPOj8PktUdIKo9BUohjjwfnQl42Dhw8/WUw= github.com/gofiber/fiber/v2 v2.52.12/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -23,8 +27,13 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU= +github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM= +github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -38,17 +47,29 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI= +github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg= +github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= +github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= +github.com/minio/minio-go/v7 v7.0.98 h1:MeAVKjLVz+XJ28zFcuYyImNSAh8Mq725uNW4beRisi0= +github.com/minio/minio-go/v7 v7.0.98/go.mod h1:cY0Y+W7yozf0mdIclrttzo1Iiu7mEf9y7nk2uXqMOvM= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tinylib/msgp v1.6.1 h1:ESRv8eL3u+DNHUoSAAQRE50Hm162zqAnBoGv9PzScPY= +github.com/tinylib/msgp v1.6.1/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= @@ -61,16 +82,20 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/shrine/models/user.go b/shrine/models/user.go index c0e1e23..95885f0 100644 --- a/shrine/models/user.go +++ b/shrine/models/user.go @@ -4,6 +4,7 @@ import ( "errors" "shrine/enums" "shrine/types" + "shrine/utils/storage" "shrine/utils/validators" "strings" "time" @@ -20,7 +21,7 @@ type User struct { DisplayName string `gorm:"size:50;not null"` Bio string `gorm:"size:500"` Birthday *time.Time - AvatarURL string `gorm:"size:512"` + AvatarURL string `gorm:"size:512;not null;default:defaults/avatar.png"` BlinkieURL string `gorm:"size:512"` Website string `gorm:"size:255"` Location string `gorm:"size:100"` @@ -111,8 +112,8 @@ func (user *User) ToResponse() types.UserResponse { DisplayName: user.DisplayName, Bio: user.Bio, Birthday: user.Birthday, - AvatarURL: user.AvatarURL, - BlinkieURL: user.BlinkieURL, + AvatarURL: storage.ResolveCDN(user.AvatarURL), + BlinkieURL: storage.ResolveCDN(user.BlinkieURL), Website: user.Website, Location: user.Location, Pronouns: user.Pronouns, @@ -127,7 +128,7 @@ func (user *User) ToSummary() types.CitizenSummary { ID: user.ID, Username: user.Username, DisplayName: user.DisplayName, - AvatarURL: user.AvatarURL, + AvatarURL: storage.ResolveCDN(user.AvatarURL), } } diff --git a/shrine/utils/storage/storage.go b/shrine/utils/storage/storage.go new file mode 100644 index 0000000..32b3db5 --- /dev/null +++ b/shrine/utils/storage/storage.go @@ -0,0 +1,50 @@ +package storage + +import ( + "context" + "io" + "shrine/config" + "shrine/utils/logger" + "strings" + + "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/credentials" +) + +var Client *minio.Client + +func init() { + if config.Storage.AccessKey == "" || config.Storage.SecretKey == "" { + logger.Infof("Storage", "MinIO credentials not configured, storage disabled") + return + } + + var err error + Client, err = minio.New(config.Storage.Endpoint, &minio.Options{ + Creds: credentials.NewStaticV4(config.Storage.AccessKey, config.Storage.SecretKey, ""), + Secure: config.Storage.UseSSL, + }) + if err != nil { + logger.Fatalf("Storage", "Failed to initialize MinIO client: %v", err) + } + + logger.Successf("Storage", "MinIO client initialized for %s", config.Storage.Endpoint) +} + +func Upload(path string, reader io.Reader, size int64, contentType string) error { + _, err := Client.PutObject(context.Background(), config.Storage.Bucket, path, reader, size, minio.PutObjectOptions{ + ContentType: contentType, + }) + return err +} + +func Delete(path string) error { + return Client.RemoveObject(context.Background(), config.Storage.Bucket, path, minio.RemoveObjectOptions{}) +} + +func ResolveCDN(path string) string { + if path == "" { + return "" + } + return strings.TrimRight(config.Storage.CDN, "/") + "/" + config.Storage.Bucket + "/" + path +}
\ No newline at end of file diff --git a/shrine/utils/validators/username.go b/shrine/utils/validators/username.go index 729548d..f77cda9 100644 --- a/shrine/utils/validators/username.go +++ b/shrine/utils/validators/username.go @@ -26,7 +26,7 @@ var reservedUsernames = collections.SetOf( "members", "online", "buttons", "webring", "guestbook", "hitcounter", "letters", "rules", "faq", "blog", "news", "feed", - "static", "assets", "uploads", "images", "media", + "static", "assets", "uploads", "images", "media", "default", "defaults", "test", "testing", "debug", "dev", "staging", "everyone", "all", "here", "channel", ) |
