Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / FileShareDialog.java @ 46d2ccd2

History | View | Annotate | Download (21.7 kB)

1
/*
2
 * Copyright 2011-2013 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
11
 *
12
 *   2. Redistributions in binary form must reproduce the above
13
 *      copyright notice, this list of conditions and the following
14
 *      disclaimer in the documentation and/or other materials
15
 *      provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * The views and conclusions contained in the software and
31
 * documentation are those of the authors and should not be
32
 * interpreted as representing official policies, either expressed
33
 * or implied, of GRNET S.A.
34
 */
35
package gr.grnet.pithos.web.client;
36

    
37
import com.google.gwt.http.client.URL;
38
import com.google.gwt.user.client.ui.*;
39
import gr.grnet.pithos.web.client.foldertree.File;
40
import gr.grnet.pithos.web.client.rest.HeadRequest;
41
import gr.grnet.pithos.web.client.rest.PostRequest;
42

    
43
import com.google.gwt.core.client.GWT;
44
import com.google.gwt.core.client.Scheduler;
45
import com.google.gwt.dom.client.NativeEvent;
46
import com.google.gwt.event.dom.client.ClickEvent;
47
import com.google.gwt.event.dom.client.ClickHandler;
48
import com.google.gwt.event.dom.client.KeyCodes;
49
import com.google.gwt.http.client.Response;
50
import com.google.gwt.http.client.UrlBuilder;
51
import com.google.gwt.resources.client.ImageResource;
52
import com.google.gwt.user.client.Command;
53
import com.google.gwt.user.client.Window;
54
import com.google.gwt.user.client.Event.NativePreviewEvent;
55

    
56
import java.util.Map;
57

    
58
/**
59
 * UI for the "Share" command.
60
 */
61
public class FileShareDialog extends AbstractPropertiesDialog {
62
    // For public sharing
63
        private final HorizontalPanel publicPathPanel = new HorizontalPanel();
64
        private final TextBox publicPathText = new TextBox();
65

    
66
    // For private sharing
67
    private final HorizontalPanel privatePathPanel = new HorizontalPanel();
68
    private final TextBox privatePathText = new TextBox();
69
    private final VerticalPanel privatePermSuperPanel = new VerticalPanel();
70
    private PermissionsList permList;
71
        
72
        /**
73
         * An image bundle for this widgets images.
74
         */
75
        public interface PublicSharingImages extends MessagePanel.Images {
76

    
77
                @Source("gr/grnet/pithos/resources/edit_user.png")
78
                ImageResource permUser();
79

    
80
                @Source("gr/grnet/pithos/resources/groups22.png")
81
                ImageResource permGroup();
82

    
83
                @Source("gr/grnet/pithos/resources/editdelete.png")
84
                ImageResource delete();
85
    }
86

    
87
    public interface PrivateSharingImages extends MessagePanel.Images {
88

    
89
        @Source("gr/grnet/pithos/resources/edit_user.png")
90
        ImageResource permUser();
91

    
92
        @Source("gr/grnet/pithos/resources/groups22.png")
93
        ImageResource permGroup();
94

    
95
        @Source("gr/grnet/pithos/resources/delete.gif")
96
        ImageResource delete();
97
    }
98

    
99
    private final File file;
100

    
101
    private final PublicSharingImages publicSharingImages = GWT.create(PublicSharingImages.class);
102
    private final PrivateSharingImages privateSharingImages = GWT.create(PrivateSharingImages.class);
103

    
104
        /**
105
         * The widget's constructor.
106
         */
107
        public FileShareDialog(Pithos app, File file) {
108
        super(app);
109
        this.file = file;
110

    
111
                Anchor close = new Anchor("close");
112
                close.addStyleName("close");
113
                close.addClickHandler(new ClickHandler() {
114
                        
115
                        @Override
116
                        public void onClick(ClickEvent event) {
117
                                hide();
118
                        }
119
                });
120
                // Set the dialog's caption.
121
                setText("Share");
122
                setGlassEnabled(true);
123
                setStyleName("pithos-DialogBox");
124

    
125
                // Outer contains inner and buttons.
126
                final VerticalPanel outer = new VerticalPanel();
127
                outer.add(close);
128
                final FocusPanel focusPanel = new FocusPanel(outer);
129
                // Inner contains generalPanel and permPanel.
130
                inner = new VerticalPanel();
131
                inner.addStyleName("inner");
132

    
133
        inner.add(createMainPanel());
134

    
135
        outer.add(inner);
136

    
137
                final Button ok = new Button("OK", new ClickHandler() {
138
                        @Override
139
                        public void onClick(ClickEvent event) {
140
                                closeDialog();
141
                        }
142
                });
143
                ok.addStyleName("button");
144

    
145
        outer.add(ok);
146
        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
147

    
148
        focusPanel.setFocus(true);
149
        setWidget(outer);
150
        }
151

    
152
    private boolean IamOwner() {
153
        return file.getOwnerID().equals(app.getUserID());
154
    }
155

    
156
    private void populatePublicSharingPanel(VerticalPanel publicSharingPanel) {
157
        if(IamOwner()) {
158
            final HorizontalPanel publicCheckPanel = new HorizontalPanel();
159
            publicCheckPanel.setSpacing(8);
160

    
161
            // Check box header
162
            final CheckBox publicCheckBox = new CheckBox();
163
            Label publicCheckTitle = new InlineHTML("<b>Public on the Internet</b>");
164
            Label publicCheckInfo = new Label("Anyone who has the public link can access. No sign-in required.", true);
165

    
166
            publicCheckBox.setValue(isFilePubliclyShared());
167
            publicCheckBox.addClickHandler(new ClickHandler() {
168
                @Override
169
                public void onClick(ClickEvent event) {
170
                    final Boolean published;
171
                    if(publicCheckBox.getValue() != file.isPublished() && IamOwner()) {
172
                        published = publicCheckBox.getValue();
173
                    }
174
                    else {
175
                        published = Boolean.FALSE;
176
                    }
177

    
178
                    updateMetaDataForPublicSharing(published);
179
                }
180
            });
181

    
182
            publicCheckPanel.add(publicCheckBox);
183
            publicCheckPanel.add(publicCheckTitle);
184
            publicCheckPanel.add(publicCheckInfo);
185

    
186
            // Public Link
187
            publicPathPanel.setVisible(false);
188
            publicPathPanel.setWidth(Const.PERCENT_100);
189
            publicPathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
190
            publicPathPanel.add(new Label("Link"));
191
            publicPathPanel.setSpacing(8);
192
            publicPathPanel.addStyleName("pithos-TabPanelBottom");
193

    
194
            publicPathText.setWidth(Const.PERCENT_100);
195
            publicPathText.addClickHandler(new ClickHandler() {
196
                @Override
197
                public void onClick(ClickEvent event) {
198
                    Pithos.enableIESelection();
199
                    ((TextBox) event.getSource()).selectAll();
200
                    Pithos.preventIESelection();
201
                }
202
            });
203
            publicPathText.setText(Window.Location.getHost() + file.getPublicUri());
204
            publicPathText.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");
205
            publicPathText.setReadOnly(true);
206
            publicPathPanel.add(publicPathText);
207

    
208
            publicSharingPanel.add(publicCheckPanel);
209
            publicSharingPanel.add(publicPathPanel);
210

    
211
            Scheduler.get().scheduleDeferred(new Command() {
212
                @Override
213
                public void execute() {
214
                    showLinkForPublicSharing();
215
                }
216
            });
217
        }
218
    }
219

    
220
    private void populatePrivateSharingPanel(VerticalPanel privateSharingPanel) {
221
        final HorizontalPanel privateCheckPanel = new HorizontalPanel();
222
        final VerticalPanel privatePermPanel = new VerticalPanel();
223
        final HorizontalPanel permButtons = new HorizontalPanel();
224

    
225
        privateCheckPanel.setSpacing(8);
226
        privatePermPanel.setVisible(isFilePrivatelyShared());
227
        permButtons.setSpacing(8);
228

    
229
        // Check box header
230
        final CheckBox privateCheckBox = new CheckBox();
231
        final Label privateCheckTitle = new  InlineHTML("<b>Private sharing</b>");
232
        final Label privateCheckInfo = new Label("Only people explicitly granted permission can access. Sign-in required.", true);
233

    
234
        privateCheckBox.setValue(isFilePrivatelyShared());
235
        privateCheckBox.addClickHandler(new ClickHandler() {
236
            @Override
237
            public void onClick(ClickEvent event) {
238
                if(isFilePrivatelyShared()) {
239
                    // ignore the click, set it always to "checked"
240
                    privateCheckBox.setValue(true);
241
                    // show permissions
242
                    privatePermPanel.setVisible(true);
243
                }
244
                else {
245
                    // This is the value *after* the click is applied :)
246
                    boolean isChecked = privateCheckBox.getValue();
247
                    privatePermPanel.setVisible(isChecked);
248
                }
249
            }
250
        });
251

    
252
        privateCheckPanel.add(privateCheckBox);
253
        privateCheckPanel.add(privateCheckTitle);
254
        privateCheckPanel.add(privateCheckInfo);
255

    
256
        // Permission list
257
        permList = new PermissionsList(app, privateSharingImages, file.getPermissions(), file.getOwnerID(), false, new Command() {
258
            @Override
259
            public void execute() {
260
                updateMetaDataForPrivateSharing();
261
            }
262
        });
263

    
264
        // Permission Add buttons
265
        Button addUser = new Button("Add User", new ClickHandler() {
266
            @Override
267
            public void onClick(ClickEvent event) {
268
                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);
269
                dlg.center();
270
                permList.updatePermissionTable();
271
            }
272
        });
273
        addUser.addStyleName("button");
274
        permButtons.add(addUser);
275

    
276
        final boolean haveGroups = app.getAccount().getGroups().size() > 0;
277
        Button addGroup = new Button("Add Group", new ClickHandler() {
278
            @Override
279
            public void onClick(ClickEvent event) {
280
                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
281
                dlg.center();
282
                permList.updatePermissionTable();
283
            }
284
        });
285
        addGroup.addStyleName("button");
286
        addGroup.setEnabled(haveGroups);
287
        if(!haveGroups) {
288
            addGroup.setTitle("You do not have any groups");
289
        }
290
        permButtons.add(addGroup);
291

    
292
        Button addEverybody = new Button("Add everybody", new ClickHandler() {
293
            @Override
294
            public void onClick(ClickEvent event) {
295
                Pithos.LOG("Adding to Everybody");
296
                Pithos.LOG("");
297
                permList.addPermission("*", true, false);
298
                permList.updatePermissionTable();
299
            }
300
        });
301
        addEverybody.addStyleName("button");
302
        permButtons.add(addEverybody);
303

    
304
        permButtons.setCellHorizontalAlignment(addGroup, HasHorizontalAlignment.ALIGN_CENTER);
305
        privatePermPanel.add(permList);
306
        privatePermPanel.add(permButtons);
307

    
308
        // Private Link
309
        privatePathPanel.setVisible(false);
310
        privatePathPanel.setWidth(Const.PERCENT_100);
311
        privatePathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
312
        privatePathPanel.add(new Label("Link"));
313
        privatePathPanel.setSpacing(8);
314
        privatePathPanel.addStyleName("pithos-TabPanelBottom");
315

    
316
        privatePathText.setWidth(Const.PERCENT_100);
317
        privatePathText.addClickHandler(new ClickHandler() {
318
            @Override
319
            public void onClick(ClickEvent event) {
320
                Pithos.enableIESelection();
321
                ((TextBox) event.getSource()).selectAll();
322
                Pithos.preventIESelection();
323
            }
324
        });
325
        privatePathText.setText(Window.Location.getHost() + file.getPublicUri());
326
        privatePathText.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");
327
        privatePathText.setWidth(Const.PERCENT_100);
328
        privatePathText.setReadOnly(true);
329
        privatePathPanel.add(privatePathText);
330

    
331
        Scheduler.get().scheduleDeferred(new Command() {
332
            @Override
333
            public void execute() {
334
                showLinkForPrivateSharing();
335
            }
336
        });
337

    
338
        privateSharingPanel.add(privateCheckPanel);
339
        privateSharingPanel.add(privatePermPanel);
340
        privateSharingPanel.add(privatePathPanel);
341
    }
342

    
343
    private Panel createMainPanel() {
344
        VerticalPanel panelAll = new VerticalPanel();
345
        VerticalPanel panelPublic = new VerticalPanel();
346
        VerticalPanel panelPrivate = new VerticalPanel();
347

    
348
        populatePrivateSharingPanel(panelPrivate);
349
        populatePublicSharingPanel(panelPublic);
350

    
351
        CaptionPanel captionPanelPrivate = new CaptionPanel();
352
        CaptionPanel captionPanelPublic = new CaptionPanel();
353
        captionPanelPrivate.add(panelPrivate);
354
        captionPanelPublic.add(panelPublic);
355

    
356
        panelAll.add(captionPanelPrivate);
357
        panelAll.add(captionPanelPublic);
358

    
359
        return panelAll;
360
    }
361

    
362
    private boolean isFilePubliclyShared() {
363
        return file.isPublished();
364
    }
365

    
366
    private boolean isFilePrivatelyShared() {
367
        return file.isShared();
368
    }
369

    
370
    private void showLinkForPublicSharing() {
371
                if (isFilePubliclyShared()) {
372
                        UrlBuilder b = Window.Location.createUrlBuilder();
373
                        b.setPath(file.getPublicUri());
374
                        publicPathText.setText(b.buildString());
375
                publicPathPanel.setVisible(true);
376
                }
377
                else {
378
                        publicPathPanel.setVisible(false);
379
                }
380
    }
