Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Every configuration setting has been moved in groups within separate classes.
The syntax is always Udongo.config.[namespace].[setting]
Udongo.config.base.host = 'udongo.dev'
Udongo.config.base.project_name = 'Udongo'
Udongo.config.base.time_zone = 'Brussels'
Udongo.config.pages.images = false
Udongo.config.tags.allow_new = false
Udongo.config.i18n.app.default_locale = :nl
Udongo.config.i18n.app.locales = %w(nl)
Udongo.config.i18n.app.default_interface_locale = 'nl'
Udongo.config.i18n.app.interface_locales = %w(nl en)
Udongo.config.flexible_content.types = %w(text picture video)
Udongo.config.flexible_content.picture_caption_editor = false
Udongo.config.flexible_content.video_caption_editor = false
Udongo.config.image_white_list = %w(gif jpeg jpg png)
Udongo.config.file_white_list = %w(doc docx pdf txt xls xlsx)
Udongo.config.articles.allow_html_in_title = false
Udongo.config.articles.allow_html_in_summary = false
Udongo.config.articles.editor_for_summary = false
Udongo.config.articles.images = true
class User < ApplicationRecord
include Concerns::Storable
storable_field :gender, String, 'male'
storable_field :age, Integer
storable_field :last_login_at, DateTime
storable_field :cool_dude, Boolean, true
storable_field :locales, Array, %w(nl)
storable_field :birthday, Date
end
u = User.first
u.gender
# Which is equal to
u.store(:default).gender
u = User.first
u.gender = 'female'
# Which is equal to
u.store(:default).gender = 'female'
u = User.first
u.gender = 'female'
u.save
u.store(:custom).gender = 'unknown'
u.save
When you save the parent object (user), all the store collections will automatically be saved.
This concern is actually the storable concern with some predefined settings. In order to use this concern your model needs to have a database text field named locales
.
class Document < ApplicationRecord
include Concerns::Translatable
# One field
translatable_field :name
# Multiple fields
translatable_fields :description, :summary
end
It also allows you to do something like this Page.with_locale(:nl)
which
will then fetch all pages that have the translatable fields in :nl avaialble.
This concern is used if you want to attach (seo) meta details to your model. In order to use this, you need to add a text colun 'seo_locales' to your model.
class Document < ApplicationRecord
include Concerns::Seo
end
This will then allow you to fetch all documents that have seo (with slug!) in
a certain locale. Document.with_seo(:nl)
Include this in your model if you want its records to appear in search autocompletes.
class Document < ApplicationRecord
include Concerns::Searchable
# One field
searchable_field :title
# Multiple fields
searchable_fields :title, :description, :summary
end
When reading values the current I18n.locale
is used. If you want to specify the locale, you need to use the longer syntax.
d = Document.first
d.name
# Which is equal to
d.translation(:nl).name
d = Document.first
d.name = 'foo'
# Which is equal to
d.translation(:nl).name = 'foo'
Make sure to always call the #save
method on your model. You can call the one on the translation, but this will not trigger an update for the locales
field.
d = Document.first
d.name = 'foo'
d.save
d.translation(:nl).foo
d.save
When you save the parent object (document), all the translations will automatically be saved.
This concern adds a scope to your model which makes it easy to fetch the models that have translations within a certain locale.
documents = Document.by_locale(:nl)
This concern makes it easy to have multiple addresses with a category linked to a model.
class User < ApplicationRecord
include Concerns::Addressable
configure_address %w(personal billing), default: 'personal'
end
If you don't provide a default, we will use the first one in the list.
If you request an address that's not initialized this will be done for you. So calling #address
, with or without category, will always return an address model.
u = User.first
u.address
# Which is equal to
u.address(:personal)
There's an Attachment
model that links to the assets. If an asset is linked to an attachment it can't be deleted. You can use this feature to use files linked to the asset module that can't be deleted when in use.
You can add tasks to the queue by executing:
QueuedTask.queue('SomeClass', id: 37, foo: bar)
The first paramter specifiecs the string of the class you want to execute the run method from. The second parameter is a hash that contains most scalar values.
class SomeClass
def initialize(data)
@id = data[:id]
@foo = data[:foo]
end
def run!
# add code to run
end
end
rake udongo:queue:process
validates :email, email: true
validates :url, url: true
There's a serialized field attachments
in the emails table. This expects
the following format.
[{ name: 'foo.pdf', filename: '1..256/[random-id]-[name]-[current_time].[extension]' }]
The name is what will be shown in the e-mail, the filename is the location of the actual file that is attached to this e-mail. The file is assumed to be stored in the following dir.
public/uploads/mail_attachments/[filename]
4.0 introduced a rough structure to build a search autocomplete upon through Concerns::Searchable
.
Included in Udongo by default is the backend search, which makes Page records accessible through an autocomplete. In order to build search support for a model, we have to make it include the concern:
# app/models/page.rb
class Page
include Concerns::Searchable
searchable_fields :title, :subtitle, :flexible_content
end
Concerns::Searchable
saves SearchIndex
records to our database whenever a model gets saved. Support for both Concern::Translatable
and Concern::FlexibleContent
is built in, meaning that translatable fields can also be searchable fields.
By including :flexible_content
as a searchable field, we flag it to build search indices for all flexible content of the ContentText
type.
Backend::SearchController#index
contains a call to Udongo::Search::Backend
. That class is responsible for matching a search term against the available search indices:
# app/controllers/backend/search_controller.rb
class Backend::SearchController < Backend::BaseController
def query
@results = Udongo::Search::Backend.new(params[:term], controller: self).search
render json: @results
end
end
Udongo::Search::Backend#search
in turn translates those indices in a format that jQueryUI's autocomplete understands: { label: 'foo', value: 'bar' }
.
# lib/udongo/search/backend.rb
module Udongo::Search
class Backend < Udongo::Search::Base
def search
indices.map do |index|
result = result_object(index)
{ label: result.build_html, value: result.url }
end
end
end
end
By default the #result_object
is an instance of Udongo::Search::ResultObjects::Base
. You can define your own result object class, which in this example is done for the Page
model:
# lib/udongo/search/result_objects/page.rb
module Udongo::Search::ResultObjects
class Page < Udongo::Search::ResultObjects::Base
def url
if namespace == :backend
controller.edit_backend_page_path(index.searchable)
end
end
end
end
This gives devs a way to extend the data for use in jQueryUI's autocomplete, or simply to mutate the index data. In the example above, we check what namespace we reside in in order to generate an edit link to the relevant page in the pages module. If one were to build a search for the frontend that includes pages, you could build the required URL for it here.
Support for HTML labels is automatically included through vendor/assets/javascripts/jquery-ui.autocomplete.html.js`. The labels should reside in partial files and be rendered with
Udongo::Search::ResultObjects::Base#build_html```. This provide support for funkier autocomplete result structures:
<!-- app/views/backend/search/_page.html.erb -->
<%= t('b.page') %> — <%= page.title %><br />
<small>
<%= truncate(page.description, length: 40) %>
</small>
Udongo::Cryptography
is a module you can include in any class to provide you with functionality to encrypt and decrypt values. It is a wrapper that currently uses ActiveSupport::MessageEncryptor
, which in turns uses the Rails secret key to encrypt keys.
By default, it is included in Backend::BaseController
.
Include the Udongo::Cryptography module in the class where you wish to encrypt/decrypt:
def YourClass
include Udongo::Cryptography
end
crypt.encrypt('foo')
=> "azZiS1lPVU8zV1ljOTdjM2tIM2hTdz09LS1PODc5OEprRmxlMFVMU1lqaDdXK25RPT0=--77983f6f21e31117ac15011fed52dac3fdf776a8"
crypt.encrypt('foo')
=> "bEFwVHVDV1hVc29UUmhJK1RQcllYUT09LS03WkZVYTdkOVhIQnloa1czUkE3L1V3PT0=--3fcc73bd6c11874966bb23811ad48980a44e40e7"
crypt.decrypt('azZiS1lPVU8zV1ljOTdjM2tIM2hTdz09LS1PODc5OEprRmxlMFVMU1lqaDdXK25RPT0=--77983f6f21e31117ac15011fed52dac3fdf776a8')
=> "foo"
crypt.decrypt('bEFwVHVDV1hVc29UUmhJK1RQcllYUT09LS03WkZVYTdkOVhIQnloa1czUkE3L1V3PT0=--3fcc73bd6c11874966bb23811ad48980a44e40e7')
=> "foo"
As the examples above illustrate, each subsequent encrypt always returns a different, decryptable hash.
You can pass a different secret to crypt
:
def Example
def foo
crypt('1234567890123456789012345678901234567890').encrypt('foo')
end
end
You can also roll your own Udongo::Cryptography module, for example in Rails 3.2 the secret token is named differently:
# lib/udongo/cryptography.rb
def Udongo::Cryptography
def crypt
@crypt ||= Udongo::Crypt.new(secret: Rails.configuration.secret_token)
end
end
crypt = Udongo::Crypt.new(secret: '1234567890123456789012345678901234567890')
=> #<Udongo::Crypt:0x007fcb1a0f3b50 @options={:secret=>"1234567890123456789012345678901234567890"}>
crypt.encrypt('foo')
=> "YXhsZDV4RlZLTnljclhvM3pKbmV3Zz09LS1ycVR4bEtZemh2UUVKVlBQRnhlcjZRPT0=--f23e37ef7fb94e94cfa8a509f93bdb94e4bc5552"
There are two custom inputs in Udongo to help handles dates. DatePickerInput
and DateRangePickerInput
. Both make use of the bootstrap-datepicker JS plugin. You can set/override its defaults through data-attributes, as explained in the docs.
Applying as: :date_picker
to a simple_form input will bind a datepicker with all the default events bound:
<%= f.input :date, as: :date_picker %>
You can combine two datepicker input fields into a range picker by applying as: :date_range_picker
to 2 different simple_form input fields.
This will link a datepicker to each input with its relevant change listeners bound to prevent you from selecting a start date past the stop date, and vice versa:
<%= f.input :start_date, as: :date_range_picker, start: 'foo' %>
<%= f.input :stop_date, as: :date_range_picker, stop: 'foo' %>
The value used in the start
and stop
attributes needs to be the same for two datepicker fields to be combined into a range picker. If these values don't match, your pickers won't display the intended behaviour.
The Udongo::Notification
class provides a generic way to parse action notices without directly interacting with I18n
. Its translate
method can be used in a number of ways:
nl:
b:
msg:
refreshed: De pagina werd opnieuw ingeladen.
irb(main):001:0> Udongo::Notification.new(:refreshed).translate
=> "De pagina werd opnieuw ingeladen."
nl:
b:
admin: Beheerder
msg:
added: '%{actor} werd toegevoegd.'
irb(main):001:0> Udongo::Notification.new(:added).translate(:admin)
=> "Beheerder werd toegevoegd."
nl:
b:
msg:
added: '%{name} werd toegevoegd met %{pies} taarten.'
irb(main):001:0> Udongo::Notification.new(:added).translate(name: 'Dave', pies: 10)
=> "Dave werd toegevoegd met 10 taarten."
Backend::BaseController#translate_notice
uses Udongo::Notification
to output translated notices. Typically this is used in tandem with redirects. For example in the admins module:
class Backend::AdminsController < Backend::BaseController
def create
redirect_to backend_admins_path, notice: translate_notice(:added, :admin)
end
end
Find a snippet from cache by its identifier and decorate it.
snippet(:identifier)
Find a page from cache by its identifier and decorate it.
page(:identifier)
Find a navigation from cache by its identifier.
navigation(:identifier)
This library is loaded by default in the backend. See https://select2.github.io
You can add SEO fields to your form by rendering a partial:
<%= simple_form_for([:backend, @your_model]) do |f| %>
...
<%= render 'backend/seo_form', f: f %>
...
<% end %>
This partial has support to let you base its SEO slug on whatever is typed in an input element of your choice. In Udongo, this field is called the sluggable field.
By default, the partial looks for a field called title. You can override
this name by passing sluggable_field
to the partial, like so:
<%= simple_form_for([:backend, @your_model]) do |f| %>
...
<%# This will look for #backend_your_model_name as its sluggable field. %>
<%= render 'backend/seo_form', f: f, sluggable_field: :name %>
...
<% end %>
Sometimes a user enters some data in a form and assumes that everything is magically saved without submitting said form.
To warn a user that this is not default behaviour, you can trigger a warning
to show up whenever a user has changed input contents and clicks on any
<a>
element on the page.
Simply call the following helper method within your form tags:
<%= simple_form_for([:backend, @your_model]) do |f| %>
<%= trigger_dirty_inputs_warning %>
...
<% end %>
This renders the following HTML:
<form class="simple_form" id="edit_your_model_1" action="/backend/your_models/1/edit" accept-charset="UTF-8" method="post">
...
<span data-dirty="false"></span>
...
</form>
You can also override the default message with your own:
<%= simple_form_for([:backend, @your_model]) do |f| %>
<%= trigger_dirty_inputs_warning(message: 'Are you sure you want to leave the page?') %>
...
<% end %>
FAQs
Unknown package
We found that udongo demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.