diff --git a/.env b/.env
new file mode 100644
index 0000000000000000000000000000000000000000..6a1ca89e91d03b60218f83ce831a863a25da2331
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+MONGO_URI=mongodb+srv://secapp-tp:hepiaschooltp@cluster0.pkjspwr.mongodb.net/
+#MONGO_URI=mongodb+srv://yug:HUDDwcbVSuDzmDXG@cluster0.ttzwnxf.mongodb.net/
+SENDGRID_API_KEY=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
+SMTP_FROM_ADDRESS=notifications@mstd.dansmonorage.blue
+PORT=5500
diff --git a/main.go b/main.go
index efa8205ebe693a74d6f8151a2895689a7c0fae23..a22e9303ae5f1679c9be84b7cb1a3e52f0d09702 100644
--- a/main.go
+++ b/main.go
@@ -12,15 +12,20 @@ import (
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/mongo"
 	"go.mongodb.org/mongo-driver/mongo/options"
+	"go.mongodb.org/mongo-driver/bson/primitive"
 	"strconv"
 	"time"    
     "github.com/go-gomail/gomail"
 	"io"
 	"mime/multipart"
+	"encoding/json"
+	"strings"
 )
 
 var usersCollection *mongo.Collection
 var postsCollection *mongo.Collection
+var privateMessagesCollection *mongo.Collection
+var tokensCollection *mongo.Collection
 var URI string
 var messages []models.Post
 var err error
