oktopus/backend/services/controller/internal/api/user.go

303 lines
6.6 KiB
Go

package api
import (
"encoding/json"
"log"
"net/http"
"net/mail"
"github.com/gorilla/mux"
"github.com/leandrofars/oktopus/internal/api/auth"
"github.com/leandrofars/oktopus/internal/db"
"github.com/leandrofars/oktopus/internal/utils"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func (a *Api) retrieveUsers(w http.ResponseWriter, r *http.Request) {
users, err := a.db.FindAllUsers()
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
for _, x := range users {
objectID, ok := x["_id"].(primitive.ObjectID)
if ok {
creationTime := objectID.Timestamp()
x["createdAt"] = creationTime.Format("02/01/2006")
}
delete(x, "password")
}
err = json.NewEncoder(w).Encode(users)
if err != nil {
log.Println(err)
}
}
func (a *Api) registerUser(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
if tokenString == "" {
w.WriteHeader(http.StatusUnauthorized)
return
}
email, err := auth.ValidateToken(tokenString)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
//Check if user which is requesting creation has the necessary privileges
rUser, err := a.db.FindUser(email)
if rUser.Level != db.AdminUser {
w.WriteHeader(http.StatusForbidden)
return
}
var user db.User
err = json.NewDecoder(r.Body).Decode(&user)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
user.Level = db.NormalUser
if err := user.HashPassword(user.Password); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
if user.Email == "" || user.Password == "" || !valid(user.Email) {
w.WriteHeader(http.StatusBadRequest)
return
}
if err := a.db.RegisterUser(user); err != nil {
if err == db.ErrorUserExists {
w.WriteHeader(http.StatusConflict)
w.Write([]byte("User with this email already exists"))
return
}
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func valid(email string) bool {
_, err := mail.ParseAddress(email)
return err == nil
}
func (a *Api) deleteUser(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
if tokenString == "" {
w.WriteHeader(http.StatusUnauthorized)
return
}
email, err := auth.ValidateToken(tokenString)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
//Check if user which is requesting deletion has the necessary privileges
rUser, err := a.db.FindUser(email)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
userEmail := mux.Vars(r)["user"]
if rUser.Email == userEmail || (rUser.Level == db.AdminUser) { //Admin can delete any account
if err := a.db.DeleteUser(userEmail); err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(err)
return
}
} else {
w.WriteHeader(http.StatusForbidden)
}
}
func (a *Api) changePassword(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
if tokenString == "" {
w.WriteHeader(http.StatusUnauthorized)
return
}
email, err := auth.ValidateToken(tokenString)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
userToChangePasswd := mux.Vars(r)["user"]
if userToChangePasswd != "" && userToChangePasswd != email {
rUser, _ := a.db.FindUser(email)
if rUser.Level != db.AdminUser {
w.WriteHeader(http.StatusForbidden)
return
}
email = userToChangePasswd
}
var user db.User
err = json.NewDecoder(r.Body).Decode(&user)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
utils.MarshallEncoder(err, w)
return
}
user.Email = email
if err := user.HashPassword(user.Password); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
if err := a.db.UpdatePassword(user); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func (a *Api) registerAdminUser(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
if tokenString == "" {
users, err := a.db.FindAllUsers()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
utils.MarshallEncoder(err, w)
}
if !adminUserExists(users) {
var user db.User
err = json.NewDecoder(r.Body).Decode(&user)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
user.Level = db.AdminUser
if err := user.HashPassword(user.Password); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
if err := a.db.RegisterUser(user); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
} else {
w.WriteHeader(http.StatusForbidden)
}
return
}
email, err := auth.ValidateToken(tokenString)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
//Check if user which is requesting creation has the necessary privileges
rUser, err := a.db.FindUser(email)
if rUser.Level != db.AdminUser {
w.WriteHeader(http.StatusForbidden)
return
}
var user db.User
err = json.NewDecoder(r.Body).Decode(&user)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
user.Level = db.AdminUser
if err := user.HashPassword(user.Password); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
if err := a.db.RegisterUser(user); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func adminUserExists(users []map[string]interface{}) bool {
if len(users) == 0 {
return false
}
for _, x := range users {
if db.UserLevels(x["level"].(int32)) == db.AdminUser {
return true
}
}
return false
}
func (a *Api) adminUserExists(w http.ResponseWriter, r *http.Request) {
users, err := a.db.FindAllUsers()
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
adminExits := adminUserExists(users)
json.NewEncoder(w).Encode(adminExits)
return
}
type TokenRequest struct {
Email string `json:"email"`
Password string `json:"password"`
}
func (a *Api) generateToken(w http.ResponseWriter, r *http.Request) {
var tokenReq TokenRequest
err := json.NewDecoder(r.Body).Decode(&tokenReq)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
user, err := a.db.FindUser(tokenReq.Email)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
json.NewEncoder(w).Encode("Invalid Credentials")
return
}
credentialError := user.CheckPassword(tokenReq.Password)
if credentialError != nil {
w.WriteHeader(http.StatusUnauthorized)
json.NewEncoder(w).Encode("Invalid Credentials")
return
}
token, err := auth.GenerateJWT(user.Email, user.Name)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Add("Content-Type", "application/json")
json.NewEncoder(w).Encode(token)
return
}