Статьи

Простая CMS в Синатре, часть III

Во второй части этой серии руководств мы закончили создание основ нашей простой системы управления контентом. Теперь можно создавать, редактировать и удалять страницы с красивыми URL-адресами.

В этом посте мы рассмотрим добавление раздела «Администрирование» и определение того, какие страницы являются общедоступными, а какие — частными.

Вход и выход

Прежде всего, мы добавим некоторые функциональные возможности, позволяющие пользователю входить и выходить из системы. Для этого нам нужно настроить наше приложение на использование сессий. Измените блок конфигурации в верхней части main.rb на следующий:

configure do Mongoid.load!("./mongoid.yml") enable :sessions end 

Теперь мы можем получить доступ к хешу сеанса, чтобы отслеживать, вошел ли пользователь в систему от запроса к запросу.

Далее мы создадим вспомогательный метод с именем admin? это true если хеш для session[:admin] имеет значение true (это будет установлено как true когда пользователь входит в систему, и устанавливается равным nil когда пользователь выходит из системы). Добавьте следующую строку под блоком configure в main.rb :

 helpers do def admin? session[:admin] end end 

Теперь у нас есть удобный способ проверить, вошел ли пользователь в представления или обработчики маршрутов. Давайте использовать это, чтобы добавить кнопку входа в наше приложение.

Мы хотим, чтобы это было на каждой странице, поэтому измените файл layout.slim в папке views следующим образом:

 doctype html html head title= @title || "Simple Sinatra CMS" link rel="stylesheet" href="/styles/main.css" body - if admin? == slim :admin - else a.rounded.button href="/login" Log In h1.logo a href="/pages" Simple Sinatra CMS == yield 

Раздел после тела теперь проверяет, вошел ли пользователь в систему (проверяя, является ли true только что созданный нами метод admin? Helper). Если они есть, то мы покажем частичное представление администратора (мы создадим это через минуту).

Если пользователь не вошел в систему, то отображается ссылка, позволяющая ему войти в систему. Эта ссылка содержит классы .rounded.button которые мы создали в последнем руководстве, поэтому она отображается в виде кнопки. Он также содержит маршрут /login , который мы рассмотрим в ближайшее время.

Давайте получить вид админ отсортирован — сохранить следующий код в admin.slim в папке просмотров:

 #admin nav ul li a.round.button href='/pages' Pages li a.round.button href='/pages/new' Add a page - if @page li a.round.button href="/pages/#{@page.id}/edit" Edit this page li a.round.button href="/pages/delete/#{@page.id}" Delete this page a.rounded.button href="/logout" Log Out 

Это добавляет кнопку «Создать новую страницу», а также кнопки для редактирования и удаления, которые отображаются, только если вы смотрите на фактическую страницу. Эти кнопки должны быть доступны только в том случае, если пользователь вошел в систему. В предыдущей версии нашего приложения они были размещены в других представлениях, поэтому мы должны удалить их сейчас и ограничить их только представлением администратора.

В index.slim удалите следующую строку кода:

 a.button.round href='/pages/new' Add a new page 

Теперь в show.slim удалите следующий код:

 a.button href="/pages/#{@page.id}/edit" Edit a.button href="/pages/delete/#{@page.id}" Delete 

Чтобы закончить, нам нужно создать фактические обработчики маршрутов, которые используются для входа и выхода пользователя. Добавьте следующие строки над обработчиками маршрута страницы в main.rb :

 get('/login'){session[:admin]=true; redirect back} get('/logout'){session[:admin]=nil; redirect back} 

Эти обработчики маршрута устанавливают для хеша session[:admin] значение true когда пользователь входит в систему, и значение nil когда пользователь выходит из системы, посещая соответствующий URL-адрес. Эта информация сохраняется в хэше сеанса с использованием файлов cookie, а затем используется admin? вспомогательный метод, который мы только что создали, чтобы проверить, вошел ли пользователь в систему или нет. Оба обработчика маршрута также используют удобный вспомогательный метод back который предоставляет Sinatra. Это вернет пользователя на любую страницу, которую он просматривал, прежде чем он вошел в систему или вышел из нее.

Теперь все должно работать. Убедитесь, что сервер запущен, а затем перейдите по адресу http: // localhost: 4567 / pages и поиграйте в него при входе и выходе. Вы должны видеть только кнопки для добавления, редактирования и удаления страниц, если вы вошли в систему.

Screenshot5

Самая небезопасная безопасность?

Глазастые из вас, возможно, заметили, что эта система аутентификации не особенно надежна — даже пароля нет! Это потому, что наличие строгой процедуры авторизации является важным делом и выходит за рамки данного руководства. То, что мы сделали здесь, это поместили кусочки на место так, чтобы подходящее решение для аутентификации могло быть затем запечено в соответствующих местах.

