لمحة بسيطة عن devise
devise هو أحد أشهر الجزم البرمجية(gem) التي تقدم حل متكامل للمصادقة(Authentication) ضمن تطبيقات Rails. إن أبرز ما يميز devise هو سهولة استخدام(عدة تعليمات برمجية ويتم تثبيته ضمن تطيق Rails وتشغيله) والدعم الكبير من قبل المجتمع الضخم من المطوريين الذي لا يزال يقدم تطويرات وإضافات مفيدة بشكل متزايد.
يتكون devise من 10 وحدات(module) يمكنك من اختيار الضروري منها وفقا للحاجة التي تريدها ضمن تطبيقك، أذكرها باختصار مع وظيفة كل منها:
- Registrable تسمح هذه الوحدة للمستخدمين بتسجيل حسابات جديدة وتعديلها وحذفها فما بعد.
- Database Authenticatable تخزين وتشفير معلومات المستخدمين في قاعدة البيانات والتحقق منها عند دخول المستخدم الى التطبيق.
- Omniauthable تقوم هذه الوحدة بإضافة نظام Omniauth والذي يسمح للمستخدم بالدخول الى تطبيقات rails بإستخدام بيانات دخوله في مواقع أخرى مثلا تويتر - فيسبوك - جووجل وغيرها .
- Confirmable إرسال بريد الى المستخدم بعد تسجيله مباشرة يحتوي على معلومات تفعيل الحساب.
- Recoverable إعادة تعيين كلمة المرور وإسترجاعها وذلك بإرسال بريد للمستخدم.
- Rememberable إدارة عملية حفظ ومسح معلومات المستخدم من على الجهاز بإستخدام saved cookie .
- Trackable تسمح هذه الوحدة بمعرفة عدد مرات وعنوان ip address و تاريخ و وقت الدخول.
- Timeoutable إنهاء الجلسة session عندما لا يكون هناك أي نشاط للمشتخدم خلال مدة زمنية محددة.
- Validatable تعمل هذه الوحدة على تطبيق شروط Validations على حقل البريد الالكتروني وكلمة المرور التي يدخلها المستخدم.
- Lockable تعمل هذه الوحدة على إيقاف حساب المستخدم بعد عدة محاولات دخول فاشلة.
تثبيت devise ضمن تطبيق Rails
لنقم أولا بإنشاء تطبيق Rails جديد باسم devise_demo
$ rails new devise_demo
بعد تنفيذ الأمر السابق وإنشاء مجموعة الملفات والمجلدات الخاصة بالتطبيق، أدخل إلى مسار التطبيق
$ cd devise_demo
واستعرض ملف Gemfile
,أضف إليه الجيم devise
gem 'devise'
وبعدها نفذ الأمر التالي
$ bundle install
Bundler هو برنامج لإدارة الحزم البرمجية Gem في مشاريع روبي. تستطيع من خلاله تحديد الحزم التي يحتاجها مشروعك ،مع تعين اصدار معين لكل حزمة في ملف واحد يسمى
Gemfile
وتنصيبها في وقت واحد عن طريق تعليمةbundle install
، دون الحاجة لاستخدام تعليمة gem لتنصيب كل حزمة على حدا
بعد الانتهاء من تثبيت الحزم الموجودة ضمن ملف Gemfile عبر تعليمة bundle
، نفذ الأمر التالي لتوليد الملفات الرئيسية لعمل devise ضمن التطبيق
$ rails generate devise:install
نتيجة تنفيذ التعليمة السابقة ستكون كالتالي:
create config/initializers/devise.rb
create config/locales/devise.en.yml
Some setup you must do manually if you haven't yet:
1. Ensure you have defined default url options in your environments files. Here
is an example of default_url_options appropriate for a development environment
in config/environments/development.rb:
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
In production, :host should be set to the actual host of your application.
2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:
root to: "home#index"
3. Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:
config.assets.initialize_on_precompile = false
On config/application.rb forcing your application to not access the DB
or load models when precompiling your assets.
5. You can copy Devise views (for customization) to your app by running:
rails g devise:views
نلاحظ أن الأمر الأخير قام بإنشاء ملفات خاصة بنظام devise وهي عبارة عن مايلي :
- ملف devise.rb و الموجود على المسار config/initalizers وهو يحتوي على الإعدادت الرئيسية لل devise والتي يتم تطبيقها بدء تشغيل التطبيق.
- ملف devise.en.yml والموجود في المسار config/locals ويحتوي على جميع الرسائل التي تظهر للمستخدمين ويمكن التعديل على هذه الرسائل و إنشاء ملفات أخرى للغات غير الإنجليزية.
أيضا نلاحظ أن هناك رسالة بمجموعة من الإعدادات يجب أن نتآكد من تنفيذها على التطبيق وهي كما يلي
1- إضافة السطر التالي config/environments/development.rb
لتحديد الرابط الافتراضي(default URL) لبيئة التطوير development :
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
2- تحديد المسار root في ملف routes.rb
يتم ذلك عن طريق إنشاء controller باسم page وتحديد action لها باسم index
$ rails g controller page index
ويتم تحديد index كصفحة رئيسية للتطبيق بإضافة التعليمة التالية ضمن ملف config/routes.rb
root "page#index"
3- إضافة الأكواد التالية لإظهار رسائل التنبيه ضمن ملف الرئيسي للتطبيق
app/views/layouts/application.html.erb
:
[...]
<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
[...]
4- الخطوة الرابعة لن نحتاج لها لأن إصدار rails الذي نستخدمه 4 وليس 3.2
وأخيرا إنشاء MODEL ضمن Devise:
$ rails generate devise user
التعليمة السابقة تولد model ضمن المسار app/model/user.rb
ويكون محتواه كالتالي :
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
نلاحظ مما سبق انه من ضمن 10 وحدات فقط 6 تكون مفعلة عند تثبيت devise وهي موضحة ضمن الكود السابق
وتولد أيضا ملف migration ضمن المسار التالي db/migrations/xxx_devise_create_users.rb
الذي يحوي على الأعمدة الضرورية التي يحتاجها devise ضمن قاعدة البيانات
إضافة الوحدتان Confirmable,Lockable واستخدامهما ضمن Devise
كما تم التوضيح سابقا أن الوحدات المفعلة بشكل افتراضي عند تثبيت devise هي 6 فقط :
database_authenticatable | registerable | recoverable |
---|---|---|
trackable | rememberable | rememberable |
لإضافة كل من الوحدتان Confirmable,Lockable إلى devise واستخدامها يجب أولا إضافتها ضمن ملف
app/model/user.rb
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable
وأخيرا إضافة الأعمدة الضرورية لعملها ضمن ملف migration الذي تم إنشائه سابقا
db/migrations/xxx_devise_create_users.rb
الأعمدة تم تولديها بالفعل ولكن تم تعطيلها بإضافة رمز
#
ليتم اعتبارها كتعليق
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
أحذف الرمز #
من الأكواد السابقة وأضف أيضا عامود لسماح للمستخدمين بإضافة اسم لهم
## Database authenticatable
t.string :name
الآن نفذ الأمر التالي لإنشاء جدول باسم user ضمن قاعدة المعطيات يحتوي على الأعمدة الموضحة بالملف
db/migrations/xxx_devise_create_users.rb
$ rake db:migrate
ضبط إعدادات Devise وفقا لعمل كل وحدة
جميع الإعدادات التي تخص عمل الوحدات الخاصة به موجودة ضمن الملف config/initializers/devise.rb
, افتح الملف السابق وابحث عن القسم الخاص بالوحدة lockable
الموجود تحت العبارة التالية Configuration for :lockable
واحذف الرمز #
من امام الإعدادت التالية :
- config.lock_strategy = :failed_attempts : هذا يعني بأن الحساب سيتم قفله بعد عدة محاولات فاشلة لتسجيل الدخول، يمكنك جعلها تساوي
none
والتعامل مع آلية القفل بنفسك. - config.unlock_strategy = :both : إجراء إلغاء قفل الحساب تتم إما عن طريق البريد الالكتروني(من خلال التأكيد على رابط يتم إرساله من قبل devise) أو من خلال الانتظار مدة معينة من الزمن، بإمكانك استبدال
both:
بالقيمة التاليةemail:
لجعل إلغاء القفل عبر البريد فقط أو استبدالة بالقيمةtime:
لجعل الإلغاء عبر الانتظار فقط أو ترك القيمة الافتراضيةboth:
لجعل الأمر يتم عبر الاثنين معا. - config.maximum_attempts = 20 : عدد المرات المتتالية التي يسمح للمستخدم فيها إدخال كلمة مرور خاطئة قبل إقفال الحساب.
- config.unlock_in = 1.hour : المدة الزمنية التي يجب على المستخدم انتظارها قبل إلغاء القفل بشكل آلي.
- config.last_attempt_warning = true :إصدار رسالة تحذير
flash message
عندما يتبقى للمستخدم محاولة وحيدة قبل إغلاق الحساب.
الآن بعد الانتهاء من إعدادات الوحدة lockable
ننتقل إلى الوحدة confirmable
بنفس الطريقة السابقة، ابحث عن القسم الخاص به الموجود تحت العبارة التالية Configuration for :confirmable
واحذف الرمز #
من امام الإعدادت التالية ايضا:
- config.confirm_within = 3.days : المدة الزمنية التي يستطيع المستخدم تنشيط حسابه ضمنها عن طريق رمز التفعيل المرسل إلى البريد الالكتروني (بعد انتهاء هذه المدة يصبح رابط التنشيط غير فعال ويتوجب على المستخدم الحصول على رمز جديد). يمكنك إضافة القيمة التالية “nil” إذا أردت ان لا تنتهي مدة تنشيط الحساب.
- config.reconfirmable = true : يجب على المستخدم إعادة تأكيد اي تغير على ملفه الشخصي عبر البريد الإلكتروني. هذه العملية تشبه عملية تنشيط الحساب بعد التسجيل.فلو مثلا قام بتعديل حقل البريد في ملفه الشخصي ولم يقم بتأكيد التعديل عبر البريد الالكتروني، يبقى البريد الجديد الذي تم إضافته غير مؤكد، ويجري تخزينه في الحقل unconfirmed_email حتى يقوم المستخدم بزيارة رابط التفعيل. وخلال هذه الفترة يتم استخدام البريد الإلكتروني القديم لتسجيل الدخول.
إذا كنت تقوم ببناء تطبيق حقيقي، لا ننسى أيضا أن تعدل هذه الإعدادات:
- config.mailer_sender : اسم البريد الذي سوف يظهر لكل مستخدم في حقل
from
. - config.secret_key : المفتاح السري
Secret key
. بإمكانك استخدام المفتاح الموجود بشكل افتراضي او توليد مفتاح جديد عن طريق التعليمة التالية:
$ rake secret
تخصيص Devise وإضافة اللمسات الأخيرة لعمله
توليد ملفات الإظهار (Generating Views)
يتم توليد جميع ملفات الإظهار الخاصة بعمل الوحدات المفعلة عن طريق الأمر التالي:
$ rails generate devise:views
التعليمة السابقة سوف تنسخ ملفات إظهار Devise الافتراضية بمجلد اسمه devise
ضمن المسار التالي app/views/layouts/devise
.
لنلقي نظرة سريعة على محتوى المجلد السابق الذي تم توليده الذي بدورة يحتوي على عدة مجدات وهي:
- confirmations : يحتوي على ملف وحيد
new.html.erb
يتم تحميله عندما يريد المستخدم إعادة إرسال رسالة التفعيل عبر البريد الالكتروني. - mailer : جميع نماذج البريد الالكتروني التي يتم إرسالها موجودة ضمن هذا المجلد.
- passwords : يحتوي على ملفين الأول
new.html.erb
يتم استدعائه عندما يريد المستخدم استعادة كلمة المرور عبر البريد الالكتروني(يحتوي على form للبريد الالكتروني الذي سيتم إرسال تعليمات الإستعادة إليه)، والآخرedit.html.erb
يتم استدعائه بعد ضغط المستخدم على رابط المرسل عبر البريد ويحتوي علىform
لكلمة المرور الجديدة وتأكيدها. - registrations : يحتوي على ملفين الأول
new.html.erb
يتم استدعائه عندما يقوم المستخدم بتسجيل جساب وجديد والملف الأخرedit.html.erb
يتم استدعائه عندما يقوم المستخدم بتعديل بيانات ملفه الشخصي. - sessions :يحتوي على ملف واحد ويتم استدعائه عندما يريد المستخدم تسجيل دخول(
login form
) - shared : يحتوي على جميع الروابط التي تظهر في صفحة من صفحات Desvise مثل (هل نسيت كلمة المرور، أعد إرسال تعليمات تفعيل الحساب …)
- unlocks :يحتوي على ملف واحد(
form
للبريد الالكتورني) يتم استدعائه عندما يريد المستخدم إلغاء القفل عن حسابه.
إذا كنت ترغب في توليد ملفات الإظهار views
لبعض وحدات فقط (مثلا registerable و confirmable)نفذ هذا الأمر:
$ rails generate devise:views -v registrations confirmations
أيضا إذا كان لديك عدة model ضمن تطبيق Rails تستخدم Devise (مثلا users, admin) بإمكانك توليد ملفات الإظهار views
الخاصة بكل Model عن طريق التعليمة التالية:
$ rails generate devise:views users
$ rails generate devise:views admin
Strong_params وحقل الخاص باسم المستخدمين name:
في Devise
إذا كنت تستخدم الإصدار 4 أو 5 من الإطار Rails فهذا يعني انك تستخدم strong_params بشكل افتراضي
لذلك يجب تمرير name:
إلى parameter الخاصة ب Devise بإضافة الأسطر التالية إلى الملف
app/controllers/application_controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
devise_parameter_sanitizer.for(:account_update) << :name
end
الآن تبقى إضافة حقل name:
إلى ملفات الإظهار الخاصة بالوحدة registrations
ليتمكن المستخدم من إضافة اسمه عند تسجيله وتعديله أيضا إذا أراد تعديل ملف الشخصي.
<div class="field">
<%= f.label :name %><br />
<%= f.email_field :name, autofocus: true %>
</div>
إعدادات إرسال البريد من قبل Devise
ضمن بيئة development
عملية إرسال البريد (بريد التفعيل واستعادة كلمة المرور …) غير مفعلة بشكل افتراضي ضمن Devise. لتفعليها أضف السطر التالي ضمن الملف config/environments/development.rb
مع إعدادات stmp:
لمخدم البريد gmail (بإمكانك استخدام مخدم بريد آخر مثل sendgrid أو mandrill)
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'example.com',
user_name: '<username>',
password: '<password>',
authentication: 'plain',
enable_starttls_auto: true }
حيث أن user_name
و password
هي اسم المستخدم وكلمة مرور حسابك في gmail
يمكن إيضا إضافة نفس الإعدادات السابقة إلى بيئة production
مع بعض الاختلافات البسيطة
config/environments/production.rb
config.action_mailer.default_url_options = { host: 'devise_demo.herokuapp.com' }
onfig.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'heroku.com',
user_name: '<username>',
password: '<password>',
authentication: 'plain',
enable_starttls_auto: true }
بالنسبة لهذا المثال تم استخدام منصة التطبيقات السحابية Heroku كبيئة
production
الاختلاف يكون فقط في
- الرابط الافتراضي للتطبيق وهو
config.action_mailer.default_url_options = { host: 'devise_demo.herokuapp.com' }
حيث devise_demo
هو اسم التطبيق الذي تم إنشائه على منصة Heroku
- والدومين :
domain: 'heroku.com'
وهذا يقودنا إلى نهاية هذه التدوينة.
الخلاصة:
هذه التدوينة ليست إلا مدخل تعريفي مع بعض الشروحات البسيطة عن وحدات وإعدادت نظام Authentication المسمى Devise هناك نقاط كتيرة لم أتطرق لها وربما تكون مهمة بالنسبة إليك لذلك أدعوك إلى الإطلاع على توثيق الجيم Wiki وبشكل خاص على الصفحة How-to’s إذا يوجد بها أكثر من 90 تدريب بسيط ومفيد جدا
سأحاول إن شاء الله من خلال تدوينة آخرى شرح بعض الإضافات التي تستخدم مع devise وكيفية استخدام الوحدة Omniauthable أيضا