Esempio n. 1
0
func (repo *repository) DetectApiRootAndSetAccessToken(values url.Values) (apiRoot string, err error) {
	if repo.URL.Host == "github.com" {
		apiRoot = "https://api.github.com"
		return
	}

	if v, ok := repo.Config[repo.URL.Host]; ok {
		apiRoot = v.ApiRoot
		values.Add("access_token", v.AccessToken)
		return
	}

	sc := SiteConfig{repo.URL.Host, "", ""}

	msg := fmt.Sprintf("Please input github API root path for '%s' (such as 'https://api.github.com') :", repo.URL.Host)
	apiRoot, err = ask.Ask(msg, false)
	if err != nil {
		return
	}
	sc.ApiRoot = strings.TrimLeft(apiRoot, "/")

	sc.AccessToken, err = repo.NewAccessToken(sc.Host, sc.ApiRoot)
	if err != nil {
		err = util.LyciaError("failed to generate new access token: " + err.Error())
		return
	}

	repo.Config[repo.URL.Host] = sc
	err = repo.Config.Save()
	if err != nil {
		err = util.LyciaError("failed to save config: " + err.Error())
		return
	}

	values.Add("access_token", sc.AccessToken)
	return
}
Esempio n. 2
0
func (repo *repository) NewAccessToken(host string, apiRoot string) (accessToken string, err error) {
	username, err := ask.Ask(fmt.Sprintf("Please input username for '%s':", host), false)
	if err != nil {
		return
	}
	password, err := ask.Ask(fmt.Sprintf("Please input password for '%s':", host), true)
	if err != nil {
		return
	}

	reqBody := fmt.Sprintf(`{"scopes":["repo"],"note":"lycia %s"}`, time.Now())
	req, err := repo.NewPostRequest(username, password, apiRoot+"/authorizations", reqBody)
	if err != nil {
		return
	}

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return
	}

	if res.StatusCode == 401 {
		if v := res.Header.Get("X-Github-Otp"); strings.HasPrefix(v, "required;") {
			var otp string
			otp, err = ask.Ask("Please input two-factor authentication code:", false)
			if err != nil {
				return
			}

			req, err = repo.NewPostRequest(username, password, apiRoot+"/authorizations", reqBody)
			if err != nil {
				return
			}
			req.Header.Add("X-Github-Otp", otp)
			res, err = client.Do(req)
			if err != nil {
				return
			}

		} else {
			err = util.LyciaError("Bad credentials")
			return
		}

	} else if res.StatusCode != 200 && res.StatusCode != 201 {
		err = util.LyciaError(fmt.Sprintf("Unknown status: %s", res.Status))
		return
	}

	defer res.Body.Close()

	decoder := json.NewDecoder(res.Body)

	var authorizations Authorizations
	if err = decoder.Decode(&authorizations); err != nil {
		return
	}

	if authorizations.HashedToken != "" {
		accessToken = authorizations.HashedToken
	} else if authorizations.Token != "" {
		accessToken = authorizations.Token
	} else {
		err = util.LyciaError("cannot detect HashedToken")
	}
	return
}