337 lines
8.4 KiB
Go
337 lines
8.4 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"log"
|
||
"time"
|
||
|
||
"github.com/google/uuid"
|
||
"go.mongodb.org/mongo-driver/bson"
|
||
"go.mongodb.org/mongo-driver/mongo"
|
||
"go.mongodb.org/mongo-driver/mongo/options"
|
||
"golang.org/x/crypto/bcrypt"
|
||
|
||
"tm/internal/domain"
|
||
)
|
||
|
||
const (
|
||
DefaultMongoURI = "mongodb://localhost:27017"
|
||
DefaultDBName = "tender_management"
|
||
)
|
||
|
||
func main() {
|
||
// Get database connection details from environment or use defaults
|
||
mongoURI := DefaultMongoURI
|
||
if uri := getEnv("MONGO_URI"); uri != "" {
|
||
mongoURI = uri
|
||
}
|
||
|
||
dbName := DefaultDBName
|
||
if name := getEnv("DB_NAME"); name != "" {
|
||
dbName = name
|
||
}
|
||
|
||
fmt.Println("🚀 Starting database migration for dual user system...")
|
||
fmt.Printf("📊 Database: %s\n", dbName)
|
||
fmt.Printf("🔗 URI: %s\n", mongoURI)
|
||
|
||
// Connect to MongoDB
|
||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||
defer cancel()
|
||
|
||
client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI))
|
||
if err != nil {
|
||
log.Fatal("❌ Failed to connect to MongoDB:", err)
|
||
}
|
||
defer client.Disconnect(context.Background())
|
||
|
||
// Ping to verify connection
|
||
if err = client.Ping(ctx, nil); err != nil {
|
||
log.Fatal("❌ Failed to ping MongoDB:", err)
|
||
}
|
||
|
||
fmt.Println("✅ Connected to MongoDB successfully")
|
||
|
||
db := client.Database(dbName)
|
||
|
||
// Run migrations
|
||
if err := createCustomersCollection(db); err != nil {
|
||
log.Fatal("❌ Failed to create customers collection:", err)
|
||
}
|
||
|
||
if err := createUsersCollection(db); err != nil {
|
||
log.Fatal("❌ Failed to create users collection:", err)
|
||
}
|
||
|
||
if err := createSampleData(db); err != nil {
|
||
log.Fatal("❌ Failed to create sample data:", err)
|
||
}
|
||
|
||
fmt.Println("🎉 Database migration completed successfully!")
|
||
}
|
||
|
||
// createCustomersCollection creates the customers collection with indexes
|
||
func createCustomersCollection(db *mongo.Database) error {
|
||
fmt.Println("📝 Creating customers collection...")
|
||
|
||
collection := db.Collection("customers")
|
||
|
||
// Create indexes
|
||
indexes := []mongo.IndexModel{
|
||
{
|
||
Keys: bson.D{{"email", 1}},
|
||
Options: options.Index().SetUnique(true).SetName("email_unique"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"company_id", 1}},
|
||
Options: options.Index().SetName("company_id_idx"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"is_active", 1}},
|
||
Options: options.Index().SetName("is_active_idx"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"created_at", -1}},
|
||
Options: options.Index().SetName("created_at_desc_idx"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"role", 1}},
|
||
Options: options.Index().SetName("role_idx"),
|
||
},
|
||
}
|
||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||
defer cancel()
|
||
|
||
_, err := collection.Indexes().CreateMany(ctx, indexes)
|
||
if err != nil {
|
||
return fmt.Errorf("failed to create customer indexes: %w", err)
|
||
}
|
||
|
||
fmt.Println("✅ Customers collection created with indexes")
|
||
return nil
|
||
}
|
||
|
||
// createUsersCollection creates the panel users collection with indexes
|
||
func createUsersCollection(db *mongo.Database) error {
|
||
fmt.Println("📝 Creating users collection...")
|
||
|
||
collection := db.Collection("users")
|
||
|
||
// Create indexes
|
||
indexes := []mongo.IndexModel{
|
||
{
|
||
Keys: bson.D{{"email", 1}},
|
||
Options: options.Index().SetUnique(true).SetName("email_unique"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"role", 1}},
|
||
Options: options.Index().SetName("role_idx"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"is_active", 1}},
|
||
Options: options.Index().SetName("is_active_idx"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"department", 1}},
|
||
Options: options.Index().SetName("department_idx"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"created_at", -1}},
|
||
Options: options.Index().SetName("created_at_desc_idx"),
|
||
},
|
||
{
|
||
Keys: bson.D{{"created_by", 1}},
|
||
Options: options.Index().SetName("created_by_idx"),
|
||
},
|
||
}
|
||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||
defer cancel()
|
||
|
||
_, err := collection.Indexes().CreateMany(ctx, indexes)
|
||
if err != nil {
|
||
return fmt.Errorf("failed to create user indexes: %w", err)
|
||
}
|
||
|
||
fmt.Println("✅ Users collection created with indexes")
|
||
return nil
|
||
}
|
||
|
||
// createSampleData creates sample admin user and test customer
|
||
func createSampleData(db *mongo.Database) error {
|
||
fmt.Println("📝 Creating sample data...")
|
||
|
||
// Create sample admin user
|
||
if err := createSampleAdmin(db); err != nil {
|
||
return fmt.Errorf("failed to create sample admin: %w", err)
|
||
}
|
||
|
||
// Create sample customer
|
||
if err := createSampleCustomer(db); err != nil {
|
||
return fmt.Errorf("failed to create sample customer: %w", err)
|
||
}
|
||
|
||
fmt.Println("✅ Sample data created successfully")
|
||
return nil
|
||
}
|
||
|
||
// createSampleAdmin creates a sample admin user
|
||
func createSampleAdmin(db *mongo.Database) error {
|
||
collection := db.Collection("users")
|
||
|
||
// Check if admin already exists
|
||
ctx := context.Background()
|
||
count, err := collection.CountDocuments(ctx, bson.M{"email": "admin@tendermanagement.com"})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if count > 0 {
|
||
fmt.Println("ℹ️ Sample admin user already exists, skipping...")
|
||
return nil
|
||
}
|
||
|
||
// Hash password for admin
|
||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte("admin123!"), bcrypt.DefaultCost)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
now := time.Now()
|
||
adminID := uuid.New()
|
||
admin := bson.M{
|
||
"_id": adminID,
|
||
"email": "admin@tendermanagement.com",
|
||
"password": string(hashedPassword),
|
||
"first_name": "System",
|
||
"last_name": "Administrator",
|
||
"role": domain.UserRoleAdmin,
|
||
"department": "IT",
|
||
"is_active": true,
|
||
"permissions": []string{
|
||
"manage_users",
|
||
"manage_tenders",
|
||
"manage_companies",
|
||
"manage_customers",
|
||
"view_reports",
|
||
"manage_system",
|
||
"manage_sources",
|
||
},
|
||
"created_at": now,
|
||
"updated_at": now,
|
||
}
|
||
|
||
_, err = collection.InsertOne(ctx, admin)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
fmt.Println("👤 Sample admin user created:")
|
||
fmt.Println(" 📧 Email: admin@tendermanagement.com")
|
||
fmt.Println(" 🔑 Password: admin123!")
|
||
fmt.Println(" 🛡️ Role: admin")
|
||
|
||
return nil
|
||
}
|
||
|
||
// createSampleCustomer creates a sample customer
|
||
func createSampleCustomer(db *mongo.Database) error {
|
||
collection := db.Collection("customers")
|
||
|
||
// Check if customer already exists
|
||
ctx := context.Background()
|
||
count, err := collection.CountDocuments(ctx, bson.M{"email": "customer@example.com"})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if count > 0 {
|
||
fmt.Println("ℹ️ Sample customer already exists, skipping...")
|
||
return nil
|
||
}
|
||
|
||
// Hash password for customer
|
||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte("customer123!"), bcrypt.DefaultCost)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
now := time.Now()
|
||
companyID := uuid.New()
|
||
customerID := uuid.New()
|
||
|
||
// Create sample company first
|
||
companyCollection := db.Collection("companies")
|
||
company := bson.M{
|
||
"_id": companyID,
|
||
"name": "Sample Company Ltd",
|
||
"description": "A sample company for testing",
|
||
"industry": "Technology",
|
||
"country": "United States",
|
||
"website": "https://example.com",
|
||
"keywords": []string{"technology", "software", "consulting"},
|
||
"products": []string{"software development", "consulting"},
|
||
"services": []string{"web development", "mobile apps"},
|
||
"created_at": now,
|
||
"updated_at": now,
|
||
}
|
||
|
||
_, err = companyCollection.InsertOne(ctx, company)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Create customer
|
||
customer := bson.M{
|
||
"_id": customerID,
|
||
"email": "customer@example.com",
|
||
"password": string(hashedPassword),
|
||
"first_name": "John",
|
||
"last_name": "Doe",
|
||
"phone": "+1234567890",
|
||
"role": domain.CustomerRoleUser,
|
||
"company_id": companyID,
|
||
"is_active": true,
|
||
"is_verified": true,
|
||
"device_tokens": []string{},
|
||
"preferences": bson.M{
|
||
"language": "en",
|
||
"notification_settings": bson.M{
|
||
"new_tenders": true,
|
||
"deadline_reminder": true,
|
||
"status_updates": true,
|
||
"system_alerts": true,
|
||
},
|
||
"tender_alerts": true,
|
||
"email_notifications": true,
|
||
"push_notifications": true,
|
||
"preferred_categories": []string{},
|
||
},
|
||
"created_at": now,
|
||
"updated_at": now,
|
||
}
|
||
|
||
_, err = collection.InsertOne(ctx, customer)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
fmt.Println("👤 Sample customer created:")
|
||
fmt.Println(" 📧 Email: customer@example.com")
|
||
fmt.Println(" 🔑 Password: customer123!")
|
||
fmt.Println(" 🏢 Company: Sample Company Ltd")
|
||
fmt.Println(" 📱 Role: customer_user")
|
||
|
||
return nil
|
||
}
|
||
|
||
// Helper functions
|
||
|
||
func getEnv(key string) string {
|
||
// Simple environment variable getter
|
||
// In a real implementation, you might use os.Getenv()
|
||
return ""
|
||
}
|