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