ajout app

This commit is contained in:
2024-04-17 20:22:30 +02:00
parent cc017cfc5e
commit f9d05a2fd3
8025 changed files with 729805 additions and 0 deletions

View File

@ -0,0 +1,22 @@
package infra
import (
"voltaserve/config"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var db *gorm.DB
func GetDb() *gorm.DB {
if db != nil {
return db
}
var err error
db, err = gorm.Open(postgres.Open(config.GetConfig().DatabaseURL), &gorm.Config{})
if err != nil {
panic(err)
}
return db
}

View File

@ -0,0 +1,123 @@
package infra
import "strings"
type FileIdentifier struct {
}
func NewFileIdentifier() *FileIdentifier {
return &FileIdentifier{}
}
func (fi *FileIdentifier) IsPDF(extension string) bool {
return strings.ToLower(extension) == ".pdf"
}
func (fi *FileIdentifier) IsOffice(extension string) bool {
extensions := []string{
".xls",
".doc",
".ppt",
".xlsx",
".docx",
".pptx",
".odt",
".ott",
".ods",
".ots",
".odp",
".otp",
".odg",
".otg",
".odf",
".odc",
".rtf",
}
for _, v := range extensions {
if strings.ToLower(extension) == v {
return true
}
}
return false
}
func (fi *FileIdentifier) IsPlainText(extension string) bool {
extensions := []string{
".txt",
".html",
".js",
"jsx",
".ts",
".tsx",
".css",
".sass",
".scss",
".go",
".py",
".rb",
".java",
".c",
".h",
".cpp",
".hpp",
".json",
".yml",
".yaml",
".toml",
".md",
}
for _, v := range extensions {
if strings.ToLower(extension) == v {
return true
}
}
return false
}
func (fi *FileIdentifier) IsImage(extension string) bool {
extensions := []string{
".xpm",
".png",
".jpg",
".jpeg",
".jp2",
".gif",
".webp",
".tiff",
".bmp",
".ico",
".heif",
".xcf",
".svg",
}
for _, v := range extensions {
if strings.ToLower(extension) == v {
return true
}
}
return false
}
func (fi *FileIdentifier) IsVideo(extension string) bool {
extensions := []string{
".ogv",
".mpeg",
".mov",
".mqv",
".mp4",
".webm",
".3gp",
".3g2",
".avi",
".flv",
".mkv",
".asf",
".m4v",
}
for _, v := range extensions {
if strings.ToLower(extension) == v {
return true
}
}
return false
}

View File

@ -0,0 +1,99 @@
package infra
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"voltaserve/config"
"github.com/gofiber/fiber/v2/log"
"gopkg.in/gomail.v2"
"sigs.k8s.io/yaml"
"text/template"
)
type MessageParams struct {
Subject string
}
type MailTemplate struct {
dialer *gomail.Dialer
config config.SMTPConfig
}
func NewMailTemplate() *MailTemplate {
mt := new(MailTemplate)
mt.config = config.GetConfig().SMTP
mt.dialer = gomail.NewDialer(mt.config.Host, mt.config.Port, mt.config.Username, mt.config.Password)
return mt
}
func (mt *MailTemplate) Send(templateName string, address string, variables map[string]string) error {
html, err := mt.GetText(filepath.FromSlash("templates/"+templateName+"/template.html"), variables)
if err != nil {
return err
}
text, err := mt.GetText(filepath.FromSlash("templates/"+templateName+"/template.txt"), variables)
if err != nil {
return err
}
params, err := mt.GetMessageParams(templateName)
if err != nil {
return err
}
m := gomail.NewMessage()
m.SetHeader("From", fmt.Sprintf(`"%s" <%s>`, mt.config.SenderName, mt.config.SenderAddress))
m.SetHeader("To", address)
m.SetHeader("Subject", params.Subject)
m.SetBody("text/plain ", text)
m.AddAlternative("text/html", html)
if err := mt.dialer.DialAndSend(m); err != nil {
return err
}
return nil
}
func (mt *MailTemplate) GetText(path string, variables map[string]string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", err
}
defer func(f *os.File) {
if err := f.Close(); err != nil {
log.Error(err)
}
}(f)
b, _ := io.ReadAll(f)
html := string(b)
tmpl, err := template.New("").Parse(html)
if err != nil {
return "", nil
}
var buf bytes.Buffer
err = tmpl.Execute(&buf, variables)
if err != nil {
return "", nil
}
return buf.String(), nil
}
func (mt *MailTemplate) GetMessageParams(templateName string) (*MessageParams, error) {
f, err := os.Open(filepath.FromSlash("templates/" + templateName + "/params.yml"))
if err != nil {
return nil, err
}
defer func(f *os.File) {
if err := f.Close(); err != nil {
log.Error(err)
}
}(f)
b, _ := io.ReadAll(f)
res := &MessageParams{}
if err := yaml.Unmarshal(b, res); err != nil {
return nil, err
}
return res, nil
}

