tmp
This commit is contained in:
parent
24f225f68b
commit
b9d8aa6525
12
.mockery.yaml
Normal file
12
.mockery.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
filename: "mock_{{.InterfaceName}}.go"
|
||||||
|
dir: "mocks/{{.PackagePath}}"
|
||||||
|
outpkg: "{{.PackageName}}"
|
||||||
|
with-expecter: true
|
||||||
|
packages:
|
||||||
|
git.optclblast.xyz/draincloud/draincloud-core/internal/storage:
|
||||||
|
interfaces:
|
||||||
|
Database:
|
||||||
|
AuthAuditLogStorage:
|
||||||
|
AuthStorage:
|
||||||
|
BlobStorage:
|
||||||
|
MetaStorage:
|
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch Package",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}/cmd/main.go"
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
cmd/main.go
13
cmd/main.go
@ -2,20 +2,29 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/app"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/app"
|
||||||
|
cleanupsessions "git.optclblast.xyz/draincloud/draincloud-core/internal/cron/cleanup_sessions"
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/plugin"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/plugin"
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/postgres"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/postgres"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
ctx := context.Background()
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
plugin.MustNewPluginLoader(ctx, 8081, plugin.NewPluginStore()).
|
plugin.MustNewPluginLoader(ctx, 8081, plugin.NewPluginStore()).
|
||||||
Run(ctx)
|
Run(ctx)
|
||||||
|
|
||||||
pg := postgres.New(ctx, "postgres://draincloud:draincloud@localhost:5432/draincloud?sslmode=disable")
|
pg := postgres.New(ctx, "postgres://draincloud:draincloud@localhost:5432/draincloud?sslmode=disable")
|
||||||
|
|
||||||
app.New(pg).
|
cleanupSessionsCron := cleanupsessions.New(pg)
|
||||||
|
cleanupSessionsCron.Run(ctx)
|
||||||
|
|
||||||
|
go app.New(pg).
|
||||||
Run(ctx)
|
Run(ctx)
|
||||||
|
|
||||||
|
<-ctx.Done()
|
||||||
}
|
}
|
||||||
|
4
go.mod
4
go.mod
@ -3,12 +3,14 @@ module git.optclblast.xyz/draincloud/draincloud-core
|
|||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
|
||||||
github.com/fatih/color v1.17.0
|
github.com/fatih/color v1.17.0
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/jackc/pgx/v5 v5.7.1
|
github.com/jackc/pgx/v5 v5.7.1
|
||||||
github.com/jmoiron/sqlx v1.4.0
|
github.com/jmoiron/sqlx v1.4.0
|
||||||
github.com/spf13/viper v1.19.0
|
github.com/spf13/viper v1.19.0
|
||||||
|
github.com/stretchr/testify v1.9.0
|
||||||
golang.org/x/crypto v0.28.0
|
golang.org/x/crypto v0.28.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,6 +38,7 @@ require (
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
@ -43,6 +46,7 @@ require (
|
|||||||
github.com/spf13/afero v1.11.0 // indirect
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
github.com/spf13/cast v1.6.0 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
|
1
go.sum
1
go.sum
@ -105,6 +105,7 @@ github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
@ -2,31 +2,31 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"errors"
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/domain"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/domain"
|
||||||
|
filesengine "git.optclblast.xyz/draincloud/draincloud-core/internal/files_engine"
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DrainCloud struct {
|
type DrainCloud struct {
|
||||||
mux *gin.Engine
|
mux *gin.Engine
|
||||||
datadase storage.Database
|
database storage.Database
|
||||||
|
filesEngine *filesengine.FilesEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
datadase storage.Database,
|
database storage.Database,
|
||||||
|
filesEngine *filesengine.FilesEngine,
|
||||||
) *DrainCloud {
|
) *DrainCloud {
|
||||||
mux := gin.Default()
|
mux := gin.Default()
|
||||||
|
|
||||||
d := &DrainCloud{
|
d := &DrainCloud{
|
||||||
datadase: datadase,
|
database: database,
|
||||||
|
filesEngine: filesEngine,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Built-in auth component of DrainCloud-Core
|
// Built-in auth component of DrainCloud-Core
|
||||||
@ -34,7 +34,17 @@ func New(
|
|||||||
{
|
{
|
||||||
authGroup.POST("/register", d.Register)
|
authGroup.POST("/register", d.Register)
|
||||||
authGroup.POST("/login", d.Login)
|
authGroup.POST("/login", d.Login)
|
||||||
authGroup.POST("/logout", d.Logout)
|
}
|
||||||
|
|
||||||
|
filesGroup := mux.Group("/files")
|
||||||
|
{
|
||||||
|
filesGroup.POST("/upload", func(ctx *gin.Context) {
|
||||||
|
err := d.uploadFile(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx.Request.Context(), "", logger.Err(err))
|
||||||
|
ctx.String(400, err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
d.mux = mux
|
d.mux = mux
|
||||||
@ -46,95 +56,22 @@ func (d *DrainCloud) Run(ctx context.Context) error {
|
|||||||
return d.mux.Run()
|
return d.mux.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DrainCloud) Register(ctx *gin.Context) {
|
func writeError(ctx *gin.Context, err error) {
|
||||||
logger.Debug(ctx, "[register] new request")
|
switch {
|
||||||
|
case errors.Is(err, ErrorAccessDenied):
|
||||||
req := new(domain.RegisterRequest)
|
ctx.JSON(http.StatusInternalServerError, domain.ErrorJson{
|
||||||
err := ctx.BindJSON(req)
|
Code: http.StatusForbidden,
|
||||||
if err != nil {
|
Message: err.Error(),
|
||||||
logger.Error(ctx, "[register] failed to bind request", logger.Err(err))
|
|
||||||
ctx.JSON(http.StatusBadRequest, map[string]string{
|
|
||||||
"error": "bad request",
|
|
||||||
})
|
})
|
||||||
return
|
case errors.Is(err, ErrorSessionExpired):
|
||||||
}
|
ctx.JSON(http.StatusInternalServerError, domain.ErrorJson{
|
||||||
|
Code: http.StatusForbidden,
|
||||||
_, err = d.register(ctx, req)
|
Message: err.Error(),
|
||||||
if err != nil {
|
})
|
||||||
logger.Error(ctx, "[register] failed to register user", logger.Err(err))
|
default:
|
||||||
ctx.JSON(http.StatusBadRequest, map[string]string{
|
ctx.JSON(http.StatusInternalServerError, domain.ErrorJson{
|
||||||
"error": err.Error(),
|
Code: http.StatusInternalServerError,
|
||||||
|
Message: "Internal Error",
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, map[string]bool{
|
|
||||||
"ok": true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type registerResult struct {
|
|
||||||
// cookies []http.Cookie
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DrainCloud) register(ctx *gin.Context, req *domain.RegisterRequest) (*registerResult, error) {
|
|
||||||
if err := validateLoginAndPassword(req.Login, req.Password); err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid creds: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 10)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error(ctx, "[register] failed to generate password", logger.Err(err))
|
|
||||||
return nil, fmt.Errorf("failed to generate password: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = d.datadase.AddUser(ctx, req.Login, req.Login, passwordHash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to add new user: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionToken, err := generateSessionToken(100)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to generate a session token: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.SetCookie("__Session_token", sessionToken, int((time.Hour * 24).Seconds()), "_path", "_domain", true, true)
|
|
||||||
|
|
||||||
csrfToken, err := generateSessionToken(100)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to generate a csrf token: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.SetCookie("__Csrf_token", csrfToken, int((time.Hour * 24).Seconds()), "_path", "_domain", true, false)
|
|
||||||
|
|
||||||
// TODO save session into database
|
|
||||||
|
|
||||||
return ®isterResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateLoginAndPassword(login, password string) error {
|
|
||||||
if len(login) < 4 {
|
|
||||||
return fmt.Errorf("login must be longer than 8 chars")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(password) < 6 {
|
|
||||||
return fmt.Errorf("password must be longer than 8 chars")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateSessionToken(length int) (string, error) {
|
|
||||||
bytes := make([]byte, length)
|
|
||||||
if _, err := rand.Read(bytes); err != nil {
|
|
||||||
return "", fmt.Errorf("failed to generate token: %w", err)
|
|
||||||
}
|
|
||||||
return base64.URLEncoding.EncodeToString(bytes), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DrainCloud) Login(ctx *gin.Context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
func (d *DrainCloud) Logout(ctx *gin.Context) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
63
internal/app/auth.go
Normal file
63
internal/app/auth.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
csrfTokenCookie = "__Csrf_token"
|
||||||
|
sessionTokenCookie = "__Session_token"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrorUnauthorized = errors.New("unauthorized")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *DrainCloud) authorize(ctx *gin.Context) (*models.Session, error) {
|
||||||
|
session, err := d.getSession(ctx)
|
||||||
|
if err != nil && !errors.Is(err, http.ErrNoCookie) {
|
||||||
|
return nil, ErrorUnauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
if session == nil {
|
||||||
|
return nil, ErrorUnauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateSession(ctx, session); err != nil {
|
||||||
|
// TODO add audit log entry
|
||||||
|
return nil, ErrorUnauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug(ctx, "[authorize] user authorized", slog.Int64("session_id", session.ID))
|
||||||
|
|
||||||
|
return session, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateLoginAndPassword(login, password string) error {
|
||||||
|
if len(login) < 4 {
|
||||||
|
return fmt.Errorf("login must be longer than 8 chars")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(password) < 6 {
|
||||||
|
return fmt.Errorf("password must be longer than 8 chars")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSessionToken(length int) (string, error) {
|
||||||
|
bytes := make([]byte, length)
|
||||||
|
if _, err := rand.Read(bytes); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to generate token: %w", err)
|
||||||
|
}
|
||||||
|
return base64.URLEncoding.EncodeToString(bytes), nil
|
||||||
|
}
|
156
internal/app/login.go
Normal file
156
internal/app/login.go
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/domain"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrorAccessDenied = errors.New("access denied")
|
||||||
|
ErrorSessionExpired = errors.New("session expired")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *DrainCloud) Login(ctx *gin.Context) {
|
||||||
|
logger.Debug(ctx, "[Login] new request")
|
||||||
|
|
||||||
|
req := new(domain.LoginRequest)
|
||||||
|
err := ctx.BindJSON(req)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx, "[Login] failed to bind request", logger.Err(err))
|
||||||
|
ctx.JSON(http.StatusBadRequest, map[string]string{
|
||||||
|
"error": "bad request",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := d.login(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx, "[Login] failed to login user", logger.Err(err))
|
||||||
|
ctx.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DrainCloud) login(ctx *gin.Context, req *domain.LoginRequest) (*domain.LoginResponse, error) {
|
||||||
|
session, err := d.getSession(ctx)
|
||||||
|
if err != nil && !errors.Is(err, http.ErrNoCookie) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if session != nil {
|
||||||
|
if err := validateSession(ctx, session); err != nil {
|
||||||
|
// TODO add audit log entry
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug(ctx, "[login] user is already logged in", slog.Int64("session_id", session.ID))
|
||||||
|
return &domain.LoginResponse{
|
||||||
|
Ok: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
logger.Debug(ctx, "[login] session not found. trying to authorize")
|
||||||
|
|
||||||
|
passwordHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 10)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx, "[login] failed to generate password hash", logger.Err(err))
|
||||||
|
return nil, fmt.Errorf("failed to generate password hash: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := d.database.GetUserByLogin(ctx, req.Login)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch user by login: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(passwordHash, user.PasswordHash) {
|
||||||
|
logger.Warn(ctx, "[login] failed to login user. passwords hashes not equal")
|
||||||
|
return nil, ErrorAccessDenied
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionCreatedAt := time.Now()
|
||||||
|
sessionExpiredAt := sessionCreatedAt.Add(time.Hour * 24 * 7)
|
||||||
|
|
||||||
|
sessionToken, err := generateSessionToken(100)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to generate a session token: %w", err)
|
||||||
|
}
|
||||||
|
ctx.SetCookie(sessionTokenCookie, sessionToken, int(sessionExpiredAt.Sub(sessionCreatedAt).Seconds()), "_path", "_domain", true, true)
|
||||||
|
|
||||||
|
csrfToken, err := generateSessionToken(100)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to generate a csrf token: %w", err)
|
||||||
|
}
|
||||||
|
ctx.SetCookie(csrfTokenCookie, csrfToken, int(sessionExpiredAt.Sub(sessionCreatedAt).Seconds()), "_path", "_domain", true, false)
|
||||||
|
|
||||||
|
if _, err = d.database.AddSession(ctx, &models.Session{
|
||||||
|
SessionToken: sessionToken,
|
||||||
|
CsrfToken: csrfToken,
|
||||||
|
UserID: user.ID,
|
||||||
|
CreatedAt: sessionCreatedAt,
|
||||||
|
ExpiredAt: sessionExpiredAt,
|
||||||
|
}); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save session: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add audit log entry
|
||||||
|
|
||||||
|
return &domain.LoginResponse{
|
||||||
|
Ok: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DrainCloud) getSession(ctx *gin.Context) (*models.Session, error) {
|
||||||
|
token, err := ctx.Cookie(sessionTokenCookie)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch session cookie from request: %w", err)
|
||||||
|
}
|
||||||
|
csrfToken, err := ctx.Cookie(csrfTokenCookie)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch csrf cookie from request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(csrfToken) == 0 || len(token) == 0 {
|
||||||
|
return nil, fmt.Errorf("session token or csrf token is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err := d.database.GetSession(ctx, token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch session from repo: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return session, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateSession(ctx *gin.Context, session *models.Session) error {
|
||||||
|
if session == nil {
|
||||||
|
return ErrorAccessDenied
|
||||||
|
}
|
||||||
|
|
||||||
|
csrfToken, err := ctx.Cookie(csrfTokenCookie)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fetch csrf cookie from request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if session.CsrfToken != csrfToken {
|
||||||
|
return ErrorAccessDenied
|
||||||
|
}
|
||||||
|
|
||||||
|
if session.ExpiredAt.Before(time.Now()) {
|
||||||
|
return ErrorSessionExpired
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
28
internal/app/middleware.go
Normal file
28
internal/app/middleware.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/reqcontext"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type authorizer interface {
|
||||||
|
authorize(ctx *gin.Context) (*models.Session, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithAuth(handler gin.HandlerFunc, auth authorizer) gin.HandlerFunc {
|
||||||
|
return func(ctx *gin.Context) {
|
||||||
|
sess, err := auth.authorize(ctx)
|
||||||
|
if err != nil {
|
||||||
|
writeError(ctx, err)
|
||||||
|
ctx.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
authCtx := reqcontext.WithSession(ctx.Request.Context(), sess)
|
||||||
|
authCtx = reqcontext.WithUserID(authCtx, sess.UserID)
|
||||||
|
ctx.Request = ctx.Request.WithContext(authCtx)
|
||||||
|
|
||||||
|
handler(ctx)
|
||||||
|
}
|
||||||
|
}
|
93
internal/app/register.go
Normal file
93
internal/app/register.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/domain"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *DrainCloud) Register(ctx *gin.Context) {
|
||||||
|
logger.Debug(ctx, "[register] new request")
|
||||||
|
|
||||||
|
// TODO check if registration is enabled
|
||||||
|
|
||||||
|
req := new(domain.RegisterRequest)
|
||||||
|
err := ctx.BindJSON(req)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx, "[register] failed to bind request", logger.Err(err))
|
||||||
|
ctx.JSON(http.StatusBadRequest, map[string]string{
|
||||||
|
"error": "bad request",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := d.register(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx, "[register] failed to register user", logger.Err(err))
|
||||||
|
ctx.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DrainCloud) register(ctx *gin.Context, req *domain.RegisterRequest) (*domain.RegisterResponse, error) {
|
||||||
|
if err := validateLoginAndPassword(req.Login, req.Password); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid creds: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
passwordHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 10)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx, "[register] failed to generate password hash", logger.Err(err))
|
||||||
|
return nil, fmt.Errorf("failed to generate password hash: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user := &models.User{
|
||||||
|
Username: req.Login,
|
||||||
|
Login: req.Login,
|
||||||
|
PasswordHash: passwordHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, err := d.database.AddUser(ctx, user.Login, user.Username, user.PasswordHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to add new user: %w", err)
|
||||||
|
}
|
||||||
|
user.ID = userID
|
||||||
|
|
||||||
|
sessionCreatedAt := time.Now()
|
||||||
|
sessionExpiredAt := sessionCreatedAt.Add(time.Hour * 24 * 7)
|
||||||
|
|
||||||
|
sessionToken, err := generateSessionToken(100)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to generate a session token: %w", err)
|
||||||
|
}
|
||||||
|
ctx.SetCookie(sessionTokenCookie, sessionToken, int(sessionExpiredAt.Sub(sessionCreatedAt).Seconds()), "_path", "_domain", true, true)
|
||||||
|
|
||||||
|
csrfToken, err := generateSessionToken(100)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to generate a csrf token: %w", err)
|
||||||
|
}
|
||||||
|
ctx.SetCookie(csrfTokenCookie, csrfToken, int(sessionExpiredAt.Sub(sessionCreatedAt).Seconds()), "_path", "_domain", true, false)
|
||||||
|
|
||||||
|
if _, err = d.database.AddSession(ctx, &models.Session{
|
||||||
|
SessionToken: sessionToken,
|
||||||
|
CsrfToken: csrfToken,
|
||||||
|
UserID: user.ID,
|
||||||
|
CreatedAt: sessionCreatedAt,
|
||||||
|
ExpiredAt: sessionExpiredAt,
|
||||||
|
}); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save session: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &domain.RegisterResponse{
|
||||||
|
Ok: true,
|
||||||
|
}, nil
|
||||||
|
}
|
52
internal/app/upload_file.go
Normal file
52
internal/app/upload_file.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
|
filesengine "git.optclblast.xyz/draincloud/draincloud-core/internal/files_engine"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxFileSize = 10 << 30
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *DrainCloud) UploadFile(ctx *gin.Context) {
|
||||||
|
if err := ctx.Request.ParseMultipartForm(maxFileSize); err != nil {
|
||||||
|
logger.Error(ctx, "uploadFile handler error", logger.Err(err))
|
||||||
|
writeError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := d.uploadFile(ctx); err != nil {
|
||||||
|
logger.Error(ctx, "uploadFile handle", logger.Err(err))
|
||||||
|
writeError(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DrainCloud) uploadFile(ctx *gin.Context) error {
|
||||||
|
title := ctx.PostForm("file")
|
||||||
|
logger.Info(ctx, "uploadFile", slog.Any("postForm data", spew.Sdump(title)))
|
||||||
|
|
||||||
|
file, header, err := ctx.Request.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info(ctx, "uploadFile", slog.Any("header", spew.Sdump(header)))
|
||||||
|
|
||||||
|
data, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.filesEngine.SaveFile(ctx, filesengine.File{
|
||||||
|
Name: header.Filename,
|
||||||
|
// UserID: ,
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
46
internal/cron/cleanup_sessions/cleanup_session.go
Normal file
46
internal/cron/cleanup_sessions/cleanup_session.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package cleanupsessions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO set with config
|
||||||
|
const cronInterval = time.Minute * 10
|
||||||
|
|
||||||
|
type ExpiredSessionsRemover interface {
|
||||||
|
RemoveExpiredSessions(ctx context.Context) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type CleanupSessionCron struct {
|
||||||
|
db ExpiredSessionsRemover
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(db ExpiredSessionsRemover) *CleanupSessionCron {
|
||||||
|
return &CleanupSessionCron{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CleanupSessionCron) Run(ctx context.Context) {
|
||||||
|
logger.Info(ctx, "[CleanupSessionCron] running cron")
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(cronInterval)
|
||||||
|
defer t.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
logger.Warn(ctx, "[CleanupSessionCron] context cancelled")
|
||||||
|
return
|
||||||
|
case <-t.C:
|
||||||
|
logger.Notice(ctx, "[CleanupSessionCron] cleanup started")
|
||||||
|
t.Reset(cronInterval)
|
||||||
|
if err := c.db.RemoveExpiredSessions(ctx); err != nil {
|
||||||
|
logger.Error(ctx, "[CleanupSessionCron] failed to remove expired sessions", logger.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
7
internal/cron/cron.go
Normal file
7
internal/cron/cron.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package cron
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
type Cron interface {
|
||||||
|
Run(ctx context.Context)
|
||||||
|
}
|
1
internal/domain/files.go
Normal file
1
internal/domain/files.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package domain
|
@ -15,5 +15,15 @@ type LoginRequest struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LoginResponse struct {
|
||||||
|
Ok bool `json:"ok"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
type LogoutRequest struct {
|
type LogoutRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ErrorJson struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
39
internal/files_engine/engine.go
Normal file
39
internal/files_engine/engine.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package filesengine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FilesEngine struct {
|
||||||
|
blobStorage storage.BlobStorage
|
||||||
|
metaStorage storage.MetaStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFilesEngine(
|
||||||
|
blobStorage storage.BlobStorage,
|
||||||
|
metaStorage storage.MetaStorage,
|
||||||
|
) *FilesEngine {
|
||||||
|
return &FilesEngine{
|
||||||
|
blobStorage: blobStorage,
|
||||||
|
metaStorage: metaStorage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Name string
|
||||||
|
UserID int64
|
||||||
|
Ext string
|
||||||
|
Type string
|
||||||
|
Size int64
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *FilesEngine) SaveFile(
|
||||||
|
ctx context.Context,
|
||||||
|
file File,
|
||||||
|
) (int64, error) {
|
||||||
|
|
||||||
|
return -1, nil
|
||||||
|
}
|
@ -7,7 +7,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoglobals // ...
|
//nolint:gochecknoglobals // ...
|
||||||
var globalLogger *slog.Logger = newLogger(LevelInfo, os.Stdout)
|
var globalLogger *slog.Logger = newLogger(LevelDebug, os.Stdout)
|
||||||
|
|
||||||
|
func SetLevel(l slog.Level) {
|
||||||
|
globalLogger = newLogger(l, os.Stdout)
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LevelEmergency = slog.Level(10000)
|
LevelEmergency = slog.Level(10000)
|
||||||
@ -73,5 +77,5 @@ func Info(ctx context.Context, message string, attrs ...any) {
|
|||||||
func Debug(ctx context.Context, message string, attrs ...any) {
|
func Debug(ctx context.Context, message string, attrs ...any) {
|
||||||
l := loggerFromCtx(ctx)
|
l := loggerFromCtx(ctx)
|
||||||
|
|
||||||
l.Log(ctx, LevelCritial, message, attrs...)
|
l.DebugContext(ctx, message, attrs...)
|
||||||
}
|
}
|
||||||
|
37
internal/reqcontext/auth.go
Normal file
37
internal/reqcontext/auth.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package reqcontext
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CtxKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserIDCtxKey CtxKey = "_ctx_user_id"
|
||||||
|
SessionCtxKey CtxKey = "_ctx_session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithUserID(parent context.Context, userID int64) context.Context {
|
||||||
|
return context.WithValue(parent, UserIDCtxKey, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserID(ctx context.Context) (int64, error) {
|
||||||
|
if id, ok := ctx.Value(UserIDCtxKey).(int64); ok {
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
return -1, fmt.Errorf("userID not passed with context")
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithSession(parent context.Context, session *models.Session) context.Context {
|
||||||
|
return context.WithValue(parent, SessionCtxKey, session)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSession(ctx context.Context) (*models.Session, error) {
|
||||||
|
if ses, ok := ctx.Value(UserIDCtxKey).(*models.Session); ok {
|
||||||
|
return ses, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("session not passed with context")
|
||||||
|
}
|
19
internal/storage/audit/storage.go
Normal file
19
internal/storage/audit/storage.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package audit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/audit"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Repository struct {
|
||||||
|
db *pgx.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repository) AddEntry(ctx context.Context, entry audit.AuditLogEntry) error {
|
||||||
|
logger.Warn(ctx, "[Repository][AddEntry] not implemented yet!")
|
||||||
|
return nil
|
||||||
|
}
|
86
internal/storage/filestorage/fs/storage.go
Normal file
86
internal/storage/filestorage/fs/storage.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Storage struct {
|
||||||
|
lm *sync.Map
|
||||||
|
dir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFSStorage(dir string) *Storage {
|
||||||
|
return &Storage{
|
||||||
|
lm: &sync.Map{},
|
||||||
|
dir: dir,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Storage) GetFile(ctx context.Context, id int64) (*os.File, error) {
|
||||||
|
tx := lockFile(s.lm, id)
|
||||||
|
defer unlockFile(s.lm, id, tx)
|
||||||
|
|
||||||
|
file, err := os.Open(getFilePath(s.dir, id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open file: %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err = file.Close(); err != nil {
|
||||||
|
logger.Error(ctx, "[getFile] close error", logger.Err(err))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return file, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Storage) SaveBlob(ctx context.Context, id int64, data []byte) error {
|
||||||
|
tx := lockFile(s.lm, id)
|
||||||
|
defer unlockFile(s.lm, id, tx)
|
||||||
|
|
||||||
|
file, err := os.Open(getFilePath(s.dir, id))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open file: %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err = file.Close(); err != nil {
|
||||||
|
logger.Error(ctx, "[saveFile] close error", logger.Err(err))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if _, err = file.Write(data); err != nil {
|
||||||
|
return fmt.Errorf("failed to write data to file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Storage) DeleteFile(ctx context.Context, id int64) error {
|
||||||
|
tx := lockFile(s.lm, id)
|
||||||
|
defer unlockFile(s.lm, id, tx)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFilePath(dir string, id int64) string {
|
||||||
|
return fmt.Sprintf("%s/%v", dir, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lockFile(lm *sync.Map, id int64) sync.Locker {
|
||||||
|
_m := &sync.Mutex{}
|
||||||
|
many, _ := lm.LoadOrStore(id, _m)
|
||||||
|
_m, _ = many.(*sync.Mutex)
|
||||||
|
_m.Lock()
|
||||||
|
return _m
|
||||||
|
}
|
||||||
|
|
||||||
|
func unlockFile(lm *sync.Map, id int64, tx sync.Locker) {
|
||||||
|
tx.Unlock()
|
||||||
|
lm.Delete(id)
|
||||||
|
}
|
@ -2,8 +2,10 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
auditmodels "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/audit"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Database interface {
|
type Database interface {
|
||||||
@ -11,7 +13,25 @@ type Database interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AuthStorage interface {
|
type AuthStorage interface {
|
||||||
AddUser(ctx context.Context, login string, username string, passwordHash []byte) (uint64, error)
|
AddUser(ctx context.Context, login string, username string, passwordHash []byte) (int64, error)
|
||||||
GetUserByLogin(ctx context.Context, login string) (*models.User, error)
|
GetUserByLogin(ctx context.Context, login string) (*models.User, error)
|
||||||
GetUserByID(ctx context.Context, id uint64) (*models.User, error)
|
GetUserByID(ctx context.Context, id uint64) (*models.User, error)
|
||||||
|
|
||||||
|
AddSession(ctx context.Context, ses *models.Session) (int64, error)
|
||||||
|
GetSession(ctx context.Context, sessionToken string) (*models.Session, error)
|
||||||
|
RemoveSession(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthAuditLogStorage interface {
|
||||||
|
AddEntry(ctx context.Context, entry auditmodels.AuditLogEntry) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetaStorage interface {
|
||||||
|
SaveMetadata(ctx context.Context, fileType string, size int64, ext string) (int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BlobStorage interface {
|
||||||
|
GetFile(ctx context.Context, id int64) (*os.File, error)
|
||||||
|
SaveBlob(ctx context.Context, id int64, data []byte) error
|
||||||
|
DeleteFile(ctx context.Context, id int64) error
|
||||||
}
|
}
|
||||||
|
49
internal/storage/models/audit/audit_log.go
Normal file
49
internal/storage/models/audit/audit_log.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package audit
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type EventType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
EventUnspecified EventType = iota
|
||||||
|
EventSuccessfullLogin
|
||||||
|
EventFailedLogin
|
||||||
|
EventSuccessfullRegister
|
||||||
|
EventFailedRegister
|
||||||
|
EventSuccessfullAuth
|
||||||
|
EventFailedAuth
|
||||||
|
EventUserUpdated
|
||||||
|
)
|
||||||
|
|
||||||
|
type Severity int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SeverityAlert = 0
|
||||||
|
SeverityWarning = 10
|
||||||
|
SeverityInfo = 100
|
||||||
|
SeverityNotice = 200
|
||||||
|
)
|
||||||
|
|
||||||
|
type Actor struct {
|
||||||
|
ActorSysName string
|
||||||
|
RemoteIP string
|
||||||
|
ID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ActorDrainCloudCore = "_actor_draincloud_core"
|
||||||
|
ActorUser = "user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuditLogEntry struct {
|
||||||
|
EventType EventType
|
||||||
|
// Who caused changes
|
||||||
|
Actor Actor
|
||||||
|
Severity Severity
|
||||||
|
SessionID int64
|
||||||
|
CreatedAt time.Time
|
||||||
|
// What changed
|
||||||
|
Object string
|
||||||
|
// How it was changed
|
||||||
|
Action string
|
||||||
|
}
|
@ -3,16 +3,16 @@ package models
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
ID string
|
ID int64
|
||||||
SessionToken string
|
SessionToken string
|
||||||
CsrfToken string
|
CsrfToken string
|
||||||
User *User
|
UserID int64
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
ExpiredAt time.Time
|
ExpiredAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID uint64
|
ID int64
|
||||||
Username string
|
Username string
|
||||||
Login string
|
Login string
|
||||||
PasswordHash []byte
|
PasswordHash []byte
|
||||||
|
@ -2,7 +2,9 @@ package postgres
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.optclblast.xyz/draincloud/draincloud-core/internal/closer"
|
"git.optclblast.xyz/draincloud/draincloud-core/internal/closer"
|
||||||
@ -37,7 +39,7 @@ type dbtx interface {
|
|||||||
Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
|
Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Database) AddUser(ctx context.Context, login string, username string, passwordHash []byte) (uint64, error) {
|
func (d *Database) AddUser(ctx context.Context, login string, username string, passwordHash []byte) (int64, error) {
|
||||||
return addUser(ctx, d.db, login, username, passwordHash)
|
return addUser(ctx, d.db, login, username, passwordHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,18 +51,59 @@ func (d *Database) GetUserByLogin(ctx context.Context, login string) (*models.Us
|
|||||||
return getUserByLogin(ctx, d.db, login)
|
return getUserByLogin(ctx, d.db, login)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Database) AddSession(ctx context.Context, ses *models.Session) (uint64, error) {
|
func (d *Database) AddSession(ctx context.Context, ses *models.Session) (int64, error) {
|
||||||
return addSession(ctx, d.db, ses)
|
return addSession(ctx, d.db, ses)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addUser(ctx context.Context, conn dbtx, login string, username string, passwordHash []byte) (uint64, error) {
|
func (d *Database) GetSession(ctx context.Context, sessionToken string) (*models.Session, error) {
|
||||||
|
const stmt = `SELECT
|
||||||
|
s.id, s.session_token, s.csrf_token, s.user_id, s.created_at, s.expired_at
|
||||||
|
FROM sessions as s
|
||||||
|
WHERE s.session_token = $1;`
|
||||||
|
|
||||||
|
row := d.db.QueryRow(ctx, stmt, sessionToken)
|
||||||
|
|
||||||
|
var (
|
||||||
|
id int64
|
||||||
|
sesToken, csrfToken string
|
||||||
|
userID int64
|
||||||
|
createdAt sql.NullTime
|
||||||
|
expiredAt sql.NullTime
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := row.Scan(&id, &sesToken, &csrfToken, &userID, &createdAt, &expiredAt); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &models.Session{
|
||||||
|
ID: id,
|
||||||
|
SessionToken: sesToken,
|
||||||
|
CsrfToken: csrfToken,
|
||||||
|
UserID: userID,
|
||||||
|
CreatedAt: createdAt.Time,
|
||||||
|
ExpiredAt: expiredAt.Time,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Database) RemoveSession(ctx context.Context, id int64) error {
|
||||||
|
const stmt = `DELETE FROM sessions WHERE id = $1;`
|
||||||
|
_, err := d.db.Exec(ctx, stmt, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Database) RemoveExpiredSessions(ctx context.Context) error {
|
||||||
|
const stmt = `DELETE FROM sessions WHERE expired_at < $1;`
|
||||||
|
res, err := d.db.Exec(ctx, stmt, time.Now())
|
||||||
|
logger.Notice(ctx, "[Database][RemoveExpiredSessions] sessions cleanup", slog.Int64("removed", res.RowsAffected()))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func addUser(ctx context.Context, conn dbtx, login string, username string, passwordHash []byte) (int64, error) {
|
||||||
const stmt = `INSERT INTO users (login,username,password)
|
const stmt = `INSERT INTO users (login,username,password)
|
||||||
VALUES ($1,$2,$3) RETURNING id`
|
VALUES ($1,$2,$3) RETURNING id`
|
||||||
|
|
||||||
row := conn.QueryRow(ctx, stmt, login, username, passwordHash)
|
row := conn.QueryRow(ctx, stmt, login, username, passwordHash)
|
||||||
|
var id int64
|
||||||
var id uint64
|
|
||||||
|
|
||||||
if err := row.Scan(&id); err != nil {
|
if err := row.Scan(&id); err != nil {
|
||||||
return 0, fmt.Errorf("failed to insert user data into users table: %w", err)
|
return 0, fmt.Errorf("failed to insert user data into users table: %w", err)
|
||||||
}
|
}
|
||||||
@ -71,7 +114,6 @@ func addUser(ctx context.Context, conn dbtx, login string, username string, pass
|
|||||||
func getUserByID(ctx context.Context, conn dbtx, id uint64) (*models.User, error) {
|
func getUserByID(ctx context.Context, conn dbtx, id uint64) (*models.User, error) {
|
||||||
const stmt = `SELECT * FROM users WHERE id = $1 LIMIT 1`
|
const stmt = `SELECT * FROM users WHERE id = $1 LIMIT 1`
|
||||||
u := new(models.User)
|
u := new(models.User)
|
||||||
|
|
||||||
row := conn.QueryRow(ctx, stmt, id)
|
row := conn.QueryRow(ctx, stmt, id)
|
||||||
if err := row.Scan(&u.ID, &u.Login, &u.Username, &u.PasswordHash, &u.CreatedAt, &u.UpdatedAt); err != nil {
|
if err := row.Scan(&u.ID, &u.Login, &u.Username, &u.PasswordHash, &u.CreatedAt, &u.UpdatedAt); err != nil {
|
||||||
return nil, fmt.Errorf("failed to fetch user by id: %w", err)
|
return nil, fmt.Errorf("failed to fetch user by id: %w", err)
|
||||||
@ -83,7 +125,6 @@ func getUserByID(ctx context.Context, conn dbtx, id uint64) (*models.User, error
|
|||||||
func getUserByLogin(ctx context.Context, conn dbtx, login string) (*models.User, error) {
|
func getUserByLogin(ctx context.Context, conn dbtx, login string) (*models.User, error) {
|
||||||
const stmt = `SELECT * FROM users WHERE login = $1 LIMIT 1`
|
const stmt = `SELECT * FROM users WHERE login = $1 LIMIT 1`
|
||||||
u := new(models.User)
|
u := new(models.User)
|
||||||
|
|
||||||
row := conn.QueryRow(ctx, stmt, login)
|
row := conn.QueryRow(ctx, stmt, login)
|
||||||
if err := row.Scan(&u.ID, &u.Login, &u.Username, &u.PasswordHash, &u.CreatedAt, &u.UpdatedAt); err != nil {
|
if err := row.Scan(&u.ID, &u.Login, &u.Username, &u.PasswordHash, &u.CreatedAt, &u.UpdatedAt); err != nil {
|
||||||
return nil, fmt.Errorf("failed to fetch user by login: %w", err)
|
return nil, fmt.Errorf("failed to fetch user by login: %w", err)
|
||||||
@ -92,11 +133,11 @@ func getUserByLogin(ctx context.Context, conn dbtx, login string) (*models.User,
|
|||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSession(ctx context.Context, conn dbtx, session *models.Session) (uint64, error) {
|
func addSession(ctx context.Context, conn dbtx, session *models.Session) (int64, error) {
|
||||||
const stmt = `INSERT INTO sessions (session_token, csrf_token, user_id,
|
const stmt = `INSERT INTO sessions (session_token, csrf_token, user_id,
|
||||||
created_at, expired_at) VALUES ($1, $2, $3, $4, $5) RETURNING id;`
|
created_at, expired_at) VALUES ($1, $2, $3, $4, $5) RETURNING id;`
|
||||||
var id uint64
|
var id int64
|
||||||
row := conn.QueryRow(ctx, stmt, session.SessionToken, session.CsrfToken, session.User.ID, session.CreatedAt, session.ExpiredAt)
|
row := conn.QueryRow(ctx, stmt, session.SessionToken, session.CsrfToken, session.UserID, session.CreatedAt, session.ExpiredAt)
|
||||||
if err := row.Scan(&id); err != nil {
|
if err := row.Scan(&id); err != nil {
|
||||||
return 0, fmt.Errorf("failed to insert new session: %w", err)
|
return 0, fmt.Errorf("failed to insert new session: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
// Code generated by mockery v2.48.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
audit "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/audit"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockAuthAuditLogStorage is an autogenerated mock type for the AuthAuditLogStorage type
|
||||||
|
type MockAuthAuditLogStorage struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockAuthAuditLogStorage_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockAuthAuditLogStorage) EXPECT() *MockAuthAuditLogStorage_Expecter {
|
||||||
|
return &MockAuthAuditLogStorage_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEntry provides a mock function with given fields: ctx, entry
|
||||||
|
func (_m *MockAuthAuditLogStorage) AddEntry(ctx context.Context, entry audit.AuditLogEntry) error {
|
||||||
|
ret := _m.Called(ctx, entry)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for AddEntry")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, audit.AuditLogEntry) error); ok {
|
||||||
|
r0 = rf(ctx, entry)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAuthAuditLogStorage_AddEntry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddEntry'
|
||||||
|
type MockAuthAuditLogStorage_AddEntry_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEntry is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - entry audit.AuditLogEntry
|
||||||
|
func (_e *MockAuthAuditLogStorage_Expecter) AddEntry(ctx interface{}, entry interface{}) *MockAuthAuditLogStorage_AddEntry_Call {
|
||||||
|
return &MockAuthAuditLogStorage_AddEntry_Call{Call: _e.mock.On("AddEntry", ctx, entry)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthAuditLogStorage_AddEntry_Call) Run(run func(ctx context.Context, entry audit.AuditLogEntry)) *MockAuthAuditLogStorage_AddEntry_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(audit.AuditLogEntry))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthAuditLogStorage_AddEntry_Call) Return(_a0 error) *MockAuthAuditLogStorage_AddEntry_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthAuditLogStorage_AddEntry_Call) RunAndReturn(run func(context.Context, audit.AuditLogEntry) error) *MockAuthAuditLogStorage_AddEntry_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockAuthAuditLogStorage creates a new instance of MockAuthAuditLogStorage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockAuthAuditLogStorage(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockAuthAuditLogStorage {
|
||||||
|
mock := &MockAuthAuditLogStorage{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
@ -0,0 +1,377 @@
|
|||||||
|
// Code generated by mockery v2.48.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
models "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockAuthStorage is an autogenerated mock type for the AuthStorage type
|
||||||
|
type MockAuthStorage struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockAuthStorage_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockAuthStorage) EXPECT() *MockAuthStorage_Expecter {
|
||||||
|
return &MockAuthStorage_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSession provides a mock function with given fields: ctx, ses
|
||||||
|
func (_m *MockAuthStorage) AddSession(ctx context.Context, ses *models.Session) (int64, error) {
|
||||||
|
ret := _m.Called(ctx, ses)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for AddSession")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *models.Session) (int64, error)); ok {
|
||||||
|
return rf(ctx, ses)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *models.Session) int64); ok {
|
||||||
|
r0 = rf(ctx, ses)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *models.Session) error); ok {
|
||||||
|
r1 = rf(ctx, ses)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAuthStorage_AddSession_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddSession'
|
||||||
|
type MockAuthStorage_AddSession_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSession is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - ses *models.Session
|
||||||
|
func (_e *MockAuthStorage_Expecter) AddSession(ctx interface{}, ses interface{}) *MockAuthStorage_AddSession_Call {
|
||||||
|
return &MockAuthStorage_AddSession_Call{Call: _e.mock.On("AddSession", ctx, ses)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_AddSession_Call) Run(run func(ctx context.Context, ses *models.Session)) *MockAuthStorage_AddSession_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(*models.Session))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_AddSession_Call) Return(_a0 int64, _a1 error) *MockAuthStorage_AddSession_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_AddSession_Call) RunAndReturn(run func(context.Context, *models.Session) (int64, error)) *MockAuthStorage_AddSession_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddUser provides a mock function with given fields: ctx, login, username, passwordHash
|
||||||
|
func (_m *MockAuthStorage) AddUser(ctx context.Context, login string, username string, passwordHash []byte) (int64, error) {
|
||||||
|
ret := _m.Called(ctx, login, username, passwordHash)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for AddUser")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte) (int64, error)); ok {
|
||||||
|
return rf(ctx, login, username, passwordHash)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte) int64); ok {
|
||||||
|
r0 = rf(ctx, login, username, passwordHash)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, []byte) error); ok {
|
||||||
|
r1 = rf(ctx, login, username, passwordHash)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAuthStorage_AddUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddUser'
|
||||||
|
type MockAuthStorage_AddUser_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddUser is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - login string
|
||||||
|
// - username string
|
||||||
|
// - passwordHash []byte
|
||||||
|
func (_e *MockAuthStorage_Expecter) AddUser(ctx interface{}, login interface{}, username interface{}, passwordHash interface{}) *MockAuthStorage_AddUser_Call {
|
||||||
|
return &MockAuthStorage_AddUser_Call{Call: _e.mock.On("AddUser", ctx, login, username, passwordHash)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_AddUser_Call) Run(run func(ctx context.Context, login string, username string, passwordHash []byte)) *MockAuthStorage_AddUser_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].([]byte))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_AddUser_Call) Return(_a0 int64, _a1 error) *MockAuthStorage_AddUser_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_AddUser_Call) RunAndReturn(run func(context.Context, string, string, []byte) (int64, error)) *MockAuthStorage_AddUser_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSession provides a mock function with given fields: ctx, sessionToken
|
||||||
|
func (_m *MockAuthStorage) GetSession(ctx context.Context, sessionToken string) (*models.Session, error) {
|
||||||
|
ret := _m.Called(ctx, sessionToken)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for GetSession")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *models.Session
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.Session, error)); ok {
|
||||||
|
return rf(ctx, sessionToken)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Session); ok {
|
||||||
|
r0 = rf(ctx, sessionToken)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*models.Session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||||
|
r1 = rf(ctx, sessionToken)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAuthStorage_GetSession_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSession'
|
||||||
|
type MockAuthStorage_GetSession_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSession is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - sessionToken string
|
||||||
|
func (_e *MockAuthStorage_Expecter) GetSession(ctx interface{}, sessionToken interface{}) *MockAuthStorage_GetSession_Call {
|
||||||
|
return &MockAuthStorage_GetSession_Call{Call: _e.mock.On("GetSession", ctx, sessionToken)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetSession_Call) Run(run func(ctx context.Context, sessionToken string)) *MockAuthStorage_GetSession_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetSession_Call) Return(_a0 *models.Session, _a1 error) *MockAuthStorage_GetSession_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetSession_Call) RunAndReturn(run func(context.Context, string) (*models.Session, error)) *MockAuthStorage_GetSession_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID provides a mock function with given fields: ctx, id
|
||||||
|
func (_m *MockAuthStorage) GetUserByID(ctx context.Context, id uint64) (*models.User, error) {
|
||||||
|
ret := _m.Called(ctx, id)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for GetUserByID")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *models.User
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, uint64) (*models.User, error)); ok {
|
||||||
|
return rf(ctx, id)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, uint64) *models.User); ok {
|
||||||
|
r0 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*models.User)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok {
|
||||||
|
r1 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAuthStorage_GetUserByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserByID'
|
||||||
|
type MockAuthStorage_GetUserByID_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - id uint64
|
||||||
|
func (_e *MockAuthStorage_Expecter) GetUserByID(ctx interface{}, id interface{}) *MockAuthStorage_GetUserByID_Call {
|
||||||
|
return &MockAuthStorage_GetUserByID_Call{Call: _e.mock.On("GetUserByID", ctx, id)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetUserByID_Call) Run(run func(ctx context.Context, id uint64)) *MockAuthStorage_GetUserByID_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(uint64))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetUserByID_Call) Return(_a0 *models.User, _a1 error) *MockAuthStorage_GetUserByID_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetUserByID_Call) RunAndReturn(run func(context.Context, uint64) (*models.User, error)) *MockAuthStorage_GetUserByID_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByLogin provides a mock function with given fields: ctx, login
|
||||||
|
func (_m *MockAuthStorage) GetUserByLogin(ctx context.Context, login string) (*models.User, error) {
|
||||||
|
ret := _m.Called(ctx, login)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for GetUserByLogin")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *models.User
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.User, error)); ok {
|
||||||
|
return rf(ctx, login)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) *models.User); ok {
|
||||||
|
r0 = rf(ctx, login)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*models.User)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||||
|
r1 = rf(ctx, login)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAuthStorage_GetUserByLogin_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserByLogin'
|
||||||
|
type MockAuthStorage_GetUserByLogin_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByLogin is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - login string
|
||||||
|
func (_e *MockAuthStorage_Expecter) GetUserByLogin(ctx interface{}, login interface{}) *MockAuthStorage_GetUserByLogin_Call {
|
||||||
|
return &MockAuthStorage_GetUserByLogin_Call{Call: _e.mock.On("GetUserByLogin", ctx, login)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetUserByLogin_Call) Run(run func(ctx context.Context, login string)) *MockAuthStorage_GetUserByLogin_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetUserByLogin_Call) Return(_a0 *models.User, _a1 error) *MockAuthStorage_GetUserByLogin_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_GetUserByLogin_Call) RunAndReturn(run func(context.Context, string) (*models.User, error)) *MockAuthStorage_GetUserByLogin_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSession provides a mock function with given fields: ctx, id
|
||||||
|
func (_m *MockAuthStorage) RemoveSession(ctx context.Context, id int64) error {
|
||||||
|
ret := _m.Called(ctx, id)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for RemoveSession")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
|
||||||
|
r0 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAuthStorage_RemoveSession_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveSession'
|
||||||
|
type MockAuthStorage_RemoveSession_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSession is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - id int64
|
||||||
|
func (_e *MockAuthStorage_Expecter) RemoveSession(ctx interface{}, id interface{}) *MockAuthStorage_RemoveSession_Call {
|
||||||
|
return &MockAuthStorage_RemoveSession_Call{Call: _e.mock.On("RemoveSession", ctx, id)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_RemoveSession_Call) Run(run func(ctx context.Context, id int64)) *MockAuthStorage_RemoveSession_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(int64))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_RemoveSession_Call) Return(_a0 error) *MockAuthStorage_RemoveSession_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAuthStorage_RemoveSession_Call) RunAndReturn(run func(context.Context, int64) error) *MockAuthStorage_RemoveSession_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockAuthStorage creates a new instance of MockAuthStorage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockAuthStorage(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockAuthStorage {
|
||||||
|
mock := &MockAuthStorage{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
@ -0,0 +1,191 @@
|
|||||||
|
// Code generated by mockery v2.48.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
os "os"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockBlobStorage is an autogenerated mock type for the BlobStorage type
|
||||||
|
type MockBlobStorage struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockBlobStorage_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockBlobStorage) EXPECT() *MockBlobStorage_Expecter {
|
||||||
|
return &MockBlobStorage_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFile provides a mock function with given fields: ctx, id
|
||||||
|
func (_m *MockBlobStorage) DeleteFile(ctx context.Context, id int64) error {
|
||||||
|
ret := _m.Called(ctx, id)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for DeleteFile")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
|
||||||
|
r0 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockBlobStorage_DeleteFile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteFile'
|
||||||
|
type MockBlobStorage_DeleteFile_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFile is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - id int64
|
||||||
|
func (_e *MockBlobStorage_Expecter) DeleteFile(ctx interface{}, id interface{}) *MockBlobStorage_DeleteFile_Call {
|
||||||
|
return &MockBlobStorage_DeleteFile_Call{Call: _e.mock.On("DeleteFile", ctx, id)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_DeleteFile_Call) Run(run func(ctx context.Context, id int64)) *MockBlobStorage_DeleteFile_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(int64))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_DeleteFile_Call) Return(_a0 error) *MockBlobStorage_DeleteFile_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_DeleteFile_Call) RunAndReturn(run func(context.Context, int64) error) *MockBlobStorage_DeleteFile_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFile provides a mock function with given fields: ctx, id
|
||||||
|
func (_m *MockBlobStorage) GetFile(ctx context.Context, id int64) (*os.File, error) {
|
||||||
|
ret := _m.Called(ctx, id)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for GetFile")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *os.File
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64) (*os.File, error)); ok {
|
||||||
|
return rf(ctx, id)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64) *os.File); ok {
|
||||||
|
r0 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*os.File)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
|
||||||
|
r1 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockBlobStorage_GetFile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFile'
|
||||||
|
type MockBlobStorage_GetFile_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFile is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - id int64
|
||||||
|
func (_e *MockBlobStorage_Expecter) GetFile(ctx interface{}, id interface{}) *MockBlobStorage_GetFile_Call {
|
||||||
|
return &MockBlobStorage_GetFile_Call{Call: _e.mock.On("GetFile", ctx, id)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_GetFile_Call) Run(run func(ctx context.Context, id int64)) *MockBlobStorage_GetFile_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(int64))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_GetFile_Call) Return(_a0 *os.File, _a1 error) *MockBlobStorage_GetFile_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_GetFile_Call) RunAndReturn(run func(context.Context, int64) (*os.File, error)) *MockBlobStorage_GetFile_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveBlob provides a mock function with given fields: ctx, id, data
|
||||||
|
func (_m *MockBlobStorage) SaveBlob(ctx context.Context, id int64, data []byte) error {
|
||||||
|
ret := _m.Called(ctx, id, data)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for SaveBlob")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64, []byte) error); ok {
|
||||||
|
r0 = rf(ctx, id, data)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockBlobStorage_SaveBlob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveBlob'
|
||||||
|
type MockBlobStorage_SaveBlob_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveBlob is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - id int64
|
||||||
|
// - data []byte
|
||||||
|
func (_e *MockBlobStorage_Expecter) SaveBlob(ctx interface{}, id interface{}, data interface{}) *MockBlobStorage_SaveBlob_Call {
|
||||||
|
return &MockBlobStorage_SaveBlob_Call{Call: _e.mock.On("SaveBlob", ctx, id, data)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_SaveBlob_Call) Run(run func(ctx context.Context, id int64, data []byte)) *MockBlobStorage_SaveBlob_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(int64), args[2].([]byte))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_SaveBlob_Call) Return(_a0 error) *MockBlobStorage_SaveBlob_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockBlobStorage_SaveBlob_Call) RunAndReturn(run func(context.Context, int64, []byte) error) *MockBlobStorage_SaveBlob_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockBlobStorage creates a new instance of MockBlobStorage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockBlobStorage(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockBlobStorage {
|
||||||
|
mock := &MockBlobStorage{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
@ -0,0 +1,377 @@
|
|||||||
|
// Code generated by mockery v2.48.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
models "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockDatabase is an autogenerated mock type for the Database type
|
||||||
|
type MockDatabase struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockDatabase_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockDatabase) EXPECT() *MockDatabase_Expecter {
|
||||||
|
return &MockDatabase_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSession provides a mock function with given fields: ctx, ses
|
||||||
|
func (_m *MockDatabase) AddSession(ctx context.Context, ses *models.Session) (int64, error) {
|
||||||
|
ret := _m.Called(ctx, ses)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for AddSession")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *models.Session) (int64, error)); ok {
|
||||||
|
return rf(ctx, ses)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *models.Session) int64); ok {
|
||||||
|
r0 = rf(ctx, ses)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *models.Session) error); ok {
|
||||||
|
r1 = rf(ctx, ses)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockDatabase_AddSession_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddSession'
|
||||||
|
type MockDatabase_AddSession_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSession is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - ses *models.Session
|
||||||
|
func (_e *MockDatabase_Expecter) AddSession(ctx interface{}, ses interface{}) *MockDatabase_AddSession_Call {
|
||||||
|
return &MockDatabase_AddSession_Call{Call: _e.mock.On("AddSession", ctx, ses)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_AddSession_Call) Run(run func(ctx context.Context, ses *models.Session)) *MockDatabase_AddSession_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(*models.Session))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_AddSession_Call) Return(_a0 int64, _a1 error) *MockDatabase_AddSession_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_AddSession_Call) RunAndReturn(run func(context.Context, *models.Session) (int64, error)) *MockDatabase_AddSession_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddUser provides a mock function with given fields: ctx, login, username, passwordHash
|
||||||
|
func (_m *MockDatabase) AddUser(ctx context.Context, login string, username string, passwordHash []byte) (int64, error) {
|
||||||
|
ret := _m.Called(ctx, login, username, passwordHash)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for AddUser")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte) (int64, error)); ok {
|
||||||
|
return rf(ctx, login, username, passwordHash)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte) int64); ok {
|
||||||
|
r0 = rf(ctx, login, username, passwordHash)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, []byte) error); ok {
|
||||||
|
r1 = rf(ctx, login, username, passwordHash)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockDatabase_AddUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddUser'
|
||||||
|
type MockDatabase_AddUser_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddUser is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - login string
|
||||||
|
// - username string
|
||||||
|
// - passwordHash []byte
|
||||||
|
func (_e *MockDatabase_Expecter) AddUser(ctx interface{}, login interface{}, username interface{}, passwordHash interface{}) *MockDatabase_AddUser_Call {
|
||||||
|
return &MockDatabase_AddUser_Call{Call: _e.mock.On("AddUser", ctx, login, username, passwordHash)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_AddUser_Call) Run(run func(ctx context.Context, login string, username string, passwordHash []byte)) *MockDatabase_AddUser_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].([]byte))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_AddUser_Call) Return(_a0 int64, _a1 error) *MockDatabase_AddUser_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_AddUser_Call) RunAndReturn(run func(context.Context, string, string, []byte) (int64, error)) *MockDatabase_AddUser_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSession provides a mock function with given fields: ctx, sessionToken
|
||||||
|
func (_m *MockDatabase) GetSession(ctx context.Context, sessionToken string) (*models.Session, error) {
|
||||||
|
ret := _m.Called(ctx, sessionToken)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for GetSession")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *models.Session
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.Session, error)); ok {
|
||||||
|
return rf(ctx, sessionToken)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Session); ok {
|
||||||
|
r0 = rf(ctx, sessionToken)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*models.Session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||||
|
r1 = rf(ctx, sessionToken)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockDatabase_GetSession_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSession'
|
||||||
|
type MockDatabase_GetSession_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSession is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - sessionToken string
|
||||||
|
func (_e *MockDatabase_Expecter) GetSession(ctx interface{}, sessionToken interface{}) *MockDatabase_GetSession_Call {
|
||||||
|
return &MockDatabase_GetSession_Call{Call: _e.mock.On("GetSession", ctx, sessionToken)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetSession_Call) Run(run func(ctx context.Context, sessionToken string)) *MockDatabase_GetSession_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetSession_Call) Return(_a0 *models.Session, _a1 error) *MockDatabase_GetSession_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetSession_Call) RunAndReturn(run func(context.Context, string) (*models.Session, error)) *MockDatabase_GetSession_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID provides a mock function with given fields: ctx, id
|
||||||
|
func (_m *MockDatabase) GetUserByID(ctx context.Context, id uint64) (*models.User, error) {
|
||||||
|
ret := _m.Called(ctx, id)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for GetUserByID")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *models.User
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, uint64) (*models.User, error)); ok {
|
||||||
|
return rf(ctx, id)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, uint64) *models.User); ok {
|
||||||
|
r0 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*models.User)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok {
|
||||||
|
r1 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockDatabase_GetUserByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserByID'
|
||||||
|
type MockDatabase_GetUserByID_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - id uint64
|
||||||
|
func (_e *MockDatabase_Expecter) GetUserByID(ctx interface{}, id interface{}) *MockDatabase_GetUserByID_Call {
|
||||||
|
return &MockDatabase_GetUserByID_Call{Call: _e.mock.On("GetUserByID", ctx, id)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetUserByID_Call) Run(run func(ctx context.Context, id uint64)) *MockDatabase_GetUserByID_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(uint64))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetUserByID_Call) Return(_a0 *models.User, _a1 error) *MockDatabase_GetUserByID_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetUserByID_Call) RunAndReturn(run func(context.Context, uint64) (*models.User, error)) *MockDatabase_GetUserByID_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByLogin provides a mock function with given fields: ctx, login
|
||||||
|
func (_m *MockDatabase) GetUserByLogin(ctx context.Context, login string) (*models.User, error) {
|
||||||
|
ret := _m.Called(ctx, login)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for GetUserByLogin")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *models.User
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) (*models.User, error)); ok {
|
||||||
|
return rf(ctx, login)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) *models.User); ok {
|
||||||
|
r0 = rf(ctx, login)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*models.User)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||||
|
r1 = rf(ctx, login)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockDatabase_GetUserByLogin_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserByLogin'
|
||||||
|
type MockDatabase_GetUserByLogin_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByLogin is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - login string
|
||||||
|
func (_e *MockDatabase_Expecter) GetUserByLogin(ctx interface{}, login interface{}) *MockDatabase_GetUserByLogin_Call {
|
||||||
|
return &MockDatabase_GetUserByLogin_Call{Call: _e.mock.On("GetUserByLogin", ctx, login)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetUserByLogin_Call) Run(run func(ctx context.Context, login string)) *MockDatabase_GetUserByLogin_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetUserByLogin_Call) Return(_a0 *models.User, _a1 error) *MockDatabase_GetUserByLogin_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_GetUserByLogin_Call) RunAndReturn(run func(context.Context, string) (*models.User, error)) *MockDatabase_GetUserByLogin_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSession provides a mock function with given fields: ctx, id
|
||||||
|
func (_m *MockDatabase) RemoveSession(ctx context.Context, id int64) error {
|
||||||
|
ret := _m.Called(ctx, id)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for RemoveSession")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
|
||||||
|
r0 = rf(ctx, id)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockDatabase_RemoveSession_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveSession'
|
||||||
|
type MockDatabase_RemoveSession_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSession is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - id int64
|
||||||
|
func (_e *MockDatabase_Expecter) RemoveSession(ctx interface{}, id interface{}) *MockDatabase_RemoveSession_Call {
|
||||||
|
return &MockDatabase_RemoveSession_Call{Call: _e.mock.On("RemoveSession", ctx, id)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_RemoveSession_Call) Run(run func(ctx context.Context, id int64)) *MockDatabase_RemoveSession_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(int64))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_RemoveSession_Call) Return(_a0 error) *MockDatabase_RemoveSession_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockDatabase_RemoveSession_Call) RunAndReturn(run func(context.Context, int64) error) *MockDatabase_RemoveSession_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockDatabase creates a new instance of MockDatabase. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockDatabase(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockDatabase {
|
||||||
|
mock := &MockDatabase{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
// Code generated by mockery v2.48.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
// MockFileStorage is an autogenerated mock type for the FileStorage type
|
||||||
|
type MockFileStorage struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockFileStorage_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockFileStorage) EXPECT() *MockFileStorage_Expecter {
|
||||||
|
return &MockFileStorage_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockFileStorage creates a new instance of MockFileStorage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockFileStorage(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockFileStorage {
|
||||||
|
mock := &MockFileStorage{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
// Code generated by mockery v2.48.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockMetaStorage is an autogenerated mock type for the MetaStorage type
|
||||||
|
type MockMetaStorage struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockMetaStorage_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockMetaStorage) EXPECT() *MockMetaStorage_Expecter {
|
||||||
|
return &MockMetaStorage_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveMetadata provides a mock function with given fields: ctx, fileType, size, ext
|
||||||
|
func (_m *MockMetaStorage) SaveMetadata(ctx context.Context, fileType string, size int64, ext string) (int64, error) {
|
||||||
|
ret := _m.Called(ctx, fileType, size, ext)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for SaveMetadata")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, int64, string) (int64, error)); ok {
|
||||||
|
return rf(ctx, fileType, size, ext)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, int64, string) int64); ok {
|
||||||
|
r0 = rf(ctx, fileType, size, ext)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, int64, string) error); ok {
|
||||||
|
r1 = rf(ctx, fileType, size, ext)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockMetaStorage_SaveMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveMetadata'
|
||||||
|
type MockMetaStorage_SaveMetadata_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveMetadata is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - fileType string
|
||||||
|
// - size int64
|
||||||
|
// - ext string
|
||||||
|
func (_e *MockMetaStorage_Expecter) SaveMetadata(ctx interface{}, fileType interface{}, size interface{}, ext interface{}) *MockMetaStorage_SaveMetadata_Call {
|
||||||
|
return &MockMetaStorage_SaveMetadata_Call{Call: _e.mock.On("SaveMetadata", ctx, fileType, size, ext)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockMetaStorage_SaveMetadata_Call) Run(run func(ctx context.Context, fileType string, size int64, ext string)) *MockMetaStorage_SaveMetadata_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string), args[2].(int64), args[3].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockMetaStorage_SaveMetadata_Call) Return(_a0 int64, _a1 error) *MockMetaStorage_SaveMetadata_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockMetaStorage_SaveMetadata_Call) RunAndReturn(run func(context.Context, string, int64, string) (int64, error)) *MockMetaStorage_SaveMetadata_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockMetaStorage creates a new instance of MockMetaStorage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockMetaStorage(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockMetaStorage {
|
||||||
|
mock := &MockMetaStorage{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user