Skip to content

Commit

Permalink
Merge pull request #71 from Avanade/sprint-19
Browse files Browse the repository at this point in the history
Sprint 19
  • Loading branch information
jerricotandelacruz authored Jun 19, 2024
2 parents 5f620ab + 7ab9dc3 commit 2c2ed4d
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 124 deletions.
4 changes: 3 additions & 1 deletion .bicep/webapp/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
"EMAIL_TENANT_ID" : "",
"EMAIL_CLIENT_ID" : "",
"EMAIL_CLIENT_SECRET" : "",
"EMAIL_USER_ID" : ""
"EMAIL_USER_ID" : "",
"LINK_FOOTERS": "",
"ORGANIZATION_NAME": ""
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/goapp/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ 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>
EMAIL_USER_ID=<Email user id>
LINK_FOOTERS=""
ORGANIZATION_NAME=""
57 changes: 57 additions & 0 deletions src/goapp/http/mux-router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package router

import (
"fmt"
"net/http"
"os"

rtPages "main/routes/pages"

"github.com/gorilla/mux"
"github.com/unrolled/secure"
)

type muxRouter struct{}

func NewMuxRouter() Router {
return &muxRouter{}
}

var (
muxDispatcher = mux.NewRouter()
)

func (*muxRouter) GET(uri string, f func(resp http.ResponseWriter, req *http.Request)) {
muxDispatcher.HandleFunc(uri, f).Methods("GET")
}

func (*muxRouter) POST(uri string, f func(resp http.ResponseWriter, req *http.Request)) {
muxDispatcher.HandleFunc(uri, f).Methods("POST")
}

func (*muxRouter) SERVE(port string) {
secureOptions := secure.Options{
SSLRedirect: true, // Strict-Transport-Security
SSLHost: os.Getenv("SSL_HOST"), // Strict-Transport-Security
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"}, // Strict-Transport-Security
FrameDeny: true,
ContentTypeNosniff: true, // X-Content-Type-Options
BrowserXssFilter: true,
ReferrerPolicy: "strict-origin", // Referrer-Policy
ContentSecurityPolicy: os.Getenv("CONTENT_SECURITY_POLICY"),
PermissionsPolicy: "fullscreen=(), geolocation=()", // Permissions-Policy
STSSeconds: 31536000, // Strict-Transport-Security
STSIncludeSubdomains: true, // Strict-Transport-Security
IsDevelopment: os.Getenv("IS_DEVELOPMENT") == "true",
}

secureMiddleware := secure.New(secureOptions)
muxDispatcher.Use(secureMiddleware.Handler)
http.Handle("/", muxDispatcher)

muxDispatcher.NotFoundHandler = http.HandlerFunc(rtPages.NotFoundHandler)
muxDispatcher.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir("./public/"))))

fmt.Printf("Mux HTTP server running on port %v", port)
http.ListenAndServe(fmt.Sprintf(":%v", port), muxDispatcher)
}
9 changes: 9 additions & 0 deletions src/goapp/http/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package router

import "net/http"

type Router interface {
GET(uri string, f func(resp http.ResponseWriter, req *http.Request))
POST(uri string, f func(resp http.ResponseWriter, req *http.Request))
SERVE(port string)
}
56 changes: 4 additions & 52 deletions src/goapp/main.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
package main

import (
"fmt"
"log"
session "main/pkg/session"
rtPages "main/routes/pages"
rtApprovals "main/routes/pages/approvals"
"net/http"
"os"
"strconv"
"time"

"github.com/gorilla/mux"
"github.com/unrolled/secure"

ev "main/pkg/envvar"

"github.com/codegangsta/negroni"
"github.com/joho/godotenv"
)

Expand All @@ -27,56 +19,16 @@ func main() {
log.Print(err.Error())
}

secureMiddleware := secure.New(secure.Options{
SSLRedirect: true, // Strict-Transport-Security
SSLHost: os.Getenv("SSL_HOST"), // Strict-Transport-Security
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"}, // Strict-Transport-Security
FrameDeny: true, // X-FRAME-OPTIONS
ContentTypeNosniff: true, // X-Content-Type-Options
BrowserXssFilter: true,
ReferrerPolicy: "strict-origin", // Referrer-Policy
ContentSecurityPolicy: os.Getenv("CONTENT_SECURITY_POLICY"),
PermissionsPolicy: "fullscreen=(), geolocation=()", // Permissions-Policy
STSSeconds: 31536000, // Strict-Transport-Security
STSIncludeSubdomains: true, // Strict-Transport-Security,
IsDevelopment: os.Getenv("IS_DEVELOPMENT") == "true",
})

// Create session and GitHubClient
session.InitializeSession()

mux := mux.NewRouter()

setPageRoutes(mux)
setApiRoutes(mux)
setUtilityRoutes(mux)

mux.NotFoundHandler = loadAzAuthPage(rtPages.NotFoundHandler)

go checkFailedCallbacks()