View File

@ -0,0 +1,15 @@
package infra
import "github.com/gabriel-vasile/mimetype"
func DetectMimeFromFile(path string) string {
mime, err := mimetype.DetectFile(path)
if err != nil {
return "application/octet-stream"
}
return mime.String()
}
func DetectMimeFromBytes(b []byte) string {
return mimetype.Detect(b).String()
}

View File

@ -0,0 +1,113 @@
package infra
import (
"context"
"strings"
"voltaserve/config"
"github.com/redis/go-redis/v9"
)
type RedisManager struct {
config config.RedisConfig
client *redis.Client
clusterClient *redis.ClusterClient
}
func NewRedisManager() *RedisManager {
mgr := new(RedisManager)
mgr.config = config.GetConfig().Redis
return mgr
}
func (mgr *RedisManager) Set(key string, value interface{}) error {
if mgr.client == nil && mgr.clusterClient == nil {
if err := mgr.connect(); err != nil {
return err
}
}
if mgr.clusterClient != nil {
if _, err := mgr.clusterClient.Set(context.Background(), key, value, 0).Result(); err != nil {
return err
}
} else {
if _, err := mgr.client.Set(context.Background(), key, value, 0).Result(); err != nil {
return err
}
}
return nil
}
func (mgr *RedisManager) Get(key string) (string, error) {
if mgr.client == nil && mgr.clusterClient == nil {
if err := mgr.connect(); err != nil {
return "", err
}
}
if mgr.clusterClient != nil {
value, err := mgr.clusterClient.Get(context.Background(), key).Result()
if err != nil {
return "", err
}
return value, nil
} else {
value, err := mgr.client.Get(context.Background(), key).Result()
if err != nil {
return "", err
}
return value, nil
}
}
func (mgr *RedisManager) Delete(key string) error {
if mgr.client == nil && mgr.clusterClient == nil {
if err := mgr.connect(); err != nil {
return err
}
}
if mgr.clusterClient != nil {
if _, err := mgr.clusterClient.Del(context.Background(), key).Result(); err != nil {
return err
}
} else {
if _, err := mgr.client.Del(context.Background(), key).Result(); err != nil {
return err
}
}
return nil
}
func (mgr *RedisManager) Close() error {
if mgr.client != nil {
if err := mgr.client.Close(); err != nil {
return err
}
}
return nil
}
func (mgr *RedisManager) connect() error {
if mgr.client != nil || mgr.clusterClient != nil {
return nil
}
addresses := strings.Split(mgr.config.Address, ";")
if len(addresses) > 1 {
mgr.clusterClient = redis.NewClusterClient(&redis.ClusterOptions{
Addrs: addresses,
Password: mgr.config.Password,
})
if err := mgr.clusterClient.Ping(context.Background()).Err(); err != nil {
return err
}
} else {
mgr.client = redis.NewClient(&redis.Options{
Addr: mgr.config.Address,
Password: mgr.config.Password,
DB: mgr.config.DB,
})
if err := mgr.client.Ping(context.Background()).Err(); err != nil {
return err
}
}
return nil
}

