Statistics
| Branch: | Tag: | Revision:

root / snf-app / synnefo / ui / static / snf / js / ui / web / ui_public_keys_view.js @ 483c9197

History | View | Annotate | Download (11.2 kB)

1
;(function(root){
2

    
3
    // root
4
    var root = root;
5
    
6
    // setup namepsaces
7
    var snf = root.synnefo = root.synnefo || {};
8
    var api = snf.api = snf.api || {};
9
    var models = snf.models = snf.models || {}
10
    var storage = snf.storage = snf.storage || {};
11
    var ui = snf.ui = snf.ui || {};
12
    var util = snf.util = snf.util || {};
13

    
14
    var views = snf.views = snf.views || {}
15

    
16
    // shortcuts
17
    var bb = root.Backbone;
18
    
19
    views.PublicKeysView = views.CollectionView.extend({
20
        collection: storage.keys,
21

    
22
        confirm_delete_msg: 'Are you sure you want to remove this key ?',
23
        create_success_msg: 'Public key created successfully.',
24
        update_success_msg: 'Public key updated successfully.',
25
        create_failed_msg: 'Failed to create public key.',
26

    
27

    
28
        initialize: function(options) {
29
            views.PublicKeysView.__super__.initialize.apply(this, arguments);
30
            this.$(".private-cont").hide();
31
            _.bindAll(this);
32
            this.keys_limit = snf.config.userdata_keys_limit || 10000;
33
            this.bind("item:add", this.animate_on_add);
34
        },
35

    
36
        animate_on_add: function(list, el, model) {
37
            el.hide();
38
            el.fadeIn(400);
39
        },
40

    
41
        append_actions: function(el, model) {
42
            var actions = $('<div class="item-actions">' +
43
                            '<div class="item-action remove">remove</div>' + 
44
                            '<div class="item-action confirm-remove">' + 
45
                            '<span class="text do-confirm">confirm</span>' + 
46
                            '<span class="cancel-remove cancel">X</span></div>' + 
47
                            '<div class="item-action edit">edit</div>' + 
48
                            '<div class="item-action show">show key</div>' + 
49
                            '</div>');
50
            el.append(actions);
51
        },
52
        
53
        close_private: function() {
54
            this.$(".private-cont").hide();
55
            this.$(".private-cont textarea").val("");   
56
            this.$('.private-cont [name=data]').val("");
57
            this.$('.private-cont [name=name]').val("");
58
        },
59

    
60
        init_handlers: function() {
61
            views.PublicKeysView.__super__.init_handlers.apply(this, arguments);
62
            
63
            this.$(".add-generate").click(_.bind(this.generate_new, this, undefined));
64

    
65
            // browser compat check
66
            if (snf.util.canReadFile()) {
67
                var self = this;
68
                this.form.find(".fromfile").get(0).addEventListener("change", function(e){
69
                    var f = undefined;
70
                    var files = e.target.files;
71
                    if (files.length == 0) { return };
72

    
73
                    f = files[0];
74
                    var data = snf.util.readFileContents(f, _.bind(function(data) {
75
                        this.form.find("textarea").val(data);   
76
                    }, self));
77
                });
78
            }
79

    
80
            var self = this;
81
            this.$(".private-cont .close-private").live("click", function(e) {
82
                self.close_private();
83
            });
84

    
85
            this.$(".item-action.show, .item-action.hide").live("click", function(e) {
86
                var open = $(this).parent().parent().parent().hasClass("expanded");
87
                if (open) {
88
                    $(this).text("show key");
89
                    $(this).addClass("show").removeClass("hide");
90
                } else {
91
                    $(this).text("hide key");
92
                    $(this).removeClass("show").addClass("hide");
93
                }
94
                $(this).parent().parent().parent().toggleClass("expanded");
95
            });
96
        },
97
        
98
        __save_new: function(generate_text, key) {
99
            var self = this;
100
            storage.keys.add_crypto_key(key.public,
101
                _.bind(function(instance, data) {
102
                    self.update_models();
103
                    this.generating = false;
104
                    this.$(".add-generate").text(generate_text).removeClass(
105
                        "in-progress").addClass("download");
106
                    this.show_download_private(instance.get('name'), key.private, instance);
107
                    this.enable_create();
108
                },this),
109

    
110
                _.bind(function() {
111
                    self.show_list_msg("error", "Cannot generate public key, please try again later.");
112
                    
113
                    this.generating = false;
114
                    this.download_private = false;
115

    
116
                    this.$(".add-generate").text(generate_text).removeClass("in-progress").removeClass("download");
117
                    this.enable_create();
118
                }, this)
119
            );
120
        },
121

    
122
        __generate_new: function(generate_text) {
123
            var self = this;
124
            var key = storage.keys.generate_new(_.bind(this.__save_new, this, generate_text), function(xhr){
125
                var resp_error = "";
126
                // try to parse response
127
                try {
128
                    json_resp = JSON.parse(xhr.responseText);
129
                    resp_error = json_resp.errors[json_resp.non_field_key].join("<br />");
130
                } catch (err) {}
131
                
132
                var msg = "Cannot generate new key pair";
133
                if (resp_error) {
134
                    msg += " ({0})".format(resp_error);
135
                }
136
                self.show_list_msg("error", msg);
137
                self.generating = false;
138
                self.download_private = false;
139
                self.$(".add-generate").text(generate_text).removeClass(
140
                        "in-progress").addClass("download");
141
                self.enable_create();
142
            });
143
        },
144

    
145
        generate_new: function() {
146
            if (this.generating) { return false };
147

    
148
            this.$(".private-cont").hide();
149
            this.generating = true;
150
            this.download_private = false;
151
            this.disable_create();
152
            var generate_text = this.$(".add-generate").text();
153
            this.$(".add-generate").text("Generating...").addClass("in-progress").removeClass("download");
154
            
155
            window.setTimeout(_.bind(this.__generate_new, this, generate_text), 400);
156

    
157
        },
158

    
159
        disable_create: function() {
160
            this.create_disabled = true;
161
            this.$(".collection-action.add").addClass("disabled");
162
        },
163
        
164
        enable_create: function() {
165
            this.create_disabled = false;
166
            this.$(".collection-action.add").removeClass("disabled");
167
        },
168
        
169
        show_download_private: function(name, private) {
170
            var download_cont = this.$(".private-cont");
171
            download_cont.show();
172
            download_cont.find(".key-contents textarea").val("");
173
            download_cont.find(".private-msg, .down-button").show();
174
            download_cont.find(".private-msg.copy").hide();
175
            download_cont.find(".private-msg.download").hide();
176
            download_cont.find("textarea").hide();
177
            download_cont.find("form").attr({action: snf.config.userdata_keys_url + '/download'})
178
            download_cont.find('[name=data]').val(private);
179
            download_cont.find('[name=name]').val(name);
180
        },
181

    
182
        update_list_item: function(el, model) {
183
            el.find(".name").text(model.get("name"));
184
            el.find(".key-type").text(model.identify_type() || "unknown");
185
            el.find(".publicid .param-content textarea").val(model.get("content"));
186
            el.find(".fingerprint .text").text(model.get("fingerprint"));
187
            el.find(".publicid").attr("title", _(model.get("content")).truncate(1000, "..."));
188
            return el;
189
        },
190

    
191
        update_list: function() {
192
            views.PublicKeysView.__super__.update_list.apply(this, arguments);
193
            this.check_limit();
194
        },
195

    
196
        check_limit: function() {
197
            if (snf.storage.keys.length >= this.keys_limit) {
198
                this.$(".collection-action").hide();
199
                this.$(".limit-msg").show();
200
            } else {
201
                this.$(".collection-action").show();
202
                this.$(".limit-msg").hide();
203
            }
204
        },
205

    
206
        update_form_from_model: function(model) {
207
            this.form.find("input.input-name").val(model.get("name"));
208
            this.form.find("textarea.input-content").val(model.get("content"));
209
        },
210

    
211
        get_form_data: function() {
212
            return {
213
                'name': this.form.find("input.input-name").val(),
214
                'content': this.form.find("textarea.input-content").val()
215
            }
216
        },
217
        
218
        get_fields_map: function() {
219
            return {'name': "input.input-name", 'content': "textarea.input-content"};
220
        },
221
        
222
        validate_data: function(data) {
223
            var user_data = _.clone(data)
224
            var errors = new snf.util.errorList();
225

    
226
            if (!data.name || _.clean(data.name) == "") {
227
                errors.add("name", "Provide a valid public key name");
228
            }
229

    
230
            if (!data.content || _.clean(data.content) == "") {
231
                errors.add("content", "Provide valid public key content");
232
                return errors;
233
            }
234
            
235
            try {
236
                var content = snf.util.validatePublicKey(data.content);
237
                if (content) {
238
                    this.form.find("textarea.input-content").val(content);
239
                }
240
            } catch (err) {
241
                errors.add("content", "Invalid key content (" + err + ")");
242
            }
243

    
244
            return errors;
245
        },
246

    
247
        reset: function() {
248
            this.$(".private-cont").hide();
249
            this.$(".list-messages").empty();
250
            this.$(".form-messages").empty();
251
            this.$(".model-item").removeClass("expanded");
252
            this.close_private();
253
            this.close_form();
254
        }
255

    
256
    })
257

    
258
    views.PublicKeysOverlay = views.Overlay.extend({
259
        
260
        view_id: "public_keys_view",
261
        content_selector: "#user_public_keys",
262
        css_class: 'overlay-public-keys overlay-info',
263
        overlay_id: "user_public_keys_overlay",
264

    
265
        title: "Manage your ssh keys",
266
        subtitle: "SSH keys",
267

    
268
        initialize: function(options) {
269
            views.PublicKeysOverlay.__super__.initialize.apply(this, arguments);
270
            this.subview = new views.PublicKeysView({el:this.$(".public-keys-view")});
271
            
272
            var self = this;
273
            this.$(".previous-view-link").live('click', function(){
274
                self.hide();
275
            })
276
        },
277

    
278
        show: function(view) {
279
            this.from_view = view || undefined;
280
            
281
            if (this.from_view) {
282
                this.$(".previous-view-link").show();
283
            } else {
284
                this.$(".previous-view-link").hide();
285
            }
286

    
287
            this.subview.reset();
288
            views.PublicKeysOverlay.__super__.show.apply(this, arguments);
289
        },
290
        
291
        onClose: function() {
292
            if (this.from_view) {
293
                this.hiding = true;
294
                this.from_view.skip_reset_on_next_open = true;
295
                this.from_view.show();
296
                this.from_view = undefined;
297
            }
298
        },
299

    
300
        init_handlers: function() {
301
        }
302
        
303
    });
304
})(this);
305

    
306