From 096a08708e2310becba56a237ef63b5cf6e3c4c4 Mon Sep 17 00:00:00 2001 From: Michael Hunteman Date: Sun, 25 Aug 2024 12:44:32 -0700 Subject: Add admin dashboard --- server/guest/handler.go | 115 ++++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 52 deletions(-) (limited to 'server/guest/handler.go') diff --git a/server/guest/handler.go b/server/guest/handler.go index 46b8a45..153a633 100644 --- a/server/guest/handler.go +++ b/server/guest/handler.go @@ -12,15 +12,15 @@ import ( ) var ( - guestRe = regexp.MustCompile(`^/guest/*$`) - guestIdRe = regexp.MustCompile(`^/guest/([0-9]+)$`) + guestRegex = regexp.MustCompile(`^/guest/*$`) + guestIDRegex = regexp.MustCompile(`^/guest/([0-9]+)$`) ) type GuestHandler struct { - store guestStore + guestStore GuestStore } -type guestStore interface { +type GuestStore interface { Find(credentials Credentials) (Guest, error) Get() ([]Guest, error) Add(guest Guest) error @@ -33,9 +33,9 @@ type appError struct { Code int } -func NewGuestHandler(s guestStore) *GuestHandler { +func NewGuestHandler(guestStore GuestStore) *GuestHandler { return &GuestHandler{ - store: s, + guestStore, } } @@ -45,11 +45,11 @@ func (guestHandler *GuestHandler) ServeHTTP(responseWriter http.ResponseWriter, responseWriter.WriteHeader(http.StatusOK) case request.Method == http.MethodPost && request.URL.Path == "/guest/login": guestHandler.handleLogIn(responseWriter, request) - case request.Method == http.MethodPut && guestIdRe.MatchString(request.URL.Path): + case request.Method == http.MethodPut && guestIDRegex.MatchString(request.URL.Path): guestHandler.handlePut(responseWriter, request) - case request.Method == http.MethodGet && guestRe.MatchString(request.URL.Path): + case request.Method == http.MethodGet && guestRegex.MatchString(request.URL.Path): guestHandler.handleGet(responseWriter, request) - case request.Method == http.MethodPost && guestRe.MatchString(request.URL.Path): + case request.Method == http.MethodPost && guestIDRegex.MatchString(request.URL.Path): guestHandler.handlePost(responseWriter, request) default: responseWriter.WriteHeader(http.StatusNotFound) @@ -57,7 +57,7 @@ func (guestHandler *GuestHandler) ServeHTTP(responseWriter http.ResponseWriter, } func (guestHandler *GuestHandler) handleLogIn(responseWriter http.ResponseWriter, request *http.Request) { - token, err := guestHandler.logInGuest(request) + token, err := guestHandler.logIn(request) if err != nil { http.Error(responseWriter, err.Message, err.Code) } else { @@ -90,28 +90,28 @@ func (guestHandler *GuestHandler) handlePost(responseWriter http.ResponseWriter, } } -func (guestHandler *GuestHandler) logInGuest(request *http.Request) ([]byte, *appError) { +func (guestHandler *GuestHandler) logIn(request *http.Request) ([]byte, *appError) { credentials, err := guestHandler.decodeCredentials(request) if err != nil { - return []byte{}, &appError{err, "Failed to unmarshal credentials", http.StatusBadRequest} + return []byte{}, &appError{err, "failed to unmarshal credentials", http.StatusBadRequest} } - guest, err := guestHandler.store.Find(credentials) + guest, err := guestHandler.guestStore.Find(credentials) if err != nil { - return []byte{}, &appError{err, "Guest not found", http.StatusUnauthorized} + return []byte{}, &appError{err, "guest not found", http.StatusUnauthorized} } expirationTime := guestHandler.setExpirationTime() claims := guestHandler.createClaims(credentials, expirationTime) - key, err := guestHandler.readKey() + key, err := guestHandler.readGuestKey() if err != nil { - return []byte{}, &appError{err, "Failed to read secret key", http.StatusInternalServerError} + return []byte{}, &appError{err, "failed to read secret key", http.StatusInternalServerError} } token, err := guestHandler.createToken(claims, key) if err != nil { - return []byte{}, &appError{err, "Failed to create token", http.StatusInternalServerError} + return []byte{}, &appError{err, "failed to create token", http.StatusInternalServerError} } jsonBytes, err := guestHandler.marshalResponse(guest, token) if err != nil { - return []byte{}, &appError{err, "Failed to marshal response", http.StatusInternalServerError} + return []byte{}, &appError{err, "failed to marshal response", http.StatusInternalServerError} } return jsonBytes, nil } @@ -136,9 +136,13 @@ func (guestHandler *GuestHandler) createClaims(credentials Credentials, expirati } } -func (guestHandler *GuestHandler) readKey() ([]byte, error) { +func (guestHandler *GuestHandler) readGuestKey() ([]byte, error) { // TODO: use properties file - return os.ReadFile("C:\\Users\\mhunt\\skey.pem") + return os.ReadFile("C:\\Users\\mhunt\\guest.pem") +} + +func (guestHandler *GuestHandler) readAdminKey() ([]byte, error) { + return os.ReadFile("C:\\Users\\mhunt\\admin.pem") } func (guestHandler *GuestHandler) createToken(claims *Claims, key []byte) (string, error) { @@ -159,38 +163,38 @@ func (guestHandler *GuestHandler) createLoginResponse(weddingGuest Guest, token } func (guestHandler *GuestHandler) putGuest(request *http.Request) *appError { - if err := guestHandler.validateToken(request); err != nil { + guestKey, err := guestHandler.readGuestKey() + if err != nil { + return &appError{err, "failed to read secret key", http.StatusInternalServerError} + } + if err := guestHandler.validateToken(request, guestKey); err != nil { return err } - if guestHandler.findId(request) { - return &appError{errors.New("ID not found"), "ID not found", http.StatusNotFound} + if guestHandler.findID(request) { + return &appError{errors.New("id not found"), "id not found", http.StatusNotFound} } guest, err := guestHandler.decodeGuest(request) if err != nil { - return &appError{err, "Invalid guest", http.StatusBadRequest} + return &appError{err, "invalid guest", http.StatusBadRequest} } - if err := guestHandler.store.Update(guest); err != nil { - return &appError{err, "Failed to update guest", http.StatusInternalServerError} + if err := guestHandler.guestStore.Update(guest); err != nil { + return &appError{err, "failed to update guest", http.StatusInternalServerError} } return nil } -func (guestHandler *GuestHandler) validateToken(request *http.Request) *appError { +func (guestHandler *GuestHandler) validateToken(request *http.Request, key []byte) *appError { authorizationHeader := guestHandler.getToken(request) - claims := guestHandler.initializeClaims() - key, err := guestHandler.readKey() - if err != nil { - return &appError{err, "Failed to read secret key", http.StatusInternalServerError} - } + claims := guestHandler.newClaims() token, err := guestHandler.parseWithClaims(authorizationHeader, claims, key) if err != nil { if err == jwt.ErrSignatureInvalid { - return &appError{err, "Invalid signature", http.StatusUnauthorized} + return &appError{err, "invalid signature", http.StatusUnauthorized} } - return &appError{err, "Failed to parse claims", http.StatusBadRequest} + return &appError{err, "failed to parse claims", http.StatusBadRequest} } if !token.Valid { - return &appError{err, "Invalid token", http.StatusUnauthorized} + return &appError{err, "invalid token", http.StatusUnauthorized} } return nil } @@ -199,7 +203,7 @@ func (guestHandler *GuestHandler) getToken(request *http.Request) string { return request.Header.Get("Authorization") } -func (guestHandler *GuestHandler) initializeClaims() *Claims { +func (guestHandler *GuestHandler) newClaims() *Claims { return &Claims{} } @@ -209,8 +213,8 @@ func (guestHandler *GuestHandler) parseWithClaims(token string, claims *Claims, }) } -func (guestHandler *GuestHandler) findId(request *http.Request) bool { - matches := guestIdRe.FindStringSubmatch(request.URL.Path) +func (guestHandler *GuestHandler) findID(request *http.Request) bool { + matches := guestIDRegex.FindStringSubmatch(request.URL.Path) return len(matches) < 2 } @@ -222,46 +226,53 @@ func (guestHandler *GuestHandler) decodeGuest(request *http.Request) (Guest, err } func (guestHandler *GuestHandler) getGuests(request *http.Request) ([]byte, *appError) { - // TODO: check with admin token - if err := guestHandler.validateToken(request); err != nil { + adminKey, err := guestHandler.readAdminKey() + if err != nil { + return []byte{}, &appError{err, "failed to read secret key", http.StatusInternalServerError} + } + if err := guestHandler.validateToken(request, adminKey); err != nil { return []byte{}, err } - guests, err := guestHandler.store.Get() + guests, err := guestHandler.guestStore.Get() if err != nil { - return []byte{}, &appError{err, "Failed to get guests", http.StatusInternalServerError} + return []byte{}, &appError{err, "failed to get guests", http.StatusInternalServerError} } jsonBytes, err := json.Marshal(guests) if err != nil { - return []byte{}, &appError{err, "Failed to marshal guests", http.StatusInternalServerError} + return []byte{}, &appError{err, "failed to marshal guests", http.StatusInternalServerError} } return jsonBytes, nil } func (guestHandler *GuestHandler) postGuest(request *http.Request) *appError { - if err := guestHandler.validateToken(request); err != nil { + adminKey, err := guestHandler.readAdminKey() + if err != nil { + return &appError{err, "failed to read secret key", http.StatusInternalServerError} + } + if err := guestHandler.validateToken(request, adminKey); err != nil { return err } guest, err := guestHandler.decodeGuest(request) if err != nil { - return &appError{err, "Invalid guest", http.StatusBadRequest} + return &appError{err, "invalid guest", http.StatusBadRequest} } - guests, err := guestHandler.store.Get() + guests, err := guestHandler.guestStore.Get() if err != nil { - return &appError{err, "Failed to get guests", http.StatusInternalServerError} + return &appError{err, "failed to get guests", http.StatusInternalServerError} } if err := guestHandler.checkExistingGuests(guests, guest); err != nil { - return &appError{err, "ID already exists", http.StatusConflict} + return &appError{err, "id already exists", http.StatusConflict} } - if err := guestHandler.store.Add(guest); err != nil { - return &appError{err, "Failed to add guest", http.StatusInternalServerError} + if err := guestHandler.guestStore.Add(guest); err != nil { + return &appError{err, "failed to add guest", http.StatusInternalServerError} } return nil } func (guestHandler *GuestHandler) checkExistingGuests(guests []Guest, newGuest Guest) error { for _, guest := range guests { - if guest.Id == newGuest.Id { - return errors.New("ID already exists") + if guest.ID == newGuest.ID { + return errors.New("id already exists") } } return nil -- cgit v1.2.3