Skip to content

Commit

Permalink
Merge pull request #2 from uug-ai/feature/generate-labels
Browse files Browse the repository at this point in the history
Implement default label generation functionality
  • Loading branch information
KilianBoute authored Feb 18, 2025
2 parents e4b9f23 + 1832f3f commit ad53892
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 1 deletion.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,37 @@ go run main.go -action vault-to-hub-migration \
2024/12/12 09:38:26 | xxxxxxxx/1733989397_6-967003_gb-frontdoor_200-200-400-400_166_769.mp4 | 3846902 | 1733989430 | lQtymLrehWpHkTavfcNTFgwfDMoSfg |
2024/12/12 09:38:26 | xxxxxxxx/1733989379_6-967003_gb-frontdoor_200-200-400-400_162_769.mp4 | 2107887 | 1733989400 | lQtymLrehWpHkTavfcNTFgwfDMoSfg |
2024/12/12 09:38:26 +---------------------------------------------------------------------------------------+-----------------+-----------------+-------------------------------------+


### Generate default labels

This tool adds starting labels to existing users in the database.

#### Command Line Arguments

- `-action`: The action to take (required). For labels, use `generate-default-labels`.
- `-mongodb-uri`: The MongoDB URI (optional if host and port are provided).
- `-mongodb-host`: The MongoDB host (optional if URI is provided).
- `-mongodb-port`: The MongoDB port (optional if URI is provided).
- `-mongodb-source-database`: The source database name (required).
- `-mongodb-database-credentials`: The database credentials (optional).
- `-mongodb-username`: The MongoDB username (optional).
- `-mongodb-password`: The MongoDB password (optional).
- `-label-names`: The names of the labels to add. Comma separated. Will add predefined default values if not provided.
- `-username`: A specific user to add labels to (optional).
- `-mode`: You can choose to run a `dry-run` or `live`.

#### Example

To run the default label generation, use the following command:

```sh
go run main.go -action generate-default-labels \
-mode 'dry-run' \
-mongodb-uri "mongodb+srv://<username>:<password>@<host>/<database>?retryWrites=true&w=majority&appName=<appName>" \
-mongodb-source-database=<sourceDatabase> \
-label-names=<labelNames> \

```

Add -username to add labels to just one specific user
228 changes: 228 additions & 0 deletions actions/generate-default-labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package actions

import (
"context"
"fmt"
"log"
"strings"
"time"

"github.com/gosuri/uiprogress"
"github.com/uug-ai/cli/database"
"github.com/uug-ai/cli/models"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"gopkg.in/mgo.v2/bson"
)

func GenerateDefaultLabels(
mode string,
mongodbURI string,
mongodbHost string,
mongodbPort string,
mongodbSourceDatabase string,
mongodbDatabaseCredentials string,
mongodbUsername string,
mongodbPassword string,
labelNames string,
username string,
) {

log.Println("====================================")
log.Println("Configuration:")
log.Println(" MongoDB URI:", mongodbURI)
log.Println(" MongoDB Host:", mongodbHost)
log.Println(" MongoDB Port:", mongodbPort)
log.Println(" MongoDB Source Database:", mongodbSourceDatabase)
log.Println(" MongoDB Database Credentials:", mongodbDatabaseCredentials)
log.Println(" MongoDB Username:", mongodbUsername)
log.Println(" MongoDB Password:", "************")
log.Println("====================================")
fmt.Println("")

fmt.Println(" >> Please wait while we process the data. Press Ctrl+C to stop the process.")
var steps = []string{
"MongoDB: verify connection",
"MongoDB: open connection",
"Hub: get users",
"Hub: generate labels",
"Hub: insert labels",
"Hub: complete",
}
bar := uiprogress.AddBar(len(steps)).AppendCompleted().PrependElapsed()
bar.PrependFunc(func(b *uiprogress.Bar) string {
return steps[b.Current()-1]
})
time.Sleep(time.Second * 2)
uiprogress.Start() // start rendering

// #####################################
//
// Step 1: Verify the connection to MongoDB
// Verify the connection to MongoDB
//
bar.Incr()
if mongodbURI == "" {
// If no URI is provided, use the host/port
if mongodbHost == "" || mongodbPort == "" {
log.Println("Please provide a valid MongoDB URI or host/port")
return
}
}
time.Sleep(time.Second * 2)

// #####################################
//
// Step 2: Connect to MongoDB
// Connect to MongoDB
//
bar.Incr()
var db *database.DB
if mongodbURI != "" {
db = database.NewMongoDBURI(mongodbURI)
} else {
db = database.NewMongoDBHost(mongodbHost, mongodbPort, mongodbDatabaseCredentials, mongodbUsername, mongodbPassword)
}
client := db.Client
defer client.Disconnect(context.Background())
time.Sleep(time.Second * 2)

// #####################################
//
// Step 3: Get the users from the Hub
// Get the owner users from the Hub
//
bar.Incr()
owners := GetOwnersFromMongodb(client, mongodbSourceDatabase, username)

time.Sleep(time.Second * 2)

// #####################################
//
// Step 4: generate the default labels
// generate the new labels to be inserted
//
bar.Incr()
labelNamesArray := strings.Split(labelNames, ",")

time.Sleep(time.Second * 2)

// #####################################
//
// Step 5: Insert the labels
// Insert the labels into the database
//
bar.Incr()
labelsCollection := client.Database(mongodbSourceDatabase).Collection("labels")
addedLabels := []models.Label{}
for _, owner := range owners {

labels := GenerateDefaultLabelsForNames(labelNamesArray, owner.Id.Hex())
for _, label := range labels {
filter := bson.M{"user_id": label.UserId, "name": label.Name}
count, err := labelsCollection.CountDocuments(context.Background(), filter)
if err != nil {
log.Println("Error checking for existing label:", err)
continue
}
if count == 0 {
if mode == "dry-run" {
// Nothing to do here..
} else if mode == "live" {
_, err = labelsCollection.InsertOne(context.Background(), label)
}
addedLabels = append(addedLabels, label)
if err != nil {
log.Println("Error inserting label:", err)
}
} else {
log.Println("Label already exists:", label.Name, "for user:", label.UserId)
}
}
}

bar.Incr()
uiprogress.Stop()

// #####################################
//
// Printout a table with the media that was transferred
//
log.Println("")
log.Println(">> Labels inserted:")
log.Println("")
log.Println(" +---------------------------------------------+----------------------+")
log.Println(" | User id | Label |")
log.Println(" +---------------------------------------------+----------------------+")
for _, label := range addedLabels {
log.Printf(" | %-43s | %-20s |\n", label.OwnerId, label.Name)
}
log.Println(" +---------------------------------------------+----------------------+")
log.Println("")
log.Println("Process completed.")
}

