001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.web.client.contents;
017
018import com.smartgwt.client.types.Alignment;
019import com.smartgwt.client.types.VerticalAlignment;
020import com.smartgwt.client.util.BooleanCallback;
021import com.smartgwt.client.util.SC;
022import com.smartgwt.client.widgets.Label;
023import com.smartgwt.client.widgets.events.ClickEvent;
024import com.smartgwt.client.widgets.events.ClickHandler;
025import com.smartgwt.client.widgets.form.DynamicForm;
026import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
027import com.smartgwt.client.widgets.layout.HLayout;
028import java.util.ArrayList;
029import org.modeshape.web.client.contents.PermissionsEditor.AclRecord;
030import org.modeshape.web.client.grid.BooleanField;
031import org.modeshape.web.client.grid.TabGrid;
032import org.modeshape.web.shared.Align;
033import org.modeshape.web.shared.Columns;
034import org.modeshape.web.shared.JcrNode;
035import org.modeshape.web.shared.JcrPermission;
036import org.modeshape.web.shared.Policy;
037
038/**
039 * Permissions editor.
040 *
041 * @author kulikov
042 */
043public class PermissionsEditor extends TabGrid<AclRecord, JcrPermission> {
044
045    private final Policy ALL_PERMISSIONS_FOR_EVERYONE = new Policy();
046    
047    //header hight in pixels
048    private final static int HEADER_HEIGHT = 30;
049    
050    protected final Contents contents;
051    private JcrNode node;
052    
053    private ComboBoxItem principal;
054    protected AddPolicyDialog addPolicyDialog;
055
056    /**
057     * Creates new Editor.
058     * 
059     * @param contents 
060     */
061    public PermissionsEditor(Contents contents) {
062        super("");
063        this.contents = contents;
064        for (JcrPermission p : ALL_PERMISSIONS_FOR_EVERYONE.permissions()) {
065            p.setStatus(true);
066        }
067        addPolicyDialog = new AddPolicyDialog(contents);        
068    }
069
070    /**
071     * Displays permissions for the given node.
072     * 
073     * @param node 
074     */
075    public void show(JcrNode node) {
076        this.node = node;
077        if (node.getAcl() == null) {
078            this.displayDisabledEditor();
079        } else if (this.isAclDefined(node)) {
080            this.selectFirstPrincipalAndDisplayPermissions(node);
081        } else {
082            this.displayEveryonePermissions();
083        }
084    }
085
086    @Override
087    protected AclRecord[] records() {
088        int n = new Policy().permissions().size();
089        AclRecord[] records = new AclRecord[n];
090        for (int i = 0; i < n; i++) {
091            records[i] = new AclRecord();
092        }
093        return records;
094    }
095
096    @Override
097    protected HLayout tableHeader() {
098        HLayout layout = new HLayout();
099
100        layout.setHeight(30);
101        layout.setWidth100();
102
103        layout.setBackgroundColor("#e6f1f6");
104
105        Label name = new Label("<b>Permission</b>");
106        name.setWidth100();
107
108        Label type = new Label("<b>Status</b>");
109        type.setWidth(50);
110
111
112        layout.addMember(name);
113        layout.addMember(type);
114
115        return layout;
116    }
117
118    @Override
119    protected HLayout toolBar() {
120        Columns layout = new Columns(Align.LEFT, Align.CENTER);
121        layout.setBackgroundColor("#ffffff");
122        layout.setHeight(HEADER_HEIGHT);
123        layout.setWidth100();
124
125        //prepare form for the principal combobox
126        DynamicForm form = new DynamicForm();
127        form.setWidth100();
128
129        //put into layout
130        layout.addMember(form);
131
132        //prepare combobox for principal selection
133        principal = new ComboBoxItem("Principal");
134        principal.setWidth("100%");
135
136        //append on form
137        form.setItems(principal);
138
139        //buttons
140        Label addPrincipalButton = new Label();
141        addPrincipalButton.setStyleName("button-label");
142        addPrincipalButton.setWidth(16);
143        addPrincipalButton.setHeight(16);
144        addPrincipalButton.setIcon("icons/group_blue_add.png");
145        addPrincipalButton.setTooltip("Add new principal name");
146        addPrincipalButton.addClickHandler(new ClickHandler() {
147            @Override
148            public void onClick(ClickEvent event) {
149                addPrincipal();
150            }
151        });
152        
153        layout.addMember(addPrincipalButton);
154
155        Label delPrincipalButton = new Label();
156        delPrincipalButton.setStyleName("button-label");
157        delPrincipalButton.setWidth(16);
158        delPrincipalButton.setHeight(16);
159        delPrincipalButton.setIcon("icons/group_blue_remove.png");
160        delPrincipalButton.setTooltip("Delete this principal");
161        delPrincipalButton.addClickHandler(new ClickHandler() {
162            @Override
163            public void onClick(ClickEvent event) {
164                delPrincipal();
165            }
166        });
167        
168        layout.addMember(delPrincipalButton);
169
170        return layout;
171    }
172
173    private void addPrincipal() {
174        addPolicyDialog.showModal();
175    }
176    
177    private void delPrincipal() {
178        SC.ask("Do you want to delete principal " + principal.getValueAsString(), new BooleanCallback() {
179            @Override
180            public void execute(Boolean status) {
181                if (status) {
182                    contents.removeAccessList(principal.getValueAsString());
183                }
184            }
185        });
186    }
187    
188    @SuppressWarnings("synthetic-access")
189    @Override
190    protected void updateRecord(int pos, AclRecord record, JcrPermission value) {
191        record.name.setContents(value.getDisplayName());
192        record.value.setValue(value.getStatus());
193        record.permission = value;
194    }
195
196    private boolean isAclDefined(JcrNode node) {
197        return !(node.getAcl() == null || node.getAcl().principals().length == 0);
198    }
199
200    private void displayEveryonePermissions() {
201        principal.setValueMap(new String[]{"Everyone"});
202        principal.setValue("Everyone");
203        principal.setDisabled(false);
204        setValues(ALL_PERMISSIONS_FOR_EVERYONE.permissions());
205    }
206
207    private void displayDisabledEditor() {
208        principal.setValueMap(new String[]{"Permission denied"});
209        principal.setValue("Permission denied");
210        principal.setDisabled(true);
211        setValues(new ArrayList());
212    }
213    
214    private void selectFirstPrincipalAndDisplayPermissions(JcrNode node) {
215        String[] principals = node.getAcl().principals();
216        principal.setValueMap(principals);
217        principal.setValue(principals[0]);
218        principal.setDisabled(false);
219        setValues(node.getAcl().getPolicy(principals[0]).permissions());
220    }
221
222    @SuppressWarnings("synthetic-access")
223    public class AclRecord extends HLayout {
224        private JcrPermission permission;
225        private Label name = new Label();
226        private BooleanField value = new BooleanField();
227
228        public AclRecord() {
229            super();
230            
231            setStyleName("grid");
232            setHeight(30);
233            setWidth100();
234
235            setDefaultLayoutAlign(VerticalAlignment.CENTER);
236            setDefaultLayoutAlign(Alignment.LEFT);
237
238            setLayoutAlign(VerticalAlignment.CENTER);
239            setLayoutAlign(Alignment.CENTER);
240
241            setAlign(VerticalAlignment.CENTER);
242            setAlign(Alignment.LEFT);
243
244            name.setIcon("icons/shield.png");
245            name.setStyleName("text");
246            name.setWidth100();
247
248            value.setWidth(50);
249            value.setStyleName("button-label");
250            value.addClickHandler(new ClickHandler() {
251                @Override
252                public void onClick(ClickEvent event) {
253                    changePermission();
254                }
255            });
256
257            addMember(name);
258            addMember(value);
259        }
260        
261        private void changePermission() {
262            //this is everyone "principal"?
263            if (node.getAcl() == null) {
264                return;
265            }            
266            permission.setStatus(!permission.getStatus());
267            contents.updateAccessList(principal.getValueAsString(), permission, permission.getStatus());
268        }
269
270    }
271}