-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add #302 Add endpoint for admin logs
1 parent
8a6373f
commit 7dfd0ba
Showing
8 changed files
with
267 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package actionlog | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/bb-consent/api/src/database" | ||
"go.mongodb.org/mongo-driver/bson" | ||
"go.mongodb.org/mongo-driver/bson/primitive" | ||
"go.mongodb.org/mongo-driver/mongo" | ||
) | ||
|
||
// Log type const | ||
const ( | ||
LogTypeSecurity = 1 | ||
LogTypeAPICalls = 2 | ||
LogTypeOrgUpdates = 3 | ||
LogTypeUserUpdates = 4 | ||
LogTypeWebhook = 5 | ||
) | ||
|
||
// LogType Log type | ||
type LogType struct { | ||
ID int | ||
Str string | ||
} | ||
|
||
// Note: Dont change the ID(s) if new type is needed then add at the end | ||
|
||
// LogTypes Array of id and string | ||
var LogTypes = []LogType{ | ||
{ID: LogTypeSecurity, Str: "Security"}, | ||
{ID: LogTypeAPICalls, Str: "API calls"}, | ||
{ID: LogTypeOrgUpdates, Str: "OrgUpdates"}, | ||
{ID: LogTypeUserUpdates, Str: "UserUpdates"}, | ||
{ID: LogTypeWebhook, Str: "Webhooks"}} | ||
|
||
// GetTypeStr Get type string from ID | ||
func GetTypeStr(logType int) string { | ||
return LogTypes[logType-1].Str | ||
} | ||
|
||
// ActionLog All access logs | ||
type ActionLog struct { | ||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` | ||
Type int `json:"type"` | ||
TypeStr string `json:"typeStr"` | ||
OrgID string `json:"orgId"` | ||
UserID string `json:"userId"` | ||
UserName string `json:"userName"` | ||
Action string `json:"action"` //Free string storing the real log | ||
} | ||
|
||
type ActionLogRepository struct { | ||
DefaultFilter bson.M | ||
} | ||
|
||
// Init | ||
func (actionLogRepo *ActionLogRepository) Init(organisationId string) { | ||
actionLogRepo.DefaultFilter = bson.M{"orgid": organisationId} | ||
} | ||
|
||
func Collection() *mongo.Collection { | ||
return database.DB.Client.Database(database.DB.Name).Collection("actionLogs") | ||
} | ||
|
||
// Add Adds access log | ||
func Add(log ActionLog) error { | ||
_, err := Collection().InsertOne(context.TODO(), log) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
// GetAccessLogByOrgID gets all notifications of a given user | ||
func (actionLogRepo *ActionLogRepository) GetAccessLogByOrgID() (results []ActionLog, err error) { | ||
filter := actionLogRepo.DefaultFilter | ||
|
||
cursor, err := Collection().Find(context.TODO(), filter) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer cursor.Close(context.TODO()) | ||
|
||
if err := cursor.All(context.TODO(), &results); err != nil { | ||
return nil, err | ||
} | ||
return results, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package actionlog | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
) | ||
|
||
func doActionLog(l ActionLog) error { | ||
err := Add(l) | ||
if err != nil { | ||
log.Printf("Failed to add access log for user: %v org: %v", l.UserID, l.OrgID) | ||
} | ||
fmt.Printf("%v \n", l) | ||
return err | ||
} | ||
|
||
// LogOrgSecurityCalls Logs all important access related entries | ||
func LogOrgSecurityCalls(userID string, uName string, orgID string, aLog string) { | ||
var l ActionLog | ||
l.OrgID = orgID | ||
l.UserID = userID | ||
l.UserName = uName | ||
l.Action = aLog | ||
l.Type = LogTypeSecurity | ||
l.TypeStr = GetTypeStr(l.Type) | ||
|
||
doActionLog(l) | ||
} | ||
|
||
// LogOrgWebhookCalls Logs all webhook triggers based on different events | ||
func LogOrgWebhookCalls(userID string, uName string, orgID string, aLog string) { | ||
var l ActionLog | ||
l.OrgID = orgID | ||
l.UserID = userID | ||
l.UserName = uName | ||
l.Action = aLog | ||
l.Type = LogTypeWebhook | ||
l.TypeStr = GetTypeStr(l.Type) | ||
|
||
doActionLog(l) | ||
} | ||
|
||
// LogOrgAPICalls Organization API calls are logged for future reference | ||
func LogOrgAPICalls(userID string, uName string, orgID string, aLog string) { | ||
var l ActionLog | ||
l.OrgID = orgID | ||
l.UserID = userID | ||
l.UserName = uName | ||
l.Action = aLog | ||
l.Type = LogTypeAPICalls | ||
l.TypeStr = GetTypeStr(l.Type) | ||
|
||
doActionLog(l) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package audit | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
"log" | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/bb-consent/api/src/common" | ||
"github.com/bb-consent/api/src/config" | ||
"github.com/bb-consent/api/src/v2/actionlog" | ||
"github.com/bb-consent/api/src/v2/paginate" | ||
"go.mongodb.org/mongo-driver/bson" | ||
"go.mongodb.org/mongo-driver/bson/primitive" | ||
) | ||
|
||
// ListActionLogsError is an error enumeration for action logs API. | ||
type ListActionLogsError int | ||
|
||
const ( | ||
// ActionLogTypeIsMissingError indicates that the action log query param is missing. | ||
ActionLogTypeIsMissingError ListActionLogsError = iota | ||
) | ||
|
||
// Error returns the string representation of the error. | ||
func (e ListActionLogsError) Error() string { | ||
switch e { | ||
case ActionLogTypeIsMissingError: | ||
return "Query param action log type is missing!" | ||
default: | ||
return "Unknown error!" | ||
} | ||
} | ||
|
||
// ParseListActionLogQueryParams parses query params for listing action logs. | ||
func ParseListActionLogQueryParams(r *http.Request) (int, error) { | ||
query := r.URL.Query() | ||
var logType int | ||
|
||
// Check if logType query param is provided. | ||
if r, ok := query["logType"]; ok && len(r) > 0 { | ||
if oInt, err := strconv.Atoi(r[0]); err == nil && oInt >= 1 { | ||
logType = oInt | ||
return logType, nil | ||
} | ||
} | ||
|
||
return logType, ActionLogTypeIsMissingError | ||
} | ||
|
||
type listActionLogsResp struct { | ||
ActionLogs interface{} `json:"logs"` | ||
Pagination paginate.Pagination `json:"pagination"` | ||
} | ||
|
||
func returnHTTPResponse(resp interface{}, w http.ResponseWriter) { | ||
response, _ := json.Marshal(resp) | ||
w.Header().Set(config.ContentTypeHeader, config.ContentTypeJSON) | ||
w.WriteHeader(http.StatusOK) | ||
w.Write(response) | ||
} | ||
|
||
// AuditGetOrgLogs Get action logs for the organization | ||
func AuditGetOrgLogs(w http.ResponseWriter, r *http.Request) { | ||
organisationId := r.Header.Get(config.OrganizationId) | ||
organisationId = common.Sanitize(organisationId) | ||
|
||
// Query params | ||
offset, limit := paginate.ParsePaginationQueryParams(r) | ||
log.Printf("Offset: %v and limit: %v\n", offset, limit) | ||
|
||
// Repository | ||
actionLogRepo := actionlog.ActionLogRepository{} | ||
actionLogRepo.Init(organisationId) | ||
|
||
var filter primitive.M | ||
|
||
logType, err := ParseListActionLogQueryParams(r) | ||
if err != nil && errors.Is(err, ActionLogTypeIsMissingError) { | ||
filter = actionLogRepo.DefaultFilter | ||
} else { | ||
filter = common.CombineFilters(actionLogRepo.DefaultFilter, bson.M{"type": logType}) | ||
} | ||
|
||
// Return all action logs | ||
var actionLogs []actionlog.ActionLog | ||
query := paginate.PaginateDBObjectsQuery{ | ||
Filter: filter, | ||
Collection: actionlog.Collection(), | ||
Context: context.Background(), | ||
Limit: limit, | ||
Offset: offset, | ||
} | ||
result, err := paginate.PaginateDBObjects(query, &actionLogs) | ||
if err != nil { | ||
if errors.Is(err, paginate.EmptyDBError) { | ||
emptyActionLogs := make([]interface{}, 0) | ||
resp := listActionLogsResp{ | ||
ActionLogs: emptyActionLogs, | ||
Pagination: result.Pagination, | ||
} | ||
returnHTTPResponse(resp, w) | ||
return | ||
} | ||
m := "Failed to paginate action log" | ||
common.HandleErrorV2(w, http.StatusInternalServerError, m, err) | ||
return | ||
|
||
} | ||
resp := listActionLogsResp{ | ||
ActionLogs: result.Items, | ||
Pagination: result.Pagination, | ||
} | ||
returnHTTPResponse(resp, w) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters