Skip to content

Commit

Permalink
Send Message To Discord About Service Blocking
Browse files Browse the repository at this point in the history
  • Loading branch information
lakshayman committed Feb 21, 2024
1 parent 646fd7b commit fea6651
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 18 deletions.
1 change: 1 addition & 0 deletions call-profile/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/aws/aws-lambda-go v1.41.0
github.com/aws/aws-sdk-go v1.44.284
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
github.com/golang-jwt/jwt/v5 v5.2.0
golang.org/x/crypto v0.14.0
google.golang.org/api v0.128.0
)
Expand Down
2 changes: 2 additions & 0 deletions call-profile/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
Expand Down
90 changes: 72 additions & 18 deletions call-profile/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"sync"
"time"
"bytes"

"cloud.google.com/go/firestore"
firebase "firebase.google.com/go"
Expand All @@ -25,6 +26,7 @@ import (
// validation packages
"github.com/go-ozzo/ozzo-validation/v4"
"github.com/go-ozzo/ozzo-validation/v4/is"
"github.com/golang-jwt/jwt/v5"
)

var wg sync.WaitGroup
Expand Down Expand Up @@ -87,6 +89,10 @@ type structProfilesSkipped struct {
OtherError []string
}

type Claims struct {
jwt.RegisteredClaims
}

