Jak na FB login na vlastní stránky

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
xciza
Člen | 194
+
0
-

Ahoj,
chtěl bych se pokusit o fb login na své stránky, ale co jsem tak koukal tak není žádný návod – možná jsem koukal špatně. Proto se ptám, najdu někde nějakou zmínku či alespoň částečný návod jak zprovoznit FB login na nový verzi nette?

Díky

jiri.pudil
Nette Blogger | 1032
+
0
-

Díval ses na Kdyby/Facebook?

xciza
Člen | 194
+
0
-

no moc chytry z toho nejsem

one-two
Člen | 80
+
0
-

Možná si přehlédl přímo dokumentaci

xciza
Člen | 194
+
0
-

jop, díky, kouknu na to. Jen ještě dotaz: Je možné mít zároveň jak přihlašování přes fb tak klasicky emailem? Co je pro to potřeba udělat?

Dík

David Matějka
Moderator | 6445
+
0
-

@xciza: ten example u kdyby/facebook ani nijak nepouziva vlastni authenticator, rovnou nastavuje identitu, tudiz tvuj authenticator s emailem by mel i nadale fungovat bez problemu

xciza
Člen | 194
+
0
-

Tak se zkousim vydat vlastni cestou ale narazil jsem na mensi problem. Stahl jsem is SDK od facebooku a ulozil ji do libs. v configu jsem si nadefinal appid a secret a v services dal facebook:

Facebook( {appId: %facebook.appId%, secret: %facebook.secret%} )

ale laděnka mě vypiše že třídu nenašla. Musim ji ještě nekde specialně registrovat tu třídu? je v:

libs
 -Facebook
    -src
       -facebook.php

díky

xciza
Člen | 194
+
0
-

Nikdo neporadi? :( Vim ze to asi blbej dotaz ale mějte pls trpělivost.

Díky

David Matějka
Moderator | 6445
+
0
-

pokud neco instalujes jinak pres composer, tak na to musi videt robot loader. to, kam vidi, si nastavis v bootstrap.php

Filip Procházka
Moderator | 4668
+
0
-

@xciza měl bys použít Kdyby/Facebook, ušetříš si spoustu práce, ten SDK přímo od facebooku se nemá s Nette moc rád kvůli sessions a taky nemá sexy debug bar panel ;)

xciza
Člen | 194
+
0
-

No asi máš pravdu. Ale skoro nechápu tu instalaci přes ten composer. Mohli by jste trošku poradit?

xciza
Člen | 194
+
0
-

Tak jsem se na to trosku hloubeji podival a nevim jestli to chapu dobre ale v podstate stahnu z github Kdyby/Facebook, hodim to slozky libs a pak v souboru composer.json hodim require: Kdyby/Facebook?

Pavel Macháň
Člen | 282
+
0
-

xciza napsal(a):

Tak jsem se na to trosku hloubeji podival a nevim jestli to chapu dobre ale v podstate stahnu z github Kdyby/Facebook, hodim to slozky libs a pak v souboru composer.json hodim require: Kdyby/Facebook?

do composer.json pridej to require a dej update… kdyby/facebook ti to stahne samo

Filip Procházka
Moderator | 4668
+
0
-

@xciza Naopak, nainstaluješ si composer, do composer.json přidáš do sekce require kdyby/facebook

"require": {
	"nette/nette": "~2.1",
	"kdyby/facebook": "~1.0"
}

Potom pustíš příkaz composer update, který stáhne Kdyby/Facebook do složky vendor/, vygeneruje autoloader a potom pomocí

require_once __DIR__ . '/../vendor/autoload.php';

tento vygenerovaný autoloader vložíš do app/bootstrap.php a díky tomu se bude Nette a Kdyby/Facebook načítat pomocí composeru (respektive autoloaderu který vygeneroval).


Používat composer se opravdu musíš naučit, doplňků a knihoven které bez něj nefungují bude ubývat.

xciza
Člen | 194
+
0
-

Díky. Úspěšně nainstalováno přes composer. v configu zapsano appId a secret. Teď bych to rád zakomponoval do svého SignPresenteru, ale tady se opět ztrácim. Nevím čím přesně začít. V SignPresenteru mám standartní komponetu pro vytvoření přihlašovacího formuláře a jeho zpracování. Pomohl by někdo opět prosím? V dokumentaci sice je nástřel authenticatoru, ale nevím jak to přehodit do toho svého…

Díky

Edit: po zapsání do configu:

facebook:
			appId: '727802710587354'
			secret: string secret

mě laděnka hodi chybu „The Application ID expects to be string, NULL given“ v souboru vendor\kdyby\facebook\src\Kdyby\Facebook\DI\FacebookExtension.php

Nmělo by si to to appId vzit z toho configu?

Editoval xciza (10. 3. 2014 16:14)

xciza
Člen | 194
+
0
-

Tak jsem si na to vytvoril od zakladu novou aplikaci pouze na to abych rozchodil prihlaseni. Prihlaseni pomoci usernam a hesla jde v pohode. Nainstaloval jsem si pomoci composeru kdyby/facebook a do sveho sign presenteru pridal komponetu FbLogin. Teď mám v souboru:

namespace App\Presenters;

use Nette,
    Kdyby\Facebook\Facebook,
    Kdyby\Facebook\Dialog\LoginDialog,
    Kdyby\Facebook\FacebookApiException,
    Nette\Diagnostics\Debugger;

/**
 * Sign in/out presenters.
 */
class SignPresenter extends BasePresenter {

    /** @var Facebook */
    private $facebook;

    public function __construct(Facebook $facebook) {
        parent::__construct();
        $this->facebook = $facebook;
    }

 protected function createComponentFbLogin() {
        $dialog = $this->facebook->createDialog('login');

...
}

ale laděnka mě vyhodí chybu:

No service of type Kdyby\Facebook\Facebook found. Make sure the type hint in App\Presenters\SignPresenter::__construct() is written correctly and service of this type is registered.

Tak nějak nevím co si s touto chybou počít?

David Matějka
Moderator | 6445
+
0
-

asi nemas registrovane extension, viz doc

xciza
Člen | 194
+
0
-

Mám to zapsané v bootsrapu.

Editoval xciza (10. 3. 2014 18:24)

Filip Procházka
Moderator | 4668
+
0
-

@xciza když to dáš do bootstrapu tak musíš cache mazat ručně, kdybys to dal do configu tak by se to překompilovalo samo… Smazal jsi cache?

xciza
Člen | 194
+
0
-

A do které sekce se to v configu musi dat? hledal jsem kam extension vlozit ale nenasel… Jinak cache promazány a další chyba: „The Application ID expects to be string, NULL given.“. Ale v configu mam appId podle dokumentace nastavene…

jiri.pudil
Nette Blogger | 1032
+
0
-

Registrace rozšíření patří do sekce extensions, konfigurace jednotlivých rozšíření do sekcí, které se jmenují stejně jako klíč, pod kterým rozšíření registruješ. Všechny jsou na stejné úrovni jako services, nette, … Tedy nějak takto:

nette:
	# ...

services:
	# ...

extensions:
	facebook: Kdyby\Facebook\DI\FacebookExtension

facebook:
	appId: "..."
	appSecret: ...
xciza
Člen | 194
+
0
-

Díky přehodil jsem to tam. Ale nic to nemění na tom že mám furt chybu: „The Application ID expects to be string, NULL given“ to appId by mělo byt z configu co se tam nastavuje, ne?

Filip Procházka
Moderator | 4668
+
0
-

Takhle to mám já a funguje

extensions:
	facebook: Kdyby\Facebook\DI\FacebookExtension

facebook:
	appId: "12345"
	appSecret: "*****"
	permissions: [email, ...]

Pokud ti to hlásí tu chybu, znamená to že hodnota se do extension nedostala. To může být způsobeno blbou cachí, tím že to píšeš do špatného configu který se třeba ani nenačítá, nebo to píšeš do blbé sekce v tom configu. Nebo neumíš kopírovat z dokumentace a místo appId jsi napsal appid.

Jdi na web http://ne-on.org, zkopíruj do levého textarea svůj config, smázni z toho hesla a hoď sem datovou strukturu jaká z toho vylezla.

Další věc co můžeš udělat je otevřít metodu Kdyby\Facebook\DI\FacebookExtension::loadConfiguration() a dumpnout si co vrací tohle

$config = $this->getConfig($this->defaults); // najdi tenhle řádek
dump($config, $this->getConfig()); exit; // tenhle řádek přidej

Mělo by se ti ukázat jaký config se dostane do extension a to by ti mohlo napovědět co děláš blbě.

xciza
Člen | 194
+
0
-

Tady je datová struktura configu:

array(5) {
   parameters => array(1) {
      facebook => array(2) {
         appId => "12345" (5)
         appSecret => "******" (6)
      }
   }
   php => array(1) {
      "date.timezone" => "Europe/Prague" (13)
   }
   nette => array(2) {
      application => array(2) {
         errorPresenter => "Error" (5)
         mapping => array(1) {
            "*" => "App\*Module\Presenters\*Presenter" (33)
         }
      }
      session => array(1) {
         expiration => "14 days" (7)
      }
   }
   extensions => array(1) {
      facebook => "Kdyby\Facebook\DI\FacebookExtension" (35)
   }
   services => array(3) {
      0 => "App\UserManager" (15)
      1 => "App\RouterFactory" (17)
      router => "@App\RouterFactory::createRouter" (32)
   }
}

tady celý config:

parameters:
	facebook:
		appId: "12345"
		appSecret: "******"


php:
	date.timezone: Europe/Prague
	# zlib.output_compression: yes


nette:
	application:
		errorPresenter: Error
		mapping:
			*: App\*Module\Presenters\*Presenter

