diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 5db86a4..5af35ea 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -9,7 +9,7 @@ services: - 27017:27017 environment: MONGO_INITDB_ROOT_USERNAME: root - MONGO_INITDB_ROOT_PASSWORD: example + MONGO_INITDB_ROOT_PASSWORD: root12345 mongo-express: image: mongo-express @@ -18,5 +18,5 @@ services: - 8081:8081 environment: ME_CONFIG_MONGODB_ADMINUSERNAME: root - ME_CONFIG_MONGODB_ADMINPASSWORD: example - ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/ + ME_CONFIG_MONGODB_ADMINPASSWORD: root12345 + ME_CONFIG_MONGODB_URL: mongodb://root:root12345@mongo:27017/ diff --git a/main.go b/main.go index e968a28..28ea074 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,8 @@ package main import ( "context" "encoding/json" + "fmt" + "gibb165lb2/util" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" @@ -16,21 +18,10 @@ import ( var client *mongo.Client -type Person struct { - ID primitive.ObjectID `bson:"_id,omitempty"` - Name string `bson:"name"` -} +// func to insert 10 random persons with real names into the database and create 30 random debts for them -type Debt struct { - ID primitive.ObjectID `bson:"_id,omitempty"` - PersonID primitive.ObjectID `bson:"fk_pid"` - Amount int `bson:"amount"` - Description string `bson:"description,omitempty"` - Datetime time.Time `bson:"datetime"` -} - -func getDebtsForPerson(client *mongo.Client, personID string) ([]Debt, error) { - var results []Debt +func getDebtsForPerson(client *mongo.Client, personID string) ([]util.Debt, error) { + var results []util.Debt ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -54,7 +45,7 @@ func getDebtsForPerson(client *mongo.Client, personID string) ([]Debt, error) { // Durchlaufen des Cursors und Hinzufügen der Ergebnisse zur results-Slice for cursor.Next(ctx) { - var debt Debt + var debt util.Debt if err := cursor.Decode(&debt); err != nil { return nil, err } @@ -72,18 +63,26 @@ func main() { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() var err error - client, err = mongo.Connect(ctx, options.Client().ApplyURI("mongodb://root:example@localhost:27017")) + client, err = mongo.Connect(ctx, options.Client().ApplyURI("mongodb://root:root12345@localhost:27017")) if err != nil { panic(err) } - + //util.InsertRandomData(client) // Router initialisieren r := mux.NewRouter() r.HandleFunc("/persons", createPerson).Methods("POST") r.HandleFunc("/persons/{id}", getPerson).Methods("GET") r.HandleFunc("/persons", getAllPersons).Methods("GET") + r.HandleFunc("/personsWithDebts", getPersonsWithDebts).Methods("GET") r.HandleFunc("/persons/{id}", updatePerson).Methods("PUT") r.HandleFunc("/persons/{id}", deletePerson).Methods("DELETE") + r.HandleFunc("/persons/{id}/debts", getDebts).Methods("GET") + r.HandleFunc("/persons/{id}/debts", createDebt).Methods("POST") + r.HandleFunc("/debts/{id}", deleteDebt).Methods("DELETE") + r.HandleFunc("/debts", getAllDebts).Methods("GET") + r.HandleFunc("/debts/{id}", getDebt).Methods("GET") + r.HandleFunc("/debts/{id}", updateDebt).Methods("PUT") + err = http.ListenAndServe(":3333", r) if err != nil { log.Fatal(err) @@ -92,7 +91,7 @@ func main() { func createPerson(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - var person Person + var person util.Person json.NewDecoder(r.Body).Decode(&person) collection := client.Database("debtlist").Collection("persons") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) @@ -108,15 +107,22 @@ func createPerson(w http.ResponseWriter, r *http.Request) { } func updatePerson(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - var person Person + var person util.Person + vars := mux.Vars(r) + personID := vars["id"] + person.ID, _ = primitive.ObjectIDFromHex(personID) json.NewDecoder(r.Body).Decode(&person) + fmt.Println(person) + collection := client.Database("debtlist").Collection("persons") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() filter := bson.M{"_id": person.ID} update := bson.M{ "$set": bson.M{ - "name": person.Name, + "name": person.Name, + "age": person.Age, + "email": person.Email, }, } result, err := collection.UpdateOne(ctx, filter, update) @@ -130,12 +136,13 @@ func updatePerson(w http.ResponseWriter, r *http.Request) { } func deletePerson(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - var person Person - json.NewDecoder(r.Body).Decode(&person) + vars := mux.Vars(r) + personID := vars["id"] collection := client.Database("debtlist").Collection("persons") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - filter := bson.M{"_id": person.ID} + newPersonID, err := primitive.ObjectIDFromHex(personID) + filter := bson.M{"_id": newPersonID} result, err := collection.DeleteOne(ctx, filter) if err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -148,7 +155,7 @@ func getPerson(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) personID := vars["id"] w.Header().Set("Content-Type", "application/json") - var person Person + var person util.Person collection := client.Database("debtlist").Collection("persons") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -164,7 +171,7 @@ func getPerson(w http.ResponseWriter, r *http.Request) { } func getAllPersons(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - var persons []Person + var persons []util.Person collection := client.Database("debtlist").Collection("persons") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -176,7 +183,7 @@ func getAllPersons(w http.ResponseWriter, r *http.Request) { } defer cursor.Close(ctx) for cursor.Next(ctx) { - var person Person + var person util.Person cursor.Decode(&person) persons = append(persons, person) } @@ -187,3 +194,167 @@ func getAllPersons(w http.ResponseWriter, r *http.Request) { } json.NewEncoder(w).Encode(persons) } + +func getDebts(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + personID := vars["id"] + w.Header().Set("Content-Type", "application/json") + debts, err := getDebtsForPerson(client, personID) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + json.NewEncoder(w).Encode(debts) +} + +func createDebt(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + w.Header().Set("Content-Type", "application/json") + var debt util.Debt + personID := vars["id"] + json.NewDecoder(r.Body).Decode(&debt) + debt.PersonID, _ = primitive.ObjectIDFromHex(personID) + collection := client.Database("debtlist").Collection("debts") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + result, err := collection.InsertOne(ctx, debt) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + json.NewEncoder(w).Encode(result) +} + +func deleteDebt(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + w.Header().Set("Content-Type", "application/json") + var debt util.Debt + debtId := vars["id"] + json.NewDecoder(r.Body).Decode(&debt) + debt.ID, _ = primitive.ObjectIDFromHex(debtId) + collection := client.Database("debtlist").Collection("debts") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + filter := bson.M{"_id": debt.ID} + result, err := collection.DeleteOne(ctx, filter) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + json.NewEncoder(w).Encode(result) +} + +func getAllDebts(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + var debts []util.Debt + collection := client.Database("debtlist").Collection("debts") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + cursor, err := collection.Find(ctx, bson.M{}) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + defer cursor.Close(ctx) + for cursor.Next(ctx) { + var debt util.Debt + cursor.Decode(&debt) + debts = append(debts, debt) + } + if err := cursor.Err(); err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + json.NewEncoder(w).Encode(debts) +} + +// eine route welche alle personen zurückgibt welche ein array aus debts haben. +func getPersonsWithDebts(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + var personsWithDebts []util.PersonWithDebts + var persons []util.Person + collection := client.Database("debtlist").Collection("persons") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + cursor, err := collection.Find(ctx, bson.M{}) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + defer cursor.Close(ctx) + for cursor.Next(ctx) { + var person util.Person + cursor.Decode(&person) + persons = append(persons, person) + } + if err := cursor.Err(); err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + for _, person := range persons { + debts, err := getDebtsForPerson(client, person.ID.Hex()) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + personsWithDebts = append(personsWithDebts, util.PersonWithDebts{Person: person, Debts: debts}) + } + json.NewEncoder(w).Encode(personsWithDebts) +} + +// neue route welche eine einzelne debt zurückgibt +func getDebt(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + debtID := vars["id"] + w.Header().Set("Content-Type", "application/json") + var debt util.Debt + collection := client.Database("debtlist").Collection("debts") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + did, err := primitive.ObjectIDFromHex(debtID) + filter := bson.M{"_id": did} + err = collection.FindOne(ctx, filter).Decode(&debt) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + json.NewEncoder(w).Encode(debt) +} + +// neue route welche eine einzelne debt aktualisiert +func updateDebt(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + var debt util.Debt + vars := mux.Vars(r) + debtID := vars["id"] + debt.ID, _ = primitive.ObjectIDFromHex(debtID) + json.NewDecoder(r.Body).Decode(&debt) + collection := client.Database("debtlist").Collection("debts") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + filter := bson.M{"_id": debt.ID} + update := bson.M{ + "$set": bson.M{ + "fk_pid": debt.PersonID, + "amount": debt.Amount, + "description": debt.Description, + "datetime": debt.Datetime, + }, + } + result, err := collection.UpdateOne(ctx, filter, update) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"message": "` + err.Error() + `"}`)) + return + } + json.NewEncoder(w).Encode(result) +} diff --git a/util/structs.go b/util/structs.go new file mode 100644 index 0000000..94ebfd0 --- /dev/null +++ b/util/structs.go @@ -0,0 +1,25 @@ +package util + +import ( + "go.mongodb.org/mongo-driver/bson/primitive" + "time" +) + +type Person struct { + ID primitive.ObjectID `bson:"_id,omitempty"` + Name string `bson:"name"` + Age int `bson:"age,omitempty" json:"age,omitempty"` + Email string `bson:"email,omitempty" json:"email,omitempty"` +} + +type Debt struct { + ID primitive.ObjectID `bson:"_id,omitempty"` + PersonID primitive.ObjectID `bson:"fk_pid"` + Amount int `bson:"amount"` + Description string `bson:"description,omitempty"` + Datetime time.Time `bson:"datetime"` +} +type PersonWithDebts struct { + Person Person `json:"person"` + Debts []Debt `json:"debts"` +} diff --git a/util/util.go b/util/util.go new file mode 100644 index 0000000..3e15609 --- /dev/null +++ b/util/util.go @@ -0,0 +1,36 @@ +package util + +import ( + "context" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" + "log" + "time" +) + +func InsertRandomData(client *mongo.Client) { + persons := []string{"Max", "Moritz", "Hans", "Peter", "Paul", "Klaus", "Karl", "Kai", "Kurt", "Karl-Heinz"} + debts := []Debt{} + for i := 0; i < 10; i++ { + person := Person{Name: persons[i]} + collection := client.Database("debtlist").Collection("persons") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + result, err := collection.InsertOne(ctx, person) + if err != nil { + log.Fatal(err) + } + for j := 0; j < 3; j++ { + debts = append(debts, Debt{PersonID: result.InsertedID.(primitive.ObjectID), Amount: j * 100, Description: "Test", Datetime: time.Now()}) + } + } + collection := client.Database("debtlist").Collection("debts") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + for _, debt := range debts { + _, err := collection.InsertOne(ctx, debt) + if err != nil { + log.Fatal(err) + } + } +}