381

    
382
    private void showLinkForPrivateSharing() {
383
        if (isFilePrivatelyShared()) {
384
            UrlBuilder b = Window.Location.createUrlBuilder();
385
            b.setPath(app.getApiPath() + file.getOwnerID() + file.getUri());
386
            String href = Window.Location.getHref();
387
            boolean hasParameters = href.contains(Const.QUESTION_MARK);
388
            privatePathText.setText(href + (hasParameters ? Const.AMPERSAND : Const.QUESTION_MARK) + Const.GOTO_EQ + b.buildString());
389
            privatePathPanel.setVisible(true);
390
        }
391
        else {
392
            privatePathPanel.setVisible(false);
393
        }
394
    }
395

    
396
        protected void updateMetaDataForPublicSharing(String api, String owner, final String path, final Boolean published) {
397
        if (published != null) {
398
            PostRequest updateFile = new PostRequest(api, owner, path) {
399
                @Override
400
                public void onSuccess(Resource result) {
401
                        HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwnerID(), path, file) {
402

    
403
                                                @Override
404
                                                public void onSuccess(File _result) {
405
                                                        showLinkForPublicSharing();
406
                                                        if (!app.isMySharedSelected()) {
407
                                            app.updateFolder(file.getParent(), true, new Command() {
408
                                                                        
409
                                                                        @Override
410
                                                                        public void execute() {
411
                                                                                app.updateMySharedRoot();
412
                                                                        }
413
                                                                }, true);
414
                            }
415
                                                        else {
416
                                                                app.updateSharedFolder(file.getParent(), true);
417
                            }
418
                                                }
419

    
420
                                                @Override
421
                                                public void onError(Throwable t) {
422
                                                        app.setError(t);
423
                                    app.displayError("System error modifying file:" + t.getMessage());
424
                                                }
425

    
426
                                                @Override
427
                                                protected void onUnauthorized(Response response) {
428
                                                        app.sessionExpired();
429
                                                }
430
                                        };
431
                                        headFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
432
                                        Scheduler.get().scheduleDeferred(headFile);
433
                }
434

    
435
                @Override
436
                public void onError(Throwable t) {
437
                                        app.setError(t);
438
                    app.displayError("System error modifying file:" + t.getMessage());
439
                }
440

    
441
                                @Override
442
                                protected void onUnauthorized(Response response) {
443
                                        app.sessionExpired();
444
                                }
445
            };
446
            updateFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
447
            updateFile.setHeader(Const.X_OBJECT_PUBLIC, published.toString());
448
            Scheduler.get().scheduleDeferred(updateFile);
449
        }
450
        else if (!app.isMySharedSelected())
451
            app.updateFolder(file.getParent(), true, new Command() {
452
                                @Override
453
                                public void execute() {
454
                                        if (file.isSharedOrPublished()) {
455
                        app.updateMySharedRoot();
456
                    }
457
                                }
458
                        }, true);
459
        else
460
                app.updateSharedFolder(file.getParent(), true);
461
    }
462
    protected void updateMetaDataForPublicSharing(Boolean published) {
463
        updateMetaDataForPublicSharing(
464
            app.getApiPath(),
465
            app.getUserID(),
466
            file.getUri() + Const.QUESTION_MARK_UPDATE_EQ,
467
            published
468
        );
469
    }
