• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

michaelcoll / quiz-app / 5832415755

11 Aug 2023 12:13PM UTC coverage: 22.074%. First build
5832415755

Pull #175

github

michaelcoll
feat(auth): switch to github auth

- switch from axios to fetch

Closes #90
Pull Request #175: feat(auth): switch to github auth

99 of 99 new or added lines in 6 files covered. (100.0%)

398 of 1803 relevant lines covered (22.07%)

1.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.38
/internal/back/infrastructure/githubCallerImpl.go
1
/*
2
 * Copyright (c) 2023 Michaƫl COLL.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package infrastructure
18

19
import (
20
        "context"
21
        "encoding/json"
22
        "fmt"
23
        "net/http"
24
        "strconv"
25

26
        "github.com/michaelcoll/quiz-app/internal/back/domain"
27
)
28

29
const accessTokenBaseUrl = "https://api.github.com"
30

31
type GithubAccessTokenCaller struct {
32
        domain.AccessTokenCaller
33

34
        accessTokenBaseUrl string
35
}
36

37
type successResponse struct {
38
        Sub     int    `json:"id"`
39
        Name    string `json:"name"`
40
        Login   string `json:"login"`
41
        Picture string `json:"avatar_url"`
42
}
43

44
type errorResponse struct {
45
        Message string `json:"message"`
46
}
47

48
func NewGithubAccessTokenCaller() *GithubAccessTokenCaller {
×
49
        return &GithubAccessTokenCaller{
×
50
                accessTokenBaseUrl: accessTokenBaseUrl,
×
51
        }
×
52
}
×
53

54
func (c *GithubAccessTokenCaller) Get(ctx context.Context, token string) (*domain.AccessToken, error) {
1✔
55
        url := fmt.Sprintf("%s/user", c.accessTokenBaseUrl)
1✔
56

1✔
57
        req, err := http.NewRequest("GET", url, nil)
1✔
58
        if err != nil {
1✔
59
                return nil, err
×
60
        }
×
61

62
        req = req.WithContext(ctx)
1✔
63

1✔
64
        res := successResponse{}
1✔
65
        if err := c.sendRequest(req, token, &res); err != nil {
1✔
66
                return nil, err
×
67
        }
×
68

69
        return c.toAccessToken(&res, token)
1✔
70
}
71

72
func (c *GithubAccessTokenCaller) sendRequest(req *http.Request, token string, v interface{}) error {
1✔
73
        req.Header.Set("Content-Type", "application/json; charset=utf-8")
1✔
74
        req.Header.Set("Accept", "application/json; charset=utf-8")
1✔
75
        authHeader := fmt.Sprintf("Bearer %s", token)
1✔
76
        req.Header.Set("Authorization", authHeader)
1✔
77

1✔
78
        res, err := http.DefaultClient.Do(req)
1✔
79
        if err != nil {
1✔
80
                return err
×
81
        }
×
82

83
        defer res.Body.Close()
1✔
84

1✔
85
        if res.StatusCode < http.StatusOK || res.StatusCode >= http.StatusBadRequest {
1✔
86
                var errRes errorResponse
×
87
                if err = json.NewDecoder(res.Body).Decode(&errRes); err == nil {
×
88
                        return domain.Errorf(domain.UnAuthorized, errRes.Message)
×
89
                }
×
90

91
                return domain.Errorf(domain.UnexpectedError, "unknown error, status code: %d", res.StatusCode)
×
92
        }
93

94
        if err = json.NewDecoder(res.Body).Decode(v); err != nil {
1✔
95
                return domain.Errorf(domain.UnexpectedError, "can't decode access token response (%v)", err)
×
96
        }
×
97

98
        return nil
1✔
99
}
100

101
func (c *GithubAccessTokenCaller) toAccessToken(res *successResponse, token string) (*domain.AccessToken, error) {
1✔
102

1✔
103
        return &domain.AccessToken{
1✔
104
                Sub:         strconv.Itoa(res.Sub),
1✔
105
                Login:       res.Login,
1✔
106
                Name:        res.Name,
1✔
107
                Picture:     res.Picture,
1✔
108
                Provenance:  domain.Api,
1✔
109
                OpaqueToken: token,
1✔
110
        }, nil
1✔
111
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc