-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
155 lines (132 loc) · 4.48 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"github.com/saurabhmittal16/fluttermate/creds"
"github.com/saurabhmittal16/fluttermate/firebase"
"github.com/saurabhmittal16/fluttermate/score"
)
var clientSecret string
var clientID string
type authHandler func(http.ResponseWriter, *http.Request, tokenData)
type text struct {
Code int `json:"code"`
Message string `json:"message"`
}
type authMessage struct {
Code int `json:"code"`
Message string `json:"message"`
}
type tokenData struct {
uid string
ghID string
email string
}
type firebaseUser struct {
Name string `json:"name" firestore:"name"`
Picture string `json:"avatar_url" firestore:"picture"`
Email string `json:"email" firestore:"email"`
Username string `json:"login" firestore:"username"`
Location string `json:"location" firestore:"location"`
Bio string `json:"bio" firestore:"bio"`
Repos int `json:"public_repos" firestore:"repos"`
Followers int `json:"followers" firestore:"followers"`
Following int `json:"following" firestore:"following"`
Github int `json:"id" firestore:"github"`
}
func getURL(id string) string {
return fmt.Sprintf("https://api.github.com/user/%s?client_id=%s&client_secret=%s", id, clientID, clientSecret)
}
func checkAuth(f authHandler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
data, err := firebase.VerifyToken(token)
checkHTTPError(w, err, "Could not verify token", http.StatusInternalServerError)
temp := data.Claims["firebase"].(map[string]interface{})["identities"].(map[string]interface{})
user := tokenData{
uid: data.UID,
ghID: temp["github.com"].([]interface{})[0].(string),
email: temp["email"].([]interface{})[0].(string),
}
// fmt.Println(user)
f(w, r, user)
}
}
// welcomeResponse handles requests to root
func welcomeResponse(w http.ResponseWriter, r *http.Request) {
err := jsonResponse(w, r, text{
Message: "Welcome to FlutterMate",
})
checkHTTPError(w, err, "Could not generate JSON Response", http.StatusInternalServerError)
}
func signupResponse(w http.ResponseWriter, r *http.Request, user tokenData) {
if r.Method != http.MethodPost {
http.Error(w, "Not found", http.StatusNotFound)
return
}
// if user already exists, respond with login successful
if firebase.DocExists(user.uid, "users") {
fmt.Println("User exists, login successful")
err := jsonResponse(w, r, authMessage{
Code: 1,
Message: "Login successful",
})
checkHTTPError(w, err, "Could not generate JSON Response", http.StatusInternalServerError)
} else {
// get user info from Github API
profile, err := http.Get(getURL(user.ghID))
checkHTTPError(w, err, "Failed to fetch data from Github API", http.StatusInternalServerError)
// decode user from API response
var newUser firebaseUser
err = json.NewDecoder(profile.Body).Decode(&newUser)
checkHTTPError(w, err, "Error while decoding API response", http.StatusInternalServerError)
newUser.Email = user.email
// save user to Firestore
err = firebase.CreateUser(user.uid, "users", newUser)
checkHTTPError(w, err, "Error while decoding API response", http.StatusInternalServerError)
fmt.Println("User created successfuly")
// respond with signup successful
err = jsonResponse(w, r, authMessage{
Code: 2,
Message: "Signup successful",
})
checkHTTPError(w, err, "Could not generate JSON Response", http.StatusInternalServerError)
// create go routine that calculates score and updates to firestore
go func(ghID string, docID string) {
start := time.Now()
score, err := score.GetScore(ghID)
if err != nil {
fmt.Printf("Could not calculate score: %v\n", err)
return
}
err = firebase.UpdateScore(docID, "users", score)
if err != nil {
fmt.Printf("Could not calculate score: %v\n", err)
return
}
fmt.Printf("Score of user %s is %v, updated successfuly in %v\n", docID, score, time.Now().Sub(start))
}(user.ghID, user.uid)
}
}
func init() {
/*
pass path of JSON file containing Github app credentials of form-
{
"client_id": "xxxxx",
"client_secret": "yyyyy"
}
*/
clientID, clientSecret = creds.GetClientCreds("./github.json")
score.Init(clientID, clientSecret)
}
func main() {
// Register routes
http.HandleFunc("/", welcomeResponse)
http.HandleFunc("/signup", checkAuth(signupResponse))
// Start the server and log errors
fmt.Println("Server running at port 3000")
log.Fatal(http.ListenAndServe(":3000", nil))
}