123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- package controller
- import (
- "encoding/json"
- "errors"
- "net/http"
- "github.com/gorilla/mux"
- "github.com/gravitl/netmaker/database"
- "github.com/gravitl/netmaker/logger"
- "github.com/gravitl/netmaker/logic"
- "github.com/gravitl/netmaker/logic/pro"
- "github.com/gravitl/netmaker/models"
- "github.com/gravitl/netmaker/models/promodels"
- )
- func networkUsersHandlers(r *mux.Router) {
- r.HandleFunc("/api/networkusers", logic.SecurityCheck(true, http.HandlerFunc(getAllNetworkUsers))).Methods("GET")
- r.HandleFunc("/api/networkusers/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkUsers))).Methods("GET")
- r.HandleFunc("/api/networkusers/{network}/{networkuser}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkUser))).Methods("GET")
- r.HandleFunc("/api/networkusers/{network}", logic.SecurityCheck(true, http.HandlerFunc(createNetworkUser))).Methods("POST")
- r.HandleFunc("/api/networkusers/{network}", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkUser))).Methods("PUT")
- r.HandleFunc("/api/networkusers/data/{networkuser}/me", logic.NetUserSecurityCheck(false, false, http.HandlerFunc(getNetworkUserData))).Methods("GET")
- r.HandleFunc("/api/networkusers/{network}/{networkuser}", logic.SecurityCheck(true, http.HandlerFunc(deleteNetworkUser))).Methods("DELETE")
- }
- // == RETURN TYPES ==
- // NetworkName - represents a network name/ID
- type NetworkName string
- // NetworkUserDataMap - map of all data per network for a user
- type NetworkUserDataMap map[NetworkName]NetworkUserData
- // NetworkUserData - data struct for network users
- type NetworkUserData struct {
- Nodes []models.Node `json:"nodes" bson:"nodes" yaml:"nodes"`
- Clients []models.ExtClient `json:"clients" bson:"clients" yaml:"clients"`
- Vpn []models.Node `json:"vpns" bson:"vpns" yaml:"vpns"`
- Networks []models.Network `json:"networks" bson:"networks" yaml:"networks"`
- User promodels.NetworkUser `json:"user" bson:"user" yaml:"user"`
- }
- // == END RETURN TYPES ==
- // returns a map of a network user's data across all networks
- func getNetworkUserData(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- var params = mux.Vars(r)
- networkUserName := params["networkuser"]
- logger.Log(1, r.Header.Get("user"), "requested fetching network user data for user", networkUserName)
- networks, err := logic.GetNetworks()
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- if networkUserName == "" {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("netuserToGet"), "badrequest"))
- return
- }
- u, err := logic.GetUser(networkUserName)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("could not find user"), "badrequest"))
- return
- }
- // initialize the return data of network users
- returnData := make(NetworkUserDataMap)
- // go through each network and get that user's data
- // if user has no access, give no data
- // if user is a net admin, give all nodes
- // if user has node access, give user's nodes if any
- // if user has client access, git user's clients if any
- for i := range networks {
- netID := networks[i].NetID
- newData := NetworkUserData{
- Nodes: []models.Node{},
- Clients: []models.ExtClient{},
- Vpn: []models.Node{},
- Networks: []models.Network{},
- }
- netUser, err := pro.GetNetworkUser(netID, promodels.NetworkUserID(networkUserName))
- // check if user has access
- if err == nil && netUser.AccessLevel != pro.NO_ACCESS {
- newData.User = promodels.NetworkUser{
- AccessLevel: netUser.AccessLevel,
- ClientLimit: netUser.ClientLimit,
- NodeLimit: netUser.NodeLimit,
- Nodes: netUser.Nodes,
- Clients: netUser.Clients,
- }
- newData.User.SetDefaults()
- // check network level permissions
- if doesNetworkAllow := pro.IsUserAllowed(&networks[i], networkUserName, u.Groups); doesNetworkAllow || netUser.AccessLevel == pro.NET_ADMIN {
- netNodes, err := logic.GetNetworkNodes(netID)
- if err != nil {
- if database.IsEmptyRecord(err) && netUser.AccessLevel == pro.NET_ADMIN {
- newData.Networks = append(newData.Networks, networks[i])
- } else {
- logger.Log(0, "failed to retrieve nodes on network", netID, "for user", string(netUser.ID))
- }
- } else {
- if netUser.AccessLevel <= pro.NODE_ACCESS { // handle nodes
- // if access level is NODE_ACCESS, filter nodes
- if netUser.AccessLevel == pro.NODE_ACCESS {
- for i := range netNodes {
- if logic.StringSliceContains(netUser.Nodes, netNodes[i].ID) {
- newData.Nodes = append(newData.Nodes, netNodes[i])
- }
- }
- } else { // net admin so, get all nodes and ext clients on network...
- newData.Nodes = netNodes
- for i := range netNodes {
- if netNodes[i].IsIngressGateway == "yes" {
- newData.Vpn = append(newData.Vpn, netNodes[i])
- if clients, err := logic.GetExtClientsByID(netNodes[i].ID, netID); err == nil {
- newData.Clients = append(newData.Clients, clients...)
- }
- }
- }
- newData.Networks = append(newData.Networks, networks[i])
- }
- }
- if netUser.AccessLevel <= pro.CLIENT_ACCESS && netUser.AccessLevel != pro.NET_ADMIN {
- for _, c := range netUser.Clients {
- if client, err := logic.GetExtClient(c, netID); err == nil {
- newData.Clients = append(newData.Clients, client)
- }
- }
- for i := range netNodes {
- if netNodes[i].IsIngressGateway == "yes" {
- newData.Vpn = append(newData.Vpn, netNodes[i])
- }
- }
- }
- }
- }
- returnData[NetworkName(netID)] = newData
- }
- }
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(returnData)
- }
- // returns a map of all network users mapped to each network
- func getAllNetworkUsers(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- logger.Log(1, r.Header.Get("user"), "requested fetching all network users")
- type allNetworkUsers = map[string][]promodels.NetworkUser
- networks, err := logic.GetNetworks()
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- var allNetUsers = make(allNetworkUsers, len(networks))
- for i := range networks {
- netusers, err := pro.GetNetworkUsers(networks[i].NetID)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- for _, v := range netusers {
- allNetUsers[networks[i].NetID] = append(allNetUsers[networks[i].NetID], v)
- }
- }
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(allNetUsers)
- }
- func getNetworkUsers(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- var params = mux.Vars(r)
- netname := params["network"]
- logger.Log(1, r.Header.Get("user"), "requested fetching network users for network", netname)
- _, err := logic.GetNetwork(netname)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- netusers, err := pro.GetNetworkUsers(netname)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(netusers)
- }
- func getNetworkUser(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- var params = mux.Vars(r)
- netname := params["network"]
- logger.Log(1, r.Header.Get("user"), "requested fetching network user", params["networkuser"], "on network", netname)
- _, err := logic.GetNetwork(netname)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- netuserToGet := params["networkuser"]
- if netuserToGet == "" {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("netuserToGet"), "badrequest"))
- return
- }
- netuser, err := pro.GetNetworkUser(netname, promodels.NetworkUserID(netuserToGet))
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(netuser)
- }
- func createNetworkUser(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- var params = mux.Vars(r)
- netname := params["network"]
- logger.Log(1, r.Header.Get("user"), "requested creating a network user on network", netname)
- network, err := logic.GetNetwork(netname)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- var networkuser promodels.NetworkUser
- // we decode our body request params
- err = json.NewDecoder(r.Body).Decode(&networkuser)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- err = pro.CreateNetworkUser(&network, &networkuser)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- w.WriteHeader(http.StatusOK)
- }
- func updateNetworkUser(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- var params = mux.Vars(r)
- netname := params["network"]
- logger.Log(1, r.Header.Get("user"), "requested updating a network user on network", netname)
- network, err := logic.GetNetwork(netname)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- var networkuser promodels.NetworkUser
- // we decode our body request params
- err = json.NewDecoder(r.Body).Decode(&networkuser)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- if networkuser.ID == "" || !pro.DoesNetworkUserExist(netname, networkuser.ID) {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid user "+string(networkuser.ID)), "badrequest"))
- return
- }
- if networkuser.AccessLevel < pro.NET_ADMIN || networkuser.AccessLevel > pro.NO_ACCESS {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid user access level provided"), "badrequest"))
- return
- }
- if networkuser.ClientLimit < 0 || networkuser.NodeLimit < 0 {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("negative user limit provided"), "badrequest"))
- return
- }
- u, err := logic.GetUser(string(networkuser.ID))
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid user "+string(networkuser.ID)), "badrequest"))
- return
- }
- if !pro.IsUserAllowed(&network, u.UserName, u.Groups) {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user must be in allowed groups or users"), "badrequest"))
- return
- }
- if networkuser.AccessLevel == pro.NET_ADMIN {
- currentUser, err := logic.GetUser(string(networkuser.ID))
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user model not found for "+string(networkuser.ID)), "badrequest"))
- return
- }
- if !logic.StringSliceContains(currentUser.Networks, netname) {
- // append network name to user model to conform to old model
- if err = logic.UpdateUserNetworks(
- append(currentUser.Networks, netname),
- currentUser.Groups,
- currentUser.IsAdmin,
- &models.ReturnUser{
- Groups: currentUser.Groups,
- IsAdmin: currentUser.IsAdmin,
- Networks: currentUser.Networks,
- UserName: currentUser.UserName,
- },
- ); err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user model failed net admin update "+string(networkuser.ID)+" (are they an admin?"), "badrequest"))
- return
- }
- }
- }
- err = pro.UpdateNetworkUser(netname, &networkuser)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- w.WriteHeader(http.StatusOK)
- }
- func deleteNetworkUser(w http.ResponseWriter, r *http.Request) {
- var params = mux.Vars(r)
- netname := params["network"]
- logger.Log(1, r.Header.Get("user"), "requested deleting network user", params["networkuser"], "on network", netname)
- _, err := logic.GetNetwork(netname)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- netuserToDelete := params["networkuser"]
- if netuserToDelete == "" {
- logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("no group name provided"), "badrequest"))
- return
- }
- if err := pro.DeleteNetworkUser(netname, netuserToDelete); err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- w.WriteHeader(http.StatusOK)
- }
|