FilePropertiesDialog is broken into three dialogs
[pithos-web-client] / src / gr / grnet / pithos / web / client / FilePermissionsDialog.java
1 /*\r
2  * Copyright 2011 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.PostRequest;\r
40 \r
41 import java.util.Map;\r
42 \r
43 import com.google.gwt.core.client.GWT;\r
44 import com.google.gwt.core.client.Scheduler;\r
45 import com.google.gwt.event.dom.client.ClickEvent;\r
46 import com.google.gwt.event.dom.client.ClickHandler;\r
47 import com.google.gwt.http.client.Response;\r
48 import com.google.gwt.http.client.URL;\r
49 import com.google.gwt.resources.client.ImageResource;\r
50 import com.google.gwt.user.client.Command;\r
51 import com.google.gwt.user.client.Window;\r
52 import com.google.gwt.user.client.ui.Anchor;\r
53 import com.google.gwt.user.client.ui.Button;\r
54 import com.google.gwt.user.client.ui.CheckBox;\r
55 import com.google.gwt.user.client.ui.DecoratedTabPanel;\r
56 import com.google.gwt.user.client.ui.FocusPanel;\r
57 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
58 import com.google.gwt.user.client.ui.HorizontalPanel;\r
59 import com.google.gwt.user.client.ui.Label;\r
60 import com.google.gwt.user.client.ui.TextBox;\r
61 import com.google.gwt.user.client.ui.VerticalPanel;\r
62 \r
63 /**\r
64  * The 'File properties' dialog box implementation.\r
65  *\r
66  */\r
67 public class FilePermissionsDialog extends AbstractPropertiesDialog {\r
68 \r
69         protected PermissionsList permList;\r
70 \r
71         protected CheckBox readForAll;\r
72 \r
73         /**\r
74          * An image bundle for this widgets images.\r
75          */\r
76         public interface Images extends MessagePanel.Images {\r
77 \r
78                 @Source("gr/grnet/pithos/resources/edit_user.png")\r
79                 ImageResource permUser();\r
80 \r
81                 @Source("gr/grnet/pithos/resources/groups22.png")\r
82                 ImageResource permGroup();\r
83 \r
84                 @Source("gr/grnet/pithos/resources/editdelete.png")\r
85                 ImageResource delete();\r
86         }\r
87 \r
88         final File file;\r
89 \r
90     Images images = GWT.create(Images.class);\r
91 \r
92         /**\r
93          * The widget's constructor.\r
94          */\r
95         public FilePermissionsDialog(Pithos _app, File _file) {\r
96         super(_app);\r
97         file = _file;\r
98 \r
99                 Anchor close = new Anchor();\r
100                 close.addStyleName("close");\r
101                 close.addClickHandler(new ClickHandler() {\r
102                         \r
103                         @Override\r
104                         public void onClick(@SuppressWarnings("unused") ClickEvent event) {\r
105                                 hide();\r
106                         }\r
107                 });\r
108                 // Set the dialog's caption.\r
109                 setText("File permissions");\r
110                 setAnimationEnabled(true);\r
111                 setGlassEnabled(true);\r
112                 setStyleName("pithos-DialogBox");\r
113 \r
114                 // Outer contains inner and buttons.\r
115                 final VerticalPanel outer = new VerticalPanel();\r
116                 outer.add(close);\r
117                 final FocusPanel focusPanel = new FocusPanel(outer);\r
118                 // Inner contains generalPanel and permPanel.\r
119                 inner = new VerticalPanel();\r
120                 inner.addStyleName("inner");\r
121 //              inner.getDeckPanel().addStyleName("pithos-TabPanelBottom");\r
122 \r
123         inner.add(createSharingPanel());\r
124 \r
125         outer.add(inner);\r
126 \r
127                 // Create the 'OK' button, along with a listener that hides the dialog\r
128                 // when the button is clicked.\r
129                 final Button ok = new Button("OK", new ClickHandler() {\r
130                         @Override\r
131                         public void onClick(@SuppressWarnings("unused") ClickEvent event) {\r
132                                 accept();\r
133                                 closeDialog();\r
134                         }\r
135                 });\r
136                 ok.addStyleName("button");\r
137 \r
138         outer.add(ok);\r
139         outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
140 \r
141         focusPanel.setFocus(true);\r
142         setWidget(outer);\r
143         }\r
144 \r
145     private VerticalPanel createSharingPanel() {\r
146         VerticalPanel permPanel = new VerticalPanel();\r
147 \r
148         permList = new PermissionsList(images, file.getPermissions(), file.getOwner(), file.getInheritedPermissionsFrom() != null);\r
149         permPanel.add(permList);\r
150 \r
151         if (file.getInheritedPermissionsFrom() == null) {\r
152             HorizontalPanel permButtons = new HorizontalPanel();\r
153             Button add = new Button("Add Group", new ClickHandler() {\r
154                 @Override\r
155                 public void onClick(@SuppressWarnings("unused") ClickEvent event) {\r
156                     PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
157                     dlg.center();\r
158                     permList.updatePermissionTable();\r
159                 }\r
160             });\r
161             add.addStyleName("button");\r
162             permButtons.add(add);\r
163             permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);\r
164 \r
165             final Button addUser = new Button("Add User", new ClickHandler() {\r
166                 @Override\r
167                 public void onClick(@SuppressWarnings("unused") 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             permButtons.setSpacing(8);\r
178             permButtons.addStyleName("pithos-TabPanelBottom");\r
179             permPanel.add(permButtons);\r
180         }\r
181 \r
182         final Label readForAllNote = new Label("When this option is enabled, the file will be readable" +\r
183                     " by everyone. By checking this option, you are certifying that you have the right to " +\r
184                     "distribute this file and that it does not violate the Terms of Use.", true);\r
185         readForAllNote.setVisible(false);\r
186         readForAllNote.setStylePrimaryName("pithos-readForAllNote");\r
187 \r
188         readForAll = new CheckBox();\r
189         readForAll.setValue(file.isPublished());\r
190         readForAll.addClickHandler(new ClickHandler() {\r
191             @Override\r
192             public void onClick(@SuppressWarnings("unused") ClickEvent event) {\r
193                 readForAllNote.setVisible(readForAll.getValue());\r
194             }\r
195         });\r
196 \r
197         // Only show the read for all permission if the user is the owner.\r
198         if (file.getOwner().equals(app.getUsername())) {\r
199             final HorizontalPanel permForAll = new HorizontalPanel();\r
200             permForAll.add(new Label("Public"));\r
201             permForAll.add(readForAll);\r
202             permForAll.setSpacing(8);\r
203             permForAll.addStyleName("pithos-TabPanelBottom");\r
204             permForAll.add(readForAllNote);\r
205             permPanel.add(permForAll);\r
206         }\r
207 \r
208         if (file.isPublished()) {\r
209             final HorizontalPanel pathPanel = new HorizontalPanel();\r
210             pathPanel.setWidth("100%");\r
211             pathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);\r
212             pathPanel.add(new Label("Link"));\r
213             pathPanel.setSpacing(8);\r
214             pathPanel.addStyleName("pithos-TabPanelBottom");\r
215 \r
216             TextBox path = new TextBox();\r
217             path.setWidth("100%");\r
218             path.addClickHandler(new ClickHandler() {\r
219                 @Override\r
220                 public void onClick(ClickEvent event) {\r
221                     Pithos.enableIESelection();\r
222                     ((TextBox) event.getSource()).selectAll();\r
223                     Pithos.preventIESelection();\r
224                 }\r
225             });\r
226             path.setText(Window.Location.getHost() + file.getPublicUri());\r
227             path.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");\r
228             path.setWidth("100%");\r
229             path.setReadOnly(true);\r
230             pathPanel.add(path);\r
231             permPanel.add(pathPanel);\r
232         }\r
233 \r
234         return permPanel;\r
235     }\r
236 \r
237         /**\r
238          * Accepts any change and updates the file\r
239          *\r
240          */\r
241         @Override\r
242         protected void accept() {\r
243                 final Map<String, Boolean[]> perms = (permList.hasChanges() ? permList.getPermissions() : null);\r
244 \r
245                 //only update the read for all perm if the user is the owner\r
246         Boolean published = null;\r
247                 if (readForAll.getValue() != file.isPublished())\r
248                         if (file.getOwner().equals(app.getUsername()))\r
249                 published = readForAll.getValue();\r
250         final Boolean finalPublished = published;\r
251 \r
252         updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", finalPublished, perms);\r
253         }\r
254 \r
255         protected void updateMetaData(String api, String owner, String path, final Boolean published, final Map<String, Boolean[]> newPermissions) {\r
256         if (published != null || newPermissions != null) {\r
257             PostRequest updateFile = new PostRequest(api, owner, path) {\r
258                 @Override\r
259                 public void onSuccess(@SuppressWarnings("unused") Resource result) {\r
260                     app.updateFolder(file.getParent(), true, new Command() {\r
261                                                 \r
262                                                 @Override\r
263                                                 public void execute() {\r
264                                                         app.updateMySharedRoot();\r
265                                                 }\r
266                                         });\r
267                 }\r
268 \r
269                 @Override\r
270                 public void onError(Throwable t) {\r
271                     GWT.log("", t);\r
272                                         app.setError(t);\r
273                     app.displayError("System error modifying file:" + t.getMessage());\r
274                 }\r
275 \r
276                                 @Override\r
277                                 protected void onUnauthorized(@SuppressWarnings("unused") Response response) {\r
278                                         app.sessionExpired();\r
279                                 }\r
280             };\r
281             updateFile.setHeader("X-Auth-Token", app.getToken());\r
282             \r
283             if (published != null)\r
284                 updateFile.setHeader("X-Object-Public", published.toString());\r
285             if (newPermissions != null) {\r
286                 String readPermHeader = "read=";\r
287                 String writePermHeader = "write=";\r
288                 for (String u : newPermissions.keySet()) {\r
289                     Boolean[] p = newPermissions.get(u);\r
290                     if (p[0] != null && p[0])\r
291                         readPermHeader += u + ",";\r
292                     if (p[1] != null && p[1])\r
293                         writePermHeader += u + ",";\r
294                 }\r
295                 if (readPermHeader.endsWith("="))\r
296                     readPermHeader = "";\r
297                 else if (readPermHeader.endsWith(","))\r
298                     readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);\r
299                 if (writePermHeader.endsWith("="))\r
300                     writePermHeader = "";\r
301                 else if (writePermHeader.endsWith(","))\r
302                     writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);\r
303                 String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;\r
304                 if (permHeader.length() == 0)\r
305                     permHeader="~";\r
306                 else\r
307                         permHeader = URL.encodePathSegment(permHeader);\r
308                 updateFile.setHeader("X-Object-Sharing", permHeader);\r
309             }\r
310             Scheduler.get().scheduleDeferred(updateFile);\r
311         }\r
312         else\r
313             app.updateFolder(file.getParent(), true, new Command() {\r
314                                 \r
315                                 @Override\r
316                                 public void execute() {\r
317                                         if (file.isShared())\r
318                                                 app.updateMySharedRoot();\r
319                                 }\r
320                         });\r
321     }\r
322 }\r