Autorisation avec Pundit

Pundit est un outil qui vous permet de limiter certaines parties de votre application Rails aux utilisateurs autorisés. Il le fait en vous fournissant certains assistants.

Dans ce didacticiel, vous allez créer un blog qui restreint certaines parties, telles que la création, la mise à jour et la suppression d'articles, aux seuls utilisateurs autorisés..

Commencer

Commencez par générer une nouvelle application Rails.

rails nouveau pundit-blog -T

le -T flag indique à Rails de générer la nouvelle application sans la suite de tests par défaut. L'exécution de la commande va générer votre application Rails et installer les gems par défaut..

Allez-y et ajoutez les gemmes suivantes à votre Gemfile. Vous utiliserez bootstrap-sass pour la présentation de votre application et Devise se chargera de l'authentification de l'utilisateur..

# Gemfile… gem 'bootstrap-sass' gem 'devise'

Exécutez la commande pour installer le gem.

installation groupée

Maintenant renommer app / assets / stylesheets / application.css à app / assets / stylesheets / application.scss. Ajouter les lignes de code suivantes pour importer bootstrap.

# app / assets / stylesheets / application.scss… @import 'bootstrap-sprockets'; @import 'bootstrap';

Créer un partiel nommé _navigation.html.erb contenir votre code de navigation; le partiel doit être situé dans app / vues / mises en page annuaire. Faites en sorte que le partiel ressemble à ce que j'ai en dessous.

# app / views / layouts / _navigation.html.erb 

Pour que la navigation soit utilisée, vous devez la rendre dans la présentation de votre application. Tweak votre mise en page de l'application pour ressembler à ce que j'ai en dessous.

# app / views / layouts / application.html.erb    Blog de Pundit <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>   <%= render "layouts/navigation" %> 
<% flash.each do |key, value| %>
<%= value %>
<% end %>
<%= yield %>

Générer le modèle d'utilisateur

Exécutez la commande pour installer Devise.

les rails génèrent un montage: installer

Maintenant, générez votre modèle d'utilisateur.

les rails génèrent un utilisateur

Migrer votre base de données.

rake db: migrer

Générer des ressources d'article

Exécutez la commande pour générer vos ressources Article..

rails générer échafaudage Titre de l'article: string body: text

Cela va générer votre ArticlesContrôleur et modèle d'article. Il générera également les vues nécessaires.

Maintenant, migrez votre base de données en exécutant:

rake db: migrer

S'ouvrir app / views / articles / _form.html.erb et le faire ressembler à ce que j'ai ci-dessous.

# app / views / articles / _form.html.erb <%= form_for(article) do |f| %> <% if article.errors.any? %> 

<%= pluralize(article.errors.count, "error") %> a interdit cet article d'être sauvé:

    <% article.errors.full_messages.each do |message| %>
  • <%= message %>
  • <% end %>
<% end %>
<%= f.label :title %> <%= f.text_field :title %>
<%= f.label :body %> <%= f.text_area :body %>
<%= f.submit %>
<% end %>

Pour votre fichier d'index, ça devrait ressembler à ça.

# app / views / articles / index.html.erb  <% @articles.each do |article| %>  <% end %> 
Titre Corps
<%= article.title %> <%= article.body %> <%= link_to 'Show', article %> <%= link_to 'Edit', edit_article_path(article) %> <%= link_to 'Destroy', article, method: :delete, data: confirm: 'Are you sure?' %>

<%= link_to 'New article', new_article_path %>

Le code ci-dessus organise les articles sur la page d'index dans un format de tableau pour lui donner un aspect présentable..

Ouvrez votre fichier de routes et ajoutez la route pour les ressources articles.

# config / routes.rb… ressources: articles racine à: "articles # index"

Intégrer Pundit

Ajoutez le joyau Pundit à votre Gemfile.

# Gemfile… gem 'pundit'

Exécutez la commande pour installer.

installation groupée

Intégrez Pundit à votre application en ajoutant la ligne suivante à votre ApplicationController.

# app / controllers / application_controller.rb… incluez Pundit… 

Lancer le générateur de Pundit.

rails g pundit: installer

Cela générera un dossier app / policies contenant une classe de base avec des stratégies. Chaque politique est une classe de base Ruby.

Voici à quoi ressemble la stratégie de classe de base.

# app / policies / application_policy.rb classe ApplicationPolicy attr_reader: utilisateur,: record def initialize (utilisateur, record) @user = utilisateur @record = record end def index? fausse fin def show? scope.where (: id => record.id) .exists? fin de créer? faux fin def new? créer? mettre fin à la mise à jour? false end def edit? mettre à jour? End def détruire? false end def scope Pundit.policy_scope! (utilisateur, record.class) end classe Scope attr_reader: utilisateur,: portée def initialiser (utilisateur, portée) @user = utilisateur @scope = fin de la portée résolution fin de la portée fin fin

