Compare commits
	
		
			No commits in common. "75ba836d6072235fc7a71659f8630ab3c1b210ad" and "68f3bd53328606a921dd72870f38723286d803e1" have entirely different histories.
		
	
	
		
			75ba836d60
			...
			68f3bd5332
		
	
		
							
								
								
									
										23
									
								
								api/dns.go
								
								
								
								
							
							
						
						
									
										23
									
								
								api/dns.go
								
								
								
								
							|  | @ -1,23 +0,0 @@ | ||||||
| package api |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"log" |  | ||||||
| 	"net/http" |  | ||||||
| 
 |  | ||||||
| 	"git.hatecomputers.club/hatecomputers/hatecomputers.club/database" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func ListDNSRecordsContinuation(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain { |  | ||||||
| 	return func(success Continuation, failure Continuation) ContinuationChain { |  | ||||||
| 		dnsRecords, err := database.GetUserDNSRecords(context.DBConn, context.User.ID) |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			resp.WriteHeader(http.StatusInternalServerError) |  | ||||||
| 			return failure(context, req, resp) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		(*context.TemplateData)["DNSRecords"] = dnsRecords |  | ||||||
| 
 |  | ||||||
| 		return success(context, req, resp) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										12
									
								
								api/serve.go
								
								
								
								
							
							
						
						
									
										12
									
								
								api/serve.go
								
								
								
								
							|  | @ -19,7 +19,6 @@ type RequestContext struct { | ||||||
| 	Id    string | 	Id    string | ||||||
| 	Start time.Time | 	Start time.Time | ||||||
| 
 | 
 | ||||||
| 	TemplateData *map[string]interface{} |  | ||||||
| 	User *database.User | 	User *database.User | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -76,14 +75,12 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { | ||||||
| 		return &RequestContext{ | 		return &RequestContext{ | ||||||
| 			DBConn: dbConn, | 			DBConn: dbConn, | ||||||
| 			Args:   argv, | 			Args:   argv, | ||||||
| 
 |  | ||||||
| 			TemplateData: &map[string]interface{}{}, |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | 	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		requestContext := makeRequestContext() | 		requestContext := makeRequestContext() | ||||||
| 		LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation("home.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) | 		LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation("home.html", nil, true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	mux.HandleFunc("GET /api/health", func(w http.ResponseWriter, r *http.Request) { | 	mux.HandleFunc("GET /api/health", func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | @ -111,15 +108,10 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { | ||||||
| 		LogRequestContinuation(requestContext, r, w)(LogoutContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) | 		LogRequestContinuation(requestContext, r, w)(LogoutContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	mux.HandleFunc("GET /dns", func(w http.ResponseWriter, r *http.Request) { |  | ||||||
| 		requestContext := makeRequestContext() |  | ||||||
| 		LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(ListDNSRecordsContinuation, GoLoginContinuation)(TemplateContinuation("dns.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	mux.HandleFunc("GET /{name}", func(w http.ResponseWriter, r *http.Request) { | 	mux.HandleFunc("GET /{name}", func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		requestContext := makeRequestContext() | 		requestContext := makeRequestContext() | ||||||
| 		name := r.PathValue("name") | 		name := r.PathValue("name") | ||||||
| 		LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation(name+".html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) | 		LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation(name+".html", nil, true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	return &http.Server{ | 	return &http.Server{ | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ import ( | ||||||
| 	"os" | 	"os" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func renderTemplate(context *RequestContext, templateName string, showBaseHtml bool) (bytes.Buffer, error) { | func renderTemplate(context *RequestContext, templateName string, showBaseHtml bool, data interface{}) (bytes.Buffer, error) { | ||||||
| 	templatePath := context.Args.TemplatePath | 	templatePath := context.Args.TemplatePath | ||||||
| 	basePath := templatePath + "/base_empty.html" | 	basePath := templatePath + "/base_empty.html" | ||||||
| 	if showBaseHtml { | 	if showBaseHtml { | ||||||
|  | @ -22,14 +22,11 @@ func renderTemplate(context *RequestContext, templateName string, showBaseHtml b | ||||||
| 		return bytes.Buffer{}, err | 		return bytes.Buffer{}, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dataPtr := context.TemplateData | 	if data == nil { | ||||||
| 	if dataPtr == nil { | 		data = map[string]interface{}{} | ||||||
| 		dataPtr = &map[string]interface{}{} |  | ||||||
| 	} | 	} | ||||||
| 
 | 	if context.User != nil { | ||||||
| 	data := *dataPtr | 		data.(map[string]interface{})["User"] = context.User | ||||||
| 	if data["User"] == nil { |  | ||||||
| 		data["User"] = context.User |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var buffer bytes.Buffer | 	var buffer bytes.Buffer | ||||||
|  | @ -41,13 +38,13 @@ func renderTemplate(context *RequestContext, templateName string, showBaseHtml b | ||||||
| 	return buffer, nil | 	return buffer, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TemplateContinuation(path string, showBase bool) Continuation { | func TemplateContinuation(path string, data interface{}, showBase bool) Continuation { | ||||||
| 	return func(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain { | 	return func(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain { | ||||||
| 		return func(success Continuation, failure Continuation) ContinuationChain { | 		return func(success Continuation, failure Continuation) ContinuationChain { | ||||||
| 			html, err := renderTemplate(context, path, true) | 			html, err := renderTemplate(context, path, true, data) | ||||||
| 			if errors.Is(err, os.ErrNotExist) { | 			if errors.Is(err, os.ErrNotExist) { | ||||||
| 				resp.WriteHeader(404) | 				resp.WriteHeader(404) | ||||||
| 				html, err = renderTemplate(context, "404.html", true) | 				html, err = renderTemplate(context, "404.html", true, nil) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					log.Println("error rendering 404 template", err) | 					log.Println("error rendering 404 template", err) | ||||||
| 					resp.WriteHeader(500) | 					resp.WriteHeader(500) | ||||||
|  |  | ||||||
|  | @ -1,40 +0,0 @@ | ||||||
| package database |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"database/sql" |  | ||||||
| 	_ "github.com/mattn/go-sqlite3" |  | ||||||
| 	"log" |  | ||||||
| 	"time" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type DNSRecord struct { |  | ||||||
| 	ID        string |  | ||||||
| 	UserID    string |  | ||||||
| 	Name      string |  | ||||||
| 	Type      string |  | ||||||
| 	Content   string |  | ||||||
| 	TTL       int |  | ||||||
| 	CreatedAt time.Time |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func GetUserDNSRecords(db *sql.DB, userID string) ([]DNSRecord, error) { |  | ||||||
| 	log.Println("getting dns records for user", userID) |  | ||||||
| 
 |  | ||||||
| 	rows, err := db.Query("SELECT * FROM dns_records WHERE user_id = ?", userID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	defer rows.Close() |  | ||||||
| 
 |  | ||||||
| 	var records []DNSRecord |  | ||||||
| 	for rows.Next() { |  | ||||||
| 		var record DNSRecord |  | ||||||
| 		err := rows.Scan(&record.ID, &record.UserID, &record.Name, &record.Type, &record.Content, &record.TTL, &record.CreatedAt) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		records = append(records, record) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return records, nil |  | ||||||
| } |  | ||||||
|  | @ -1,33 +1,13 @@ | ||||||
| :root { | :root { | ||||||
|   --background-color-light: #f4e8e9; |   --background-color: #f4e8e9; | ||||||
|   --background-color-light-2: #f7f7f7; |   --text-color: #333; | ||||||
|   --text-color-light: #333; |   --link-color: #d291bc; | ||||||
|   --link-color-light: #d291bc; |   --container-bg: #fff7f8; | ||||||
|   --container-bg-light: #fff7f87a; |  | ||||||
|   --border-color-light: #692fcc; |  | ||||||
| 
 |  | ||||||
|   --background-color-dark: #333; |  | ||||||
|   --background-color-dark-2: #2c2c2c; |  | ||||||
|   --text-color-dark: #f4e8e9; |  | ||||||
|   --link-color-dark: #b86b77; |  | ||||||
|   --container-bg-dark: #424242ea; |  | ||||||
|   --border-color-dark: #956ade; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [data-theme="DARK"] { | [data-theme="DARK"] { | ||||||
|   --background-color: var(--background-color-dark); |   --background-color: #333; | ||||||
|   --background-color-2: var(--background-color-dark-2); |   --text-color: #f4e8e9; | ||||||
|   --text-color: var(--text-color-dark); |   --link-color: #b86b77; | ||||||
|   --link-color: var(--link-color-dark); |   --container-bg: #424242; | ||||||
|   --container-bg: var(--container-bg-dark); |  | ||||||
|   --border-color: var(--border-color-dark); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| [data-theme="LIGHT"] { |  | ||||||
|   --background-color: var(--background-color-light); |  | ||||||
|   --background-color-2: var(--background-color-light-2); |  | ||||||
|   --text-color: var(--text-color-light); |  | ||||||
|   --link-color: var(--link-color-light); |  | ||||||
|   --container-bg: var(--container-bg-light); |  | ||||||
|   --border-color: var(--border-color-light); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,30 +0,0 @@ | ||||||
| form { |  | ||||||
|   max-width: 600px; |  | ||||||
|   padding: 1em; |  | ||||||
|   background: var(--background-color-2); |  | ||||||
|   border: 1px solid #ccc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| label { |  | ||||||
|   display: block; |  | ||||||
|   margin: 0 0 1em; |  | ||||||
|   font-weight: bold; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| input { |  | ||||||
|   display: block; |  | ||||||
|   width: 100%; |  | ||||||
|   padding: 0.5em; |  | ||||||
|   margin: 0 0 1em; |  | ||||||
|   border: 1px solid var(--border-color); |  | ||||||
|   background: var(--container-bg); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| button, |  | ||||||
| input[type="submit"] { |  | ||||||
|   padding: 0.5em 1em; |  | ||||||
|   background: var(--link-color); |  | ||||||
|   color: var(--text-color); |  | ||||||
|   border: 0; |  | ||||||
|   cursor: pointer; |  | ||||||
| } |  | ||||||
|  | @ -1,7 +1,5 @@ | ||||||
| @import "/static/css/colors.css"; | @import "/static/css/colors.css"; | ||||||
| @import "/static/css/blinky.css"; | @import "/static/css/blinky.css"; | ||||||
| @import "/static/css/table.css"; |  | ||||||
| @import "/static/css/form.css"; |  | ||||||
| 
 | 
 | ||||||
| @font-face { | @font-face { | ||||||
|   font-family: "ComicSans"; |   font-family: "ComicSans"; | ||||||
|  | @ -13,10 +11,10 @@ | ||||||
|   margin: 0; |   margin: 0; | ||||||
|   padding: 0; |   padding: 0; | ||||||
|   color: var(--text-color); |   color: var(--text-color); | ||||||
|   font-family: "ComicSans", sans-serif; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| body { | body { | ||||||
|  |   font-family: "ComicSans", sans-serif; | ||||||
|   background-color: var(--background-color); |   background-color: var(--background-color); | ||||||
|   background-image: url("/static/img/stars.gif"); |   background-image: url("/static/img/stars.gif"); | ||||||
|   min-height: 100vh; |   min-height: 100vh; | ||||||
|  | @ -37,6 +35,7 @@ a:hover { | ||||||
|   margin: auto; |   margin: auto; | ||||||
|   background-color: var(--container-bg); |   background-color: var(--container-bg); | ||||||
|   padding: 1rem; |   padding: 1rem; | ||||||
|  |   opacity: 0.95; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| hr { | hr { | ||||||
|  | @ -45,11 +44,3 @@ hr { | ||||||
| 
 | 
 | ||||||
|   margin: 20px 0; |   margin: 20px 0; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| .blinkies { |  | ||||||
|   display: flex; |  | ||||||
|   justify-content: left; |  | ||||||
|   flex-wrap: wrap; |  | ||||||
|   max-width: 900px; |  | ||||||
|   gap: 10px 10px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,26 +0,0 @@ | ||||||
| table { |  | ||||||
|   width: auto; |  | ||||||
|   border-collapse: collapse; |  | ||||||
|   border: 1px solid var(--border-color); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| th, |  | ||||||
| td { |  | ||||||
|   padding: 12px 20px; |  | ||||||
|   text-align: left; |  | ||||||
|   border-bottom: 1px solid var(--border-color); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| tbody tr:nth-child(odd) { |  | ||||||
|   background-color: var(--link-color); |  | ||||||
|   color: var(--text-color); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| tbody tr { |  | ||||||
|   transition: background-color 0.3s ease; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| tbody tr:hover { |  | ||||||
|   background-color: #ff47daa0; |  | ||||||
|   color: #2a2a2a; |  | ||||||
| } |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 4.0 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.2 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.4 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.7 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 704 B | 
|  | @ -24,4 +24,4 @@ themeSwitcher.addEventListener("click", () => | ||||||
|   setTheme(flipFlopTheme(document.documentElement.getAttribute("data-theme"))), |   setTheme(flipFlopTheme(document.documentElement.getAttribute("data-theme"))), | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| setTheme(localStorage.getItem("theme") || THEMES.LIGHT); | setTheme(localStorage.getItem("theme") ?? THEMES.LIGHT); | ||||||
|  |  | ||||||
|  | @ -1,10 +1,5 @@ | ||||||
| const preferredMode = window.matchMedia("(prefers-color-scheme: dark)").matches |  | ||||||
|   ? "DARK" |  | ||||||
|   : "LIGHT"; |  | ||||||
| 
 |  | ||||||
| // sets theme before rendering & jquery loaded to prevent flashing of uninitialized theme
 | // sets theme before rendering & jquery loaded to prevent flashing of uninitialized theme
 | ||||||
| // (ugly white background)
 | // (ugly white background)
 | ||||||
| localStorage.setItem("theme", localStorage.getItem("theme") || preferredMode); |  | ||||||
| document.documentElement.setAttribute( | document.documentElement.setAttribute( | ||||||
|   "data-theme", |   "data-theme", | ||||||
|   localStorage.getItem("theme"), |   localStorage.getItem("theme"), | ||||||
|  |  | ||||||
|  | @ -50,6 +50,13 @@ | ||||||
| 
 | 
 | ||||||
|       <div class="footer"> |       <div class="footer"> | ||||||
| 	<div> | 	<div> | ||||||
|  | 	  <img width="150" height="20" src="/static/img/blinkies/hatecomputers-club.gif"> | ||||||
|  | 	  <img width="150" height="20" src="/static/img/blinkies/loveuguys.gif"> | ||||||
|  | 	  <img width="150" height="20" src="/static/img/blinkies/autism.gif"> | ||||||
|  | 	  <img width="150" height="20" src="/static/img/blinkies/fuckcomputers.gif"> | ||||||
|  | 	  <img width="150" height="20" src="/static/img/blinkies/connection.gif"> | ||||||
|  | 	</div> | ||||||
|  | 	 | ||||||
| 	{{ if .User }} | 	{{ if .User }} | ||||||
| 	<a href="https://git.hatecomputers.club/{{ .User.Username }}">git.</a> | 	<a href="https://git.hatecomputers.club/{{ .User.Username }}">git.</a> | ||||||
| 	{{ else }} | 	{{ else }} | ||||||
|  | @ -61,21 +68,6 @@ | ||||||
| 	<span> | </span> | 	<span> | </span> | ||||||
| 	<a href="https://auth.hatecomputers.club">sso.</a> | 	<a href="https://auth.hatecomputers.club">sso.</a> | ||||||
|       </div> |       </div> | ||||||
| 
 |  | ||||||
| 	<br> |  | ||||||
| 
 |  | ||||||
| 	<div class="blinkies"> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/hatecomputers-club.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/autism.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/fuckcomputers.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/bee.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/begaydocrime.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/bored.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/connection.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/eepy.gif'> |  | ||||||
| 	  <img width='150' height='20' src='/static/img/blinkies/loveuguys.gif'> |  | ||||||
| 	</div> |  | ||||||
|       </div> |  | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <script data-main="/static/js/script.js" src="/static/js/require.js"></script> |     <script data-main="/static/js/script.js" src="/static/js/require.js"></script> | ||||||
|  |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| {{ define "content" }} |  | ||||||
|   <table> |  | ||||||
|     <tr> |  | ||||||
|       <th>Type</th> |  | ||||||
|       <th>Name</th> |  | ||||||
|       <th>Content</th> |  | ||||||
|       <th>TTL</th> |  | ||||||
|     </tr> |  | ||||||
|     {{ if (eq (len .DNSRecords) 0) }} |  | ||||||
|     <tr> |  | ||||||
|       <td colspan="4"><span class="blinky">No DNS records found</span></td> |  | ||||||
|     </tr> |  | ||||||
|     {{ end }} |  | ||||||
|     {{ range $record := .DNSRecords }} |  | ||||||
|       <tr> |  | ||||||
| 	<td>{{ $record.Type }}</td> |  | ||||||
| 	<td>{{ $record.Name }}</td> |  | ||||||
| 	<td>{{ $record.Content }}</td> |  | ||||||
| 	<td>{{ $record.TTL }}</td> |  | ||||||
|       </tr> |  | ||||||
|     {{ end }} |  | ||||||
|   </table> |  | ||||||
|   <br> |  | ||||||
|   <form method="POST" action="/dns"> |  | ||||||
|     <h2>Add DNS Records</h2> |  | ||||||
|     <hr> |  | ||||||
|     <label for="type">Type</label> |  | ||||||
|     <input type="text" name="type" placeholder="CNAME" required /> |  | ||||||
|     <label for="name">Name</label> |  | ||||||
|     <input type="text" name="name" placeholder="{{ .User.Username }}" required /> |  | ||||||
|     <label for="content">Content</label> |  | ||||||
|     <input type="text" name="content" placeholder="{{ .User.Username }}.dev" required /> |  | ||||||
|     <label for="ttl">TTL</label> |  | ||||||
|     <input type="text" name="ttl" placeholder="43200" required /> |  | ||||||
|     <input type="submit" value="Add" /> |  | ||||||
|   </form> |  | ||||||
| {{ end }} |  | ||||||
		Loading…
	
		Reference in New Issue