Ural penguins - Сообщения с тегом jinja
http://uralbash.ru/blog/tag/jinja/atom.xml
2011-10-26T23:35:00Z
ABlog
Авторизация в Pylons за 5 мин при помощи repoze.what
http://uralbash.ru/articles/2011/repoze.what/
2011-10-26T23:35:00Z
2011-10-26T23:35:00Z
Uralbash
<div class="section" id="pylons-5-repoze-what">
<span id="repoze-what"></span>
<p>Статья по сути вольный перевод <a class="reference external" href="http://countergram.com/open-source/PylonsTemplates">PylonsTemplates: extra Paster templates for
Pylons apps</a> с моими
дополнениями.</p>
<p><a class="reference external" href="https://github.com/countergram/PylonsTemplates/">PylonsTemplates</a> дает вам дополнительные шаблоны в paster для приложений на
<a class="reference external" href="http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/">Pylons</a>. После установки <a class="reference external" href="https://github.com/countergram/PylonsTemplates/">PylonsTemplates</a> можно создать новый проект на
<a class="reference external" href="http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/">Pylons</a> примерно так:</p>
<div class="highlight-bash"><div class="highlight"><pre><span></span>$ paster create -t <span class="o">[</span>templatename<span class="o">]</span> <span class="o">[</span>projectname<span class="o">]</span>
</pre></div>
</div>
<div class="section" id="pylons-repoze-what">
<h2>pylons_repoze_what</h2>
<p>Шаблон <code class="docutils literal"><span class="pre">pylons_repoze_what</span></code> добавляет систему авторизации основанную на
<a class="reference external" href="http://what.repoze.org/docs/1.0/index.html#module-repoze.what" title="(в repoze.what v1.0)"><code class="xref py py-mod docutils literal"><span class="pre">repoze.what</span></code></a> и <code class="xref py py-mod docutils literal"><span class="pre">repoze.what.plugins.quickstart</span></code>. (При этом аутентификация на
<a class="reference external" href="https://repoze.readthedocs.io/projects/repozewho/en/latest/index.html#module-repoze.who" title="(в repoze.who v2.2)"><code class="xref py py-mod docutils literal"><span class="pre">repoze.who</span></code></a> устанавливается автоматически.)</p>
<p>Шаблон включает в себя:</p>
<ul class="simple">
<li>Модели <code class="docutils literal"><span class="pre">User</span></code>, <code class="docutils literal"><span class="pre">Group</span></code> и <code class="docutils literal"><span class="pre">Permission</span></code> для <a class="reference external" href="http://sqlalchemy.org/">SQLALchemy</a></li>
<li>Контроллер login (& logout)</li>
<li>Простой шаблон для входа</li>
<li>Зависимость от <code class="xref py py-mod docutils literal"><span class="pre">repoze.what.plugins.pylonshq</span></code>, включающая декораторы которые можно
использовать в контроллерах и действиях (action).</li>
<li>Закоментированный код в websetup.py который создает user, group и permission.</li>
</ul>
<p>Список всех шаблонов:</p>
<div class="highlight-bash"><div class="highlight"><pre><span></span>paster create --list-templates
</pre></div>
</div>
<p>Создание проекта:</p>
<div class="highlight-bash"><div class="highlight"><pre><span></span>paster create -t pylons_repoze_what myapp
</pre></div>
</div>
</div>
<div class="section" id="repoze-what-pylons">
<h2>Пример с repoze.what-pylons</h2>
<p>После создания проекта используя <code class="docutils literal"><span class="pre">paster</span> <span class="pre">create</span> <span class="pre">-t</span> <span class="pre">pylons_repoze_what</span></code>, вам нужно
защитить контроллеры и их действия от несанкционированного доступа. Ниже
простой пример:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">repoze.what.predicates</span> <span class="kn">import</span> <span class="n">has_permission</span>
<span class="kn">from</span> <span class="nn">repoze.what.plugins.pylonshq</span> <span class="kn">import</span> <span class="n">ActionProtector</span>
<span class="k">class</span> <span class="nc">HelloWorldController</span><span class="p">(</span><span class="n">BaseController</span><span class="p">):</span>
<span class="nd">@ActionProtector</span><span class="p">(</span><span class="n">has_permission</span><span class="p">(</span><span class="s1">'be_cool'</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s1">'Hello World'</span>
</pre></div>
</div>
<p>Здесь запрещен доступ к действию <code class="docutils literal"><span class="pre">index</span></code> всем у кого нет прав <code class="docutils literal"><span class="pre">be_cool</span></code>. Что бы
запретить весь контроллер есть декоратор
<code class="xref py py-class docutils literal"><span class="pre">repoze.what.plugins.pylonshq.protectors.ControllerProtector</span></code>. Более
подробно об этом можно почитать в документации на <code class="xref py py-mod docutils literal"><span class="pre">repoze.what.plugins.pylonshq</span></code>.</p>
<p>У меня в шаблонах отображается постоянно кто сейчас залогирован.
Что бы это сделать, создадим <code class="docutils literal"><span class="pre">lib/auth.py</span></code></p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pylons</span> <span class="kn">import</span> <span class="n">request</span>
<span class="k">def</span> <span class="nf">get_user</span><span class="p">(</span><span class="n">default</span><span class="p">):</span>
<span class="sd">"""Return the user object from the `repoze.who` Metadata Plugin</span>
<span class="sd"> :param default: default item to send back if user not logged in</span>
<span class="sd"> Since we might not be logged in and template choke on trying to output</span>
<span class="sd"> None/empty data we can pass in a blank User object to get back as a default</span>
<span class="sd"> and the templates should work ok with default empty values on that</span>
<span class="sd"> """</span>
<span class="k">if</span> <span class="s1">'repoze.who.identity'</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="p">:</span>
<span class="k">return</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s1">'repoze.who.identity'</span><span class="p">][</span><span class="s1">'user'</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">default</span>
</pre></div>
</div>
<p>И добавим контекстную переменную во все контроллеры при помощи <code class="docutils literal"><span class="pre">lib/base.py</span></code></p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">gottlieb.model.auth</span> <span class="kn">import</span> <span class="n">User</span>
<span class="kn">from</span> <span class="nn">gottlieb.lib</span> <span class="kn">import</span> <span class="n">auth</span>
<span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="sd">"""Invoke the Controller"""</span>
<span class="c1"># WSGIController.__call__ dispatches to the Controller method</span>
<span class="c1"># the request is routed to. This routing information is</span>
<span class="c1"># available in environ['pylons.routes_dict']</span>
<span class="c1"># if there's no user set, just setup a blank instance</span>
<span class="n">c</span><span class="o">.</span><span class="n">current_user</span> <span class="o">=</span> <span class="n">auth</span><span class="o">.</span><span class="n">get_user</span><span class="p">(</span><span class="n">User</span><span class="p">())</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">WSGIController</span><span class="o">.</span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="n">meta</span><span class="o">.</span><span class="n">Session</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
</pre></div>
</div>
<p>Теперь можно в шаблоны вставлять что то вроде того (примеры на <a class="reference external" href="http://jinja.pocoo.org/">Jinja</a>):</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"userBox"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">c.current_user.user_name</span> <span class="cp">%}</span>
<span class="cp">{{</span> <span class="nv">c.current_user.user_name</span> <span class="cp">}}</span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"/logout"</span><span class="p">></span>(logout)<span class="p"></</span><span class="nt">a</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">else</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"/login"</span><span class="p">></span>login<span class="p"></</span><span class="nt">a</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
</div>
<p>или</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">for</span> <span class="nv">group</span> <span class="k">in</span> <span class="nv">c.current_user.groups</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">group.group_name</span> <span class="o">==</span> <span class="s1">'admin'</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"/admin"</span> <span class="na">target</span><span class="o">=</span><span class="s">"_self"</span><span class="p">></span>Admin<span class="p"></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div>
</div>
<div class="figure align-center" id="id1">
<img alt="_static/2011/header_login_logout.png" src="_static/2011/header_login_logout.png" />
<p class="caption"><span class="caption-text">отображение залогированного пользователя</span></p>
</div>
<div class="figure align-center" id="id2">
<img alt="_static/2011/login_form.png" src="_static/2011/login_form.png" />
<p class="caption"><span class="caption-text">форма авторизации</span></p>
</div>
</div>
</div>