	session:
		expiration: 14 days


extensions:
	facebook: Kdyby\Facebook\DI\FacebookExtension


services:
	- App\UserManager
	- App\RouterFactory
	router: @App\RouterFactory::createRouter

a zde dump ze souboru FacebookExtension:

array (9)
appId => NULL
appSecret => NULL
fileUploadSupport => FALSE
trustForwarded => FALSE
clearAllWithLogout => TRUE
domains => array ()
permissions => array ()
canvasBaseUrl => NULL
curlOptions => array (6)
78 => 10
19913 => TRUE
13 => 20
10018 => "facebook-php-3.2" (16)
10023 => array ()
2 => TRUE
array ()

Jestli to z toho dumpu chápu dobře tak se tam config ani nenatáhne. Jak je to možné?

Configy mám dva: config.neon (struktura výše) a config.local.neon kde je pouze pripojení na db

Editoval xciza (11. 3. 2014 7:08)

jiri.pudil
Nette Blogger | 1032
+
0
-

Jak jsem napsal: „všechny [konfigurační sekce] jsou na stejné úrovni jako services, nette, …“ Tedy i facebook má být samostatná sekce (stejně jako extensions), v parameters nemá co dělat.

xciza
Člen | 194
+
0
-

Jo aha, blbe sem to pochopil. Teď za se mám chybu „No service of type Facebook found. Make sure the type hint in App\Presenters\SignPresenter::__construct() is written correctly and service of this type is registered.“

Přeoložit si to umim, ale zaregistrovana je v tom configu ne?

EDIT: Moje chyba-vloudil se me tam spatny znak. po smazani je to ok

Editoval xciza (11. 3. 2014 9:16)

xciza
Člen | 194
+
0
-

Ještě se k tomu zeptám: Co vše je nejlepší ukládat do db a podle čeho nejlépe kontrolovat jestli uživatel již není na stránkách registrován? Později chci implementovat i sdílení příspěvků, které uživatel napíše na webovkách. Proto se ptám co je nejlepší ukládat do db, podle čeho pak příspěvky můžu postnout na zeď uživatele na fb?

jiri.pudil
Nette Blogger | 1032
+
0
-

Určitě si ulož id uživatele, abys ho měl příště jak poznat. A hodit se ti může také access token. Kdyby si ho sice drží v session, ale není od věci mít ho i v databázi pro případ, kdy bys chtěl s Facebookem něco provádět třeba v CLI skriptu.

A co se týče kontroly, jestli uživatel už není registrovaný, nejjednoduššeji a nejpřímočařeji to jde asi podle emailu (musíš si o něj říct v configu v permissions).

xciza
Člen | 194
+
0
-

Díky, tak nějak jsem si to myslel. K tomu budoucímu sdílení příspěvků z webovek na fb je potřeba taky nějaký speciální povolení nebo si vystačim s defaultním?

Filip Procházka
Moderator | 4668
+
0
-

@xciza facebook ve svých best practise říká, že o právo o sdílení si máš říct až jej potřebuješ.

Není od věci si udělat nějakou tabulku user_facebook_permissions, do které si uložíš jednotlivá práva která ti uživatel povolil, bude to taková databázová cache těch oprávnění.

dump($facebook->getProfile()->getPermissions());
  • koukneš jestli máš podle databáze povoleno sdílení
    • A) pokud máš tak pošleš požadavek na sdílení
      • pokud sdílení selže (vyhodí to FacebookApiException) tak B)
    • B) oprávnění nemáš, takže uživatele přesměruješ na facebook s žádostí o povolení oprávnění
      • až se vrátíš, tak si uložíš nový stav oprávnění do databáze, potom A)
