Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/andrioid/prototypes.
Something went wrong. Try again.
3.5 kB · 143 lines
Go
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144package main
import ( "bytes" "encoding/json" "fmt" "io" "nats-w-auth/internal/users" "net/http" "os" "strconv")
// https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-a-usertype GitHubUser struct { Name string Avatar_url string ID int}
func githubSuccessHandler(w http.ResponseWriter, r *http.Request) { provider := "github" code := r.URL.Query().Get("code") fmt.Println("callback from github", code) token, err := tokenForCode(code) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Println("access token", token) ghUser, err := getGithubUser(token) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Println("user", ghUser) sessionManager.Put(r.Context(), "pie", ghUser.Name) user, err := userManager.GetOAuthUser(r.Context(), provider, strconv.Itoa(ghUser.ID)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if user == nil { // TODO: Create core user // TODO: Create user/oauth connection fmt.Println("we should create user", user) user, err = userManager.CreateUser(r.Context(), users.UserModelInfo{ Name: ghUser.Name, AvatarURL: ghUser.Avatar_url, }) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } } err = userManager.LinkUserProvider(r.Context(), user, provider, strconv.Itoa(ghUser.ID)) sessionManager.Put(r.Context(), "user_id", user.ID) sessionManager.Put(r.Context(), "name", user.Name) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return }
// TODO: Find or create user according to GitHub user_id // TODO: Set (our) user_id, user on session
// DONE http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}
func tokenForCode(code string) (string, error) { // TODO: Validate the code url := "https://github.com/login/oauth/access_token"
payload := map[string]string{ "client_id": os.Getenv("GH_CLIENT_ID"), "client_secret": os.Getenv("GH_CLIENT_SECRET"), "code": code, } body, _ := json.Marshal(payload)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) if err != nil { return "", err } req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req) if err != nil { return "", err } defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
var tokenResp map[string]any if err := json.Unmarshal(respBody, &tokenResp); err != nil { return "", err }
token, ok := tokenResp["access_token"].(string) if !ok { return "", fmt.Errorf("no access toke in response: %v", tokenResp) } return token, nil
}
func getGithubUser(token string) (*GitHubUser, error) { url := "https://api.github.com/user"
req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close()
if resp.StatusCode != 200 { return nil, fmt.Errorf("GitHub API responded with %d", resp.StatusCode) }
body, _ := io.ReadAll(resp.Body) //fmt.Println("user data", body)
var user GitHubUser if err := json.Unmarshal(body, &user); err != nil { return nil, err } fmt.Println("github user", user)
return &user, nil
}