raddar 0.0.1.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +3 -0
  4. data/Rakefile +27 -0
  5. data/app/assets/images/raddar/fallback/avatar/medium.png +0 -0
  6. data/app/assets/images/raddar/fallback/avatar/thumb.png +0 -0
  7. data/app/assets/javascripts/raddar/admin/dashboard.js.coffee +3 -0
  8. data/app/assets/javascripts/raddar/application.js +16 -0
  9. data/app/assets/javascripts/raddar/followerships.js.coffee +3 -0
  10. data/app/assets/javascripts/raddar/home.js.coffee +3 -0
  11. data/app/assets/javascripts/raddar/notifications.js.coffee +16 -0
  12. data/app/assets/javascripts/raddar/users.js.coffee +3 -0
  13. data/app/assets/javascripts/raddar/users/privacies.js.coffee +3 -0
  14. data/app/assets/stylesheets/raddar/admin/dashboard.css.scss +3 -0
  15. data/app/assets/stylesheets/raddar/application.css +14 -0
  16. data/app/assets/stylesheets/raddar/followerships.css.scss +3 -0
  17. data/app/assets/stylesheets/raddar/home.css.scss +3 -0
  18. data/app/assets/stylesheets/raddar/notifications.css.scss +6 -0
  19. data/app/assets/stylesheets/raddar/users.css.scss +3 -0
  20. data/app/assets/stylesheets/raddar/users/privacies.css.scss +3 -0
  21. data/app/controllers/raddar/admin/dashboard_controller.rb +11 -0
  22. data/app/controllers/raddar/admin/users_controller.rb +34 -0
  23. data/app/controllers/raddar/application_controller.rb +17 -0
  24. data/app/controllers/raddar/followerships_controller.rb +60 -0
  25. data/app/controllers/raddar/home_controller.rb +8 -0
  26. data/app/controllers/raddar/notifications_controller.rb +31 -0
  27. data/app/controllers/raddar/users/email_preferences_controller.rb +24 -0
  28. data/app/controllers/raddar/users/external_accounts_controller.rb +18 -0
  29. data/app/controllers/raddar/users/omniauth_callbacks_controller.rb +30 -0
  30. data/app/controllers/raddar/users/passwords_controller.rb +22 -0
  31. data/app/controllers/raddar/users/privacies_controller.rb +25 -0
  32. data/app/controllers/raddar/users/registrations_controller.rb +51 -0
  33. data/app/controllers/raddar/users/sessions_controller.rb +11 -0
  34. data/app/controllers/raddar/users_controller.rb +8 -0
  35. data/app/helpers/raddar/admin/dashboard_helper.rb +4 -0
  36. data/app/helpers/raddar/application_helper.rb +4 -0
  37. data/app/helpers/raddar/notifications_helper.rb +19 -0
  38. data/app/helpers/raddar/users/privacies_helper.rb +4 -0
  39. data/app/mailers/raddar/notification_mailer.rb +16 -0
  40. data/app/models/raddar/external_account.rb +12 -0
  41. data/app/models/raddar/followership.rb +20 -0
  42. data/app/models/raddar/followership_completion.rb +37 -0
  43. data/app/models/raddar/notification.rb +10 -0
  44. data/app/models/raddar/omniauth_completion.rb +83 -0
  45. data/app/models/raddar/role.rb +7 -0
  46. data/app/models/raddar/user.rb +70 -0
  47. data/app/policies/raddar/admin/dashboard_policy.rb +7 -0
  48. data/app/policies/raddar/admin/user_policy.rb +15 -0
  49. data/app/policies/raddar/application_policy.rb +42 -0
  50. data/app/policies/raddar/followership_policy.rb +25 -0
  51. data/app/policies/raddar/notification_policy.rb +21 -0
  52. data/app/policies/raddar/user_policy.rb +17 -0
  53. data/app/uploaders/raddar/avatar_uploader.rb +56 -0
  54. data/app/views/layouts/raddar/_alerts.html.erb +3 -0
  55. data/app/views/layouts/raddar/_navbar.html.erb +22 -0
  56. data/app/views/layouts/raddar/_notifications.html.erb +20 -0
  57. data/app/views/layouts/raddar/_user_menu.html.erb +21 -0
  58. data/app/views/layouts/raddar/application.html.erb +21 -0
  59. data/app/views/layouts/raddar/notification_mailer.html.erb +12 -0
  60. data/app/views/raddar/admin/dashboard/index.html.erb +6 -0
  61. data/app/views/raddar/admin/users/index.html.erb +11 -0
  62. data/app/views/raddar/admin/users/show.html.erb +12 -0
  63. data/app/views/raddar/followerships/followers.html.erb +9 -0
  64. data/app/views/raddar/followerships/following.html.erb +9 -0
  65. data/app/views/raddar/home/index.html.erb +1 -0
  66. data/app/views/raddar/notification_mailer/new_follower.html.erb +11 -0
  67. data/app/views/raddar/notifications/index.html.erb +12 -0
  68. data/app/views/raddar/notifications/index.json.jbuilder +4 -0
  69. data/app/views/raddar/users/confirmations/new.html.erb +16 -0
  70. data/app/views/raddar/users/email_preferences/edit.html.erb +11 -0
  71. data/app/views/raddar/users/external_accounts/index.html.erb +14 -0
  72. data/app/views/raddar/users/mailer/confirmation_instructions.html.erb +5 -0
  73. data/app/views/raddar/users/mailer/reset_password_instructions.html.erb +8 -0
  74. data/app/views/raddar/users/mailer/unlock_instructions.html.erb +7 -0
  75. data/app/views/raddar/users/passwords/change.html.erb +13 -0
  76. data/app/views/raddar/users/passwords/edit.html.erb +19 -0
  77. data/app/views/raddar/users/passwords/new.html.erb +15 -0
  78. data/app/views/raddar/users/privacies/edit.html.erb +12 -0
  79. data/app/views/raddar/users/registrations/destroy.html.erb +13 -0
  80. data/app/views/raddar/users/registrations/edit.html.erb +30 -0
  81. data/app/views/raddar/users/registrations/new.html.erb +16 -0
  82. data/app/views/raddar/users/sessions/new.html.erb +13 -0
  83. data/app/views/raddar/users/shared/_links.erb +25 -0
  84. data/app/views/raddar/users/show.html.erb +52 -0
  85. data/app/views/raddar/users/unlocks/new.html.erb +16 -0
  86. data/config/cucumber.yml +8 -0
  87. data/config/initializers/carrierwave.rb +10 -0
  88. data/config/initializers/devise.rb +262 -0
  89. data/config/initializers/kaminari_config.rb +10 -0
  90. data/config/initializers/simple_form.rb +142 -0
  91. data/config/initializers/simple_form_bootstrap.rb +17 -0
  92. data/config/locales/devise.en.yml +59 -0
  93. data/config/locales/en.yml +49 -0
  94. data/config/locales/flash.en.yml +20 -0
  95. data/config/locales/mailers.en.yml +5 -0
  96. data/config/locales/simple_form.en.yml +35 -0
  97. data/config/locales/views.en.yml +36 -0
  98. data/config/routes.rb +43 -0
  99. data/db/migrate/20130824222728_devise_create_raddar_users.rb +66 -0
  100. data/db/migrate/20131013222926_create_raddar_followerships.rb +14 -0
  101. data/db/migrate/20131020174318_create_raddar_roles.rb +11 -0
  102. data/db/migrate/20131020175354_create_join_table_raddar_role_user.rb +8 -0
  103. data/db/migrate/20131021134623_create_raddar_notifications.rb +13 -0
  104. data/db/migrate/20131026133924_create_raddar_external_accounts.rb +23 -0
  105. data/lib/raddar.rb +15 -0
  106. data/lib/raddar/engine.rb +5 -0
  107. data/lib/raddar/hstore_serializer.rb +22 -0
  108. data/lib/raddar/version.rb +3 -0
  109. data/lib/tasks/cucumber.rake +65 -0
  110. data/lib/tasks/raddar_tasks.rake +4 -0
  111. metadata +390 -0
