Külső felhasználó adatbázis használata Drupal 6 alatt

Az előző cikk folytatásaként, most bemutatom, hogyan lehet a Drupal 6 alatt külső adatbázissal végezni a felhasználó autentikációt.

A hook_auth eltünt, helyette a már megszokott hook_form_alter-t kell használnunk, illetve van egy segédfüggvény (nem hook!) amit használhatunk, a user_external_login_register.

A feladatra többféle helyes megoldás adható, én itt a hook_auth funkcionalitását fogom szimulálni. Ahhoz, hogy ezt megtegyük, meg kell ismerni, hogyan áll össze a drupal core felhasználó autentikációja:

Két form létezik, amivel be lehet lépni, a user_login és a user_login_block. Mindkettőnek, három, azaz 3 darab #authenticate metódusa van, ami annyit jelent, hogy mind a három függvény hiba nélkül kell lefusson. Ha valamelyik hibát jelez, akkor a felhasználót nem lehet beengedni.

- user_login_name_validate (modules/user/user.module:1285): azt ellenőrzi, hogy az adott felhasználónév nincs-e tiltólistán.
- user_login_authenticate_validate (modules/user/user.module:1302): azt ellenőrzi, hogy a felhasználónév-jelszó páros benne van-e a users táblában. Ha benne van, akkor létrehozza a $user objektumot a tábla adatainak megfelelően.
- user_login_final_validate (modules/user/user.module:1310): mindössze annyit ellenőriz, hogy $user->uid nem 0-e. Ha 0 hibát jelez.

Ha a felhasználó helyes felhasználónév-jelszó párost adott meg, akkor a user_login_authenticate_validate létrehozza a $user objektumot, és többek között az uid értékét is beállítja. Ekkor a user_login_final_validate nem jelez hibát.

Namármost, ha szimulálni akarjuk a hook_auth működését, annyit kell tennünk, hogy a user_login_finval_validate metódus elé beteszünk még egy másik authenticate metódust, ami ellenőrzi a felhasználónév-jelszó párost a külső adatbázis alapján is. Ha mi helyesnek találjuk ezt a párost, akkor létre kell hozni az adatbázisban a felhasználót, és be kell léptetni. Hogy ne kelljen kézzel matatni a users táblában, a Drupal ad egy függvényt nekünk ami hajszál pontosan ezt csinálja. Ez a függvény a user_external_login_register. Mindössze két paramétere van, az egyik a felhasználónév, a másik a modul név ami beengedte a user-t.

Ezek után nem marad más hátra, mint a kód:

<?php
function abcauth_form_alter(&$form, $form_state, $form_id) {
  global
$user;
  if (
$form_id == 'user_login' or $form_id == 'user_login_block') {
   
$form['#validate'] = array (
     
0 => 'user_login_name_validate',
     
1 => 'abcauth_validate',
     
2 => 'user_login_authenticate_validate',
     
3 => 'user_login_final_validate',
    );
  }
}

function
abcauth_validate ($form, &$form_state) {
  global
$abcauth_new_user;
 
// ide jön a valódi autentikáció
 
if ($form_state['values']['pass'] == 'abc') {
   
user_external_login_register($form_state['values']['name'], 'abcauth');
   
$abcauth_new_user = array(
     
'name' => $form_state['values']['name'],
     
'pass' => 'abc',
     
'mail' => 'abc@example.com',
    );
  }
  else {
   
$abcauth_new_user = FALSE;
  }
}

function
abcauth_user($op, &$edit, &$account, $category = NULL) {
  global
$abcauth_new_user;
  switch(
$op) {
    case
'insert':
      if (
$abcauth_new_user !== FALSE) {
       
db_query(
         
"UPDATE {users} SET mail = '%s', pass = '-' WHERE uid = %d",
         
$abcauth_new_user['email'],
         
$account->uid
       
);
      }
      break;
  }
}
?>

Említettem, hogy Drupal 6 alatt is vannak hibák. Szerencsére itt nem mindig. A fenti megoldás a profile module bekapcsolt állapotban, sajnos nem fér meg egymás mellet. SQL és egyéb szörnyű hibákat generál. Erre még nem találtam megoldást, ha találok akkor frissítem a post-ot (ha nem felejtem el).