add file storage: metadata schema, minio upload/download, content-type extension mapping
- add files_metadata and files_metadata_connections tables with CRUD helpers - add FileMetadata type and Sha256Hash typedef; replace Media struct - add minio upload, presigned download URL, and key generation - fix bucket existence check to use FileStorageBucketName instead of hardcoded "main" - fix files_metadata_connections table name and trailing comma in DDL - fix column name original -> name in files_metadata schema - add canonical MIME-to-extension map with .unk fallback - add FileDownloadLinkTtl constant (24h)
This commit is contained in:
@@ -67,6 +67,28 @@ func PgInit(ctx context.Context) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = dbConn.Exec(ctx, `
|
||||
CREATE TABLE IF NOT EXISTS files_metadata (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
uploader_id UUID NOT NULL REFERENCES users(id),
|
||||
name TEXT,
|
||||
hash TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = dbConn.Exec(ctx, `
|
||||
CREATE TABLE IF NOT EXISTS files_metadata_connections (
|
||||
file_metadata_id UUID NOT NULL REFERENCES files_metadata(id) ON DELETE CASCADE,
|
||||
connection_id UUID NOT NULL REFERENCES user_connections(id) ON DELETE CASCADE
|
||||
)
|
||||
`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func PgUserSave(ctx context.Context, user *types.User) error {
|
||||
@@ -221,3 +243,57 @@ func PgConnectionGetMessagesBefore(ctx context.Context, before time.Time, connec
|
||||
}
|
||||
return messages, rows.Err()
|
||||
}
|
||||
|
||||
func PgFileMetadataSave(ctx context.Context, metadata *types.FileMetadata) error {
|
||||
_, err := dbConn.Exec(ctx, `
|
||||
INSERT INTO files_metadata (id, uploader_id, name, hash, created_at) VALUES ($1, $2, $3, $4, $5)
|
||||
`, metadata.Id, metadata.UploaderId, metadata.Name, metadata.Hash, metadata.CreatedAt)
|
||||
return err
|
||||
}
|
||||
|
||||
func PgFileMetadataGet(ctx context.Context, metadata *types.FileMetadata) error {
|
||||
return dbConn.QueryRow(ctx, `
|
||||
SELECT uploader_id, name, hash, created_at FROM files_metadata WHERE id = $1
|
||||
`, metadata.Id).Scan(&metadata.UploaderId, &metadata.Name, &metadata.Hash, &metadata.CreatedAt)
|
||||
}
|
||||
|
||||
func PgFileMetadataDelete(ctx context.Context, metadataId *uuid.UUID) error {
|
||||
_, err := dbConn.Exec(ctx, `
|
||||
DELETE FROM files_metadata WHERE id = $1
|
||||
`, metadataId)
|
||||
return err
|
||||
}
|
||||
|
||||
func PgFileConnectionsAdd(ctx context.Context, metadataId *uuid.UUID, connectionId *uuid.UUID) error {
|
||||
_, err := dbConn.Exec(ctx, `
|
||||
INSERT INTO files_metadata_connections (file_metadata_id, connection_id) VALUES ($1, $2)
|
||||
`, metadataId, connectionId)
|
||||
return err
|
||||
}
|
||||
|
||||
func PgFileConnectionsGet(ctx context.Context, metadata *types.FileMetadata) error {
|
||||
rows, err := dbConn.Query(ctx, `
|
||||
SELECT connection_id FROM files_metadata_connections WHERE file_metadata_id = $1
|
||||
`, metadata.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
connectionId := uuid.UUID{}
|
||||
if err = rows.Scan(&connectionId); err != nil {
|
||||
return err
|
||||
}
|
||||
metadata.Connections = append(metadata.Connections, connectionId)
|
||||
}
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func PgFileMetadataHashExists(ctx context.Context, hash *types.Sha256Hash) (bool, error) {
|
||||
var exists bool
|
||||
err := dbConn.QueryRow(ctx, `
|
||||
SELECT EXISTS (SELECT FROM files_metadata WHERE hash = $1)
|
||||
`, hash).Scan(&exists)
|
||||
return exists, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user