/*
Structures Conversions
*/
Expand Down Expand Up @@ -155,6 +161,8 @@ var Constants map[string]string = map[string]string{
"ENV_PRODUCTION": "PRODUCTION",
"STORED": "stored",
"FIRE_STORE_CRED": "firestoreCred",
"DISCORD_BOT_URL": "discordBotURL",
"IDENTITY_SERVICE_PRIVATE_KEY": "identityServicePrivateKey",
"PROFILE_SERVICE_HEALTH": "PROFILE_SERVICE_HEALTH",
"PROFILE_SKIPPED": "PROFILE_SKIPPED",
"PROFILE_DIFF_STORED": "PROFILE_DIFF_STORED",
Expand All @@ -173,11 +181,11 @@ var Constants map[string]string = map[string]string{
/*
Setting Firestore Key for development/production
*/
func getFirestoreKey() string {
func getParameter(parameter string) string {
if os.Getenv(("environment")) == Constants["ENV_DEVELOPMENT"] {
return os.Getenv(Constants["FIRE_STORE_CRED"])
return os.Getenv(parameter)
} else if os.Getenv(("environment")) == Constants["ENV_PRODUCTION"] {
var parameterName string = Constants["FIRE_STORE_CRED"]
var parameterName string = parameter

sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
Expand Down Expand Up @@ -206,7 +214,7 @@ func getFirestoreKey() string {
Function to initialize the firestore client
*/
func initializeFirestoreClient(ctx context.Context) (*firestore.Client, error) {
sa := option.WithCredentialsJSON([]byte(getFirestoreKey()))
sa := option.WithCredentialsJSON([]byte(getParameter(Constants["FIRE_STORE_CRED"])))
app, err := firebase.NewApp(ctx, nil, sa)
if err != nil {
return nil, err
Expand Down Expand Up @@ -234,6 +242,29 @@ func (res Res) Validate() error {
validation.Field(&res.Website, is.URL))
}

/*
Functions to generate jwt token
*/

func generateJWTToken() string {
signKey, errGeneratingRSAKey := jwt.ParseRSAPrivateKeyFromPEM([]byte(getParameter(Constants["IDENTITY_SERVICE_PRIVATE_KEY"])))
if(errGeneratingRSAKey != nil) {
return "";
}
expirationTime := time.Now().Add(1 * time.Minute)
t := jwt.New(jwt.GetSigningMethod("RS256"))
t.Claims = &Claims{
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(expirationTime),
},
}
tokenString, err := t.SignedString(signKey)
if(err != nil) {
return "";
}
return tokenString
}

/*
MODELS
*/
Expand Down Expand Up @@ -294,12 +325,28 @@ func logProfileStored(client *firestore.Client, ctx context.Context, userId stri
/*
Function for setting the profileStatus in user object in firestore
*/
func setProfileStatusBlocked(client *firestore.Client, ctx context.Context, userId string, reason string, sessionId string) {
func setProfileStatusBlocked(client *firestore.Client, ctx context.Context, userId string, reason string, sessionId string, discordId string) {
client.Collection("users").Doc(userId).Set(ctx, map[string]interface{}{
"profileStatus": Constants["STATUS_BLOCKED"],
"chaincode": "",
}, firestore.MergeAll)

if discordId != "" {
tokenString := generateJWTToken();
postBody, _ := json.Marshal(map[string]string{
"userId": discordId,
"reason": reason,
})

responseBody := bytes.NewBuffer(postBody)

httpClient := &http.Client{}
req, _ := http.NewRequest("POST", os.Getenv(Constants["DISCORD_BOT_URL"]) + "/profile/blocked", responseBody)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", tokenString))
httpClient.Do(req)
}

newLog := Log{
Type: Constants["PROFILE_SERVICE_BLOCKED"],
Timestamp: time.Now(),
Expand Down Expand Up @@ -364,13 +411,13 @@ func generateAndStoreDiff(client *firestore.Client, ctx context.Context, res Res
/*
Getting data from the user's service
*/
func getdata(client *firestore.Client, ctx context.Context, userId string, userUrl string, chaincode string, userData Res, sessionId string) string {
func getdata(client *firestore.Client, ctx context.Context, userId string, userUrl string, chaincode string, userData Res, sessionId string, discordId string) string {
var status string = ""
userUrl = userUrl + "profile"
hashedChaincode, err := bcrypt.GenerateFromPassword([]byte(chaincode), bcrypt.DefaultCost)
if err != nil {
logProfileSkipped(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId, discordId)
return "chaincode not encrypted"
}

Expand All @@ -380,18 +427,18 @@ func getdata(client *firestore.Client, ctx context.Context, userId string, userU
resp, err := httpClient.Do(req)
if err != nil {
logProfileSkipped(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId, discordId)
return "error getting profile data"
}
if resp.StatusCode == 401 {
logProfileSkipped(client, ctx, userId, "Unauthenticated Access to Profile Data", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Unauthenticated Access to Profile Data", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Unauthenticated Access to Profile Data", sessionId, discordId)
resp.Body.Close()
return "unauthenticated access to profile data"
}
if resp.StatusCode != 200 {
logProfileSkipped(client, ctx, userId, "Error in getting Profile Data", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Error in getting Profile Data", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Error in getting Profile Data", sessionId, discordId)
resp.Body.Close()
return "error in getting profile data"
}
Expand All @@ -401,22 +448,22 @@ func getdata(client *firestore.Client, ctx context.Context, userId string, userU
r, err := ioutil.ReadAll(resp.Body)
if err != nil {
logProfileSkipped(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId, discordId)
return "error reading profile data"
}
var res Res
err = json.Unmarshal([]byte(r), &res)
if err != nil {
logProfileSkipped(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId, discordId)
return "error converting data to json"
}

err = res.Validate()

if err != nil {
logProfileSkipped(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId)
setProfileStatusBlocked(client, ctx, userId, fmt.Sprintln(err), sessionId, discordId)
return fmt.Sprintf("error in validation: ", err)
}

Expand Down Expand Up @@ -481,22 +528,29 @@ func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyRespo

var userUrl string
var chaincode string
var discordId string

if str, ok := dsnap.Data()["profileURL"].(string); ok {
userUrl = str
} else {
logProfileSkipped(client, ctx, userId, "Profile URL not available", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Profile URL not available", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Profile URL not available", sessionId, discordId)
return events.APIGatewayProxyResponse{
Body: "Profile Skipped No Profile URL",
StatusCode: 200,
}, nil
}

if str, ok := dsnap.Data()["discordId"].(string); ok {
discordId = str
} else {
discordId = ""
}

if str, ok := dsnap.Data()["chaincode"].(string); ok {
if str == "" {
logProfileSkipped(client, ctx, userId, "Profile Service Blocked or Chaincode is empty", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Profile Service Blocked or Chaincode is empty", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Profile Service Blocked or Chaincode is empty", sessionId, discordId)
return events.APIGatewayProxyResponse{
Body: "Profile Skipped Profile Service Blocked",
StatusCode: 200,
Expand All @@ -505,7 +559,7 @@ func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyRespo
chaincode = str
} else {
logProfileSkipped(client, ctx, userId, "Chaincode Not Found", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Chaincode Not Found", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Chaincode Not Found", sessionId, discordId)
return events.APIGatewayProxyResponse{
Body: "Profile Skipped Chaincode Not Found",
StatusCode: 200,
Expand Down Expand Up @@ -539,14 +593,14 @@ func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyRespo
logHealth(client, ctx, userId, isServiceRunning, sessionId)
if !isServiceRunning {
logProfileSkipped(client, ctx, userId, "Profile Service Down", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Profile Service Down", sessionId)
setProfileStatusBlocked(client, ctx, userId, "Profile Service Down", sessionId, discordId)
return events.APIGatewayProxyResponse{
Body: "Profile Skipped Service Down",
StatusCode: 200,
}, nil
}

dataErr := getdata(client, ctx, userId, userUrl, chaincode, diffToRes(userData), sessionId)
dataErr := getdata(client, ctx, userId, userUrl, chaincode, diffToRes(userData), sessionId, discordId)
if dataErr != "" {
return events.APIGatewayProxyResponse{
Body: "Profile Skipped " + dataErr,
Expand Down
2 changes: 2 additions & 0 deletions template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Globals:
firestoreCred: YourFirestoreCredentials
environment: PRODUCTION
baseURL: YourBaseAPIURL
discordBotURL: DiscordBotURL
identityServicePrivateKey: YourIdentityServicePrivateKey

Resources:
HealthFunction:
Expand Down

0 comments on commit fea6651

Please sign in to comment.