Créer la politique d'article

Maintenant, vous devez écrire votre propre politique. Pour ce tutoriel, vous souhaitez autoriser uniquement les utilisateurs enregistrés à créer de nouveaux articles. De plus, seuls les créateurs d'un article devraient pouvoir modifier et supprimer l'article..

Pour ce faire, votre politique d'article ressemblera à ceci.

# app / policies / article_policy.rb class ArticlePolicy < ApplicationPolicy def index? true end def create? user.present? end def update? return true if user.present? && user == article.user end def destroy? return true if user.present? && user == article.user end private def article record end end

Dans ce qui précède, vous autorisez tout le monde (utilisateurs enregistrés et non enregistrés) à voir la page d'index. Pour créer un nouvel article, un utilisateur doit être enregistré. Tu utilises user.present? savoir si l'utilisateur qui tente d'effectuer l'action est enregistré.

Pour mettre à jour et supprimer, vous voulez vous assurer que seul l'utilisateur qui a créé l'article est capable d'effectuer ces actions.

À ce stade, vous devez établir une relation entre votre modèle d'article et votre modèle d'utilisateur..

Vous le faites en générant une nouvelle migration.

les rails génèrent la migration add_user_id_to_articles utilisateur: références

Ensuite, migrez votre base de données en exécutant la commande suivante:

rake db: migrer

Ouvrez le modèle utilisateur et ajoutez la ligne qui scelle la relation.

# app / models / user.rb… has_many: articles

Votre modèle d'article devrait avoir ceci.

# app / models / article.rb… appartient_to: utilisateur

Maintenant, vous devez mettre à jour votre ArticlesContrôleur il est donc en phase avec ce que vous avez fait jusqu'à présent.

Classe # app / controllers / articles_controller.rb ArticlesController < ApplicationController before_action :set_article, only: [:show, :edit, :update, :destroy] # GET /articles # GET /articles.json def index @articles = Article.all authorize @articles end # GET /articles/1 # GET /articles/1.json def show end # GET /articles/new def new @article = Article.new authorize @article end # GET /articles/1/edit def edit end # POST /articles # POST /articles.json def create @article = Article.new(article_params) @article.user = current_user authorize @article respond_to do |format| if @article.save format.html  redirect_to @article, notice: 'Article was successfully created.'  format.json  render :show, status: :created, location: @article  else format.html  render :new  format.json  render json: @article.errors, status: :unprocessable_entity  end end end # PATCH/PUT /articles/1 # PATCH/PUT /articles/1.json def update respond_to do |format| if @article.update(article_params) format.html  redirect_to @article, notice: 'Article was successfully updated.'  format.json  render :show, status: :ok, location: @article  else format.html  render :edit  format.json  render json: @article.errors, status: :unprocessable_entity  end end end # DELETE /articles/1 # DELETE /articles/1.json def destroy @article.destroy respond_to do |format| format.html  redirect_to articles_url, notice: 'Article was successfully destroyed.'  format.json  head :no_content  end end private # Use callbacks to share common setup or constraints between actions. def set_article @article = Article.find(params[:id]) authorize @article end # Never trust parameters from the scary internet, only allow the white list through. def article_params params.require(:article).permit(:title, :body, :user_id) end end

À ce stade de votre application, vous avez mis en œuvre avec succès les stratégies qui limitent certaines parties de votre application aux utilisateurs sélectionnés..

Vous souhaitez ajouter un message d'erreur standard qui s'affiche chaque fois qu'un utilisateur non autorisé tente d'accéder à une page restreinte. Pour ce faire, ajoutez ce qui suit à votre ApplicationController.

# app / controllers / application_controller.rb… rescue_from Pundit :: NotAuthorizedError, avec:: user_not_authorized private def user_not_authorized flash [: warning] = "Vous n'êtes pas autorisé à effectuer cette action." redirect_to (request.referrer || root_path) fin

Ce code affiche simplement un texte de base indiquant à l'utilisateur qu'il n'est pas autorisé à effectuer l'action..

Courir:

serveur $ rails

Pour démarrer votre serveur Rails, pointez votre navigateur sur http: // localhost: 3000 pour voir ce que tu as.

Conclusion

Dans ce tutoriel, vous avez appris à travailler avec Devise et Pundit. Vous avez pu créer des stratégies autorisant uniquement les utilisateurs autorisés à afficher certaines parties de l'application. Vous avez également créé un texte d'erreur de base indiquant lorsqu'un utilisateur non autorisé tente d'accéder à une partie restreinte de l'application..

Vous pouvez en apprendre plus sur Pundit en consultant la page GitHub.