Completed
Push — main ( 3a80b2...74ebe2 )
by Yume
15s queued 13s
created

oauth.GetGithubData   B

Complexity

Conditions 7

Size

Total Lines 37
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 22
nop 2
dl 0
loc 37
rs 7.952
c 0
b 0
f 0
1
package oauth
2
3
import (
4
	"bytes"
5
	"context"
6
	"fmt"
7
	"io"
8
	"net/http"
9
10
	"github.com/memnix/memnix-rest/config"
11
	"github.com/memnix/memnix-rest/infrastructures"
12
	"github.com/memnix/memnix-rest/views"
13
	"github.com/pkg/errors"
14
)
15
16
// Represents the response received from Github
17
type githubAccessTokenResponse struct {
18
	AccessToken string `json:"access_token"`
19
	TokenType   string `json:"token_type"`
20
	Scope       string `json:"scope"`
21
}
22
23
const (
24
	githubAccessTokenURL = "https://github.com/login/oauth/access_token"
25
	githubAPIURL         = "https://api.github.com/user"
26
)
27
28
// GetGithubAccessToken gets the access token from Github using the code
29
func GetGithubAccessToken(ctx context.Context, code string) (string, error) {
30
	_, span := infrastructures.GetFiberTracer().Start(ctx, "GetGithubAccessToken")
31
	defer span.End()
32
	// Set us the request body as JSON
33
	requestBodyMap := map[string]string{
34
		"client_id":     infrastructures.GetAppConfig().GithubConfig.ClientID,
35
		"client_secret": infrastructures.GetAppConfig().GithubConfig.ClientSecret,
36
		"code":          code,
37
	}
38
	requestJSON, _ := config.JSONHelper.Marshal(requestBodyMap)
39
40
	// POST request to set URL
41
	req, err := http.NewRequestWithContext(ctx,
42
		http.MethodPost,
43
		githubAccessTokenURL,
44
		bytes.NewBuffer(requestJSON),
45
	)
46
	if err != nil || req == nil || req.Body == nil || req.Header == nil {
47
		return "", errors.Wrap(err, views.RequestFailed)
48
	}
49
	req.Header.Set("Content-Type", "application/json")
50
	req.Header.Set("Accept", "application/json")
51
52
	// Get the response
53
	resp, err := http.DefaultClient.Do(req)
54
	if err != nil {
55
		return "", errors.Wrap(err, views.ResponseFailed)
56
	}
57
58
	defer func(resp *http.Response) {
59
		if resp != nil && resp.Body != nil {
60
			resp.Body.Close()
61
		}
62
	}(resp)
63
	// Response body converted to stringified JSON
64
	respbody, _ := io.ReadAll(resp.Body)
65
66
	// Convert stringified JSON to a struct object of type githubAccessTokenResponse
67
	var ghresp githubAccessTokenResponse
68
	err = config.JSONHelper.Unmarshal(respbody, &ghresp)
69
	if err != nil {
70
		return "", err
71
	}
72
73
	// Return the access token (as the rest of the
74
	// details are relatively unnecessary for us)
75
	return ghresp.AccessToken, nil
76
}
77
78
// GetGithubData gets the user data from Github using the access token
79
func GetGithubData(ctx context.Context, accessToken string) (string, error) {
80
	_, span := infrastructures.GetFiberTracer().Start(ctx, "GetGithubData")
81
	defer span.End()
82
	// Get request to a set URL
83
	req, err := http.NewRequestWithContext(ctx,
84
		http.MethodGet,
85
		"https://api.github.com/user",
86
		nil,
87
	)
88
	if err != nil {
89
		return "", err
90
	}
91
92
	// Set the Authorization header before sending the request
93
	// Authorization: token XXXXXXXXXXXXXXXXXXXXXXXXXXX
94
	authorizationHeaderValue := fmt.Sprintf("token %s", accessToken)
95
	req.Header.Set("Authorization", authorizationHeaderValue)
96
97
	// Make the request
98
	resp, err := http.DefaultClient.Do(req)
99
	if err != nil {
100
		return "", err
101
	}
102
103
	defer func(resp *http.Response) {
104
		if resp != nil && resp.Body != nil {
105
			resp.Body.Close()
106
		}
107
	}(resp)
108
	// Read the response as a byte slice
109
	respbody, err := io.ReadAll(resp.Body)
110
	if err != nil {
111
		return "", err
112
	}
113
114
	// Convert byte slice to string and return
115
	return string(respbody), nil
116
}
117