Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sprint 17 #55

Merged
merged 4 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .bicep/webapp/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,19 @@
"CLIENT_ID": "",
"CLIENT_SECRET": "",
"HOME_URL": "",
"EMAIL_ENDPOINT": "",
"DOCKER_REGISTRY_SERVER_URL": "",
"DOCKER_REGISTRY_SERVER_PASSWORD": "",
"DOCKER_REGISTRY_SERVER_USERNAME": "",
"APPROVALSYSTEMDB_CONNECTION_STRING": "",
"DOCKER_ENABLE_CI": "",
"WEBSITES_ENABLE_APP_SERVICE_STORAGE": "",
"CONTENT_SECURITY_POLICY": ""
"CONTENT_SECURITY_POLICY": "",
"EMAIL_SUPPORT":"",
"EMAIL_ENABLED" : "",
"EMAIL_TENANT_ID" : "",
"EMAIL_CLIENT_ID" : "",
"EMAIL_CLIENT_SECRET" : "",
"EMAIL_USER_ID" : ""
}
}
}
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/approval-system-iac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,20 @@ jobs:
echo "AD_TENANT_ID=${{secrets.AD_TENANT_ID}}" >> $GITHUB_ENV
echo "AD_CLIENT_ID=${{secrets.AD_CLIENT_ID}}" >> $GITHUB_ENV
echo "AD_CLIENT_SECRET=${{secrets.AD_CLIENT_SECRET}}" >> $GITHUB_ENV
echo "EMAIL_TENANT_ID=${{secrets.EMAIL_TENANT_ID}}" >> $GITHUB_ENV
echo "EMAIL_CLIENT_ID=${{secrets.EMAIL_CLIENT_ID}}" >> $GITHUB_ENV
echo "EMAIL_CLIENT_SECRET=${{secrets.EMAIL_CLIENT_SECRET}}" >> $GITHUB_ENV
echo "EMAIL_USER_ID=${{secrets.EMAIL_USER_ID}}" >> $GITHUB_ENV
;;
"prod")
echo "HOME_URL=${{ secrets.CUSTOM_DOMAIN_PROD}}" >> $GITHUB_ENV
echo "AD_TENANT_ID=${{secrets.AD_TENANT_ID_PROD}}" >> $GITHUB_ENV
echo "AD_CLIENT_ID=${{secrets.AD_CLIENT_ID_PROD}}" >> $GITHUB_ENV
echo "AD_CLIENT_SECRET=${{secrets.AD_CLIENT_SECRET_PROD}}" >> $GITHUB_ENV
echo "EMAIL_TENANT_ID=${{secrets.AD_TENANT_ID_PROD}}" >> $GITHUB_ENV
echo "EMAIL_CLIENT_ID=${{secrets.AD_CLIENT_ID_PROD}}" >> $GITHUB_ENV
echo "EMAIL_CLIENT_SECRET=${{secrets.AD_CLIENT_SECRET_PROD}}" >> $GITHUB_ENV
echo "EMAIL_USER_ID=${{secrets.EMAIL_USER_ID_PROD}}" >> $GITHUB_ENV
;;
esac

