Skip to content

Conversation

@ahmedxgouda
Copy link
Collaborator

Proposed change

  • Added google callback view to handle google auth redirects.
  • Add a button to give the user the ability to sign in with google.

Resolves #2044

Add the PR description here.

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 19, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Summary by CodeRabbit

  • New Features
    • Google Sign-In for Slack users: new “Sign In to Google” button in the app home and a /google-sign-in command that guides you through OAuth and confirms when you’re signed in. OAuth callback endpoint added with a success page.
  • Documentation
    • Environment template updated with configuration keys for Google OAuth and AWS KMS.
  • Chores
    • Added Google authentication client libraries to backend dependencies.

Walkthrough

Adds Google OAuth integration for Slack: new GoogleAccountAuthorization model with KMS-encrypted token fields, OAuth flow and callback view, Slack command/action and UI blocks, KMS client and encrypted model field, settings/env vars and dependencies, migrations, tests, and manifest/template updates.

Changes

Cohort / File(s) Summary
Environment & Settings
backend/.env.example, backend/settings/base.py, backend/settings/urls.py
Adds AWS KMS and Google OAuth env vars and settings, feature flags, and registers Google OAuth callback URL.
Google OAuth model & migrations
backend/apps/nest/models/google_account_authorization.py, backend/apps/nest/models/__init__.py, backend/apps/nest/migrations/0004_googleaccountauthorization.py, backend/apps/nest/migrations/0005_rename_scopes_googleaccountauthorization_scope_and_more.py
Adds GoogleAccountAuthorization model (member, access/refresh tokens, expires_at, scope) and applies migrations including table/field renames and metadata.
KMS client & encrypted field
backend/apps/nest/clients/kms.py, backend/apps/common/model_fields.py
Adds KmsClient wrapper with singleton accessor and KmsEncryptedField for encrypting/decrypting model data via AWS KMS.
Slack UI, command & handlers
backend/apps/slack/commands/google_sign_in.py, backend/apps/slack/commands/__init__.py, backend/apps/slack/common/handlers/google_sign_in.py, backend/apps/slack/actions/home.py, backend/apps/slack/blocks.py, backend/apps/slack/constants.py, backend/apps/slack/templates/events/app_home_opened.jinja, backend/apps/slack/MANIFEST.yaml
Adds /google-sign-in command, Google sign-in handler, app-home "Sign In to Google" button and action wiring, constant, manifest slash command, and app-home help entry.
Views & client factory
backend/apps/nest/views.py, backend/apps/nest/auth/clients/google.py
Adds google_auth_callback view and get_google_auth_client() factory that constructs a google_auth_oauthlib Flow from settings.
Dependencies
backend/pyproject.toml
Adds google-api-python-client, google-auth-httplib2, google-auth-oauthlib.
Tests
backend/tests/apps/nest/clients/kms_test.py, backend/tests/apps/common/model_fileds_test.py, backend/tests/apps/nest/models/google_account_authorization_test.py, backend/tests/apps/nest/auth/clients/google_test.py, backend/tests/apps/slack/common/handlers/google_sign_in_test.py
Adds unit tests covering KMS client/field, Google auth client/flow, model behavior and token refresh, and Slack handler.
Misc
cspell/custom-dict.txt
Adds dictionary entry “PLW”.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
Implement Google OAuth callback view (#2044)
Implement Slack sign-in command and UI (#2044)
Integrate Slack bot with Google OAuth flow, including state and token handling (#2044)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Add cspell dictionary entry “PLW” (cspell/custom-dict.txt) Spelling dictionary update unrelated to OAuth or Slack integration objectives.
Introduce KmsEncryptedField (backend/apps/common/model_fields.py) Adds a new encrypted model field extending infrastructure beyond the explicit callback/command requirement.
Add KMS client & singleton (backend/apps/nest/clients/kms.py) KMS client infrastructure supports encrypted storage but is additional infrastructure not explicitly requested by the issue.

Possibly related PRs

Suggested labels

backend

Suggested reviewers

  • arkid15r
  • kasya
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🧹 Nitpick comments (22)
backend/tests/apps/common/clients_test.py (3)

14-22: Stabilize boto3.client patching and target the correct import path

Using with patch("boto3.client") inside the fixture only patches during fixture execution. Calls outside (e.g., get_kms_client() creating a new KmsClient) will hit the real boto3. Prefer patching the import path used by the module and keeping it active for the test.

Apply this refactor to keep the patch active and targeted:

-@pytest.fixture(autouse=True)
-def setup(self):
-    """Set up mock KMS client."""
-    with patch("boto3.client") as mock_boto3_client:
-        self.mock_boto3_client = mock_boto3_client
-        self.mock_kms_client = Mock()
-        self.mock_boto3_client.return_value = self.mock_kms_client
-        self.kms_client = KmsClient()
+@pytest.fixture(autouse=True)
+def setup(self, monkeypatch):
+    """Set up mock KMS client."""
+    self.mock_kms_client = Mock()
+    # Patch the exact import path used by the code under test.
+    monkeypatch.setattr("apps.common.clients.boto3.client", lambda *_, **__: self.mock_kms_client)
+    self.kms_client = KmsClient()

42-49: Avoid cross-test leakage from the KMS singleton

get_kms_client() uses a module-level singleton (_kms_client). Once set, it persists across tests. Reset it to avoid hidden coupling.

Add this module-level autouse fixture to reset the singleton before each test:

# Place near the top of this file, after imports.
@pytest.fixture(autouse=True)
def reset_kms_singleton(monkeypatch):
    import apps.common.clients as clients_mod
    monkeypatch.setattr(clients_mod, "_kms_client", None, raising=False)
    yield

51-74: Make the Google client test independent of default settings

The test asserts default auth_uri and token_uri values without overriding them, creating hidden coupling to base settings. Set them explicitly in override_settings to keep the test robust.

Apply this diff:

 @override_settings(
     IS_GOOGLE_AUTH_ENABLED=True,
     GOOGLE_AUTH_CLIENT_ID="test_client_id",
     GOOGLE_AUTH_CLIENT_SECRET="test_client_secret",  # noqa: S106
     GOOGLE_AUTH_REDIRECT_URI="test_redirect_uri",
+    GOOGLE_AUTH_AUTH_URI="https://accounts.google.com/o/oauth2/auth",
+    GOOGLE_AUTH_TOKEN_URI="https://oauth2.googleapis.com/token",
 )
backend/settings/urls.py (1)

19-19: Import google_auth_callback lazily and name the route

For consistency with slack_request_handler and to avoid importing Slack/Google code when Slack isn’t enabled, import google_auth_callback inside the Slack block. Also consider naming the URL for easier reversing.

Apply this diff:

-from apps.slack.views import google_auth_callback
@@
 if SlackConfig.app:
-    from apps.slack.views import slack_request_handler
+    from apps.slack.views import google_auth_callback, slack_request_handler
@@
-        path("integrations/slack/oauth2/callback/", google_auth_callback),
+        path(
+            "integrations/slack/oauth2/callback/",
+            google_auth_callback,
+            name="slack_google_oauth2_callback",
+        ),

Also applies to: 41-41

backend/apps/slack/blocks.py (1)

88-97: Sign-in button added — consider centralizing action_id constant usage

The block is valid. For consistency and to avoid drift, consider referencing the shared SIGN_IN_WITH_GOOGLE_ACTION constant (and, longer-term, migrate other action_ids here to constants too).

Example change (requires adding an import at the top of this file):

+from apps.slack.constants import SIGN_IN_WITH_GOOGLE_ACTION
@@
-                    "action_id": "sign_in_with_google_action",
+                    "action_id": SIGN_IN_WITH_GOOGLE_ACTION,
backend/apps/slack/migrations/0021_alter_googleauth_access_token_and_more.py (3)

12-16: Re-add blank=True to token field to preserve form/admin behavior

This alter drops blank=True (present in 0019/0020), making the field “required” in forms/admin despite null=True. Tokens are programmatically set; forms shouldn’t require them.

Apply this diff within this migration (or amend before merge to avoid another migration):

-            field=models.BinaryField(null=True, verbose_name="Access Token"),
+            field=models.BinaryField(null=True, blank=True, verbose_name="Access Token"),

17-21: expires_at should also keep blank=True

You’re removing blank=True that existed in 0019. Without it, admin/forms will treat it as required even though DB allows NULL.

-            field=models.DateTimeField(null=True, verbose_name="Token Expiry"),
+            field=models.DateTimeField(null=True, blank=True, verbose_name="Token Expiry"),

22-26: Re-add blank=True for refresh_token for consistency

Same reasoning as access_token: keep forms/admin non-required; ensure consistency across migrations.

-            field=models.BinaryField(null=True, verbose_name="Refresh Token"),
+            field=models.BinaryField(null=True, blank=True, verbose_name="Refresh Token"),
backend/tests/apps/common/model_fileds_test.py (3)

1-1: Typo in filename: model_fileds_test.pymodel_fields_test.py

Minor but worthwhile for discoverability and consistency.

Would you like me to generate a Git move patch for this rename?


56-61: Add a “happy path” encrypt/decrypt test with KMS enabled (monkeypatched)

Current tests cover disabled KMS and invalid types, but not successful round-trip. Add a test that:

  • monkeypatches apps.common.clients.get_kms_client() to a fake that returns deterministic ciphertext (e.g., prefix) and decrypts accordingly,
  • asserts get_prep_value("plain") produces bytes,
  • asserts from_db_value(ciphertext, ...) returns the original string.

This guards against regressions in the encryption plumbing.

I can draft this test using pytest’s monkeypatch fixture; say the word and I’ll include the code.


17-28: Intentional hard-fail behavior when KMS is disabled—double-check it’s desired globally

When IS_AWS_KMS_ENABLED=False, get_prep_value, to_python, and from_db_value raise. This is secure-by-default, but it can be a footgun for local dev/admin reads.

If you want a softer local experience, consider:

  • Allow read-as-None when disabled, while still forbidding writes; or
  • Gating model/feature usage behind IS_GOOGLE_AUTH_ENABLED so the field isn’t read at all.

If the hard-fail is intentional (as tests encode), ignore this.

backend/apps/slack/migrations/0019_googleauth.py (1)

22-27: Avoid any window where plaintext tokens could be persisted

Since 0019 stores tokens as TextField, ensure environments won’t persist plaintext before 0023 lands, or add a feature gate preventing writes until encryption is in place. If any data may already exist, plan a data migration to encrypt/backfill.

I can provide a targeted backfill migration tailored to your deployment plan if needed.

backend/.env.example (2)

15-19: Use Google's v2 OAuth endpoint for new apps

The v1 auth URI is deprecated in most docs. Prefer the v2 endpoint to avoid surprises.

-DJANGO_GOOGLE_AUTH_AUTH_URI=https://accounts.google.com/o/oauth2/auth
+DJANGO_GOOGLE_AUTH_AUTH_URI=https://accounts.google.com/o/oauth2/v2/auth

6-7: Clarify KMS env usage and defaults

Minor: consider commenting that these are only required when KMS is enabled so devs aren’t blocked locally.

Example comment to append next to these lines:

  • "Only required if IS_AWS_KMS_ENABLED=True"

Also applies to: 20-20

backend/apps/common/clients.py (3)

8-21: Harden get_google_auth_client: add guard and configurable scopes

  • Add a defensive guard to prevent constructing a Flow when Google auth is disabled.
  • Allow scopes to be configured via settings, falling back to the default.
-def get_google_auth_client():
-    """Get a Google OAuth client."""
-    return Flow.from_client_config(
+def get_google_auth_client() -> Flow:
+    """Get a Google OAuth client."""
+    if not getattr(settings, "IS_GOOGLE_AUTH_ENABLED", False):
+        raise ValueError("Google OAuth client ID is not configured or Google auth is disabled.")
+    return Flow.from_client_config(
         client_config={
             "web": {
                 "client_id": settings.GOOGLE_AUTH_CLIENT_ID,
                 "client_secret": settings.GOOGLE_AUTH_CLIENT_SECRET,
                 "redirect_uris": [settings.GOOGLE_AUTH_REDIRECT_URI],
                 "auth_uri": settings.GOOGLE_AUTH_AUTH_URI,
                 "token_uri": settings.GOOGLE_AUTH_TOKEN_URI,
             }
         },
-        scopes=["https://www.googleapis.com/auth/calendar.readonly"],
+        scopes=getattr(
+            settings,
+            "GOOGLE_AUTH_SCOPES",
+            ["https://www.googleapis.com/auth/calendar.readonly"],
+        ),
     )

If you want me to add GOOGLE_AUTH_SCOPES to settings with a sane default, I can draft that as well.


27-35: Fail fast when AWS region is missing for KMS

If KMS is enabled but region is unset, boto3 will raise later with a less clear error. Validate upfront for a better DX.

     def __init__(self):
         """Initialize the KMS client."""
-        self.client = boto3.client(
+        if settings.AWS_REGION in (None, "None", ""):
+            raise ValueError("AWS_REGION is not configured but required when using KMS.")
+        self.client = boto3.client(
             "kms",
             aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
             aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
             region_name=settings.AWS_REGION,
         )

47-55: Thread-safety of the singleton KMS client

Module-level lazy init is not thread-safe. Rare in Django, but easy to make robust with a lock if desired.

Happy to draft a lock-based initialization if you prefer.

backend/apps/common/model_fields.py (1)

8-11: Error message mentions only bytes/bytearray but you also accept memoryview

Keep the message accurate to reduce confusion when debugging.

-BYTES_ERROR_MESSAGE = "Value must be bytes or bytearray to decrypt."
+BYTES_ERROR_MESSAGE = "Value must be bytes, bytearray, or memoryview to decrypt."
backend/tests/apps/slack/models/google_auth_test.py (1)

202-245: Refresh flow coverage looks good; minor nit: token types in test

The mock assigns byte strings to token/refresh_token. Google credentials typically yield strings. Not harmful here, but consider using str for parity.

backend/apps/slack/models/google_auth.py (3)

14-18: Clarify misconfiguration error messaging.

AUTH_ERROR_MESSAGE implies config validation but code only checks the enable flag. Either update the message to reflect that or add explicit config checks (see get_flow refactor below).

Apply this diff to make the message accurate:

-AUTH_ERROR_MESSAGE = (
-    "Google OAuth client ID, secret, and redirect URI must be set in environment variables."
-)
+AUTH_ERROR_MESSAGE = (
+    "Google OAuth is disabled or misconfigured. Ensure client ID, client secret, auth/token URIs, and redirect URI are set."
+)

40-48: Avoid mixed return types from authenticate for API clarity.

Returning either a model instance or a tuple complicates call sites. Consider returning a small result object (e.g., a dataclass with auth, authorization_url, state) for clarity.

If desired, I can provide a minimal AuthResult dataclass and update usage sites.


33-38: Unit tests: cover refresh-token preservation and error paths.

  • Add a test ensuring refresh_access_token does not overwrite an existing refresh_token when Google returns None.
  • Add tests for refresh failure raising ValidationError.
  • Add tests for authenticate fallback when refresh fails.

I can draft these tests aligned with your existing test style (backend/tests/apps/slack/models/google_auth_test.py).

Also applies to: 111-136

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ff71251 and 1ac36d1.

⛔ Files ignored due to path filters (1)
  • backend/poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • backend/.env.example (1 hunks)
  • backend/apps/common/clients.py (1 hunks)
  • backend/apps/common/model_fields.py (1 hunks)
  • backend/apps/slack/actions/home.py (4 hunks)
  • backend/apps/slack/blocks.py (1 hunks)
  • backend/apps/slack/constants.py (1 hunks)
  • backend/apps/slack/migrations/0019_googleauth.py (1 hunks)
  • backend/apps/slack/migrations/0020_alter_googleauth_access_token_and_more.py (1 hunks)
  • backend/apps/slack/migrations/0021_alter_googleauth_access_token_and_more.py (1 hunks)
  • backend/apps/slack/migrations/0022_alter_googleauth_options_alter_googleauth_table.py (1 hunks)
  • backend/apps/slack/migrations/0023_alter_googleauth_access_token_and_more.py (1 hunks)
  • backend/apps/slack/models/__init__.py (1 hunks)
  • backend/apps/slack/models/google_auth.py (1 hunks)
  • backend/apps/slack/views.py (2 hunks)
  • backend/pyproject.toml (1 hunks)
  • backend/settings/base.py (1 hunks)
  • backend/settings/urls.py (2 hunks)
  • backend/tests/apps/common/clients_test.py (1 hunks)
  • backend/tests/apps/common/model_fileds_test.py (1 hunks)
  • backend/tests/apps/slack/models/google_auth_test.py (1 hunks)
  • cspell/custom-dict.txt (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (10)
backend/tests/apps/slack/models/google_auth_test.py (2)
backend/apps/slack/models/google_auth.py (6)
  • GoogleAuth (20-139)
  • is_token_expired (105-109)
  • get_flow (98-102)
  • authenticate (41-66)
  • refresh_access_token (112-135)
  • authenticate_callback (69-95)
backend/apps/slack/models/member.py (1)
  • Member (10-78)
backend/settings/urls.py (1)
backend/apps/slack/views.py (1)
  • google_auth_callback (32-53)
backend/tests/apps/common/clients_test.py (1)
backend/apps/common/clients.py (5)
  • KmsClient (24-44)
  • get_google_auth_client (8-21)
  • get_kms_client (50-55)
  • encrypt (40-44)
  • decrypt (36-38)
backend/tests/apps/common/model_fileds_test.py (1)
backend/apps/common/model_fields.py (4)
  • KmsEncryptedField (13-47)
  • get_prep_value (18-27)
  • to_python (45-47)
  • from_db_value (41-43)
backend/apps/slack/models/__init__.py (1)
backend/apps/slack/models/google_auth.py (1)
  • GoogleAuth (20-139)
backend/apps/slack/migrations/0023_alter_googleauth_access_token_and_more.py (1)
backend/apps/common/model_fields.py (1)
  • KmsEncryptedField (13-47)
backend/apps/slack/views.py (2)
backend/apps/slack/apps.py (1)
  • SlackConfig (13-26)
backend/apps/slack/models/google_auth.py (2)
  • GoogleAuth (20-139)
  • authenticate_callback (69-95)
backend/apps/slack/models/google_auth.py (3)
backend/apps/common/clients.py (1)
  • get_google_auth_client (8-21)
backend/apps/common/model_fields.py (1)
  • KmsEncryptedField (13-47)
backend/apps/slack/models/member.py (1)
  • Member (10-78)
backend/apps/common/model_fields.py (1)
backend/apps/common/clients.py (3)
  • get_kms_client (50-55)
  • encrypt (40-44)
  • decrypt (36-38)
backend/apps/slack/actions/home.py (3)
backend/apps/slack/models/google_auth.py (1)
  • GoogleAuth (20-139)
backend/apps/slack/models/member.py (1)
  • Member (10-78)
backend/apps/slack/blocks.py (1)
  • markdown (21-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (18)
cspell/custom-dict.txt (1)

21-21: LGTM: Add “PLW” to cspell dictionary

Prevents false positives for ruff codes like PLW0603. Placement after PLR keeps the list ordered.

backend/apps/slack/constants.py (1)

27-27: LGTM: Introduces dedicated action ID for Google sign-in

Constant name and value are clear and align with the action_id used in blocks and handlers.

backend/settings/urls.py (1)

34-42: Confirm OAuth “state” handling defends against CSRF and tampering

The callback route is wired; ensure google_auth_callback validates the OAuth state securely (e.g., signed/nonce-bound server-side, not just a raw member ID).

Would you confirm that:

  • A cryptographically random state value is generated per login attempt and bound server-side (e.g., cache/DB), or is HMAC-signed to embed member_id safely.
  • The callback verifies the state value before exchanging the code.

If not, I can propose a minimal HMAC-based state scheme for Slack flows.

backend/apps/slack/models/__init__.py (1)

3-3: LGTM: Re-exporting GoogleAuth from models package is appropriate

Publicly exposing GoogleAuth via the models package aligns with how other models are surfaced and eases imports in views/actions/tests.

backend/apps/slack/migrations/0022_alter_googleauth_options_alter_googleauth_table.py (1)

1-20: LGTM: Migration updates model options and table name

The migration correctly updates verbose_name_plural and db_table for GoogleAuth and chains to 0021 as expected.

backend/apps/slack/actions/home.py (3)

13-13: LGTM: Constant import for Google sign-in action

Using SIGN_IN_WITH_GOOGLE_ACTION keeps action registration consistent with the rest of the actions.


33-35: LGTM: Lazy imports to avoid init-time/cyclic issues

Importing GoogleAuth and Member inside the handler is a reasonable trade-off to avoid app init or circular import issues in Slack runtime.


127-128: LGTM: Action registration updated

New SIGN_IN_WITH_GOOGLE_ACTION registered with the app alongside others; matches the header button’s action_id.

backend/apps/slack/views.py (1)

3-11: LGTM on imports; consider adding signing for state verification

The new imports are fine. For secure OAuth, you’ll need django signing to validate the state (see callback comment).

backend/apps/slack/migrations/0020_alter_googleauth_access_token_and_more.py (1)

11-21: Check DB casting safety: TextField → BinaryField may not auto-cast cleanly

On PostgreSQL, altering textbytea can fail or produce unexpected values without an explicit USING clause. Auto-generated migrations sometimes work, but it’s DB-version sensitive. Since this is transitional (0021/0023 follow quickly), please verify applying this on a database with potential rows.

Suggested verification steps before merge:

  • Apply the full migration chain on a snapshot with sample plaintext token values and confirm no errors and that values remain readable (post-0023) when KMS is enabled.
  • If risk is identified, replace this AlterField with a two-step: add new binary columns, backfill, then drop old ones; or inject a USING clause via RunSQL.
backend/apps/slack/migrations/0019_googleauth.py (1)

12-38: Baseline model creation looks correct

One-to-one to Slack member, token fields and expiry shape are sensible for OAuth state. Given later migrations move to encrypted storage, this is a reasonable starting point.

backend/.env.example (1)

18-18: Redirect URI Matches Registered Route
Confirmed: backend/settings/urls.py defines

path("integrations/slack/oauth2/callback/", google_auth_callback),

which exactly matches the .env.example value (including trailing slash). No changes needed.

backend/apps/common/model_fields.py (1)

29-40: Decryption path is consistent and concise

Good handling of empty values, type validation, and timezone-agnostic bytes handling.

backend/tests/apps/slack/models/google_auth_test.py (2)

91-101: Solid coverage for the "existing valid token" path

Good use of get_or_create and ensuring no unnecessary save occurs.


128-145: Nice: expired token path refreshes via static method and preserves instance

Clear expectations without touching the DB.

backend/settings/base.py (1)

26-31: Good separation of Google OAuth config

Explicitly enumerating URIs and secrets keeps usage clear across the codebase.

backend/apps/slack/models/google_auth.py (2)

33-38: Good use of KMS-encrypted fields for token storage.

Storing access/refresh tokens in KmsEncryptedField is the right call, and handling timezone-awareness on expiry is solid.


97-103: Validate required Google OAuth settings before building the flow.

This makes AUTH_ERROR_MESSAGE actionable and avoids late failures.

Apply this diff:

     def get_flow():
         """Create a Google OAuth flow instance."""
         if not settings.IS_GOOGLE_AUTH_ENABLED:
             raise ValueError(AUTH_ERROR_MESSAGE)
-        return get_google_auth_client()
+        required = (
+            "GOOGLE_AUTH_CLIENT_ID",
+            "GOOGLE_AUTH_CLIENT_SECRET",
+            "GOOGLE_AUTH_REDIRECT_URI",
+            "GOOGLE_AUTH_AUTH_URI",
+            "GOOGLE_AUTH_TOKEN_URI",
+        )
+        missing = [name for name in required if not getattr(settings, name, None)]
+        if missing:
+            raise ValueError(f"{AUTH_ERROR_MESSAGE} Missing: {', '.join(missing)}")
+        return get_google_auth_client()
⛔ Skipped due to learnings
Learnt from: ahmedxgouda
PR: OWASP/Nest#2021
File: backend/apps/slack/models/google_auth.py:39-52
Timestamp: 2025-08-12T17:38:56.165Z
Learning: In the OWASP Nest project, IS_GOOGLE_AUTH_ENABLED in backend/settings/base.py already validates that all three Google OAuth settings (CLIENT_ID, CLIENT_SECRET, REDIRECT_URI) are present and not None/"None"/"", so additional validation in GoogleAuth.get_flow() is redundant.

ahmedxgouda and others added 2 commits August 22, 2025 09:34
…st.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ahmedxgouda
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
backend/tests/apps/nest/models/google_account_authorization_test.py (3)

50-56: Don't assert reverse OneToOne accessors via ORM instances; assert via model metadata instead.

Accessing self.member.google_account_authorization without saving triggers ORM access and couples the test to KMS/DB. Assert the accessor and relationship using model metadata.

-    def test_one_to_one_relationship(self):
-        """Test one-to-one relationship with Member."""
-        auth = GoogleAccountAuthorization(member=self.member, access_token=self.valid_token)
-
-        assert self.member.google_account_authorization == auth
-        assert auth.member == self.member
+    def test_one_to_one_relationship(self):
+        """Test OneToOne relationship metadata."""
+        field = GoogleAccountAuthorization._meta.get_field("member")
+        assert field.related_model is Member
+        assert field.remote_field.get_accessor_name() == "google_account_authorization"

24-26: Use str, not bytes, for tokens in tests (KmsEncryptedField expects str).

Tests currently set tokens as byte strings and assert against bytes. This will diverge from production behavior and can mask issues (e.g., field prep expecting str). Convert all token literals and related assertions to plain str.

Apply the following diff hunks:

@@
-        self.valid_token = b"valid_token"
-        self.valid_refresh_token = b"valid_refresh_token"
+        self.valid_token = "valid_token"
+        self.valid_refresh_token = "valid_refresh_token"
@@
-        mock_credentials_instance = Mock()
-        mock_credentials_instance.token = b"token"  # NOSONAR
-        mock_credentials_instance.refresh_token = b"refresh_token"
+        mock_credentials_instance = Mock()
+        mock_credentials_instance.token = "token"  # NOSONAR
+        mock_credentials_instance.refresh_token = "refresh_token"
@@
-        assert auth.access_token == b"token"
-        assert auth.refresh_token == b"refresh_token"
+        assert auth.access_token == "token"
+        assert auth.refresh_token == "refresh_token"
@@
-        mock_credentials = Mock()
-        mock_credentials.token = b"token"  # NOSONAR
-        mock_credentials.refresh_token = b"refresh_token"
+        mock_credentials = Mock()
+        mock_credentials.token = "token"  # NOSONAR
+        mock_credentials.refresh_token = "refresh_token"
@@
-        assert result.access_token == b"token"
-        assert result.refresh_token == b"refresh_token"
+        assert result.access_token == "token"
+        assert result.refresh_token == "refresh_token"
@@
-        mock_get_or_create.assert_called_once_with(
+        mock_get_or_create.assert_called_once_with(
             member=self.member,
             defaults={
-                "access_token": b"token",
-                "refresh_token": b"refresh_token",
+                "access_token": "token",
+                "refresh_token": "refresh_token",
                 "expires_at": self.future_time,
                 "scope": ["https://www.googleapis.com/auth/userinfo.profile"],
             },
         )

If helpful, I can push an automated commit updating all remaining byte-token literals across tests.

#!/usr/bin/env bash
# Find lingering byte-string tokens in test files
rg -nP "b\"(token|refresh_token|valid_token)\"" backend/tests --type py -C1

Also applies to: 268-276, 276-281, 361-378, 379-387


93-98: Fix incorrect parameter type passed to authorize().

GoogleAccountAuthorization.authorize() expects a slack_user_id: str, but the test passes a Member instance.

-        with pytest.raises(ValueError, match="AWS KMS is not enabled"):
-            GoogleAccountAuthorization.authorize(self.member)
+        with pytest.raises(ValueError, match="AWS KMS is not enabled"):
+            GoogleAccountAuthorization.authorize(self.member.slack_user_id)
backend/apps/nest/models/google_account_authorization.py (1)

118-141: Harden token exchange; wrap fetch_token and avoid logging PII.

Network/OAuth errors will currently bubble and 500 the view. Wrap fetch_token and surface a user-friendly ValidationError. Also avoid logging the raw state/token values.

-        flow = GoogleAccountAuthorization.get_flow()
-        flow.redirect_uri = settings.GOOGLE_AUTH_REDIRECT_URI
-        flow.fetch_token(authorization_response=auth_response)
+        flow = GoogleAccountAuthorization.get_flow()
+        flow.redirect_uri = settings.GOOGLE_AUTH_REDIRECT_URI
+        try:
+            flow.fetch_token(authorization_response=auth_response)
+        except Exception as e:  # google/auth/requests exceptions
+            raise ValidationError("Failed to retrieve Google OAuth tokens.") from e
@@
-        auth, _ = GoogleAccountAuthorization.objects.get_or_create(
+        auth, _ = GoogleAccountAuthorization.objects.get_or_create(
             member=member,
             defaults={
                 "access_token": flow.credentials.token,
                 "refresh_token": flow.credentials.refresh_token,
                 "expires_at": expires_at,
                 "scope": settings.GOOGLE_AUTH_SCOPES,
             },
         )
🧹 Nitpick comments (6)
backend/tests/apps/nest/models/google_account_authorization_test.py (2)

204-223: Optional: Assert the returned (url, state) tuple from authorize() for first-time auth.

You're validating authorization_url was called with the expected args, but not verifying that authorize() actually returns the (url, state) tuple. Add an assertion for the return value to increase coverage.

Example:

url_state = GoogleAccountAuthorization.authorize(self.member.slack_user_id)
assert isinstance(url_state, tuple) and len(url_state) == 2

350-359: Optional: Use a realistic URL string for auth_response.

Passing {} as auth_response relies on mocks tolerating non-string inputs. Provide a minimal realistic callback URL (e.g., "https://example.com/callback?state=...&code=...") to keep the test closer to runtime behavior.

-        result = GoogleAccountAuthorization.authorize_callback({})
+        result = GoogleAccountAuthorization.authorize_callback(
+            "https://example.com/callback?state=test_state&code=abc"
+        )
backend/apps/nest/models/google_account_authorization.py (4)

98-106: Handle Google OAuth error callbacks early (access_denied, etc.).

If the user cancels or an error occurs, Google includes error/error_description in the callback. Handle this before state verification for a cleaner UX.

-        parsed_url = urlparse(auth_response)
-        state = parse_qs(parsed_url.query).get("state", [None])[0]
+        parsed_url = urlparse(auth_response)
+        query = parse_qs(parsed_url.query)
+        error = query.get("error", [None])[0]
+        if error:
+            description = query.get("error_description", [error])[0]
+            raise ValidationError(description)
+        state = query.get("state", [None])[0]

64-86: Optional: Centralize feature/config checks in a helper and raise ImproperlyConfigured.

Checks for IS_GOOGLE_AUTH_ENABLED / IS_AWS_KMS_ENABLED are duplicated across methods; messages also imply missing client credentials. Consider a single _ensure_config() guard that validates flags and required settings, raising ImproperlyConfigured. This reduces duplication and clarifies intent.

Example:

+from django.core.exceptions import ImproperlyConfigured
@@
+REQUIRED_GOOGLE_SETTINGS = (
+    "GOOGLE_AUTH_CLIENT_ID",
+    "GOOGLE_AUTH_CLIENT_SECRET",
+    "GOOGLE_AUTH_REDIRECT_URI",
+    "GOOGLE_AUTH_AUTH_URI",
+    "GOOGLE_AUTH_TOKEN_URI",
+)
+
 class GoogleAccountAuthorization(models.Model):
@@
+    @staticmethod
+    def _ensure_config():
+        if not settings.IS_GOOGLE_AUTH_ENABLED:
+            raise ImproperlyConfigured("Google OAuth is disabled. Set IS_GOOGLE_AUTH_ENABLED=True.")
+        missing = [s for s in REQUIRED_GOOGLE_SETTINGS if not getattr(settings, s, None)]
+        if missing:
+            raise ImproperlyConfigured(f"Missing Google OAuth settings: {', '.join(missing)}")
+        if not settings.IS_AWS_KMS_ENABLED:
+            raise ImproperlyConfigured(KMS_ERROR_MESSAGE)

Then call _ensure_config() at the start of authorize, authorize_callback, get_flow, and refresh_access_token.


35-45: Model design: member is nullable; consider uniqueness and identity.

With member=null=True and no alternative unique identifier (e.g., Google account ID or email), the table may accumulate duplicate or orphaned records. If Slack Member can be absent during bootstrap, consider:

  • Storing google_subject (sub) or email and adding a unique constraint.
  • Making member non-nullable once linked, or enforcing a partial unique index.

If you want, I can propose a migration strategy with a nullable google_subject initially, then enforce uniqueness.


174-188: Optional: Avoid logging-and-raise in refresh path; message is sufficient.

Inside the except RefreshError block, logging the error and re-raising leads to duplicated logs upstream. Prefer raising ValidationError with a clear message and let the caller log.

-        except RefreshError as e:
-            error_message = "Error refreshing Google OAuth token"
-            logger.exception(error_message)
-            raise ValidationError(error_message) from e
+        except RefreshError as e:
+            raise ValidationError("Error refreshing Google OAuth token") from e
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 30a4ad0 and 1879ff3.

📒 Files selected for processing (2)
  • backend/apps/nest/models/google_account_authorization.py (1 hunks)
  • backend/tests/apps/nest/models/google_account_authorization_test.py (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-12T17:38:56.165Z
Learnt from: ahmedxgouda
PR: OWASP/Nest#2021
File: backend/apps/slack/models/google_auth.py:39-52
Timestamp: 2025-08-12T17:38:56.165Z
Learning: In the OWASP Nest project, IS_GOOGLE_AUTH_ENABLED in backend/settings/base.py already validates that all three Google OAuth settings (CLIENT_ID, CLIENT_SECRET, REDIRECT_URI) are present and not None/"None"/"", so additional validation in GoogleAuth.get_flow() is redundant.

Applied to files:

  • backend/apps/nest/models/google_account_authorization.py
📚 Learning: 2025-08-22T06:36:42.582Z
Learnt from: ahmedxgouda
PR: OWASP/Nest#2089
File: backend/apps/nest/models/google_account_authorization.py:61-62
Timestamp: 2025-08-22T06:36:42.582Z
Learning: In the OWASP/Nest project, ruff linting rules discourage using logger.error() immediately before raising exceptions as it creates redundant logging. The preferred approach is to remove the logging call and let the caller handle logging the exception appropriately.

Applied to files:

  • backend/apps/nest/models/google_account_authorization.py
🔇 Additional comments (1)
backend/apps/nest/models/google_account_authorization.py (1)

151-155: Bug: timezone.timedelta does not exist; import timedelta from datetime.

django.utils.timezone has no timedelta. This will raise at runtime. Use from datetime import timedelta and reference timedelta(...).

@@
-from django.utils import timezone
+from django.utils import timezone
+from datetime import timedelta
@@
-        return self.expires_at is None or self.expires_at <= timezone.now() + timezone.timedelta(
-            seconds=60
-        )
+        return (
+            self.expires_at is None
+            or self.expires_at <= timezone.now() + timedelta(seconds=60)
+        )
⛔ Skipped due to learnings
Learnt from: ahmedxgouda
PR: OWASP/Nest#2021
File: backend/apps/slack/models/google_auth.py:77-81
Timestamp: 2025-08-12T17:45:36.105Z
Learning: django.utils.timezone.timedelta exists and is an alias for datetime.timedelta. It can be used directly after importing timezone from django.utils.

Comment on lines 91 to 98
if not settings.IS_GOOGLE_AUTH_ENABLED:
logger.exception(AUTH_ERROR_MESSAGE)
raise ValueError(AUTH_ERROR_MESSAGE)

if not settings.IS_AWS_KMS_ENABLED:
logger.exception(KMS_ERROR_MESSAGE)
raise ValueError(KMS_ERROR_MESSAGE)
parsed_url = urlparse(auth_response)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove pre-raise logging; raise directly.

Logging immediately before raising is discouraged in this codebase (ruff + local convention) and adds noise. Raise directly.

-        if not settings.IS_GOOGLE_AUTH_ENABLED:
-            logger.exception(AUTH_ERROR_MESSAGE)
-            raise ValueError(AUTH_ERROR_MESSAGE)
-
-        if not settings.IS_AWS_KMS_ENABLED:
-            logger.exception(KMS_ERROR_MESSAGE)
-            raise ValueError(KMS_ERROR_MESSAGE)
+        if not settings.IS_GOOGLE_AUTH_ENABLED:
+            raise ValueError(AUTH_ERROR_MESSAGE)
+        if not settings.IS_AWS_KMS_ENABLED:
+            raise ValueError(KMS_ERROR_MESSAGE)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if not settings.IS_GOOGLE_AUTH_ENABLED:
logger.exception(AUTH_ERROR_MESSAGE)
raise ValueError(AUTH_ERROR_MESSAGE)
if not settings.IS_AWS_KMS_ENABLED:
logger.exception(KMS_ERROR_MESSAGE)
raise ValueError(KMS_ERROR_MESSAGE)
parsed_url = urlparse(auth_response)
if not settings.IS_GOOGLE_AUTH_ENABLED:
raise ValueError(AUTH_ERROR_MESSAGE)
if not settings.IS_AWS_KMS_ENABLED:
raise ValueError(KMS_ERROR_MESSAGE)
parsed_url = urlparse(auth_response)
🤖 Prompt for AI Agents
In backend/apps/nest/models/google_account_authorization.py around lines 91 to
98, remove the pre-raise logger.exception calls and raise the ValueError
directly; replace "logger.exception(AUTH_ERROR_MESSAGE); raise
ValueError(AUTH_ERROR_MESSAGE)" with just "raise ValueError(AUTH_ERROR_MESSAGE)"
and similarly replace the KMS logging+raise with just "raise
ValueError(KMS_ERROR_MESSAGE)" so no logging occurs immediately before the
raises.

@ahmedxgouda ahmedxgouda marked this pull request as ready for review August 28, 2025 19:24
@ahmedxgouda ahmedxgouda requested a review from kasya as a code owner August 28, 2025 19:24
Comment on lines 30 to 38
_kms_client = None


def get_kms_client() -> KmsClient:
"""Get the AWS KMS client."""
global _kms_client # noqa: PLW0603
if _kms_client is None:
_kms_client = KmsClient()
return _kms_client
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not quite. It may be look like one but it's a global variable technically. And its discouraged to use them -- see the PLW0603 you suppressed (I suggest paying more attention to what automated checks suggest)

@property
def is_token_expired(self):
"""Check if the access token is expired."""
return self.expires_at is None or self.expires_at <= timezone.now() + timezone.timedelta(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 60 seconds timedelta?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rabbit suggested that, there is a case that the user may use the token near the expiration date.

@sonarqubecloud
Copy link

@ahmedxgouda ahmedxgouda requested a review from arkid15r August 30, 2025 03:40
Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it's still not a singleton -- just a regular class. Nevermind, let's fix that later.

@arkid15r arkid15r merged commit 76cf178 into OWASP:feature/nestbot-calendar-events Aug 30, 2025
22 checks passed
ahmedxgouda added a commit to ahmedxgouda/Nest that referenced this pull request Sep 7, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arkid15r added a commit that referenced this pull request Sep 15, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arkid15r added a commit that referenced this pull request Sep 17, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arkid15r added a commit that referenced this pull request Sep 19, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arkid15r added a commit that referenced this pull request Sep 19, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arkid15r added a commit that referenced this pull request Sep 23, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arkid15r added a commit that referenced this pull request Sep 28, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arkid15r added a commit that referenced this pull request Oct 7, 2025
* Add google libs

* Add model

* Update logic and add tests

* Update tests, apply make-check and suggestions

* Skip sonar and apply rabbit suggestion

* Update poetry lock

* Add migrations

* Change user to member

* Update env.example

* Update poetry.lock

* Update tokens to binary field

* Improve auth logic

* Apply migrations

* Apply rabbit's suggestions

* Separate google client from slack.GoogleAuth model

* Convert singleton to factory

* Update auth_uri

* Apply suggestions

* Add meta class

* Update refresh logic and tests

* Make google auth credentials secret

* Update code

* Apply suggestions

* Update tests and member related name

* Clean up migrations

* Add kms key id to env

* Add AWS to settings

* Add KMS client, encryption and decryption

* Separate kms client from GoogleAuth model

* Update kms client

* Update tests

* Update refresh and tests

* Apply rabbit suggestion

* Apply check-spelling

* Apply rabbit suggestion and add google client test

* Add custom field for kms

* Update tests

* Apply suggestions

* Update tests

* Guard authenticate method with KMS

* Update tests

* Add migrations

* Update settings

* Clean up migrations

* Add google callback

* Add google sign in button

* Apply suggestions

* Apply suggestion

* Update tests

* Change name

* Add migrations

* Refactor google and kms clients

* Update tests

* Add sign in command

* Update tests

* Add handler test

* Clean up migrations

* Apply suggestions

* Update backend/tests/apps/nest/models/google_account_authorization_test.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Apply rabbit's suggestion

* Update poetry lock

* Update code

* Apply suggestions

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integrate Slack with google OAuth

2 participants