Fixed auto-refresh to update only the files of the current folder
[pithos-web-client] / src / gr / grnet / pithos / web / client / FilePermissionsDialog.java
1 /*\r
2  * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
3  *\r
4  * Redistribution and use in source and binary forms, with or\r
5  * without modification, are permitted provided that the following\r
6  * conditions are met:\r
7  *\r
8  *   1. Redistributions of source code must retain the above\r
9  *      copyright notice, this list of conditions and the following\r
10  *      disclaimer.\r
11  *\r
12  *   2. Redistributions in binary form must reproduce the above\r
13  *      copyright notice, this list of conditions and the following\r
14  *      disclaimer in the documentation and/or other materials\r
15  *      provided with the distribution.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
28  * POSSIBILITY OF SUCH DAMAGE.\r
29  *\r
30  * The views and conclusions contained in the software and\r
31  * documentation are those of the authors and should not be\r
32  * interpreted as representing official policies, either expressed\r
33  * or implied, of GRNET S.A.\r
34  */\r
35 package gr.grnet.pithos.web.client;\r
36 \r
37 import gr.grnet.pithos.web.client.foldertree.File;\r
38 import gr.grnet.pithos.web.client.foldertree.Resource;\r
39 import gr.grnet.pithos.web.client.rest.HeadRequest;\r
40 import gr.grnet.pithos.web.client.rest.PostRequest;\r
41 \r
42 import java.util.Map;\r
43 \r
44 import com.google.gwt.core.client.GWT;\r
45 import com.google.gwt.core.client.Scheduler;\r
46 import com.google.gwt.dom.client.NativeEvent;\r
47 import com.google.gwt.event.dom.client.ClickEvent;\r
48 import com.google.gwt.event.dom.client.ClickHandler;\r
49 import com.google.gwt.event.dom.client.KeyCodes;\r
50 import com.google.gwt.http.client.Response;\r
51 import com.google.gwt.http.client.URL;\r
52 import com.google.gwt.http.client.UrlBuilder;\r
53 import com.google.gwt.i18n.client.Dictionary;\r
54 import com.google.gwt.resources.client.ImageResource;\r
55 import com.google.gwt.user.client.Command;\r
56 import com.google.gwt.user.client.Window;\r
57 import com.google.gwt.user.client.Event.NativePreviewEvent;\r
58 import com.google.gwt.user.client.ui.Anchor;\r
59 import com.google.gwt.user.client.ui.Button;\r
60 import com.google.gwt.user.client.ui.CheckBox;\r
61 import com.google.gwt.user.client.ui.FocusPanel;\r
62 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
63 import com.google.gwt.user.client.ui.HorizontalPanel;\r
64 import com.google.gwt.user.client.ui.Label;\r
65 import com.google.gwt.user.client.ui.TextBox;\r
66 import com.google.gwt.user.client.ui.VerticalPanel;\r
67 \r
68 /**\r
69  * The 'File properties' dialog box implementation.\r
70  *\r
71  */\r
72 public class FilePermissionsDialog extends AbstractPropertiesDialog {\r
73 \r
74         protected PermissionsList permList;\r
75 \r
76         protected CheckBox readForAll;\r
77         \r
78         private HorizontalPanel pathPanel;\r
79         \r
80         private TextBox path;\r
81         \r
82         private Dictionary otherProperties = Dictionary.getDictionary("otherProperties");\r
83         \r
84         /**\r
85          * An image bundle for this widgets images.\r
86          */\r
87         public interface Images extends MessagePanel.Images {\r
88 \r
89                 @Source("gr/grnet/pithos/resources/edit_user.png")\r
90                 ImageResource permUser();\r
91 \r
92                 @Source("gr/grnet/pithos/resources/groups22.png")\r
93                 ImageResource permGroup();\r
94 \r
95                 @Source("gr/grnet/pithos/resources/editdelete.png")\r
96                 ImageResource delete();\r
97         }\r
98 \r
99         final File file;\r
100 \r
101     Images images = GWT.create(Images.class);\r
102 \r
103         /**\r
104          * The widget's constructor.\r
105          */\r
106         public FilePermissionsDialog(Pithos _app, File _file) {\r
107         super(_app);\r
108         file = _file;\r
109 \r
110                 Anchor close = new Anchor();\r
111                 close.addStyleName("close");\r
112                 close.addClickHandler(new ClickHandler() {\r
113                         \r
114                         @Override\r
115                         public void onClick(ClickEvent event) {\r
116                                 hide();\r
117                         }\r
118                 });\r
119                 // Set the dialog's caption.\r
120                 setText("File permissions");\r
121                 setAnimationEnabled(true);\r
122                 setGlassEnabled(true);\r
123                 setStyleName("pithos-DialogBox");\r
124 \r
125                 // Outer contains inner and buttons.\r
126                 final VerticalPanel outer = new VerticalPanel();\r
127                 outer.add(close);\r
128                 final FocusPanel focusPanel = new FocusPanel(outer);\r
129                 // Inner contains generalPanel and permPanel.\r
130                 inner = new VerticalPanel();\r
131                 inner.addStyleName("inner");\r
132 \r
133         inner.add(createSharingPanel());\r
134 \r
135         outer.add(inner);\r
136 \r
137                 final Button ok = new Button("Close", new ClickHandler() {\r
138                         @Override\r
139                         public void onClick(ClickEvent event) {\r
140                                 closeDialog();\r
141                         }\r
142                 });\r
143                 ok.addStyleName("button");\r
144 \r
145         outer.add(ok);\r
146         outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
147 \r
148         focusPanel.setFocus(true);\r
149         setWidget(outer);\r
150         }\r
151 \r
152     private VerticalPanel createSharingPanel() {\r
153         VerticalPanel permPanel = new VerticalPanel();\r
154 \r
155         permList = new PermissionsList(images, file.getPermissions(), file.getOwner(), false, new Command() {\r
156                         \r
157                         @Override\r
158                         public void execute() {\r
159                                 accept();\r
160                         }\r
161                 });\r
162         permPanel.add(permList);\r
163 \r
164         HorizontalPanel permButtons = new HorizontalPanel();\r
165         final Button addUser = new Button("Add User", new ClickHandler() {\r
166             @Override\r
167             public void onClick(ClickEvent event) {\r
168                 PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);\r
169                 dlg.center();\r
170                 permList.updatePermissionTable();\r
171             }\r
172         });\r
173         addUser.addStyleName("button");\r
174         permButtons.add(addUser);\r
175         permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);\r
176 \r
177         Button add = new Button("Add Group", new ClickHandler() {\r
178             @Override\r
179             public void onClick(ClickEvent event) {\r
180                 PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
181                 dlg.center();\r
182                 permList.updatePermissionTable();\r
183             }\r
184         });\r
185         add.addStyleName("button");\r
186         permButtons.add(add);\r
187         permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);\r
188 \r
189         permButtons.setSpacing(8);\r
190         permButtons.addStyleName("pithos-TabPanelBottom");\r
191         permPanel.add(permButtons);\r
192 \r
193         final Label readForAllNote = new Label("When this option is enabled, the file will be readable" +\r
194                     " by everyone. By checking this option, you are certifying that you have the right to " +\r
195                     "distribute this file and that it does not violate the Terms of Use.", true);\r
196         readForAllNote.setStylePrimaryName("pithos-readForAllNote");\r
197 \r
198         readForAll = new CheckBox();\r
199         readForAll.setValue(file.isPublished());\r
200         readForAll.addClickHandler(new ClickHandler() {\r
201             @Override\r
202             public void onClick(ClickEvent event) {\r
203                 accept();\r
204             }\r
205         });\r
206 \r
207         // Only show the read for all permission if the user is the owner.\r
208         if (file.getOwner().equals(app.getUsername())) {\r
209             final HorizontalPanel permForAll = new HorizontalPanel();\r
210             permForAll.add(new Label("Public"));\r
211             permForAll.add(readForAll);\r
212             permForAll.setSpacing(8);\r
213             permForAll.addStyleName("pithos-TabPanelBottom");\r
214             permForAll.add(readForAllNote);\r
215             permPanel.add(permForAll);\r
216         }\r
217 \r
218         pathPanel = new HorizontalPanel();\r
219         pathPanel.setVisible(false);\r
220         pathPanel.setWidth("100%");\r
221         pathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);\r
222         pathPanel.add(new Label("Link"));\r
223         pathPanel.setSpacing(8);\r
224         pathPanel.addStyleName("pithos-TabPanelBottom");\r
225 \r
226         path = new TextBox();\r
227         path.setWidth("100%");\r
228         path.addClickHandler(new ClickHandler() {\r
229             @Override\r
230             public void onClick(ClickEvent event) {\r
231                 Pithos.enableIESelection();\r
232                 ((TextBox) event.getSource()).selectAll();\r
233                 Pithos.preventIESelection();\r
234             }\r
235         });\r
236         path.setText(Window.Location.getHost() + file.getPublicUri());\r
237         path.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");\r
238         path.setWidth("100%");\r
239         path.setReadOnly(true);\r
240         pathPanel.add(path);\r
241         permPanel.add(pathPanel);\r
242 \r
243         Scheduler.get().scheduleDeferred(new Command() {\r
244                         \r
245                         @Override\r
246                         public void execute() {\r
247                                 showLinkIfPublished();\r
248                         }\r
249                 });\r
250         return permPanel;\r
251     }\r
252 \r
253     void showLinkIfPublished() {\r
254                 if (file.isShared()) {\r
255                         UrlBuilder b = Window.Location.createUrlBuilder();\r
256                         if (file.isPublished()) {\r
257                                 b.setPath(file.getPublicUri());\r
258                                 path.setText(b.buildString());\r
259                         }\r
260                         else {\r
261                                 b.setPath(app.getApiPath() + file.getOwner() + file.getUri());\r
262                                 String href = Window.Location.getHref();\r
263                                 boolean hasParameters = href.contains("?");\r
264                                 path.setText(href + (hasParameters ? "&" : "?") + "goto=" + b.buildString());\r
265                         }\r
266                 pathPanel.setVisible(true);\r
267                 }\r
268                 else {\r
269                         pathPanel.setVisible(false);\r
270                 }\r
271     }\r
272         /**\r
273          * Accepts any change and updates the file\r
274          *\r
275          */\r
276         @Override\r
277         protected void accept() {\r
278         Boolean published = null;\r
279                 if (readForAll.getValue() != file.isPublished())\r
280                         if (file.getOwner().equals(app.getUsername()))\r
281                 published = readForAll.getValue();\r
282         updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", published, permList.getPermissions());\r
283         }\r
284 \r
285         protected void updateMetaData(String api, String owner, final String path, final Boolean published, final Map<String, Boolean[]> newPermissions) {\r
286         if (published != null || newPermissions != null) {\r
287             PostRequest updateFile = new PostRequest(api, owner, path) {\r
288                 @Override\r
289                 public void onSuccess(Resource result) {\r
290                         HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwner(), path, file) {\r
291 \r
292                                                 @Override\r
293                                                 public void onSuccess(File _result) {\r
294                                                         showLinkIfPublished();\r
295                                     app.updateFolder(file.getParent(), true, new Command() {\r
296                                                                 \r
297                                                                 @Override\r
298                                                                 public void execute() {\r
299                                                                         app.updateMySharedRoot();\r
300                                                                 }\r
301                                                         }, true);\r
302                                                 }\r
303 \r
304                                                 @Override\r
305                                                 public void onError(Throwable t) {\r
306                                     GWT.log("", t);\r
307                                                         app.setError(t);\r
308                                     app.displayError("System error modifying file:" + t.getMessage());\r
309                                                 }\r
310 \r
311                                                 @Override\r
312                                                 protected void onUnauthorized(Response response) {\r
313                                                         app.sessionExpired();\r
314                                                 }\r
315                                         };\r
316                                         headFile.setHeader("X-Auth-Token", app.getToken());\r
317                                         Scheduler.get().scheduleDeferred(headFile);\r
318                 }\r
319 \r
320                 @Override\r
321                 public void onError(Throwable t) {\r
322                     GWT.log("", t);\r
323                                         app.setError(t);\r
324                     app.displayError("System error modifying file:" + t.getMessage());\r
325                 }\r
326 \r
327                                 @Override\r
328                                 protected void onUnauthorized(Response response) {\r
329                                         app.sessionExpired();\r
330                                 }\r
331             };\r
332             updateFile.setHeader("X-Auth-Token", app.getToken());\r
333             \r
334             if (published != null)\r
335                 updateFile.setHeader("X-Object-Public", published.toString());\r
336             if (newPermissions != null) {\r
337                 String readPermHeader = "read=";\r
338                 String writePermHeader = "write=";\r
339                 for (String u : newPermissions.keySet()) {\r
340                     Boolean[] p = newPermissions.get(u);\r
341                     if (p[0] != null && p[0])\r
342                         readPermHeader += u + ",";\r
343                     if (p[1] != null && p[1])\r
344                         writePermHeader += u + ",";\r
345                 }\r
346                 if (readPermHeader.endsWith("="))\r
347                     readPermHeader = "";\r
348                 else if (readPermHeader.endsWith(","))\r
349                     readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);\r
350                 if (writePermHeader.endsWith("="))\r
351                     writePermHeader = "";\r
352                 else if (writePermHeader.endsWith(","))\r
353                     writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);\r
354                 String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;\r
355                 if (permHeader.length() == 0)\r
356                     permHeader="~";\r
357                 else\r
358                         permHeader = URL.encodePathSegment(permHeader);\r
359                 updateFile.setHeader("X-Object-Sharing", permHeader);\r
360             }\r
361             Scheduler.get().scheduleDeferred(updateFile);\r
362         }\r
363         else\r
364             app.updateFolder(file.getParent(), true, new Command() {\r
365                                 \r
366                                 @Override\r
367                                 public void execute() {\r
368                                         if (file.isShared())\r
369                                                 app.updateMySharedRoot();\r
370                                 }\r
371                         }, true);\r
372     }\r
373 \r
374         @Override\r
375         protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
376             super.onPreviewNativeEvent(preview);\r
377 \r
378             NativeEvent evt = preview.getNativeEvent();\r
379             if (evt.getType().equals("keydown") && evt.getKeyCode() == KeyCodes.KEY_ENTER)\r
380                                 closeDialog();\r
381         }\r
382 }\r