Checkpoint 4

This commit is contained in:
Arti Zirk
2023-07-30 01:03:52 +03:00
parent 172dbcc210
commit 9116635efc
5 changed files with 208 additions and 17 deletions

View File

@@ -3,12 +3,17 @@
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"os/signal"
"strings"
"sync"
"time"
)
@@ -25,9 +30,21 @@ type cardToken struct {
}
type cardList struct {
AllowedUids []cardToken `json:"allowed_uids"`
AllowedUids []cardToken `json:"allowed_uids"`
KeepOpenUntil *time.Time `json:"keep_open_until,omitempty"`
}
var keys []cardToken = []cardToken{
//{card{UidHash: "d72c87d0f077c7766f2985dfab30e8955c373a13a1e93d315203939f542ff86e73ee37c31f4c4b571f4719fa8e3589f12db8dcb57ea9f56764bb7d58f64cf705"}},
{card{UidHash: "873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},
{card{UidHash: "a08094343b4057777af4935b79df586d7eb999117883a53393e8b46f1ab19577b12039a5d2e0b9d0364bbed5c82d83a507492fea47ace633acf23da2dcf1560e"}},
{card{UidHash: "d78271547cde009726b159dca09e53bee72feebe90b3eb7cb6e394caafc30bdb1f1567efc2f19bbdf3c6922e0bebed910ee4fa4f5b13bd379651da4f620f3559"}},
}
var keyLock sync.RWMutex
var keepOpenUntil *time.Time
func getRoot(w http.ResponseWriter, r *http.Request) {
fmt.Printf("got / request\n")
io.WriteString(w, "This is my website!\n")
@@ -35,14 +52,13 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
func getAllowed(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
keyLock.RLock()
keys := cardList{
AllowedUids: []cardToken{
{card{UidHash: "d72c87d0f077c7766f2985dfab30e8955c373a13a1e93d315203939f542ff86e73ee37c31f4c4b571f4719fa8e3589f12db8dcb57ea9f56764bb7d58f64cf705"}},
{card{UidHash: "873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},
{card{UidHash: "aabbccddeeff"}},
},
AllowedUids: keys,
KeepOpenUntil: keepOpenUntil,
}
respJson, _ := json.Marshal(keys)
keyLock.RUnlock()
_, err := w.Write(respJson)
if err != nil {
return
@@ -115,10 +131,116 @@ func (doobserver *DoorBoyServer) postOpenDoor(w http.ResponseWriter, r *http.Req
}
func postCardSwipe(w http.ResponseWriter, r *http.Request) {
data, err := io.ReadAll(r.Body)
if err != nil {
log.Println("Got swipe request without data")
return
}
log.Println("Swipe Request with key:", string(data))
w.Write([]byte("OK"))
}
func (doobserver *DoorBoyServer) postAddCard(w http.ResponseWriter, r *http.Request) {
data, err := io.ReadAll(r.Body)
if err != nil {
log.Println("Got swipe request without data")
return
}
cardHex := string(data)
if len(cardHex) != 128 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Key invalid"))
return
}
keyLock.RLock()
found := false
for _, key := range keys {
if key.Token.UidHash == cardHex {
// key is already in there!
found = true
}
}
keyLock.RUnlock()
if found {
return
}
keyLock.Lock()
keys = append(keys, cardToken{Token: card{UidHash: cardHex}})
keyLock.Unlock()
for _, datastream := range doobserver.longPollers {
datastream <- "update"
}
log.Println("Added new key:", string(data))
}
func (doobserver *DoorBoyServer) postRemoveCard(w http.ResponseWriter, r *http.Request) {
data, err := io.ReadAll(r.Body)
if err != nil {
log.Println("Got swipe request without data")
return
}
cardHex := string(data)
if len(cardHex) != 128 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Key invalid"))
return
}
keyLock.Lock()
foundIndex := -1
for i, key := range keys {
if key.Token.UidHash == cardHex {
// key is already in there!
foundIndex = i
}
}
if foundIndex == -1 {
keyLock.Unlock()
return
}
if foundIndex == len(keys)-1 {
keys = keys[:foundIndex]
} else {
keys = append(keys[:foundIndex], keys[foundIndex+1:]...)
}
keyLock.Unlock()
for _, datastream := range doobserver.longPollers {
datastream <- "update"
}
log.Println("Remove key:", string(data))
}
func (doobserver *DoorBoyServer) postKeepDoorOpen(w http.ResponseWriter, r *http.Request) {
rs, _ := io.ReadAll(r.Body)
parsedTime, err := time.Parse(time.RFC3339, strings.TrimSpace(string(rs)))
if err != nil {
fmt.Println("Error with parsing time: %v", err)
w.WriteHeader(http.StatusBadRequest)
}
keepOpenUntil = &parsedTime
doobserver.postOpenDoor(w, r)
}
func main() {
fmt.Println("Running...")
var dumpKeys []cardToken
savedKeys, err := os.ReadFile("keys.json")
err = json.Unmarshal(savedKeys, &dumpKeys)
if err == nil {
for _, k := range dumpKeys {
keys = append(keys, k)
}
log.Println("Loaded keys successfully!")
}
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
doorboyserver := DoorBoyServer{longPollers: map[string]chan string{}}
http.HandleFunc("/", getRoot)
http.HandleFunc("/allowed", getAllowed)
@@ -126,13 +248,28 @@ func main() {
http.HandleFunc("/jspoll", doorboyserver.getLongPollJson)
http.HandleFunc("/open", doorboyserver.postOpenDoor)
http.HandleFunc("/cardswipe", postCardSwipe)
http.HandleFunc("/keepdooropen", doorboyserver.postKeepDoorOpen)
http.HandleFunc("/addcard", doorboyserver.postAddCard)
http.HandleFunc("/removecard", doorboyserver.postRemoveCard)
err := http.ListenAndServe(":3333", nil)
go func() {
err := http.ListenAndServe(":3333", nil)
if errors.Is(err, http.ErrServerClosed) {
fmt.Printf("server closed\n")
} else if err != nil {
fmt.Printf("error starting server: %s\n", err)
os.Exit(1)
if errors.Is(err, http.ErrServerClosed) {
fmt.Printf("server closed\n")
} else if err != nil {
fmt.Printf("error starting server: %s\n", err)
os.Exit(1)
}
}()
<-ctx.Done()
log.Println("Shutting down!")
keyLock.Lock()
data, err := json.Marshal(keys)
if err == nil {
os.WriteFile("keys.json", data, 0600)
log.Println("Saved keys successfully!")
}
keyLock.Unlock()
}

1
godoor_server/keys.json Normal file
View File

@@ -0,0 +1 @@
[{"token":{"uid_hash":"873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},{"token":{"uid_hash":"a08094343b4057777af4935b79df586d7eb999117883a53393e8b46f1ab19577b12039a5d2e0b9d0364bbed5c82d83a507492fea47ace633acf23da2dcf1560e"}},{"token":{"uid_hash":"d78271547cde009726b159dca09e53bee72feebe90b3eb7cb6e394caafc30bdb1f1567efc2f19bbdf3c6922e0bebed910ee4fa4f5b13bd379651da4f620f3559"}},{"token":{"uid_hash":"d72c87d0f077c7766f2985dfab30e8955c373a13a1e93d315203939f542ff86e73ee37c31f4c4b571f4719fa8e3589f12db8dcb57ea9f56764bb7d58f64cf705"}},{"token":{"uid_hash":"873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},{"token":{"uid_hash":"a08094343b4057777af4935b79df586d7eb999117883a53393e8b46f1ab19577b12039a5d2e0b9d0364bbed5c82d83a507492fea47ace633acf23da2dcf1560e"}},{"token":{"uid_hash":"d78271547cde009726b159dca09e53bee72feebe90b3eb7cb6e394caafc30bdb1f1567efc2f19bbdf3c6922e0bebed910ee4fa4f5b13bd379651da4f620f3559"}},{"token":{"uid_hash":"873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},{"token":{"uid_hash":"a08094343b4057777af4935b79df586d7eb999117883a53393e8b46f1ab19577b12039a5d2e0b9d0364bbed5c82d83a507492fea47ace633acf23da2dcf1560e"}},{"token":{"uid_hash":"d78271547cde009726b159dca09e53bee72feebe90b3eb7cb6e394caafc30bdb1f1567efc2f19bbdf3c6922e0bebed910ee4fa4f5b13bd379651da4f620f3559"}}]