470

    
471
    protected void updateMetaDataForPrivateSharing(String api, String owner, final String path, final Map<String, Boolean[]> newPermissions) {
472
        if (newPermissions != null) {
473
            PostRequest updateFile = new PostRequest(api, owner, path) {
474
                @Override
475
                public void onSuccess(Resource result) {
476
                    HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwnerID(), path, file) {
477

    
478
                        @Override
479
                        public void onSuccess(File _result) {
480
                            showLinkForPrivateSharing();
481
                            if (!app.isMySharedSelected())
482
                                app.updateFolder(file.getParent(), true, new Command() {
483

    
484
                                    @Override
485
                                    public void execute() {
486
                                        app.updateMySharedRoot();
487
                                    }
488
                                }, true);
489
                            else
490
                                app.updateSharedFolder(file.getParent(), true);
491
                        }
492

    
493
                        @Override
494
                        public void onError(Throwable t) {
495
                            app.setError(t);
496
                            app.displayError("System error modifying file:" + t.getMessage());
497
                        }
498

    
499
                        @Override
500
                        protected void onUnauthorized(Response response) {
501
                            app.sessionExpired();
502
                        }
503
                    };
504
                    headFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
505
                    Scheduler.get().scheduleDeferred(headFile);
506
                }
507

    
508
                @Override
509
                public void onError(Throwable t) {
510
                    app.setError(t);
511
                    app.displayError("System error modifying file:" + t.getMessage());
512
                }
513

    
514
                @Override
515
                protected void onUnauthorized(Response response) {
516
                    app.sessionExpired();
517
                }
518
            };
519
            updateFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
520

    
521
            String readPermHeader = Const.READ_EQ;
522
            String writePermHeader = Const.WRITE_EQ;
523
            for (String u : newPermissions.keySet()) {
524
                Boolean[] p = newPermissions.get(u);
525
                if (p[0] != null && p[0]) {
526
                    readPermHeader += u + Const.COMMA;
527
                }
528
                if (p[1] != null && p[1]) {
529
                    writePermHeader += u + Const.COMMA;
530
                }
531
            }
532
            if (readPermHeader.endsWith(Const.EQ)) {
533
                readPermHeader = "";
534
            }
535
            else if (readPermHeader.endsWith(Const.COMMA)) {
536
                readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
537
            }
538
            if (writePermHeader.endsWith(Const.EQ)) {
539
                writePermHeader = "";
540
            }
541
            else if (writePermHeader.endsWith(Const.COMMA)) {
542
                writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
543
            }
544
            String permHeader = readPermHeader +
545
                ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  Const.SEMI : "") + writePermHeader;
546
            if (permHeader.length() == 0) {
547
                permHeader=Const.TILDE;
548
            }
549
            else {
550
                permHeader = URL.encodePathSegment(permHeader);
551
            }
552
            updateFile.setHeader(Const.X_OBJECT_SHARING, permHeader);
553
            Scheduler.get().scheduleDeferred(updateFile);
554
        }
555
        else if (!app.isMySharedSelected()) {
556
            app.updateFolder(file.getParent(), true, new Command() {
557
                @Override
558
                public void execute() {
559
                    if (file.isSharedOrPublished())
560
                        app.updateMySharedRoot();
561
                }
562
            }, true);
563
        }
564
        else {
565
            app.updateSharedFolder(file.getParent(), true);
566
        }
567
    }
568
    protected void updateMetaDataForPrivateSharing() {
569
        updateMetaDataForPrivateSharing(
570
            app.getApiPath(),
571
            app.getUserID(),
572
            file.getUri() + Const.QUESTION_MARK_UPDATE_EQ,
573
            permList.getPermissions()
574
        );
575
    }
576
    @Override
577
        protected void onPreviewNativeEvent(NativePreviewEvent preview) {
578
            super.onPreviewNativeEvent(preview);
579

    
580
            NativeEvent evt = preview.getNativeEvent();
581
            if (evt.getType().equals(Const.EVENT_TYPE_KEYDOWN) &&
582
            evt.getKeyCode() == KeyCodes.KEY_ENTER) {
583

    
584
            closeDialog();
585
        }
586
        }
587

    
588
    @Override
589
    protected boolean accept() {
590
        return true;
591
    }
592
}