Skip to content

Commit

Permalink
Fix gspread error handling (#1512)
Browse files Browse the repository at this point in the history
* secret description fixed

* readme file fixed

* secrets description changed

* removed unused imports

* fixed: wrong url error handling

---------

Co-authored-by: Vsevolod <[email protected]>
  • Loading branch information
sevabakutov and Vsevolod authored Dec 11, 2024
1 parent 39907f7 commit 40f5e25
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 62 deletions.
44 changes: 0 additions & 44 deletions module/move/gspread/.key/readme.md

This file was deleted.

42 changes: 42 additions & 0 deletions module/move/gspread/.secret/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Getting API Keys for OAuth Authentication

Follow these steps to create and configure your OAuth credentials for using Google APIs.

## 1. Create API Credentials

1. Go to the [Google API Console](https://console.developers.google.com/).
2. From the projects list, select an existing project or create a new one.
3. In the left side menu, select **APIs & Services**.
4. On the left menu, click **Credentials**.
5. Click **Create Credentials** and select **OAuth client ID**.
6. In the **Application type** section, select **Desktop app**.
7. Provide an appropriate name for your client ID (e.g., "Gspread OAuth Client").
8. Click **Create**.

Once the credential is created, you will receive a **Client ID** and **Client Secret**. These are required for accessing the API.

## 2. Store Your Credentials

Save the **Client ID** and **Client Secret** in a `.env` within a `.secret` directory. The file should look like this:

```bash
CLIENT_ID=YOUR_CLIENT_ID
CLIENT_SECRET=YOUR_SECRET_KEY
```

## 3. Why do we need it?

After executing each command, you need to grant the GSPREAD program access to the Google API. You will receive a link that begin with 'Please direct your browser to https://....' that will redirect you to your browser, where you must authorize the access. You will need to select the appropriate Google account that has the credentials for the application. The **CLIENT_ID** and **CLIENT_SECRET** are set up to do this process.

## 4. Troubleshooting

If you encounter a page displaying an error instead of the Google account selection screen, it is likely that you need to add **AUTH_URI** or **TOKEN_URI** to the .env file. In this case, all four secrets are required. To retrieve them, download the API key you created in JSON format. Open the file and copy the necessary keys into the .env file. After making these changes, your .env file should look like this:

```bash
CLIENT_ID=YOUR_CLIENT_ID
CLIENT_SECRET=YOUR_SECRET_KEY
AUTH_URI=YOUR_AUTH_URI
TOKEN_URI=YOUR_TOKEN_URI
```

If you still get some issues, follow [Google OAuth Documentation](https://developers.google.com/identity/protocols/oauth2/).
17 changes: 13 additions & 4 deletions module/move/gspread/src/actions/gspread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,34 @@ mod private
#[ from ]
#[ serde_as( as = "DisplayFromStr" ) ]
google_sheets4::Error
)
),

#[ error( "Invalid URL format: {0}" ) ]
InvalidUrl
(
String
),
}

pub fn get_spreadsheet_id_from_url
(
url : &str
) -> Option< &str >
) -> Result< &str >
{

let re = Regex::new( r"d/([^/]+)/edit" ).unwrap();
if let Some( captures ) = re.captures( url )
{
if let Some( id ) = captures.get( 1 )
{
return Some( id.as_str() );
return Ok( id.as_str() );
}
}

None
Err
(
Error::InvalidUrl( "Wrong url format.\nFix: copy sheet's the whole url from your browser. Usage: --url '<your copied url>'".to_string() )
)
}

pub type Result< T > = core::result::Result< T, Error >;
Expand Down
3 changes: 1 addition & 2 deletions module/move/gspread/src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::error::Error;
use std::env;
use clap::Parser;
use dotenv::dotenv;

