Checkpoint 2
This commit is contained in:
		
							
								
								
									
										1
									
								
								format.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								format.ps1
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
npx prettier . --write --use-tabs
 | 
			
		||||
							
								
								
									
										57
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								index.html
									
									
									
									
									
								
							@@ -1,13 +1,14 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<head>
 | 
			
		||||
	<meta charset="UTF-8">
 | 
			
		||||
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
	<meta charset="UTF-8" />
 | 
			
		||||
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
			
		||||
	<title>{{.Title}}</title>
 | 
			
		||||
	<style>
 | 
			
		||||
		* {
 | 
			
		||||
			font-family: Tahoma, sans-serif;
 | 
			
		||||
			font-size: large;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		html {
 | 
			
		||||
			background-color: #222222;
 | 
			
		||||
			color: #eeeeee;
 | 
			
		||||
@@ -17,24 +18,52 @@
 | 
			
		||||
<body>
 | 
			
		||||
	<div style="display: flex; align-items: center; flex-direction: column">
 | 
			
		||||
		<p>{{.Message}}</p>
 | 
			
		||||
	{{if .ShowInput}}
 | 
			
		||||
		{{if not .Authenticated}}
 | 
			
		||||
		<form
 | 
			
		||||
			action="/login"
 | 
			
		||||
			method="post"
 | 
			
		||||
			style="display: flex; flex-direction: column; align-items: stretch"
 | 
			
		||||
		>
 | 
			
		||||
			<label>
 | 
			
		||||
				Username:
 | 
			
		||||
				<input type="text" name="username" required />
 | 
			
		||||
			</label>
 | 
			
		||||
			<label>
 | 
			
		||||
				Password:
 | 
			
		||||
				<input type="password" name="password" required />
 | 
			
		||||
			</label>
 | 
			
		||||
			<button type="submit">Login</button>
 | 
			
		||||
		</form>
 | 
			
		||||
		{{end}} {{if .ShowInput}}
 | 
			
		||||
		<form action="/post" method="post">
 | 
			
		||||
			<label>
 | 
			
		||||
				How many hours should the timeout be?
 | 
			
		||||
			<input type="number" name="next" min="1" max="24" value="24" step="1" required>
 | 
			
		||||
				<input
 | 
			
		||||
					type="number"
 | 
			
		||||
					name="next"
 | 
			
		||||
					min="1"
 | 
			
		||||
					max="24"
 | 
			
		||||
					value="24"
 | 
			
		||||
					step="1"
 | 
			
		||||
					required
 | 
			
		||||
				/>
 | 
			
		||||
			</label>
 | 
			
		||||
			<button type="submit">Submit</button>
 | 
			
		||||
		</form>
 | 
			
		||||
		{{end}}
 | 
			
		||||
	{{if .ShowLogin}}
 | 
			
		||||
	<form action="/login" method="post">
 | 
			
		||||
		<label>
 | 
			
		||||
			<input type="text" name="username" required>
 | 
			
		||||
			<input type="password" name="password" required>
 | 
			
		||||
		</label>
 | 
			
		||||
		<button type="submit">Login</button>
 | 
			
		||||
	</form>
 | 
			
		||||
		{{ range .Timestamps}}
 | 
			
		||||
		<table style="text-align: center">
 | 
			
		||||
			<tr>
 | 
			
		||||
				<th>Taken</th>
 | 
			
		||||
				<th>Ends</th>
 | 
			
		||||
				<th>Has Ended</th>
 | 
			
		||||
			</tr>
 | 
			
		||||
			<tr>
 | 
			
		||||
				<td>{{ index . 0}}</td>
 | 
			
		||||
				<td>{{ index . 1}}</td>
 | 
			
		||||
				<td>{{ index . 2}}</td>
 | 
			
		||||
			</tr>
 | 
			
		||||
		</table>
 | 
			
		||||
		{{end}}
 | 
			
		||||
 | 
			
		||||
	</div>
 | 
			
		||||
</body>
 | 
			
		||||
							
								
								
									
										124
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								main.go
									
									
									
									
									
								
							@@ -28,6 +28,8 @@ type PageData struct {
 | 
			
		||||
	Message       string
 | 
			
		||||
	ShowLogin     bool
 | 
			
		||||
	ShowInput     bool
 | 
			
		||||
	Authenticated bool
 | 
			
		||||
	Timestamps    [][]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var Username string
 | 
			
		||||
@@ -41,14 +43,14 @@ func main() {
 | 
			
		||||
	Username = os.Getenv("USERNAME")
 | 
			
		||||
	fmt.Println("Username: ", Username)
 | 
			
		||||
 | 
			
		||||
	Password = os.Getenv("API_KEY")
 | 
			
		||||
	fmt.Println("API_KEY: ", Password)
 | 
			
		||||
	Password = os.Getenv("PASSWORD")
 | 
			
		||||
	fmt.Println("Password: ", Password)
 | 
			
		||||
 | 
			
		||||
	DataDir = os.Getenv("DATA_DIR")
 | 
			
		||||
	if DataDir == "" {
 | 
			
		||||
		DataDir = "./data"
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println("DATA_DIR: ", DataDir)
 | 
			
		||||
	fmt.Println("DataDir: ", DataDir)
 | 
			
		||||
 | 
			
		||||
	DataStore = DataDir + "/data.json"
 | 
			
		||||
 | 
			
		||||
@@ -145,7 +147,7 @@ func commit(next int64) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func query() bool {
 | 
			
		||||
func queryCanPost() bool {
 | 
			
		||||
	// Check if file exists
 | 
			
		||||
	if file, err := os.Open(DataStore); err != nil {
 | 
			
		||||
		fmt.Println("Error opening file, check permissions")
 | 
			
		||||
@@ -179,47 +181,57 @@ func query() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func queryData() []Timestamp {
 | 
			
		||||
	// Check if file exists
 | 
			
		||||
	if file, err := os.Open(DataStore); err != nil {
 | 
			
		||||
		fmt.Println("Error opening file, check permissions")
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	} else {
 | 
			
		||||
		// Decode file
 | 
			
		||||
		decoder := json.NewDecoder(file)
 | 
			
		||||
		store := Store{}
 | 
			
		||||
		if err = decoder.Decode(&store); err != nil {
 | 
			
		||||
			fmt.Println("Error decoding file")
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		if err = file.Close(); err != nil {
 | 
			
		||||
			fmt.Println("Error closing file")
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return store.Timestamps
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func index(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	tmpl := template.Must(template.ParseFiles("index.html"))
 | 
			
		||||
	var data PageData
 | 
			
		||||
	fmt.Println("GET request received")
 | 
			
		||||
	unauthenticated := PageData{
 | 
			
		||||
		Title:     "Log in",
 | 
			
		||||
		Message:   "Please enter your username and password",
 | 
			
		||||
		ShowLogin: true,
 | 
			
		||||
		ShowInput: false,
 | 
			
		||||
	tmpl := template.Must(template.ParseFiles("index.html"))
 | 
			
		||||
	auth := checkAuth(r)
 | 
			
		||||
	data := PageData{
 | 
			
		||||
		Authenticated: auth,
 | 
			
		||||
	}
 | 
			
		||||
	authenticated := PageData{
 | 
			
		||||
		Title:     "View data",
 | 
			
		||||
		Message:   "Welcome back " + Username + ". Check in after the timeout",
 | 
			
		||||
		ShowLogin: false,
 | 
			
		||||
		ShowInput: true,
 | 
			
		||||
	if auth {
 | 
			
		||||
		data.Title = "View data"
 | 
			
		||||
		data.Message = "Welcome back " + Username + ". Check in after the timeout"
 | 
			
		||||
		data.ShowInput = queryCanPost()
 | 
			
		||||
 | 
			
		||||
		var timestamps [][]string
 | 
			
		||||
		for _, ts := range queryData() {
 | 
			
		||||
			one := time.Unix(ts.Current, 0)
 | 
			
		||||
			two := time.Unix(ts.Next, 0)
 | 
			
		||||
			ended := time.Now().Unix() > ts.Next
 | 
			
		||||
			str := strconv.FormatBool(ended)
 | 
			
		||||
			timestamps = append(timestamps, []string{one.Format(time.DateTime), two.Format(time.DateTime), str})
 | 
			
		||||
		}
 | 
			
		||||
	// Check for session cookie
 | 
			
		||||
	cookie, err := r.Cookie("session")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		data = unauthenticated
 | 
			
		||||
 | 
			
		||||
		data.Timestamps = timestamps
 | 
			
		||||
	} else {
 | 
			
		||||
		// Parse cookie to int64
 | 
			
		||||
		if session, err := strconv.ParseInt(cookie.Value, 10, 64); err != nil {
 | 
			
		||||
			fmt.Println("Error parsing cookie")
 | 
			
		||||
			data = unauthenticated
 | 
			
		||||
		} else {
 | 
			
		||||
			found := false
 | 
			
		||||
			for _, uuid := range Authorised {
 | 
			
		||||
				if uuid == session {
 | 
			
		||||
					found = true
 | 
			
		||||
		data.Title = "Log in"
 | 
			
		||||
		data.Message = "Please enter your username and password"
 | 
			
		||||
		data.ShowInput = false
 | 
			
		||||
		data.Timestamps = nil
 | 
			
		||||
	}
 | 
			
		||||
			}
 | 
			
		||||
			if found {
 | 
			
		||||
				data = authenticated
 | 
			
		||||
			} else {
 | 
			
		||||
				// If cookie is not in Authorised list, remove it
 | 
			
		||||
				data = unauthenticated
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	authenticated.ShowInput = query()
 | 
			
		||||
	if err := tmpl.Execute(w, data); err != nil {
 | 
			
		||||
		http.Error(w, "Error rendering template", http.StatusInternalServerError)
 | 
			
		||||
	}
 | 
			
		||||
@@ -227,6 +239,12 @@ func index(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
 | 
			
		||||
func post(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	fmt.Println("POST request received")
 | 
			
		||||
 | 
			
		||||
	if !checkAuth(r) {
 | 
			
		||||
		http.Error(w, "Not authorised", http.StatusUnauthorized)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := r.ParseForm(); err != nil {
 | 
			
		||||
		http.Error(w, "Error parsing form", http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
@@ -273,12 +291,38 @@ func login(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
 | 
			
		||||
func logout(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	fmt.Println("LOGOUT request received")
 | 
			
		||||
 | 
			
		||||
	if !checkAuth(r) {
 | 
			
		||||
		http.Error(w, "Not authorised", http.StatusUnauthorized)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cookie := http.Cookie{
 | 
			
		||||
		Name:  "session",
 | 
			
		||||
		Value: "",
 | 
			
		||||
		Expires: time.Now().Add(-1 * time.Hour),
 | 
			
		||||
	}
 | 
			
		||||
	http.SetCookie(w, &cookie)
 | 
			
		||||
	http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkAuth(r *http.Request) bool {
 | 
			
		||||
	// Check for session cookie
 | 
			
		||||
	cookie, err := r.Cookie("session")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	} else {
 | 
			
		||||
		// Parse cookie to int64
 | 
			
		||||
		if session, err := strconv.ParseInt(cookie.Value, 10, 64); err != nil {
 | 
			
		||||
			fmt.Println("Error parsing cookie")
 | 
			
		||||
			return false
 | 
			
		||||
		} else {
 | 
			
		||||
			for _, uuid := range Authorised {
 | 
			
		||||
				if uuid == session {
 | 
			
		||||
					return true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user