Files
soroush.asadi 90ac0b81d1 feat: V2 microservices stack — backend services, gateway, JWT auth
Add full V2 architecture: identity, content, studio (.NET 10) and file,
render, notification, gateway (Go) services with vendored deps, plus DB
migrations, event/API contracts, and an init-db script.

Wire the Next.js frontend to the gateway: server-side JWT auth routes
(login/register/refresh/logout/me), gateway fetch helper, and session/
cookie/jwt helpers under src/lib.

Containerize the stack via docker-compose.v2.yml and per-service
Dockerfiles. Base images resolve through a Nexus mirror (Docker Hub) and
MCR directly; npm/NuGet pull from Nexus groups. Self-host fonts via
next/font/local to avoid Google Fonts (geo-blocked).

Add CI workflow and ignore .env.v2, *.stackdump, and .NET bin/obj.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 23:29:31 +03:30

76 lines
2.0 KiB
Go

package storage
import (
"context"
"fmt"
"io"
"net/url"
"time"
"github.com/google/uuid"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)
type MinioClient struct {
client *minio.Client
endpoint string
}
type Config struct {
Endpoint string
AccessKeyID string
SecretAccessKey string
UseSSL bool
}
func NewMinioClient(cfg Config) (*MinioClient, error) {
client, err := minio.New(cfg.Endpoint, &minio.Options{
Creds: credentials.NewStaticV4(cfg.AccessKeyID, cfg.SecretAccessKey, ""),
Secure: cfg.UseSSL,
})
if err != nil {
return nil, fmt.Errorf("minio client: %w", err)
}
return &MinioClient{client: client, endpoint: cfg.Endpoint}, nil
}
func (m *MinioClient) PresignedPutURL(ctx context.Context, bucket, key string, expiry time.Duration) (string, error) {
u, err := m.client.PresignedPutObject(ctx, bucket, key, expiry)
if err != nil {
return "", err
}
return u.String(), nil
}
func (m *MinioClient) PresignedGetURL(ctx context.Context, bucket, key string, expiry time.Duration) (string, error) {
reqParams := url.Values{}
u, err := m.client.PresignedGetObject(ctx, bucket, key, expiry, reqParams)
if err != nil {
return "", err
}
return u.String(), nil
}
func (m *MinioClient) GenerateKey(folder string) string {
return fmt.Sprintf("%s/%s", folder, uuid.New().String())
}
func (m *MinioClient) DeleteObject(ctx context.Context, bucket, key string) error {
return m.client.RemoveObject(ctx, bucket, key, minio.RemoveObjectOptions{})
}
func (m *MinioClient) GetObject(ctx context.Context, bucket, key string) (io.ReadCloser, error) {
obj, err := m.client.GetObject(ctx, bucket, key, minio.GetObjectOptions{})
if err != nil {
return nil, err
}
return obj, nil
}
func (m *MinioClient) InitiateMultipartUpload(ctx context.Context, bucket, key string) (string, error) {
// MinIO SDK doesn't directly expose multipart — use presigned PUT per chunk instead.
// Return a generated upload ID for session tracking.
return uuid.New().String(), nil
}