mini_blog 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +34 -0
- data/Rakefile +36 -0
- data/app/assets/config/mini_blog_manifest.js +2 -0
- data/app/assets/javascripts/mini_blog/application.js +27 -0
- data/app/assets/stylesheets/mini_blog/application.scss +30 -0
- data/app/controllers/mini_blog/application_controller.rb +5 -0
- data/app/controllers/mini_blog/articles_controller.rb +56 -0
- data/app/controllers/mini_blog/users/confirmations_controller.rb +34 -0
- data/app/controllers/mini_blog/users/omniauth_callbacks_controller.rb +34 -0
- data/app/controllers/mini_blog/users/passwords_controller.rb +39 -0
- data/app/controllers/mini_blog/users/registrations_controller.rb +66 -0
- data/app/controllers/mini_blog/users/sessions_controller.rb +32 -0
- data/app/controllers/mini_blog/users/unlocks_controller.rb +34 -0
- data/app/helpers/mini_blog/application_helper.rb +4 -0
- data/app/jobs/mini_blog/application_job.rb +4 -0
- data/app/mailers/mini_blog/application_mailer.rb +6 -0
- data/app/models/mini_blog/application_record.rb +5 -0
- data/app/models/mini_blog/article.rb +10 -0
- data/app/models/mini_blog/article_tag_relation.rb +9 -0
- data/app/models/mini_blog/image.rb +6 -0
- data/app/models/mini_blog/tag.rb +8 -0
- data/app/models/mini_blog/user.rb +10 -0
- data/app/uploaders/mini_blog/image_content_uploader.rb +49 -0
- data/app/views/kaminari/bootstrap4/_first_page.html.slim +2 -0
- data/app/views/kaminari/bootstrap4/_gap.html.slim +2 -0
- data/app/views/kaminari/bootstrap4/_last_page.html.slim +2 -0
- data/app/views/kaminari/bootstrap4/_next_page.html.slim +2 -0
- data/app/views/kaminari/bootstrap4/_page.html.slim +6 -0
- data/app/views/kaminari/bootstrap4/_paginator.html.slim +12 -0
- data/app/views/kaminari/bootstrap4/_prev_page.html.slim +2 -0
- data/app/views/layouts/mini_blog/application.html.slim +28 -0
- data/app/views/mini_blog/articles/_form.html.slim +9 -0
- data/app/views/mini_blog/articles/edit.html.slim +1 -0
- data/app/views/mini_blog/articles/index.html.slim +14 -0
- data/app/views/mini_blog/articles/new.html.slim +1 -0
- data/app/views/mini_blog/articles/show.json.ruby +3 -0
- data/app/views/mini_blog/users/confirmations/new.html.erb +16 -0
- data/app/views/mini_blog/users/mailer/confirmation_instructions.html.erb +5 -0
- data/app/views/mini_blog/users/mailer/email_changed.html.erb +7 -0
- data/app/views/mini_blog/users/mailer/password_change.html.erb +3 -0
- data/app/views/mini_blog/users/mailer/reset_password_instructions.html.erb +8 -0
- data/app/views/mini_blog/users/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/mini_blog/users/passwords/edit.html.slim +22 -0
- data/app/views/mini_blog/users/passwords/new.html.slim +10 -0
- data/app/views/mini_blog/users/registrations/edit.html.erb +43 -0
- data/app/views/mini_blog/users/registrations/new.html.erb +29 -0
- data/app/views/mini_blog/users/sessions/new.html.slim +17 -0
- data/app/views/mini_blog/users/shared/_links.html.erb +25 -0
- data/app/views/mini_blog/users/unlocks/new.html.erb +16 -0
- data/config/initializers/devise.rb +279 -0
- data/config/locales/devise.en.yml +64 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20180224022923_create_mini_blog_articles.rb +12 -0
- data/db/migrate/20180224025140_create_mini_blog_images.rb +9 -0
- data/db/migrate/20180224090210_devise_create_mini_blog_users.rb +45 -0
- data/db/migrate/20180224112101_create_mini_blog_tags.rb +9 -0
- data/db/migrate/20180224113006_create_mini_blog_article_tag_relations.rb +12 -0
- data/lib/mini_blog.rb +11 -0
- data/lib/mini_blog/engine.rb +5 -0
- data/lib/mini_blog/version.rb +3 -0
- data/lib/tasks/mini_blog_tasks.rake +4 -0
- metadata +260 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MiniBlog
|
4
|
+
module Users
|
5
|
+
class UnlocksController < Devise::UnlocksController
|
6
|
+
# GET /resource/unlock/new
|
7
|
+
# def new
|
8
|
+
# super
|
9
|
+
# end
|
10
|
+
|
11
|
+
# POST /resource/unlock
|
12
|
+
# def create
|
13
|
+
# super
|
14
|
+
# end
|
15
|
+
|
16
|
+
# GET /resource/unlock?unlock_token=abcdef
|
17
|
+
# def show
|
18
|
+
# super
|
19
|
+
# end
|
20
|
+
|
21
|
+
# protected
|
22
|
+
|
23
|
+
# The path used after sending unlock password instructions
|
24
|
+
# def after_sending_unlock_instructions_path_for(resource)
|
25
|
+
# super(resource)
|
26
|
+
# end
|
27
|
+
|
28
|
+
# The path used after unlocking the resource
|
29
|
+
# def after_unlock_path_for(resource)
|
30
|
+
# super(resource)
|
31
|
+
# end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module MiniBlog
|
2
|
+
class Article < ApplicationRecord
|
3
|
+
has_many :article_tag_relations, dependent: :destroy
|
4
|
+
has_many :tags, through: :article_tag_relations
|
5
|
+
|
6
|
+
validates :title, presence: true
|
7
|
+
validates :body, presence: true
|
8
|
+
validates :status, presence: true
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module MiniBlog
|
2
|
+
class User < ApplicationRecord
|
3
|
+
# Include default devise modules. Others available are:
|
4
|
+
# :confirmable, :lockable, :timeoutable and :omniauthable
|
5
|
+
devise :database_authenticatable, :recoverable,
|
6
|
+
:rememberable, :trackable, :validatable
|
7
|
+
|
8
|
+
validates :name, presence: true
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module MiniBlog
|
2
|
+
class ImageContentUploader < CarrierWave::Uploader::Base
|
3
|
+
# Include RMagick or MiniMagick support:
|
4
|
+
# include CarrierWave::RMagick
|
5
|
+
# include CarrierWave::MiniMagick
|
6
|
+
|
7
|
+
# Choose what kind of storage to use for this uploader:
|
8
|
+
storage :file
|
9
|
+
# storage :fog
|
10
|
+
|
11
|
+
# Override the directory where uploaded files will be stored.
|
12
|
+
# This is a sensible default for uploaders that are meant to be mounted:
|
13
|
+
def store_dir
|
14
|
+
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Provide a default URL as a default if there hasn't been a file uploaded:
|
18
|
+
# def default_url(*args)
|
19
|
+
# # For Rails 3.1+ asset pipeline compatibility:
|
20
|
+
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
|
21
|
+
#
|
22
|
+
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
|
23
|
+
# end
|
24
|
+
|
25
|
+
# Process files as they are uploaded:
|
26
|
+
# process scale: [200, 300]
|
27
|
+
#
|
28
|
+
# def scale(width, height)
|
29
|
+
# # do something
|
30
|
+
# end
|
31
|
+
|
32
|
+
# Create different versions of your uploaded files:
|
33
|
+
# version :thumb do
|
34
|
+
# process resize_to_fit: [50, 50]
|
35
|
+
# end
|
36
|
+
|
37
|
+
# Add a white list of extensions which are allowed to be uploaded.
|
38
|
+
# For images you might use something like this:
|
39
|
+
# def extension_whitelist
|
40
|
+
# %w(jpg jpeg gif png)
|
41
|
+
# end
|
42
|
+
|
43
|
+
# Override the filename of the uploaded files:
|
44
|
+
# Avoid using model.id or version_name here, see uploader/store.rb for details.
|
45
|
+
# def filename
|
46
|
+
# "something.jpg" if original_filename
|
47
|
+
# end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
- if page.current?
|
2
|
+
li.page-item.active
|
3
|
+
= content_tag :a, page, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)), class: 'page-link'
|
4
|
+
- else
|
5
|
+
li.page-item
|
6
|
+
= link_to page, url, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)), class: 'page-link'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= paginator.render do
|
2
|
+
nav
|
3
|
+
ul.pagination
|
4
|
+
== first_page_tag unless current_page.first?
|
5
|
+
== prev_page_tag unless current_page.first?
|
6
|
+
- each_page do |page|
|
7
|
+
- if page.left_outer? || page.right_outer? || page.inside_window?
|
8
|
+
== page_tag page
|
9
|
+
- elsif !page.was_truncated?
|
10
|
+
== gap_tag
|
11
|
+
== next_page_tag unless current_page.last?
|
12
|
+
== last_page_tag unless current_page.last?
|
@@ -0,0 +1,28 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
title
|
5
|
+
| Mini blog
|
6
|
+
meta name="viewport" content="width=device-width,initial-scale=1"
|
7
|
+
= stylesheet_link_tag 'mini_blog/application', media: 'all'
|
8
|
+
= javascript_include_tag 'mini_blog/application'
|
9
|
+
= csrf_meta_tags
|
10
|
+
body
|
11
|
+
header
|
12
|
+
nav.navbar.navbar-expand-lg.navbar-light.bg-light
|
13
|
+
.container
|
14
|
+
button.navbar-toggler data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"
|
15
|
+
span.navbar-toggler-icon
|
16
|
+
= link_to 'MiniBlog', root_path, class: 'navbar-brand'
|
17
|
+
#navbarSupportedContent.collapse.navbar-collapse
|
18
|
+
ul.navbar-nav.mr-auto
|
19
|
+
- if user_signed_in?
|
20
|
+
li.nav-item
|
21
|
+
= link_to 'Sign out', destroy_user_session_path, class: 'nav-link', method: :delete
|
22
|
+
li.nav-item
|
23
|
+
= link_to 'New Article', new_article_path, class: 'nav-link'
|
24
|
+
- else
|
25
|
+
li.nav-item
|
26
|
+
= link_to 'Sign in', new_user_session_path, class: 'nav-link'
|
27
|
+
.container.main-contents
|
28
|
+
= yield
|
@@ -0,0 +1,9 @@
|
|
1
|
+
= form_with model: article, local: true do |f|
|
2
|
+
.form-group
|
3
|
+
= f.text_field :title, class: 'form-control', placeholder: 'Title'
|
4
|
+
.form-group
|
5
|
+
= f.text_area :body, class: 'form-control form-control-lg', placeholder: 'Body'
|
6
|
+
.form-group
|
7
|
+
= text_field :article, :tags, value: article.tags.pluck(:name).join('; '), class: 'form-control', placeholder: 'Tag'
|
8
|
+
button.btn.btn-info type="submit"
|
9
|
+
| send
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'form', article: @article
|
@@ -0,0 +1,14 @@
|
|
1
|
+
ul
|
2
|
+
- @articles.each do |article|
|
3
|
+
li.card
|
4
|
+
.card-header
|
5
|
+
h2
|
6
|
+
= "#{l(article.created_at)} #{article.title}"
|
7
|
+
ul
|
8
|
+
- article.tags.each do |tag|
|
9
|
+
li.badge.badge-dark.tag
|
10
|
+
= tag.name
|
11
|
+
article.article.card-body.collapse*{id: "article-#{article.id}", 'data-id': article.id}
|
12
|
+
button.btn.btn-link.btn-sm.text-left data-toggle="collapse" href="#article-#{article.id}" role="button" aria-expanded="false" aria-controls="article-#{article.id}"
|
13
|
+
| open...
|
14
|
+
= paginate @articles, theme: :bootstrap4
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'form', article: @article
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<h2>Resend confirmation instructions</h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
|
6
|
+
<div class="field">
|
7
|
+
<%= f.label :email %><br />
|
8
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class="actions">
|
12
|
+
<%= f.submit "Resend confirmation instructions" %>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<%= render "mini_blog/users/shared/links" %>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<p>Hello <%= @email %>!</p>
|
2
|
+
|
3
|
+
<% if @resource.try(:unconfirmed_email?) %>
|
4
|
+
<p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
|
5
|
+
<% else %>
|
6
|
+
<p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
|
7
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<p>Hello <%= @resource.email %>!</p>
|
2
|
+
|
3
|
+
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
|
4
|
+
|
5
|
+
<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
|
6
|
+
|
7
|
+
<p>If you didn't request this, please ignore this email.</p>
|
8
|
+
<p>Your password won't change until you access the link above and create a new one.</p>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<p>Hello <%= @resource.email %>!</p>
|
2
|
+
|
3
|
+
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
|
4
|
+
|
5
|
+
<p>Click the link below to unlock your account:</p>
|
6
|
+
|
7
|
+
<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
h2
|
2
|
+
| Change your password
|
3
|
+
= form_with model: resource, url: user_password_path, html: {method: :put}, local: true do |f|
|
4
|
+
= devise_error_messages!
|
5
|
+
= f.hidden_field :reset_password_token
|
6
|
+
.form-group
|
7
|
+
= f.label :password, 'New password'
|
8
|
+
br
|
9
|
+
- if @minimum_password_length
|
10
|
+
em
|
11
|
+
| (
|
12
|
+
= @minimum_password_length
|
13
|
+
| characters minimum)
|
14
|
+
br
|
15
|
+
= f.password_field :password, autofocus: true, autocomplete: 'off', class: 'form-controller'
|
16
|
+
.field
|
17
|
+
= f.label :password_confirmation, 'Confirm new password'
|
18
|
+
br
|
19
|
+
= f.password_field :password_confirmation, autocomplete: 'off'
|
20
|
+
button.btn.btn-outline-success
|
21
|
+
| Send me reset password instructions
|
22
|
+
= render 'mini_blog/users/shared/links'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
h2
|
2
|
+
| Forgot your password?
|
3
|
+
= form_with model: resource, url: user_password_path, local: true do |f|
|
4
|
+
= devise_error_messages!
|
5
|
+
.form-group
|
6
|
+
= f.label :email
|
7
|
+
= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control'
|
8
|
+
button.btn.btn-outline-success
|
9
|
+
| Send me reset password instructions
|
10
|
+
= render 'mini_blog/users/shared/links'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<h2>Edit <%= resource_name.to_s.humanize %></h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
|
6
|
+
<div class="field">
|
7
|
+
<%= f.label :email %><br />
|
8
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
|
12
|
+
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<div class="field">
|
16
|
+
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
|
17
|
+
<%= f.password_field :password, autocomplete: "off" %>
|
18
|
+
<% if @minimum_password_length %>
|
19
|
+
<br />
|
20
|
+
<em><%= @minimum_password_length %> characters minimum</em>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="field">
|
25
|
+
<%= f.label :password_confirmation %><br />
|
26
|
+
<%= f.password_field :password_confirmation, autocomplete: "off" %>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div class="field">
|
30
|
+
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
|
31
|
+
<%= f.password_field :current_password, autocomplete: "off" %>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<div class="actions">
|
35
|
+
<%= f.submit "Update" %>
|
36
|
+
</div>
|
37
|
+
<% end %>
|
38
|
+
|
39
|
+
<h3>Cancel my account</h3>
|
40
|
+
|
41
|
+
<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
|
42
|
+
|
43
|
+
<%= link_to "Back", :back %>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<h2>Sign up</h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
|
6
|
+
<div class="field">
|
7
|
+
<%= f.label :email %><br />
|
8
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class="field">
|
12
|
+
<%= f.label :password %>
|
13
|
+
<% if @minimum_password_length %>
|
14
|
+
<em>(<%= @minimum_password_length %> characters minimum)</em>
|
15
|
+
<% end %><br />
|
16
|
+
<%= f.password_field :password, autocomplete: "off" %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div class="field">
|
20
|
+
<%= f.label :password_confirmation %><br />
|
21
|
+
<%= f.password_field :password_confirmation, autocomplete: "off" %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="actions">
|
25
|
+
<%= f.submit "Sign up" %>
|
26
|
+
</div>
|
27
|
+
<% end %>
|
28
|
+
|
29
|
+
<%= render "mini_blog/users/shared/links" %>
|