alumni_lookup

Feature 1: Authentication & Onboarding

⚠️ PLANNING DOCUMENT - This describes features that are NOT YET IMPLEMENTED.

Builds on: Auth & Roles System — Google SSO patterns, OmniAuth infrastructure, and Pundit policies established there extend to Champion Portal with Apple/Facebook providers.


Overview

Authentication for the Champion Portal is separate from the internal Lookup Portal. Champions (external alumni) authenticate through a different system than internal staff users.


Goals


✅ Foundational Decisions (Resolved)

Decision Answer Rationale
Onboarding flow Progressive Account Creation Email + name first (feels like “getting started”), password after email verification
BUID requirement Optional + Two-tier verification Email Verified = basic access; Champion Verified = full access
Account timing Single table + status champions table with verification_status enum
Non-degree alumni Supported Can be Champion Verified without degree data

Verification Tiers

Status How Achieved Access Level
Unverified Account created, email not confirmed Cannot log in
Email Verified Clicked email verification link, set password Can log in, edit own profile only
Champion Verified BUID linked by Engagement Team Full portal access

Access Matrix

Feature Unverified Email Verified Champion Verified
Log in
View/edit own profile
Browse directory
Appear in directory
Post on boards
Submit events
Contact other Champions
See own degree info ✅ (if available)

User Messaging: Email Verified users see clear messaging that verification typically happens within 1 business day.


Onboarding Flows

Option A: Progressive Account Creation (Email)

┌─────────────────────────────────────────────────────────────┐
│ Step 1: Get Started                                         │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ First Name: [________________]                          │ │
│ │ Last Name:  [________________]                          │ │
│ │ Email:      [________________]                          │ │
│ │                                                         │ │
│ │ [Get Started]                                           │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│ Step 2: Check Your Email                                    │
│                                                             │
│ We sent a verification link to [email].                     │
│ Click the link to continue setting up your account.         │
│                                                             │
│ [Resend Email]                                              │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼ (click email link)
┌─────────────────────────────────────────────────────────────┐
│ Step 3: Set Your Password                                   │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Password:         [________________]                    │ │
│ │ Confirm Password: [________________]                    │ │
│ │                                                         │ │
│ │ [Create Account]                                        │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│ Step 4: Complete Your Profile                               │
│ (Status: Email Verified - awaiting Champion Verification)   │
│                                                             │
│ While you wait for verification (usually within 1 business  │
│ day), you can complete your profile:                        │
│                                                             │
│ • Contact information                                       │
│ • Employment                                                │
│ • Affinities                                                │
│ • Privacy settings                                          │
│                                                             │
│ [Continue to Profile]                                       │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│ Step 5: Champion Role Quiz (optional, can do later)         │
│                                                             │
│ Discover which Champion role fits you best!                 │
│                                                             │
│ [Take the Quiz] or [Skip for Now]                           │
└─────────────────────────────────────────────────────────────┘

Option B: Social Sign-In (SSO)

┌─────────────────────────────────────────────────────────────┐
│ Welcome to Belmont Alumni Champions                         │
│                                                             │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │       Continue with Google                              │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │       Sign in with Apple                                │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │       Continue with Facebook                            │ │
│ └─────────────────────────────────────────────────────────┘ │
│                                                             │
│                     ── or ──                                │
│                                                             │
│   [Create account with email]    [Sign in with email]       │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼ (clicks SSO button)
┌─────────────────────────────────────────────────────────────┐
│ Google/Apple OAuth                                          │
│                                                             │
│ (User authorizes app, redirected back)                      │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│ Step 2: Enter Your Location                                 │
│ (Account created as Email Verified - email from SSO)        │
│                                                             │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ZIP Code: [________]                                    │ │
│ │                                                         │ │
│ │ We'll use this to connect you with nearby Champions     │ │
│ │ and regional events.                                    │ │
│ │                                                         │ │
│ │ [Continue]                                              │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│ Step 3: Complete Your Profile                               │
│ (Status: Email Verified - awaiting Champion Verification)   │
│                                                             │
│ (Same as Step 4 in email flow)                              │
└─────────────────────────────────────────────────────────────┘

SSO Benefits:

SSO Notes:


Champion Verification Process

How It Works (Engagement Team Side)

  1. New Email Verified champion appears in Engagement Team queue
  2. Team looks up champion by name in existing systems
  3. Team finds BUID and links it to champion account
  4. Champion status changes to Champion Verified
  5. Champion receives email notification of full access

Non-Degree Alumni Support

Some Champions won’t have degree records:

Solution: Champions can be verified (BUID linked) without degree data. Their profile simply won’t display education information.

# Champion can be verified even without degree data
champion.champion_verified? # true
champion.has_degree_info?   # false (no degrees in alumni record)

Features

Account Creation

Login

Password Management

Social Sign-In (SSO)

Supported Providers:

Future Consideration: LinkedIn could pull employer/job title, but deferred—2 fields don’t justify the API complexity.

Implementation:

Auth & Roles project installs the OmniAuth foundation for Google. Champion Portal adds Apple and Facebook:

# Gemfile (Apple and Facebook added to existing OmniAuth setup)
gem 'omniauth-apple'
gem 'omniauth-facebook'
# gem 'omniauth-google-oauth2' — already installed by Auth & Roles
# gem 'omniauth-rails_csrf_protection' — already installed by Auth & Roles

SSO Behavior: | Scenario | Result | |———-|——–| | New user via SSO | Account created, email_verified, prompt for ZIP | | Existing email via SSO | Link provider to existing account | | Different email via SSO | Reject, show existing account message |

Database Fields (on cp_champions):

t.string :google_uid
t.string :apple_uid
t.string :facebook_uid
t.datetime :google_linked_at
t.datetime :apple_linked_at
t.datetime :facebook_linked_at

Sign-In UI (mobile-first order):

┌──────────────────────────────────────────┐
│       Continue with Google               │  ← Most common
├──────────────────────────────────────────┤
│       Sign in with Apple                 │  ← Apple users
├──────────────────────────────────────────┤
│       Continue with Facebook             │  ← Alumni demographic
├──────────────────────────────────────────┤
│               ── or ──                   │
├──────────────────────────────────────────┤
│  Email: [____________________________]   │
│  Password: [_________________________]   │  ← Traditional
│  [ Sign In ]  or  [ Create Account ]     │
└──────────────────────────────────────────┘

Role Levels

Role Description Assignment
Champion Default role for all Champion Verified users Automatic on verification
CLC (City Leadership Council) Elevated regional permissions Manual assignment by Engagement Team

Technical Implementation

Champion Model

# app/models/cp_champion.rb
class CpChampion < ApplicationRecord
  devise :database_authenticatable, :registerable, 
         :recoverable, :rememberable, :validatable,
         :confirmable,      # for email verification
         :omniauthable,     # for SSO
         omniauth_providers: [:google_oauth2, :apple, :facebook]
  
  # Link to Alumni record (optional - supports non-degree alumni)
  belongs_to :alumni, primary_key: :buid, foreign_key: :buid, optional: true
  
  # Verification status
  enum verification_status: { 
    unverified: 0,        # Email not confirmed (can't log in)
    email_verified: 1,    # Email confirmed, limited access
    champion_verified: 2  # BUID linked, full access
  }
  
  # Portal role
  enum role: { champion: 0, city_leader: 1 }
  
  # Region assignment
  belongs_to :region, optional: true
  
  # SSO helper methods
  def google_connected?
    google_uid.present?
  end
  
  def apple_connected?
    apple_uid.present?
  end
  
  def facebook_connected?
    facebook_uid.present?
  end
  
  def sso_only?
    !encrypted_password.present? && (google_connected? || apple_connected? || facebook_connected?)
  end
  
  def has_degree_info?
    alumni.present? && alumni.degrees.any?
  end
  
  def full_access?
    champion_verified?
  end
  
  # OmniAuth callbacks
  def self.from_omniauth(auth)
    where(email: auth.info.email).first_or_initialize.tap do |champion|
      champion.email = auth.info.email
      champion.first_name ||= auth.info.first_name
      champion.last_name ||= auth.info.last_name
      
      case auth.provider
      when 'google_oauth2'
        champion.google_uid = auth.uid
        champion.google_linked_at = Time.current
      when 'apple'
        champion.apple_uid = auth.uid
        champion.apple_linked_at = Time.current
        # Apple only sends name on first auth - save it!
        champion.first_name ||= auth.info.name&.split&.first
        champion.last_name ||= auth.info.name&.split&.last
      when 'facebook'
        champion.facebook_uid = auth.uid
        champion.facebook_linked_at = Time.current
      end
      
      # SSO users skip email verification
      champion.confirmation_token = nil
      champion.confirmed_at ||= Time.current
      champion.verification_status = :email_verified if champion.unverified?
      
      champion.save!
    end
  end
end

Authentication Guards

# app/controllers/champions/base_controller.rb
class Champions::BaseController < PublicController
  before_action :authenticate_champion!
  
  private
  
  def authenticate_champion!
    redirect_to champions_login_path unless current_champion
  end
  
  def require_full_access!
    unless current_champion&.champion_verified?
      redirect_to champions_pending_path, 
        alert: 'Your account is pending verification. This usually takes 1 business day.'
    end
  end
  
  def require_clc!
    redirect_to champions_root_path unless current_champion&.city_leader?
  end
end

Custom Devise Flow for Progressive Account Creation

# app/controllers/champions/registrations_controller.rb
class Champions::RegistrationsController < Devise::RegistrationsController
  # Step 1: Collect name + email only (no password yet)
  def create
    build_resource(sign_up_params.except(:password, :password_confirmation))
    resource.skip_password_validation = true
    
    if resource.save
      # Send confirmation email with special token
      resource.send_confirmation_instructions
      redirect_to champions_check_email_path
    else
      render :new
    end
  end
  
  # Step 3: Set password after email confirmation
  def set_password
    @champion = Champion.find_by(confirmation_token: params[:token])
    
    if @champion && request.post?
      @champion.password = params[:password]
      @champion.password_confirmation = params[:password_confirmation]
      @champion.skip_password_validation = false
      @champion.confirm # Mark email as confirmed
      @champion.email_verified! # Update verification status
      
      if @champion.save
        sign_in(@champion)
        redirect_to champions_profile_path
      end
    end
  end
end

Migration from Current Signup Flow

Current State

Migration Path

  1. Keep current signup flow working during transition
  2. Build new Champion authentication system
  3. Optionally migrate existing signups to champion accounts
  4. Update champions.bualum.co to point to new portal