Skip to content

Commit

Permalink
refactor(api) improve Cognitive Complexity
Browse files Browse the repository at this point in the history
  • Loading branch information
helderbetiol committed Jun 14, 2024
1 parent 7dfa5a5 commit 2c73718
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 96 deletions.
4 changes: 0 additions & 4 deletions API/app/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ var JwtAuthentication = func(next http.Handler) http.Handler {
if tokenHeader == "" {
response = u.Message("Missing auth token")
w.WriteHeader(http.StatusForbidden)
w.Header().Add("Content-Type", "application/json")
u.Respond(w, response)
return
}
Expand All @@ -58,7 +57,6 @@ var JwtAuthentication = func(next http.Handler) http.Handler {
if len(splitted) != 2 {
response = u.Message("Invalid/Malformed auth token")
w.WriteHeader(http.StatusForbidden)
w.Header().Add("Content-Type", "application/json")
u.Respond(w, response)
return
}
Expand All @@ -75,7 +73,6 @@ var JwtAuthentication = func(next http.Handler) http.Handler {
if err != nil {
response = u.Message("Malformed authentication token")
w.WriteHeader(http.StatusForbidden)
w.Header().Add("Content-Type", "application/json")
u.Respond(w, response)
return
}
Expand All @@ -84,7 +81,6 @@ var JwtAuthentication = func(next http.Handler) http.Handler {
if !token.Valid || ((tk.Email == u.RESET_TAG) != (requestPath == "/api/users/password/reset")) {
response = u.Message("Token is not valid.")
w.WriteHeader(http.StatusForbidden)
w.Header().Add("Content-Type", "application/json")
u.Respond(w, response)
return
}
Expand Down
111 changes: 58 additions & 53 deletions API/controllers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ func CreateAccount(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "POST, OPTIONS")
u.WriteOptionsHeader(w, "POST")
} else {
account := &models.Account{}
err := json.NewDecoder(r.Body).Decode(account)
Expand Down Expand Up @@ -185,8 +184,7 @@ func Authenticate(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "POST, OPTIONS")
u.WriteOptionsHeader(w, "POST")
} else {
var account models.Account
err := json.NewDecoder(r.Body).Decode(&account)
Expand Down Expand Up @@ -229,8 +227,7 @@ func VerifyToken(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS")
u.WriteOptionsHeader(w, "GET")
} else {
u.Respond(w, u.Message("working"))
}
Expand All @@ -256,8 +253,7 @@ func GetAllAccounts(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "GET, HEAD")
} else {
var resp map[string]interface{}

Expand Down Expand Up @@ -310,8 +306,7 @@ func RemoveAccount(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "DELETE, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "DELETE, HEAD")
} else {
// Get caller user
callerUser := getUserFromToken(w, r)
Expand Down Expand Up @@ -389,36 +384,18 @@ func ModifyUserRoles(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "PATCH, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "PATCH, HEAD")
} else {
var resp map[string]interface{}
userId := mux.Vars(r)["id"]

// Check if POST body is valid
var data map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&data)
rolesConverted, err := getUserRolesFromBody(r)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
u.Respond(w, u.Message("Invalid request"))
u.Respond(w, u.Message(err.Error()))
return
}
roles, ok := data["roles"].(map[string]interface{})
if len(data) > 1 || !ok {
w.WriteHeader(http.StatusBadRequest)
u.Respond(w, u.Message("Only 'roles' should be provided to patch"))
return
}
rolesConverted := map[string]models.Role{}
for k := range roles {
if v, ok := roles[k].(string); ok {
rolesConverted[k] = models.Role(v)
} else {
w.WriteHeader(http.StatusBadRequest)
u.Respond(w, u.Message("Invalid roles format"))
return
}
}

// Get caller user
callerUser := getUserFromToken(w, r)
Expand Down Expand Up @@ -454,6 +431,28 @@ func ModifyUserRoles(w http.ResponseWriter, r *http.Request) {
}
}

func getUserRolesFromBody(r *http.Request) (map[string]models.Role, error) {
var data map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil {
return nil, fmt.Errorf("invalid request")
}

roles, ok := data["roles"].(map[string]interface{})
if len(data) > 1 || !ok {
return nil, fmt.Errorf("only 'roles' should be provided to patch")
}
rolesConverted := map[string]models.Role{}
for k := range roles {
if v, ok := roles[k].(string); ok {
rolesConverted[k] = models.Role(v)
} else {
return nil, fmt.Errorf("invalid roles format")
}
}
return rolesConverted, nil
}

// swagger:operation POST /api/users/password/change Authentication ModifyUserPassword
// For logged in user to change its own password.
// ---
Expand Down Expand Up @@ -509,8 +508,7 @@ func ModifyUserPassword(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "POST, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "POST, HEAD")
} else {
// Get user ID and email from token
userData := r.Context().Value("user")
Expand All @@ -524,26 +522,11 @@ func ModifyUserPassword(w http.ResponseWriter, r *http.Request) {
userEmail := userData.(map[string]interface{})["email"].(string)

// Check if POST body is valid
var data map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&data)
currentPassword, newPassword, isReset,
err := getModifyPassDataFromBody(r, userEmail)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
u.Respond(w, u.Message("Invalid request"))
return
}
isReset := false
hasCurrent := true
currentPassword := ""
if userEmail == u.RESET_TAG {
// it's not change, it's reset (no need for current password)
isReset = true
} else {
currentPassword, hasCurrent = data["currentPassword"].(string)
}
newPassword, hasNew := data["newPassword"].(string)
if !hasCurrent || !hasNew {
w.WriteHeader(http.StatusBadRequest)
u.Respond(w, u.Message("Invalid request: wrong body format"))
u.Respond(w, u.Message(err.Error()))
return
}

Expand Down Expand Up @@ -575,6 +558,29 @@ func ModifyUserPassword(w http.ResponseWriter, r *http.Request) {
}
}

func getModifyPassDataFromBody(r *http.Request, userEmail string) (string, string, bool, error) {
isReset := false
hasCurrent := true
currentPassword := ""
var data map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil {
return currentPassword, "", isReset, err
}
if userEmail == u.RESET_TAG {
// it's not change, it's reset (no need for current password)
isReset = true
} else {
currentPassword, hasCurrent = data["currentPassword"].(string)
}
newPassword, hasNew := data["newPassword"].(string)
if !hasCurrent || !hasNew {
return currentPassword, "", isReset,
fmt.Errorf("invalid request: wrong body format")
}
return currentPassword, newPassword, isReset, nil
}

// swagger:operation POST /api/users/password/forgot Authentication UserForgotPassword
// Forgot my password.
// Public endpoint to request a reset of a user's password (forgot my password).
Expand Down Expand Up @@ -605,8 +611,7 @@ func UserForgotPassword(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "POST, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "POST, HEAD")
} else {
// Check if POST body is valid
var data map[string]interface{}
Expand Down
40 changes: 12 additions & 28 deletions API/controllers/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,7 @@ func HandleGenericObjects(w http.ResponseWriter, r *http.Request) {
}
u.Respond(w, u.RespDataWrapper("successfully deleted objects", matchingObjects))
} else if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS")
u.WriteOptionsHeader(w, "GET")
} else {
matchingObjects = pie.Map(matchingObjects, func(object map[string]any) map[string]any {
entityStr := object["entity"].(string)
Expand Down Expand Up @@ -702,8 +701,7 @@ func HandleComplexFilters(w http.ResponseWriter, r *http.Request) {
}
u.Respond(w, u.RespDataWrapper("successfully deleted objects", matchingObjects))
} else if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "POST, OPTIONS")
u.WriteOptionsHeader(w, "POST")
} else {
u.Respond(w, u.RespDataWrapper("successfully processed request", matchingObjects))
}
Expand Down Expand Up @@ -801,8 +799,7 @@ func GetEntity(w http.ResponseWriter, r *http.Request) {

// Respond
if r.Method == "OPTIONS" && data != nil {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, DELETE, OPTIONS, PATCH, PUT")
u.WriteOptionsHeader(w, "GET, DELETE, OPTIONS, PATCH, PUT")
} else {
if modelErr != nil {
u.ErrLog("Error while getting "+entityStr, "GET "+strings.ToUpper(entityStr),
Expand Down Expand Up @@ -911,8 +908,7 @@ func GetLayerObjects(w http.ResponseWriter, r *http.Request) {

// Respond
if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, DELETE, OPTIONS, PATCH, PUT")
u.WriteOptionsHeader(w, "GET, DELETE, PATCH, PUT")
} else {
u.Respond(w, u.RespDataWrapper("successfully processed request", matchingObjects))
}
Expand Down Expand Up @@ -1443,8 +1439,7 @@ func GetSiteAttr(w http.ResponseWriter, r *http.Request) {
u.RespondWithError(w, err)
} else {
if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "GET, HEAD")
} else {
resp := u.RespDataWrapper(
"successfully got attribute from object's parent site",
Expand Down Expand Up @@ -1540,8 +1535,7 @@ func GetEntitiesOfAncestor(w http.ResponseWriter, r *http.Request) {
"GET CHILDRENOFPARENT", modelErr.Message, r)
u.RespondWithError(w, modelErr)
} else if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS")
u.WriteOptionsHeader(w, "GET")
} else {
u.Respond(w, u.RespDataWrapper("successfully got object", data))
}
Expand Down Expand Up @@ -1663,8 +1657,7 @@ func GetHierarchyByName(w http.ResponseWriter, r *http.Request) {
u.ErrLog("Error while getting "+entity, "GET "+entity, modelErr.Message, r)
u.RespondWithError(w, modelErr)
} else if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS")
u.WriteOptionsHeader(w, "GET")
} else {
u.Respond(w, u.RespDataWrapper("successfully got object's hierarchy", data))
}
Expand Down Expand Up @@ -1723,8 +1716,7 @@ func GetCompleteHierarchy(w http.ResponseWriter, r *http.Request) {
u.RespondWithError(w, err)
} else {
if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "GET, HEAD")
} else {
u.Respond(w, u.RespDataWrapper("successfully got hierarchy", data))
}
Expand Down Expand Up @@ -1763,8 +1755,7 @@ func GetCompleteHierarchyAttributes(w http.ResponseWriter, r *http.Request) {
u.RespondWithError(w, err)
} else {
if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "GET, HEAD")
} else {
u.Respond(w, u.RespDataWrapper("successfully got attrs hierarchy", data))
}
Expand Down Expand Up @@ -1957,9 +1948,7 @@ func BaseOption(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, DELETE, OPTIONS, PATCH, POST, PUT")

u.WriteOptionsHeader(w, "GET, DELETE, PATCH, PUT, POST")
}

// swagger:operation GET /api/stats About GetStats
Expand All @@ -1982,13 +1971,10 @@ func GetStats(w http.ResponseWriter, r *http.Request) {
DispRequestMetaData(r)
if r.Method == "OPTIONS" {
w.Header().Add("Allow", "GET, HEAD, OPTIONS")
//w.WriteHeader(http.StatusOK)
} else {
r := models.GetStats()
u.Respond(w, r)
}
//w.Header().Add("Content-Type", "application/json")

}

// swagger:operation POST /api/validate/{entity} Objects ValidateObject
Expand Down Expand Up @@ -2044,8 +2030,7 @@ func ValidateEntity(w http.ResponseWriter, r *http.Request) {
}

if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "POST, OPTIONS")
u.WriteOptionsHeader(w, "POST")
return
}

Expand Down Expand Up @@ -2093,8 +2078,7 @@ func ValidateEntity(w http.ResponseWriter, r *http.Request) {
func GetVersion(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{}
if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS, HEAD")
u.WriteOptionsHeader(w, "GET, HEAD")
return
} else {
data["status"] = true
Expand Down
5 changes: 2 additions & 3 deletions API/controllers/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,9 @@ func GetSchemaJSON(w http.ResponseWriter, r *http.Request) {
"GET GetSchemaJSON", err.Message, r)
u.RespondWithError(w, err)
} else if r.Method == "OPTIONS" {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Allow", "GET, OPTIONS")
u.WriteOptionsHeader(w, "GET")
} else {
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Content-Type", u.HttpResponseContentType)
w.Write(file)
}
}
Loading

0 comments on commit 2c73718

Please sign in to comment.