Neilk1021 opened a new pull request, #6720:
URL: https://github.com/apache/texera/pull/6720

   
   ### What changes were proposed in this PR?
   Refactors authentication to **decouple identity from credentials**: all auth 
material moves out of the `"user"` table into a dedicated `auth_provider` 
table, external-provider login (Google, Facebook) is unified behind a single 
provisioning path, and **Facebook OAuth** is added as a new login option.
   
   1. **Schema split — new `auth_provider` table.** The `"user"` table drops 
`password`, `google_id`, `google_avatar`, and the old `ck_nulltest` CHECK, and 
gains a provider-neutral `avatar` column. A new `provider_type_enum 
('LOCAL','GOOGLE','FACEBOOK')` and `auth_provider (uid, provider_type, 
provider_id, password, created_at)` table are added, with `PRIMARY KEY (uid, 
provider_type)`, an FK to `"user"(uid) ON DELETE CASCADE`, 
`uq_provider_identity UNIQUE (provider_type, provider_id)`, and 
`ck_provider_credential` (LOCAL ⇒ password set / provider_id null; non-LOCAL ⇒ 
provider_id set / password null) replacing `ck_nulltest`. Liquibase migration 
`sql/updates/29.sql` (registered in `sql/changelog.xml`) creates the enum + 
table and backfills `LOCAL` rows from `user.password` and `GOOGLE` rows from 
`user.google_id`. The jOOQ `AuthProvider` table/dao/pojo and `ProviderTypeEnum` 
are regenerated from the new DDL.
   
   2. **Shared `ExternalAuthProvisioner` abstraction.** New `object 
ExternalAuthProvisioner` that both Google and Facebook login route through. 
Given an `ExternalProfile(providerType, providerId, name, email, avatar: 
Option[String])`, `loginOrProvision` runs a single transaction that resolves 
the user by provider identity → else by email → else creates an `INACTIVE` 
user, then upserts the provider row (guarding the `(uid, provider_type)` PK 
against collision) and refreshes `name`/`email`/`avatar`. `avatar` is optional 
so a Facebook login (no avatar) never clobbers an avatar set by Google.
   
   3. **Facebook OAuth (new).** `FacebookAuthResource` at `/auth/facebook` 
(`GET /clientid`, `POST /login`) verifies the access token via the Graph API 
`debug_token` + `/me` endpoints, falling back to `{id}@facebook.local` when 
Facebook returns no email. Config gains `facebook.clientId` / 
`facebook.appSecret` (envs `USER_SYS_FACEBOOK_CLIENT_ID` / 
`USER_SYS_FACEBOOK_APP_SECRET`) with matching `UserSystemConfig` accessors.
   
   4. **Google + local login retargeted to the new schema.** 
`GoogleAuthResource` drops its inline DAO logic and delegates to 
`ExternalAuthProvisioner`. Local login (`AuthResource`) now joins 
`auth_provider` on `PROVIDER_TYPE = LOCAL` and checks the hashed password 
there; registration and admin bootstrap write the `user` row + a `LOCAL` 
provider row atomically via a new private `InsertUser`. 
`AdminUserResource`/`UserResource` and related resources rebind `avatar` onto 
`user`.
   
   5. **JWT claims simplified.** `JwtAuth.jwtClaims` emits a single `avatar` 
claim instead of `googleId`/`googleAvatar`; `JwtParser` and `SessionUser` are 
updated to match (`SessionUser.getGoogleId` removed), constructing `User` via 
setters rather than the old positional constructor.
   
   6. **Frontend.** New consolidated login page (`texera-login.component`) with 
tabbed local sign-in/sign-up plus Google and Facebook buttons; new 
`FacebookAuthService`; the `User` type and `auth.service` JWT decode swap 
`googleId`/`googleAvatar` for `avatar`; `app.module` registers a 
`FacebookLoginProvider` alongside Google, resolving both client ids in parallel.
   
   7. **Tests.** New: `ExternalAuthProvisionerSpec` (embedded-Postgres 
integration over the full provisioning matrix), 
`facebook-auth.service.spec.ts`, `texera-login.component.spec.ts`. Updated: 
`JwtAuth`/`JwtParser`/`SessionUser`/`UserAuthenticator` specs for the 
avatar-claim change, plus a repo-wide sweep dropping `user.setPassword(...)` 
from existing specs to match the new schema.
   
   ### Any related issues, documentation, discussions?
   Closes #6718. The design rationale and coupling points that drove this split 
(the `jwtClaims` provider fields, the `ck_nulltest` CHECK, the DAO-per-resource 
pattern, and the frontend `User` shape) are documented in 
`auth-split-notes.md`. No other tracked issues.
   
   ### How was this PR tested?
   Auth-specific suites were run and are green:
   - **Backend (`sbt`, ScalaTest):** `ExternalAuthProvisionerSpec` runs against 
embedded Postgres (`MockTexeraDB` loads the real `sql/texera_ddl.sql`, so the 
`auth_provider` constraints are live) — **7/7**, covering new-identity 
provisioning, returning-identity idempotency, profile refresh, the 
Facebook-avatar-not-clobbered case, email-match linking, and provider-id 
upsert. `JwtAuthSpec` — **5/5**, including the new `avatar` claim.
   - **Frontend (`ng test` / Vitest):** `facebook-auth.service.spec.ts` + 
`texera-login.component.spec.ts` — **22/22**, covering local login/register 
validation and navigation, social sign-in routing (Google vs Facebook), the 
confirm-password validator, and error paths.
   
   Commands:
   ```bash
   sbt "Auth/testOnly org.apache.texera.auth.JwtAuthSpec" \
       "WorkflowExecutionService/testOnly 
org.apache.texera.web.resource.auth.ExternalAuthProvisionerSpec"
   npx ng test --watch=false \
     --include="src/app/common/service/user/facebook-auth.service.spec.ts" \
     --include="src/app/hub/component/login/texera-login.component.spec.ts"
   ```
   A full `sbt clean compile test` + complete frontend suite run is still 
recommended before merge (the schema-matching spec sweep touches many modules).
   
   ### Was this PR authored or co-authored using generative AI tooling?
   Yes. This PR was co-authored with **Claude Opus 4.8**. The overall 
architecture and design decisions were the author's; Claude assisted with 
implementing much of the code and the accompanying tests.


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to