Expand Down Expand Up @@ -174,7 +182,10 @@ jobs:
parameters.appServiceSettings.value.CLIENT_ID : ${{ env.AD_CLIENT_ID }}
parameters.appServiceSettings.value.CLIENT_SECRET : ${{ env.AD_CLIENT_SECRET }}
parameters.appServiceSettings.value.HOME_URL : ${{env.HOME_URL}}
parameters.appServiceSettings.value.EMAIL_ENDPOINT : ${{ secrets.EMAIL_ENDPOINT }}
parameters.appServiceSettings.value.EMAIL_TENANT_ID : ${{ env.EMAIL_TENANT_ID }}
parameters.appServiceSettings.value.EMAIL_CLIENT_ID : ${{ env.EMAIL_CLIENT_ID }}
parameters.appServiceSettings.value.EMAIL_CLIENT_SECRET : ${{ env.EMAIL_CLIENT_SECRET }}
parameters.appServiceSettings.value.EMAIL_USER_ID : ${{ env.EMAIL_USER_ID }}
parameters.appServiceSettings.value.DOCKER_REGISTRY_SERVER_URL : https://${{ secrets.ACR_REGISTRY }}
parameters.appServiceSettings.value.DOCKER_REGISTRY_SERVER_USERNAME : ${{ secrets.ACR_USERNAME }}
parameters.appServiceSettings.value.DOCKER_REGISTRY_SERVER_PASSWORD : ${{ secrets.ACR_PASSWORD }}
Expand Down
10 changes: 8 additions & 2 deletions src/goapp/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ CLIENT_SECRET=<Client Secret>
KEY_VAULT_NAME=<Azure Key Vault Name>
HOME_URL=http://localhost:8080
APPROVALSYSTEMDB_CONNECTION_STRING=<db connection string>
EMAIL_ENDPOINT=<Email Endpoint>
CALLBACK_RETRY_FREQ=<Interval in minutes. 0 to disable. Default is 15.>
CONTENT_SECURITY_POLICY=<Cpmtemt security policy>
IS_DEVELOPMENT=<Defaults to false>
IS_DEVELOPMENT=<Defaults to false>
EMAIL_SUMMARY_REPORT=<Recipient of daily summary report>
EMAIL_SUPPORT=<Support Email>
EMAIL_TENANT_ID=<Tenant Id>
EMAIL_CLIENT_ID=<Client Id>
EMAIL_CLIENT_SECRET=<Client Secret>
EMAIL_ENABLED=<Email enabled. default: false>
EMAIL_USER_ID=<Email user id>
1 change: 0 additions & 1 deletion src/goapp/models/approvals.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ type TypRequestApproval struct {
ApplicationId string `json:"applicationId"`
ApplicationModuleId string `json:"applicationModuleId"`
RequesterEmail string `json:"requesterEmail"`
Email string `json:"email"` // Obsolete
Emails []string `json:"emails"`
Subject string `json:"subject"`
Body string `json:"body"`
Expand Down
100 changes: 87 additions & 13 deletions src/goapp/pkg/email/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,100 @@ package email

import (
"bytes"
"encoding/json"
"net/http"
"fmt"
"main/pkg/msgraph"
"os"
"text/template"
)

func SendEmail(msg TypEmailMessage) (*http.Response, error) {
endpoint := os.Getenv("EMAIL_ENDPOINT")
type MessageType string

postBody, _ := json.Marshal(map[string]string{
"to": msg.To,
"subject": msg.Subject,
"body": msg.Body,
})
payload := bytes.NewBuffer(postBody)
resp, err := http.Post(endpoint, "application/json", payload)
const (
HtmlMessageType MessageType = "html"
TextMessageType MessageType = "text"
)

type EmailMessage struct {
To string
Cc string
Subject string
Body string
}

type Message struct {
Subject string
Body Body
ToRecipients []Recipient
CcRecipients []Recipient
}

type Body struct {
Content string
Type MessageType
}

type Recipient struct {
Email string
}

func SendEmail(message Message, hasDefaultCc bool) error {
sendMailRequest := msgraph.SendMailRequest{
Message: msgraph.EmailMessage{
Subject: message.Subject,
Body: msgraph.BodyContent{
ContentType: string(message.Body.Type),
Content: message.Body.Content,
},
},
SaveToSentItems: "true",
}

for _, recipient := range message.ToRecipients {
sendMailRequest.Message.ToRecipients = append(sendMailRequest.Message.ToRecipients, msgraph.Recipient{
EmailAddress: msgraph.EmailAddress{
Address: recipient.Email,
},
})
}

var ccRecipients []msgraph.Recipient

// DEFAULT CC RECIPIENT
if hasDefaultCc {
if os.Getenv("EMAIL_SUPPORT") != "" {
ccRecipients = append(ccRecipients, msgraph.Recipient{
EmailAddress: msgraph.EmailAddress{
Address: os.Getenv("EMAIL_SUPPORT"),
},
})
}
}

if len(message.CcRecipients) > 0 {
for _, recipient := range message.CcRecipients {
ccRecipients = append(ccRecipients, msgraph.Recipient{
EmailAddress: msgraph.EmailAddress{
Address: recipient.Email,
},
})
}
}

if ccRecipients != nil {
sendMailRequest.Message.CcRecipients = ccRecipients
} else {
sendMailRequest.Message.CcRecipients = []msgraph.Recipient{}
}

userId := os.Getenv("EMAIL_USER_ID")

err := msgraph.SendEmail(userId, sendMailRequest)
if err != nil {
return nil, err
fmt.Println("Error sending email:", err)
return err
}
return resp, nil

return nil
}

func ComposeEmail(data TypEmailData) (string, error) {
Expand Down
120 changes: 120 additions & 0 deletions src/goapp/pkg/msgraph/email.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package msgraph

import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
)

type EmailAddress struct {
Address string `json:"address"`
}

type Recipient struct {
EmailAddress EmailAddress `json:"emailAddress"`
}

type BodyContent struct {
ContentType string `json:"contentType"`
Content string `json:"content"`
}

type EmailMessage struct {
Subject string `json:"subject"`
Body BodyContent `json:"body"`
ToRecipients []Recipient `json:"toRecipients"`
CcRecipients []Recipient `json:"ccRecipients"`
}

type SendMailRequest struct {
Message EmailMessage `json:"message"`
SaveToSentItems string `json:"saveToSentItems"`
}

func GetEmailToken() (string, error) {

urlPath := fmt.Sprintf("https://login.microsoftonline.com/%s/oauth2/v2.0/token", os.Getenv("EMAIL_TENANT_ID"))
client := &http.Client{
Timeout: time.Second * 10,
}

data := url.Values{}
data.Set("client_id", os.Getenv("EMAIL_CLIENT_ID"))
data.Set("scope", "https://graph.microsoft.com/.default")
data.Set("client_secret", os.Getenv("EMAIL_CLIENT_SECRET"))
data.Set("grant_type", "client_credentials")
encodedData := data.Encode()

req, err := http.NewRequest("POST", urlPath, strings.NewReader(encodedData))
if err != nil {
return "", err
}

req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
response, err := client.Do(req)
if err != nil {
return "", err
}
defer response.Body.Close()

var tokenResponse TokenResponse
err = json.NewDecoder(response.Body).Decode(&tokenResponse)
if err != nil {
return "", err
}

return tokenResponse.AccessToken, nil
}

func SendEmail(userId string, request SendMailRequest) error {
if os.Getenv("EMAIL_ENABLED") != "true" {
log.Println("Email not sent because it is not enabled.")
return nil
}

accessToken, err := GetEmailToken()
if err != nil {
return err
}

requestBody, err := json.Marshal(request)
if err != nil {
return fmt.Errorf("error marshalling JSON: %v", err)
}

// Use a different API endpoint based on your requirements
apiEndpoint := fmt.Sprintf("https://graph.microsoft.com/v1.0/users/%s/sendMail", userId)
req, err := http.NewRequest("POST", apiEndpoint, bytes.NewBuffer(requestBody))
if err != nil {
return fmt.Errorf("error creating HTTP request: %v", err)
}

req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("error performing HTTP request: %v", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusAccepted {
// Print the response body for additional details
responseBody, _ := io.ReadAll(resp.Body)
fmt.Println("Response Body:", string(responseBody))
return fmt.Errorf("unexpected response status: %v", resp.Status)
}

fmt.Println("Email sent successfully!")
return nil
}
2 changes: 0 additions & 2 deletions src/goapp/public/components/combobox.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ const combobox = ({
},
// EVENT HANDLER
onInputHandler(e) {
console.log(e.target.value)
this.setOptions(e.target.value)
},
onFocusIn() {
Expand All @@ -70,7 +69,6 @@ const combobox = ({
this.isShowOptions = !this.isShowOptions
},
onInsertItem(e){
console.log(e.target.value)
if (!this.isInsertable)
return

Expand Down
Loading
Loading