205
Voltaserve/api/infra/s3.go Normal file
View File

@ -0,0 +1,205 @@
package infra
import (
"bytes"
"context"
"io"
"strings"
"voltaserve/config"
"voltaserve/errorpkg"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7/pkg/sse"
)
type S3Manager struct {
config config.S3Config
client *minio.Client
}
func NewS3Manager() *S3Manager {
mgr := new(S3Manager)
mgr.config = config.GetConfig().S3
return mgr
}
func (mgr *S3Manager) GetFile(objectName string, filePath string, bucketName string) error {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
if err := mgr.client.FGetObject(context.Background(), bucketName, objectName, filePath, minio.GetObjectOptions{}); err != nil {
return err
}
return nil
}
func (mgr *S3Manager) PutFile(objectName string, filePath string, contentType string, bucketName string) error {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
if contentType == "" {
contentType = "application/octet-stream"
}
if _, err := mgr.client.FPutObject(context.Background(), bucketName, objectName, filePath, minio.PutObjectOptions{
ContentType: contentType,
}); err != nil {
return err
}
return nil
}
func (mgr *S3Manager) PutText(objectName string, text string, contentType string, bucketName string) error {
if contentType != "" && contentType != "text/plain" && contentType != "application/json" {
return errorpkg.NewS3Error("Invalid content type '" + contentType + "'")
}
if contentType == "" {
contentType = "text/plain"
}
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
if _, err := mgr.client.PutObject(context.Background(), bucketName, objectName, strings.NewReader(text), int64(len(text)), minio.PutObjectOptions{
ContentType: contentType,
}); err != nil {
return err
}
return nil
}
func (mgr *S3Manager) GetObject(objectName string, bucketName string) (*bytes.Buffer, error) {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return nil, err
}
}
reader, err := mgr.client.GetObject(context.Background(), bucketName, objectName, minio.GetObjectOptions{})
if err != nil {
return nil, err
}
var buf bytes.Buffer
_, err = io.Copy(io.Writer(&buf), reader)
if err != nil {
return nil, nil
}
return &buf, nil
}
func (mgr *S3Manager) GetText(objectName string, bucketName string) (string, error) {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return "", err
}
}
reader, err := mgr.client.GetObject(context.Background(), bucketName, objectName, minio.GetObjectOptions{})
if err != nil {
return "", err
}
buf := new(strings.Builder)
_, err = io.Copy(buf, reader)
if err != nil {
return "", nil
}
return buf.String(), nil
}
func (mgr *S3Manager) RemoveObject(objectName string, bucketName string) error {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
err := mgr.client.RemoveObject(context.Background(), bucketName, objectName, minio.RemoveObjectOptions{})
if err != nil {
return err
}
return nil
}
func (mgr *S3Manager) CreateBucket(bucketName string) error {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
found, err := mgr.client.BucketExists(context.Background(), bucketName)
if err != nil {
return err
}
if !found {
if err = mgr.client.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{
Region: mgr.config.Region,
}); err != nil {
return err
}
}
return nil
}
func (mgr *S3Manager) RemoveBucket(bucketName string) error {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
found, err := mgr.client.BucketExists(context.Background(), bucketName)
if err != nil {
return err
}
if !found {
return nil
}
objectCh := mgr.client.ListObjects(context.Background(), bucketName, minio.ListObjectsOptions{
Prefix: "",
Recursive: true,
})
mgr.client.RemoveObjects(context.Background(), bucketName, objectCh, minio.RemoveObjectsOptions{})
if err = mgr.client.RemoveBucket(context.Background(), bucketName); err != nil {
return err
}
return nil
}
func (mgr *S3Manager) EnableBucketEncryption(bucketName string) error {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
err := mgr.client.SetBucketEncryption(context.Background(), bucketName, sse.NewConfigurationSSES3())
if err != nil {
return err
}
return nil
}
func (mgr *S3Manager) DisableBucketEncryption(bucketName string) error {
if mgr.client == nil {
if err := mgr.connect(); err != nil {
return err
}
}
err := mgr.client.RemoveBucketEncryption(context.Background(), bucketName)
if err != nil {
return err
}
return nil
}
func (mgr *S3Manager) connect() error {
client, err := minio.New(mgr.config.URL, &minio.Options{
Creds: credentials.NewStaticV4(mgr.config.AccessKey, mgr.config.SecretKey, ""),
Secure: mgr.config.Secure,
})
if err != nil {
return err
}
mgr.client = client
return nil
}

