symphonia 3.3.0 → 3.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -3
- data/app/controllers/symphonia/accounts_controller.rb +14 -12
- data/app/helpers/symphonia/application_helper.rb +17 -61
- data/app/mailers/symphonia/notifier.rb +2 -1
- data/app/models/symphonia/user.rb +0 -1
- data/app/views/layouts/symphonia/application.pdf.erb +0 -1
- data/app/views/symphonia/accounts/lost_password.html.erb +1 -1
- data/app/views/symphonia/accounts/reset_password.html.erb +2 -2
- data/app/views/symphonia/login/_form.html.erb +0 -2
- data/app/views/symphonia/notifier/reset_password_user.html.erb +1 -2
- data/app/views/symphonia/notifier/reset_password_user.text.erb +1 -1
- data/config/locales/cs.yml +2 -0
- data/lib/symphonia/engine.rb +0 -1
- data/lib/symphonia/user_management.rb +9 -1
- data/lib/symphonia/version.rb +1 -1
- data/spec/controllers/account_controller_spec.rb +1 -1
- data/spec/factories/factories.rb +2 -14
- data/spec/mailers/previews/symphonia/notifier_preview.rb +1 -2
- data/spec/mailers/symphonia/notifier_spec.rb +1 -1
- data/spec/requests/accounts_spec.rb +2 -2
- data/spec/spec_helper.rb +0 -1
- metadata +6 -24
- data/spec/support/common_file.txt +0 -2
- data/spec/support/symphonia.jpg +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81d7e486f9226d136f252f53841733cf7fd1f76a84a27b80ff0472cfc574ae30
|
4
|
+
data.tar.gz: 39fa3ee78ed46669f2dcd583179818e7288fd392c54556b943d7ca2a9b1b312b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16fa7bf6a6fbfbb875f0d6bf84c554ecd48ba9d2aacf2c259b361c3e5cb90ac57d448bd1da3c95ab3a1918f18b1a22a05ed3db1517bb36dcc34a4d10e30b7577
|
7
|
+
data.tar.gz: 4fd6defbf9b4128295eb1c5d90c9ec9476c08e4d80adb58fdcd275cc5998190adad1db771d496cbb97f6ed128d6fafa46109b9b96b320ec892544ebb6c5a3743
|
data/CHANGELOG.md
CHANGED
@@ -5,11 +5,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
|
+
## [3.3.2] - 2020-10-17
|
9
|
+
### Added
|
10
|
+
- `render_super` for templates
|
11
|
+
### Changed
|
12
|
+
- lost password check
|
13
|
+
## [3.3.1] - 2020-09-28
|
8
14
|
### Removed
|
9
|
-
- openapi (it seems to be
|
15
|
+
- openapi (it seems to be unnecessarily)
|
10
16
|
- paperclip support
|
17
|
+
- the_sortable_tree
|
11
18
|
### Changed
|
12
|
-
- upgrade authlogic to 6.
|
19
|
+
- upgrade authlogic to 6.2.0
|
13
20
|
## [3.2.4] - 2020-05-10
|
14
21
|
### Added
|
15
22
|
- sidekiq-cron gem
|
@@ -80,7 +87,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
80
87
|
- do not require password for SSO users
|
81
88
|
- hide password field from form of SSO users
|
82
89
|
## [3.0.0] - 2019-07-06
|
83
|
-
###
|
90
|
+
### Added
|
84
91
|
- external_id on user
|
85
92
|
### Changed
|
86
93
|
- users/show only for logged users
|
@@ -100,6 +100,8 @@ module Symphonia
|
|
100
100
|
|
101
101
|
end
|
102
102
|
|
103
|
+
# @!group Reset lost password
|
104
|
+
|
103
105
|
def reset_password
|
104
106
|
@user = find_account_by_token(params.require(:id))
|
105
107
|
return render_404 if @user.nil?
|
@@ -109,28 +111,28 @@ module Symphonia
|
|
109
111
|
end
|
110
112
|
|
111
113
|
if @user.changed? && @user.save
|
112
|
-
|
114
|
+
logger.info "#{@user.id} has changed password"
|
115
|
+
return redirect_to(login_path, notice: t(:text_password_reset_success))
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
116
119
|
def lost_password
|
117
120
|
@user = find_account_by_mail(params[:email]) if params[:email]
|
118
|
-
if @user
|
119
|
-
|
120
|
-
|
121
|
-
|
121
|
+
if @user&.active?
|
122
|
+
@user.reset_perishable_token!
|
123
|
+
activation_url = url_for(action: "reset_password", id: @user.perishable_token, only_path: false)
|
124
|
+
Notifier.reset_password_user(@user, activation_url).deliver_later
|
125
|
+
end
|
126
|
+
respond_to do |format|
|
127
|
+
format.html do
|
122
128
|
redirect_to login_path, notice: t(:text_reset_password_resend)
|
123
|
-
else
|
124
|
-
redirect_to login_path, flash: { error: t("authlogic.error_messages.not_active") }
|
125
|
-
end
|
126
|
-
else
|
127
|
-
respond_to do |format|
|
128
|
-
format.html
|
129
|
-
format.js
|
130
129
|
end
|
130
|
+
format.js
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
+
# @!endgroup
|
135
|
+
|
134
136
|
private
|
135
137
|
|
136
138
|
def prepare_user
|
@@ -242,6 +242,23 @@ module Symphonia
|
|
242
242
|
fa_icon(fa, (text && { text: content_tag(:span, text, class: 'd-none d-sm-inline') } || {}).merge(options))
|
243
243
|
end
|
244
244
|
|
245
|
+
# Render original template from engine
|
246
|
+
# Useful for override part of engine view
|
247
|
+
#
|
248
|
+
# @example render_super "login/new"
|
249
|
+
# @param [String] template_name
|
250
|
+
# @param [Class<Symphonia::Engine>] engine
|
251
|
+
# @param [String] format
|
252
|
+
def render_super(template_name, engine: Symphonia::Engine, format: "html")
|
253
|
+
resolver = lookup_context.view_paths.paths.find do |resolver|
|
254
|
+
resolver.path == engine.root.join("app", "views").to_s
|
255
|
+
end
|
256
|
+
template = resolver.find_all(template_name, engine.engine_name, false, { locale: ["."], formats: [format], variants: [], handlers: [:erb] }, nil, {}).first
|
257
|
+
return "" unless template
|
258
|
+
|
259
|
+
render template: template
|
260
|
+
end
|
261
|
+
|
245
262
|
def render_symphonia_dialog(*args, &block)
|
246
263
|
ActiveSupport::Deprecation.warn "Use `render_modal` instead"
|
247
264
|
options = args.extract_options!
|
@@ -356,67 +373,6 @@ module Symphonia
|
|
356
373
|
end
|
357
374
|
|
358
375
|
end
|
359
|
-
|
360
|
-
# Example of use
|
361
|
-
# <%=
|
362
|
-
# table_header_tag_for(User) do |t|
|
363
|
-
# t.th :login
|
364
|
-
# t.th :email
|
365
|
-
# end
|
366
|
-
# %>
|
367
|
-
# options:
|
368
|
-
# => column : DB full name of column
|
369
|
-
#
|
370
|
-
# def table_header_tag_for(model, &block)
|
371
|
-
# tags = TableHeaderTag.new(model, self)
|
372
|
-
# yield tags
|
373
|
-
# tags.to_html
|
374
|
-
# end
|
375
|
-
#
|
376
|
-
# class TableHeaderTag
|
377
|
-
#
|
378
|
-
# attr_reader :view, :model
|
379
|
-
#
|
380
|
-
# def initialize(model, view)
|
381
|
-
# @model = model
|
382
|
-
# @tags = Array.new
|
383
|
-
# @view = view
|
384
|
-
# end
|
385
|
-
#
|
386
|
-
# def th(*args)
|
387
|
-
# options = args.extract_options!
|
388
|
-
# attribute = args.first
|
389
|
-
# label = args[1]
|
390
|
-
# raise ArgumentError if attribute.nil?
|
391
|
-
#
|
392
|
-
# sort_options = options.delete(:sort_options) || {}
|
393
|
-
# html_options = options.delete(:html_options) || {}
|
394
|
-
#
|
395
|
-
# label ||= @model.send(:human_attribute_name, attribute, options[:i18n] || {})
|
396
|
-
# @tags << @view.content_tag(:th, html_options) do
|
397
|
-
# if options[:sort] === false
|
398
|
-
# label
|
399
|
-
# else
|
400
|
-
# sort_options[:column] ||= options.delete(:column)
|
401
|
-
# sort_options[:column] ||= "#{@model.send(:table_name)}.#{attribute}"
|
402
|
-
# # @view.sortable_column(label, sort_options) # TODO: Rails 5 error
|
403
|
-
# label
|
404
|
-
# end
|
405
|
-
# end
|
406
|
-
#
|
407
|
-
# end
|
408
|
-
#
|
409
|
-
# def to_html
|
410
|
-
# @tags.join("\n").html_safe
|
411
|
-
# end
|
412
|
-
#
|
413
|
-
# end
|
414
|
-
|
415
|
-
# def render_share_buttons(url, name, options = {})
|
416
|
-
# options[:icon_css] ||= ''
|
417
|
-
# render(partial: 'common/share_links', locals: options.merge({ url: url, name: name }))
|
418
|
-
# end
|
419
376
|
end
|
420
377
|
end
|
421
378
|
|
422
|
-
#ApplicationHelper.send :include, Symphonia::ApplicationHelperExtension
|
@@ -21,8 +21,9 @@ module Symphonia
|
|
21
21
|
mail({ to: @user.mail, subject: 'Váš účet je aktivován' })
|
22
22
|
end
|
23
23
|
|
24
|
-
def reset_password_user(user)
|
24
|
+
def reset_password_user(user, url)
|
25
25
|
@user = user
|
26
|
+
@url = url
|
26
27
|
mail({ to: @user.mail, subject: t(:subject_reset_password_mail) })
|
27
28
|
end
|
28
29
|
|
@@ -21,7 +21,6 @@ module Symphonia
|
|
21
21
|
acts_as_authentic do |config|
|
22
22
|
config.crypto_provider = ::Authlogic::CryptoProviders::SCrypt
|
23
23
|
end
|
24
|
-
validates :email, uniqueness: { case_sensitive: false }
|
25
24
|
validates :password,
|
26
25
|
confirmation: { if: :require_password? },
|
27
26
|
length: {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= form_tag
|
1
|
+
<%= form_tag url_for({action: 'lost_password'}) do %>
|
2
2
|
<div class="form-group required">
|
3
3
|
<%= label_tag(:email, t(:'attributes.mail'), required: true, class: 'sr-only') %>
|
4
4
|
<%= email_field_tag(:email, nil, autofocus: true, placeholder: t(:'attributes.mail'), required: true, size: 35, class: 'form-control') %>
|
@@ -3,11 +3,11 @@
|
|
3
3
|
<div class="card w-75 mx-auto">
|
4
4
|
<div class="card-body">
|
5
5
|
<h4 class="card-title"><%= t(:label_reset_password) %></h4>
|
6
|
-
<%= symphonia_form_tag(url:
|
6
|
+
<%= symphonia_form_tag(url: url_for(action: "reset_password", id: params[:id]), method: 'put') do |f| %>
|
7
7
|
<%= f.error_messages %>
|
8
8
|
<%= f.password_field(:password, label: t(:'attributes.password'), required: true, wrapper_class: 'required') -%>
|
9
9
|
|
10
|
-
<%= f.submit(t(:
|
10
|
+
<%= f.submit(t(:button_save), class: 'btn btn-primary btn-block') -%>
|
11
11
|
<% end %>
|
12
12
|
</div>
|
13
13
|
</div>
|
@@ -8,7 +8,6 @@
|
|
8
8
|
<%= f.check_box :remember_me %>
|
9
9
|
<% end %>
|
10
10
|
|
11
|
-
<%= f.form_group class: 'text-center' do %>
|
12
11
|
<%= f.submit t(:button_login), class: 'btn btn-primary btn-block' %>
|
13
12
|
<% if f.object.is_a?(Symphonia::UserSession) %>
|
14
13
|
<%= link_to(t(:label_reset_password), lost_password_account_path, remote: true, class: 'btn btn-link btn-sm ') %>
|
@@ -16,4 +15,3 @@
|
|
16
15
|
<%= link_to(t(:button_register), register_path, class: 'btn btn-link btn-sm ') %>
|
17
16
|
<% end %>
|
18
17
|
<% end %>
|
19
|
-
<% end %>
|
data/config/locales/cs.yml
CHANGED
@@ -153,6 +153,8 @@ cs:
|
|
153
153
|
text_error_query_not_init: Filtry nejsou nastaveny. Registruj query!
|
154
154
|
text_error_there_is_no_filters_available: Nejsou zaregistrované žádné validní filtry.
|
155
155
|
text_error_login_required: Přihlašte se prosím
|
156
|
+
text_password_reset_success: "Nové heslo uloženo. Přihlašte se prosím"
|
157
|
+
|
156
158
|
|
157
159
|
title_toggle_multiselect: Přepnout multiselect
|
158
160
|
title_login: Přihlášení
|
data/lib/symphonia/engine.rb
CHANGED
@@ -13,7 +13,10 @@ module Symphonia
|
|
13
13
|
# validates :password, presence: true, if: ->(u){ u.new_record? }
|
14
14
|
|
15
15
|
validates :email, presence: true, uniqueness: { case_sensitive: false }
|
16
|
-
validates :login, :
|
16
|
+
validates :login, presence: true, uniqueness: { case_sensitive: false }
|
17
|
+
validates :first_name, presence: true
|
18
|
+
|
19
|
+
before_validation :set_uuid, only: -> { uuid.blank? }
|
17
20
|
|
18
21
|
def self.current=(entity)
|
19
22
|
Rails.logger.info("* #{entity.class.name}: #{entity.login} id: #{entity.id}") if entity
|
@@ -54,6 +57,11 @@ module Symphonia
|
|
54
57
|
|
55
58
|
alias_method :activate!, :unarchive!
|
56
59
|
|
60
|
+
private
|
61
|
+
|
62
|
+
def set_uuid
|
63
|
+
self.uuid ||= SecureRandom.uuid
|
64
|
+
end
|
57
65
|
end
|
58
66
|
end
|
59
67
|
end
|
data/lib/symphonia/version.rb
CHANGED
@@ -90,7 +90,7 @@ module Symphonia
|
|
90
90
|
subject { FactoryBot.create :user }
|
91
91
|
it "reset" do
|
92
92
|
put :reset_password, params: { id: subject.perishable_token, password: "secret-pass-1" }
|
93
|
-
expect(response).to redirect_to /
|
93
|
+
expect(response).to redirect_to /login/
|
94
94
|
expect { subject.reload }.to change(subject, :crypted_password)
|
95
95
|
end
|
96
96
|
end
|
data/spec/factories/factories.rb
CHANGED
@@ -2,7 +2,7 @@ FactoryBot.define do
|
|
2
2
|
factory :user, class: 'Symphonia::User', aliases: [:author] do
|
3
3
|
sequence(:first_name) { |n| "#{Faker::Name.first_name} #{n}" }
|
4
4
|
sequence(:last_name) { |n| "#{Faker::Name.last_name} #{n}" }
|
5
|
-
sequence(:email) { |n| "#{n}
|
5
|
+
sequence(:email) { |n| "#{n}-#{Faker::Internet.email}" }
|
6
6
|
login { email }
|
7
7
|
admin { false }
|
8
8
|
password { SecureRandom.hex(16) }
|
@@ -26,19 +26,7 @@ FactoryBot.define do
|
|
26
26
|
factory :role, class: 'Symphonia::Role' do
|
27
27
|
sequence(:name) { |n| "#{Faker::Job.title} #{n}" }
|
28
28
|
end
|
29
|
-
|
30
|
-
# factory :attachment, class: 'Symphonia::Attachment' do
|
31
|
-
# association :attachable, factory: :user
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# factory :file, parent: :attachment, class: 'Symphonia::CommonFile' do
|
35
|
-
# attachment { File.new(File.expand_path('../../support/common_file.txt', __FILE__)) }
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# factory :image, parent: :attachment, class: 'Symphonia::Image' do
|
39
|
-
# attachment { File.new(File.expand_path('../../support/symphonia.jpg', __FILE__)) }
|
40
|
-
# end
|
41
|
-
|
29
|
+
|
42
30
|
factory :preference, class: 'Symphonia::Preference' do
|
43
31
|
|
44
32
|
factory :email_preference, class: 'Symphonia::EmailPreference' do
|
@@ -10,7 +10,7 @@ module Symphonia
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def reset_password_user
|
13
|
-
Notifier.reset_password_user(User.last)
|
13
|
+
Notifier.reset_password_user(User.last, "http://symphonia.app/reset?id=123")
|
14
14
|
end
|
15
15
|
|
16
16
|
def activation_user
|
@@ -21,7 +21,6 @@ module Symphonia
|
|
21
21
|
Notifier.user_change_to_active(User.last)
|
22
22
|
end
|
23
23
|
|
24
|
-
|
25
24
|
end
|
26
25
|
|
27
26
|
end
|
@@ -45,7 +45,7 @@ module Symphonia
|
|
45
45
|
end
|
46
46
|
|
47
47
|
context '#reset_password_user' do
|
48
|
-
let(:mail) { described_class.reset_password_user(user) }
|
48
|
+
let(:mail) { described_class.reset_password_user(user, Symphonia::Engine.routes.url_helpers.reset_password_path(user.perishable_token)) }
|
49
49
|
|
50
50
|
it 'renders the headers' do
|
51
51
|
expect(mail.subject).to match 'heslo'
|
@@ -61,7 +61,7 @@ describe Symphonia::AccountsController do
|
|
61
61
|
|
62
62
|
it 'html' do
|
63
63
|
get symphonia.lost_password_account_path
|
64
|
-
expect(response).to have_http_status :
|
64
|
+
expect(response).to have_http_status :redirect
|
65
65
|
end
|
66
66
|
|
67
67
|
end
|
@@ -91,7 +91,7 @@ describe Symphonia::AccountsController do
|
|
91
91
|
|
92
92
|
it 'valid token' do
|
93
93
|
put symphonia.reset_password_account_path(id: token, password: password, password_confirmation: password)
|
94
|
-
expect(response).to redirect_to
|
94
|
+
expect(response).to redirect_to /login/
|
95
95
|
expect(flash[:notice]).not_to be :blank
|
96
96
|
end
|
97
97
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: symphonia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.3.
|
4
|
+
version: 3.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lukas Pokorny
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 6.
|
75
|
+
version: 6.2.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 6.
|
82
|
+
version: 6.2.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: scrypt
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,20 +234,6 @@ dependencies:
|
|
234
234
|
- - "~>"
|
235
235
|
- !ruby/object:Gem::Version
|
236
236
|
version: 4.4.0
|
237
|
-
- !ruby/object:Gem::Dependency
|
238
|
-
name: the_sortable_tree
|
239
|
-
requirement: !ruby/object:Gem::Requirement
|
240
|
-
requirements:
|
241
|
-
- - '='
|
242
|
-
- !ruby/object:Gem::Version
|
243
|
-
version: 2.6.1
|
244
|
-
type: :runtime
|
245
|
-
prerelease: false
|
246
|
-
version_requirements: !ruby/object:Gem::Requirement
|
247
|
-
requirements:
|
248
|
-
- - '='
|
249
|
-
- !ruby/object:Gem::Version
|
250
|
-
version: 2.6.1
|
251
237
|
- !ruby/object:Gem::Dependency
|
252
238
|
name: bootstrap-datepicker-rails
|
253
239
|
requirement: !ruby/object:Gem::Requirement
|
@@ -591,13 +577,11 @@ files:
|
|
591
577
|
- spec/requests/roles_spec.rb
|
592
578
|
- spec/requests/users_spec.rb
|
593
579
|
- spec/spec_helper.rb
|
594
|
-
- spec/support/common_file.txt
|
595
580
|
- spec/support/query.rb
|
596
581
|
- spec/support/shared.rb
|
597
582
|
- spec/support/shared_controllers.rb
|
598
583
|
- spec/support/shared_requests.rb
|
599
584
|
- spec/support/stub_users.rb
|
600
|
-
- spec/support/symphonia.jpg
|
601
585
|
- spec/support/wait_for_ajax.rb
|
602
586
|
- spec/version_spec.rb
|
603
587
|
- spec/views/filters/options.html.erb_spec.rb
|
@@ -621,7 +605,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
621
605
|
version: '0'
|
622
606
|
requirements: []
|
623
607
|
rubygems_version: 3.0.6
|
624
|
-
signing_key:
|
608
|
+
signing_key:
|
625
609
|
specification_version: 4
|
626
610
|
summary: My administration
|
627
611
|
test_files:
|
@@ -638,9 +622,7 @@ test_files:
|
|
638
622
|
- spec/requests/login_spec.rb
|
639
623
|
- spec/requests/accounts_spec.rb
|
640
624
|
- spec/requests/users_spec.rb
|
641
|
-
- spec/support/symphonia.jpg
|
642
625
|
- spec/support/stub_users.rb
|
643
|
-
- spec/support/common_file.txt
|
644
626
|
- spec/support/shared.rb
|
645
627
|
- spec/support/wait_for_ajax.rb
|
646
628
|
- spec/support/shared_controllers.rb
|
@@ -1,2 +0,0 @@
|
|
1
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris dolor felis, sagittis at, luctus sed, aliquam non, tellus. Etiam dictum tincidunt diam. Suspendisse sagittis ultrices augue. Nullam justo enim, consectetuer nec, ullamcorper ac, vestibulum in, elit. Nulla quis diam. Duis bibendum, lectus ut viverra rhoncus, dolor nunc faucibus libero, eget facilisis enim ipsum id lacus. Sed convallis magna eu sem. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nulla accumsan, elit sit amet varius semper, nulla mauris mollis quam, tempor suscipit diam nulla vel leo. Nullam eget nisl. Pellentesque pretium lectus id turpis. Proin in tellus sit amet nibh dignissim sagittis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam commodo dui eget wisi. Nunc auctor. Vivamus porttitor turpis ac leo. Nullam sapien sem, ornare ac, nonummy non, lobortis a enim. In sem justo, commodo ut, suscipit at, pharetra vitae, orci.
|
2
|
-
|
data/spec/support/symphonia.jpg
DELETED
Binary file
|