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

suculent / thinx-device-api / #252646768

01 Nov 2025 03:31PM UTC coverage: 46.298% (-25.7%) from 71.971%
#252646768

push

suculent
testing upgraded mqtt package

1123 of 3470 branches covered (32.36%)

Branch coverage included in aggregate %.

5324 of 10455 relevant lines covered (50.92%)

4.07 hits per line

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

27.94
/lib/thinx/oauth-github.js
1
var axios = require('axios');
1✔
2

3
var events = require('events');
1✔
4
var url = require('url');
1✔
5
var crypto = require('crypto');
1✔
6

7
module.exports = function (opts) {
1✔
8
  if (!opts.callbackURI) opts.callbackURI = '/github/callback';
2!
9
  if (!opts.loginURI) opts.loginURI = '/github/login';
2!
10
  if (typeof opts.scope === 'undefined') opts.scope = 'user';
2!
11
  var state = crypto.randomBytes(8).toString('hex');
2✔
12
  var urlObj = url.parse(opts.baseURL);
2✔
13
  urlObj.pathname = url.resolve(urlObj.pathname, opts.callbackURI);
2✔
14
  var redirectURI = url.format(urlObj);
2✔
15
  var emitter = new events.EventEmitter();
2✔
16

17
  function login(req, resp) {
18
    var u = 'https://github.com/login/oauth/authorize'
×
19
      + '?client_id=' + opts.githubClient
20
      + (opts.scope ? '&scope=' + opts.scope : '')
×
21
      + '&redirect_uri=' + redirectURI
22
      + '&state=' + state
23
      ;
24
    resp.statusCode = 302;
×
25
    resp.setHeader('location', u);
×
26
    resp.end();
×
27
  }
28

29
  function parseResponse(body) {
30
    const items = body.split("&");
×
31
    var data = null;
×
32
    for (item in items) {
×
33
      const kv = items[0].split("=");
×
34
      const key = kv[0];
×
35
      const val = kv[1];
×
36
      if (key.indexOf("access_token" !== -1)) {
×
37
        data = val;
×
38
        break;
×
39
      }
40
    }
41
    return data;
×
42
  }
43

44
  function callback(req, resp, cb) {
45
    var query = url.parse(req.url, true).query
×
46
    var code = query.code
×
47
    if (!code || code.length < 4) {
×
48
      const rbody = resp.body;
×
49
      console.log("[debug] [oauth-github] missing or invalid oauth code in ", {query}, {rbody});
×
50
      return emitter.emit('error', { error: 'missing or invalid oauth code' }, resp)
×
51
    }
52
    var u = 'https://github.com/login/oauth/access_token'
×
53
      + '?client_id=' + opts.githubClient
54
      + '&client_secret=' + opts.githubSecret
55
      + '&code=' + code
56
      + '&state=' + state
57
      ;
58

59
    (async () => {
×
60
      try {
×
61
        const body = await axios.get(u);
×
62
        //console.log("[debug] emitting event token with body", { body });
63
        const data = parseResponse(body.data);
×
64
        if (data.indexOf("gho_") !== -1) {
×
65
          emitter.emit('token', data);
×
66
          if (cb) return cb(null, data);
×
67
        } else {
68
          console.log("[debug] Invalid GitHub Response:", {body});
×
69
        }
70
      } catch (e) {
71
        console.log("axios get error:", e);
×
72
        if (cb) return cb(e);
×
73
        emitter.emit('error', null, e);
×
74
      }
75
    })()
76
  }
77

78
  emitter.login = login;
2✔
79
  emitter.callback = callback;
2✔
80
  return emitter;
2✔
81
}
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

© 2026 Coveralls, Inc