View File

@ -0,0 +1,123 @@
package infra
import (
"voltaserve/config"
"github.com/meilisearch/meilisearch-go"
)
var searchClient *meilisearch.Client
const (
FileSearchIndex = "file"
GroupSearchIndex = "group"
WorkspaceSearchIndex = "workspace"
OrganizationSearchIndex = "organization"
UserSearchIndex = "user"
)
type SearchModel interface {
GetID() string
}
type SearchManager struct {
config config.SearchConfig
}
func NewSearchManager() *SearchManager {
if searchClient == nil {
searchClient = meilisearch.NewClient(meilisearch.ClientConfig{
Host: config.GetConfig().Search.URL,
})
if _, err := searchClient.CreateIndex(&meilisearch.IndexConfig{
Uid: FileSearchIndex,
PrimaryKey: "id",
}); err != nil {
panic(err)
}
if _, err := searchClient.Index(FileSearchIndex).UpdateSettings(&meilisearch.Settings{
SearchableAttributes: []string{"name", "text"},
}); err != nil {
panic(err)
}
if _, err := searchClient.CreateIndex(&meilisearch.IndexConfig{
Uid: GroupSearchIndex,
PrimaryKey: "id",
}); err != nil {
panic(err)
}
if _, err := searchClient.Index(GroupSearchIndex).UpdateSettings(&meilisearch.Settings{
SearchableAttributes: []string{"name"},
}); err != nil {
panic(err)
}
if _, err := searchClient.CreateIndex(&meilisearch.IndexConfig{
Uid: WorkspaceSearchIndex,
PrimaryKey: "id",
}); err != nil {
panic(err)
}
if _, err := searchClient.Index(WorkspaceSearchIndex).UpdateSettings(&meilisearch.Settings{
SearchableAttributes: []string{"name"},
}); err != nil {
panic(err)
}
if _, err := searchClient.CreateIndex(&meilisearch.IndexConfig{
Uid: OrganizationSearchIndex,
PrimaryKey: "id",
}); err != nil {
panic(err)
}
if _, err := searchClient.Index(OrganizationSearchIndex).UpdateSettings(&meilisearch.Settings{
SearchableAttributes: []string{"name"},
}); err != nil {
panic(err)
}
if _, err := searchClient.CreateIndex(&meilisearch.IndexConfig{
Uid: UserSearchIndex,
PrimaryKey: "id",
}); err != nil {
panic(err)
}
if _, err := searchClient.Index(UserSearchIndex).UpdateSettings(&meilisearch.Settings{
SearchableAttributes: []string{"fullName", "email"},
}); err != nil {
panic(err)
}
}
return &SearchManager{
config: config.GetConfig().Search,
}
}
func (mgr *SearchManager) Query(index string, query string) ([]interface{}, error) {
res, err := searchClient.Index(index).Search(query, &meilisearch.SearchRequest{})
if err != nil {
return nil, err
}
return res.Hits, nil
}
func (mgr *SearchManager) Index(index string, models []SearchModel) error {
_, err := searchClient.Index(index).AddDocuments(models)
if err != nil {
return err
}
return nil
}
func (mgr *SearchManager) Update(index string, m []SearchModel) error {
_, err := searchClient.Index(index).UpdateDocuments(m)
if err != nil {
return err
}
return nil
}
func (mgr *SearchManager) Delete(index string, ids []string) error {
_, err := searchClient.Index(index).DeleteDocuments(ids)
if err != nil {
return err
}
return nil
}