Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Contao Discourse Laravel Package

craffft/contao-discourse

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require craffft/contao-discourse "~2.0"

Ensure your project uses Contao 4.x and Symfony 4.x/5.x (as the bundle is built for Contao’s Symfony integration).

  1. Enable the Bundle: Add the bundle to config/bundles.php (Symfony 4+) or app/AppKernel.php (Symfony 3/Contao 3):

    return [
        // ...
        Craffft\ContaoDiscourseSSOBundle\CraffftContaoDiscourseSSOBundle::class => ['all' => true],
    ];
    
  2. Configuration: Publish the default config and update config/packages/craffft_contao_discourse.yaml:

    php bin/console contao:discourse:install
    

    This generates a discourse.yaml file in config/packages/. Configure:

    • discourse_url: Your Discourse instance URL (e.g., https://forum.example.com).
    • secret_key: Shared secret from Discourse admin → Settings → Single Sign On.
    • trust_proxy: Set to true if behind a reverse proxy (e.g., Nginx/Apache).
  3. First Use Case: Test SSO by logging into Contao and clicking a "Discourse SSO" link (if added to a module). Verify redirection to Discourse and automatic login.


Implementation Patterns

Core Workflows

  1. User Authentication Flow:

    • Contao → Discourse: Trigger SSO via a Contao module (e.g., custom button or menu item) using the DiscourseSsoService:
      use Craffft\ContaoDiscourseSSOBundle\Service\DiscourseSsoService;
      
      $ssoService = $this->container->get(DiscourseSsoService::class);
      $ssoUrl = $ssoService->generateSsoUrl($contaoUserId, $contaoUserEmail);
      
      Redirect users to $ssoUrl (Discourse will handle authentication).
    • Discourse → Contao: After SSO, Discourse redirects back to Contao with a sso query param. Override the ContaoUserListener to sync Discourse users to Contao:
      # config/packages/craffft_contao_discourse.yaml
      craffft_contao_discourse:
          sync_users: true  # Auto-create Contao users on SSO
      
  2. User Synchronization:

    • Manual Sync: Use the CLI command to sync existing Discourse users to Contao:
      php bin/console contao:discourse:sync-users
      
    • Event-Driven Sync: Extend the UserSynchronizer to customize field mappings (e.g., map Discourse username to Contao username):
      // src/EventListener/CustomUserSynchronizer.php
      public function syncUser($discourseUser, ContaoUser $contaoUser)
      {
          $contaoUser->username = $discourseUser['username'];
          $contaoUser->save();
      }
      
      Register the listener in services.yaml:
      services:
          App\EventListener\CustomUserSynchronizer:
              tags: ['contao.discourse.user_synchronizer']
      
  3. Role Mapping:

    • Map Discourse groups to Contao user groups via config:
      craffft_contao_discourse:
          group_mapping:
              admins: ['admin']          # Discourse group "admins" → Contao group "admin"
              moderators: ['moderator']  # Discourse group "moderators" → Contao group "moderator"
      

Integration Tips

  • Contao Backend Integration: Add a custom button in the Contao backend to trigger SSO:
    // src/Resources/contao/dca/tl_module.php
    $GLOBALS['TL_DCA']['tl_module']['palettes']['discourse_sso'] .= ';discourse_sso';
    $GLOBALS['TL_DCA']['tl_module']['fields']['discourse_sso'] = [
        'label' => ['Discourse SSO', 'discourse_sso'],
        'inputType' => 'button',
        'eval' => ['button_callback' => ['ContaoDiscourse', 'generateSsoUrl']],
    ];
    
  • Frontend Integration: Use a custom module to display Discourse content or SSO links:
    {# templates/mod_discourse_sso.html #}
    <a href="{{ path('contao_discourse_sso', {'userId': member.id}) }}">Go to Discourse</a>
    
    Route the link in config/routes.yaml:
    contao_discourse_sso:
        path: /discourse/sso/{userId}
        controller: Craffft\ContaoDiscourseSSOBundle\Controller\SsoController::generateSsoUrl
    

Gotchas and Tips

Pitfalls

  1. Secret Key Mismatch:

    • Symptom: SSO fails with "Invalid signature" errors.
    • Fix: Regenerate the secret key in Discourse (Settings → Single Sign On) and update config/packages/craffft_contao_discourse.yaml.
  2. User Sync Conflicts:

    • Symptom: Duplicate Contao users or missing Discourse users.
    • Fix: Disable auto-sync (sync_users: false) and manually sync via CLI:
      php bin/console contao:discourse:sync-users --force
      
      Use --dry-run to preview changes:
      php bin/console contao:discourse:sync-users --dry-run
      
  3. CORS Issues:

    • Symptom: Discourse redirects fail silently.
    • Fix: Ensure Discourse’s sso_secret and sso_url are correctly configured, and Contao’s trust_proxy is set if behind a proxy.
  4. Contao User Group Permissions:

    • Symptom: Synced users lack Contao backend access.
    • Fix: Manually assign groups or extend the group_mapping to include Contao’s admin group.

Debugging

  • Enable Debug Logging: Add to config/packages/craffft_contao_discourse.yaml:

    craffft_contao_discourse:
        debug: true
    

    Logs appear in var/log/contao_discourse.log.

  • Test SSO Locally: Use ngrok to expose Discourse locally for testing:

    ngrok http 3000  # If Discourse runs on port 3000
    

    Update discourse_url to your ngrok.io subdomain.

Extension Points

  1. Custom User Fields: Extend the UserSynchronizer to map custom Discourse fields (e.g., custom_fields) to Contao user fields:

    public function syncUser($discourseUser, ContaoUser $contaoUser)
    {
        if (isset($discourseUser['custom_fields']['location'])) {
            $contaoUser->address = $discourseUser['custom_fields']['location'];
        }
    }
    
  2. Pre-SSO Hooks: Add logic before SSO (e.g., validate user eligibility):

    // src/EventListener/PreSsoListener.php
    public function onPreSso(PreSsoEvent $event)
    {
        if (!$event->getUser()->isActive) {
            throw new \RuntimeException('User is inactive.');
        }
    }
    

    Register the listener:

    services:
        App\EventListener\PreSsoListener:
            tags: ['kernel.event_listener', 'contao_discourse.pre_sso']
    
  3. Post-Sync Actions: Trigger actions after user sync (e.g., send welcome email):

    // src/EventListener/PostSyncListener.php
    public function onPostSync(PostSyncEvent $event)
    {
        $this->mailer->sendWelcomeEmail($event->getContaoUser());
    }
    

    Register:

    services:
        App\EventListener\PostSyncListener:
            tags: ['kernel.event_listener', 'contao_discourse.post_sync']
    

Configuration Quirks

  • Case Sensitivity: Discourse group names in group_mapping are case-sensitive. Use the exact group name from Discourse’s API (/admin/groups.json).
  • Email Normalization: Ensure Contao and Discourse user emails are normalized (lowercase, trimmed) to avoid sync conflicts. Configure in UserSynchronizer:
    $contaoUser->email = strtolower(trim($discourseUser['email']));
    
  • Rate Limiting: Discourse’s SSO
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity