James Moger
2012-10-10 5d7545652a6529c9076f67acd75f7a977c8a44a6
commit | author | age
f13c4c 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  */
1f9dae 16 package com.gitblit.models;
dfb889 17
JM 18 import java.io.Serializable;
8c9a20 19 import java.security.Principal;
20714a 20 import java.util.HashMap;
831469 21 import java.util.HashSet;
20714a 22 import java.util.Map;
831469 23 import java.util.Set;
dfb889 24
20714a 25 import com.gitblit.Constants.AccessPermission;
1e1b85 26 import com.gitblit.Constants.AccessRestrictionType;
6adf56 27 import com.gitblit.Constants.AuthorizationControl;
20714a 28 import com.gitblit.Constants.Unused;
efe8ec 29 import com.gitblit.utils.StringUtils;
JM 30
d9f687 31 /**
JM 32  * UserModel is a serializable model class that represents a user and the user's
33  * restricted repository memberships. Instances of UserModels are also used as
34  * servlet user principals.
35  * 
36  * @author James Moger
37  * 
38  */
4b430b 39 public class UserModel implements Principal, Serializable, Comparable<UserModel> {
dfb889 40
JM 41     private static final long serialVersionUID = 1L;
42
616590 43     public static final UserModel ANONYMOUS = new UserModel();
e94078 44     
2a7306 45     // field names are reflectively mapped in EditUser page
JM 46     public String username;
47     public String password;
a31cf9 48     public String cookie;
7e0ce4 49     public String displayName;
JC 50     public String emailAddress;
2a7306 51     public boolean canAdmin;
1e1b85 52     public boolean canFork;
6662e3 53     public boolean canCreate;
831469 54     public boolean excludeFromFederation;
20714a 55     // retained for backwards-compatibility with RPC clients
JM 56     @Deprecated
831469 57     public final Set<String> repositories = new HashSet<String>();
20714a 58     public final Map<String, AccessPermission> permissions = new HashMap<String, AccessPermission>();
fe24a0 59     public final Set<TeamModel> teams = new HashSet<TeamModel>();
dfb889 60
6adf56 61     // non-persisted fields
JM 62     public boolean isAuthenticated;
63     
511554 64     public UserModel(String username) {
dfb889 65         this.username = username;
6adf56 66         this.isAuthenticated = true;
dfb889 67     }
JM 68
616590 69     private UserModel() {
ec0ce1 70         this.username = "$anonymous";
616590 71         this.isAuthenticated = false;
e94078 72     }
JM 73
efe8ec 74     /**
JM 75      * This method does not take into consideration Ownership where the
76      * administrator has not explicitly granted access to the owner.
77      * 
78      * @param repositoryName
79      * @return
80      */
81     @Deprecated
d0d438 82     public boolean canAccessRepository(String repositoryName) {
fe24a0 83         return canAdmin || repositories.contains(repositoryName.toLowerCase())
JM 84                 || hasTeamAccess(repositoryName);
dfb889 85     }
JM 86
20714a 87     @Deprecated
JM 88     @Unused
efe8ec 89     public boolean canAccessRepository(RepositoryModel repository) {
JM 90         boolean isOwner = !StringUtils.isEmpty(repository.owner)
91                 && repository.owner.equals(username);
6adf56 92         boolean allowAuthenticated = isAuthenticated && AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl);
fe24a0 93         return canAdmin || isOwner || repositories.contains(repository.name.toLowerCase())
6adf56 94                 || hasTeamAccess(repository.name) || allowAuthenticated;
fe24a0 95     }
JM 96
20714a 97     @Deprecated
JM 98     @Unused
fe24a0 99     public boolean hasTeamAccess(String repositoryName) {
JM 100         for (TeamModel team : teams) {
20714a 101             if (team.hasRepositoryPermission(repositoryName)) {
fe24a0 102                 return true;
JM 103             }
104         }
105         return false;
efe8ec 106     }
1e1b85 107     
20714a 108     @Deprecated
JM 109     @Unused
110     public boolean hasRepository(String name) {
111         return hasRepositoryPermission(name);
112     }
113
114     @Deprecated
115     @Unused
116     public void addRepository(String name) {
117         addRepositoryPermission(name);
118     }
119
120     @Deprecated
121     @Unused
122     public void removeRepository(String name) {
123         removeRepositoryPermission(name);
124     }
125     
126     /**
127      * Returns true if the user has any type of specified access permission for
128      * this repository.
129      * 
130      * @param name
131      * @return true if user has a specified access permission for the repository
132      */
133     public boolean hasRepositoryPermission(String name) {
134         String repository = AccessPermission.repositoryFromRole(name).toLowerCase();
135         return permissions.containsKey(repository) || repositories.contains(repository);
136     }
137     
138     /**
139      * Adds a repository permission to the team.
140      * <p>
141      * Role may be formatted as:
142      * <ul>
143      * <li> myrepo.git <i>(this is implicitly RW+)</i>
144      * <li> RW+:myrepo.git
145      * </ul>
146      * @param role
147      */
148     public void addRepositoryPermission(String role) {
149         AccessPermission permission = AccessPermission.permissionFromRole(role);
150         String repository = AccessPermission.repositoryFromRole(role).toLowerCase();
151         repositories.add(repository);
152         permissions.put(repository, permission);
153     }
154     
155     public AccessPermission removeRepositoryPermission(String name) {
156         String repository = AccessPermission.repositoryFromRole(name).toLowerCase();
157         repositories.remove(repository);
158         return permissions.remove(repository);
159     }
160         
161     public void setRepositoryPermission(String repository, AccessPermission permission) {
162         permissions.put(repository.toLowerCase(), permission);
163     }
164
165     public AccessPermission getRepositoryPermission(RepositoryModel repository) {
166         if (canAdmin || repository.isOwner(username) || repository.isUsersPersonalRepository(username)) {
167             return AccessPermission.REWIND;
eb1405 168         }
20714a 169         if (AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl) && isAuthenticated) {
JM 170             // AUTHENTICATED is a shortcut for authorizing all logged-in users RW access
171             return AccessPermission.REWIND;
172         }
173         
174         // determine best permission available based on user's personal permissions
175         // and the permissions of teams of which the user belongs
176         AccessPermission permission = AccessPermission.NONE;
177         if (permissions.containsKey(repository.name.toLowerCase())) {
5d7545 178             // exact repository permission specified
20714a 179             AccessPermission p = permissions.get(repository.name.toLowerCase());
JM 180             if (p != null) {
181                 permission = p;
182             }
5d7545 183         } else {
JM 184             // search for regex permission match
185             for (String key : permissions.keySet()) {
186                 if (repository.name.matches(key)) {
187                     AccessPermission p = permissions.get(key);
188                     if (p != null) {
189                         permission = p;
190                     }
191                 }
192             }
20714a 193         }
JM 194         
195         for (TeamModel team : teams) {
196             AccessPermission p = team.getRepositoryPermission(repository);
197             if (permission == null || p.exceeds(permission)) {
198                 // use team permission
199                 permission = p;
200             }
201         }
202         return permission;
203     }
204     
205     private boolean canAccess(RepositoryModel repository, AccessRestrictionType ifRestriction, AccessPermission requirePermission) {
206         if (repository.accessRestriction.atLeast(ifRestriction)) {
207             AccessPermission permission = getRepositoryPermission(repository);
208             return permission.atLeast(requirePermission);
eb1405 209         }
JM 210         return true;
211     }
212     
20714a 213     public boolean canView(RepositoryModel repository) {
JM 214         return canAccess(repository, AccessRestrictionType.VIEW, AccessPermission.VIEW);
215     }
216
217     public boolean canClone(RepositoryModel repository) {
218         return canAccess(repository, AccessRestrictionType.CLONE, AccessPermission.CLONE);
219     }
220
221     public boolean canPush(RepositoryModel repository) {
222         if (repository.isFrozen) {
223             return false;
224         }
225         return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.PUSH);
226     }
227
228     public boolean canCreateRef(RepositoryModel repository) {
229         if (repository.isFrozen) {
230             return false;
231         }
232         return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.CREATE);
233     }
234
235     public boolean canDeleteRef(RepositoryModel repository) {
236         if (repository.isFrozen) {
237             return false;
238         }
239         return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.DELETE);
240     }
241
242     public boolean canRewindRef(RepositoryModel repository) {
243         if (repository.isFrozen) {
244             return false;
245         }
246         return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.REWIND);
247     }
248
249     public boolean canFork(RepositoryModel repository) {
250         if (repository.isUsersPersonalRepository(username)) {
251             // can not fork your own repository
252             return false;
253         }
254         if (canAdmin || repository.isOwner(username)) {
1e1b85 255             return true;
JM 256         }
257         if (!repository.allowForks) {
258             return false;
259         }
20714a 260         if (!isAuthenticated || !canFork) {
JM 261             return false;
1e1b85 262         }
20714a 263         return canClone(repository);
1e1b85 264     }
20714a 265     
JM 266     public boolean canDelete(RepositoryModel model) {
267         return canAdmin || model.isUsersPersonalRepository(username);
93f472 268     }
20714a 269     
JM 270     public boolean canEdit(RepositoryModel model) {
271         return canAdmin || model.isUsersPersonalRepository(username) || model.isOwner(username);
93f472 272     }
JM 273
fe24a0 274     public boolean isTeamMember(String teamname) {
JM 275         for (TeamModel team : teams) {
276             if (team.name.equalsIgnoreCase(teamname)) {
277                 return true;
278             }
279         }
280         return false;
281     }
282
997c16 283     public TeamModel getTeam(String teamname) {
JM 284         if (teams == null) {
285             return null;
286         }
287         for (TeamModel team : teams) {
288             if (team.name.equalsIgnoreCase(teamname)) {
289                 return team;
290             }
291         }
292         return null;
293     }
294
8a2e9c 295     @Override
85c2e6 296     public String getName() {
8c9a20 297         return username;
JM 298     }
d2426e 299     
JM 300     public String getDisplayName() {
301         if (StringUtils.isEmpty(displayName)) {
302             return username;
303         }
304         return displayName;
305     }
6662e3 306     
JM 307     public String getPersonalPath() {
308         return "~" + username;
309     }
310     
311     @Override
312     public int hashCode() {
313         return username.hashCode();
314     }
315     
316     @Override
317     public boolean equals(Object o) {
318         if (o instanceof UserModel) {
319             return username.equals(((UserModel) o).username);
320         }
321         return false;
322     }
8c9a20 323
JM 324     @Override
dfb889 325     public String toString() {
JM 326         return username;
327     }
4b430b 328
JM 329     @Override
330     public int compareTo(UserModel o) {
331         return username.compareTo(o.username);
332     }
dfb889 333 }