mux.Use(secureMiddleware.Handler)
http.Handle("/", mux)

port := ev.GetEnvVar("PORT", "8080")
fmt.Printf("Now listening on port %v\n", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", port), mux))

}

// Verifies authentication before loading the page.
func loadAzAuthPage(f func(w http.ResponseWriter, r *http.Request)) *negroni.Negroni {
return negroni.New(
negroni.HandlerFunc(session.IsAuthenticated),
negroni.Wrap(http.HandlerFunc(f)),
)
}
setPageRoutes()
setApiRoutes()
setUtilityRoutes()

func loadGuidAuthApi(f func(w http.ResponseWriter, r *http.Request)) *negroni.Negroni {
return negroni.New(
negroni.HandlerFunc(session.IsGuidAuthenticated),
negroni.Wrap(http.HandlerFunc(f)),
)
serve()
}

func checkFailedCallbacks() {
Expand Down
36 changes: 36 additions & 0 deletions src/goapp/middleware/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package middleware

import (
"main/pkg/session"
"net/http"
)

type Middleware func(http.HandlerFunc) http.HandlerFunc

func AzureAuth() Middleware {
return func(f http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
isAuth := session.IsAuthenticated(w, r)
if isAuth {
f(w, r)
}
}
}
}

func ManagedIdentityAuth() Middleware {
return func(f http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session.IsGuidAuthenticated(w, r)
f(w, r)
}
}
}

// Chain applies middlewares to a http.HandlerFunc
func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
for _, m := range middlewares {
f = m(f)
}
return f
}
13 changes: 10 additions & 3 deletions src/goapp/models/data.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package models

type TypPageData struct {
Header interface{}
Profile interface{}
Content interface{}
Header interface{}
Profile interface{}
Content interface{}
Footers []Footer
OrganizationName string
}

type Footer struct {
Text string
Url string
}

type TypHeaders struct {
Expand Down
18 changes: 8 additions & 10 deletions src/goapp/pkg/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func InitializeSession() {
gob.Register(map[string]interface{}{})
}

func IsAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
func IsAuthenticated(w http.ResponseWriter, r *http.Request) bool {
var url string
url = fmt.Sprintf("%v", r.URL)
if strings.HasPrefix(url, "/response/") {
Expand All @@ -40,8 +40,7 @@ func IsAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFu

authReq = IsAuthRequired(appModuleGuid)
if authReq == false {
next(w, r)
return
return true
}
}

Expand All @@ -54,21 +53,22 @@ func IsAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFu
MaxAge: -1}
http.SetCookie(w, &c)
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
return
return false
}
// fmt.Println(session)
if _, ok := session.Values["profile"]; !ok {

// Asks user to login if there is no saved user profile
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
return false

} else {
// If there is a user profile saved
authenticator, err := auth.NewAuthenticator()

if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
return false
}

// Retrieve current token data
Expand Down Expand Up @@ -105,24 +105,22 @@ func IsAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFu

if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
return false
}
}
}
next(w, r)
return true
}
}

func IsGuidAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
func IsGuidAuthenticated(w http.ResponseWriter, r *http.Request) {
// Check header if authenticated
_, err := auth.VerifyAccessToken(r)
// RETURN ERROR
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// RETURN SUCCESS
next(w, r)
}

func GetState(w http.ResponseWriter, r *http.Request) (string, error) {
Expand Down
23 changes: 18 additions & 5 deletions src/goapp/pkg/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"main/models"
session "main/pkg/session"
"net/http"
"os"
"strings"
)

Expand All @@ -21,8 +22,8 @@ func UseTemplate(w *http.ResponseWriter, r *http.Request, page string, pageData

if profile == nil {
profile = map[string]interface{}{
"name": "",
"preferred_username":"",
"name": "",
"preferred_username": "",
}
}

Expand All @@ -32,10 +33,22 @@ func UseTemplate(w *http.ResponseWriter, r *http.Request, page string, pageData
menu = append(menu, models.TypMenu{Name: "My Approvals", Url: "/myapprovals", IconPath: "/public/icons/approvals.svg"})
masterPageData := models.TypHeaders{Menu: menu, Page: getUrlPath(r.URL.Path)}

//Footers
var footers []models.Footer
footerString := os.Getenv("LINK_FOOTERS")
res := strings.Split(footerString, ";")
for _, footer := range res {
f := strings.Split(footer, ">")
footers = append(footers, models.Footer{Text: f[0], Url: f[1]})
}

data := models.TypPageData{
Header: masterPageData,
Profile: profile,
Content: pageData}
Header: masterPageData,
Profile: profile,
Content: pageData,
Footers: footers,
OrganizationName: os.Getenv("ORGANIZATION_NAME"),
}

tmpl := template.Must(
template.ParseFiles("templates/master.html", "templates/buttons.html",
Expand Down
Loading

0 comments on commit 2c2ed4d

Please sign in to comment.