Initialize base
This commit is contained in:
@@ -0,0 +1,336 @@
|
||||
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 ""
|
||||
}
|
||||
Reference in New Issue
Block a user