This commit is contained in:
r8zavetr8v 2024-12-15 11:56:03 -05:00
parent f74a4779aa
commit 5bdb7fb0b0
10 changed files with 57 additions and 48 deletions

View File

@ -21,6 +21,7 @@ func main() {
pg := postgres.New(ctx, "postgres://draincloud:draincloud@localhost:5432/draincloud?sslmode=disable") pg := postgres.New(ctx, "postgres://draincloud:draincloud@localhost:5432/draincloud?sslmode=disable")
// TODO move cron on a separate job (k8s cronjob / docker cron)
cleanupSessionsCron := cleanupsessions.New(pg) cleanupSessionsCron := cleanupsessions.New(pg)
cleanupSessionsCron.Run(ctx) cleanupSessionsCron.Run(ctx)

3
go.mod
View File

@ -7,8 +7,10 @@ require (
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/google/uuid v1.4.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/nats-io/nats.go v1.37.0
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.28.0 golang.org/x/crypto v0.28.0
@ -38,7 +40,6 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
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/nats-io/nats.go v1.37.0 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect github.com/nats-io/nuid v1.0.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect

2
go.sum
View File

@ -39,6 +39,8 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=

View File

@ -32,7 +32,7 @@ func New(
authGroup := mux.Group("/auth") authGroup := mux.Group("/auth")
{ {
authGroup.POST("/register", d.Register) authGroup.POST("/register", d.Register)
authGroup.POST("/login", d.Login) authGroup.POST("/logon", d.Login)
} }
filesGroup := mux.Group("/files") filesGroup := mux.Group("/files")

View File

@ -6,6 +6,7 @@ import (
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage" "git.optclblast.xyz/draincloud/draincloud-core/internal/storage"
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/files" "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/files"
"github.com/google/uuid"
) )
type FilesEngine struct { type FilesEngine struct {
@ -25,7 +26,7 @@ func NewFilesEngine(
type File struct { type File struct {
Name string Name string
UserID int64 UserID uuid.UUID
Ext string Ext string
Type string Type string
Size int64 Size int64
@ -36,14 +37,14 @@ type File struct {
func (e *FilesEngine) SaveFile( func (e *FilesEngine) SaveFile(
ctx context.Context, ctx context.Context,
file File, file File,
) (int64, error) { ) (uuid.UUID, error) {
fileID, err := e.metaStorage.SaveMetadata(ctx, files.FileMetadata{}) fileID, err := e.metaStorage.SaveMetadata(ctx, files.FileMetadata{})
if err != nil { if err != nil {
return -1, fmt.Errorf("failed to create new file metadata: %w", err) return uuid.Nil, fmt.Errorf("failed to create new file metadata: %w", err)
} }
if err = e.blobStorage.SaveBlob(ctx, fileID, file.Data); err != nil { if err = e.blobStorage.SaveBlob(ctx, fileID, file.Data); err != nil {
return -1, fmt.Errorf("failed to save file data: %w", err) return uuid.Nil, fmt.Errorf("failed to save file data: %w", err)
} }
return fileID, nil return fileID, nil

View File

@ -7,6 +7,7 @@ import (
"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" auditmodels "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/audit"
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/files" "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models/files"
"github.com/google/uuid"
) )
type Database interface { type Database interface {
@ -14,13 +15,13 @@ type Database interface {
} }
type AuthStorage interface { type AuthStorage interface {
AddUser(ctx context.Context, login string, username string, passwordHash []byte) (int64, error) AddUser(ctx context.Context, login string, username string, passwordHash []byte) (uuid.UUID, 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 uuid.UUID) (*models.User, error)
AddSession(ctx context.Context, ses *models.Session) (int64, error) AddSession(ctx context.Context, ses *models.Session) (uuid.UUID, error)
GetSession(ctx context.Context, sessionToken string) (*models.Session, error) GetSession(ctx context.Context, sessionToken string) (*models.Session, error)
RemoveSession(ctx context.Context, id int64) error RemoveSession(ctx context.Context, id uuid.UUID) error
} }
type AuthAuditLogStorage interface { type AuthAuditLogStorage interface {
@ -28,11 +29,11 @@ type AuthAuditLogStorage interface {
} }
type MetaStorage interface { type MetaStorage interface {
SaveMetadata(ctx context.Context, meta files.FileMetadata) (int64, error) SaveMetadata(ctx context.Context, meta files.FileMetadata) (uuid.UUID, error)
} }
type BlobStorage interface { type BlobStorage interface {
GetFile(ctx context.Context, id int64) (*os.File, error) GetFile(ctx context.Context, id uuid.UUID) (*os.File, error)
SaveBlob(ctx context.Context, id int64, data []byte) error SaveBlob(ctx context.Context, id uuid.UUID, data []byte) error
DeleteFile(ctx context.Context, id int64) error DeleteFile(ctx context.Context, id uuid.UUID) error
} }

View File

@ -1,18 +1,22 @@
package models package models
import "time" import (
"time"
"github.com/google/uuid"
)
type Session struct { type Session struct {
ID int64 ID uuid.UUID
SessionToken string SessionToken string
CsrfToken string CsrfToken string
UserID int64 UserID uuid.UUID
CreatedAt time.Time CreatedAt time.Time
ExpiredAt time.Time ExpiredAt time.Time
} }
type User struct { type User struct {
ID int64 ID uuid.UUID
Username string Username string
Login string Login string
PasswordHash []byte PasswordHash []byte

View File

@ -1,7 +1,9 @@
package files package files
import "github.com/google/uuid"
type FileMetadata struct { type FileMetadata struct {
Id int64 Id uuid.UUID
Name string Name string
UserID int64 UserID int64
Ext string Ext string

View File

@ -10,6 +10,7 @@ import (
"git.optclblast.xyz/draincloud/draincloud-core/internal/closer" "git.optclblast.xyz/draincloud/draincloud-core/internal/closer"
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger" "git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
"git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models" "git.optclblast.xyz/draincloud/draincloud-core/internal/storage/models"
"github.com/google/uuid"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgconn"
) )
@ -39,11 +40,11 @@ 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) (int64, error) { func (d *Database) AddUser(ctx context.Context, login string, username string, passwordHash []byte) (uuid.UUID, error) {
return addUser(ctx, d.db, login, username, passwordHash) return addUser(ctx, d.db, login, username, passwordHash)
} }
func (d *Database) GetUserByID(ctx context.Context, id uint64) (*models.User, error) { func (d *Database) GetUserByID(ctx context.Context, id uuid.UUID) (*models.User, error) {
return getUserByID(ctx, d.db, id) return getUserByID(ctx, d.db, id)
} }
@ -51,7 +52,7 @@ 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) (int64, error) { func (d *Database) AddSession(ctx context.Context, ses *models.Session) (uuid.UUID, error) {
return addSession(ctx, d.db, ses) return addSession(ctx, d.db, ses)
} }
@ -64,9 +65,9 @@ func (d *Database) GetSession(ctx context.Context, sessionToken string) (*models
row := d.db.QueryRow(ctx, stmt, sessionToken) row := d.db.QueryRow(ctx, stmt, sessionToken)
var ( var (
id int64 id uuid.UUID
sesToken, csrfToken string sesToken, csrfToken string
userID int64 userID uuid.UUID
createdAt sql.NullTime createdAt sql.NullTime
expiredAt sql.NullTime expiredAt sql.NullTime
) )
@ -85,7 +86,7 @@ func (d *Database) GetSession(ctx context.Context, sessionToken string) (*models
}, nil }, nil
} }
func (d *Database) RemoveSession(ctx context.Context, id int64) error { func (d *Database) RemoveSession(ctx context.Context, id uuid.UUID) error {
const stmt = `DELETE FROM sessions WHERE id = $1;` const stmt = `DELETE FROM sessions WHERE id = $1;`
_, err := d.db.Exec(ctx, stmt, id) _, err := d.db.Exec(ctx, stmt, id)
return err return err
@ -98,20 +99,20 @@ func (d *Database) RemoveExpiredSessions(ctx context.Context) error {
return err return err
} }
func addUser(ctx context.Context, conn dbtx, login string, username string, passwordHash []byte) (int64, error) { func addUser(ctx context.Context, conn dbtx, login string, username string, passwordHash []byte) (uuid.UUID, 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 uuid.UUID
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 uuid.Nil, fmt.Errorf("failed to insert user data into users table: %w", err)
} }
return id, nil return id, nil
} }
func getUserByID(ctx context.Context, conn dbtx, id uint64) (*models.User, error) { func getUserByID(ctx context.Context, conn dbtx, id uuid.UUID) (*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)
@ -133,13 +134,13 @@ 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) (int64, error) { func addSession(ctx context.Context, conn dbtx, session *models.Session) (uuid.UUID, 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 int64 var id uuid.UUID
row := conn.QueryRow(ctx, stmt, session.SessionToken, session.CsrfToken, session.UserID, 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 uuid.Nil, fmt.Errorf("failed to insert new session: %w", err)
} }
return id, nil return id, nil

View File

@ -4,7 +4,7 @@ SELECT 'up SQL query';
-- Users as auth data -- Users as auth data
create table if not exists users ( create table if not exists users (
id bigserial primary key, id uuid primary key,
username text default null, username text default null,
login text not null unique, login text not null unique,
password bytea not null, password bytea not null,
@ -18,10 +18,10 @@ create index idx_users_username on users (username);
-- Sessions and auth data -- Sessions and auth data
create table sessions ( create table sessions (
id bigserial primary key, id uuid primary key,
session_token varchar(200) not null unique, session_token varchar(200) not null unique,
csrf_token varchar(200) not null unique, csrf_token varchar(200) not null unique,
user_id bigserial references users(id), user_id uuid references users(id),
created_at timestamp default current_timestamp, created_at timestamp default current_timestamp,
expired_at timestamp not null expired_at timestamp not null
); );
@ -30,13 +30,13 @@ create index if not exists idx_sessions_session_token_csrf_token on sessions (se
-- Files -- Files
create table files_metadata ( create table files_metadata (
id bigserial primary key, id uuid primary key,
name text not null, name text not null,
fslink text not null, fslink text not null,
size bigint not null, size bigint not null,
ext text not null, ext text not null,
owner_id bigint not null, owner_id uuid not null,
parent_dir bigint not null, parent_dir uuid not null,
created_at timestamptz default current_timestamp, created_at timestamptz default current_timestamp,
updated_at timestamptz default null, updated_at timestamptz default null,
deleted_at timestamptz default null deleted_at timestamptz default null
@ -46,10 +46,10 @@ create index idx_fm_owner_id on files_metadata(owner_id);
create index idx_fm_owner_id_parent_dir on files_metadata(owner_id, parent_dir); create index idx_fm_owner_id_parent_dir on files_metadata(owner_id, parent_dir);
create table directories ( create table directories (
id bigserial primary key, id uuid primary key,
name text not null, name text not null,
owner_id bigint not null, owner_id uuid not null,
parent_dir bigint not null, parent_dir uuid not null,
created_at timestamptz default current_timestamp, created_at timestamptz default current_timestamp,
updated_at timestamptz default null, updated_at timestamptz default null,
deleted_at timestamptz default null deleted_at timestamptz default null
@ -58,9 +58,9 @@ create table directories (
create index idx_directories_owner_id_parent_dir on directories(owner_id, parent_dir); create index idx_directories_owner_id_parent_dir on directories(owner_id, parent_dir);
create table directory_users_access ( create table directory_users_access (
id bigserial primary key, id uuid primary key,
dir_id bigint not null, dir_id uuid not null,
user_id bigint not null, user_id uuid not null,
assess_flag integer, assess_flag integer,
created_at timestamptz default current_timestamp, created_at timestamptz default current_timestamp,
updated_at timestamptz default null updated_at timestamptz default null
@ -68,8 +68,4 @@ create table directory_users_access (
create index idx_dua_owner_id_parent_dir on directories(owner_id, parent_dir); create index idx_dua_owner_id_parent_dir on directories(owner_id, parent_dir);
-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query';
-- +goose StatementEnd