func GetOwnersFromMongodb(client *mongo.Client, DatabaseName string, username string) []models.User {
ctx, cancel := context.WithTimeout(context.Background(), TIMEOUT)
defer cancel()
db := client.Database(DatabaseName)
usersCollection := db.Collection("users")

var owners []models.User
match := bson.M{"role": "owner"}
if username != "" {
match = bson.M{"role": "owner", "username": username}
}
cursor, err := usersCollection.Find(ctx, match)
if err != nil {
log.Println(err)
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var user models.User
if err := cursor.Decode(&user); err != nil {
log.Println(err)
}
owners = append(owners, user)
}
if err := cursor.Err(); err != nil {
log.Println(err)
}

return owners
}

func GenerateDefaultLabelsForNames(names []string, userId string) []models.Label {
// Adjust default colors here
colors := []string{
"#9B260B", // Red
"#135A14", // Green
"#214598", // Blue
"#FFC32D", // Yellow
"#F89A2E", // Orange
"#5D2C6C", // Purple
}

// Default label names if empty
if len(names) == 0 {
names = []string{"Incident", "suspicious", "unauthorized"}
}

var labels []models.Label
for i, name := range names {
// Generate the label
label := models.Label{
Id: primitive.NewObjectID(),
Name: name,
Description: "Label for " + name,
Color: colors[i%len(colors)],
UserId: userId,
OwnerId: userId,
CreatedAt: time.Now().Unix(),
IsPrivate: false,
Types: []string{"case"},
}
labels = append(labels, label)
}
return labels
}
4 changes: 4 additions & 0 deletions database/mongodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ type DB struct {
Client *mongo.Client
}

func (d *DB) Collection(s string) any {
panic("unimplemented")
}

var TIMEOUT = 120 * time.Second
var _init_ctx sync.Once
var _instance *DB
Expand Down
17 changes: 16 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ func main() {
mongodbUsername := flag.String("mongodb-username", "", "MongoDB Username")
mongodbPassword := flag.String("mongodb-password", "", "MongoDB Password")
queueName := flag.String("queue", "", "The queue used to transfer the data")
username := flag.String("username", "", "Username")
username := flag.String("username", "", "Specific username to target")
startTimestamp := flag.Int64("start-timestamp", 0, "Start Timestamp")
endTimestamp := flag.Int64("end-timestamp", 0, "End Timestamp")
timezone := flag.String("timezone", "", "Timezone")
mode := flag.String("mode", "dry-run", "Mode")
pipeline := flag.String("pipeline", "monitor,sequence", "Provide the pipeline to execute")
batchSize := flag.Int("batch-size", 10, "Batch Size")
batchDelay := flag.Int("batch-delay", 1000, "Batch Delay in milliseconds")
labelNames := flag.String("label-names", "", "Names of the labels to generate separated by comma")

flag.Parse()

Expand All @@ -63,10 +64,24 @@ func main() {
*batchSize,
*batchDelay,
)
case "generate-default-labels":
fmt.Println("Generating default labels...")
actions.GenerateDefaultLabels(*mode,
*mongodbURI,
*mongodbHost,
*mongodbPort,
*mongodbSourceDatabase,
*mongodbDatabaseCredentials,
*mongodbUsername,
*mongodbPassword,
*labelNames,
*username,
)
default:
fmt.Println("Please provide a valid action.")
fmt.Println("Available actions:")
fmt.Println(" -action vault-to-hub-migration")
fmt.Println(" -action generate-default-labels")
}

}
13 changes: 13 additions & 0 deletions models/hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,16 @@ type SequencesWithMedia struct {
Star bool `json:"star" bson:"star"`
Devices []string `json:"devices" bson:"devices"`
}

// Case labels
type Label struct {
Id primitive.ObjectID `json:"id" bson:"_id,omitempty,omitempty"`
Name string `json:"name" bson:"name,omitempty"`
Description string `json:"description" bson:"description,omitempty"`
Color string `json:"color" bson:"color,omitempty"`
UserId string `json:"user_id" bson:"user_id,omitempty"` // Log which user created the label
OwnerId string `json:"owner_id" bson:"owner_id,omitempty"` // Log which master account the user belongs to, used to group labels
CreatedAt int64 `json:"created_at" bson:"created_at,omitempty"` // For sorting purposes
IsPrivate bool `json:"is_private" bson:"is_private"` // Could be available on only private tasks in future
Types []string `json:"type" bson:"type,omitempty"` // Could be used to group labels by tasks, media, alerts,...
}

0 comments on commit ad53892

Please sign in to comment.