mirror of
				https://github.com/jesperh1/csgo-hub-backend.git
				synced 2025-11-03 23:08:18 +00:00 
			
		
		
		
	Much better success page along with better project structure
This commit is contained in:
		
							parent
							
								
									296f977dd2
								
							
						
					
					
						commit
						764fb5b6ab
					
				
							
								
								
									
										67
									
								
								assets/checkmark.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								assets/checkmark.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					  svg {
 | 
				
			||||||
 | 
					    width: 10rem;
 | 
				
			||||||
 | 
					    height: 10rem;
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
 | 
					    margin: 40px auto 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .path {
 | 
				
			||||||
 | 
					    stroke-dasharray: 1000;
 | 
				
			||||||
 | 
					    stroke-dashoffset: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .path.circle {
 | 
				
			||||||
 | 
					    -webkit-animation: dash 0.9s ease-in-out;
 | 
				
			||||||
 | 
					    animation: dash 0.9s ease-in-out;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .path.line {
 | 
				
			||||||
 | 
					    stroke-dashoffset: 1000;
 | 
				
			||||||
 | 
					    -webkit-animation: dash 0.9s 0.35s ease-in-out forwards;
 | 
				
			||||||
 | 
					    animation: dash 0.9s 0.35s ease-in-out forwards;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .path.check {
 | 
				
			||||||
 | 
					    stroke-dashoffset: -100;
 | 
				
			||||||
 | 
					    -webkit-animation: dash-check 0.9s 0.35s ease-in-out forwards;
 | 
				
			||||||
 | 
					    animation: dash-check 0.9s 0.35s ease-in-out forwards;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  p {
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    margin: 20px 0 60px;
 | 
				
			||||||
 | 
					    font-size: 1.25em;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  p.success {
 | 
				
			||||||
 | 
					    color: #73af55;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  p.error {
 | 
				
			||||||
 | 
					    color: #d06079;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @-webkit-keyframes dash {
 | 
				
			||||||
 | 
					    0% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: 1000;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    100% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @keyframes dash {
 | 
				
			||||||
 | 
					    0% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: 1000;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    100% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @-webkit-keyframes dash-check {
 | 
				
			||||||
 | 
					    0% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: -100;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    100% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: 900;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @keyframes dash-check {
 | 
				
			||||||
 | 
					    0% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: -100;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    100% {
 | 
				
			||||||
 | 
					      stroke-dashoffset: 900;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								csgo-hub-backend
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								csgo-hub-backend
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							@ -218,7 +218,7 @@ func main() {
 | 
				
			|||||||
	router.HandleFunc("/discover", discoverHandler)
 | 
						router.HandleFunc("/discover", discoverHandler)
 | 
				
			||||||
	router.HandleFunc("/openidcallback", callbackHandler)
 | 
						router.HandleFunc("/openidcallback", callbackHandler)
 | 
				
			||||||
	router.HandleFunc("/{token}", indexHandler)
 | 
						router.HandleFunc("/{token}", indexHandler)
 | 
				
			||||||
	router.Handle("/static/", (http.StripPrefix("/static", http.FileServer(http.Dir("./assets")))))
 | 
						router.PathPrefix("/static/").Handler(http.StripPrefix("/static", http.FileServer(http.Dir("./assets"))))
 | 
				
			||||||
	router.HandleFunc("/api/v1/users", GetMultipleUsers)
 | 
						router.HandleFunc("/api/v1/users", GetMultipleUsers)
 | 
				
			||||||
	router.HandleFunc("/api/v1/token/{discord}", CreateToken)
 | 
						router.HandleFunc("/api/v1/token/{discord}", CreateToken)
 | 
				
			||||||
	http.ListenAndServe(port, router)
 | 
						http.ListenAndServe(port, router)
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,9 @@
 | 
				
			|||||||
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
					  <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
				
			||||||
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
					  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
				
			||||||
  <link rel="stylesheet" href="/static/style.css">
 | 
					  <link rel="stylesheet" href="/static/style.css">
 | 
				
			||||||
  <title>Steam OpenID</title>
 | 
					  <title>CS:GO Hub</title>
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
 | 
					 | 
				
			||||||
<body>
 | 
					<body>
 | 
				
			||||||
  {{if .DiscordName}}
 | 
					 | 
				
			||||||
  <div class="navbar">
 | 
					  <div class="navbar">
 | 
				
			||||||
    <ul>
 | 
					    <ul>
 | 
				
			||||||
      <li style="float:right"><img alt="avatar" src="{{.DiscordAvatar}}" width="50" height="50px"></li>
 | 
					      <li style="float:right"><img alt="avatar" src="{{.DiscordAvatar}}" width="50" height="50px"></li>
 | 
				
			||||||
@ -29,16 +27,9 @@
 | 
				
			|||||||
      <span>Login with Steam</span>
 | 
					      <span>Login with Steam</span>
 | 
				
			||||||
    </a>
 | 
					    </a>
 | 
				
			||||||
    <br>
 | 
					    <br>
 | 
				
			||||||
    {{else if .user}}
 | 
					 | 
				
			||||||
    <div class="login">
 | 
					 | 
				
			||||||
      <p>{{.user}} Linked to your Discord account</p>
 | 
					 | 
				
			||||||
      {{else}}
 | 
					 | 
				
			||||||
      <p>An error occured</p>
 | 
					 | 
				
			||||||
      {{end}}
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="footer">
 | 
					    <div class="footer">
 | 
				
			||||||
      <p><i>This site is not associated with Valve Corp.</i></p>
 | 
					      <p><i>This site is not associated with Valve Corp.</i></p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
 | 
					 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										30
									
								
								sites/success.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								sites/success.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8">
 | 
				
			||||||
 | 
					    <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="/static/style.css">
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="/static/checkmark.css">
 | 
				
			||||||
 | 
					    <title>CS:GO Hub</title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <div class="navbar">
 | 
				
			||||||
 | 
					        <ul>
 | 
				
			||||||
 | 
					          <li style="float:right"><img alt="avatar" src="{{.DiscordAvatar}}" width="50" height="50px"></li>
 | 
				
			||||||
 | 
					          <li style="float:right"><a class="active" href="#"><b>{{.DiscordName}}</b></a></li>
 | 
				
			||||||
 | 
					        </ul>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="login">
 | 
				
			||||||
 | 
					        <h1>{{.Status}}</h1>
 | 
				
			||||||
 | 
					        <br>
 | 
				
			||||||
 | 
					        <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 130.2 130.2">
 | 
				
			||||||
 | 
					            <circle class="path circle" fill="none" stroke="#73AF55" stroke-width="6" stroke-miterlimit="10" cx="65.1" cy="65.1" r="62.1"/>
 | 
				
			||||||
 | 
					            <polyline class="path check" fill="none" stroke="#73AF55" stroke-width="6" stroke-linecap="round" stroke-miterlimit="10" points="100.2,40.2 51.5,88.8 29.8,67.5 "/>
 | 
				
			||||||
 | 
					          </svg>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="footer">
 | 
				
			||||||
 | 
					          <p><i>This site is not associated with Valve Corp.</i></p>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										48
									
								
								steam.go
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								steam.go
									
									
									
									
									
								
							@ -16,9 +16,8 @@ import (
 | 
				
			|||||||
	"github.com/yohcop/openid-go"
 | 
						"github.com/yohcop/openid-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Load the templates once
 | 
					var authenticateTmpl = template.Must(template.ParseFiles("./sites/authenticate.html"))
 | 
				
			||||||
var templateDir = "./"
 | 
					var successTmpl = template.Must(template.ParseFiles("./sites/success.html"))
 | 
				
			||||||
var indexTemplate = template.Must(template.ParseFiles(templateDir + "index.html"))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NoOpDiscoveryCache implements the DiscoveryCache interface and doesn't cache anything.
 | 
					// NoOpDiscoveryCache implements the DiscoveryCache interface and doesn't cache anything.
 | 
				
			||||||
// For a simple website, I'm not sure you need a cache.
 | 
					// For a simple website, I'm not sure you need a cache.
 | 
				
			||||||
@ -39,6 +38,11 @@ type IndexStruct struct {
 | 
				
			|||||||
	DiscordName   string `json:"DiscordName"`
 | 
						DiscordName   string `json:"DiscordName"`
 | 
				
			||||||
	DiscordAvatar string `json:"DiscordAvatar"`
 | 
						DiscordAvatar string `json:"DiscordAvatar"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					type SuccessStruct struct {
 | 
				
			||||||
 | 
						DiscordName   string `json:"DiscordName"`
 | 
				
			||||||
 | 
						DiscordAvatar string `json:"DiscordAvatar"`
 | 
				
			||||||
 | 
						Status        string `json:"Status"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DiscordUser struct {
 | 
					type DiscordUser struct {
 | 
				
			||||||
	Id               string `json:"id"`
 | 
						Id               string `json:"id"`
 | 
				
			||||||
@ -93,7 +97,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
	expiration := time.Now().Add(time.Hour)
 | 
						expiration := time.Now().Add(time.Hour)
 | 
				
			||||||
	cookie := http.Cookie{Name: "token", Value: token, Expires: expiration}
 | 
						cookie := http.Cookie{Name: "token", Value: token, Expires: expiration}
 | 
				
			||||||
	http.SetCookie(w, &cookie)
 | 
						http.SetCookie(w, &cookie)
 | 
				
			||||||
	indexTemplate.Execute(w, tmpl)
 | 
						authenticateTmpl.Execute(w, tmpl)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// discoverHandler calls the Steam openid API and redirects to steam for login.
 | 
					// discoverHandler calls the Steam openid API and redirects to steam for login.
 | 
				
			||||||
@ -118,6 +122,7 @@ func ClearToken(token string) error {
 | 
				
			|||||||
// callbackHandler handles the response back from Steam. It verifies the callback and then renders
 | 
					// callbackHandler handles the response back from Steam. It verifies the callback and then renders
 | 
				
			||||||
// the index template with the logged in user's id.
 | 
					// the index template with the logged in user's id.
 | 
				
			||||||
func callbackHandler(w http.ResponseWriter, r *http.Request) {
 | 
					func callbackHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						var tmpl SuccessStruct
 | 
				
			||||||
	fullURL := "http://" + domain + r.URL.String()
 | 
						fullURL := "http://" + domain + r.URL.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	id, err := openid.Verify(fullURL, discoveryCache, nonceStore)
 | 
						id, err := openid.Verify(fullURL, discoveryCache, nonceStore)
 | 
				
			||||||
@ -150,6 +155,31 @@ func callbackHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		ClearToken(token)
 | 
							ClearToken(token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req, _ := http.NewRequest("GET", "https://discord.com/api/v9/users/"+discordId, nil)
 | 
				
			||||||
 | 
							req.Header.Add("Authorization", bearer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							client := &http.Client{}
 | 
				
			||||||
 | 
							resp, err := client.Do(req)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Println("Error on response.\n[ERROR] -", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer resp.Body.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							body, err := io.ReadAll(resp.Body)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Println("Error while reading the response bytes:", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var discord DiscordUser
 | 
				
			||||||
 | 
							json.Unmarshal(body, &discord)
 | 
				
			||||||
 | 
							var discordAvatarURL string
 | 
				
			||||||
 | 
							if discord.Avatar == "" {
 | 
				
			||||||
 | 
								discordAvatarURL = "https://csgohub.xyz/assets/empty-avatar.png"
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								discordAvatarURL = "https://cdn.discordapp.com/avatars/" + discord.Id + "/" + discord.Avatar + ".png?size=100"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							tmpl.DiscordName = discord.Username
 | 
				
			||||||
 | 
							tmpl.DiscordAvatar = discordAvatarURL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var checkId, checkFriend string
 | 
							var checkId, checkFriend string
 | 
				
			||||||
		query = `SELECT discord_id, friend_code FROM users where discord_id = ?`
 | 
							query = `SELECT discord_id, friend_code FROM users where discord_id = ?`
 | 
				
			||||||
		err = db.QueryRow(query, discordId).Scan(&checkId, &checkFriend)
 | 
							err = db.QueryRow(query, discordId).Scan(&checkId, &checkFriend)
 | 
				
			||||||
@ -161,8 +191,10 @@ func callbackHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
				fmt.Fprintf(w, "Bad request")
 | 
									fmt.Fprintf(w, "Bad request")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			log.Print(err)
 | 
								log.Print(err)
 | 
				
			||||||
			w.WriteHeader(http.StatusCreated)
 | 
								// w.WriteHeader(http.StatusCreated)
 | 
				
			||||||
			fmt.Fprintf(w, "Account link updated")
 | 
								// fmt.Fprintf(w, "Account link updated")
 | 
				
			||||||
 | 
								tmpl.Status = "Account link updated"
 | 
				
			||||||
 | 
								successTmpl.Execute(w, tmpl)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -171,10 +203,12 @@ func callbackHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
			log.Println(err)
 | 
								log.Println(err)
 | 
				
			||||||
			w.WriteHeader(http.StatusBadRequest)
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
			fmt.Fprintf(w, "Bad request")
 | 
								fmt.Fprintf(w, "Bad request")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							tmpl.Status = "Account linked"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		w.WriteHeader(http.StatusCreated)
 | 
							w.WriteHeader(http.StatusCreated)
 | 
				
			||||||
		data["user"] = id
 | 
							data["user"] = id
 | 
				
			||||||
		indexTemplate.Execute(w, data)
 | 
							successTmpl.Execute(w, tmpl)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user