James Moger
2012-09-10 fabe060d3a435f116128851f828e35c2af5fde67
commit | author | age
eb96ea 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.text.MessageFormat;
21 import java.util.List;
22
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import com.gitblit.models.TeamModel;
27 import com.gitblit.models.UserModel;
6cca86 28 import com.gitblit.utils.DeepCopier;
eb96ea 29
JM 30 /**
31  * This class wraps the default user service and is recommended as the starting
32  * point for custom user service implementations.
33  * 
34  * This does seem a little convoluted, but the idea is to allow IUserService to
35  * evolve with new methods and implementations without breaking custom
36  * authentication implementations.
37  * 
38  * The most common implementation of a custom IUserService is to only override
39  * authentication and then delegate all other functionality to one of Gitblit's
40  * user services. This class optimizes that use-case.
41  * 
42  * Extending GitblitUserService allows for authentication customization without
43  * having to keep-up-with IUSerService API changes.
44  * 
45  * @author James Moger
46  * 
47  */
48 public class GitblitUserService implements IUserService {
49
50     protected IUserService serviceImpl;
51
52     private final Logger logger = LoggerFactory.getLogger(GitblitUserService.class);
53
54     public GitblitUserService() {
55     }
56
57     @Override
58     public void setup(IStoredSettings settings) {
59         File realmFile = GitBlit.getFileOrFolder(Keys.realm.userService, "users.conf");
60         serviceImpl = createUserService(realmFile);
f5fa79 61         logger.info("GUS delegating to " + serviceImpl.toString());
eb96ea 62     }
JM 63
64     @SuppressWarnings("deprecation")
65     protected IUserService createUserService(File realmFile) {
66         IUserService service = null;
67         if (realmFile.getName().toLowerCase().endsWith(".properties")) {
68             // v0.5.0 - v0.7.0 properties-based realm file
69             service = new FileUserService(realmFile);
70         } else if (realmFile.getName().toLowerCase().endsWith(".conf")) {
71             // v0.8.0+ config-based realm file
72             service = new ConfigUserService(realmFile);
73         }
74
75         assert service != null;
76
e3d0d4 77         if (!realmFile.exists()) {
eb96ea 78             // Create the Administrator account for a new realm file
JM 79             try {
80                 realmFile.createNewFile();
81             } catch (IOException x) {
82                 logger.error(MessageFormat.format("COULD NOT CREATE REALM FILE {0}!", realmFile), x);
83             }
84             UserModel admin = new UserModel("admin");
85             admin.password = "admin";
86             admin.canAdmin = true;
87             admin.excludeFromFederation = true;
88             service.updateUserModel(admin);
89         }
90
91         if (service instanceof FileUserService) {
92             // automatically create a users.conf realm file from the original
93             // users.properties file
94             File usersConfig = new File(realmFile.getParentFile(), "users.conf");
95             if (!usersConfig.exists()) {
96                 logger.info(MessageFormat.format("Automatically creating {0} based on {1}",
97                         usersConfig.getAbsolutePath(), realmFile.getAbsolutePath()));
98                 ConfigUserService configService = new ConfigUserService(usersConfig);
8051a2 99                 for (String username : service.getAllUsernames()) {
JM 100                     UserModel userModel = service.getUserModel(username);
eb96ea 101                     configService.updateUserModel(userModel);
JM 102                 }
103             }
104             // issue suggestion about switching to users.conf
105             logger.warn("Please consider using \"users.conf\" instead of the deprecated \"users.properties\" file");
106         }
107         return service;
108     }
f5fa79 109     
JM 110     @Override
111     public String toString() {
112         return getClass().getSimpleName();
113     }
eb96ea 114
JM 115     @Override
6cca86 116     public boolean supportsCredentialChanges() {
JM 117         return serviceImpl.supportsCredentialChanges();
118     }
119
120     @Override
0aa8cf 121     public boolean supportsDisplayNameChanges() {
JM 122         return serviceImpl.supportsDisplayNameChanges();
123     }
124
125     @Override
126     public boolean supportsEmailAddressChanges() {
127         return serviceImpl.supportsEmailAddressChanges();
128     }
129
130     @Override
6cca86 131     public boolean supportsTeamMembershipChanges() {
JM 132         return serviceImpl.supportsTeamMembershipChanges();
133     }
134
135     @Override
eb96ea 136     public boolean supportsCookies() {
JM 137         return serviceImpl.supportsCookies();
138     }
139
140     @Override
62aeb9 141     public String getCookie(UserModel model) {
eb96ea 142         return serviceImpl.getCookie(model);
JM 143     }
144
145     @Override
146     public UserModel authenticate(char[] cookie) {
147         return serviceImpl.authenticate(cookie);
148     }
149
150     @Override
151     public UserModel authenticate(String username, char[] password) {
152         return serviceImpl.authenticate(username, password);
153     }
ea094a 154     
JM 155     @Override
156     public void logout(UserModel user) {
157         serviceImpl.logout(user);
158     }
eb96ea 159
JM 160     @Override
161     public UserModel getUserModel(String username) {
162         return serviceImpl.getUserModel(username);
163     }
164
165     @Override
166     public boolean updateUserModel(UserModel model) {
167         return serviceImpl.updateUserModel(model);
168     }
169
170     @Override
171     public boolean updateUserModel(String username, UserModel model) {
6cca86 172         if (supportsCredentialChanges()) {
JM 173             if (!supportsTeamMembershipChanges()) {
f3b625 174                 //  teams are externally controlled - copy from original model
JC 175                 UserModel existingModel = getUserModel(username);
176                 
6cca86 177                 model = DeepCopier.copy(model);
JM 178                 model.teams.clear();
f3b625 179                 model.teams.addAll(existingModel.teams);
6cca86 180             }
JM 181             return serviceImpl.updateUserModel(username, model);
182         }
183         if (model.username.equals(username)) {
184             // passwords are not persisted by the backing user service
185             model.password = null;
186             if (!supportsTeamMembershipChanges()) {
f3b625 187                 //  teams are externally controlled- copy from original model
JC 188                 UserModel existingModel = getUserModel(username);
189                 
6cca86 190                 model = DeepCopier.copy(model);
JM 191                 model.teams.clear();
f3b625 192                 model.teams.addAll(existingModel.teams);
6cca86 193             }
JM 194             return serviceImpl.updateUserModel(username, model);
195         }
196         logger.error("Users can not be renamed!");
197         return false;
eb96ea 198     }
JM 199     @Override
200     public boolean deleteUserModel(UserModel model) {
201         return serviceImpl.deleteUserModel(model);
202     }
203
204     @Override
205     public boolean deleteUser(String username) {
206         return serviceImpl.deleteUser(username);
207     }
208
209     @Override
210     public List<String> getAllUsernames() {
211         return serviceImpl.getAllUsernames();
212     }
213
214     @Override
abeaaf 215     public List<UserModel> getAllUsers() {
JM 216         return serviceImpl.getAllUsers();
217     }
218
219     @Override
eb96ea 220     public List<String> getAllTeamNames() {
JM 221         return serviceImpl.getAllTeamNames();
222     }
223
224     @Override
abeaaf 225     public List<TeamModel> getAllTeams() {
JM 226         return serviceImpl.getAllTeams();
227     }
228
229     @Override
eb96ea 230     public List<String> getTeamnamesForRepositoryRole(String role) {
JM 231         return serviceImpl.getTeamnamesForRepositoryRole(role);
232     }
233
234     @Override
235     public boolean setTeamnamesForRepositoryRole(String role, List<String> teamnames) {
236         return serviceImpl.setTeamnamesForRepositoryRole(role, teamnames);
237     }
238
239     @Override
240     public TeamModel getTeamModel(String teamname) {
241         return serviceImpl.getTeamModel(teamname);
242     }
243
244     @Override
245     public boolean updateTeamModel(TeamModel model) {
246         return serviceImpl.updateTeamModel(model);
247     }
248
249     @Override
250     public boolean updateTeamModel(String teamname, TeamModel model) {
6cca86 251         if (!supportsTeamMembershipChanges()) {
f3b625 252             // teams are externally controlled - copy from original model
JC 253             TeamModel existingModel = getTeamModel(teamname);
254             
6cca86 255             model = DeepCopier.copy(model);
JM 256             model.users.clear();
f3b625 257             model.users.addAll(existingModel.users);
6cca86 258         }
eb96ea 259         return serviceImpl.updateTeamModel(teamname, model);
JM 260     }
261
262     @Override
263     public boolean deleteTeamModel(TeamModel model) {
264         return serviceImpl.deleteTeamModel(model);
265     }
266
267     @Override
268     public boolean deleteTeam(String teamname) {
269         return serviceImpl.deleteTeam(teamname);
270     }
271
272     @Override
273     public List<String> getUsernamesForRepositoryRole(String role) {
274         return serviceImpl.getUsernamesForRepositoryRole(role);
275     }
276
277     @Override
278     public boolean setUsernamesForRepositoryRole(String role, List<String> usernames) {
279         return serviceImpl.setUsernamesForRepositoryRole(role, usernames);
280     }
281
282     @Override
283     public boolean renameRepositoryRole(String oldRole, String newRole) {
284         return serviceImpl.renameRepositoryRole(oldRole, newRole);
285     }
286
287     @Override
288     public boolean deleteRepositoryRole(String role) {
289         return serviceImpl.deleteRepositoryRole(role);
290     }
291 }