betodealmeida opened a new pull request, #27631:
URL: https://github.com/apache/superset/pull/27631

   <!---
   Please write the PR title following the conventions at 
https://www.conventionalcommits.org/en/v1.0.0/
   Example:
   fix(dashboard): load charts correctly
   -->
   
   ### SUMMARY
   <!--- Describe the change below, including rationale and design decisions -->
   
   This PR introduces a new table called `database_user_oauth2_tokens`. The 
table is used for storing personal user tokens associated with a given database:
   
   ```sql
   # \d database_user_oauth2_tokens
                                                  Table 
"public.database_user_oauth2_tokens"
            Column          |            Type             | Collation | 
Nullable |                         Default
   
-------------------------+-----------------------------+-----------+----------+---------------------------------------------------------
    created_on              | timestamp without time zone |           |         
 |
    changed_on              | timestamp without time zone |           |         
 |
    id                      | integer                     |           | not 
null | nextval('database_user_oauth2_tokens_id_seq'::regclass)
    user_id                 | integer                     |           | not 
null |
    database_id             | integer                     |           | not 
null |
    access_token            | bytea                       |           |         
 |
    access_token_expiration | timestamp without time zone |           |         
 |
    refresh_token           | bytea                       |           |         
 |
    created_by_fk           | integer                     |           |         
 |
    changed_by_fk           | integer                     |           |         
 |
   Indexes:
       "database_user_oauth2_tokens_pkey" PRIMARY KEY, btree (id)
   Foreign-key constraints:
       "database_user_oauth2_tokens_changed_by_fk_fkey" FOREIGN KEY 
(changed_by_fk) REFERENCES ab_user(id)
       "database_user_oauth2_tokens_created_by_fk_fkey" FOREIGN KEY 
(created_by_fk) REFERENCES ab_user(id)
       "database_user_oauth2_tokens_database_id_fkey" FOREIGN KEY (database_id) 
REFERENCES dbs(id)
       "database_user_oauth2_tokens_user_id_fkey" FOREIGN KEY (user_id) 
REFERENCES ab_user(id)
   ```
   
   Whenever a SQLAlchemy engine is instantiated, the personal user token will 
be passed to the `get_url_for_impersonation` method in the DB engine spec, if 
available, so that a custom URL can be built for the user. For example, for 
GSheets:
   
   ```python
   def get_url_for_impersonation(
       cls,
       url: URL,
       impersonate_user: bool,
       username: str | None,
       access_token: str | None,  # <== here
   ) -> URL:
       if not impersonate_user:
           return url
   
       if username is not None:
           user = security_manager.find_user(username=username)
           if user and user.email:
               url = url.update_query_dict({"subject": user.email})
   
       if access_token:
           url = url.update_query_dict({"access_token": access_token})
   
       return url
   ```
   
   The change allows users to login to databases like BigQuery, Snowflake, 
Dremio, Databricks, Google Sheets, etc. using their own credentials. This makes 
it easier to set up databases, since service accounts are no longer required, 
and provides better isolation of data between users.
   
   In order to populate the table with personal access tokens, the DB engine 
spec checks for a specific exception that signals that OAuth2 should start:
   
   ```python
   class BaseEngineSpec:
       def execute(...) -> None:
           try:
               cursor.execute(query)
           except cls.oauth2_exception as ex:  # <== here
               if cls.is_oauth2_enabled() and g.user:
                   cls.start_oauth2_dance(database_id)
               raise cls.get_dbapi_mapped_exception(ex) from ex
           except Exception as ex:
               raise cls.get_dbapi_mapped_exception(ex) from ex
   ```
   
   When called, the `start_oauth2_dance` method will return the error 
`OAUTH2_REDIRECT` to the frontend. The errors is captured by the 
`ErrorMessageWithStackTrace` component, which provides a link to the user so 
they can start the OAuth2 authentication.
   
   Since this is implemented at the DB engine spec level, any query will 
trigger it — in SQL Lab, Explore, or dashboards. See the screenshots below for 
the UX.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   <!--- Skip this if not applicable -->
   
   ### TESTING INSTRUCTIONS
   <!--- Required! What steps can be taken to manually verify the changes? -->
   
   1. Create a Google Sheets database.
   2. Create a Google OAuth2 application at 
https://console.cloud.google.com/apis/credentials/oauthclient/ of type "Web 
application"
   3. Edit `superset_config.py` and add the client ID and secret:
   
   ```python
   DATABASE_OAUTH2_CREDENTIALS = {
       "Google Sheets": {
          "CLIENT_ID": "XXX.apps.googleusercontent.com",
          "CLIENT_SECRET": "GOCSPX-YYY",
       },
   }
   ```
   
   4. In SQL Lab, try to query a sheet that is not shared publicly. It should 
trigger OAuth2.
   5. Add the sheet as a dataset and create a chart.
   6. Delete the tokens from the database:
   
   ```sql
   DELETE FROM database_user_oauth2_tokens;
   ```
   
   7. Reload the chart. It should trigger OAuth2.
   8. Add the chart to a dashboard, delete the tokens, and reload the 
dashboard. It should trigger OAuth2.
   
   ### ADDITIONAL INFORMATION
   <!--- Check any relevant boxes with "x" -->
   <!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
   - [x] Has associated issue: https://github.com/apache/superset/issues/20300
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [x] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [x] Migration is atomic, supports rollback & is backwards-compatible
     - [x] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [x] Introduces new feature or API
   - [ ] Removes existing feature or API
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@superset.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@superset.apache.org
For additional commands, e-mail: notifications-h...@superset.apache.org

Reply via email to