From c2ce21e56c9a55157c68dc92283bc218f8022230 Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Mon, 22 Dec 2025 12:23:39 +0530 Subject: [PATCH] [WEB-5657] feat: add synchronization configuration for multiple providers in authentication adapter (#8336) * feat: add sync functionality for OAuth providers - Implemented `check_sync_enabled` method to verify if sync is enabled for Google, GitHub, GitLab, and Gitea. - Added `sync_user_data` method to update user details, including first name, last name, display name, and avatar. - Updated configuration variables to include sync options for each provider. - Integrated sync check into the login/signup process. * feat: add sync toggle for OAuth providers in configuration forms * fix: remove default value for sync options in OAuth configuration forms * chore: delete old avatar and upload a new one * chore: update class method * chore: add email nullable * refactor: streamline sync check for multiple providers and improve avatar deletion logic * fix: ensure ENABLE_SYNC configurations default to "0" for Gitea, Github, Gitlab, and Google forms * fix: simplify toggle switch value handling in ControllerSwitch component --------- Co-authored-by: b-saikrishnakanth --- .../(dashboard)/authentication/gitea/form.tsx | 41 ++++++---- .../authentication/github/form.tsx | 43 ++++++---- .../authentication/gitlab/form.tsx | 42 ++++++---- .../authentication/google/form.tsx | 40 +++++---- .../components/common/controller-switch.tsx | 40 +++++++++ apps/api/plane/authentication/adapter/base.py | 82 +++++++++++++++++-- apps/api/plane/db/models/user.py | 10 +++ apps/api/plane/settings/storage.py | 12 +++ .../utils/instance_config_variables/core.py | 24 ++++++ packages/types/src/instance/auth.ts | 17 +++- 10 files changed, 278 insertions(+), 73 deletions(-) create mode 100644 apps/admin/core/components/common/controller-switch.tsx diff --git a/apps/admin/app/(all)/(dashboard)/authentication/gitea/form.tsx b/apps/admin/app/(all)/(dashboard)/authentication/gitea/form.tsx index 250c45125..7cad550f8 100644 --- a/apps/admin/app/(all)/(dashboard)/authentication/gitea/form.tsx +++ b/apps/admin/app/(all)/(dashboard)/authentication/gitea/form.tsx @@ -12,6 +12,8 @@ import { CodeBlock } from "@/components/common/code-block"; import { ConfirmDiscardModal } from "@/components/common/confirm-discard-modal"; import type { TControllerInputFormField } from "@/components/common/controller-input"; import { ControllerInput } from "@/components/common/controller-input"; +import type { TControllerSwitchFormField } from "@/components/common/controller-switch"; +import { ControllerSwitch } from "@/components/common/controller-switch"; import type { TCopyField } from "@/components/common/copy-field"; import { CopyField } from "@/components/common/copy-field"; // hooks @@ -40,6 +42,7 @@ export function InstanceGiteaConfigForm(props: Props) { GITEA_HOST: config["GITEA_HOST"] || "https://gitea.com", GITEA_CLIENT_ID: config["GITEA_CLIENT_ID"], GITEA_CLIENT_SECRET: config["GITEA_CLIENT_SECRET"], + ENABLE_GITEA_SYNC: config["ENABLE_GITEA_SYNC"] || "0", }, }); @@ -103,6 +106,11 @@ export function InstanceGiteaConfigForm(props: Props) { }, ]; + const GITEA_FORM_SWITCH_FIELD: TControllerSwitchFormField = { + name: "ENABLE_GITEA_SYNC", + label: "Gitea", + }; + const GITEA_SERVICE_FIELD: TCopyField[] = [ { key: "Callback_URI", @@ -129,20 +137,22 @@ export function InstanceGiteaConfigForm(props: Props) { const onSubmit = async (formData: GiteaConfigFormValues) => { const payload: Partial = { ...formData }; - await updateInstanceConfigurations(payload) - .then((response = []) => { - setToast({ - type: TOAST_TYPE.SUCCESS, - title: "Done!", - message: "Your Gitea authentication is configured. You should test it now.", - }); - reset({ - GITEA_HOST: response.find((item) => item.key === "GITEA_HOST")?.value, - GITEA_CLIENT_ID: response.find((item) => item.key === "GITEA_CLIENT_ID")?.value, - GITEA_CLIENT_SECRET: response.find((item) => item.key === "GITEA_CLIENT_SECRET")?.value, - }); - }) - .catch((err) => console.error(err)); + try { + const response = await updateInstanceConfigurations(payload); + setToast({ + type: TOAST_TYPE.SUCCESS, + title: "Done!", + message: "Your Gitea authentication is configured. You should test it now.", + }); + reset({ + GITEA_HOST: response.find((item) => item.key === "GITEA_HOST")?.value, + GITEA_CLIENT_ID: response.find((item) => item.key === "GITEA_CLIENT_ID")?.value, + GITEA_CLIENT_SECRET: response.find((item) => item.key === "GITEA_CLIENT_SECRET")?.value, + ENABLE_GITEA_SYNC: response.find((item) => item.key === "ENABLE_GITEA_SYNC")?.value, + }); + } catch (err) { + console.error(err); + } }; const handleGoBack = (e: React.MouseEvent) => { @@ -176,12 +186,13 @@ export function InstanceGiteaConfigForm(props: Props) { required={field.required} /> ))} +