piskotek
Člen | 35
+
0
-

ahoj,
zkousim pouzit FB login, ale vyhodilo mi to tuto chybu:

Nette\MemberAccessException

Call to undefined method Nette\DI\ServiceDefinition::setInject()

kdyby/facebook/src/Kdyby/Facebook/DI/FacebookExtension.php:72

64:    //        dump($config, $this->getConfig()); exit;
65:
66:            $configurator = $builder->addDefinition($this->prefix('config'))
67:                ->setClass('Kdyby\Facebook\Configuration')
68:                ->setArguments(array($config['appId'], $config['appSecret']))
69:                ->addSetup('$fileUploadSupport', array($config['fileUploadSupport']))
70:                ->addSetup('$trustForwarded', array($config['trustForwarded']))
71:                ->addSetup('$permissions', array($config['permissions']))
72:                ->setInject(FALSE);

poradite mi nekdo co s tim ?
diky

Tomáš Votruba
Moderator | 1114
+
0
-

Ahoj, tvá verze Nette zřejmě tuto metodu nemá. Jakou verzi Nette používáš?
Doporučuji instalovat přes composer, který se o závislosti postará.

xciza
Člen | 194
+
0
-

Ahoj,
tak jsem si chtěl udělat opět fb login na nových stránkách, šel jsem znovu podle návodu na gitu, upravil metody a po kliknutí v šabloně na odkaz na přihlášení mám tuto chybu:

The signal receiver component 'fbLogin' is not found.

Co bych mohl mít špatně prosím?
Díky

xciza
Člen | 194
+
0
-

Tak tohle jsem vyresil prozatim presunutim vytvoreni componenty FbLogin do BasePresenteru (možnost přihlásit se bude na každé stránce). Ale teď mě to vyhodilo hlášku:

Call to a member function createDialog() on a non-object

na řádek

$dialog = $this->facebook->createDialog('login');

Chápu že se to snaží vytvořit na ne-objektu, ale co upravit?

Děkuju moc

Filip Procházka
Moderator | 4668
+
0
-

Problém je v tom, že se snažíš sahat na property $facebook ve které nic není. Nejspíš do té property budeš muset dostat nějak tu službu.

Takže buďto v čistém Nette takto (pozor, to @var a @inject jsou důležité!).

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	/** @var \Kdyby\Facebook\Facebook @inject */
	public $facebook;

	// potom v createControlFbLogin() už bude naplněná
	// protože nette tam tu třídu dá po vytvoření instance presenteru samo
}

Nebo pomocí Kdyby\Autowired, pokud máš PHP >= 5.4

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	use \Kdyby\Autowired\AutowireProperties;

	/** @var \Kdyby\Facebook\Facebook @autowire */
	protected $facebook;

	// v createControlFbLogin() bude objekt přístupný
	// ovšem jeho instance se díky magii bude vytvářet lazy
}
piskotek
Člen | 35
+
0
-

ahoj, tak mam dalsi problem …

