init storage server

alpha
alex 2023-01-02 22:11:44 +01:00
commit 8a55703b58
13 changed files with 582 additions and 0 deletions

8
config.example.yml Normal file
View File

@ -0,0 +1,8 @@
debug: false
storagePath: "./storage/"
imageUrlAddress: "http://localhost:8081/v1/"
scylladb:
host: 127.0.0.1
username: user
password: password
keyspace: keyspace

28
go.mod Normal file
View File

@ -0,0 +1,28 @@
module clickandjoin.app/storageserver
go 1.19
require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/gocql/gocql v1.3.1 // indirect
github.com/gofiber/fiber/v2 v2.40.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/h2non/bimg v1.1.9 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/kolesa-team/go-webp v1.0.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/scylladb/go-reflectx v1.0.1 // indirect
github.com/scylladb/gocqlx/v2 v2.7.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.41.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

73
go.sum Normal file
View File

@ -0,0 +1,73 @@
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gocql/gocql v1.3.1 h1:BTwM4rux+ah5G3oH6/MQa+tur/TDd/XAAOXDxBBs7rg=
github.com/gocql/gocql v1.3.1/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/gofiber/fiber/v2 v2.40.1 h1:pc7n9VVpGIqNsvg9IPLQhyFEMJL8gCs1kneH5D1pIl4=
github.com/gofiber/fiber/v2 v2.40.1/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/h2non/bimg v1.1.9 h1:WH20Nxko9l/HFm4kZCA3Phbgu2cbHvYzxwxn9YROEGg=
github.com/h2non/bimg v1.1.9/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/kolesa-team/go-webp v1.0.2 h1:XCrWqxI7tNOI3dr0YufD9TUb+54vBDogg9KsHH7q5Lc=
github.com/kolesa-team/go-webp v1.0.2/go.mod h1:oMvdivD6K+Q5qIIkVC2w4k2ZUnI1H+MyP7inwgWq9aA=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
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/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ=
github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc=
github.com/scylladb/gocqlx/v2 v2.7.0 h1:/w1VeJHCEAsg9eTculTvIS9eIe/VmEu0clhlH1CF7lc=
github.com/scylladb/gocqlx/v2 v2.7.0/go.mod h1:jKhM0/LkEAhEOSwd10TCMQdlC5x8aEzK7cXjQcPyMJ0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
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/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.41.0 h1:zeR0Z1my1wDHTRiamBCXVglQdbUwgb9uWG3k1HQz6jY=
github.com/valyala/fasthttp v1.41.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

46
main.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"log"
"os"
"clickandjoin.app/storageserver/modules/config"
"clickandjoin.app/storageserver/modules/scylladb"
"clickandjoin.app/storageserver/routers/router"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/sirupsen/logrus"
)
func init() {
config.LoadConfig()
if config.Cfg.Debug {
logrus.SetLevel(logrus.DebugLevel)
}
logrus.Println("Debug:", config.Cfg.Debug)
scylladb.InitDatabase()
}
func main() {
app := fiber.New()
app.Use(cors.New())
if config.Cfg.Debug {
app.Use(logger.New(logger.Config{
Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n",
}))
}
router.SetupRoutes(app)
if len(os.Args) < 2 {
log.Fatalln("Please specify port")
}
app.Listen("127.0.0.1:" + os.Args[1])
}

36
modules/config/config.go Normal file
View File

@ -0,0 +1,36 @@
package config
import (
"os"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
)
var Cfg Config
type Config struct {
Debug bool
StoragePath string `yaml:"storagePath"`
ImageUrlAddress string `yaml:"imageUrlAddress"`
ScyllaDB ScyllaDB `yaml:"scylladb"`
}
type ScyllaDB struct {
Host string
Username string
Password string
Keyspace string
}
func LoadConfig() {
data, err := os.ReadFile("config.yml")
if err != nil {
logrus.Fatalln("Failed to read config file, err:", err)
}
if err := yaml.Unmarshal(data, &Cfg); err != nil {
logrus.Fatalln("Failed to unmarshal config file, err:", err)
}
}

139
modules/image/image.go Normal file
View File

@ -0,0 +1,139 @@
package image
import (
"errors"
"io"
"mime/multipart"
"os"
"strconv"
"clickandjoin.app/storageserver/modules/config"
"clickandjoin.app/storageserver/modules/utils"
"github.com/google/uuid"
"github.com/h2non/bimg"
"github.com/sirupsen/logrus"
)
// is specified in the form data of the frontend
const FormFileKey = "file"
const MaxAvatarSize = 2 * 1024 * 1024 // 2 MB
// filename len = 36 + dot . 1 + longestFileType 4
// example: cf75ace7-da4c-434d-bf7d-0bdbcea5c57d.webp
const MaxFileNameLen = 41
var validFileTypes = []string{"jpeg", "jpg", "png", "webp"}
// represents the query parameter size for the dynamic image resolution
// example ?size=1 -> 64x64
var ImageSizes = []int{32, 64, 150, 256, 512, 1024}
const DefaultImageSize = 0
func FileTypeVerification(fileType string) bool {
for _, validFileType := range validFileTypes {
if fileType == "image/"+validFileType {
return true
}
}
return false
}
func createUserFolder(userId string) error {
path := config.Cfg.StoragePath + userId
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
err = os.Mkdir(utils.GetUserStoragePath(userId), os.ModePerm)
if err != nil && !errors.Is(err, os.ErrExist) {
logrus.Errorln("Failed to create user folder, err:", err)
return err
}
}
return nil
}
func SaveImage(fileHeader *multipart.FileHeader, userId string) (fileName string, err error) {
err = createUserFolder(userId)
if err != nil {
return "", err
}
f, err := fileHeader.Open()
if err != nil {
logrus.Errorln("Failed to open file header, err:", err)
return "", err
}
fileData, err := io.ReadAll(f)
if err != nil {
logrus.Errorln("Failed to read file, err:", err)
return "", err
}
fileName = uuid.New().String()
newImage := bimg.NewImage(fileData).Image()
err = bimg.Write(utils.GetUserStoragePath(userId)+fileName+".webp", newImage)
if err != nil {
logrus.Errorln("Failed to save image, err:", err)
return "", err
}
return fileName + ".webp", nil
}
func GetImage(userId string, fileName string, imageSize string) ([]byte, error) {
imgSize, err := strconv.Atoi(imageSize)
if err != nil {
imgSize = DefaultImageSize
}
buffer, err := bimg.Read(utils.GetUserStoragePath(userId) + fileName)
if err != nil {
logrus.Errorln("Failed to read image, err:", err)
return []byte{}, err
}
// check that the value has not been manipulated and is greater than the largest index value in the list
if imgSize > len(ImageSizes)-1 {
imgSize = DefaultImageSize
}
resolution := ImageSizes[imgSize]
newImage, err := bimg.NewImage(buffer).ForceResize(resolution, resolution)
if err != nil {
logrus.Errorln("Failed to force resize, err:", err)
return []byte{}, err
}
return newImage, nil
}
func DeleteOldAvatarImage(userId string) error {
path := utils.GetUserStoragePath(userId)
dir, err := os.ReadDir(path)
if err != nil {
logrus.Errorln("Failed to read dir, err:", err)
return err
}
for _, file := range dir {
logrus.Println(file.Name())
os.Remove(path + file.Name())
}
return nil
}

View File

@ -0,0 +1,38 @@
package scylladb
import (
"github.com/scylladb/gocqlx/v2/table"
)
var (
Users = table.New(table.Metadata{
Name: "users",
Columns: []string{
"id",
"username",
"account_name",
"email",
"password",
"description",
"latitude",
"longitude",
"privacy",
"xp_level",
"xp_points",
"followers_count",
"following_count",
"account_status",
"avatar_url",
"created_at",
"updated_at"},
PartKey: []string{"id"},
})
Sessions = table.New(table.Metadata{
Name: "sessions",
Columns: []string{
"id",
"user_id"},
PartKey: []string{"id"},
})
)

View File

@ -0,0 +1,32 @@
package scylladb
import (
"clickandjoin.app/storageserver/modules/config"
"github.com/gocql/gocql"
"github.com/scylladb/gocqlx/v2"
"github.com/sirupsen/logrus"
)
var Session gocqlx.Session
var Cluster *gocql.ClusterConfig
func InitDatabase() {
Cluster = gocql.NewCluster(config.Cfg.ScyllaDB.Host)
Cluster.Authenticator = gocql.PasswordAuthenticator{
Username: config.Cfg.ScyllaDB.Username,
Password: config.Cfg.ScyllaDB.Password,
}
Cluster.Keyspace = config.Cfg.ScyllaDB.Keyspace
var err error
Session, err = gocqlx.WrapSession(Cluster.CreateSession())
if err != nil {
logrus.Fatal(err)
}
logrus.Info("Database connected")
}

47
modules/structs/user.go Normal file
View File

