rmails 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +15 -0
- data/Vagrantfile +1 -1
- data/app/assets/javascripts/controls/domains.coffee.erb +68 -75
- data/app/assets/javascripts/models/domain.coffee.erb +4 -3
- data/app/assets/stylesheets/application.sass +5 -13
- data/app/assets/stylesheets/base.css.sass +0 -4
- data/app/controllers/domains_controller.rb +1 -1
- data/app/models/virtual_domain.rb +6 -0
- data/app/models/virtual_user.rb +2 -2
- data/app/views/admin_users/first.html.haml +0 -1
- data/app/views/aliases/_templates.html.haml +29 -0
- data/app/views/domains/_templates.html.haml +71 -0
- data/app/views/domains/index.html.haml +9 -114
- data/app/views/users/_form.html.haml +4 -2
- data/app/views/users/_templates.html.haml +27 -0
- data/bin/rmails +14 -5
- data/config/locales/server/help/dovecot/cz.yml +4 -2
- data/config/locales/server/key/dovecot/en.yml +17 -17
- data/config/locales/views/aliases/cz.yml +3 -1
- data/config/locales/views/aliases/en.yml +20 -0
- data/config/locales/views/domains/cz.yml +1 -1
- data/config/locales/views/domains/en.yml +11 -10
- data/config/locales/views/server/cz.yml +1 -0
- data/config/locales/views/users/cz.yml +8 -2
- data/config/locales/views/users/en.yml +22 -0
- data/db/migrate/20121112201341_virtual_user.rb +0 -8
- data/lib/rmails/installer.rb +12 -3
- data/lib/rmails/version.rb +2 -2
- data/public/assets/{application-83367ef0d1b7ecb80fbc1ba279811151.js → application-3b8b925cdaedaadcce73613bb5c35985.js} +1 -1
- data/public/assets/{application-83367ef0d1b7ecb80fbc1ba279811151.js.gz → application-3b8b925cdaedaadcce73613bb5c35985.js.gz} +0 -0
- data/public/assets/application-ab23db04de6609ba65d1ee5a378d5735.css +1 -0
- data/public/assets/{application-7b6b5d175d26fb23a5584728dc35220f.css.gz → application-ab23db04de6609ba65d1ee5a378d5735.css.gz} +0 -0
- data/public/assets/application.css +1 -1
- data/public/assets/application.css.gz +0 -0
- data/public/assets/application.js +1 -1
- data/public/assets/application.js.gz +0 -0
- data/public/assets/manifest.yml +26 -26
- data/system/dist/rmails/Gemfile.2 +1 -0
- metadata +10 -6
- data/public/assets/application-7b6b5d175d26fb23a5584728dc35220f.css +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f401f448f9d918ccaf166213e68aab5c2e960a68
|
4
|
+
data.tar.gz: b0005de980f5159a5095ab98c32ef7af3f6c7bfb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d03c6d4acacde0f7c16a54d146f2b02585720e9bf30da126fd4221c5ef6c67d915ff66583be37e9f5ca8480f8bd07ca6d86f8e7600874645342c798b6bb0344
|
7
|
+
data.tar.gz: 1d53cfbc754550f2849e9235f1b1162bfbde10474bc7a40f4b0ea2657d5cc2ff91ba30ce8698e7b4bc204cc148e0b98869e963563c7724dc37ce3e95c304bd31
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
data/Vagrantfile
CHANGED
@@ -21,7 +21,7 @@ Vagrant::Config.run do |config|
|
|
21
21
|
c.vm.box = "debian32"
|
22
22
|
c.vm.forward_port 80, 8091
|
23
23
|
c.vm.forward_port 3000, 4001
|
24
|
-
c.vm.forward_port 25,
|
24
|
+
c.vm.forward_port 25, 1125
|
25
25
|
c.vm.forward_port 587, 11587
|
26
26
|
c.vm.forward_port 110, 11110
|
27
27
|
c.vm.forward_port 995, 11995
|
@@ -1,3 +1,7 @@
|
|
1
|
+
can.route( ':action/:id' )
|
2
|
+
can.route( ':action' )
|
3
|
+
|
4
|
+
|
1
5
|
window.Domains = can.Control({
|
2
6
|
|
3
7
|
init: (el, opt) ->
|
@@ -5,6 +9,27 @@ window.Domains = can.Control({
|
|
5
9
|
@model = Domain.models JSON.parse($('#domains_JSON').text())
|
6
10
|
return
|
7
11
|
|
12
|
+
render_manage_area: (li, item) ->
|
13
|
+
li.addClass('open').find('.item').append( can.view( 'manage_area_EJS' ) )
|
14
|
+
users = new Users(li.find('.item .users'), {
|
15
|
+
items: item["virtual_users"]
|
16
|
+
domain_id: item.id
|
17
|
+
domain_name: item.name
|
18
|
+
})
|
19
|
+
aliases = new Aliases(li.find('.item .aliases'), {
|
20
|
+
items: item["virtual_aliases"]
|
21
|
+
domain_id: item.id
|
22
|
+
domain_name: item.name
|
23
|
+
})
|
24
|
+
|
25
|
+
close_manage_area: (li) ->
|
26
|
+
li.find('.nomanage').hide()
|
27
|
+
li.find('.manage').show()
|
28
|
+
li.removeClass('open')
|
29
|
+
it = li.find('.item .item-content:last')
|
30
|
+
if it.hasClass('out')
|
31
|
+
it.remove()
|
32
|
+
|
8
33
|
"form reset": (el, ev) ->
|
9
34
|
li = el.parents('li')
|
10
35
|
if li.hasClass('empty')
|
@@ -16,22 +41,12 @@ window.Domains = can.Control({
|
|
16
41
|
li.find('.item').html(
|
17
42
|
can.view( 'domain_item_EJS', { item: item } )
|
18
43
|
)
|
19
|
-
|
20
|
-
".add-domain click": (el, ev) ->
|
21
|
-
ev.preventDefault()
|
22
|
-
$('#domains .empty').remove()
|
23
|
-
$('#domains').prepend(can.view( 'domain_form_EJS', { item: new Domain } ))
|
24
|
-
$('.add-domain').toggle()
|
25
|
-
|
26
|
-
".rm-domain click": (el, ev) ->
|
27
|
-
ev.preventDefault()
|
28
|
-
$('#domains .empty').remove()
|
29
|
-
$('.add-domain').toggle()
|
44
|
+
can.route.attr('action', '' )
|
30
45
|
|
31
46
|
"#new_virtual_domain submit": (el, ev) ->
|
32
47
|
ev.preventDefault()
|
33
|
-
self = this
|
34
48
|
values = el.formParams()
|
49
|
+
self = this
|
35
50
|
item = new Domain(values["virtual_domain"])
|
36
51
|
if item.errors() # validation error
|
37
52
|
item.alert()
|
@@ -45,71 +60,49 @@ window.Domains = can.Control({
|
|
45
60
|
)
|
46
61
|
else
|
47
62
|
# post-creation hook
|
48
|
-
item.attr(
|
49
|
-
li.removeClass('empty').attr('id', 'domain_'+
|
50
|
-
# show links to edit and remove with right id
|
51
|
-
li.find('.item').html(
|
52
|
-
can.view( 'domain_item_EJS', { item: item } )
|
53
|
-
).find('.btn-group a').attr('href', (i, v) ->
|
54
|
-
return unescape(v).replace(/{id}/g, json.id)
|
55
|
-
)
|
56
|
-
self.model.unshift(item)
|
57
|
-
$('.add-domain').toggle()
|
63
|
+
item.attr(json.domain)
|
64
|
+
li.removeClass('empty').attr('id', 'domain_'+item.attr('id'))
|
58
65
|
)
|
66
|
+
# show links to edit and remove with right id
|
67
|
+
li.find('.item').html( can.view( 'domain_item_EJS', { item: item } ) )
|
68
|
+
@model.unshift(item)
|
69
|
+
$('.add-domain').toggle()
|
59
70
|
|
71
|
+
":action route": (a) ->
|
72
|
+
# action NEW
|
73
|
+
if a["action"] == 'new'
|
74
|
+
$('#domains .empty').remove()
|
75
|
+
$('#domains').prepend(can.view( 'domain_form_EJS', { item: new Domain } ))
|
76
|
+
$('.add-domain').toggle()
|
60
77
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
el.removeClass('label-info')
|
91
|
-
else
|
92
|
-
el.addClass('label-info')
|
93
|
-
li.find('.item-content:last').remove()
|
94
|
-
return false
|
95
|
-
|
96
|
-
id = li.attr('id').replace('domain_','')
|
97
|
-
item = @model.with_id(parseInt(id))
|
98
|
-
if li.find('.item .item-content:last').hasClass('out')
|
99
|
-
return false
|
100
|
-
li.find('.item').append(
|
101
|
-
can.view( 'manage_area_EJS' )
|
102
|
-
)
|
103
|
-
users = new Users(li.find('.item .users'), {
|
104
|
-
items: item["virtual_users"]
|
105
|
-
domain_id: id
|
106
|
-
domain_name: item.name
|
107
|
-
})
|
108
|
-
aliases = new Aliases(li.find('.item .aliases'), {
|
109
|
-
items: item["virtual_aliases"]
|
110
|
-
domain_id: id
|
111
|
-
domain_name: item.name
|
112
|
-
})
|
113
|
-
return false
|
78
|
+
":action/:id route": (params) ->
|
79
|
+
li = $("#domain_" + params["id"])
|
80
|
+
item = @model.with_id(parseInt(params["id"]))
|
81
|
+
self = this
|
82
|
+
# action EDIT
|
83
|
+
if params["action"] == 'edit'
|
84
|
+
li.find('.item').html(can.view( 'domain_edit_EJS', { item: item } ))
|
85
|
+
li.addClass('inedit')
|
86
|
+
# action DELETE
|
87
|
+
else if params["action"] == 'delete'
|
88
|
+
if confirm(li.find('.rm').data('msg'))
|
89
|
+
Domain.destroy(item, (json) ->
|
90
|
+
if json["errors"]
|
91
|
+
alert(json["errors"])
|
92
|
+
else
|
93
|
+
# delete from local Model.list
|
94
|
+
self.model.splice(self.model.indexOf(item), 1)
|
95
|
+
li.remove()
|
96
|
+
)
|
97
|
+
can.route.attr({action:''})
|
98
|
+
# action SHOW
|
99
|
+
else if params["action"] == 'show'
|
100
|
+
li.find('.manage').hide()
|
101
|
+
li.find('.nomanage').show()
|
102
|
+
@close_manage_area($('.open'))
|
103
|
+
@render_manage_area(li, item)
|
104
|
+
# action HIDE
|
105
|
+
else if params["action"] == 'hide'
|
106
|
+
@close_manage_area(li)
|
114
107
|
|
115
108
|
})
|
@@ -11,7 +11,9 @@ window.Domain = can.Model({
|
|
11
11
|
url = unescape('<%= Rails.application.routes.url_helpers.domain_path('{id}') %>').replace('{id}', domain.id)
|
12
12
|
return $.post(url, attrs, null, "json")
|
13
13
|
|
14
|
-
destroy : (
|
14
|
+
destroy : (item, callback) ->
|
15
|
+
url = unescape('<%= Rails.application.routes.url_helpers.domain_path('{id}') %>').replace("{id}", item.id)
|
16
|
+
return $.post(url, {"_method":"DELETE"}, callback, "json")
|
15
17
|
|
16
18
|
|
17
19
|
attributes: {
|
@@ -20,8 +22,7 @@ window.Domain = can.Model({
|
|
20
22
|
},
|
21
23
|
|
22
24
|
init: () ->
|
23
|
-
@
|
24
|
-
#@validateFormatOf ['name'], /\A(?:[-a-z0-9]+\.)+[a-z]{2,}\Z/i
|
25
|
+
@validateFormatOf ['name'], /^(?:[-a-z0-9]+\.)+[a-z]{2,}$/i
|
25
26
|
|
26
27
|
}, {})
|
27
28
|
|
@@ -91,8 +91,7 @@ header
|
|
91
91
|
display: inline-block
|
92
92
|
background: transparent
|
93
93
|
border: none
|
94
|
-
|
95
|
-
display: inline
|
94
|
+
|
96
95
|
//.actions
|
97
96
|
float: right
|
98
97
|
//.inputs
|
@@ -103,15 +102,12 @@ header
|
|
103
102
|
#rmails
|
104
103
|
.list .table
|
105
104
|
tr td
|
106
|
-
|
105
|
+
.aliases
|
107
106
|
display: inline-block
|
108
107
|
.help-block
|
109
108
|
display: block !important
|
110
109
|
|
111
|
-
|
112
|
-
display: inline !important
|
113
|
-
|
114
|
-
.aliases, .users
|
110
|
+
.aliases
|
115
111
|
margin: 0
|
116
112
|
label
|
117
113
|
display: block !important
|
@@ -126,9 +122,6 @@ header
|
|
126
122
|
width: 100%
|
127
123
|
.control-group
|
128
124
|
vertical-align: top
|
129
|
-
|
130
|
-
.aliases
|
131
|
-
.control-group
|
132
125
|
float: left
|
133
126
|
input.string, textarea
|
134
127
|
display: block !important
|
@@ -144,9 +137,8 @@ header
|
|
144
137
|
padding: 3px
|
145
138
|
|
146
139
|
.users
|
147
|
-
|
148
|
-
|
149
|
-
display: inline-block !important
|
140
|
+
|
141
|
+
|
150
142
|
|
151
143
|
#system
|
152
144
|
/*.control-label
|
@@ -21,7 +21,7 @@ class DomainsController < ApplicationController
|
|
21
21
|
def create # JSON only
|
22
22
|
@domain = current_admin_user.build_domain(params[:virtual_domain])
|
23
23
|
if @domain.save
|
24
|
-
render :json => {:
|
24
|
+
render :json => {:domain => @domain}
|
25
25
|
else
|
26
26
|
render :json => {:errors => @domain.errors}
|
27
27
|
end
|
data/app/models/virtual_user.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
class VirtualUser < ActiveRecord::Base
|
2
2
|
|
3
3
|
devise :database_authenticatable, :encryptable,
|
4
|
-
:recoverable, :rememberable, :
|
4
|
+
:recoverable, :rememberable, :validatable,
|
5
5
|
:encryptor => :dovecot_ssha512, :stretches => 1
|
6
6
|
|
7
7
|
belongs_to :virtual_domain
|
8
8
|
|
9
|
-
attr_accessible :name, :email, :password, :
|
9
|
+
attr_accessible :name, :email, :password, :quota_kb, :quota_messages
|
10
10
|
|
11
11
|
before_validation :repair_email_format
|
12
12
|
|
@@ -7,6 +7,5 @@
|
|
7
7
|
= f.input :name, :label => t('.name')
|
8
8
|
= f.input :email, :label => t('.email')
|
9
9
|
= f.input :password, :label => t('.pass'), :required => true
|
10
|
-
= f.input :password_confirmation, :label => t('.passs')
|
11
10
|
|
12
11
|
= f.button :button, t('.create'), :type => 'submit', :class => 'btn-primary'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
%script#aliass_each_EJS{"type" => "text/ejs"}
|
2
|
+
:plain
|
3
|
+
<% list (items, function(item, index) { %>
|
4
|
+
<tr id="alias_<%= index %>">
|
5
|
+
%td.tar
|
6
|
+
:plain
|
7
|
+
<%= item.source %>
|
8
|
+
%td
|
9
|
+
%b
|
10
|
+
:plain
|
11
|
+
@<%= domain_name %>
|
12
|
+
%i.icon-hand-right
|
13
|
+
%td
|
14
|
+
:plain
|
15
|
+
<%= item.destination %>
|
16
|
+
%td.tar
|
17
|
+
= link_to t(".edit"), edit_domain_alias_path('{domain_id}', '{id}'), :class => 'label edit-alias'
|
18
|
+
= link_to "×".html_safe, domain_alias_path('{domain_id}', '{id}'), :class => 'rm-alias', :title => t(".delete")
|
19
|
+
:plain
|
20
|
+
</tr>
|
21
|
+
<% }) %>
|
22
|
+
|
23
|
+
%script#aliass_tabr_EJS{"type" => "text/ejs"}
|
24
|
+
%tr.new
|
25
|
+
|
26
|
+
%script#aliass_form_EJS{"type" => "text/ejs"}
|
27
|
+
%td{:colspan => "4"}
|
28
|
+
= render :partial => '/aliases/form', :locals => { :virtual_alias => alias_ejs_object }
|
29
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
%script#domain_form_EJS{"type" => "text/ejs"}
|
2
|
+
%li.empty
|
3
|
+
.item
|
4
|
+
.iconat @
|
5
|
+
= render :partial => 'form', :locals => { :domain => domain_ejs_object }
|
6
|
+
.out
|
7
|
+
|
8
|
+
%script#domain_edit_EJS{"type" => "text/ejs"}
|
9
|
+
.iconat @
|
10
|
+
= render :partial => 'form', :locals => { :domain => domain_ejs_object }
|
11
|
+
.out
|
12
|
+
|
13
|
+
%script#domain_item_EJS{"type" => "text/ejs"}
|
14
|
+
.iconat @
|
15
|
+
.btn-group
|
16
|
+
:plain
|
17
|
+
<a href="#!edit/<%= item.attr('id') %>" class="label edit">
|
18
|
+
= t("domains.index.edit")
|
19
|
+
:plain
|
20
|
+
</a>
|
21
|
+
:plain
|
22
|
+
<a href="#!delete/<%= item.attr('id') %>" class="label label-warning rm" data-msg="#{t("domains.index.confirm")}">
|
23
|
+
= t("domains.index.delete")
|
24
|
+
:plain
|
25
|
+
</a>
|
26
|
+
|
27
|
+
.item-content
|
28
|
+
:plain
|
29
|
+
<a href="#!show/<%= item.attr('id') %>" class="item-label">
|
30
|
+
<%= item.attr('name') %>
|
31
|
+
</a>
|
32
|
+
:plain
|
33
|
+
<a href="#!show/<%= item.attr('id') %>" class="label label-info manage">
|
34
|
+
= t("domains.index.manage")
|
35
|
+
:plain
|
36
|
+
</a>
|
37
|
+
|
38
|
+
:plain
|
39
|
+
<a href="#!hide/<%= item.attr('id') %>" class="label dn nomanage">
|
40
|
+
= t("domains.index.nomanage")
|
41
|
+
:plain
|
42
|
+
</a>
|
43
|
+
|
44
|
+
%script#errors_EJS{"type" => "text/ejs"}
|
45
|
+
.errors
|
46
|
+
%h6= t('domains.index.errors')
|
47
|
+
:plain
|
48
|
+
<% for (attr in errors) { %>
|
49
|
+
<% list (errors[attr], function(error) { %>
|
50
|
+
<p><%= error %></p>
|
51
|
+
<% }) %>
|
52
|
+
<% } %>
|
53
|
+
|
54
|
+
%script#manage_area_EJS{"type" => "text/ejs"}
|
55
|
+
.item-content.out.row-fluid
|
56
|
+
.span5.users
|
57
|
+
%h4
|
58
|
+
%span.title= t('users.index.title')
|
59
|
+
%span.dn.title_new= t('users.index.title_new')
|
60
|
+
%span.dn.title_edit= t('users.index.title_edit')
|
61
|
+
.label-info.label.new-user=t 'users.form.create'
|
62
|
+
%table.table.table-condensed
|
63
|
+
.span5.aliases
|
64
|
+
%h4
|
65
|
+
%span.title= t('aliases.index.title')
|
66
|
+
%span.dn.title_new= t('aliases.index.title_new')
|
67
|
+
%span.dn.title_edit= t('aliases.index.title_edit')
|
68
|
+
.label-info.label.new-alias=t 'aliases.form.create'
|
69
|
+
%table.table.table-condensed
|
70
|
+
|
71
|
+
|