001/*
002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.platform.login.deputy.management;
023
024import java.io.Serializable;
025import java.util.ArrayList;
026import java.util.Calendar;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Map;
030
031import org.nuxeo.ecm.core.api.DataModel;
032import org.nuxeo.ecm.core.api.DocumentModel;
033import org.nuxeo.ecm.core.api.DocumentModelList;
034import org.nuxeo.ecm.core.api.NuxeoException;
035import org.nuxeo.ecm.core.api.impl.DataModelImpl;
036import org.nuxeo.ecm.core.api.impl.DocumentModelImpl;
037import org.nuxeo.ecm.directory.DirectoryException;
038import org.nuxeo.ecm.directory.Session;
039import org.nuxeo.ecm.directory.api.DirectoryService;
040import org.nuxeo.runtime.api.Framework;
041
042public class DeputyManagementStorageService implements DeputyManager {
043
044    private static final String DIR_NAME = "deputies";
045
046    private static final String DIR_COL_ID = "id";
047
048    private static final String DIR_COL_USERID = "userid";
049
050    private static final String DIR_COL_DEPUTY = "deputy";
051
052    private static final String DIR_COL_VALIDATE_DATE = "validateDate";
053
054    private static final String DIR_COL_START_VALIDITY = "validityStartDate";
055
056    private static final String DIR_COL_END_VALIDITY = "validityEndDate";
057
058    private DirectoryService directoryService;
059
060    private Session dirSession;
061
062    private String directorySchema;
063
064    @Override
065    public String getDeputySchemaName() {
066        return directorySchema;
067    }
068
069    protected void initPersistentService() {
070        if (directoryService == null) {
071            directoryService = Framework.getService(DirectoryService.class);
072        }
073        dirSession = directoryService.open(DIR_NAME);
074        directorySchema = directoryService.getDirectorySchema(DIR_NAME);
075    }
076
077    private void releasePersistenceService() {
078        // for now directory sessions are lost during passivation of the
079        // DirectoryFacade
080        // this can't be tested on the client side
081        // => release directorySession after each call ...
082
083        if (directoryService == null) {
084            dirSession = null;
085            return;
086        }
087        if (dirSession != null) {
088            try {
089                dirSession.close();
090            } catch (DirectoryException e) {
091                // do nothing
092            }
093        }
094        dirSession = null;
095    }
096
097    public void resetDeputies() {
098        initPersistentService();
099
100        try {
101            DocumentModelList allEntries = dirSession.getEntries();
102            List<String> ids = new ArrayList<String>();
103            for (DocumentModel entry : allEntries) {
104                ids.add(entry.getId());
105            }
106            for (String id : ids) {
107                dirSession.deleteEntry(id);
108            }
109
110        } finally {
111            releasePersistenceService();
112        }
113
114    }
115
116    @Override
117    public List<String> getPossiblesAlternateLogins(String userName) {
118        List<String> users = new ArrayList<String>();
119        List<String> outdatedEntriesId = new ArrayList<String>();
120
121        initPersistentService();
122
123        try {
124            Map<String, Serializable> filter = new HashMap<String, Serializable>();
125            filter.put(DIR_COL_DEPUTY, userName);
126
127            DocumentModelList entries = null;
128
129            entries = dirSession.query(filter);
130
131            long currentTime = System.currentTimeMillis();
132            for (DocumentModel entry : entries) {
133
134                String alternateId = (String) entry.getProperty(directorySchema, DIR_COL_USERID);
135                Calendar startDate = (Calendar) entry.getProperty(directorySchema, DIR_COL_START_VALIDITY);
136                Calendar endDate = (Calendar) entry.getProperty(directorySchema, DIR_COL_END_VALIDITY);
137
138                boolean validateDate = (Boolean) entry.getProperty(directorySchema, DIR_COL_VALIDATE_DATE);
139                boolean valid = true;
140                if (validateDate && (startDate != null) && (startDate.getTimeInMillis() > currentTime)) {
141                    valid = false;
142                }
143                if (validateDate && (endDate != null) && (endDate.getTimeInMillis() < currentTime)) {
144                    valid = false;
145                }
146
147                if (valid) {
148                    users.add(alternateId);
149                } else {
150                    outdatedEntriesId.add(entry.getId());
151                }
152            }
153
154            for (String outDatedId : outdatedEntriesId) {
155                dirSession.deleteEntry(outDatedId);
156            }
157
158            return users;
159        } finally {
160
161            releasePersistenceService();
162        }
163    }
164
165    @Override
166    public List<String> getAvalaibleDeputyIds(String userName) {
167        List<String> deputies = new ArrayList<String>();
168
169        for (DocumentModel entry : getAvalaibleMandates(userName)) {
170            String alternateId = (String) entry.getProperty(directorySchema, DIR_COL_DEPUTY);
171            deputies.add(alternateId);
172        }
173
174        return deputies;
175    }
176
177    @Override
178    public List<DocumentModel> getAvalaibleMandates(String userName) {
179        List<DocumentModel> deputies = new ArrayList<DocumentModel>();
180
181        initPersistentService();
182
183        try {
184            Map<String, Serializable> filter = new HashMap<String, Serializable>();
185            filter.put(DIR_COL_USERID, userName);
186            return dirSession.query(filter);
187        } catch (DirectoryException e) {
188            return deputies;
189        } finally {
190            releasePersistenceService();
191        }
192
193    }
194
195    @Override
196    public DocumentModel newMandate(String username, String deputy) {
197
198        initPersistentService();
199
200        try {
201            DocumentModel entry = newEntry(username, deputy);
202            Calendar cal = Calendar.getInstance();
203            entry.setProperty(directorySchema, DIR_COL_VALIDATE_DATE, new Boolean(false));
204            entry.setProperty(directorySchema, DIR_COL_START_VALIDITY, cal);
205            entry.setProperty(directorySchema, DIR_COL_END_VALIDITY, cal);
206            return entry;
207        } finally {
208            releasePersistenceService();
209        }
210    }
211
212    protected DocumentModel newEntry(String username, String deputy) {
213        DataModel data = new DataModelImpl(directorySchema, new HashMap<String, Object>());
214        DocumentModelImpl entry = new DocumentModelImpl(null, directorySchema, "0", null, null, null, null,
215                new String[] { directorySchema }, null, null, null);
216        entry.addDataModel(data);
217        entry.setProperty(directorySchema, DIR_COL_ID, id(username, deputy));
218        entry.setProperty(directorySchema, DIR_COL_USERID, username);
219        entry.setProperty(directorySchema, DIR_COL_DEPUTY, deputy);
220        return entry;
221    }
222
223    @Override
224    public DocumentModel newMandate(String username, String deputy, Calendar start, Calendar end)
225            {
226
227        initPersistentService();
228
229        try {
230            DocumentModel entry = newEntry(username, deputy);
231            entry.setProperty(directorySchema, DIR_COL_VALIDATE_DATE, new Boolean(true));
232            entry.setProperty(directorySchema, DIR_COL_START_VALIDITY, start);
233            entry.setProperty(directorySchema, DIR_COL_END_VALIDITY, end);
234            return entry;
235        } finally {
236            releasePersistenceService();
237        }
238    }
239
240    @Override
241    public void addMandate(DocumentModel entry) {
242
243        initPersistentService();
244
245        try {
246            String id = id(entry);
247
248            if (dirSession.getEntry(id) != null) {
249                // first remove entry
250                dirSession.deleteEntry(id);
251            }
252
253            entry.setProperty(directorySchema, DIR_COL_ID, id);
254
255            dirSession.createEntry(entry);
256
257        } catch (DirectoryException e) {
258            throw new NuxeoException(e);
259        } finally {
260            releasePersistenceService();
261        }
262        return;
263    }
264
265    @Override
266    public void removeMandate(String username, String deputy) {
267
268        initPersistentService();
269
270        try {
271            String id = id(username, deputy);
272            dirSession.deleteEntry(id);
273        } finally {
274            releasePersistenceService();
275        }
276    }
277
278    protected String id(DocumentModel entry) {
279        return id((String) entry.getProperty(directorySchema, "userid"),
280                (String) entry.getProperty(directorySchema, "deputy"));
281    }
282
283    protected String id(String username, String deputy) {
284        return username + ":" + deputy;
285    }
286
287}