Skip to content

Commit

Permalink
edit fridays from admin page
Browse files Browse the repository at this point in the history
  • Loading branch information
mpoegel committed Mar 21, 2024
1 parent 988e548 commit 6e592d1
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 81 deletions.
48 changes: 12 additions & 36 deletions pkg/pizza/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type Server struct {
sessions map[string]*TokenClaims
}

func NewServer(config Config, metricsReg MetricsRegistry) (Server, error) {
func NewServer(config Config, metricsReg MetricsRegistry) (*Server, error) {
r := mux.NewRouter()

var accessor Accessor
Expand All @@ -53,7 +53,7 @@ func NewServer(config Config, metricsReg MetricsRegistry) (Server, error) {
Log.Info("using the sqlite accessor")
accessor, err = NewSQLAccessor(config.DBFile)
if err != nil {
return Server{}, err
return nil, err
}
} else if len(config.FaunaSecret) > 0 {
Log.Info("using the faunadb accessor")
Expand All @@ -64,18 +64,18 @@ func NewServer(config Config, metricsReg MetricsRegistry) (Server, error) {

googleCal, err := NewGoogleCalendar(config.Calendar.CredentialFile, config.Calendar.TokenFile, config.Calendar.ID, context.Background())
if err != nil {
return Server{}, err
return nil, err
}

ctx := context.Background()
provider, err := oidc.NewProvider(ctx, config.OAuth2.KeycloakURL+"/realms/"+config.OAuth2.Realm)
if err != nil {
return Server{}, err
return nil, err
}
k, err := NewKeycloak(config.OAuth2)
if err != nil {
Log.Error("keycloak failure", zap.Error(err))
return Server{}, err
return nil, err
}

s := Server{
Expand Down Expand Up @@ -125,8 +125,9 @@ func NewServer(config Config, metricsReg MetricsRegistry) (Server, error) {
r.HandleFunc("/login/callback", s.HandleLoginCallback)
r.HandleFunc("/logout", s.HandleLogout)
r.HandleFunc("/admin", s.HandleAdmin)
r.HandleFunc("/admin/submit", s.HandleAdminSubmit)

return s, nil
return &s, nil
}

func (s *Server) Start() error {
Expand Down Expand Up @@ -163,6 +164,7 @@ type IndexFridayData struct {
Date string
ID int64
Guests []string
Active bool
}

type PageData struct {
Expand All @@ -185,22 +187,8 @@ func (s *Server) HandleIndex(w http.ResponseWriter, r *http.Request) {
LoggedIn: false,
}

var claims *TokenClaims
for _, cookie := range r.Cookies() {
if cookie.Name == "session" {
var ok bool
claims, ok = s.sessions[cookie.Value]
// either bad session or auth has expired
if !ok || time.Now().After(time.Unix(claims.Exp, 0)) {
Log.Debug("cookie session invalid or expired")
delete(s.sessions, cookie.Value)
break
}
}
}
if claims == nil {
Log.Debug("no login cookies found")
} else {
claims, ok := s.authenticateRequest(r)
if ok {
data.LoggedIn = true

Log.Info("welcome", zap.String("name", claims.Name))
Expand Down Expand Up @@ -250,20 +238,8 @@ func (s *Server) HandleIndex(w http.ResponseWriter, r *http.Request) {
func (s *Server) HandleSubmit(w http.ResponseWriter, r *http.Request) {
s.submitPostMetric.Increment()

var claims *TokenClaims
for _, cookie := range r.Cookies() {
if cookie.Name == "session" {
var ok bool
claims, ok = s.sessions[cookie.Value]
// either bad session or auth has expired
if !ok || time.Now().After(time.Unix(claims.Exp, 0)) {
delete(s.sessions, cookie.Value)
http.Redirect(w, r, "/login", http.StatusFound)
return
}
}
}
if claims == nil {
claims, ok := s.authenticateRequest(r)
if !ok {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
Expand Down
118 changes: 101 additions & 17 deletions pkg/pizza/server_admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,29 @@ package pizza
import (
"net/http"
"path"
"strconv"
"text/template"
"time"

zap "go.uber.org/zap"
)

type AdminPageData struct {
const futureFridayLimit = 90

func getFutureFridays() []time.Time {
dates := make([]time.Time, 0)
loc, _ := time.LoadLocation("America/New_York")
start := time.Now()
friday := time.Date(start.Year(), start.Month(), start.Day(), 17, 30, 0, 0, loc)
for friday.Weekday() != time.Friday {
friday = friday.AddDate(0, 0, 1)
}
endDate := time.Now().AddDate(0, 0, futureFridayLimit)
for friday.Before(endDate) {
dates = append(dates, friday)
friday = friday.AddDate(0, 0, 7)
}
return dates
}

func (s *Server) HandleAdmin(w http.ResponseWriter, r *http.Request) {
Expand All @@ -19,22 +35,9 @@ func (s *Server) HandleAdmin(w http.ResponseWriter, r *http.Request) {
s.Handle500(w, r)
return
}
data := AdminPageData{}

var claims *TokenClaims
for _, cookie := range r.Cookies() {
if cookie.Name == "session" {
var ok bool
claims, ok = s.sessions[cookie.Value]
// either bad session or auth has expired
if !ok || time.Now().After(time.Unix(claims.Exp, 0)) {
delete(s.sessions, cookie.Value)
http.Redirect(w, r, "/login", http.StatusFound)
return
}
}
}
if claims == nil {

claims, ok := s.authenticateRequest(r)
if !ok {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
Expand All @@ -44,9 +47,90 @@ func (s *Server) HandleAdmin(w http.ResponseWriter, r *http.Request) {
return
}

data := PageData{
Name: claims.GivenName,
}

allFridays := getFutureFridays()
setFridays, err := s.store.GetUpcomingFridays(futureFridayLimit)
if err != nil {
Log.Error("failed to get fridays", zap.Error(err))
s.Handle500(w, r)
return
}
Log.Info("set fridays", zap.Times("dates", setFridays))
fridayIndex := 0
data.FridayTimes = make([]IndexFridayData, 0)
for _, friday := range allFridays {
f := IndexFridayData{
Date: friday.Format(time.RFC822),
ID: friday.Unix(),
Guests: nil,
Active: false,
}
if fridayIndex < len(setFridays) && friday.Equal(setFridays[fridayIndex]) {
f.Active = true
fridayIndex++
}
data.FridayTimes = append(data.FridayTimes, f)
}

if err = plate.Execute(w, data); err != nil {
Log.Error("template execution failure", zap.Error(err))
s.Handle500(w, r)
return
}
}

func (s *Server) HandleAdminSubmit(w http.ResponseWriter, r *http.Request) {
claims, ok := s.authenticateRequest(r)
if !ok {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
if !claims.HasRole("pizza_host") {
s.Handle4xx(w, r)
return
}

form := r.URL.Query()
dates := form["date"]
loc, _ := time.LoadLocation("America/New_York")
dateIndex := 0
allFridays := getFutureFridays()
for _, d := range allFridays {
f := time.Now().AddDate(1, 0, 0).In(loc)
if dateIndex < len(dates) {
num, err := strconv.ParseInt(dates[dateIndex], 10, 64)
if err != nil {
Log.Error("failed parsing date int from rsvp form", zap.String("date", dates[dateIndex]))
s.Handle500(w, r)
return
}
f = time.Unix(num, 0).In(loc)
}
if d.Equal(f) {
// friday selected, so add it
err := s.store.accessor.AddFriday(f)
if err != nil {
Log.Error("failed to add friday", zap.Error(err))
} else {
Log.Info("added friday", zap.Time("date", f))
}
dateIndex++
} else if f.After(d) {
// friday is not selected, so remove it
err := s.store.accessor.RemoveFriday(d)
if err != nil {
Log.Error("failed to remove friday", zap.Error(err))
} else {
Log.Info("removed friday", zap.Time("date", d))
}
} else {
// f.Before(d) == true
// do nothing
}
}

http.Redirect(w, r, "/admin", http.StatusFound)
}
74 changes: 47 additions & 27 deletions pkg/pizza/server_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,6 @@ import (
zap "go.uber.org/zap"
)

func (s *Server) HandleLogin(w http.ResponseWriter, r *http.Request) {
state := uuid.New()
rawAccessToken := r.Header.Get("Authorization")
if rawAccessToken == "" {
s.sessions[state.String()] = nil
http.Redirect(w, r, s.oauth2Conf.AuthCodeURL(state.String()), http.StatusFound)
return
}

authParts := strings.Split(rawAccessToken, " ")
if len(authParts) != 2 {
w.WriteHeader(400)
return
}

ctx := context.Background()
_, err := s.verifier.Verify(ctx, authParts[1])
if err != nil {
s.sessions[state.String()] = nil
http.Redirect(w, r, s.oauth2Conf.AuthCodeURL(state.String()), http.StatusFound)
return
}

w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}

type TokenClaims struct {
Exp int64 `json:"exp"`
Iat int64 `json:"iat"`
Expand Down Expand Up @@ -72,6 +45,53 @@ func (c *TokenClaims) HasRole(role string) bool {
return false
}

func (s *Server) authenticateRequest(r *http.Request) (*TokenClaims, bool) {
var claims *TokenClaims
for _, cookie := range r.Cookies() {
if cookie.Name == "session" {
var ok bool
claims, ok = s.sessions[cookie.Value]
// either bad session or auth has expired
if !ok || time.Now().After(time.Unix(claims.Exp, 0)) {
delete(s.sessions, cookie.Value)
return nil, false
}
}
}
if claims == nil {
return nil, false
}

return claims, true
}

func (s *Server) HandleLogin(w http.ResponseWriter, r *http.Request) {
state := uuid.New()
rawAccessToken := r.Header.Get("Authorization")
if rawAccessToken == "" {
s.sessions[state.String()] = nil
http.Redirect(w, r, s.oauth2Conf.AuthCodeURL(state.String()), http.StatusFound)
return
}

authParts := strings.Split(rawAccessToken, " ")
if len(authParts) != 2 {
w.WriteHeader(400)
return
}

ctx := context.Background()
_, err := s.verifier.Verify(ctx, authParts[1])
if err != nil {
s.sessions[state.String()] = nil
http.Redirect(w, r, s.oauth2Conf.AuthCodeURL(state.String()), http.StatusFound)
return
}

w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}

func (s *Server) HandleLoginCallback(w http.ResponseWriter, r *http.Request) {
state := r.URL.Query().Get("state")
if _, ok := s.sessions[state]; !ok {
Expand Down
21 changes: 20 additions & 1 deletion static/html/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,27 @@
<body>
<h2>Pizza Admin</h2>

<p>Welcome</p>
<p>Hi {{.Name}}</p>

<form method="get" action="/admin/submit">
{{range .FridayTimes}}
{{if .Active}}
<input type="checkbox" id="{{.Date}}" name="date" value="{{.ID}}" checked>
{{else}}
<input type="checkbox" id="{{.Date}}" name="date" value="{{.ID}}">
{{end}}
<label for="{{.Date}}">{{.Date}}</label><br>
<div class="guestLevel">{{range .Guests}}<span class="guest" title="{{.}}">&nbsp;</span>{{end}}<br></div>
{{end}}
<br>
<div id="submit">
<input type="submit" value="Update">
</div>
</form>

<br><br>
<a href="/">pizza</a> |
<a href="/logout">logout</a>
</body>

</html>

0 comments on commit 6e592d1

Please sign in to comment.