@@ -0,0 +1,25 @@
1
+ module Raddar
2
+ class Users::PrivaciesController < Raddar::ApplicationController
3
+ skip_after_action :verify_authorized
4
+
5
+ def edit
6
+ @user = current_user
7
+ @user.privacy ||= {}
8
+ end
9
+
10
+ def update
11
+ @user = current_user
12
+ @user.privacy ||= {}
13
+
14
+ @user.update_attributes(privacy_params)
15
+
16
+ redirect_to edit_user_privacy_path, notice: t('flash.users.privacies.update')
17
+ end
18
+
19
+ private
20
+
21
+ def privacy_params
22
+ params.require(:user).permit(privacy: @user.privacy_keys)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,51 @@
1
+ module Raddar
2
+ class Users::RegistrationsController < Devise::RegistrationsController
3
+ before_action :configure_permitted_parameters
4
+
5
+ def update
6
+ @user = User.find(current_user.id)
7
+
8
+ prev_unconfirmed_email = @user.unconfirmed_email if @user.respond_to?(:unconfirmed_email)
9
+
10
+ if @user.update_attributes(account_update_params)
11
+ if is_navigational_format?
12
+ flash_key = update_needs_confirmation?(@user, prev_unconfirmed_email) ?
13
+ :update_needs_confirmation : :updated
14
+ set_flash_message :notice, flash_key
15
+ end
16
+
17
+ sign_in @user, bypass: true
18
+ respond_with @user, location: @user
19
+ else
20
+ clean_up_passwords @user
21
+ respond_with @user
22
+ end
23
+ end
24
+
25
+ def destroy
26
+ @user = current_user
27
+
28
+ if request.request_method_symbol == :delete
29
+ if @user.valid_password?(params[:user][:password])
30
+ super
31
+ else
32
+ @user.valid?
33
+ @user.errors.add :password, params[:user][:password].blank? ? :blank : :invalid
34
+ clean_up_passwords @user
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def configure_permitted_parameters
42
+ devise_parameter_sanitizer.for(:sign_up) do |u|
43
+ u.permit(:name, :email, :password, :password_confirmation)
44
+ end
45
+
46
+ devise_parameter_sanitizer.for(:account_update) do |u|
47
+ u.permit(:name, :email, :gender, :bio, :location, :birthday, :avatar)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ module Raddar
2
+ class Users::SessionsController < Devise::SessionsController
3
+ before_action :configure_permitted_parameters
4
+
5
+ private
6
+
7
+ def configure_permitted_parameters
8
+ devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login) }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Raddar
2
+ class UsersController < Raddar::ApplicationController
3
+ def show
4
+ @user = User.find(params[:id])
5
+ authorize(@user)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ module Raddar
2
+ module Admin::DashboardHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Raddar
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,19 @@
1
+ module Raddar
2
+ module NotificationsHelper
3
+ def unread_notifications_count(user)
4
+ user.notifications.where(unread: true).count
5
+ end
6
+
7
+ def last_notifications(user)
8
+ user.notifications.order('created_at DESC').limit(10)
9
+ end
10
+
11
+ def link_to_notification(notification)
12
+ text = t(notification.token, scope: 'notifications.tokens', notifiable: notification.notifiable.name)
13
+
14
+ unread_class = notification.unread ? 'unread' : 'read'
15
+
16
+ link_to(text, [raddar, notification], class: "notification #{ unread_class }")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,4 @@
1
+ module Raddar
2
+ module Users::PrivaciesHelper
3
+ end
4
+ end
@@ -0,0 +1,16 @@
1
+ module Raddar
2
+ class NotificationMailer < ActionMailer::Base
3
+ default from: "#{ Raddar.app_name } <#{ Raddar.default_from }>"
4
+
5
+ def new_follower(notification)
6
+ @user = notification.user
7
+ @follower = notification.notifiable
8
+ @notification = notification
9
+
10
+ mail(
11
+ to: @user.email,
12
+ subject: t('mailers.notification.new_follower.subject', follower: @follower.name)
13
+ )
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module Raddar
2
+ class ExternalAccount < ActiveRecord::Base
3
+ belongs_to :user
4
+
5
+ validates :provider, presence: true
6
+ validates :uid, presence: true, uniqueness: { scope: :provider }
7
+ validates :name, presence: true, uniqueness: { scope: :provider }
8
+ validates :url, presence: true, uniqueness: { scope: :provider }
9
+ validates :token, presence: true, uniqueness: { scope: :provider }
10
+ validates :user_id, presence: true, uniqueness: { scope: :provider }
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Raddar
2
+ class Followership < ActiveRecord::Base
3
+ belongs_to :user
4
+ belongs_to :followable, polymorphic: true, inverse_of: :followers
5
+
6
+ validates :user_id, presence: true, uniqueness: { scope: [:followable_id, :followable_type] }
7
+ validates :followable_id, presence: true
8
+
9
+ validate :user_and_followable_must_be_different
10
+
11
+
12
+ private
13
+
14
+ def user_and_followable_must_be_different
15
+ if self.user.present? && self.user == self.followable
16
+ self.errors[:base] << 'User cannot follow himself/herself.'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ module Raddar
2
+ class FollowershipCompletion
3
+ def initialize(followership)
4
+ @followership = followership
5
+ end
6
+
7
+ def create
8
+ successful = @followership.save
9
+
10
+ if successful
11
+ notify_followed_user
12
+ end
13
+
14
+ successful
15
+ end
16
+
17
+ private
18
+
19
+ def notify_followed_user
20
+ followable = @followership.followable
21
+
22
+ if followable.is_a?(User)
23
+ notification = Notification.new
24
+ notification.user = followable
25
+ notification.token = 'new_follower'
26
+ notification.notifiable = @followership.user
27
+ notification.save!
28
+
29
+ email_preferences = followable.email_preferences || {}
30
+
31
+ if email_preferences[:new_follower] != false
32
+ NotificationMailer.new_follower(notification).deliver
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,10 @@
1
+ module Raddar
2
+ class Notification < ActiveRecord::Base
3
+ belongs_to :user
4
+ belongs_to :notifiable, polymorphic: true
5
+
6
+ validates :token, presence: true
7
+ validates :user_id, presence: true
8
+ validates :notifiable_id, presence: true
9
+ end
10
+ end
@@ -0,0 +1,83 @@
1
+ module Raddar
2
+ class OmniauthCompletion
3
+ def self.complete(auth_data, current_user = nil)
4
+ user = User.new(password: Devise.friendly_token[0,20])
5
+
6
+ provider = auth_data[:provider]
7
+
8
+ account = ExternalAccount.find_by(provider: provider, uid: auth_data[:uid])
9
+
10
+ if current_user.present?
11
+ if account.present?
12
+ if account.user != current_user
13
+ raise 'Another user already owns this account.'
14
+ end
15
+ else
16
+ create_account_for(current_user, auth_data)
17
+ end
18
+
19
+ user = current_user
20
+ elsif account.present?
21
+ user = account.user
22
+ elsif auth_data[:info][:email].present?
23
+ user_with_the_given_email = User.find_by(email: auth_data[:info][:email])
24
+
25
+ if user_with_the_given_email.present?
26
+ create_account_for(user_with_the_given_email, auth_data)
27
+
28
+ user = user_with_the_given_email
29
+ end
30
+ end
31
+
32
+ populate(user, auth_data)
33
+
34
+ if user.valid?
35
+ if user.new_record?
36
+ user.confirm!
37
+
38
+ user.save
39
+
40
+ create_account_for(user, auth_data)
41
+ else
42
+ user.save
43
+ end
44
+ end
45
+
46
+ user
47
+ end
48
+
49
+ private
50
+
51
+ def self.create_account_for(user, auth_data)
52
+ account = user.external_accounts.new
53
+
54
+ account.provider = auth_data[:provider]
55
+ account.token = auth_data[:credentials][:token]
56
+ account.secret = auth_data[:credentials][:secret]
57
+ account.verified = auth_data[:info][:verified]
58
+ account.name = auth_data[:info][:nickname]
59
+ account.uid = auth_data[:uid]
60
+ account.email = auth_data[:info][:email]
61
+ account.url = auth_data[:info][:urls][account.provider.titleize.to_sym]
62
+
63
+ account.save!
64
+ end
65
+
66
+ def self.populate(user, auth_data)
67
+ user.email = user.email.presence || auth_data[:info][:email]
68
+
69
+ user.name ||= auth_data[:info][:nickname]
70
+ user.bio ||= auth_data[:info][:description]
71
+ user.location ||= auth_data[:info][:location]
72
+
73
+ user.remote_avatar_url = auth_data[:info][:image] if user.avatar.blank?
74
+
75
+ if auth_data[:provider] == 'facebook'
76
+ fb_birthday = auth_data[:extra][:raw_info][:birthday]
77
+
78
+ user.birthday ||= Date.strptime(fb_birthday, '%m/%d/%Y') if fb_birthday
79
+ user.gender ||= auth_data[:extra][:raw_info][:gender]
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,7 @@
1
+ module Raddar
2
+ class Role < ActiveRecord::Base
3
+ has_and_belongs_to_many :users
4
+
5
+ validates :name, presence: true, uniqueness: { case_sensitive: false }
6
+ end
7
+ end
@@ -0,0 +1,70 @@
1
+ module Raddar
2
+ class User < ActiveRecord::Base
3
+ attr_accessor :login
4
+
5
+ store_accessor :privacy
6
+ store_accessor :email_preferences
7
+
8
+ serialize :email_preferences, Raddar::HstoreSerializer
9
+ serialize :privacy, Raddar::HstoreSerializer
10
+
11
+ has_many :followerships, dependent: :destroy
12
+ has_many :followers, class_name: 'Followership', as: :followable, dependent: :destroy
13
+ has_and_belongs_to_many :roles
14
+ has_many :notifications, dependent: :destroy
15
+ has_many :external_accounts, dependent: :destroy
16
+
17
+ mount_uploader :avatar, AvatarUploader
18
+
19
+ # Include default devise modules. Others available are:
20
+ # :token_authenticatable,
21
+ # :lockable and :timeoutable
22
+ devise :database_authenticatable, :registerable, :omniauthable,
23
+ :recoverable, :rememberable, :trackable, :validatable,
24
+ :confirmable, authentication_keys: [:login]
25
+
26
+ validates :name,
27
+ presence: true,
28
+ uniqueness: {
29
+ case_sensitive: false
30
+ },
31
+ format: { with: /\A(([a-z]|[A-Z]|[0-9]|_)+)\z/ },
32
+ length: { maximum: 20, minimum: 3 }
33
+
34
+ validates :state, presence: true, inclusion: { in: ['active', 'blocked'] }
35
+
36
+ def self.find_first_by_auth_conditions(warden_conditions)
37
+ conditions = warden_conditions.dup
38
+ if login = conditions.delete(:login)
39
+ where(conditions).where('lower(name) = :value OR lower(email) = :value', value: login.downcase).first
40
+ else
41
+ where(conditions).first
42
+ end
43
+ end
44
+
45
+ cattr_accessor(:privaciable_fields) do
46
+ [:email, :gender, :location, :birthday]
47
+ end
48
+
49
+ cattr_accessor(:email_preferences_keys) do
50
+ [:new_follower]
51
+ end
52
+
53
+ def admin?
54
+ self.roles.exists?(name: 'admin') == '1'
55
+ end
56
+
57
+ def active_for_authentication?
58
+ super && self.state == 'active'
59
+ end
60
+
61
+ def inactive_message
62
+ (self.state == 'active') ? super : I18n.t('flash.users.sessions.blocked')
63
+ end
64
+
65
+ def privacy_keys
66
+ account_keys = self.external_accounts.map(&:provider)
67
+ @@privaciable_fields + account_keys
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,7 @@
1
+ module Raddar
2
+ class Admin::DashboardPolicy < ApplicationPolicy
3
+ def index?
4
+ @user.admin?
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module Raddar
2
+ class Admin::UserPolicy < ApplicationPolicy
3
+ def index?
4
+ @user.admin?
5
+ end
6
+
7
+ def show?
8
+ @user.admin?
9
+ end
10
+
11
+ def update?
12
+ @user.admin?
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ module Raddar
2
+ class ApplicationPolicy
3
+ attr_reader :user, :record
4
+
5
+ def initialize(user, record)
6
+ @user = user
7
+ @record = record
8
+ end
9
+
10
+ def index?
11
+ false
12
+ end
13
+
14
+ def show?
15
+ scope.where(:id => record.id).exists?
16
+ end
17
+
18
+ def create?
19
+ false
20
+ end
21
+
22
+ def new?
23
+ create?
24
+ end
25
+
26
+ def update?
27
+ false
28
+ end
29
+
30
+ def edit?
31
+ update?
32
+ end
33
+
34
+ def destroy?
35
+ false
36
+ end
37
+
38
+ def scope
39
+ Pundit.policy_scope!(user, record.class)
40
+ end
41
+ end
42
+ end