Add ability to authorize on Yandex with needed permissions

This commit is contained in:
Vladimir Hodakov 2019-03-30 04:31:31 +04:00
parent 134228f63f
commit 1a93f57ff8
Signed by: Vladimir Hodakov
GPG Key ID: 673980B6882F82C6
6 changed files with 112 additions and 24 deletions

View File

@ -14,10 +14,11 @@ import (
func authorize() { func authorize() {
if !checkAuth() { if !checkAuth() {
baseURL := "https://oauth.yandex.ru/authorize?response_type=code&client_id={{ client_id }}" baseURL := "https://oauth.yandex.ru/authorize?response_type=code&client_id={{ client_id }}"
baseURL += "&device_id={{ device_id }}&device_name=yapusher-cli&force_confirm=yes" baseURL += "&device_id={{ device_id }}&device_name={{ device_name }}&force_confirm=yes"
baseURL = strings.Replace(baseURL, "{{ client_id }}", YANDEX_APPID, 1) baseURL = strings.Replace(baseURL, "{{ client_id }}", YANDEX_APPID, 1)
baseURL = strings.Replace(baseURL, "{{ device_id }}", c.Config.DeviceID, 1) baseURL = strings.Replace(baseURL, "{{ device_id }}", c.Config.DeviceID, 1)
baseURL = strings.Replace(baseURL, "{{ device_name }}", DEVICE_NAME, 1)
dlog.Info().Msg("Please open in your browser this URL and authorize the app. After getting the code restart the app with -authCode param (see -h for details).") dlog.Info().Msg("Please open in your browser this URL and authorize the app. After getting the code restart the app with -authCode param (see -h for details).")
dlog.Info().Msgf("Auth URL: %s", baseURL) dlog.Info().Msgf("Auth URL: %s", baseURL)

View File

@ -10,6 +10,8 @@ import (
) )
const YANDEX_APPID = "7d8a0561fdc44c05bb6695b464403f9c" const YANDEX_APPID = "7d8a0561fdc44c05bb6695b464403f9c"
const YANDEX_APPPW = "56e12e4ed0d64738bf441a47f68c7146"
const DEVICE_NAME = "yapusher-cli"
var ( var (
c *context.Context c *context.Context
@ -33,6 +35,11 @@ func New(cc *context.Context) {
// Process handles authorization and files // Process handles authorization and files
func Process() { func Process() {
authCode, _ := c.Flagger.GetIntValue("authCode")
if authCode != 0 {
sendCode(authCode)
}
if !checkAuth() { if !checkAuth() {
authorize() authorize()
} }

View File

@ -0,0 +1,59 @@
// Yandex Disk File Pusher
// Copyright (c) 2019 Vladimir "fat0troll" Hodakov
package yandexv1
import (
"encoding/json"
"net/http"
"net/url"
"os"
"strconv"
"strings"
)
func sendCode(code int) {
baseURL := "https://oauth.yandex.ru/token"
client := http.Client{}
form := url.Values{}
form.Set("grant_type", "authorization_code")
form.Set("code", strconv.Itoa(code))
form.Set("device_id", c.Config.DeviceID)
form.Set("device_name", DEVICE_NAME)
form.Set("client_id", YANDEX_APPID)
form.Set("client_secret", YANDEX_APPPW)
req, _ := http.NewRequest("POST", baseURL, strings.NewReader(form.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(form.Encode())))
resp, err := client.Do(req)
if err != nil {
dlog.Fatal().Err(err).Msg("Failed to send request")
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
err = json.NewDecoder(resp.Body).Decode(&c.Config.Token)
if err != nil {
dlog.Error().Err(err).Msg("Failed to decode response")
}
c.SaveConfig()
dlog.Info().Msg("You've authorized successfully. Now you can use this app to upload files to your Yandex.Disk")
dlog.Info().Msg("See -h for details")
} else {
errorData := TokenError{}
err = json.NewDecoder(resp.Body).Decode(&errorData)
if err != nil {
dlog.Error().Err(err).Msg("Failed to decode response")
}
dlog.Error().Interface("response", errorData).Msg("Got error from Yandex, not authorized. Please retry authorization")
authorize()
}
os.Exit(0)
}

View File

@ -0,0 +1,9 @@
// Yandex Disk File Pusher
// Copyright (c) 2019 Vladimir "fat0troll" Hodakov
package yandexv1
type TokenError struct {
Error string `json:"error"`
ErrorDescription string `json:"error_description"`
}

View File

@ -38,6 +38,21 @@ func (c *Context) initFlagger() {
c.Flagger.Initialize() c.Flagger.Initialize()
} }
func (c *Context) readConfig() {
fh, err := os.Open(c.configFilePath)
if err != nil {
dlog.Fatal().Err(err).Msg("Failed to read config file")
}
defer fh.Close()
decoder := json.NewDecoder(fh)
err = decoder.Decode(&c.Config)
if err != nil {
dlog.Fatal().Err(err).Msg("Failed to decode config")
}
}
// Init is an initialization function for core context // Init is an initialization function for core context
// Without these parts of the application we can't start at all // Without these parts of the application we can't start at all
func (c *Context) Init() { func (c *Context) Init() {
@ -61,36 +76,31 @@ func (c *Context) InitConfig() {
dlog.Debug().Str("config directory", configPath).Msg("Got config directory") dlog.Debug().Str("config directory", configPath).Msg("Got config directory")
configFile := filepath.Join(configPath, "settings.json") configFile := filepath.Join(configPath, "settings.json")
c.configFilePath = configFile
if _, err = os.Stat(configFile); os.IsNotExist(err) { if _, err = os.Stat(configFile); os.IsNotExist(err) {
// Generating new config on first run // Generating new config on first run
dlog.Debug().Msg("Generating new config") dlog.Debug().Msg("Generating new config")
c.generateDefaultConfig() c.generateDefaultConfig()
fh, err := os.Create(configFile) c.SaveConfig()
} else {
dlog.Debug().Msg("Using existing config")
c.readConfig()
}
}
func (c *Context) SaveConfig() {
fh, err := os.Create(c.configFilePath)
if err != nil { if err != nil {
dlog.Fatal().Err(err).Msg("Failed to create config file") dlog.Fatal().Err(err).Msg("Failed to create config file")
} }
defer fh.Close() defer fh.Close()
encoder := json.NewEncoder(fh) encoder := json.NewEncoder(fh)
err = encoder.Encode(c.Config) err = encoder.Encode(&c.Config)
if err != nil { if err != nil {
dlog.Fatal().Err(err).Msg("Failed to encode config") dlog.Fatal().Err(err).Msg("Failed to encode config")
} }
} else {
dlog.Debug().Msg("Using existing config")
fh, err := os.Open(configFile)
if err != nil {
dlog.Fatal().Err(err).Msg("Failed to read config file")
}
defer fh.Close()
decoder := json.NewDecoder(fh)
decoder.Decode(c.Config)
if err != nil {
dlog.Fatal().Err(err).Msg("Failed to decode config")
}
}
} }

View File

@ -18,6 +18,8 @@ var (
// Context is the main application context. // Context is the main application context.
type Context struct { type Context struct {
configFilePath string
Config config.Config Config config.Config
Flagger *flagger.Flagger Flagger *flagger.Flagger
Logger zerolog.Logger Logger zerolog.Logger