Bläddra i källkod

setup event logger, add event for user login

abhishek9686 4 månader sedan
förälder
incheckning
2121ad7e03
6 ändrade filer med 130 tillägg och 45 borttagningar
  1. 59 0
      controllers/user.go
  2. 1 2
      logic/telemetry.go
  3. 51 0
      models/events.go
  4. 0 1
      pro/controllers/users.go
  5. 17 5
      pro/logic/events.go
  6. 2 37
      schema/activity.go

+ 59 - 0
controllers/user.go

@@ -43,6 +43,7 @@ func userHandlers(r *mux.Router) {
 	r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(createUserAccessToken))).Methods(http.MethodPost)
 	r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(getUserAccessTokens))).Methods(http.MethodGet)
 	r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(deleteUserAccessTokens))).Methods(http.MethodDelete)
+	r.HandleFunc("/api/v1/user/logout", logic.SecurityCheck(true, http.HandlerFunc(logout))).Methods(http.MethodPost)
 }
 
 // @Summary     Authenticate a user to retrieve an authorization token
@@ -258,6 +259,36 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
 			logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("access denied to dashboard"), "unauthorized"))
 			return
 		}
+		// log user activity
+		logic.LogEvent(models.Activity{
+			Action: models.Login,
+			Source: models.Subject{
+				ID:   user.UserName,
+				Name: user.UserName,
+				Type: models.UserSub,
+			},
+			Target: models.Subject{
+				ID:   models.DashboardSub.String(),
+				Name: models.DashboardSub.String(),
+				Type: models.DashboardSub,
+			},
+			Origin: models.Dashboard,
+		})
+	} else {
+		logic.LogEvent(models.Activity{
+			Action: models.Login,
+			Source: models.Subject{
+				ID:   user.UserName,
+				Name: user.UserName,
+				Type: models.UserSub,
+			},
+			Target: models.Subject{
+				ID:   models.ClientAppSub.String(),
+				Name: models.ClientAppSub.String(),
+				Type: models.ClientAppSub,
+			},
+			Origin: models.ClientApp,
+		})
 	}
 
 	username := authRequest.UserName
@@ -902,3 +933,31 @@ func listRoles(w http.ResponseWriter, r *http.Request) {
 
 	logic.ReturnSuccessResponseWithJson(w, r, roles, "successfully fetched user roles permission templates")
 }
+
+// swagger:route POST /api/v1/user/logout user logout
+//
+// LogOut user.
+//
+//			Schemes: https
+//
+//			Security:
+//	  		oauth
+//
+//			Responses:
+//				200: userBodyResponse
+func logout(w http.ResponseWriter, r *http.Request) {
+	// set header.
+	w.Header().Set("Content-Type", "application/json")
+
+	users, err := logic.GetUsers()
+
+	if err != nil {
+		logger.Log(0, "failed to fetch users: ", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+
+	logic.SortUsers(users[:])
+	logger.Log(2, r.Header.Get("user"), "fetched users")
+	json.NewEncoder(w).Encode(users)
+}

+ 1 - 2
logic/telemetry.go

@@ -7,7 +7,6 @@ import (
 
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
-	"github.com/gravitl/netmaker/schema"
 
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
@@ -21,7 +20,7 @@ var (
 	telServerRecord = models.Telemetry{}
 )
 
-var LogEvent = func(a schema.Activity) {}
+var LogEvent = func(a models.Activity) {}
 
 // posthog_pub_key - Key for sending data to PostHog
 const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES"

+ 51 - 0
models/events.go

@@ -0,0 +1,51 @@
+package models
+
+type Action string
+
+const (
+	Create Action = "CREATE"
+	Update Action = "UPDATE"
+	Delete Action = "DELETE"
+	Login  Action = "LOGIN"
+)
+
+type SubjectType string
+
+const (
+	UserSub      SubjectType = "USER"
+	DeviceSub    SubjectType = "DEVICE"
+	NodeSub      SubjectType = "NODE"
+	SettingSub   SubjectType = "SETTING"
+	AclSub       SubjectType = "ACLs"
+	EgressSub    SubjectType = "EGRESS"
+	NetworkSub   SubjectType = "NETWORK"
+	DashboardSub SubjectType = "DASHBOARD"
+	ClientAppSub SubjectType = "CLIENT-APP"
+)
+
+func (sub SubjectType) String() string {
+	return string(sub)
+}
+
+type Origin string
+
+const (
+	Dashboard Origin = "DASHBOARD"
+	Api       Origin = "API"
+	NMCTL     Origin = "NMCTL"
+	ClientApp Origin = "CLIENT-APP"
+)
+
+type Subject struct {
+	ID   string      `json:"id"`
+	Name string      `json:"name"`
+	Type SubjectType `json:"subject_type"`
+}
+
+type Activity struct {
+	Action    Action
+	Source    Subject
+	Origin    Origin
+	Target    Subject
+	NetworkID NetworkID
+}

+ 0 - 1
pro/controllers/users.go

@@ -62,7 +62,6 @@ func UserHandlers(r *mux.Router) {
 	r.HandleFunc("/api/users/{username}/remote_access_gw/{remote_access_gateway_id}", logic.SecurityCheck(true, http.HandlerFunc(removeUserFromRemoteAccessGW))).Methods(http.MethodDelete)
 	r.HandleFunc("/api/users/{username}/remote_access_gw", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUserRemoteAccessGwsV1)))).Methods(http.MethodGet)
 	r.HandleFunc("/api/users/ingress/{ingress_id}", logic.SecurityCheck(true, http.HandlerFunc(ingressGatewayUsers))).Methods(http.MethodGet)
-
 }
 
 // swagger:route POST /api/v1/users/invite-signup user userInviteSignUp