Fatal Error
Using $this when not in object context
67:                    if (! $existing = $this->usersModel->findByFacebookId($fb->getUser())) {
David Matějka
Moderator | 6445
+
0
-

a kde to pouzivas? nemas to v anonymni fci v php 5.3?
kdyztak pouzij

$self = $this;
function() use($self) {
	if(!$existing = $self->usersModel ...)
...

(usersModel pak musi byt public, pripadne si do use rovnou predej ten usersModel)

piskotek
Člen | 35
+
0
-

používám to v SignPresenteru, mám vytvořený úplně nový projekt a mám to udělané dle návodu
nicméně, při přidání $self mi vyskočí chyba:

PDOException #2013

SQLSTATE[HY000] [2013] Lost connection to MySQL server at 'reading initial communication packet', system error: 111

File: …/vendor/nette/database/src/Database/Connection.php:66

66:            $this->pdo = new PDO($this->params[0], $this->params[1], $this->params[2], $this->options);
David Matějka
Moderator | 6445
+
0
-

tohle opravdu nesouvisi s kdyby/facebook, ale s chybou s pripojenim k mysql serveru. Bud mas spatne nastaveny pristupovy udaje nebo si to proste vygoogli.

vosy
Člen | 532
+
0
-

tridu „usersModel“ model jsi mam vytvorit sam? nebo je nekde preddefinovana? Nejaka ukazka?

dix

Tomáš Votruba
Moderator | 1114
+
0
-

@vosy Tu si musíš vytvořit sám. Pracuje s databází, příkladem ti může být UserManager ze sandboxu.

vosy
Člen | 532
+
0
-

oukej, mno nejak sem si to vytvoril. Ted mam problemek ze kdyz se dohlasim pomoci

$this->getUser()->logout();

a nasledne se budu chtit znova prihlasit prez FB tak uz se mi nezobrazi ten puvodni FB formular.

David Matějka
Moderator | 6445
+
+1
-

@vosy a co se stane? nejaka chyba? neprihlasi te to?
nebo jen ze te to prihlasi bez zobrazeni toho okna? jestli tohle tak je to spravne, aplikace je jiz u fb toho uzivatele autorizovana.
Nevim, jestli to jde nejak elegantnejc pro testovani, ale muzes ji odebrat na facebooku a pak se prihlasis znova

vosy
Člen | 532
+
0
-

mno vsechno prave projde automaticky, vse je F poradku, jen sem myslel ze bude lepsi kdyz bude uzivatel zase vedet VOCO jde.

ale dix

luke82
Člen | 12
+
0
-

@vosy, řeším teď stejný problém jak jsi zde nastínil. Když se přihlásím do nette aplikace přes kdyby/facebook, a pak se odhlásím pomocí:

$this->getUser()->logout();

a následně se chci do aplikace přihlásit zase přes facebook, ale již jako jiný uživatel, už mi to nenabídne přihlašovací okno pro facebook. Prostě se přihlásí jako předchozí. Vyřešil jsi to nějak? Díky.

Oli
Člen | 1215
+
0
-

To je ale správně. Odhlaš se z facebooku a zkus se přihlásit pomocí stránky. Nabídne ti to přihlašovací formulář pro fcb, protože fcb neví kdo jsi. Když jsi přihlášen a stránku jsi potvrdil, tak už te fcb nijak neotravuje a rovnou tě přihlásí…

luke82
Člen | 12
+
0
-

Jde mi o to, že když se uživatel přihlásí do nette aplikace přes Facebook login, nemusí mu dojít, že je přihlášen i na Facebooku. Odhlásí se z nette aplikace, ale na Facebooku přihlášen zůstane. Když je uživatel zrovna třeba v internetové kavárně, je to bezpečnostní problém… A když zůstane přihlášen na Facebooku, nette aplikace se už neptá a přihlásí se zase jako předchozí uživatel.

Filip Procházka
Moderator | 4668
+
0
-

@luke82 to na straně tvojí aplikace jen těžko vyřešíš. Maximálně můžeš udělat nějaké okno „nezapomeňte se odhlásit i z facebooku“ potom co se odhlásí od tebe.

David Matějka
Moderator | 6445
+
0
-

Jestli jsem dobre pochopil dokumentaci, tak by odhlaseni v aplikaci by melo odhlasit i uzivatele na fb: https://developers.facebook.com/…ok-login/web#…

Note: This function call will also log the person out of Facebook. The reason for this is that someone may have logged into your app and into Facebook during the login flow. If this is the case, they might not expect to still be logged into Facebook when they log out of your app. To avoid confusing people and to protect personal security, we enforce this logout behavior.