Возможно, вы захотите взглянуть на драгоценный камень sinatra-auth (или один из множества других драгоценных камней, обеспечивающих аутентификацию). Вы можете использовать Twitter Authentication или вы можете использовать собственное решение.

Для целей этого руководства я просто хотел продемонстрировать, как приложение будет работать по-разному в зависимости от того, вошел ли пользователь в систему или нет.

Защита функций администратора

В нашем приложении есть несколько маршрутов, к которым мы не хотим, чтобы все пользователи обращались. Фактически, большинство маршрутов подпадают под эту категорию, мы хотим, чтобы URL-адреса показа были видны всем.

Мы успешно скрыли кнопки, которые ссылаются на маршруты администратора, но это не может помешать определенному или любопытному пользователю просто ввести URL-адреса непосредственно в адресную строку браузера. Например, вы можете просто перейти к «http: // localhost: 4567 / pages / new», чтобы добавить новую страницу.

Нам нужно добавить некоторую защиту самим маршрутам, чтобы фактически позволить пользователям получать доступ к этим маршрутам, только если они вошли в систему. Это делается путем создания protected! вспомогательный метод.

Добавьте следующий метод в блок helpers который мы создали ранее:

 def protected! halt 401,"You are not authorized to see this page!" unless admin? end 

При этом используется вспомогательный метод остановки Sinatra, чтобы остановить запрос в его дорожках и выдать 401 «неавторизованную» ошибку с пользовательским сообщением (это может быть строка или вы можете создать представление для нее). Обратите внимание, что мы используем admin? вспомогательный метод, который мы создали в начале этого урока, чтобы проверить, вошел ли пользователь в систему, поэтому запрос будет остановлен, только если пользователь НЕ вошел в систему.

Теперь этот метод необходимо добавить ко всем обработчикам маршрутов, которые мы хотим защитить. Это означает, что нам нужно изменить многие наши обработчики маршрутов на следующие:

 get '/pages/new' do protected! @page = Page.new slim :new end post '/pages' do protected! page = Page.create(params[:page]) redirect to("/pages/#{page.id}") end put '/pages/:id' do protected! page = Page.find(params[:id]) page.update_attributes(params[:page]) redirect to("/pages/#{page.id}") end get '/pages/delete/:id' do protected! @page = Page.find(params[:id]) slim :delete end delete '/pages/:id' do protected! Page.find(params[:id]).destroy redirect to('/pages') end get '/pages/:id/edit' do protected! @page = Page.find(params[:id]) slim :edit end 

Теперь ни один из этих маршрутов не будет доступен для любых пользователей, которые не вошли в систему, даже если они вводят маршрут непосредственно в браузер.

Разные URL для разных пользователей

В последнем посте мы создали красивые URL-адреса, основанные на заголовке страницы. Это те URL-адреса, которые мы хотели бы использовать для большинства пользователей — они выглядят лучше, и мы не хотим, чтобы они видели идентификаторы каждой страницы, отображаемой в URL-адресе.

Однако, когда пользователь вошел в систему, мы хотим использовать URL-адрес, который ссылается на идентификатор страницы. Для этого нам нужно добавить помощник url наш блок помощников в main.rb :

 def url_for page if admin? "/pages/" + page.id else "/" + page.permalink end end 

Это в основном использует блок if ... else чтобы проверить, вошел ли пользователь, используя нашего admin? помощник. Если пользователь вошел в систему, тогда URL будет использовать идентификатор страницы, в противном случае он будет использовать красивый URL страницы.

Теперь мы можем просто использовать этого помощника всякий раз, когда мы хотим дать ссылку на страницу, будучи уверенными, что будет отображаться правильный URL. Кроме того, если мы хотим изменить структуру имен для URL-адресов страниц, мы должны сделать это только в одном месте.

Единственное место, где мы в настоящее время ссылаемся на страницы, — это частичная страница, поэтому нам нужно изменить представление page.slim на следующее:

 li a href="#{url_for page}" =page.title 

Добавить стиль

Чтобы закончить, мы можем сделать список кнопок в разделе администратора в виде горизонтального списка, добавив следующий фрагмент кода Sass внизу styles.scss :

 #admin ul{ list-style: none; margin: 0; padding: 0; li{ display: inline-block; } } 

Теперь перезапустите сервер и поэкспериментируйте с различными функциями — проверьте, что ссылки различаются в зависимости от того, вошли вы в систему или нет.

Screenshot6

Это все люди!

В этом посте мы добавили раздел администрирования в нашу систему управления контентом, хотя, возможно, и с наименее безопасной системой аутентификации.

Несмотря на отсутствие безопасности, возможность входа пользователей позволила нам разделить различные представления и функциональные возможности приложения. В следующем посте мы рассмотрим, как кэшировать страницы, а также добавлять временные метки и версии для страниц.

Пожалуйста, оставьте любые комментарии ниже, а также любые запросы о том, как бы вы хотели, чтобы эта CMS развивалась.