Expand All @@ -15,7 +14,7 @@ async fn main() -> Result< (), Box< dyn Error > >
{
dotenv().ok();

let secret = Secret::load()?;
let secret = Secret::read();

let hub = hub( &secret ).await?;

Expand Down
20 changes: 18 additions & 2 deletions module/move/gspread/src/commands/gspread_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ mod private
{
Commands::Get { url, tab, cel } =>
{
let spreadsheet_id = get_spreadsheet_id_from_url( url.as_str() ).unwrap();
let spreadsheet_id = match get_spreadsheet_id_from_url( url.as_str() )
{
Ok( id ) => id,
Err( error ) =>
{
eprintln!( "Error extracting spreadsheet ID: {}", error );
return;
}
};

let result = actions::gspread_cell_get::action
(
Expand All @@ -74,7 +82,15 @@ mod private

Commands::Set { url, tab, cel, val } =>
{
let spreadsheet_id = get_spreadsheet_id_from_url( url.as_str() ).unwrap();
let spreadsheet_id = match get_spreadsheet_id_from_url( url.as_str() )
{
Ok( id ) => id,
Err( error ) =>
{
eprintln!( "Error extracting spreadsheet ID: {}", error );
return;
}
};

let result = actions::gspread_cell_set::action
(
Expand Down
10 changes: 9 additions & 1 deletion module/move/gspread/src/commands/gspread_cells.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,15 @@ mod private
{
Commands::Set { select_row_by_key, json, url, tab } =>
{
let spreadsheet_id = get_spreadsheet_id_from_url( url.as_str() ).unwrap();
let spreadsheet_id = match get_spreadsheet_id_from_url( url.as_str() )
{
Ok( id ) => id,
Err( error ) =>
{
eprintln!( "Error extracting spreadsheet ID: {}", error );
return;
}
};

let result = actions::gspread_cells_set::action
(
Expand Down
11 changes: 10 additions & 1 deletion module/move/gspread/src/commands/gspread_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ mod private
{
CommonArgs { url, tab } =>
{
let spreadsheet_id = get_spreadsheet_id_from_url( url.as_str() ).unwrap();
let spreadsheet_id = match get_spreadsheet_id_from_url( url.as_str() )
{
Ok( id ) => id,
Err( error ) =>
{
eprintln!( "Error extracting spreadsheet ID: {}", error );
return;
}
};

let result = actions::gspread_get_header::action
(
hub,
Expand Down
10 changes: 9 additions & 1 deletion module/move/gspread/src/commands/gspread_rows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,15 @@ mod private
{
CommonArgs { url, tab } =>
{
let spreadsheet_id = get_spreadsheet_id_from_url( url.as_str() ).unwrap();
let spreadsheet_id = match get_spreadsheet_id_from_url( url.as_str() )
{
Ok( id ) => id,
Err( error ) =>
{
eprintln!( "Error extracting spreadsheet ID: {}", error );
return;
}
};

let result = actions::gspread_get_rows::action
(
Expand Down
14 changes: 7 additions & 7 deletions module/move/gspread/src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod private
#[ allow( non_snake_case ) ]
pub fn load() -> Result< Self >
{
let path = "./.key/-env.sh";
let path = "./.secret/.env";

let r = dotenv::from_path( path );
if let Err( ref err ) = r
Expand All @@ -67,8 +67,8 @@ mod private
{
CLIENT_SECRET : var( "CLIENT_SECRET", None )?,
CLIENT_ID : var( "CLIENT_ID", None )?,
AUTH_URI : var ( "AUTH_URI", None )?,
TOKEN_URI : var ( "TOKEN_URI", None )?
AUTH_URI : var ( "AUTH_URI", Some( "https://accounts.google.com/o/oauth2/auth" ) )?,
TOKEN_URI : var ( "TOKEN_URI", Some( "https://oauth2.googleapis.com/token" ) )?
};
Ok( config )
}
Expand All @@ -77,7 +77,7 @@ mod private
{
Self::load().unwrap_or_else( | err |
{
let example = include_str!("../.key/readme.md");
let example = include_str!("../.secret/readme.md");
let explanation = format!
(
r#" = Lack of secrets
Expand All @@ -87,7 +87,7 @@ Failed to load secret or some its parameters.
= Fix
Either define missing environment variable or make sure `./.key/-env.toml` file has it defined.
Add missing secret to .env file in .secret directory. Example: MISSING_SECRET=YOUR_MISSING_SECRET
= More information
Expand All @@ -109,10 +109,10 @@ Either define missing environment variable or make sure `./.key/-env.toml` file
fn var
(
name : &'static str,
default : Option<&'static str>,
default : Option< &'static str >,
) -> Result < String >
{
match env::var(name)
match env::var( name )
{
Ok( val ) => Ok ( val ),
Err( _ ) =>
Expand Down

0 comments on commit 40f5e25

Please sign in to comment.