Checkpoint 4
This commit is contained in:
		| @@ -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
									
								
							
							
						
						
									
										1
									
								
								godoor_server/keys.json
									
									
									
									
									
										Normal 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"}}] | ||||
		Reference in New Issue
	
	Block a user