#### Discrete Permissions with Regex Matching (Gitblit v1.2.0+) | #### Discrete Permissions with Regex Matching (Gitblit v1.2.0+) | ||||
Gitblit also supports regex matching for repository permissions. The following permission grants push privileges to all repositories in the *mygroup* folder. | |||||
Gitblit also supports *case-insensitive* regex matching for repository permissions. The following permission grants push privileges to all repositories in the *mygroup* folder. | |||||
RW:mygroup/[A-Za-z0-9-~_\\./]+ | |||||
RW:mygroup/[a-z0-9-~_\\./]+ | |||||
#### No-So-Discrete Permissions (Gitblit <= v1.1.0) | #### No-So-Discrete Permissions (Gitblit <= v1.1.0) | ||||
- RWD (clone and push with ref creation, deletion) | - RWD (clone and push with ref creation, deletion) | ||||
- RW+ (clone and push with ref creation, deletion, rewind) | - RW+ (clone and push with ref creation, deletion, rewind) | ||||
While not as sophisticated as Gitolite, this does give finer access controls. These permissions fit in cleanly with the existing users.conf and users.properties files. In Gitblit <= 1.1.0, all your existing user accounts have RW+ access. If you are upgrading to 1.2.0, the RW+ access is *preserved* and you will have to lower/adjust accordingly. | While not as sophisticated as Gitolite, this does give finer access controls. These permissions fit in cleanly with the existing users.conf and users.properties files. In Gitblit <= 1.1.0, all your existing user accounts have RW+ access. If you are upgrading to 1.2.0, the RW+ access is *preserved* and you will have to lower/adjust accordingly. | ||||
- Implemented regex repository permission matching (issue 36) | |||||
This allows you to specify a permission like `RW:mygroup/[A-Za-z0-9-~_\\./]+` to grant push privileges to all repositories within the *mygroup* project/folder. | |||||
- Implemented *case-insensitive* regex repository permission matching (issue 36) | |||||
This allows you to specify a permission like `RW:mygroup/[a-z0-9-~_\\./]+` to grant push privileges to all repositories within the *mygroup* project/folder. | |||||
- Added DELETE, CREATE, and NON-FAST-FORWARD ref change logging | - Added DELETE, CREATE, and NON-FAST-FORWARD ref change logging | ||||
- Added support for personal repositories. | - Added support for personal repositories. | ||||
Personal repositories can be created by accounts with the *create* permission and are stored in *git.repositoriesFolder/~username*. Each user with personal repositories will have a user page, something like the GitHub profile page. Personal repositories have all the same features as common repositories, except personal repositories can be renamed by their owner. | Personal repositories can be created by accounts with the *create* permission and are stored in *git.repositoriesFolder/~username*. Each user with personal repositories will have a user page, something like the GitHub profile page. Personal repositories have all the same features as common repositories, except personal repositories can be renamed by their owner. |
import com.gitblit.Constants.AccessRestrictionType; | import com.gitblit.Constants.AccessRestrictionType; | ||||
import com.gitblit.Constants.RegistrantType; | import com.gitblit.Constants.RegistrantType; | ||||
import com.gitblit.Constants.Unused; | import com.gitblit.Constants.Unused; | ||||
import com.gitblit.utils.StringUtils; | |||||
/** | /** | ||||
* TeamModel is a serializable model class that represents a group of users and | * TeamModel is a serializable model class that represents a group of users and | ||||
permission = p; | permission = p; | ||||
} | } | ||||
} else { | } else { | ||||
// search for regex permission match | |||||
// search for case-insensitive regex permission match | |||||
for (String key : permissions.keySet()) { | for (String key : permissions.keySet()) { | ||||
if (repository.name.matches(key)) { | |||||
if (StringUtils.matchesIgnoreCase(repository.name, key)) { | |||||
AccessPermission p = permissions.get(key); | AccessPermission p = permissions.get(key); | ||||
if (p != null) { | if (p != null) { | ||||
permission = p; | permission = p; |
return p; | return p; | ||||
} | } | ||||
} else { | } else { | ||||
// search for regex permission match | |||||
// search for case-insensitive regex permission match | |||||
for (String key : permissions.keySet()) { | for (String key : permissions.keySet()) { | ||||
if (repository.name.matches(key)) { | |||||
if (StringUtils.matchesIgnoreCase(repository.name, key)) { | |||||
AccessPermission p = permissions.get(key); | AccessPermission p = permissions.get(key); | ||||
if (p != null) { | if (p != null) { | ||||
permission = p; | permission = p; |
} | } | ||||
return path; | return path; | ||||
} | } | ||||
/** | |||||
* Variation of String.matches() which disregards case issues. | |||||
* | |||||
* @param regex | |||||
* @param input | |||||
* @return true if the pattern matches | |||||
*/ | |||||
public static boolean matchesIgnoreCase(String input, String regex) { | |||||
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); | |||||
Matcher m = p.matcher(input); | |||||
return m.matches(); | |||||
} | |||||
} | } |
repository.accessRestriction = AccessRestrictionType.VIEW; | repository.accessRestriction = AccessRestrictionType.VIEW; | ||||
UserModel user = new UserModel("test"); | UserModel user = new UserModel("test"); | ||||
user.setRepositoryPermission("ubercool/[A-Za-z0-9-~_\\./]+", AccessPermission.CLONE); | |||||
user.setRepositoryPermission("ubercool/[A-Z0-9-~_\\./]+", AccessPermission.CLONE); | |||||
assertTrue("user DOES NOT HAVE a repository permission!", user.hasRepositoryPermission(repository.name)); | assertTrue("user DOES NOT HAVE a repository permission!", user.hasRepositoryPermission(repository.name)); | ||||
assertTrue("user CAN NOT view!", user.canView(repository)); | assertTrue("user CAN NOT view!", user.canView(repository)); |