using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ScrewTurn.Wiki.PluginFramework;
namespace ScrewTurn.Wiki {
public partial class PermissionsManager : System.Web.UI.UserControl {
protected void Page_Load(object sender, EventArgs e) {
}
///
/// Gets or sets the name of the resource of which to display the actions.
///
public AclResources CurrentResourceType {
get {
return aclActionsSelector.CurrentResource;
}
set {
aclActionsSelector.CurrentResource = value;
}
}
///
/// Gets or sets the full (internal) name of the current resource.
///
public string CurrentResourceName {
get {
return ViewState["CRN"] as string;
}
set {
ViewState["CRN"] = value;
PopulateSubjectsList();
}
}
///
/// Gets or sets the current files provider (if CurrentResourceType is Directories).
///
public string CurrentFilesProvider {
get {
return ViewState["CFP"] as string;
}
set {
ViewState["CFP"] = value;
PopulateSubjectsList();
}
}
///
/// Gets the subjects for the current resource.
///
/// The subjects.
private SubjectInfo[] GetSubjects() {
if(CurrentResourceType != AclResources.Namespaces && string.IsNullOrEmpty(CurrentResourceName) ||
(CurrentResourceType == AclResources.Directories && string.IsNullOrEmpty(CurrentFilesProvider))) {
return new SubjectInfo[0];
}
switch(CurrentResourceType) {
case AclResources.Namespaces:
return AuthReader.RetrieveSubjectsForNamespace(Pages.FindNamespace(CurrentResourceName));
case AclResources.Pages:
return AuthReader.RetrieveSubjectsForPage(Pages.FindPage(CurrentResourceName));
case AclResources.Directories:
return AuthReader.RetrieveSubjectsForDirectory(
Collectors.FilesProviderCollector.GetProvider(CurrentFilesProvider), CurrentResourceName);
default:
throw new NotSupportedException();
}
}
///
/// Populates the subjects list.
///
private void PopulateSubjectsList() {
SubjectInfo[] subjects = GetSubjects();
// Sort: groups first, users second
Array.Sort(subjects, delegate(SubjectInfo x, SubjectInfo y) {
if(x.Type == y.Type) return x.Name.CompareTo(y.Name);
else {
if(x.Type == SubjectType.Group) return -1;
else return 1;
}
});
lstSubjects.Items.Clear();
foreach(SubjectInfo subject in subjects) {
bool isGroup = subject.Type == SubjectType.Group;
lstSubjects.Items.Add(
new ListItem((isGroup ? Properties.Messages.Group : Properties.Messages.User) +
": " + subject.Name, (isGroup ? "G." : "U.") + subject.Name));
}
ClearPermissions();
}
protected void lstSubjects_SelectedIndexChanged(object sender, EventArgs e) {
string selectedSubject = lstSubjects.SelectedValue;
if(string.IsNullOrEmpty(selectedSubject)) ClearPermissions();
else DisplaySubjectPermissions(selectedSubject.Substring(2), selectedSubject.StartsWith("G.") ? SubjectType.Group : SubjectType.User);
}
///
/// Displays the permissions for a subject in the actions matrix.
///
/// The subject.
/// The subject type.
private void DisplaySubjectPermissions(string subject, SubjectType type) {
lblSelectedSubject.Text = subject;
string[] grants = null;
string[] denials = null;
switch(CurrentResourceType) {
case AclResources.Namespaces:
if(type == SubjectType.Group) {
grants = AuthReader.RetrieveGrantsForNamespace(
Users.FindUserGroup(subject),
Pages.FindNamespace(CurrentResourceName));
denials = AuthReader.RetrieveDenialsForNamespace(
Users.FindUserGroup(subject),
Pages.FindNamespace(CurrentResourceName));
}
else {
grants = AuthReader.RetrieveGrantsForNamespace(
Users.FindUser(subject),
Pages.FindNamespace(CurrentResourceName));
denials = AuthReader.RetrieveDenialsForNamespace(
Users.FindUser(subject),
Pages.FindNamespace(CurrentResourceName));
}
break;
case AclResources.Pages:
if(type == SubjectType.Group) {
grants = AuthReader.RetrieveGrantsForPage(
Users.FindUserGroup(subject),
Pages.FindPage(CurrentResourceName));
denials = AuthReader.RetrieveDenialsForPage(
Users.FindUserGroup(subject),
Pages.FindPage(CurrentResourceName));
}
else {
grants = AuthReader.RetrieveGrantsForPage(
Users.FindUser(subject),
Pages.FindPage(CurrentResourceName));
denials = AuthReader.RetrieveDenialsForPage(
Users.FindUser(subject),
Pages.FindPage(CurrentResourceName));
}
break;
case AclResources.Directories:
string directory = CurrentResourceName;
IFilesStorageProviderV30 prov = Collectors.FilesProviderCollector.GetProvider(CurrentFilesProvider);
if(type == SubjectType.Group) {
grants = AuthReader.RetrieveGrantsForDirectory(
Users.FindUserGroup(subject),
prov, directory);
denials = AuthReader.RetrieveDenialsForDirectory(
Users.FindUserGroup(subject),
prov, directory);
}
else {
grants = AuthReader.RetrieveGrantsForDirectory(
Users.FindUser(subject),
prov, directory);
denials = AuthReader.RetrieveDenialsForDirectory(
Users.FindUser(subject),
prov, directory);
}
break;
default:
throw new NotSupportedException();
}
aclActionsSelector.GrantedActions = grants;
aclActionsSelector.DeniedActions = denials;
btnSave.Enabled = true;
btnRemove.Enabled = true;
}
///
/// Clears the actions matrix.
///
private void ClearPermissions() {
lblSelectedSubject.Text = "";
aclActionsSelector.GrantedActions = new string[0];
aclActionsSelector.DeniedActions = new string[0];
btnSave.Enabled = false;
btnRemove.Enabled = false;
}
///
/// Removes all the ACL entries for a subject.
///
/// The subject.
/// The namespace (null for the root).
/// true if the operation succeeded, false otherwise.
private bool RemoveAllAclEntriesForNamespace(string subject, string nspace) {
bool isGroup = lstSubjects.SelectedValue.StartsWith("G.");
subject = subject.Substring(2);
NamespaceInfo namespaceInfo = Pages.FindNamespace(nspace);
if(isGroup) {
return AuthWriter.RemoveEntriesForNamespace(
Users.FindUserGroup(subject), namespaceInfo);
}
else {
return AuthWriter.RemoveEntriesForNamespace(
Users.FindUser(subject), namespaceInfo);
}
}
///
/// Removes all the ACL entries for a subject.
///
/// The subject.
/// The page.
/// true if the operation succeeded, false otherwise.
private bool RemoveAllAclEntriesForPage(string subject, string page) {
bool isGroup = lstSubjects.SelectedValue.StartsWith("G.");
subject = subject.Substring(2);
PageInfo currentPage = Pages.FindPage(page);
if(isGroup) {
return AuthWriter.RemoveEntriesForPage(
Users.FindUserGroup(subject), currentPage);
}
else {
return AuthWriter.RemoveEntriesForPage(
Users.FindUser(subject), currentPage);
}
}
///
/// Removes all the ACL entries for a subject.
///
/// The subject.
/// The provider.
/// The directory.
/// true if the operation succeeded, false otherwise.
private bool RemoveAllAclEntriesForDirectory(string subject, IFilesStorageProviderV30 provider, string directory) {
bool isGroup = lstSubjects.SelectedValue.StartsWith("G.");
subject = subject.Substring(2);
if(isGroup) {
return AuthWriter.RemoveEntriesForDirectory(
Users.FindUserGroup(subject), provider, directory);
}
else {
return AuthWriter.RemoveEntriesForDirectory(
Users.FindUser(subject), provider, directory);
}
}
///
/// Adds some ACL entries for a subject.
///
/// The subject.
/// The namespace (null for the root).
/// The granted actions.
/// The denied actions.
/// true if the operation succeeded, false otherwise.
private bool AddAclEntriesForNamespace(string subject, string nspace, string[] grants, string[] denials) {
bool isGroup = subject.StartsWith("G.");
subject = subject.Substring(2);
NamespaceInfo namespaceInfo = Pages.FindNamespace(nspace);
UserGroup group = null;
UserInfo user = null;
if(isGroup) group = Users.FindUserGroup(subject);
else user = Users.FindUser(subject);
foreach(string action in grants) {
bool done = false;
if(isGroup) {
done = AuthWriter.SetPermissionForNamespace(AuthStatus.Grant,
namespaceInfo, action, group);
}
else {
done = AuthWriter.SetPermissionForNamespace(AuthStatus.Grant,
namespaceInfo, action, user);
}
if(!done) return false;
}
foreach(string action in denials) {
bool done = false;
if(isGroup) {
done = AuthWriter.SetPermissionForNamespace(AuthStatus.Deny,
namespaceInfo, action, group);
}
else {
done = AuthWriter.SetPermissionForNamespace(AuthStatus.Deny,
namespaceInfo, action, user);
}
if(!done) return false;
}
return true;
}
///
/// Adds some ACL entries for a subject.
///
/// The subject.
/// The page.
/// The granted actions.
/// The denied actions.
/// true if the operation succeeded, false otherwise.
private bool AddAclEntriesForPage(string subject, string page, string[] grants, string[] denials) {
bool isGroup = subject.StartsWith("G.");
subject = subject.Substring(2);
PageInfo currentPage = Pages.FindPage(page);
UserGroup group = null;
UserInfo user = null;
if(isGroup) group = Users.FindUserGroup(subject);
else user = Users.FindUser(subject);
foreach(string action in grants) {
bool done = false;
if(isGroup) {
done = AuthWriter.SetPermissionForPage(AuthStatus.Grant,
currentPage, action, group);
}
else {
done = AuthWriter.SetPermissionForPage(AuthStatus.Grant,
currentPage, action, user);
}
if(!done) return false;
}
foreach(string action in denials) {
bool done = false;
if(isGroup) {
done = AuthWriter.SetPermissionForPage(AuthStatus.Deny,
currentPage, action, group);
}
else {
done = AuthWriter.SetPermissionForPage(AuthStatus.Deny,
currentPage, action, user);
}
if(!done) return false;
}
return true;
}
///
/// Adds some ACL entries for a subject.
///
/// The subject.
/// The provider.
/// The directory.
/// The granted actions.
/// The denies actions.
/// true if the operation succeeded, false otherwise.
private bool AddAclEntriesForDirectory(string subject, IFilesStorageProviderV30 provider, string directory, string[] grants, string[] denials) {
bool isGroup = subject.StartsWith("G.");
subject = subject.Substring(2);
UserGroup group = null;
UserInfo user = null;
if(isGroup) group = Users.FindUserGroup(subject);
else user = Users.FindUser(subject);
foreach(string action in grants) {
bool done = false;
if(isGroup) {
done = AuthWriter.SetPermissionForDirectory(AuthStatus.Grant,
provider, directory, action, group);
}
else {
done = AuthWriter.SetPermissionForDirectory(AuthStatus.Grant,
provider, directory, action, user);
}
if(!done) return false;
}
foreach(string action in denials) {
bool done = false;
if(isGroup) {
done = AuthWriter.SetPermissionForDirectory(AuthStatus.Deny,
provider, directory, action, group);
}
else {
done = AuthWriter.SetPermissionForDirectory(AuthStatus.Deny,
provider, directory, action, user);
}
if(!done) return false;
}
return true;
}
protected void btnSave_Click(object sender, EventArgs e) {
string subject = lstSubjects.SelectedValue;
bool done = false;
switch(CurrentResourceType) {
case AclResources.Namespaces:
// Remove old values, add new ones
done = RemoveAllAclEntriesForNamespace(subject, CurrentResourceName);
if(done) {
done = AddAclEntriesForNamespace(subject, CurrentResourceName,
aclActionsSelector.GrantedActions, aclActionsSelector.DeniedActions);
}
break;
case AclResources.Pages:
// Remove old values, add new ones
done = RemoveAllAclEntriesForPage(subject, CurrentResourceName);
if(done) {
done = AddAclEntriesForPage(subject, CurrentResourceName,
aclActionsSelector.GrantedActions, aclActionsSelector.DeniedActions);
}
break;
case AclResources.Directories:
// Remove old values, add new ones
IFilesStorageProviderV30 prov = Collectors.FilesProviderCollector.GetProvider(CurrentFilesProvider);
done = RemoveAllAclEntriesForDirectory(subject, prov, CurrentResourceName);
if(done) {
done = AddAclEntriesForDirectory(subject, prov, CurrentResourceName,
aclActionsSelector.GrantedActions, aclActionsSelector.DeniedActions);
}
break;
default:
throw new NotSupportedException();
}
if(done) {
PopulateSubjectsList();
}
else {
lblSaveResult.CssClass = "resulterror";
lblSaveResult.Text = Properties.Messages.CouldNotStorePermissions;
}
}
protected void btnRemove_Click(object sender, EventArgs e) {
string subject = lstSubjects.SelectedValue;
bool done = false;
switch(CurrentResourceType) {
case AclResources.Namespaces:
// Remove values
done = RemoveAllAclEntriesForNamespace(subject, CurrentResourceName);
break;
case AclResources.Pages:
// Remove values
done = RemoveAllAclEntriesForPage(subject, CurrentResourceName);
break;
case AclResources.Directories:
// Remove values
done = RemoveAllAclEntriesForDirectory(subject,
Collectors.FilesProviderCollector.GetProvider(CurrentFilesProvider),
CurrentResourceName);
break;
default:
throw new NotSupportedException();
}
if(done) {
PopulateSubjectsList();
}
else {
lblSaveResult.CssClass = "resulterror";
lblSaveResult.Text = Properties.Messages.CouldNotStorePermissions;
}
}
protected void btnSearch_Click(object sender, EventArgs e) {
string subject = txtNewSubject.Text.Trim().ToLowerInvariant();
SubjectInfo[] currentSubjects = GetSubjects();
if(subject.Length > 0) {
// Find all groups and users whose name starts with the specified string
lstFoundSubjects.Items.Clear();
foreach(UserGroup group in Users.GetUserGroups()) {
if(group.Name.ToLowerInvariant().StartsWith(subject) &&
!IsAlreadyPresent(group.Name, SubjectType.Group, currentSubjects)) {
lstFoundSubjects.Items.Add(new ListItem(Properties.Messages.Group + ": " + group.Name, "G." + group.Name));
}
}
foreach(UserInfo user in Users.GetUsers()) {
if(user.Username.ToLowerInvariant().StartsWith(subject) &&
!IsAlreadyPresent(user.Username, SubjectType.User, currentSubjects)) {
lstFoundSubjects.Items.Add(new ListItem(Properties.Messages.User + ": " + user.Username, "U." + user.Username));
}
}
btnAdd.Enabled = lstFoundSubjects.Items.Count > 0;
}
}
///
/// Determines whether a subject is already in a list.
///
/// The subject to test.
/// The type of the subject.
/// The subject list.
/// true if the subject is present in allSubjects, false otherwise.
private bool IsAlreadyPresent(string subject, SubjectType type, SubjectInfo[] allSubjects) {
foreach(SubjectInfo current in allSubjects) {
if(current.Type == type && current.Name == subject) {
return true;
}
}
return false;
}
protected void btnAdd_Click(object sender, EventArgs e) {
// Add the selected subject with full control deny, then select it in the main list
string subject = lstFoundSubjects.SelectedValue.Substring(2);
bool isGroup = lstFoundSubjects.SelectedValue.StartsWith("G.");
bool done = false;
switch(CurrentResourceType) {
case AclResources.Namespaces:
if(isGroup) {
done = AuthWriter.SetPermissionForNamespace(AuthStatus.Deny,
Pages.FindNamespace(CurrentResourceName), Actions.FullControl,
Users.FindUserGroup(subject));
}
else {
done = AuthWriter.SetPermissionForNamespace(AuthStatus.Deny,
Pages.FindNamespace(CurrentResourceName), Actions.FullControl,
Users.FindUser(subject));
}
break;
case AclResources.Pages:
if(isGroup) {
done = AuthWriter.SetPermissionForPage(AuthStatus.Deny,
Pages.FindPage(CurrentResourceName), Actions.FullControl,
Users.FindUserGroup(subject));
}
else {
done = AuthWriter.SetPermissionForPage(AuthStatus.Deny,
Pages.FindPage(CurrentResourceName), Actions.FullControl,
Users.FindUser(subject));
}
break;
case AclResources.Directories:
IFilesStorageProviderV30 prov = Collectors.FilesProviderCollector.GetProvider(CurrentFilesProvider);
if(isGroup) {
done = AuthWriter.SetPermissionForDirectory(AuthStatus.Deny,
prov, CurrentResourceName, Actions.FullControl,
Users.FindUserGroup(subject));
}
else {
done = AuthWriter.SetPermissionForDirectory(AuthStatus.Deny,
prov, CurrentResourceName, Actions.FullControl,
Users.FindUser(subject));
}
break;
default:
throw new NotSupportedException();
}
if(done) {
PopulateSubjectsList();
// Select in main list and display permissions in actions matrix
foreach(ListItem item in lstSubjects.Items) {
if(item.Value == lstFoundSubjects.SelectedValue) {
item.Selected = true;
break;
}
}
DisplaySubjectPermissions(subject, isGroup ? SubjectType.Group : SubjectType.User);
txtNewSubject.Text = "";
lstFoundSubjects.Items.Clear();
btnAdd.Enabled = false;
}
else {
lblAddResult.CssClass = "resulterror";
lblAddResult.Text = Properties.Messages.CouldNotStorePermissions;
}
}
}
}