+ 17 - 5
pro/logic/events.go

@@ -2,24 +2,36 @@ package logic
 
 import (
 	"context"
+	"encoding/json"
+	"time"
 
+	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/db"
+	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/schema"
 )
 
-var EventActivityCh = make(chan schema.Activity, 100)
+var EventActivityCh = make(chan models.Activity, 100)
 
-func LogEvent(a schema.Activity) {
+func LogEvent(a models.Activity) {
 	EventActivityCh <- a
 }
 
 func EventWatcher() {
 
 	for e := range EventActivityCh {
-		if e.ID == "CLOSE" {
-			return
+		sourceJson, _ := json.Marshal(e.Source)
+		dstJson, _ := json.Marshal(e.Target)
+		a := schema.Activity{
+			ID:        uuid.New().String(),
+			Action:    e.Action,
+			Source:    sourceJson,
+			Target:    dstJson,
+			Origin:    e.Origin,
+			NetworkID: e.NetworkID,
+			TimeStamp: time.Now().UTC(),
 		}
-		e.Create(db.WithContext(context.TODO()))
+		a.Create(db.WithContext(context.TODO()))
 	}
 
 }

+ 2 - 37
schema/activity.go

@@ -9,46 +9,11 @@ import (
 	"gorm.io/datatypes"
 )
 
-type Action string
-
-const (
-	Create Action = "CREATE"
-	Update Action = "UPDATE"
-	Delete Action = "DELETE"
-)
-
-type SubjectType string
-
-const (
-	UserSub    SubjectType = "USER"
-	DeviceSub  SubjectType = "DEVICE"
-	NodeSub    SubjectType = "NODE"
-	SettingSub SubjectType = "SETTING"
-	AclSub     SubjectType = "ACLs"
-	EgressSub  SubjectType = "EGRESS"
-	NetworkSub SubjectType = "NETWORK"
-)
-
-type Origin string
-
-const (
-	Dashboard Origin = "DASHBOARD"
-	Api       Origin = "API"
-	NMCTL     Origin = "NMCTL"
-	ClientApp Origin = "CLIENT-APP"
-)
-
-type Subject struct {
-	ID   string      `json:"id"`
-	Name string      `json:"name"`
-	Type SubjectType `json:"subject_type"`
-}
-
 type Activity struct {
 	ID        string           `gorm:"primaryKey" json:"id"`
-	Action    Action           `gorm:"action" json:"action"`
+	Action    models.Action    `gorm:"action" json:"action"`
 	Source    datatypes.JSON   `gorm:"source" json:"source"`
-	Origin    string           `gorm:"origin" json:"origin"`
+	Origin    models.Origin    `gorm:"origin" json:"origin"`
 	Target    datatypes.JSON   `gorm:"target" json:"target"`
 	NetworkID models.NetworkID `gorm:"network_id" json:"network_id"`
 	TimeStamp time.Time        `gorm:"time_stamp" json:"time_stamp"`