@@ -341,6 +346,7 @@ func main() {
 	fmt.Println("Connected successfully")
 	usersCollection = client.Database("authentication").Collection("users")
 	postsCollection = client.Database("mydb").Collection("messages")
+	privateMessagesCollection = client.Database("mydb").Collection("private_messages")
 	fs := http.FileServer(http.Dir("./view"))
 	http.Handle("/", fs)
 	http.HandleFunc("/signin", signInHandler)
@@ -350,12 +356,511 @@ func main() {
 	http.HandleFunc("/reset-password", handlePasswordReset)
 	http.HandleFunc("/post", handlePost)
 	http.HandleFunc("/messages", messagesHandler)
+	http.HandleFunc("/editbyadmin", editbyAdminHandler)
 	http.HandleFunc("/edit", editHandler)
 	http.HandleFunc("/admin", adminHandler)
 	http.HandleFunc("/delete", deleteHandler)
+	http.HandleFunc("/admin-change-password", adminChangePasswordHandler)
+	http.HandleFunc("/private-messages", privateMessagesHandler)
+	http.HandleFunc("/send-private-message", sendPrivateMessageHandler)
+
+	http.HandleFunc("/api/messages", messagesAPIHandler)
+	http.HandleFunc("/api/message/", IDmessagesAPIHandler)
+	http.HandleFunc("/api/message", postPublicMessageHandler)
+	http.HandleFunc("/generate-api-token", generateAPITokenHandler)
+
 	log.Fatal(http.ListenAndServe(":5500", nil))
 }
 
+func postPublicMessageHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != http.MethodPost {
+		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
+		return
+	}
+	// Check the XAPITOKEN header
+	token := r.Header.Get("XAPITOKEN")
+	if token == "" {
+		http.Error(w, "Unauthorized", http.StatusUnauthorized)
+		return
+	}
+	// Verify the API token
+	var result struct {
+		Username string `bson:"username"`
+		IsAdmin  string `bson:"is_admin"`
+	}
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	defer client.Disconnect(context.Background())
+	
+	tokensCollection = client.Database("Token").Collection("tokens")
+	err = tokensCollection.FindOne(context.Background(), bson.M{"token": token}).Decode(&result)
+	if err != nil {
+		http.Error(w, "Unauthorized", http.StatusUnauthorized)
+		return
+	}
+	// Check if the user is the token owner
+	fmt.Println("printing result")
+	fmt.Println(result)
+
+	// Get the message data from the REST request body
+	
+	/*var message models.Post
+	err = json.NewDecoder(r.Body).Decode(&message)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}*/
+	message := r.FormValue("message")
+	// Create a document that contains the message
+	doc := bson.M{"message": message}
+	// Insert the message into the database
+	postsCollection = client.Database("mydb").Collection("messages")
+	_, err = postsCollection.InsertOne(context.Background(), doc)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+}
+
+func IDmessagesAPIHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != http.MethodGet {
+		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
+		return
+	}
+
+	// Get the message ID from the URL
+	idStr := strings.TrimPrefix(r.URL.Path, "/api/message/")
+	// Convert the string ID to an ObjectID
+	id, err := primitive.ObjectIDFromHex(idStr)
+	if err != nil {
+		http.Error(w, "Invalid ID", http.StatusBadRequest)
+		return
+	}
+	fmt.Println("printing id")
+	fmt.Println(id)
+	// Check the XAPITOKEN header
+	token := r.Header.Get("XAPITOKEN")
+	if token == "" {
+		http.Error(w, "Unauthorized", http.StatusUnauthorized)
+		return
+	}
+	// Verify the API token
+	var result struct {
+		Username string `bson:"username"`
+		IsAdmin  string `bson:"is_admin"`
+	}
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	defer client.Disconnect(context.Background())
+
+	tokensCollection = client.Database("Token").Collection("tokens")
+	err = tokensCollection.FindOne(context.Background(), bson.M{"token": token}).Decode(&result)
+	if err != nil {
+		http.Error(w, "Unauthorized", http.StatusUnauthorized)
+		return
+	}
+
+	// Check if the user is not an admin
+	var message bson.M
+	if result.IsAdmin == "false" {
+		// check if the message id is that of the user and its token
+		err := privateMessagesCollection.FindOne(context.Background(), bson.M{"_id": id}).Decode(&message)
+		fmt.Println("printing message")
+		fmt.Println(message)
+		if err != nil {
+			return
+		}
+		if message["sender"] != result.Username && message["receiver"] != result.Username {
+			http.Error(w, "Unauthorized", http.StatusUnauthorized)
+
+			return
+		}
+		// return the message
+		err = json.NewEncoder(w).Encode(message)
+		return
+	}
+	// if the user is an admin return the message
+	err = privateMessagesCollection.FindOne(context.Background(), bson.M{"_id": id}).Decode(&message)
+	if err != nil {
+		return
+	}
+	fmt.Println("printing message")
+	fmt.Println(message)
+	err = json.NewEncoder(w).Encode(message)
+
+}
+
+func getMessage(client *mongo.Client, messageID string) (bson.M, error) {
+    messagesCollection := client.Database("yourDatabase").Collection("messages")
+
+    var message bson.M
+    err := messagesCollection.FindOne(context.Background(), bson.M{"_id": messageID}).Decode(&message)
+    if err != nil {
+        return nil, err
+    }
+
+    return message, nil
+} 
+
+func messagesAPIHandler(w http.ResponseWriter, r *http.Request) {
+	// Handle the API request here
+	if r.Method != http.MethodGet {
+		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
+		return
+	}
+
+
+	// Check the XAPITOKEN header
+	token := r.Header.Get("XAPITOKEN")
+
+	if token == "" {
+		http.Error(w, "Unauthorized", http.StatusUnauthorized)
+		return
+	}
+	
+	// Verify the API token
+	var result struct {
+		Username string `bson:"username"`
+		IsAdmin  string `bson:"is_admin"`
+	}
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	defer client.Disconnect(context.Background())
+
+	tokensCollection = client.Database("Token").Collection("tokens")
+	err = tokensCollection.FindOne(context.Background(), bson.M{"token": token}).Decode(&result)
+	if err != nil {
+		http.Error(w, "Unauthorized", http.StatusUnauthorized)
+		return
+	}
+	fmt.Println("printing result")
+	fmt.Println(result)
+	fmt.Println("token is not empty")
+	// Check if the user is an admin
+	if result.IsAdmin != "false" {
+		// Retrieve all messages from the database if the user is an admin
+		fmt.Println("I am not an admin")
+		messages, err := getAllPrivateMessagesAdmin()
+		fmt.Println("printing messages")
+		fmt.Println(messages)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		// send the messages back to the user RESTfully
+		err = json.NewEncoder(w).Encode(messages)
+	}
+	// Retrieve the user's messages from the database if the user is not an admin
+	messages, err := getAllPrivateMessages(result.Username)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	// send the messages back to the user RESTfully
+	err = json.NewEncoder(w).Encode(messages)
+	
+}
+
+func getAllPrivateMessagesAdmin() ([]models.PrivateMessage, error) {
+	fmt.Println("Entered getAllPrivateMessagesAdmin")
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		return nil, err
+	}
+	defer client.Disconnect(context.Background())
+
+	// Retrieve all private messages from the database
+	var messages []models.PrivateMessage
+	cursor, err := privateMessagesCollection.Find(context.Background(), bson.M{})
+	if err != nil {
+		return nil, err
+	}
+	defer cursor.Close(context.Background())
+	for cursor.Next(context.Background()) {
+		var message models.PrivateMessage
+		err := cursor.Decode(&message)
+		if err != nil {
+			return nil, err
+		}
+		messages = append(messages, message)
+	}
+	fmt.Println("printing messages from getAllPrivateMessagesAdmin")
+	fmt.Println(messages)
+	return messages, nil
+}
+
+func generateAPIToken(username string) string {
+    // Get the current time
+    now := time.Now()
+
+    // Combine the username and the current time to create the token
+    token := fmt.Sprintf("%s_%d", username, now.Unix())
+
+    return token
+}
+
+func generateAPITokenHandler(w http.ResponseWriter, r *http.Request) {
+    if r.Method != http.MethodGet {
+        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
+        return
+    }
+
+    // Get the username from the cookie
+    cookie, err := r.Cookie("username")
+    if err != nil {
+        http.Redirect(w, r, "/signin", http.StatusSeeOther)
+        return
+    }
+    username := cookie.Value
+	var isAdmin string = "false"
+
+    // Generate a new API token
+    token := generateAPIToken(username)
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	defer client.Disconnect(context.Background())
+
+	// Check if the user is an admin
+	user, err := getUser(username)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	if user.Role != "admin" {
+		isAdmin = "false"
+	} else {
+		isAdmin = "true"
+	}
+
+	// Save the API token to the MongoDB database
+    tokensCollection := client.Database("Token").Collection("tokens")
+	// Delete the user's old API token from the database if it exists
+	_, err = tokensCollection.DeleteOne(context.Background(), bson.M{"username": username})
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	// Insert the token into the database
+    _, err = tokensCollection.InsertOne(context.TODO(), map[string]string{
+        "username": username,
+        "token":    token,
+		"is_admin":  isAdmin,
+    })
+
+	if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+
+    // Display the API token to the user
+    w.Write([]byte("Your new API token is: " + token))
+}
+
+func privateMessagesAPIHandler(w http.ResponseWriter, r *http.Request) {
+    // Handle the API request here
+
+}
+
+func privateMessagesHandler(w http.ResponseWriter, r *http.Request) {
+    // Get the username from the cookie
+    cookie, err := r.Cookie("username")
+    if err != nil {
+        http.Redirect(w, r, "/signin", http.StatusSeeOther)
+        return
+    }
+    username := cookie.Value
+
+    // Get the private messages from the database
+    messages, err := getAllPrivateMessages(username)
+	fmt.Println("printing messages")
+	fmt.Println(messages)
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+	// Convert the Content field to template.HTML
+    for i := range messages {
+        messages[i].Content = template.HTML(messages[i].Content)
+    }
+    // Create a data structure to hold the messages
+    data := struct {
+        PrivateMessages []models.PrivateMessage
+    }{
+        PrivateMessages: messages,
+    }
+
+    // Render the DM.html page
+    tmpl := template.Must(template.ParseFiles("view/DM.html"))
+    tmpl.Execute(w, data)
+}
+
+func getAllPrivateMessages(username string) ([]models.PrivateMessage, error) {
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		return nil, err
+	}
+	defer client.Disconnect(context.Background())
+
+	// Retrieve all private messages from the database
+	var messages []models.PrivateMessage
+	cursor, err := privateMessagesCollection.Find(context.Background(), bson.M{"$or": []bson.M{
+		bson.M{"sender": username},
+		bson.M{"receiver": username},
+	}})
+	if err != nil {
+		return nil, err
+	}
+	defer cursor.Close(context.Background())
+	for cursor.Next(context.Background()) {
+		var message models.PrivateMessage
+		err := cursor.Decode(&message)
+		if err != nil {
+			return nil, err
+		}
+		messages = append(messages, message)
+	}
+
+	return messages, nil
+}
+func getPrivateMessages(username string) ([]models.PrivateMessage, error) {
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		return nil, err
+	}
+	defer client.Disconnect(context.Background())
+
+	// Retrieve all private messages from the database
+	var messages []models.PrivateMessage
+	cursor, err := privateMessagesCollection.Find(context.Background(), bson.M{"$or": []bson.M{
+		bson.M{"sender": username},
+		bson.M{"receiver": username},
+	}})
+	if err != nil {
+		return nil, err
+	}
+	defer cursor.Close(context.Background())
+	for cursor.Next(context.Background()) {
+		var message models.PrivateMessage
+		err := cursor.Decode(&message)
+		if err != nil {
+			return nil, err
+		}
+		messages = append(messages, message)
+	}
+
+	return messages, nil
+}
+
+func sendPrivateMessage(sender, receiver, content string) error {
+	// Create a new private message object
+	message := models.PrivateMessage{
+		Sender:    sender,
+		Receiver:  receiver,
+		Content:    template.HTML(content),
+		Timestamp: time.Now(),
+	}
+
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		return err
+	}
+	defer client.Disconnect(context.Background())
+
+	// Insert the message into the database
+	_, err = privateMessagesCollection.InsertOne(context.Background(), message)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func sendPrivateMessageHandler(w http.ResponseWriter, r *http.Request) {
+    // Get the username from the cookie
+    cookie, err := r.Cookie("username")
+    if err != nil {
+        http.Redirect(w, r, "/signin", http.StatusSeeOther)
+        return
+    }
+    sender := cookie.Value
+
+    // Get the receiver and content from the form data
+    receiver := r.FormValue("receiver")
+    content := r.FormValue("content")
+
+    // Send the private message
+    err = sendPrivateMessage(sender, receiver, content)
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+
+    // Redirect the user back to the private messages page
+    http.Redirect(w, r, "/private-messages", http.StatusSeeOther)
+}
+
+func adminChangePasswordHandler(w http.ResponseWriter, r *http.Request) {
+	// Check if the user is an admin
+	cookie, err := r.Cookie("username")
+	if err != nil {
+		http.Redirect(w, r, "/signin", http.StatusSeeOther)
+		return
+	}
+	username := cookie.Value
+	user, err := getUser(username)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	if user.Role != "admin" {
+		http.Error(w, "Unauthorized", http.StatusUnauthorized)
+		return
+	}
+
+	// Get the username and password from the form data
+	usernameToChange := r.FormValue("username")
+	password := r.FormValue("password")
+
+	// Update the user's password in the database
+	_,err = updateEmailAndPassword(usernameToChange, "", password)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	// Redirect the user back to the admin page
+	http.Redirect(w, r, "/admin", http.StatusSeeOther)
+}
+
 
 //deleteUser function
 func deleteUser(username string) error {
@@ -679,6 +1184,163 @@ func saveAvatarFile(username, filename string, file multipart.File) error {
 	return nil
 }
 
+// create updateEmailAndPassword
+func updateEmailAndPassword(username, email, password string) (models.User, error) {
+	// Connect to the MongoDB database
+	clientOptions := options.Client().ApplyURI(URI)
+	client, err := mongo.Connect(context.Background(), clientOptions)
+	if err != nil {
+		return models.User{}, err
+	}
+	defer client.Disconnect(context.Background())
+	
+	// Update the user's avatar URL in the database
+	_, err = usersCollection.UpdateOne(context.Background(), bson.M{"username": username}, bson.M{"$set": bson.M{"email": email, "password": password}})
+	if err != nil {
+		return models.User{}, err
+	}
+	
+	user, err:= getUser(username)
+	if(err != nil) {
+		return models.User{}, err
+	}
+	user.Email = email
+	user.Password = password
+
+
+	return user, nil
+}
+
+func editbyAdminHandler(w http.ResponseWriter, r *http.Request) {
+    // Check if the user is an admin
+    cookie, err := r.Cookie("username")
+    if err != nil {
+        http.Redirect(w, r, "/signin", http.StatusSeeOther)
+        return
+    }
+    username := cookie.Value
+    user, err := getUser(username)
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+    if user.Role != "admin" {
+        http.Error(w, "Unauthorized", http.StatusUnauthorized)
+        return
+    }
+
+    // Get the username, email, and password from the form data
+    usernameToUpdate := r.FormValue("username")
+    email := r.FormValue("email")
+    password := r.FormValue("password")
+
+    // Update the email and password of the user in the database
+    _,err = updateEmailAndPassword(usernameToUpdate, email, password)
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+
+    // Redirect the user back to the admin page
+    http.Redirect(w, r, "/admin", http.StatusSeeOther)
+}
+
+func editbyAdminHandler_old(w http.ResponseWriter, r *http.Request) {
+    // Check if the user is an admin
+    cookie, err := r.Cookie("username")
+    if err != nil {
+        http.Redirect(w, r, "/signin", http.StatusSeeOther)
+        return
+    }
+    username := cookie.Value
+    user, err := getUser(username)
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+    if user.Role != "admin" {
+        http.Error(w, "Unauthorized", http.StatusUnauthorized)
+        return
+    }
+
+    // Get the username to delete from the form data
+    usernameToEdit := r.FormValue("username")
+	
+
+	// Edit the user from the database
+	userEdit, err := getUser(usernameToEdit)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	// Handle form submission
+	if r.Method == "POST" {
+		// Parse the form data
+		err := r.ParseMultipartForm(32 << 20) // 32 MB
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+
+		// Update the user's information in the database
+		userEdit.FullName = r.FormValue("fullname")
+		userEdit.Email = r.FormValue("email")
+		userEdit.Age, err = strconv.Atoi(r.FormValue("age"))
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		userEdit.Bio = r.FormValue("bio")
+		userEdit.Role = r.FormValue("role")
+		err = updateUser(userEdit)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+
+		// Upload the new avatar file (if provided)
+		file, handler, err := r.FormFile("avatar")
+		if err == nil {
+			defer file.Close()
+			
+			// Save the file to disk
+			err = saveAvatarFile(userEdit.Username, handler.Filename, file)
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+
+			// Update the user's avatar URL in the database
+			userEdit.Avatar = fmt.Sprintf("/uploads/%s/%s", userEdit.Username, handler.Filename)
+			err = updateUser(userEdit)
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+		}
+
+	}
+
+	// Render the edit page with the user's information
+    tmpl, err := template.ParseFiles("./view/edit.html")
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+    err = tmpl.Execute(w, struct {
+        User models.User
+    }{
+        User: user,
+    })
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusInternalServerError)
+        return
+    }
+   
+    // Redirect the user back to the admin page
+    http.Redirect(w, r, "/admin", http.StatusSeeOther)
+}
 
 func editHandler(w http.ResponseWriter, r *http.Request) {
     // Get the user's username from the cookie
@@ -817,8 +1479,7 @@ func getUserMessages(username string) ([]models.Post, error) {
         messages = append(messages, message)
     }
 
-	fmt.Println("printing messages from user" + username)
-	fmt.Println(messages)
+
     
 
     return messages, nil
diff --git a/models/attachment.go b/models/attachment.go
new file mode 100644
index 0000000000000000000000000000000000000000..3f6f92aef8579cae950817e214e65a9a079f4833
--- /dev/null
+++ b/models/attachment.go
@@ -0,0 +1,11 @@
+package models
+
+import (
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Attachment struct {
+	ID       primitive.ObjectID `bson:"_id,omitempty"`
+	PostID	 primitive.ObjectID `bson:"postid"`
+	Description *string `json:"description"`
+}
diff --git a/models/private_message.go b/models/private_message.go
new file mode 100644
index 0000000000000000000000000000000000000000..d57b132fede627ccb81b7076bd0fe6f30c5af439
--- /dev/null
+++ b/models/private_message.go
@@ -0,0 +1,14 @@
+package models
+
+import (
+    "time"
+    "html/template"
+)
+
+type PrivateMessage struct {
+    ID        string    `bson:"_id,omitempty"`
+    Sender    string    `bson:"sender"`
+    Receiver  string    `bson:"receiver"`
+    Content   template.HTML    `bson:"content"`
+    Timestamp time.Time `bson:"timestamp"`
+}
\ No newline at end of file
diff --git a/output b/output
new file mode 100755
index 0000000000000000000000000000000000000000..af9ba38241307c9d14cc480e33b32b58495ef669
Binary files /dev/null and b/output differ
diff --git a/uploads/admin_rom.jpeg b/uploads/admin_rom.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..00eeca5138c54a4135aebb357c98d8885eec6acf
Binary files /dev/null and b/uploads/admin_rom.jpeg differ
diff --git a/uploads/testoo_hug-difficult.png b/uploads/testoo_hug-difficult.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e68b32495f5a850c444b967f3d22ce9f3dcc21a
Binary files /dev/null and b/uploads/testoo_hug-difficult.png differ
diff --git a/view/DM.html b/view/DM.html
new file mode 100644
index 0000000000000000000000000000000000000000..2263ddcf4e199e7c8ff1bf072c6cadb7eec4aecd
--- /dev/null
+++ b/view/DM.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Direct Messages</title>
+</head>
+
+<body>
+    <h1>Direct Messages</h1>
+    <form method="POST" action="/send-private-message">
+        <label for="receiver">To:</label>
+        <input type="text" name="receiver" required><br>
+        <label for="content">Message:</label>
+        <textarea name="content" required></textarea><br>
+        <button type="submit">Send</button>
+    </form>
+    <h2>Your Messages</h2>
+    <ul>
+        {{range .PrivateMessages}}
+        <li>
+            <p>From: {{.Sender}} To: {{.Receiver}}</p>
+            <p>Message: {{.Content}}</p>
+            <p>Time: {{.Timestamp}}</p>
+        </li>
+        {{end}}
+    </ul>
+    <a href="/profile">Back to Profile</a>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/admin.html b/view/admin.html
new file mode 100644
index 0000000000000000000000000000000000000000..6767df189a47761d8d991ee2a3a4ca7a086c6c74
--- /dev/null
+++ b/view/admin.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Admin</title>
+</head>
+
+<body>
+    <h1>Admin</h1>
+    <table>
+        <thead>
+            <tr>
+                <th>Username</th>
+                <th>Email</th>
+                <th>IsAdmin</th>
+                <th>Actions</th>
+            </tr>
+        </thead>
+        <tbody>
+            {{range .Users}}
+            <tr>
+                <td>{{.Username}}</td>
+                <td>{{.Email}}</td>
+                <td>{{.Role}}</td>
+                <td>
+                    <a href="/editbyadmin?username={{.Username}}">Edit</a>
+                    <a href="/delete?username={{.Username}}">Delete/Disable</a>
+                    <a href="/reset?username={{.Username}}">Reset Password</a>
+                </td>
+            </tr>
+            {{end}}
+        </tbody>
+    </table>
+    <a href="/profile">Back to Home</a>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/delete.html b/view/delete.html
new file mode 100644
index 0000000000000000000000000000000000000000..7064a79c0c8e85d617dbcab4be10e00b348f5d38
--- /dev/null
+++ b/view/delete.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Admin</title>
+</head>
+
+<body>
+    <h1>Admin</h1>
+    <table>
+        <thead>
+            <tr>
+                <th>Username</th>
+                <th>Email</th>
+                <th>IsAdmin</th>
+                <th>Actions</th>
+            </tr>
+        </thead>
+        <tbody>
+            {{range .Users}}
+            <tr>
+                <td>{{.Username}}</td>
+                <td>{{.Email}}</td>
+                <td>{{.IsAdmin}}</td>
+                <td>
+                    <a href="/edit?username={{.Username}}">Edit</a>
+                    <a href="/delete?username={{.Username}}">Delete/Disable</a>
+                    <a href="/reset?username={{.Username}}">Reset Password</a>
+                </td>
+            </tr>
+            {{end}}
+        </tbody>
+    </table>
+    <a href="/">Back to Home</a>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/edit.html b/view/edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..7179c0355c25625ad3a9e7418abb6c7e3d0efa97
--- /dev/null
+++ b/view/edit.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Edit Profile</title>
+</head>
+
+<body>
+    <h1>Edit Profile</h1>
+    <form action="/edit" method="post" enctype="multipart/form-data">
+        <label for="fullname">Full Name:</label>
+        <input type="text" id="fullname" name="fullname" value="{{.User.FullName}}"><br><br>
+        <label for="email">Email:</label>
+        <input type="email" id="email" name="email" value="{{.User.Email}}"><br><br>
+        <label for="avatar">Avatar:</label>
+        <input type="file" id="avatar" name="avatar"><br><br>
+        <input type="submit" value="Save">
+    </form>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/editbyadmin.html b/view/editbyadmin.html
new file mode 100644
index 0000000000000000000000000000000000000000..2cdf7144b3857009b6b0c51338ba37baa5ec7f96
--- /dev/null
+++ b/view/editbyadmin.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Edit User by Admin</title>
+</head>
+
+<body>
+    <h1>Edit User by Admin</h1>
+    <form method="POST" action="/editbyadmin">
+        <input type="hidden" name="username" value="{{.Username}}">
+        <label for="email">Email:</label>
+        <input type="email" name="email" value="{{.Email}}" required><br>
+        <label for="password">New Password:</label>
+        <input type="password" name="password" required><br>
+        <button type="submit">Save</button>
+        <a href="/admin">Cancel</a>
+    </form>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/generate_API.html b/view/generate_API.html
new file mode 100644
index 0000000000000000000000000000000000000000..9b6d75702e6bc746e06c61e0a0d07bf6dba352c9
--- /dev/null
+++ b/view/generate_API.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Generate API Token</title>
+</head>
+
+<body>
+    <h1>Your API Token</h1>
+    <p id="token"></p>
+    <button onclick="generateAPIToken()">Generate API Token</button>
+
+    <script>
+        function generateAPIToken() {
+            fetch('/api/generate-token', {
+                method: 'GET',
+                credentials: 'include', // Include cookies
+            })
+                .then(response => response.text())
+                .then(token => {
+                    document.getElementById('token').textContent = 'Your new API token is: ' + token;
+                })
+                .catch(error => {
+                    console.error('Error:', error);
+                });
+        }
+    </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/messages.html b/view/messages.html
new file mode 100644
index 0000000000000000000000000000000000000000..858481df7d3ff7d3a473fc08bc0745819391715a
--- /dev/null
+++ b/view/messages.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Messages</title>
+</head>
+
+
+<body>
+    <h1>Messages</h1>
+    <ul>
+        {{range .Messages}}
+        <li>{{.Title}}</li>
+        <p>{{.Content}}</p>
+        <p>{{.Username}}</p>
+        <p>{{.CreatedAt}}</p>
+        {{end}}
+    </ul>
+    <a href="/profile">Back to Profile</a>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/profile.html b/view/profile.html
index 727589aed683c6f4f088e36462f618964664e18a..104ab2ed1a0e82a17df7006ac5114c50d7de3d6c 100644
--- a/view/profile.html
+++ b/view/profile.html
@@ -109,12 +109,14 @@
     <a href="/messages">Messages</a>
     <h2>Avatar</h2>
     {{if .User.Avatar}}
-    <img src="/uploads/{{.User.Avatar}}" alt="avatar" class="profile-photo">
+    <img src="/uploads/" {{.User.Avatar}} alt="avatar" class="profile-photo">
     {{else}}
     <img src="https://mstd.dansmonorage.blue/system/site_uploads/files/000/000/002/original/mascot.png" alt="avatar"
         class="profile-photo">
     {{end}}
     <a href="/edit?username={{.User.Username}}">EditProfile</a>
+    <a href="/generate-api-token">Generate API Token</a>
+
 
     <a href="/admin">Admin</a>