@ -0,0 +1,47 @@
package structs
const (
LenUserId = 36
LenXAuthorizationToken = 36
)
// Representation of the user model
// TABLE users
type User struct {
Id string
Username string
AccountName string
Email string
Password string
Description string
Latitude float64
Longitude float64
ParticipatingEvents []string
VisitedEvents []string
Notifications []string
Privacy UserPrivacy
XpLevel int
XpPoints int
FollowersCount int
FollowingCount int
AccountStatus uint8
AvatarUrl string
CreatedAt int64
UpdatedAt int64
}
type UserPrivacy struct {
Test uint8
}
// TABLE sessions
type UserSession struct {
Id string
UserId string
FcmToken string
UserAgent string
AppVersion string
Ip string
LastUsed int64
CreatedAt int64
}

20
modules/utils/utils.go Normal file
View File

@ -0,0 +1,20 @@
package utils
import (
"clickandjoin.app/storageserver/modules/config"
"github.com/gofiber/fiber/v2"
)
const URL = "http://localhost:8081/v1/"
func GetAuhorizationToken(c *fiber.Ctx) string {
return c.GetReqHeaders()["X-Authorization"]
}
func GetUserStoragePath(userId string) string {
return config.Cfg.StoragePath + "users/" + userId + "/"
}
func GetUserAvatarUrl(userId string, filename string) string {
return config.Cfg.ImageUrlAddress + "avatars/" + userId + "/" + filename
}

8
readme.md Normal file
View File

@ -0,0 +1,8 @@
The following library must be installed
```
sudo apt install libvips-dev
```
so that the used library (https://github.com/h2non/bimg) works.
*Needed download package found here https://github.com/davidbyttow/govips*

14
routers/router/router.go Normal file
View File

@ -0,0 +1,14 @@
package router
import (
"clickandjoin.app/storageserver/routers/routes/v1/user"
"github.com/gofiber/fiber/v2"
)
func SetupRoutes(app *fiber.App) {
v1 := app.Group("/v1")
v1.Get("/avatars/:userId/:fileName", user.GetAvatar)
u := v1.Group("/user")
u.Post("/avatar", user.UpdateAvatar)
}

View File

@ -0,0 +1,93 @@
package user
import (
"clickandjoin.app/storageserver/modules/image"
"clickandjoin.app/storageserver/modules/scylladb"
"clickandjoin.app/storageserver/modules/structs"
"clickandjoin.app/storageserver/modules/utils"
"github.com/gofiber/fiber/v2"
"github.com/sirupsen/logrus"
)
func GetAvatar(c *fiber.Ctx) error {
userId := c.Params("userId")
if len(userId) != structs.LenUserId {
logrus.Debugln("UserId is longer than allowed")
return c.SendStatus(fiber.StatusBadRequest)
}
fileName := c.Params("fileName")
// check if the filename length has not been manipulated by the user
if len(fileName) > image.MaxFileNameLen {
logrus.Debugln("Filename is longer than allowed")
return c.SendStatus(fiber.StatusBadRequest)
}
// image resolution
size := c.Query("size")
img, err := image.GetImage(userId, fileName, size)
if err != nil {
return c.SendStatus(fiber.StatusBadRequest)
}
return c.Send(img)
}
func UpdateAvatar(c *fiber.Ctx) error {
xAuthorization := utils.GetAuhorizationToken(c)
if len(xAuthorization) != structs.LenXAuthorizationToken {
return c.SendStatus(fiber.StatusUnauthorized)
}
foundSession := structs.UserSession{Id: xAuthorization}
q := scylladb.Session.Query(scylladb.Sessions.Get("user_id")).BindStruct(foundSession)
if err := q.GetRelease(&foundSession); err != nil {
logrus.Errorln("Failed to get user session, err:", err)
return c.SendStatus(fiber.StatusInternalServerError)
}
file, err := c.FormFile(image.FormFileKey)
if err != nil {
logrus.Errorln("Failed to get form file, err:", err)
return c.SendStatus(fiber.StatusBadRequest)
}
logrus.Println("size", file.Size, "header", file.Header, "filename", file.Filename)
if file.Size > image.MaxAvatarSize {
return c.SendStatus(fiber.StatusRequestEntityTooLarge)
}
if valid := image.FileTypeVerification(file.Header.Get("Content-Type")); !valid {
return c.SendStatus(fiber.StatusUnsupportedMediaType)
}
if err = image.DeleteOldAvatarImage(foundSession.UserId); err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
fileName, err := image.SaveImage(file, foundSession.UserId)
if err != nil {
return c.SendStatus(fiber.StatusBadRequest)
}
user := structs.User{Id: foundSession.UserId, AvatarUrl: utils.GetUserAvatarUrl(foundSession.UserId, fileName)}
q = scylladb.Session.Query(scylladb.Users.Update("avatar_url")).BindStruct(user)
if err := q.ExecRelease(); err != nil {
logrus.Errorln("Failed to update user avatar url, err:", err)
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.SendStatus(fiber.StatusOK)
}