Как сделать динамические поддомены (multiple dynamic firewalls, роутинг и т.д.) в symfony2?

Делаю сервис.
Помимо frontend- и backend-частей есть еще dashboard (у каждой компании свой) со своей авторизацией и прочими плюшками.
Сейчас dashboard открывается по адресу site.com/dashboard/..., firewall один на всех, данные в контроллерах выводятся в зависимости от $company_id = $this->getUser()->getCompany()->getId()
Хочу перенести dashboard на поддомены аля companyname.site.com/...
Настроил nginx так, чтобы все запросы вида companyname.site.com/ шли на site.com/.
Теперь вопросики:
1) Сейчас для тестов прописан вручную 1 firewall для тестовой компании, у которой slug = democompany. Как запилить динамические firewall'ы для всех хостов типа companyname.site.com?
security.yml
security:
  ...
  providers:
    dashboard_user_provider:
      id: acme.dashboard.user_provider
  firewalls:
    ...
    dashboard:
      host: democompany.%domain%
      pattern: ^/
      form_login:
        login_path: /login
        check_path: /login_check
        provider: dashboard_user_provider
        csrf_provider: form.csrf_provider
        default_target_path: /
      logout:
        path: /logout
        target: /
      anonymous: true
      remember_me:
        key:      "%secret%"
        lifetime: 31536000 # 365 days in seconds
        path:     /
        domain:   ~
  access_control:
    ...
    - { host: democompany.%domain%, path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { host: democompany.%domain%, path: ^/, role: [ROLE_DASHBOARD_USER] }

2) Чтобы ограничить выборку данных в пределах текущей компании в каждом контроллере сейчас делаю вот так:
public function listAction($company_slug) {
    if ($company_slug !== $this->getUser()->getCompany()->getSlug()) {
        throw $this->createNotFoundException(sprintf("No data found"));
    }
    
    ...
    ...
}

И ежу понятно, что это говнокод.
На каком уровне делать такие проверки?

Серфинг по гуглу и гитхабу ничего не дал.
Может кто уже делал подобное? Или видел пример?
Спасибо.
  • Вопрос задан
  • 3340 просмотров
Решения вопроса 4
Посмотрите вот здесь knpuniversity.com/screencast/question-answer-day/s... - вроде бы то, что вам надо.
Ответ написан
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Ну... давайте прикинем...

1) в security.yml можно в правилах задавать host (регулярками), если у вас структура ссылок для каждого поддомена дублируется, можно ограничиться общими правилами.
2) можно вынести домен третьего уровня как переменную запроса (ваш slug)
3) можно реализовать свой фаервол/юзер провайдер, который сетит нужную роль пользователю в зависимости от slug и полномочий.
4) если вы хотите вместо 401/403 ошибки отдавать 404-ую, всеравно придется реализовывать обработку ошибок и взависимости от оной менять результат.

Но да, проверять это все в контроллере... ну можно, но стоит хотя бы вынести на уровень выше (обработчик события kernel.request).
Ответ написан
pavel_salauyou
@pavel_salauyou
Symfony2 & Angular разработчик
С субдоменами нужно через роуты работать. Авторизацию делать в контроллёре и там же и проверять пользователей компаний.
Ответ написан
0neS
@0neS Автор вопроса
Вот проблемы, которые мучают меня в настоящий момент:
1) Как на этапе авторизации проверять, принадлежит ли пользователь компании, на поддомене которой он авторизуется?
2) Как лучше ограничить вывод данных по id текущей компании. Делать в каждом контроллере вручную проверку?
3) Как в шаблонах выводить, к примеру, company.name? app.user.company.name? Мне кажется это не самый корректный способ.
4) Как сделать текущую компанию значением по-умолчанию в роутах? Т.е. сейчас же все разруливаю через роуты (host: "{company_slug}.%domain%") и приходится абсолютно в каждом роуте в шаблоне выводить доп. параметром slug текущей компании, типа:
<a href="{{ path("dashboard.user.list", { "company_slug": app.user.company.slug }) }}">Users</a>


Сейчас вынес часть логики в эвентлистнер как пишут здесь: knpuniversity.com/screencast/question-answer-day/s...

public function listAction() {
    $companyManager = $this->container->get('acme.dashboard.company_manager');
    $currentCompany = $companyManager->getCurrentCompany();
    $userManager = $this->container->get('acme.dashboard.user_manager');
    $users = $userManager->findUsersByCompanyId($currentCompany->getId());

    return [
        'company' => $currentCompany,
        'users' => $users,
    ];
}

Но, помоему, это все еще не предел мечтаний.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы