diff --git a/.gitignore b/.gitignore
index af1682391a296805c7e98e14e0626b0f50118ea6..a6902832f325541bb40c94e75d382ac5fd86260d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 vestibule
 __debug_bin
 miscellaneous/mock_onlyoffice/data
+data
\ No newline at end of file
diff --git a/data/test.db b/data/test.db
index 63e82905f495f41d3f1acdcacdfc0c12b7eed19b..8616989263916b184bb39769ac9d9f20f3a3e14e 100644
Binary files a/data/test.db and b/data/test.db differ
diff --git a/data/users.db b/data/users.db
index 1fd01c942aefe82b974eb7234f74ad9f15356dd3..e9762194df4f577e3e5737e17077abe89a10a2e7 100644
Binary files a/data/users.db and b/data/users.db differ
diff --git a/internal/mocks/mocks.go b/internal/mocks/mocks.go
index b8af888e350b26a2731ffe173df15bb7f2cdeb1b..9ccdf8144df115be8922e8ed290728cbe8f59b3f 100644
--- a/internal/mocks/mocks.go
+++ b/internal/mocks/mocks.go
@@ -10,6 +10,9 @@ import (
 	"github.com/nicolaspernoud/vestibule/pkg/middlewares"
 )
 
+const literralContentType = "Content-Type"
+const literralApplicationJson = "application/json"
+
 var (
 	hostname = os.Getenv("HOSTNAME")
 	port     string
@@ -38,12 +41,12 @@ func CreateMockOAuth2() *http.ServeMux {
 
 	// Returns access token back to the user
 	mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+		w.Header().Set(literralContentType, "application/x-www-form-urlencoded")
 		w.Write([]byte("access_token=mocktoken&scope=user&token_type=bearer"))
 	})
 	// Returns userinfo back to the user
 	mux.HandleFunc("/userinfo", func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/json")
+		w.Header().Set(literralContentType, literralApplicationJson)
 		w.Write([]byte(`{
 			"displayName": "Us ER",
 			"memberOf": [
@@ -56,7 +59,7 @@ func CreateMockOAuth2() *http.ServeMux {
 	})
 	// Returns userinfo back to the user (with an admin user)
 	mux.HandleFunc("/admininfo", func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/json")
+		w.Header().Set(literralContentType, literralApplicationJson)
 		w.Write([]byte(`{
 			"displayName": "Ad MIN",
 			"memberOf": [
@@ -82,7 +85,7 @@ func CreateMockAPI() *http.ServeMux {
 	frameSource := "https://static." + hostname + ":" + port
 	mux.Handle("/", middlewares.Cors(func() http.Handler {
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			w.Header().Set("Content-Type", "application/json")
+			w.Header().Set(literralContentType, literralApplicationJson)
 			w.Write([]byte(`{
 				"foo": "bar",
 				"bar": "foo"
diff --git a/internal/models/bankAccounts.go b/internal/models/bankAccounts.go
index 7e7d17da23ea28217571dde2874f76357695b6a9..c3164f16cf2eeefb72080f4201a1f721b778558a 100644
--- a/internal/models/bankAccounts.go
+++ b/internal/models/bankAccounts.go
@@ -16,128 +16,228 @@ func (d *DataHandler) HandleBankAccounts(w http.ResponseWriter, r *http.Request)
 	case "GET":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			if id != 0 {
-				var o BankAccount
-				if err := d.db.Preload("Operations").First(&o, id).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				var o []BankAccount
-				d.db.Preload("Operations").Find(&o)
-				json.NewEncoder(w).Encode(o)
-			}
+			d.getBankAccountAdmin(w, r, id)
 		case "BANKER":
-			user := d.getLoggedUser(w, r).(UserBanker)
-			if id != 0 {
-				var o BankAccount
-				if err := d.db.Preload("Operations").First(&o, id).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				// Check that the bank account belong to a one of the banker's client
-				var userClient UserClient
-				if err := d.db.Where("id = ? and user_banker_id = ?", o.UserClientID, user.ID).First(&userClient).Error; err != nil {
-					http.Error(w, "You can not access this ressource", http.StatusForbidden)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				var o []BankAccount
-				d.db.Preload("Operations").Where("user_client_id IN (?)", d.db.Table("user_clients").Select("id").Where("user_banker_id = ?", user.ID).QueryExpr()).Find(&o)
-				json.NewEncoder(w).Encode(o)
-			}
+			d.getBankAccountBanker(w, r, id)
 		case "CLIENT":
-			user := d.getLoggedUser(w, r).(UserClient)
-			if id != 0 {
-				var o BankAccount
-				if err := d.db.Preload("Operations").Where("id = ? AND user_client_id = ?", id, user.ID).First(&o).Error; err != nil {
-					http.Error(w, "You can not access this ressource", http.StatusForbidden)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				var o []BankAccount
-				d.db.Preload("Operations").Where("user_client_id = ?", user.ID).Find(&o)
-				json.NewEncoder(w).Encode(o)
-			}
+			d.getBankAccountClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	case "POST":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			var o BankAccount
-			err := json.NewDecoder(r.Body).Decode(&o)
-			if err != nil {
-				http.Error(w, err.Error(), http.StatusInternalServerError)
-			}
-			if o.UserClientID != 0 {
-				d.db.Create(&o)
-			} else {
-				http.Error(w, "id of UserClient is missing", http.StatusNotFound)
-			}
+			d.postBankAccountAdmin(w, r, id)
 		case "BANKER":
-			user := d.getLoggedUser(w, r).(UserBanker)
-			var o BankAccount
-			err := json.NewDecoder(r.Body).Decode(&o)
-			if err != nil {
-				http.Error(w, err.Error(), http.StatusInternalServerError)
-			}
-
-			if o.UserClientID != 0 {
-				var userClient UserClient
-				if err := d.db.Where("id = ? and user_banker_id = ?", o.UserClientID, user.ID).First(&userClient).Error; err != nil {
-					http.Error(w, "You can not access this ressource", http.StatusForbidden)
-					return
-				}
-
-				d.db.Create(&o)
-			} else {
-				http.Error(w, "id of UserClient is missing", http.StatusNotFound)
-			}
+			d.postBankAccountBanker(w, r, id)
 		case "CLIENT":
-			http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
+			d.postBankAccountClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
+		}
+	case "PUT":
+		switch auth.GetLoggedUserTechnical(w, r).Role {
+		case "ADMIN":
+			d.putBankAccountAdmin(w, r, id)
+		case "BANKER":
+			d.putBankAccountBanker(w, r, id)
+		case "CLIENT":
+			d.putBankAccountClient(w, r, id)
+		default:
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	case "DELETE":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			if id != 0 {
-				var o BankAccount
-				if err := d.db.First(&o, id).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				d.db.Delete(&o)
-			} else {
-				http.Error(w, "id is missing", http.StatusNotFound)
-			}
+			d.deleteBankAccountAdmin(w, r, id)
 		case "BANKER":
-			user := d.getLoggedUser(w, r).(UserBanker)
-			if id != 0 {
-				var o BankAccount
-				if err := d.db.First(&o, id).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				var userClient UserClient
-				if err := d.db.Where("id = ? and user_banker_id = ?", o.UserClientID, user.ID).First(&userClient).Error; err != nil {
-					http.Error(w, "You can not access this ressource", http.StatusForbidden)
-					return
-				}
-				d.db.Delete(&o)
-			} else {
-				http.Error(w, "id is missing", http.StatusNotFound)
-			}
+			d.deleteBankAccountBanker(w, r, id)
 		case "CLIENT":
-			http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
+			d.deleteBankAccountClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	default:
 		http.Error(w, "method not allowed", 400)
 	}
 }
+
+func (d *DataHandler) getBankAccountAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o BankAccount
+		if err := d.db.Preload("Operations").First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDDoesNotExist, http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []BankAccount
+		d.db.Preload("Operations").Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) getBankAccountBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	if id != 0 {
+		var o BankAccount
+		if err := d.db.Preload("Operations").First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		// Check that the bank account belong to a one of the banker's client
+		var userClient UserClient
+		if err := d.db.Where(reqIDAndBankerID, o.UserClientID, user.ID).First(&userClient).Error; err != nil {
+			http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []BankAccount
+		d.db.Preload("Operations").Where("user_client_id IN (?)", d.db.Table("user_clients").Select("id").Where("user_banker_id = ?", user.ID).QueryExpr()).Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) getBankAccountClient(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserClient)
+	if id != 0 {
+		var o BankAccount
+		if err := d.db.Preload("Operations").Where("id = ? AND user_client_id = ?", id, user.ID).First(&o).Error; err != nil {
+			http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []BankAccount
+		d.db.Preload("Operations").Where("user_client_id = ?", user.ID).Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) postBankAccountAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	var o BankAccount
+	err := json.NewDecoder(r.Body).Decode(&o)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	if o.UserClientID == 0 {
+		http.Error(w, ErrorUserIDIsMissing, http.StatusInternalServerError)
+	}
+	d.db.Create(&o)
+	d.db.Last(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) postBankAccountBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	var o BankAccount
+	err := json.NewDecoder(r.Body).Decode(&o)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+
+	if o.UserClientID == 0 {
+		http.Error(w, ErrorUserIDIsMissing, http.StatusInternalServerError)
+
+	}
+	var userClient UserClient
+	if err := d.db.Where(reqIDAndBankerID, o.UserClientID, user.ID).First(&userClient).Error; err != nil {
+		http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+		return
+	}
+
+	d.db.Create(&o)
+	d.db.Last(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) postBankAccountClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
+
+func (d *DataHandler) putBankAccountAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	var o BankAccount
+	if err := d.db.Preload("Operations").First(&o, id).Error; err != nil {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+		return
+	}
+	var bankAccount BankAccount
+	err := json.NewDecoder(r.Body).Decode(&bankAccount)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	o.BankOverdraft = bankAccount.BankOverdraft
+	o.Type = bankAccount.Type
+	if o.UserClientID == 0 {
+		http.Error(w, ErrorUserIDIsMissing, http.StatusInternalServerError)
+	}
+	d.db.Save(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) putBankAccountBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	var o BankAccount
+	if err := d.db.Preload("Operations").First(&o, id).Error; err != nil {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+		return
+	}
+	var bankAccount BankAccount
+	err := json.NewDecoder(r.Body).Decode(&bankAccount)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	o.BankOverdraft = bankAccount.BankOverdraft
+	o.Type = bankAccount.Type
+	if o.UserClientID == 0 {
+		http.Error(w, ErrorUserIDIsMissing, http.StatusInternalServerError)
+	}
+	var userClient UserClient
+	if err := d.db.Where(reqIDAndBankerID, o.UserClientID, user.ID).First(&userClient).Error; err != nil {
+		http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+		return
+	}
+	d.db.Save(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) putBankAccountClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
+
+func (d *DataHandler) deleteBankAccountAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o BankAccount
+		if err := d.db.First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		d.db.Delete(&o)
+	} else {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+	}
+}
+
+func (d *DataHandler) deleteBankAccountBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	if id != 0 {
+		var o BankAccount
+		if err := d.db.First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		var userClient UserClient
+		if err := d.db.Where(reqIDAndBankerID, o.UserClientID, user.ID).First(&userClient).Error; err != nil {
+			http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+			return
+		}
+		d.db.Delete(&o)
+	} else {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+	}
+}
+
+func (d *DataHandler) deleteBankAccountClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
diff --git a/internal/models/bankers.go b/internal/models/bankers.go
index e78875c12ceec3f9a1c97a2e81542a20535b58bc..f0383677337e55b9b155185ea73724b259cfd6fd 100644
--- a/internal/models/bankers.go
+++ b/internal/models/bankers.go
@@ -16,89 +16,159 @@ func (d *DataHandler) HandleBankers(w http.ResponseWriter, r *http.Request) {
 	case "GET":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			if id != 0 {
-				var o UserBanker
-				if err := d.db.Preload("UserClients").Where("id = ?", id).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				var o []UserBanker
-				d.db.Preload("UserClients").Find(&o)
-				json.NewEncoder(w).Encode(o)
-			}
+			d.getBankerAdmin(w, r, id)
 		case "BANKER":
-			user := d.getLoggedUser(w, r).(UserBanker)
-			if id != 0 {
-				var o UserBanker
-				if err := d.db.Preload("UserClients").Where("id = ?", id).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				if o.ID != user.ID {
-					http.Error(w, "You can not access this ressource", http.StatusForbidden)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				http.Error(w, "You can not access this ressource", http.StatusForbidden)
-			}
+			d.getBankerBanker(w, r, id)
 		case "CLIENT":
-			user := d.getLoggedUser(w, r).(UserClient)
-			if id != 0 && int(user.ID) == id {
-				var userClient UserClient
-				if err := d.db.Where("user_id = ?", user.ID).First(&userClient).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				var o UserBanker
-				if err := d.db.Where("id = ?", userClient.UserBankerID).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				http.Error(w, "You can not access this ressource", http.StatusForbidden)
-			}
+			d.getBankerClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	case "POST":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			var o UserBanker
-			err := json.NewDecoder(r.Body).Decode(&o)
-			if err != nil {
-				http.Error(w, err.Error(), http.StatusInternalServerError)
-			}
-			d.db.Create(&o)
+			d.postBankerAdmin(w, r, id)
 		case "BANKER", "CLIENT":
-			http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
+			d.postBankerClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 
+	case "PUT":
+		switch auth.GetLoggedUserTechnical(w, r).Role {
+		case "ADMIN":
+			d.putBankerAdmin(w, r, id)
+		case "BANKER", "CLIENT":
+			d.putBankerClient(w, r, id)
+		default:
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
+		}
 	case "DELETE":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			if id != 0 {
-				var o UserBanker
-				if err := d.db.First(&o, id).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				d.db.Delete(&o)
-			} else {
-				http.Error(w, "id is missing", http.StatusNotFound)
-			}
+			d.deleteBankerAdmin(w, r, id)
 		case "BANKER", "CLIENT":
-			http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
+			d.deleteBankerClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 
 	default:
 		http.Error(w, "method not allowed", 400)
 	}
 }
+
+func (d *DataHandler) getBankerAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o UserBanker
+		if err := d.db.Preload("UserClients").Where(reqID, id).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []UserBanker
+		d.db.Preload("UserClients").Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) getBankerBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	if id != 0 {
+		var o UserBanker
+		if err := d.db.Preload("UserClients").Where(reqID, id).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		if o.ID != user.ID {
+			http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+	}
+}
+
+func (d *DataHandler) getBankerClient(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserClient)
+	if id != 0 && int(user.ID) == id {
+		var userClient UserClient
+		if err := d.db.Where(reqUserID, user.ID).First(&userClient).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		var o UserBanker
+		if err := d.db.Where(reqID, userClient.UserBankerID).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+	}
+}
+
+func (d *DataHandler) postBankerAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	var o UserBanker
+	err := json.NewDecoder(r.Body).Decode(&o)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	// check userID is not already present in DB
+	var client UserClient
+	if err := d.db.Where(reqUserID, o.UserID).First(&client).Error; err == nil {
+		http.Error(w, "UserID is already bind to a Client", http.StatusNotFound)
+		return
+	}
+	var banker UserBanker
+	if err := d.db.Where(reqUserID, o.UserID).First(&banker).Error; err == nil {
+		http.Error(w, "UserID is already bind to a Banker", http.StatusNotFound)
+		return
+	}
+	d.db.Create(&o)
+	d.db.Last(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) postBankerClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
+
+func (d *DataHandler) putBankerAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	var o UserBanker
+	if err := d.db.Preload("UserClients").Where(reqID, id).First(&o).Error; err != nil {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+		return
+	}
+	var updatedBanker UserBanker
+	err := json.NewDecoder(r.Body).Decode(&updatedBanker)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	o.Name = updatedBanker.Name
+	d.db.Save(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) putBankerClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
+
+func (d *DataHandler) deleteBankerAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o UserBanker
+		if err := d.db.First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		d.db.Delete(&o)
+	} else {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+	}
+}
+
+func (d *DataHandler) deleteBankerClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
diff --git a/internal/models/clients.go b/internal/models/clients.go
index a58b1ad1fdedf66fb6c7dba5276dddebc9fbef96..996269427593b9c5bef1cb425279c0c64f1ec773 100644
--- a/internal/models/clients.go
+++ b/internal/models/clients.go
@@ -17,120 +17,221 @@ func (d *DataHandler) HandleClients(w http.ResponseWriter, r *http.Request) {
 
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			if id != 0 {
-				var o UserClient
-				if err := d.db.Preload("BankAccounts").Where("id = ?", id).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				var o []UserClient
-				d.db.Preload("BankAccounts").Find(&o)
-				json.NewEncoder(w).Encode(o)
-			}
+			d.getClientAdmin(w, r, id)
 		case "BANKER":
-			user := d.getLoggedUser(w, r).(UserBanker)
-			if id != 0 {
-				var o UserClient
-				if err := d.db.Preload("BankAccounts").Where("id = ?", id).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				if o.UserBankerID != user.ID {
-					http.Error(w, "You can not access this ressource", http.StatusForbidden)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				var o []UserClient
-				d.db.Preload("BankAccounts").Find(&o)
-				json.NewEncoder(w).Encode(o)
-			}
+			d.getClientBanker(w, r, id)
 		case "CLIENT":
-			user := d.getLoggedUser(w, r).(UserClient)
-			if id != 0 && int(user.ID) == id {
-				var o UserClient
-				if err := d.db.Preload("BankAccounts").Where("id = ?", id).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else if id == 0 {
-				var o []UserClient
-				d.db.Preload("BankAccounts").Where("id = ?", user.ID).Find(&o)
-				json.NewEncoder(w).Encode(o)
-			} else {
-				http.Error(w, "You can not access this ressource", http.StatusForbidden)
-				return
-			}
+			d.getClientClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	case "POST":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			var o UserClient
-			err := json.NewDecoder(r.Body).Decode(&o)
-			if err != nil {
-				http.Error(w, err.Error(), http.StatusInternalServerError)
-			}
-			d.db.Create(&o)
+			d.postClientAdmin(w, r, id)
 		case "BANKER":
-			user := d.getLoggedUser(w, r).(UserBanker)
-			var o UserClient
-			err := json.NewDecoder(r.Body).Decode(&o)
-			if err != nil {
-				http.Error(w, err.Error(), http.StatusInternalServerError)
-			}
-			o.UserBankerID = user.ID
-			d.db.Create(&o)
+			d.postClientBanker(w, r, id)
 		case "CLIENT":
-			http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
+			d.postClientClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
+		}
+	case "PUT":
+		switch auth.GetLoggedUserTechnical(w, r).Role {
+		case "ADMIN":
+			d.putClientAdmin(w, r, id)
+		case "BANKER":
+			d.putClientBanker(w, r, id)
+		case "CLIENT":
+			d.putClientClient(w, r, id)
+		default:
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	case "DELETE":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN":
-			if id != 0 {
-				var o UserClient
-				if err := d.db.Where("id = ?", id).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				// Delete bank accounts of user
-				d.db.Where("user_client_id = ?", o.ID).Delete(&BankAccount{})
-
-				d.db.Delete(&o)
-			} else {
-				http.Error(w, "id is missing", http.StatusNotFound)
-			}
+			d.deleteClientAdmin(w, r, id)
 		case "BANKER":
-			user := d.getLoggedUser(w, r).(UserBanker)
-			if id != 0 {
-				var o UserClient
-				if err := d.db.Where("id = ?", id).First(&o).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				if o.UserBankerID != user.ID {
-					http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
-					return
-				}
-				// Delete bank accounts of user
-				d.db.Where("user_client_id = ?", o.ID).Delete(&BankAccount{})
-
-				d.db.Delete(&o)
-			} else {
-				http.Error(w, "id is missing", http.StatusNotFound)
-			}
+			d.deleteClientBanker(w, r, id)
 		case "CLIENT":
-			http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
+			d.deleteClientClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	default:
 		http.Error(w, "method not allowed", 400)
 	}
 }
+
+func (d *DataHandler) getClientAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o UserClient
+		if err := d.db.Preload("BankAccounts").Where(reqID, id).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []UserClient
+		d.db.Preload("BankAccounts").Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) getClientBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	if id != 0 {
+		var o UserClient
+		if err := d.db.Preload("BankAccounts").Where(reqID, id).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		if o.UserBankerID != user.ID {
+			http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []UserClient
+		d.db.Preload("BankAccounts").Where("user_banker_id = ?", user.ID).Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) getClientClient(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserClient)
+	if id != 0 && int(user.ID) == id {
+		var o UserClient
+		if err := d.db.Preload("BankAccounts").Where(reqID, id).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else if id == 0 {
+		var o []UserClient
+		d.db.Preload("BankAccounts").Where(reqID, user.ID).Find(&o)
+		json.NewEncoder(w).Encode(o)
+	} else {
+		http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
+		return
+	}
+}
+
+func (d *DataHandler) postClientAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	var o UserClient
+	err := json.NewDecoder(r.Body).Decode(&o)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	// check userID is not already present in DB
+	var client UserClient
+	if err := d.db.Where(reqUserID, o.UserID).First(&client).Error; err == nil {
+		http.Error(w, "UserID is already bind to a Client", http.StatusNotFound)
+		return
+	}
+	var banker UserBanker
+	if err := d.db.Where(reqUserID, o.UserID).First(&banker).Error; err == nil {
+		http.Error(w, "UserID is already bind to a Banker", http.StatusNotFound)
+		return
+	}
+	d.db.Create(&o)
+	d.db.Last(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) postClientBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	var o UserClient
+	err := json.NewDecoder(r.Body).Decode(&o)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	o.UserBankerID = user.ID
+	d.db.Create(&o)
+	d.db.Last(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) postClientClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
+
+func (d *DataHandler) putClientAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	var o UserClient
+	if err := d.db.Preload("BankAccounts").Where(reqID, id).First(&o).Error; err != nil {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+		return
+	}
+	var updatedUser UserClient
+	err := json.NewDecoder(r.Body).Decode(&updatedUser)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	o.Name = updatedUser.Name
+	o.UserBankerID = updatedUser.UserBankerID
+	d.db.Save(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) putClientBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	var o UserClient
+	if err := d.db.Preload("BankAccounts").Where(reqID, id).First(&o).Error; err != nil {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+		return
+	}
+	var updatedUser UserClient
+	err := json.NewDecoder(r.Body).Decode(&updatedUser)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	o.Name = updatedUser.Name
+	o.UserBankerID = user.ID
+	d.db.Save(&o)
+	json.NewEncoder(w).Encode(o)
+}
+
+func (d *DataHandler) putClientClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
+
+func (d *DataHandler) deleteClientAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o UserClient
+		if err := d.db.Where(reqID, id).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		// Delete bank accounts of user
+		d.db.Where("user_client_id = ?", o.ID).Delete(&BankAccount{})
+
+		d.db.Delete(&o)
+	} else {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+	}
+}
+
+func (d *DataHandler) deleteClientBanker(w http.ResponseWriter, r *http.Request, id int) {
+	user := d.getLoggedUser(w, r).(UserBanker)
+	if id != 0 {
+		var o UserClient
+		if err := d.db.Where(reqID, id).First(&o).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		if o.UserBankerID != user.ID {
+			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+			return
+		}
+		// Delete bank accounts of user
+		d.db.Where("user_client_id = ?", o.ID).Delete(&BankAccount{})
+
+		d.db.Delete(&o)
+	} else {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+	}
+}
+
+func (d *DataHandler) deleteClientClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
diff --git a/internal/models/models.go b/internal/models/models.go
index 6ab1dbfbd58002a3cbc1893a9ae7f8ccc724592a..3a812bce2d8b1fc41270da61b56f4578989b497d 100644
--- a/internal/models/models.go
+++ b/internal/models/models.go
@@ -17,6 +17,28 @@ type DataHandler struct {
 	db *gorm.DB
 }
 
+// ErrorIDDoesNotExist = "id does not exist"
+const ErrorIDDoesNotExist = "id does not exist"
+
+// ErrorIDIsMissing = "id is missing"
+const ErrorIDIsMissing = "id is missing"
+
+// ErrorCannotAccessRessource = "You can not access this ressource"
+const ErrorCannotAccessRessource = "You can not access this ressource"
+
+// ErrorRoleOfLoggedUser = "Could not get role of logged user"
+const ErrorRoleOfLoggedUser = "Could not get role of logged user"
+
+// ErrorNotAuthorizeMethodOnRessource = "You're not authorize to execute this method on this ressource."
+const ErrorNotAuthorizeMethodOnRessource = "You're not authorize to execute this method on this ressource."
+
+// ErrorUserIDIsMissing = "id of UserClient is missing"
+const ErrorUserIDIsMissing = "id of UserClient is missing"
+
+const reqID = "id = ?"
+const reqUserID = "user_id = ?"
+const reqIDAndBankerID = "id = ? and user_banker_id = ?"
+
 // NewDataHandler init a DataHandler and returns a pointer to it
 func NewDataHandler() *DataHandler {
 	db, err := gorm.Open("sqlite3", "./data/test.db")
@@ -57,7 +79,7 @@ type UserClient struct {
 	CreatedAt    time.Time  `json:"-"`
 	UpdatedAt    time.Time  `json:"-"`
 	DeletedAt    *time.Time `json:"-"`
-	UserID       int
+	UserID       int        `gorm:"not null;unique"`
 	Name         string
 	UserBankerID uint
 	BankAccounts []BankAccount
@@ -69,7 +91,7 @@ type UserBanker struct {
 	CreatedAt   time.Time  `json:"-"`
 	UpdatedAt   time.Time  `json:"-"`
 	DeletedAt   *time.Time `json:"-"`
-	UserID      int
+	UserID      int        `gorm:"not null;unique"`
 	Name        string
 	UserClients []UserClient
 }
@@ -104,19 +126,19 @@ func (d *DataHandler) getLoggedUser(w http.ResponseWriter, r *http.Request) inte
 	user := auth.GetLoggedUserTechnical(w, r)
 	if user.Role != "" && (user.Role == "BANKER") {
 		var o UserBanker
-		if err := d.db.Where("user_id = ?", user.ID).First(&o).Error; err != nil {
+		if err := d.db.Where(reqUserID, user.ID).First(&o).Error; err != nil {
 			o := UserBanker{UserID: user.ID, Name: user.Login}
 			d.db.Create(&o)
-			d.db.Where("user_id = ?", user.ID).First(&o)
+			d.db.Where(reqUserID, user.ID).First(&o)
 			return o
 		}
 		return o
 	} else if user.Role != "" && (user.Role == "CLIENT") {
 		var o UserClient
-		if err := d.db.Where("user_id = ?", user.ID).First(&o).Error; err != nil {
+		if err := d.db.Where(reqUserID, user.ID).First(&o).Error; err != nil {
 			o := UserClient{UserID: user.ID, Name: user.Login}
 			d.db.Create(&o)
-			d.db.Where("user_id = ?", user.ID).First(&o)
+			d.db.Where(reqUserID, user.ID).First(&o)
 			return o
 		}
 
diff --git a/internal/models/operations.go b/internal/models/operations.go
index f3793bb30ad86f4294be2c80ed624e62f0798596..90114c589c804a8c9d9f74818b16f9e03726256e 100644
--- a/internal/models/operations.go
+++ b/internal/models/operations.go
@@ -17,108 +17,123 @@ func (d *DataHandler) HandleOperations(w http.ResponseWriter, r *http.Request) {
 	case "GET":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN", "BANKER", "CLIENT":
-			if id != 0 {
-				var o Operation
-				if err := d.db.First(&o, id).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				json.NewEncoder(w).Encode(o)
-			} else {
-				var o []Operation
-				d.db.Find(&o)
-				json.NewEncoder(w).Encode(o)
-			}
+			d.getOperationClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	case "POST":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN", "BANKER", "CLIENT":
-			var o Operation
-			err := json.NewDecoder(r.Body).Decode(&o)
-			if err != nil {
-				http.Error(w, err.Error(), http.StatusInternalServerError)
-			}
-
-			var debtor BankAccount
-			var creditor BankAccount
-			if err := d.db.Where("id = ?", o.Debtor).First(&debtor).Error; err != nil {
-				http.Error(w, "Can not find debtor account", http.StatusInternalServerError)
-				return
-			}
-			if err := d.db.First(&creditor, o.Creditor).Error; err != nil {
-				http.Error(w, "Can not find creditor account", http.StatusInternalServerError)
-				return
-			}
-			if (debtor.Amount + o.Amount) <= debtor.BankOverdraft {
-				http.Error(w, "Not enough money", http.StatusExpectationFailed)
-				return
-			}
-			// Update BankAccounts
-			debtor.Amount += o.Amount
-			creditor.Amount -= o.Amount
-			d.db.Save(&debtor)
-			d.db.Save(&creditor)
-
-			now := time.Now()
-			o.Date = now
-			d.db.Create(&o)
-
-			// Add the operation to creditor
-			op := Operation{
-				Debtor:   o.Creditor,
-				Amount:   -o.Amount,
-				Date:     now,
-				Creditor: o.Debtor,
-			}
-			d.db.Create(&op)
-
+			d.postOperationClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 
 	case "DELETE":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
 		case "ADMIN", "BANKER":
-			if id != 0 {
-				var o Operation
-				if err := d.db.First(&o, id).Error; err != nil {
-					http.Error(w, "id does not exist", http.StatusNotFound)
-					return
-				}
-				// update BankAccounts
-				var debtor BankAccount
-				var creditor BankAccount
-				if err := d.db.First(&debtor, o.Debtor).Error; err == nil {
-					if err := d.db.First(&creditor, o.Creditor).Error; err == nil {
-						// Update BankAccounts
-						debtor.Amount -= o.Amount
-						creditor.Amount += o.Amount
-						d.db.Save(&debtor)
-						d.db.Save(&creditor)
-
-						// Get the operation of the creditor
-						var op Operation
-						if err := d.db.First(&op, id+1).Error; err != nil {
-							http.Error(w, "id does not exist", http.StatusNotFound)
-							return
-						}
-
-						// Delete the operations
-						d.db.Delete(&o)
-						d.db.Delete(&op)
-					}
-				}
-			} else {
-				http.Error(w, "id is missing", http.StatusNotFound)
-			}
+			d.deleteOperationBanker(w, r, id)
 		case "CLIENT":
-			http.Error(w, "You're not authorize to execute this method on this ressource.", http.StatusMethodNotAllowed)
+			d.deleteOperationClient(w, r, id)
 		default:
-			http.Error(w, "Could not get role of logged user", http.StatusInternalServerError)
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
 		}
 	default:
 		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
 	}
 }
+
+func (d *DataHandler) getOperationClient(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o Operation
+		if err := d.db.First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDDoesNotExist, http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []Operation
+		d.db.Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) postOperationClient(w http.ResponseWriter, r *http.Request, id int) {
+	var o Operation
+	err := json.NewDecoder(r.Body).Decode(&o)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+
+	var debtor BankAccount
+	var creditor BankAccount
+	if err := d.db.Where(reqID, o.Debtor).First(&debtor).Error; err != nil {
+		http.Error(w, "Can not find debtor account", http.StatusInternalServerError)
+		return
+	}
+	if err := d.db.First(&creditor, o.Creditor).Error; err != nil {
+		http.Error(w, "Can not find creditor account", http.StatusInternalServerError)
+		return
+	}
+	if (debtor.Amount + o.Amount) <= debtor.BankOverdraft {
+		http.Error(w, "Not enough money", http.StatusExpectationFailed)
+		return
+	}
+	// Update BankAccounts
+	debtor.Amount += o.Amount
+	creditor.Amount -= o.Amount
+	d.db.Save(&debtor)
+	d.db.Save(&creditor)
+
+	now := time.Now()
+	o.Date = now
+	d.db.Create(&o)
+
+	// Add the operation to creditor
+	op := Operation{
+		Debtor:   o.Creditor,
+		Amount:   -o.Amount,
+		Date:     now,
+		Creditor: o.Debtor,
+	}
+	d.db.Create(&op)
+}
+
+func (d *DataHandler) deleteOperationBanker(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o Operation
+		if err := d.db.First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		// update BankAccounts
+		var debtor BankAccount
+		var creditor BankAccount
+		if err := d.db.First(&debtor, o.Debtor).Error; err == nil {
+			if err := d.db.First(&creditor, o.Creditor).Error; err == nil {
+				// Update BankAccounts
+				debtor.Amount -= o.Amount
+				creditor.Amount += o.Amount
+				d.db.Save(&debtor)
+				d.db.Save(&creditor)
+
+				// Get the operation of the creditor
+				var op Operation
+				if err := d.db.First(&op, id+1).Error; err != nil {
+					http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+					return
+				}
+
+				// Delete the operations
+				d.db.Delete(&o)
+				d.db.Delete(&op)
+			}
+		}
+	} else {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+	}
+}
+
+func (d *DataHandler) deleteOperationClient(w http.ResponseWriter, r *http.Request, id int) {
+	http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+}
diff --git a/internal/rootmux/admin_test.go b/internal/rootmux/admin_test.go
index efea4aaee99c29983d87b631605503ebee3ad5da..945d11fc542ee8df12e2e746dd404ed60b4b1cee 100644
--- a/internal/rootmux/admin_test.go
+++ b/internal/rootmux/admin_test.go
@@ -56,6 +56,7 @@ func AdminTests(t *testing.T) {
 		// Try to delete the first operation
 		do("DELETE", "/api/Operations/1", xsrfHeader, ``, 200, "")
 	}
+	const apiAdminUsers = "/api/admin/users/"
 	userTests := func() {
 		response := do("GET", "/api/common/WhoAmI", noH, "", 200, "")
 		token := auth.TokenData{}
@@ -63,11 +64,11 @@ func AdminTests(t *testing.T) {
 		xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
 
 		// Create a Client
-		do("POST", "/api/admin/users/", xsrfHeader, `{"login":"UserTest","password": "password","role":"CLIENT"}`, 200, `[{"id":1,"idOAuth":"","login":"Dupond"`)
+		do("POST", apiAdminUsers, xsrfHeader, `{"login":"UserTest","password": "password","role":"CLIENT"}`, 200, `{"id":7,"idOAuth":"","login":"UserTest","role":"CLIENT","passwordHash":"`)
 		// Create a Banker
-		do("POST", "/api/admin/users/", xsrfHeader, `{"login":"BankerTest","password": "password","role":"BANKER"}`, 200, `[{"id":1,"idOAuth":"","login":"Dupond"`)
+		do("POST", apiAdminUsers, xsrfHeader, `{"login":"BankerTest","password": "password","role":"BANKER"}`, 200, `{"id":8,"idOAuth":"","login":"BankerTest","role":"BANKER","passwordHash":"`)
 		// Get all users
-		do("GET", "/api/admin/users/", xsrfHeader, ``, 200, `[{"id":1,"idOAuth":"","login":"Dupond"`)
+		do("GET", apiAdminUsers, xsrfHeader, ``, 200, `[{"id":1,"idOAuth":"","login":"Dupond"`)
 		// Delete created users
 		do("DELETE", "/api/admin/users/7", xsrfHeader, ``, 200, ``)
 		do("DELETE", "/api/admin/users/8", xsrfHeader, ``, 200, ``)
diff --git a/internal/rootmux/banker_test.go b/internal/rootmux/banker_test.go
index 3e78e49f8bbb4e6a8b8d119ab4fe05c4fcb32e5a..d2ab2e9086a5a970fbf645ae1ed8d7cc1662e202 100644
--- a/internal/rootmux/banker_test.go
+++ b/internal/rootmux/banker_test.go
@@ -40,7 +40,7 @@ func BankerTests(t *testing.T) {
 		// Try to get another banker's client should fail with 405
 		do("GET", "/api/UserClients/2", xsrfHeader, "", 403, `You can not access this ressource`)
 		// Try to get all the clients of the banker
-		do("GET", "/api/UserClients", xsrfHeader, "", 200, `[{"ID":1,"UserID":1,"Name":"Dupond","UserBankerID":1,"BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":null}]},{"ID":2,"UserID":2,"Name":"Boulangerie","UserBankerID":2,"BankAccounts":[{"ID":2,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4745,"BankOverdraft":-500,"Operations":null}]},{"ID":3,"UserID":7,"Name":"Dupond","UserBankerID":1,"BankAccounts":[]}]`)
+		do("GET", "/api/UserClients", xsrfHeader, "", 200, `[{"ID":1,"UserID":1,"Name":"Dupond","UserBankerID":1,"BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":null}]},{"ID":3,"UserID":7,"Name":"Dupond","UserBankerID":1,"BankAccounts":[]}]`)
 		// Try to delete a banker client
 		do("DELETE", "/api/UserClients/3", xsrfHeader, ``, 200, ``)
 		// Try to delete the bakery client should fail with 405
diff --git a/internal/rootmux/client_test.go b/internal/rootmux/client_test.go
index 0b04943c8397abb6c94575e575f7431252c02f91..c6229a881edc97bc02b2477eedf28478bb265e50 100644
--- a/internal/rootmux/client_test.go
+++ b/internal/rootmux/client_test.go
@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"testing"
 
+	"forge.grandlyon.com/apoyen/sdk-go/internal/models"
 	"forge.grandlyon.com/apoyen/sdk-go/pkg/auth"
 	"forge.grandlyon.com/apoyen/sdk-go/pkg/tester"
 )
@@ -23,11 +24,11 @@ func ClientTests(t *testing.T) {
 		xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
 
 		// Try to create a client should fail with 405
-		do("POST", "/api/UserClients", xsrfHeader, `{"ID":11,"UserID":"11","Name":"Dupont"}`, 405, "You're not authorize to execute this method on this ressource.")
+		do("POST", "/api/UserClients", xsrfHeader, `{"ID":11,"UserID":"11","Name":"Dupont"}`, 405, models.ErrorNotAuthorizeMethodOnRessource)
 		// Try to create a banker should fail with 405
-		do("POST", "/api/UserBankers", xsrfHeader, `{"ID":11,"UserID":"11","Name":"Banker"}`, 405, "You're not authorize to execute this method on this ressource.")
+		do("POST", "/api/UserBankers", xsrfHeader, `{"ID":11,"UserID":"11","Name":"Banker"}`, 405, models.ErrorNotAuthorizeMethodOnRessource)
 		// Try to create a BankAccount should fail with 405
-		do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0}`, 405, "You're not authorize to execute this method on this ressource.")
+		do("POST", "/api/BankAccounts", xsrfHeader, `{"Number":"01-02","UserClientID":1,"Type":"saving-account","Amount":1287,"BankOverdraft":0}`, 405, models.ErrorNotAuthorizeMethodOnRessource)
 		// Client should be able to create an operation
 		do("POST", "/api/Operations", xsrfHeader, `{"Debtor":1,"Amount":-100,"Creditor":2}`, 200, ``)
 
@@ -47,11 +48,11 @@ func ClientTests(t *testing.T) {
 		do("GET", "/api/UserClients", xsrfHeader, "", 200, `[{"ID":1,"UserID":1,"Name":"Dupond","UserBankerID":1,"BankAccounts":[{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":null}]}]`)
 
 		// Try to delete the first operation should fail
-		do("DELETE", "/api/Operations/1", xsrfHeader, ``, 405, "You're not authorize to execute this method on this ressource.")
+		do("DELETE", "/api/Operations/1", xsrfHeader, ``, 405, models.ErrorNotAuthorizeMethodOnRessource)
 		// Try to delete the saving account of Dupond should fail
-		do("DELETE", "/api/BankAccounts/2", xsrfHeader, ``, 405, "You're not authorize to execute this method on this ressource.")
+		do("DELETE", "/api/BankAccounts/2", xsrfHeader, ``, 405, models.ErrorNotAuthorizeMethodOnRessource)
 		// Try to delete the client Dupond should fail
-		do("DELETE", "/api/UserClients/2", xsrfHeader, ``, 405, "You're not authorize to execute this method on this ressource.")
+		do("DELETE", "/api/UserClients/2", xsrfHeader, ``, 405, models.ErrorNotAuthorizeMethodOnRessource)
 	}
 	// Do a in memory login with an known user
 	do("POST", "/Login", noH, `{"login": "Dupond","password": "password"}`, 200, "")
diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go
index 992209b402b7622ebebf85ce292d3522d43faa02..78b3337109d145795971a198ffe0d3121329abee 100644
--- a/internal/rootmux/rootmux_test.go
+++ b/internal/rootmux/rootmux_test.go
@@ -89,26 +89,28 @@ func appTests(t *testing.T) {
 		json.Unmarshal([]byte(response), &token)
 		xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken}
 
+		const apiOperation1 = "/api/Operations/1"
+		const apiBankAccount1 = "/api/BankAccounts/1"
 		// Add invalid operation between client and Bakery must be refused with 417 (Expectation failed)
 		do("POST", "/api/Operations", xsrfHeader, `{"Debtor":1,"Amount":-1789,"Creditor":2}`, 417, "Not enough money")
 
 		// Add an operation between Dupond and Bakery and verify that bank accounts are updated and opposite operation is created
 		do("POST", "/api/Operations", xsrfHeader, `{"Debtor":1,"Amount":-100,"Creditor":2}`, 200, "")
-		do("GET", "/api/Operations/1", xsrfHeader, "", 200, `{"ID":1,"Debtor":1,"Amount":-100`)
+		do("GET", apiOperation1, xsrfHeader, "", 200, `{"ID":1,"Debtor":1,"Amount":-100`)
 		do("GET", "/api/Operations/2", xsrfHeader, "", 200, `{"ID":2,"Debtor":2,"Amount":100`)
-		do("GET", "/api/BankAccounts/1", xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":[{"ID":1,"Debtor":1,"Amount":-100,"Date":"`)
+		do("GET", apiBankAccount1, xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":358,"BankOverdraft":-100,"Operations":[{"ID":1,"Debtor":1,"Amount":-100,"Date":"`)
 		do("GET", "/api/BankAccounts/2", xsrfHeader, "", 200, `{"ID":2,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4845,"BankOverdraft":-500,"Operations":[{"ID":2,"Debtor":2,"Amount":100,"Date":`)
 
 		// Try to delete the first operation, the opposite operation should also have been deleted and bank accounts updated
-		do("DELETE", "/api/Operations/1", xsrfHeader, ``, 200, "")
-		do("GET", "/api/Operations/1", xsrfHeader, "", 404, `id does not exist`)
+		do("DELETE", apiOperation1, xsrfHeader, ``, 200, "")
+		do("GET", apiOperation1, xsrfHeader, "", 404, `id does not exist`)
 		do("GET", "/api/Operations/2", xsrfHeader, "", 404, `id does not exist`)
-		do("GET", "/api/BankAccounts/1", xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]}`)
+		do("GET", apiBankAccount1, xsrfHeader, "", 200, `{"ID":1,"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100,"Operations":[]}`)
 		do("GET", "/api/BankAccounts/2", xsrfHeader, "", 200, `{"ID":2,"Number":"02-01","UserClientID":2,"Type":"checking-account","Amount":4745,"BankOverdraft":-500,"Operations":[]}`)
 
 		// Delete a client should also delete his banks accounts
 		do("DELETE", "/api/UserClients/1", xsrfHeader, ``, 200, "")
-		do("GET", "/api/BankAccounts/1", xsrfHeader, "", 404, `id does not exist`)
+		do("GET", apiBankAccount1, xsrfHeader, "", 404, `id does not exist`)
 
 	}
 	// Do an OAuth2 login with an known admin
diff --git a/internal/rootmux/unlogged_test.go b/internal/rootmux/unlogged_test.go
index 2a445f0d5435502cdb77a4b9365b7fa04ee0a89e..dedec8e383ea0932752fefae97957a3e9980875b 100644
--- a/internal/rootmux/unlogged_test.go
+++ b/internal/rootmux/unlogged_test.go
@@ -8,6 +8,9 @@ import (
 /**
 UNLOGGED USER TESTS (this tests are to check that the security protections works)
 **/
+
+const errorExtractingToken = `error extracting token`
+
 func UnLoggedUserTests(t *testing.T) {
 	// Create the tester
 	ts, do, _ := createTester(t)
@@ -23,30 +26,30 @@ func UnLoggedUserTests(t *testing.T) {
 
 	// Without authent API calls must fails with 401 error extracting token
 	// Try to get the first client should fail
-	do("GET", "/api/UserClients/1", noH, "", 401, `error extracting token`)
+	do("GET", "/api/UserClients/1", noH, "", 401, errorExtractingToken)
 	// Try to get all clients should fail
-	do("GET", "/api/UserClients", noH, "", 401, `error extracting token`)
+	do("GET", "/api/UserClients", noH, "", 401, errorExtractingToken)
 	// Try to get the first operation should fail
-	do("GET", "/api/UserBankers/1", noH, "", 401, `error extracting token`)
+	do("GET", "/api/UserBankers/1", noH, "", 401, errorExtractingToken)
 	// Try to get all clients should fail
-	do("GET", "/api/UserBankers", noH, "", 401, `error extracting token`)
+	do("GET", "/api/UserBankers", noH, "", 401, errorExtractingToken)
 	// Try to get the first operation should fail
-	do("GET", "/api/Operations/1", noH, "", 401, `error extracting token`)
+	do("GET", "/api/Operations/1", noH, "", 401, errorExtractingToken)
 	// Try to get all operations should fail
-	do("GET", "/api/Operations", noH, "", 401, `error extracting token`)
+	do("GET", "/api/Operations", noH, "", 401, errorExtractingToken)
 	// Try to get the first BankAccount should fail
-	do("GET", "/api/BankAccounts/1", noH, "", 401, `error extracting token`)
+	do("GET", "/api/BankAccounts/1", noH, "", 401, errorExtractingToken)
 	// Try to get all BankAccounts should fail
-	do("GET", "/api/BankAccounts", noH, "", 401, `error extracting token`)
+	do("GET", "/api/BankAccounts", noH, "", 401, errorExtractingToken)
 
 	// Unlogged user should not be able to create a Client
-	do("POST", "/api/UserClients", noH, `{"Name":"Dupond"}`, 401, `error extracting token`)
+	do("POST", "/api/UserClients", noH, `{"Name":"Dupond"}`, 401, errorExtractingToken)
 	// Unlogged user should not be able to create a Banker
-	do("POST", "/api/UserBankers", noH, `{"Name":"Dupond"}`, 401, `error extracting token`)
+	do("POST", "/api/UserBankers", noH, `{"Name":"Dupond"}`, 401, errorExtractingToken)
 	// Unlogged user should not be able to create a Bank Account
-	do("POST", "/api/BankAccounts", noH, `{"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100}`, 401, `error extracting token`)
+	do("POST", "/api/BankAccounts", noH, `{"Number":"01-01","UserClientID":1,"Type":"checking-account","Amount":458,"BankOverdraft":-100}`, 401, errorExtractingToken)
 	// Unlogged user should not be able to create an Operation
-	do("POST", "/api/Operations", noH, `{"Debtor":1,"Amount":-100,"Creditor":3}`, 401, `error extracting token`)
+	do("POST", "/api/Operations", noH, `{"Debtor":1,"Amount":-100,"Creditor":3}`, 401, errorExtractingToken)
 
 	// Unlogged user should not be able to delete an Operation
 	do("DELETE", "/api/Operations/1", noH, ``, 401, "error extracting token")
diff --git a/pkg/auth/dbusers.go b/pkg/auth/dbusers.go
index 9d10593efc3bc750b585f47fa36d211b17671a0f..5b9c4d6d5e425eb403f3f788754cebd2271b0cb1 100644
--- a/pkg/auth/dbusers.go
+++ b/pkg/auth/dbusers.go
@@ -24,17 +24,28 @@ func NewDataHandler() *DataHandler {
 	return &DataHandler{db: db}
 }
 
-func (d *DataHandler) saveUser(user User) error {
+func (d *DataHandler) createUser(user User) error {
 	d.db.Create(&user)
 	return nil
 }
 
+func (d *DataHandler) saveUser(user User) error {
+	d.db.Save(&user)
+	return nil
+}
+
 func (d *DataHandler) getUsers() []User {
 	var users []User
 	d.db.Find(&users)
 	return users
 }
 
+func (d *DataHandler) getUser(id int) User {
+	var user User
+	d.db.First(&user, id)
+	return user
+}
+
 func (d *DataHandler) removeUser(id int) error {
 	var o User
 	if err := d.db.First(&o, id).Error; err != nil {
diff --git a/pkg/auth/inmemory.go b/pkg/auth/inmemory.go
index bbb0944d76eb638f1571df55b04eb0857a6cd9f9..870944ec9bb29ded5fff3b9a0197f1629fd51210 100644
--- a/pkg/auth/inmemory.go
+++ b/pkg/auth/inmemory.go
@@ -68,6 +68,8 @@ func ProcessUsers(w http.ResponseWriter, req *http.Request) {
 		d.SendUsers(w, req)
 	case "POST":
 		d.AddUser(w, req)
+	case "PUT":
+		d.UpdateUser(w, req)
 	case "DELETE":
 		d.DeleteUser(w, req)
 	default:
@@ -108,22 +110,73 @@ func (d *DataHandler) AddUser(w http.ResponseWriter, req *http.Request) {
 		newUser.PasswordHash = string(hash)
 		newUser.Password = ""
 	}
-	// Select the new id for the user
-	newUser.ID = 1
+	// Check login don't already exist
 	for _, val := range users {
-		if newUser.ID <= val.ID {
-			newUser.ID = val.ID + 1
-		}
 		if newUser.Login == val.Login {
 			http.Error(w, "login already exists", 400)
 			return
 		}
 	}
-	d.saveUser(newUser)
-	d.SendUsers(w, req)
+	d.createUser(newUser)
+	d.db.Last(&newUser)
+	json.NewEncoder(w).Encode(newUser)
+
+}
+
+// UpdateUser update an user
+func (d *DataHandler) UpdateUser(w http.ResponseWriter, req *http.Request) {
+	id, _ := strconv.Atoi(strings.TrimPrefix(req.URL.Path, "/users/"))
+	if id != 0 {
+		user := d.getUser(id)
+		if req.Body == nil {
+			http.Error(w, "please send a request body", http.StatusBadRequest)
+			return
+		}
+		var newUser User
+		err := json.NewDecoder(req.Body).Decode(&newUser)
+		if _, ok := err.(*json.UnmarshalTypeError); !ok && err != nil {
+			http.Error(w, err.Error(), http.StatusBadRequest)
+			return
+		}
+		// check that login doesn't already exist
+		if user.Login != newUser.Login {
+			var users = d.getUsers()
+			for _, val := range users {
+				if newUser.Login == val.Login {
+					http.Error(w, "login already exists", 400)
+					return
+				}
+			}
+		}
+		user.IDOAuth = newUser.IDOAuth
+		user.Login = newUser.Login
+		user.DisplayName = newUser.DisplayName
+		user.Name = newUser.Name
+		user.Surname = newUser.Surname
+		user.Role = newUser.Role
+		// Encrypt the password with bcrypt if appropriate
+		if newUser.Password == "" && newUser.PasswordHash == "" {
+			http.Error(w, "passwords cannot be blank", http.StatusBadRequest)
+			return
+		}
+		if newUser.Password != "" {
+			hash, err := bcrypt.GenerateFromPassword([]byte(newUser.Password), bcrypt.DefaultCost)
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusBadRequest)
+				return
+			}
+			user.PasswordHash = string(hash)
+			user.Password = ""
+		}
+		d.saveUser(user)
+		json.NewEncoder(w).Encode(user)
+	} else {
+		http.Error(w, "Please provide an ID", http.StatusBadRequest)
+		return
+	}
 }
 
-// DeleteUser adds an user
+// DeleteUser remove an user
 func (d *DataHandler) DeleteUser(w http.ResponseWriter, req *http.Request) {
 	pathElements := strings.Split(req.URL.Path, "/")
 	idx, err := strconv.Atoi(pathElements[len(pathElements)-1])
@@ -136,7 +189,6 @@ func (d *DataHandler) DeleteUser(w http.ResponseWriter, req *http.Request) {
 		http.Error(w, err.Error(), 400)
 		return
 	}
-	d.SendUsers(w, req)
 }
 
 // MatchUser attempt to find the given user against users in configuration file
diff --git a/pkg/auth/oauth2.go b/pkg/auth/oauth2.go
index 1458a6c6c60efc351a3e59460a26c011236a0786..73a1f3918001bf1f87aa39c338c4a3ebffa54296 100644
--- a/pkg/auth/oauth2.go
+++ b/pkg/auth/oauth2.go
@@ -188,6 +188,6 @@ func (d *DataHandler) addUserInMemory(userOauth2 UserOAuth2) (User, error) {
 		}
 	}
 	// Sauvegarder l'utilisateur dans InMemory
-	d.saveUser(user)
+	d.createUser(user)
 	return user, nil
 }
diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go
index c503ba29534bb72ab9c9df4147251e0c6937c289..54311c7738e542398bfb6cae3b3406f10f5c2315 100644
--- a/pkg/log/log_test.go
+++ b/pkg/log/log_test.go
@@ -7,6 +7,8 @@ import (
 	"testing"
 )
 
+const londonIPAdress = "81.2.69.142:1234"
+
 func TestGetCityAndCountryFromRequest(t *testing.T) {
 
 	ipDbLocation = "../../configs/ipgeodatabase/GeoLite2-City.mmdb"
@@ -15,7 +17,7 @@ func TestGetCityAndCountryFromRequest(t *testing.T) {
 	requestFromLocalHost.RemoteAddr = "[::1]:1234"
 
 	requestFromLondon := httptest.NewRequest("GET", "/test", strings.NewReader(""))
-	requestFromLondon.RemoteAddr = "81.2.69.142:1234"
+	requestFromLondon.RemoteAddr = londonIPAdress
 
 	requestWithLocalIP := httptest.NewRequest("GET", "/test", strings.NewReader(""))
 
diff --git a/web/components/bankerPage/bankAccount.js b/web/components/bankerPage/bankAccount.js
new file mode 100644
index 0000000000000000000000000000000000000000..cb8811642bae4091f27a93e0aa5c37cd42bb35fd
--- /dev/null
+++ b/web/components/bankerPage/bankAccount.js
@@ -0,0 +1,155 @@
+// Imports
+import * as Auth from "/services/auth/auth.js";
+import * as Messages from "/services/messages/messages.js";
+import { RandomString } from "/services/common/common.js";
+import * as Operations from "/components/bankerPage/operations.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where, parent) {
+  const bankAccount = new BankAccount(parent);
+  await bankAccount.mount(where);
+  return bankAccount;
+}
+
+class BankAccount {
+  constructor(parent) {
+    // Random id seed
+    this.prefix = RandomString(8);
+    this.parent = parent;
+  }
+
+  async mount(where) {
+    current_user = await Auth.GetUser();
+
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="container">
+        <div class="columns">
+          <div class="column is-one-third">
+            <h5 class="title is-5">Informations du compte bancaire <em id="account-number"></em></h5>
+            <div class="container">
+              <div class="field" id="users-modal-role-container">
+                <label>Type de compte</label><br />
+                <div class="control select">
+                  <select name="type" id="account-type" ${current_user.role == "CLIENT" ? `disabled` : ``}>
+                    <option value="checking-account">Compte courant</option>
+                    <option value="saving-account">Compte épargne</option>
+                  </select>
+                </div>
+              </div>
+              <div class="field">
+                <label>Découvert autorisé</label>
+                <div class="control">
+                  <input class="input" type="number" id="account-overdraft" ${current_user.role == "CLIENT" ? `disabled` : ``} />
+                </div>
+              </div>
+              ${current_user.role != "CLIENT"
+                ? /* HTML */ ` <button id="account-save" class="button is-success">Sauvegarder</button>
+                    <button id="account-cancel" class="button">Annuler</button>`
+                : ``}
+            </div>
+          </div>
+          <div class="column">
+            <h5 class="title is-5">Opérations du compte bancaire</h5>
+            <div id="operations"></div>
+          </div>
+        </div>
+      </div>
+    `;
+  }
+
+  async handleDom() {
+    document.getElementById("account-number").innerHTML = this.bankAccount.Number;
+    document.getElementById("account-type").value = this.bankAccount.Type;
+    document.getElementById("account-overdraft").value = this.bankAccount.BankOverdraft;
+    let operationHandler = await Operations.mount("operations", this);
+    await operationHandler.displayOperations(this.bankAccount);
+
+    if (current_user.role != "CLIENT") {
+      let bankAccount = this;
+      document.getElementById(`account-cancel`).addEventListener("click", function () {
+        bankAccount.handleDom();
+      });
+      document.getElementById(`account-save`).addEventListener("click", function () {
+        bankAccount.bankAccount.BankOverdraft = parseInt(document.getElementById("account-overdraft").value);
+        bankAccount.bankAccount.Type = document.getElementById("account-type").value;
+        bankAccount.postBankAccount();
+      });
+    }
+  }
+
+  editBankAccount(bankAccount) {
+    this.bankAccount = bankAccount;
+    this.isNew = false;
+    this.handleDom();
+  }
+
+  newBankAccount(client) {
+    this.bankAccount = {};
+    this.bankAccount.ID = 0;
+    this.bankAccount.Number = "0" + client.ID + "-0" + (client.BankAccounts.length + 1);
+    this.bankAccount.UserClientID = client.ID;
+    this.bankAccount.Type = document.getElementById("account-type").value;
+    this.bankAccount.Amount = 0;
+    this.bankAccount.BankOverdraft = 0;
+    this.isNew = true;
+    this.handleDom();
+  }
+
+  viewBankAccount(bankAccount) {
+    this.bankAccount = bankAccount;
+    this.handleDom();
+  }
+
+  async deleteAccount(bankAccount) {
+    try {
+      const response = await fetch("/api/BankAccounts/" + bankAccount.ID, {
+        method: "delete",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`BankAccount could not be deleted (status ${response.status})`);
+      }
+      document.getElementById(`accounts-account-${bankAccount.ID}`).remove();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async postBankAccount() {
+    let method;
+    if (this.isNew) method = "POST";
+    else method = "PUT";
+
+    try {
+      const response = await fetch("/api/BankAccounts/" + this.bankAccount.ID, {
+        method: method,
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+        body: JSON.stringify({
+          ID: this.bankAccount.ID,
+          Number: this.bankAccount.Number,
+          UserClientID: this.bankAccount.UserClientID,
+          Type: this.bankAccount.Type,
+          Amount: this.bankAccount.Amount,
+          BankOverdraft: this.bankAccount.BankOverdraft,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Banker could not be updated (status ${response.status})`);
+      }
+      await this.parent.updateBankAccounts();
+      document.getElementById(`accounts-account-edit-${this.bankAccount.ID}`).click();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+}
diff --git a/web/components/bankerPage/bankerPage.js b/web/components/bankerPage/bankerPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..93f65b56561da36b33cc80d6a9654ccfef842c40
--- /dev/null
+++ b/web/components/bankerPage/bankerPage.js
@@ -0,0 +1,97 @@
+// Imports
+import { RandomString } from "/services/common/common.js";
+import * as Messages from "/services/messages/messages.js";
+import * as Auth from "/services/auth/auth.js";
+import * as ClientDetails from "/components/bankerPage/clientDetails.js";
+
+// DOM elements
+
+// local variables
+let clients;
+let current_user;
+
+export async function mount(where) {
+  const bankerPage = new BankerPage();
+  await bankerPage.mount(where);
+  await bankerPage.displayClients();
+}
+
+class BankerPage {
+  constructor() {
+    // Random id seed
+    this.prefix = RandomString(8);
+  }
+
+  async mount(where) {
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="container">
+        <h1 class="title">Page du banquier</h1>
+      </div>
+      <section class="section">
+        <div class="container">
+          <div class="columns">
+            <div class="column is-one-third">
+            <h5 class="title is-5">Mes clients</h5>
+              <div class="table-container">
+                <table class="table is-bordered is-narrow is-hoverable is-fullwidth">
+                  <thead>
+                    <tr class="is-selected">
+                      <th>Id</th>
+                      <th>Nom</th>
+                    </tr>
+                  </thead>
+                  <tbody id="clients"></tbody>
+                </table>
+              </div>
+            </div>
+            <div class="column">
+            <h5 class="title is-5">Comptes bancaires de <em id="client-title">Veuillez sélectionner un client</em></h5>
+              <div class="container">
+                <div id="bank-accounts"></div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </section>
+      <section class="section>
+        <div class="container" id="bank-account"></div>
+      </section>
+    `;
+    current_user = await Auth.GetUser();
+  }
+
+  async displayClients() {
+    try {
+      const response = await fetch("/api/UserClients/", {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Users could not be fetched (status ${response.status})`);
+      }
+      clients = await response.json();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    const markup = clients.map((client) => this.clientTemplate(client)).join("");
+    document.getElementById("clients").innerHTML = markup;
+    clients.map((client) => {
+      document.getElementById(`clients-client-${client.ID}`).addEventListener("click", function () {
+        document.getElementById("client-title").innerHTML = client.Name;
+        ClientDetails.mount("bank-accounts", client);
+      });
+    });
+  }
+
+  clientTemplate(client) {
+    return /* HTML */ `
+      <tr id="clients-client-${client.ID}">
+        <td>${client.ID}</td>
+        <td>${client.Name}</td>
+      </tr>
+    `;
+  }
+}
diff --git a/web/components/bankerPage/clientDetails.js b/web/components/bankerPage/clientDetails.js
new file mode 100644
index 0000000000000000000000000000000000000000..91a4543f44d33ca04272624e504cfb58f316a768
--- /dev/null
+++ b/web/components/bankerPage/clientDetails.js
@@ -0,0 +1,139 @@
+// Imports
+import * as Auth from "/services/auth/auth.js";
+import * as Messages from "/services/messages/messages.js";
+import { RandomString } from "/services/common/common.js";
+import * as BankAccount from "/components/bankerPage/bankAccount.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where, client) {
+  const clientDetails = new ClientDetails(client);
+  await clientDetails.mount(where);
+  clientDetails.displayBankAccounts();
+}
+
+class ClientDetails {
+  constructor(client) {
+    // Random id seed
+    this.prefix = RandomString(8);
+    this.client = client;
+  }
+
+  async mount(where) {
+    current_user = await Auth.GetUser();
+
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="table-container">
+        <table class="table is-bordered is-narrow is-hoverable is-fullwidth">
+          <thead>
+            <tr class="is-selected">
+              <th>Id</th>
+              <th>Numéro</th>
+              <th>Type</th>
+              <th>Montant</th>
+              <th>Découvert autorisé</th>
+              <th>Actions</th>
+            </tr>
+          </thead>
+          <tbody id="accounts"></tbody>
+        </table>
+
+        ${current_user.role != "CLIENT"
+          ? `
+        <nav class="level">
+          <div class="level-left"></div>
+          <!-- Right side -->
+          <div class="level-right">
+            <button id="bankAccount-new" class="button is-success">
+              <span class="icon is-small">
+                <i class="fas fa-plus"></i>
+              </span>
+            </button>
+          </div>
+        </nav>`
+          : ``}
+      </div>
+    `;
+  }
+
+  async displayBankAccounts() {
+    const markup = this.client.BankAccounts.map((bankAccount) => this.bankAccountTemplate(bankAccount)).join("");
+    document.getElementById("accounts").innerHTML = markup;
+    let accountHandler = await BankAccount.mount("bank-account", this);
+
+    this.client.BankAccounts.map((bankAccount) => {
+      if (current_user.role == "CLIENT") {
+        document.getElementById(`accounts-account-view-${bankAccount.ID}`).addEventListener("click", function () {
+          document.getElementById("account-title").innerHTML = bankAccount.Number;
+          accountHandler.viewBankAccount(bankAccount);
+        });
+      } else {
+        document.getElementById(`accounts-account-edit-${bankAccount.ID}`).addEventListener("click", function () {
+          accountHandler.editBankAccount(bankAccount);
+        });
+        document.getElementById(`accounts-account-delete-${bankAccount.ID}`).addEventListener("click", function () {
+          accountHandler.deleteAccount(bankAccount);
+        });
+        let clientDetails = this;
+        document.getElementById(`bankAccount-new`).addEventListener("click", function () {
+          accountHandler.newBankAccount(clientDetails.client);
+        });
+      }
+    });
+  }
+
+  bankAccountTemplate(bankAccount) {
+    return /* HTML */ `
+      <tr id="accounts-account-${bankAccount.ID}">
+        <td>${bankAccount.ID}</td>
+        <td>${bankAccount.Number}</td>
+        <td>${bankAccount.Type}</td>
+        <td>${bankAccount.Amount}</td>
+        <td>${bankAccount.BankOverdraft}</td>
+        <td>
+          ${current_user.role == "CLIENT"
+            ? `<a id="accounts-account-view-${bankAccount.ID}" class="button is-link is-small">
+        <span>Visualiser</span>
+        <span class="icon is-small">
+          <i class="fas fa-pen"></i>
+        </span>
+      </a>`
+            : `<a id="accounts-account-edit-${bankAccount.ID}" class="button is-link is-small">
+            <span>Modifier</span>
+            <span class="icon is-small">
+              <i class="fas fa-pen"></i>
+            </span>
+          </a>
+          <a id="accounts-account-delete-${bankAccount.ID}" class="button is-danger is-small">
+            <span>Supprimer</span>
+            <span class="icon is-small">
+              <i class="fas fa-times"></i>
+            </span>
+          </a>`}
+        </td>
+      </tr>
+    `;
+  }
+
+  async updateBankAccounts() {
+    try {
+      const response = await fetch("/api/UserClients/" + this.client.ID, {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Users could not be fetched (status ${response.status})`);
+      }
+      this.client = await response.json();
+      await this.displayBankAccounts();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+}
diff --git a/web/components/bankerPage/operations.js b/web/components/bankerPage/operations.js
new file mode 100644
index 0000000000000000000000000000000000000000..50c0c50d8182b73b69107b5e2045192bd91c37c0
--- /dev/null
+++ b/web/components/bankerPage/operations.js
@@ -0,0 +1,247 @@
+// Imports
+import * as Auth from "/services/auth/auth.js";
+import * as Messages from "/services/messages/messages.js";
+import * as Users from "/components/users/users.js";
+import { RandomString } from "/services/common/common.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where, parent) {
+  const operation = new Operation(parent);
+  await operation.mount(where);
+  operation.handleDom();
+  return operation;
+}
+
+class Operation {
+  constructor(parent) {
+    // Random id seed
+    this.prefix = RandomString(8);
+    this.parent = parent;
+  }
+
+  async mount(where) {
+    current_user = await Auth.GetUser();
+
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="table-container">
+        <table class="table is-bordered is-narrow is-hoverable is-fullwidth">
+          <thead>
+            <tr class="is-selected">
+              <th>Id</th>
+              <th>Montant</th>
+              <th>Client</th>
+              <th>Date</th>
+              ${current_user.role != "CLIENT" ? `<th>Actions</th>` : ``}
+            </tr>
+          </thead>
+          <tbody id="operations-table"></tbody>
+        </table>
+      </div>
+      <nav class="level">
+        <div class="level-left"></div>
+        <!-- Right side -->
+        <div class="level-right">
+          <button id="operation-new" class="button is-success">
+            <span class="icon is-small">
+              <i class="fas fa-plus"></i>
+            </span>
+          </button>
+        </div>
+      </nav>
+
+      <div class="modal" id="operation-modal">
+        <div class="modal-background"></div>
+        <div class="modal-card" id="operation-modal-card">
+          <header class="modal-card-head">
+            <p class="modal-card-title">Ajout d'une opération</p>
+            <button class="delete" aria-label="close" id="operation-modal-close"></button>
+          </header>
+          <section class="modal-card-body">
+            <div class="field">
+              <label>Montant</label>
+              <div class="control">
+                <input class="input" type="text" id="operation-modal-amount" />
+              </div>
+            </div>
+            <div class="field">
+              <label>Compte bancaire</label><br />
+              <div class="control select">
+                <select name="bankAccount" id="operation-modal-bankAccount"> </select>
+              </div>
+            </div>
+          </section>
+          <footer class="modal-card-foot">
+            <button id="operation-modal-save" class="button is-success">Sauvegarder</button>
+            <button id="operation-modal-cancel" class="button">Annuler</button>
+          </footer>
+        </div>
+      </div>
+    `;
+  }
+
+  handleDom() {
+    let operationHandler = this;
+    document.getElementById(`operation-new`).addEventListener("click", function () {
+      Users.toggleModal("operation-modal", "operation-modal-card");
+      operationHandler.newOperation();
+    });
+
+    document.getElementById(`operation-modal-close`).addEventListener("click", function () {
+      Users.toggleModal("operation-modal", "operation-modal-card");
+    });
+    document.getElementById(`operation-modal-cancel`).addEventListener("click", function () {
+      Users.toggleModal("operation-modal", "operation-modal-card");
+    });
+    document.getElementById(`operation-modal-save`).addEventListener("click", function () {
+      operationHandler.postOperation();
+    });
+  }
+
+  async displayOperations(bankAccount) {
+    this.bankAccount = await this.updateBankAccount(bankAccount.ID);
+    const markup = this.bankAccount.Operations.map((operation) => this.operationTemplate(operation)).join("");
+    document.getElementById("operations-table").innerHTML = markup;
+
+    let operationHandler = this;
+    if (current_user.role != "CLIENT") {
+      this.bankAccount.Operations.map((operation) => {
+        document.getElementById(`operations-operation-delete-${operation.ID}`).addEventListener("click", function () {
+          operationHandler.deleteOperation(operation);
+        });
+      });
+    }
+  }
+
+  operationTemplate(operation) {
+    return /* HTML */ `
+      <tr id="operations-operation-${operation.ID}">
+        <td>${operation.ID}</td>
+        <td>${operation.Amount}</td>
+        <td>${operation.Creditor}</td>
+        <td>${new Date(operation.Date).toLocaleDateString()}</td>
+        ${current_user.role != "CLIENT"
+          ? `
+        <td>
+          <a id="operations-operation-delete-${operation.ID}" class="button is-danger is-small">
+            <span>Supprimer</span>
+            <span class="icon is-small">
+              <i class="fas fa-times"></i>
+            </span>
+          </a>
+        </td>
+        `
+          : ``}
+      </tr>
+    `;
+  }
+
+  async updateBankAccount(bankAccountID) {
+    try {
+      const response = await fetch("/api/BankAccounts/" + bankAccountID, {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`BankAccount could not be fetched (status ${response.status})`);
+      }
+      return await response.json();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async deleteOperation(operation) {
+    try {
+      const response = await fetch("/api/Operations/" + operation.ID, {
+        method: "delete",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Operation could not be deleted (status ${response.status})`);
+      }
+      document.getElementById(`operations-operation-${operation.ID}`).remove();
+      await this.parent.parent.updateBankAccounts();
+      document.getElementById(`accounts-account-edit-${this.bankAccount.ID}`).click();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async newOperation() {
+    try {
+      const response = await fetch("/api/BankAccounts/", {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`BankAccounts could not be fetched (status ${response.status})`);
+      }
+      let bankAccounts = await response.json();
+
+      let select = document.getElementById("operation-modal-bankAccount");
+      bankAccounts.forEach(async (bankAccount) => {
+        if (bankAccount.ID != this.bankAccount.ID) {
+          let el = document.createElement("option");
+          let client = await this.getClientById(bankAccount.UserClientID);
+          el.textContent = client.Name + " - " + bankAccount.Number;
+          el.value = bankAccount.ID;
+          select.appendChild(el);
+        }
+      });
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async postOperation() {
+    try {
+      const response = await fetch("/api/Operations/", {
+        method: "POST",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+        body: JSON.stringify({
+          Debtor: this.bankAccount.ID,
+          Creditor: parseInt(document.getElementById("operation-modal-bankAccount").value),
+          Amount: parseInt(document.getElementById("operation-modal-amount").value),
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Operation could not be created (status ${response.status})`);
+      }
+      await this.displayOperations(this.bankAccount);
+      await this.parent.parent.updateBankAccounts();
+      document.getElementById(`accounts-account-edit-${this.bankAccount.ID}`).click();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Users.toggleModal("operation-modal", "operation-modal-card");
+  }
+
+  async getClientById(clientID) {
+    const response = await fetch("/api/UserClients/" + clientID, {
+      method: "GET",
+      headers: new Headers({
+        "XSRF-Token": current_user.xsrftoken,
+      }),
+    });
+    if (response.status !== 200) {
+      throw new Error(`Could not get clients (status ${response.status})`);
+    }
+    return await response.json();
+  }
+}
diff --git a/web/components/clientPage/clientPage.js b/web/components/clientPage/clientPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..b5a1fd28522870dbd2ae5234d1eb30d14608a5e2
--- /dev/null
+++ b/web/components/clientPage/clientPage.js
@@ -0,0 +1,48 @@
+// Imports
+import { RandomString } from "/services/common/common.js";
+import * as Auth from "/services/auth/auth.js";
+import * as ClientDetails from "/components/bankerPage/clientDetails.js";
+
+// DOM elements
+
+// local variables
+let current_user;
+
+export async function mount(where) {
+  const clientPage = new ClientPage();
+  await clientPage.mount(where);
+}
+
+class ClientPage {
+  constructor() {
+    // Random id seed
+    this.prefix = RandomString(8);
+  }
+
+  async mount(where) {
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="container">
+        <h1 class="title">Ma banque</h1>
+      </div>
+
+      <section class="section">
+        <div class="columns">
+          <div class="column is-one-third">
+            <h5 class="title is-5">Mes comptes</h5>
+            <div id="bank-accounts"></div>
+          </div>
+          <div class="column">
+            <h5 class="title is-5">Compte bancaire n°<em id="account-title"> Veuillez sélectionner un compte</em></h5>
+            <div class="container">
+              <div id="bank-account"></div>
+            </div>
+          </div>
+        </div>
+      </section>
+    `;
+    current_user = await Auth.GetUser();
+
+    let client = await Auth.getClientByUserID(current_user.id, current_user);
+    ClientDetails.mount("bank-accounts", client);
+  }
+}
diff --git a/web/components/home/home.js b/web/components/home/home.js
new file mode 100644
index 0000000000000000000000000000000000000000..97b7678e4d7dc7bce02a857ee115411ad6bb91ee
--- /dev/null
+++ b/web/components/home/home.js
@@ -0,0 +1,20 @@
+// Imports
+
+// DOM elements
+let mountpoint;
+
+// local variables
+
+export async function mount(where) {
+  mountpoint = where;
+  document.getElementById(mountpoint).innerHTML = /* HTML */ `
+    <section class="section">
+      <div class="container">
+        <h1 class="title">Accueil de la GO-banque</h1>
+        <h2 class="subtitle">
+          Ceci est une application de démonstration du SDK écrit en GO avec GORM et Vanilla JS avec le framework CSS Bulma.
+        </h2>
+      </div>
+    </section>
+  `;
+}
diff --git a/web/components/navbar/navbar.js b/web/components/navbar/navbar.js
index 6a724a0884de353f3681e0dc191acea5de3bee50..f558982cea37e2e1147542e68a73b938cca22e53 100644
--- a/web/components/navbar/navbar.js
+++ b/web/components/navbar/navbar.js
@@ -24,9 +24,9 @@ export function mount(mountpoint) {
   // Hamburger menu
   const burger = document.getElementById("navbar-burger");
   menu = document.getElementById("navbar-menu");
-  const openClose = e => {
+  const openClose = (e) => {
     if (burger.classList.contains("is-active")) {
-      AnimateCSS(menu, "slideOutRight", function() {
+      AnimateCSS(menu, "slideOutRight", function () {
         menu.classList.remove("is-active");
         burger.classList.remove("is-active");
       });
@@ -51,9 +51,13 @@ export async function CreateMenu() {
             user === undefined
               ? ``
               : /* HTML */ `
-                  ${user.isAdmin
+                  <a class="navbar-item" href="#home"><i class="navbar-menu-icon fas fa-home"></i>Accueil</a>
+                  ${user.role == "CLIENT" ? /* HTML */ ` <a class="navbar-item" href="#client"><i class="navbar-menu-icon fas fa-money-check"></i>Mes comptes</a> ` : ""}
+                  ${user.role == "BANKER" ? /* HTML */ ` <a class="navbar-item" href="#banker"><i class="navbar-menu-icon fas fa-university"></i>Mes Clients</a> ` : ""}
+                  ${user.role == "ADMIN"
                     ? /* HTML */ `
-                        <a class="navbar-item" href="#users"><i class="navbar-menu-icon fas fa-users"></i>Users</a>
+                        <a class="navbar-item" href="#banker"><i class="navbar-menu-icon fas fa-university"></i>Mes Clients</a>
+                        <a class="navbar-item" href="#users"><i class="navbar-menu-icon fas fa-users"></i>Utilisateurs</a>
                       `
                     : ""}
                 `
@@ -62,12 +66,8 @@ export async function CreateMenu() {
         <div class="navbar-end">
           ${
             user === undefined
-              ? /* HTML */ `
-                  <a class="navbar-item" href="#login"><i class="navbar-menu-icon fas fa-sign-in-alt"></i>Log in</a>
-                `
-              : /* HTML */ `
-                  <a class="navbar-item" href="/Logout"><i class="navbar-menu-icon fas fa-sign-out-alt"></i>Log out</a>
-                `
+              ? /* HTML */ ` <a class="navbar-item" href="#login"><i class="navbar-menu-icon fas fa-sign-in-alt"></i>Connexion</a> `
+              : /* HTML */ ` <a class="navbar-item" href="/Logout"><i class="navbar-menu-icon fas fa-sign-out-alt"></i>Déconnexion</a> `
           }
         </div>
      `;
diff --git a/web/components/users/handleBanker.js b/web/components/users/handleBanker.js
new file mode 100644
index 0000000000000000000000000000000000000000..dbe644e60d931ae3b1542271babea3b69943726c
--- /dev/null
+++ b/web/components/users/handleBanker.js
@@ -0,0 +1,120 @@
+// Imports
+import { RandomString } from "/services/common/common.js";
+import * as Messages from "/services/messages/messages.js";
+import * as Auth from "/services/auth/auth.js";
+import * as Users from "/components/users/users.js";
+
+// DOM elements
+let name_field;
+let banker_name_field;
+let banker_id_field;
+
+// local variables
+let current_user;
+let update_banker;
+let user_id;
+
+export async function mount(where, parent) {
+  const handleBanker = new HandleBanker(parent);
+  await handleBanker.mount(where);
+  handleBanker.handleDom();
+  return handleBanker;
+}
+
+class HandleBanker {
+  constructor(parent) {
+    // Random id seed
+    this.prefix = RandomString(8);
+    this.parent = parent;
+  }
+
+  async mount(where) {
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="modal-background"></div>
+      <div class="modal-card" id="banker-modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">Ajout/Supression d'un banquier</p>
+          <button class="delete" aria-label="close" id="banker-modal-close"></button>
+        </header>
+        <section class="modal-card-body">
+          <div class="field">
+            <label>Id</label>
+            <div class="control">
+              <input class="input" type="number" id="banker-modal-id" disabled />
+            </div>
+          </div>
+          <div class="field">
+            <label>Nom</label>
+            <div class="control">
+              <input class="input" type="text" id="banker-modal-name" />
+            </div>
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          <button id="banker-modal-save" class="button is-success">Sauvegarder</button>
+          <button id="banker-modal-cancel" class="button">Annuler</button>
+        </footer>
+      </div>
+    `;
+    current_user = await Auth.GetUser();
+  }
+
+  handleDom() {
+    name_field = document.getElementById("users-modal-name");
+    banker_id_field = document.getElementById("banker-modal-id");
+    banker_name_field = document.getElementById("banker-modal-name");
+
+    document.getElementById(`banker-modal-close`).addEventListener("click", function () {
+      Users.toggleModal("banker-modal", "banker-modal-card");
+    });
+    document.getElementById(`banker-modal-cancel`).addEventListener("click", function () {
+      Users.toggleModal("banker-modal", "banker-modal-card");
+    });
+    let bankerHandler = this
+    document.getElementById(`banker-modal-save`).addEventListener("click", function () {
+      bankerHandler.postBanker();
+    });
+  }
+
+  async editBanker(banker) {
+    update_banker = true;
+    banker_id_field.value = banker.ID;
+    banker_name_field.value = banker.Name;
+    Users.toggleModal("banker-modal", "banker-modal-card");
+  }
+
+  async newBanker(userID) {
+    update_banker = false;
+    user_id = userID;
+    banker_name_field.value = name_field.value;
+    Users.toggleModal("banker-modal", "banker-modal-card");
+  }
+
+  async postBanker() {
+    let method;
+    if (update_banker) method = "PUT";
+    else method = "POST";
+
+    try {
+      const response = await fetch("/api/UserBankers/" + banker_id_field.value, {
+        method: method,
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+        body: JSON.stringify({
+          ID: parseInt(banker_id_field.value),
+          Name: banker_name_field.value,
+          UserID: parseInt(user_id),
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Banker could not be updated (status ${response.status})`);
+      }
+      this.parent.displayUsers();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Users.toggleModal("banker-modal", "banker-modal-card");
+  }
+}
diff --git a/web/components/users/handleClient.js b/web/components/users/handleClient.js
new file mode 100644
index 0000000000000000000000000000000000000000..74bf9dcfeead8ae6b325750ba660e7290b5304c4
--- /dev/null
+++ b/web/components/users/handleClient.js
@@ -0,0 +1,163 @@
+// Imports
+import { RandomString } from "/services/common/common.js";
+import * as Messages from "/services/messages/messages.js";
+import * as Auth from "/services/auth/auth.js";
+import * as Users from "/components/users/users.js";
+
+// DOM elements
+let name_field;
+let client_id_field;
+let client_name_field;
+let client_bankerID_field;
+
+// local variables
+let current_user;
+let bankers = [];
+let update_client;
+let user_id;
+
+export async function mount(where, parent) {
+  const handleClient = new HandleClient(parent);
+  await handleClient.mount(where);
+  handleClient.handleDom();
+  return handleClient;
+}
+
+class HandleClient {
+  constructor(parent) {
+    // Random id seed
+    this.prefix = RandomString(8);
+    this.parent = parent;
+  }
+
+  async mount(where) {
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="modal-background"></div>
+      <div class="modal-card" id="client-modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">Ajout/Supression d'un client</p>
+          <button class="delete" aria-label="close" id="client-modal-close"></button>
+        </header>
+        <section class="modal-card-body">
+          <div class="field">
+            <label>Id</label>
+            <div class="control">
+              <input class="input" type="number" id="client-modal-id" disabled />
+            </div>
+          </div>
+          <div class="field">
+            <label>Nom</label>
+            <div class="control">
+              <input class="input" type="text" id="client-modal-name" />
+            </div>
+          </div>
+          <div class="field" id="users-modal-role-container">
+            <label>Banquier</label><br />
+            <div class="control select">
+              <select name="banker" id="client-modal-banker-id"> </select>
+            </div>
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          <button id="client-modal-save" class="button is-success">Sauvegarder</button>
+          <button id="client-modal-cancel" class="button">Annuler</button>
+        </footer>
+      </div>
+    `;
+    current_user = await Auth.GetUser();
+  }
+
+  handleDom() {
+    name_field = document.getElementById("users-modal-name");
+    client_id_field = document.getElementById("client-modal-id");
+    client_name_field = document.getElementById("client-modal-name");
+    client_bankerID_field = document.getElementById("client-modal-banker-id");
+
+    document.getElementById(`client-modal-close`).addEventListener("click", function () {
+      Users.toggleModal("client-modal", "client-modal-card");
+    });
+    document.getElementById(`client-modal-cancel`).addEventListener("click", function () {
+      Users.toggleModal("client-modal", "client-modal-card");
+    });
+    let clientHandler = this;
+    document.getElementById(`client-modal-save`).addEventListener("click", function () {
+      clientHandler.postClient();
+    });
+  }
+
+  async editClient(client) {
+    await this.refreshBankers();
+    update_client = true;
+    client_id_field.value = client.ID;
+    client_name_field.value = client.Name;
+    client_bankerID_field.value = client.UserBankerID;
+    Users.toggleModal("client-modal", "client-modal-card");
+  }
+
+  async newClient(userID) {
+    await this.refreshBankers();
+    update_client = false;
+    user_id = userID;
+    console.log(user_id)
+    client_name_field.value = name_field.value;
+    client_bankerID_field.value = 0;
+    Users.toggleModal("client-modal", "client-modal-card");
+  }
+
+  async refreshBankers() {
+    const response = await fetch("/api/UserBankers/", {
+      method: "GET",
+      headers: new Headers({
+        "XSRF-Token": current_user.xsrftoken,
+      }),
+    });
+    if (response.status !== 200) {
+      throw new Error(`Users could not be updated (status ${response.status})`);
+    }
+    bankers = await response.json();
+
+    for (let i = client_bankerID_field.options.length - 1; i >= 0; i--) {
+      client_bankerID_field.remove(i);
+    }
+
+    let el = document.createElement("option");
+    el.textContent = "Veuillez sélectionner un banquier";
+    el.value = 0;
+    client_bankerID_field.appendChild(el);
+    bankers.forEach((banker) => {
+      el = document.createElement("option");
+      el.textContent = banker.Name;
+      el.value = banker.ID;
+      client_bankerID_field.appendChild(el);
+    });
+  }
+
+  async postClient() {
+    let method;
+    if (update_client) method = "PUT";
+    else method = "POST";
+
+    try {
+      const response = await fetch("/api/UserClients/" + client_id_field.value, {
+        method: method,
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+        body: JSON.stringify({
+          ID: parseInt(client_id_field.value),
+          UserID: parseInt(user_id),
+          Name: client_name_field.value,
+          UserBankerID: parseInt(client_bankerID_field.value),
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Client could not be updated (status ${response.status})`);
+      }
+      this.parent.displayUsers();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Users.toggleModal("client-modal", "client-modal-card");
+  }
+}
diff --git a/web/components/users/handleUser.js b/web/components/users/handleUser.js
new file mode 100644
index 0000000000000000000000000000000000000000..21d615864778cc487ecabdcf9c7d100d1bd57a9e
--- /dev/null
+++ b/web/components/users/handleUser.js
@@ -0,0 +1,262 @@
+// Imports
+import { RandomString } from "/services/common/common.js";
+import * as Messages from "/services/messages/messages.js";
+import * as Auth from "/services/auth/auth.js";
+import * as Users from "/components/users/users.js";
+
+// DOM elements
+let id_field;
+let idOAuth_field;
+let login_field;
+let displayName_field;
+let password_field;
+let passwordhash_field;
+let name_field;
+let surname_field;
+let role_field;
+
+// local variables
+let current_user;
+let update_user;
+
+export async function mount(where, parent) {
+  const handleUser = new HandleUser(parent);
+  await handleUser.mount(where);
+  handleUser.handleDom();
+  return handleUser;
+}
+
+class HandleUser {
+  constructor(parent) {
+    // Random id seed
+    this.prefix = RandomString(8);
+    this.parent = parent;
+  }
+
+  async mount(where) {
+    document.getElementById(where).innerHTML = /* HTML */ `
+      <div class="modal-background"></div>
+      <div class="modal-card" id="users-modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">Ajout/modification d'un utilisateur</p>
+          <button class="delete" aria-label="close" id="users-modal-close"></button>
+        </header>
+        <section class="modal-card-body">
+          <div class="field">
+            <label>Id</label>
+            <div class="control">
+              <input class="input" type="number" id="users-modal-id" disabled />
+            </div>
+          </div>
+          <div class="field">
+            <label>IdOAuth</label>
+            <div class="control">
+              <input class="input" type="text" id="users-modal-idoauth" />
+            </div>
+          </div>
+          <div class="field">
+            <label>Identifiant</label>
+            <div class="control">
+              <input class="input" type="text" id="users-modal-login" />
+            </div>
+          </div>
+          <div class="field" id="users-modal-password-container">
+            <label>Mot de passe</label>
+            <div class="control">
+              <input class="input" type="text" id="users-modal-password" />
+            </div>
+          </div>
+          <div class="field" id="users-modal-password-container">
+            <div class="control">
+              <input class="input" type="hidden" id="users-modal-passwordhash" />
+            </div>
+          </div>
+          <div class="field" id="users-modal-name-container">
+            <label>Nom</label>
+            <div class="control">
+              <input class="input" type="text" id="users-modal-name" />
+            </div>
+          </div>
+          <div class="field" id="users-modal-name-container">
+            <label>Nom complet</label>
+            <div class="control">
+              <input class="input" type="text" id="users-modal-displayName" />
+            </div>
+          </div>
+          <div class="field" id="users-modal-surname-container">
+            <label>Surnom</label>
+            <div class="control">
+              <input class="input" type="text" id="users-modal-surname" />
+            </div>
+          </div>
+          <div class="field" id="users-modal-role-container">
+            <label>Rôle</label><br />
+            <div class="control select">
+              <select name="role" id="users-modal-role">
+                <option value="CLIENT">Client</option>
+                <option value="BANKER">Banquier</option>
+                <option value="ADMIN">Administrateur</option>
+              </select>
+            </div>
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          <button id="users-modal-save" class="button is-success">Sauvegarder</button>
+          <button id="users-modal-cancel" class="button">Annuler</button>
+        </footer>
+      </div>
+    `;
+    current_user = await Auth.GetUser();
+  }
+
+  handleDom() {
+    id_field = document.getElementById("users-modal-id");
+    idOAuth_field = document.getElementById("users-modal-idoauth");
+    login_field = document.getElementById("users-modal-login");
+    password_field = document.getElementById("users-modal-password");
+    passwordhash_field = document.getElementById("users-modal-passwordhash");
+    displayName_field = document.getElementById("users-modal-displayName");
+    name_field = document.getElementById("users-modal-name");
+    surname_field = document.getElementById("users-modal-surname");
+    role_field = document.getElementById("users-modal-role");
+
+    document.getElementById(`users-modal-close`).addEventListener("click", function () {
+      Users.toggleModal("users-modal", "users-modal-card");
+    });
+    document.getElementById(`users-modal-cancel`).addEventListener("click", function () {
+      Users.toggleModal("users-modal", "users-modal-card");
+    });
+    let userHandler = this;
+    document.getElementById(`users-modal-save`).addEventListener("click", function () {
+      userHandler.postUser();
+    });
+    document.getElementById(`users-new`).addEventListener("click", function () {
+      userHandler.newUser();
+    });
+  }
+
+  async newUser() {
+    update_user = false;
+    id_field.value = "";
+    login_field.value = "";
+    password_field.value = RandomString(48);
+    passwordhash_field.value = "";
+    name_field.value = "";
+    displayName_field.value = "";
+    surname_field.value = "";
+    role_field.value = "";
+    Users.toggleModal("users-modal", "users-modal-card");
+  }
+
+  async deleteUser(user) {
+    try {
+      const response = await fetch("/api/admin/users/" + user.id, {
+        method: "delete",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`User could not be deleted (status ${response.status})`);
+      }
+      document.getElementById(`users-user-${user.id}`).remove();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  editUser(user) {
+    this.parent.cleanUser(user);
+    update_user = true;
+    id_field.value = user.id;
+    idOAuth_field.value = user.idOAuth;
+    login_field.value = user.login;
+    password_field.value = "";
+    passwordhash_field.value = user.passwordHash;
+    name_field.value = user.name;
+    displayName_field.value = user.displayName;
+    surname_field.value = user.surname;
+    role_field.value = user.role;
+    Users.toggleModal("users-modal", "users-modal-card");
+  }
+
+  async updateUsers() {
+    try {
+      const response = await fetch("/api/admin/users/", {
+        method: "GET",
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`Users could not be fetched (status ${response.status})`);
+      }
+      return await response.json();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+  }
+
+  async getBankerByUserID(userID) {
+    let bankerToSend = undefined;
+    const response = await fetch("/api/UserBankers/", {
+      method: "GET",
+      headers: new Headers({
+        "XSRF-Token": current_user.xsrftoken,
+      }),
+    });
+    if (response.status !== 200) {
+      throw new Error(`Could not get bankers (status ${response.status})`);
+    }
+    let bankers = await response.json();
+    bankers.forEach((banker) => {
+      if (banker.UserID == userID) {
+        bankerToSend = banker;
+      }
+    });
+    return bankerToSend;
+  }
+
+  async postUser() {
+    let method;
+    if (update_user) method = "PUT";
+    else method = "POST";
+
+    try {
+      const response = await fetch("/api/admin/users/" + id_field.value, {
+        method: method,
+        headers: new Headers({
+          "XSRF-Token": current_user.xsrftoken,
+        }),
+        body: JSON.stringify({
+          id: id_field.value,
+          login: login_field.value,
+          password: password_field.value,
+          passwordHash: passwordhash_field.value,
+          name: name_field.value,
+          surname: surname_field.value,
+          role: role_field.value,
+        }),
+      });
+      if (response.status !== 200) {
+        throw new Error(`User could not be updated or created (status ${response.status})`);
+      }
+      let user = await response.json();
+      if (user.role == "BANKER") {
+        let banker = await this.getBankerByUserID(user.id);
+        if (banker != undefined) this.parent.HandleBanker.editBanker(banker);
+        else this.parent.HandleBanker.newBanker(user.id);
+      } else if (user.role == "CLIENT") {
+        let client = await Auth.getClientByUserID(user.id, current_user);
+        if (client != undefined) this.parent.HandleClient.editClient(client);
+        else this.parent.HandleClient.newClient(user.id);
+      } else Users.displayUsers();
+    } catch (e) {
+      Messages.Show("is-warning", e.message);
+      console.error(e);
+    }
+    Users.toggleModal("users-modal", "users-modal-card");
+  }
+}
diff --git a/web/components/users/users.js b/web/components/users/users.js
index 5d508f334554e5440c15333501524fa2751f98c9..958c8e147a22c1bc0322420204985baf56342478 100644
--- a/web/components/users/users.js
+++ b/web/components/users/users.js
@@ -1,288 +1,126 @@
 // Imports
-import * as Messages from "/services/messages/messages.js";
 import { AnimateCSS, RandomString } from "/services/common/common.js";
 import * as Auth from "/services/auth/auth.js";
 import { Delete } from "/services/common/delete.js";
+import * as HandleUser from "/components/users/handleUser.js";
+import * as HandleBanker from "/components/users/handleBanker.js";
+import * as HandleClient from "/components/users/handleClient.js";
 
 // DOM elements
-let mountpoint;
-let id_field;
-let login_field;
-let password_field;
-let passwordhash_field;
-let name_field;
-let surname_field;
-let roles_field;
 
 // local variables
-let users;
 let current_user;
 
 export async function mount(where) {
-  mountpoint = where;
-  document.getElementById(mountpoint).innerHTML = /* HTML */ `
-    <div class="table-container">
-      <table class="table is-bordered is-narrow is-hoverable is-fullwidth">
-        <thead>
-          <tr class="is-selected">
-            <th>Id</th>
-            <th>Login</th>
-            <th>Password</th>
-            <th>Hash</th>
-            <th>Name</th>
-            <th>Surname</th>
-            <th>Roles</th>
-            <th>Actions</th>
-          </tr>
-        </thead>
-        <tbody id="users"></tbody>
-      </table>
-    </div>
-    <button id="users-new" class="button is-primary">
-      <span class="icon is-small">
-        <i class="fas fa-plus"></i>
-      </span>
-    </button>
-
-    <div class="modal" id="users-modal">
-      <div class="modal-background"></div>
-      <div class="modal-card" id="users-modal-card">
-        <header class="modal-card-head">
-          <p class="modal-card-title">Add/Edit user</p>
-          <button class="delete" aria-label="close" id="users-modal-close"></button>
-        </header>
-        <section class="modal-card-body">
-          <div class="field">
-            <label>Id</label>
-            <div class="control">
-              <input class="input" type="number" id="users-modal-id" />
-            </div>
-          </div>
-          <div class="field">
-            <label>Login</label>
-            <div class="control">
-              <input class="input" type="text" id="users-modal-login" />
-            </div>
-          </div>
-          <div class="field" id="users-modal-password-container">
-            <label>Password</label>
-            <div class="control">
-              <input class="input" type="text" id="users-modal-password" />
-            </div>
-          </div>
-          <div class="field" id="users-modal-password-container">
-            <label>Password Hash</label>
-            <div class="control">
-              <input class="input" type="text" id="users-modal-passwordhash" />
-            </div>
-          </div>
-          <div class="field" id="users-modal-name-container">
-            <label>Name</label>
-            <div class="control">
-              <input class="input" type="text" id="users-modal-name" />
-            </div>
-          </div>
-          <div class="field" id="users-modal-surname-container">
-            <label>Surname</label>
-            <div class="control">
-              <input class="input" type="text" id="users-modal-surname" />
-            </div>
-          </div>
-          <div class="field" id="users-modal-roles-container">
-            <label>Roles (separated with commas)</label>
-            <div class="control">
-              <input class="input" type="text" id="users-modal-roles" />
-            </div>
-          </div>
-        </section>
-        <footer class="modal-card-foot">
-          <button id="users-modal-save" class="button is-success">Save changes</button>
-          <button id="users-modal-cancel" class="button">Cancel</button>
-        </footer>
-      </div>
-    </div>
-  `;
-  registerModalFields();
-  current_user = await Auth.GetUser();
-  await firstShowUsers();
+  const userPage = new Users();
+  await userPage.mount(where);
 }
 
-function cleanUser(user) {
-  let props = ["password", "name", "surname", "memberOf"];
-  for (const prop of props) {
-    user[prop] = user[prop] === undefined ? "" : user[prop];
+class Users {
+  constructor() {
+    // Random id seed
+    this.prefix = RandomString(8);
   }
-}
 
-function userTemplate(user) {
-  cleanUser(user);
-  return /* HTML */ `
-    <tr id="users-user-${user.id}">
-      <th>${user.id}</th>
-      <td>${user.login}</td>
-      <td>${user.password}</td>
-      <td>${user.passwordHash === undefined ? "" : "..."}</td>
-      <td>${user.name}</td>
-      <td>${user.surname}</td>
-      <td>${user.memberOf}</td>
-      <td>
-        <a id="users-user-edit-${user.id}" class="button is-link is-small">
-          <span>Edit</span>
-          <span class="icon is-small">
-            <i class="fas fa-pen"></i>
-          </span>
-        </a>
-        <a id="users-user-delete-${user.id}" class="button is-danger is-small">
-          <span>Delete</span>
-          <span class="icon is-small">
-            <i class="fas fa-times"></i>
-          </span>
-        </a>
-      </td>
-    </tr>
-  `;
-}
+  async mount(where) {
+    const mountpoint = where;
+    document.getElementById(mountpoint).innerHTML = /* HTML */ `
+      <div class="table-container">
+        <table class="table is-bordered is-narrow is-hoverable is-fullwidth">
+          <thead>
+            <tr class="is-selected">
+              <th>Id</th>
+              <th>IdOAuth</th>
+              <th>Identifiant</th>
+              <th>Nom complet</th>
+              <th>Nom</th>
+              <th>Surnom</th>
+              <th>Rôle</th>
+              <th>Actions</th>
+            </tr>
+          </thead>
+          <tbody id="users"></tbody>
+        </table>
+      </div>
+      <button id="users-new" class="button is-primary">
+        <span class="icon is-small">
+          <i class="fas fa-plus"></i>
+        </span>
+      </button>
 
-function displayUsers() {
-  const markup = users.map(user => userTemplate(user)).join("");
-  document.getElementById("users").innerHTML = markup;
-  users.map(user => {
-    document.getElementById(`users-user-edit-${user.id}`).addEventListener("click", function() {
-      editUser(user);
-    });
-    document.getElementById(`users-user-delete-${user.id}`).addEventListener("click", function() {
-      new Delete(() => {
-        deleteUser(user);
-      });
-    });
-  });
-}
+      <div class="modal" id="users-modal"></div>
 
-async function firstShowUsers() {
-  try {
-    const response = await fetch("/api/admin/users/", {
-      method: "GET",
-      headers: new Headers({
-        "XSRF-Token": current_user.xsrftoken
-      })
-    });
-    if (response.status !== 200) {
-      throw new Error(`Users could not be fetched (status ${response.status})`);
-    }
-    users = await response.json();
-    displayUsers();
-  } catch (e) {
-    Messages.Show("is-warning", e.message);
-    console.error(e);
+      <div class="modal" id="banker-modal"></div>
+
+      <div class="modal" id="client-modal"></div>
+    `;
+    current_user = await Auth.GetUser();
+    this.HandleUser = await HandleUser.mount("users-modal", this);
+    this.HandleBanker = await HandleBanker.mount("banker-modal", this);
+    this.HandleClient = await HandleClient.mount("client-modal", this);
+    await this.displayUsers();
   }
-}
 
-async function deleteUser(user) {
-  try {
-    const response = await fetch("/api/admin/users/" + user.id, {
-      method: "delete",
-      headers: new Headers({
-        "XSRF-Token": current_user.xsrftoken
-      })
+  async displayUsers() {
+    let users = await this.HandleUser.updateUsers();
+    const markup = users.map((user) => this.userTemplate(user)).join("");
+    document.getElementById("users").innerHTML = markup;
+    let userHandler = this.HandleUser;
+    users.map((user) => {
+      document.getElementById(`users-user-edit-${user.id}`).addEventListener("click", function () {
+        userHandler.editUser(user);
+      });
+      document.getElementById(`users-user-delete-${user.id}`).addEventListener("click", function () {
+        new Delete(() => {
+          userHandler.deleteUser(user);
+        });
+      });
     });
-    if (response.status !== 200) {
-      throw new Error(`User could not be deleted (status ${response.status})`);
-    }
-    document.getElementById(`users-user-${user.id}`).remove();
-  } catch (e) {
-    Messages.Show("is-warning", e.message);
-    console.error(e);
   }
-}
 
-function registerModalFields() {
-  id_field = document.getElementById("users-modal-id");
-  login_field = document.getElementById("users-modal-login");
-  password_field = document.getElementById("users-modal-password");
-  passwordhash_field = document.getElementById("users-modal-passwordhash");
-  name_field = document.getElementById("users-modal-name");
-  surname_field = document.getElementById("users-modal-surname");
-  roles_field = document.getElementById("users-modal-roles");
-  document.getElementById(`users-modal-close`).addEventListener("click", function() {
-    toggleModal();
-  });
-  document.getElementById(`users-modal-cancel`).addEventListener("click", function() {
-    toggleModal();
-  });
-  document.getElementById(`users-modal-save`).addEventListener("click", function() {
-    postUser();
-  });
-  document.getElementById(`users-new`).addEventListener("click", function() {
-    newUser();
-  });
-  password_field.addEventListener("click", function() {
-    password_field.value = RandomString(48);
-  });
-}
-
-async function editUser(user) {
-  cleanUser(user);
-  id_field.value = user.id;
-  login_field.value = user.login;
-  password_field.value = user.passwordHash !== "" ? "" : RandomString(48);
-  passwordhash_field.value = user.passwordHash;
-  name_field.value = user.name;
-  surname_field.value = user.surname;
-  roles_field.value = user.memberOf;
-  toggleModal();
-}
-
-async function newUser() {
-  let maxid = 0;
-  users.map(function(user) {
-    if (parseInt(user.id) > maxid) maxid = user.id;
-  });
-  maxid++;
-  id_field.value = maxid.toString();
-  login_field.value = "";
-  password_field.value = RandomString(48);
-  passwordhash_field.value = "";
-  name_field.value = "";
-  surname_field.value = "";
-  roles_field.value = "";
-  toggleModal();
-}
-
-async function postUser() {
-  try {
-    const response = await fetch("/api/admin/users/", {
-      method: "POST",
-      headers: new Headers({
-        "XSRF-Token": current_user.xsrftoken
-      }),
-      body: JSON.stringify({
-        id: id_field.value,
-        login: login_field.value,
-        password: password_field.value,
-        passwordHash: passwordhash_field.value,
-        name: name_field.value,
-        surname: surname_field.value,
-        memberOf: roles_field.value.split(",")
-      })
-    });
-    if (response.status !== 200) {
-      throw new Error(`Users could not be updated (status ${response.status})`);
+  cleanUser(user) {
+    let props = ["password", "name", "surname", "memberOf"];
+    for (const prop of props) {
+      user[prop] = user[prop] === undefined ? "" : user[prop];
     }
-    users = await response.json();
-    displayUsers();
-  } catch (e) {
-    Messages.Show("is-warning", e.message);
-    console.error(e);
   }
-  toggleModal();
+
+  userTemplate(user) {
+    this.cleanUser(user);
+    return /* HTML */ `
+      <tr id="users-user-${user.id}">
+        <td>${user.id}</td>
+        <td>${user.idOAuth}</td>
+        <td>${user.login}</td>
+        <td>${user.displayName == undefined ? "" : user.displayName}</td>
+        <td>${user.name}</td>
+        <td>${user.surname}</td>
+        <td>${user.role}</td>
+        <td>
+          <a id="users-user-edit-${user.id}" class="button is-link is-small">
+            <span>Modifier</span>
+            <span class="icon is-small">
+              <i class="fas fa-pen"></i>
+            </span>
+          </a>
+          <a id="users-user-delete-${user.id}" class="button is-danger is-small">
+            <span>Supprimer</span>
+            <span class="icon is-small">
+              <i class="fas fa-times"></i>
+            </span>
+          </a>
+        </td>
+      </tr>
+    `;
+  }
 }
 
-function toggleModal() {
-  const modal = document.getElementById("users-modal");
-  const card = document.getElementById("users-modal-card");
+export function toggleModal(modalID, cardID) {
+  const modal = document.getElementById(modalID);
+  const card = document.getElementById(cardID);
   if (modal.classList.contains("is-active")) {
     AnimateCSS(modal, "fadeOut");
-    AnimateCSS(card, "zoomOut", function() {
+    AnimateCSS(card, "zoomOut", function () {
       modal.classList.remove("is-active");
     });
   } else {
diff --git a/web/index.html b/web/index.html
index 717b32451387a14c601d927fc717c9c6778648aa..1b39b9c71505a24232b6ddcc9b175c7226878cba 100644
--- a/web/index.html
+++ b/web/index.html
@@ -1,17 +1,19 @@
 <!DOCTYPE html>
 <html lang="en" class="has-navbar-fixed-top">
-  <title>SDK-GO</title>
-  <meta charset="UTF-8" />
-  <meta name="viewport" content="width=device-width, initial-scale=1" />
-  <link rel="icon" href="assets/brand/favicon.ico" />
-  <link rel="manifest" href="assets/brand/manifest.json" />
-  <link rel="stylesheet" href="assets/bulma.min.css" />
-  <link rel="stylesheet" href="assets/animate.css" />
-  <link rel="stylesheet" href="style.css" />
-  <script defer src="assets/fontawesome/brands.min.js"></script>
-  <script defer src="assets/fontawesome/solid.min.js"></script>
-  <script defer src="assets/fontawesome/fontawesome.min.js"></script>
-  <script defer type="module" src="main.js"></script>
+  <head>
+    <title>SDK-GO</title>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <link rel="icon" href="assets/brand/favicon.ico" />
+    <link rel="manifest" href="assets/brand/manifest.json" />
+    <link rel="stylesheet" href="assets/bulma.min.css" />
+    <link rel="stylesheet" href="assets/animate.css" />
+    <link rel="stylesheet" href="style.css" />
+    <script defer src="assets/fontawesome/brands.min.js"></script>
+    <script defer src="assets/fontawesome/solid.min.js"></script>
+    <script defer src="assets/fontawesome/fontawesome.min.js"></script>
+    <script defer type="module" src="main.js"></script>
+  </head>
   <body>
     <!-- Navbar -->
     <nav id="navbar" class="navbar is-dark is-fixed-top" role="navigation" aria-label="main navigation"></nav>
@@ -23,18 +25,18 @@
     </div>
 
     <!-- Footer -->
-    <nav class="navbar is-dark is-fixed-bottom">
+    <nav aria-label="footer-nav" class="navbar is-dark is-fixed-bottom">
       <div class="navbar-brand">
         <div class="navbar-item">
           <div class="buttons">
-            <a class="button is-primary" href="https://www.github.com/nicolaspernoud/Vestibule" target="_blank">
+            <a class="button is-primary" href="https://www.github.com/nicolaspernoud/Vestibule" target="_blank" rel="noopener noreferrer">
               <span class="icon">
-                <i class="fab fa-github"></i>
+                <em class="fab fa-github"></em>
               </span>
             </a>
-            <a class="button is-danger" href="https://forge.grandlyon.com/NPERNOUD/vestibule" target="_blank">
+            <a class="button is-danger" href="https://forge.grandlyon.com/NPERNOUD/vestibule" target="_blank" rel="noopener noreferrer">
               <span class="icon">
-                <i class="fab fa-gitlab"></i>
+                <em class="fab fa-gitlab"></em>
               </span>
             </a>
           </div>
@@ -42,7 +44,7 @@
       </div>
       <div class="navbar-menu">
         <div class="navbar-end">
-          <div class="navbar-item"><p>v4.2.0</p></div>
+          <div class="navbar-item"><p>v1.0.0</p></div>
         </div>
       </div>
     </nav>
diff --git a/web/main.js b/web/main.js
index f6e9a35bd75a0b98e72cc6023cc2ed4ca0e62666..947158044d8dd777ec93c9afede7882edbcd1d96 100644
--- a/web/main.js
+++ b/web/main.js
@@ -1,10 +1,14 @@
+import * as Home from "/components/home/home.js";
 import * as Users from "/components/users/users.js";
+import * as Client from "/components/clientPage/clientPage.js";
+import * as Banker from "/components/bankerPage/bankerPage.js";
 import * as Login from "/components/login/login.js";
 import * as Navbar from "/components/navbar/navbar.js";
 import { AnimateCSS } from "/services/common/common.js";
 
 const mountPoint = document.getElementById("main");
 const spinner = document.getElementById("spinner");
+let sysInfoInterval;
 
 document.addEventListener("DOMContentLoaded", function() {
   Navbar.mount("navbar");
@@ -13,19 +17,35 @@ document.addEventListener("DOMContentLoaded", function() {
 });
 
 async function navigate() {
+  clearInterval(sysInfoInterval);
   switch (location.hash) {
+    case "#home":
+      load(mountPoint, async function() {
+        await Home.mount("main");
+      });
+      break;
     case "#users":
       load(mountPoint, async function() {
         await Users.mount("main");
       });
       break;
+    case "#client":
+      load(mountPoint, async function() {
+        await Client.mount("main");
+      });
+      break;
+      case "#banker":
+      load(mountPoint, async function() {
+        await Banker.mount("main");
+      });
+      break;
     case "#login":
       load(mountPoint, async function() {
         await Login.mount("main");
       });
       break;
     default:
-      location.hash = "#users";
+      location.hash = "#home";
       break;
   }
 }
diff --git a/web/services/auth/auth.js b/web/services/auth/auth.js
index 6333d8459b0f7e15d1166873db74fbd5af5f2cd9..ffe80d77a498377593309322506fcb0346faf28a 100644
--- a/web/services/auth/auth.js
+++ b/web/services/auth/auth.js
@@ -21,3 +21,23 @@ export async function GetUser() {
     location.hash = "#login";
   }
 }
+
+export async function getClientByUserID(userID, current_user) {
+  let clientToSend = undefined;
+  const response = await fetch("/api/UserClients/", {
+    method: "GET",
+    headers: new Headers({
+      "XSRF-Token": current_user.xsrftoken,
+    }),
+  });
+  if (response.status !== 200) {
+    throw new Error(`Could not get clients (status ${response.status})`);
+  }
+  let clients = await response.json();
+  clients.forEach((client) => {
+    if (client.UserID == userID) {
+      clientToSend = client;
+    }
+  });
+  return clientToSend;
+}
diff --git a/web/style.css b/web/style.css
index 861673e967fee9109296c3d4dbe9fe2693a80069..e3fd68954006a09aa10e5af3e75e14fbddec4980 100644
--- a/web/style.css
+++ b/web/style.css
@@ -87,3 +87,7 @@ img {
 .media a {
   cursor: auto;
 }
+
+.select, select{
+  width :100%;
+}
\ No newline at end of file