Skip to content

Commit e57cd8f

Browse files
committed
initial commit
1 parent c5e8755 commit e57cd8f

136 files changed

Lines changed: 28176 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/packages
2+
bin
3+
obj
4+
/nuget/versions
5+
*.nupkg

AssemblyVersion.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
using System.Reflection;
3+
4+
[assembly: AssemblyCompany("")]
5+
[assembly: AssemblyProduct("ScrewTurn Wiki")]
6+
[assembly: AssemblyCopyright("Copyright © Threeplicate Srl 2006-2011")]
7+
[assembly: AssemblyTrademark("")]
8+
[assembly: AssemblyCulture("")]
9+
10+
// Version information for an assembly consists of the following four values:
11+
//
12+
// Major Version
13+
// Minor Version
14+
// Build Number
15+
// Revision
16+
//
17+
// You can specify all the values or you can default the Revision and Build Numbers
18+
// by using the '*' as shown below:
19+
[assembly: AssemblyVersion("6.0.0.0")]
20+
[assembly: AssemblyFileVersion("6.0.0.0")]
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+

2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace ScrewTurn.Wiki.AclEngine {
7+
8+
/// <summary>
9+
/// Contains arguments for the <see cref="IAclManager.AclChanged" /> event.
10+
/// </summary>
11+
public class AclChangedEventArgs : EventArgs {
12+
13+
private AclEntry[] entries;
14+
private Change change;
15+
16+
/// <summary>
17+
/// Initializes a new instance of the <see cref="T:AclChangedEventArgs" /> class.
18+
/// </summary>
19+
/// <param name="entries">The entries that changed.</param>
20+
/// <param name="change">The change.</param>
21+
/// <exception cref="ArgumentNullException">If <paramref name="entries"/> is <c>null</c>.</exception>
22+
/// <exception cref="ArgumentException">If <paramref name="entries"/> is empty.</exception>
23+
public AclChangedEventArgs(AclEntry[] entries, Change change) {
24+
if(entries == null) throw new ArgumentNullException("entry");
25+
if(entries.Length == 0) throw new ArgumentException("Entries cannot be empty", "entries");
26+
27+
this.entries = entries;
28+
this.change = change;
29+
}
30+
31+
/// <summary>
32+
/// Gets the entries that changed.
33+
/// </summary>
34+
public AclEntry[] Entries {
35+
get { return entries; }
36+
}
37+
38+
/// <summary>
39+
/// Gets the change.
40+
/// </summary>
41+
public Change Change {
42+
get { return change; }
43+
}
44+
45+
}
46+
47+
/// <summary>
48+
/// Lists legal changes for ACL entries.
49+
/// </summary>
50+
public enum Change {
51+
/// <summary>
52+
/// An entry is stored.
53+
/// </summary>
54+
EntryStored,
55+
/// <summary>
56+
/// An entry is deleted.
57+
/// </summary>
58+
EntryDeleted
59+
}
60+
61+
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+

2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace ScrewTurn.Wiki.AclEngine {
7+
8+
/// <summary>
9+
/// Represents an ACL Entry.
10+
/// </summary>
11+
public class AclEntry {
12+
13+
/// <summary>
14+
/// The full control action.
15+
/// </summary>
16+
public const string FullControlAction = "*";
17+
18+
/// <summary>
19+
/// The controlled resource.
20+
/// </summary>
21+
private string resource;
22+
/// <summary>
23+
/// The controlled action on the resource.
24+
/// </summary>
25+
private string action;
26+
/// <summary>
27+
/// The subject whose access to the resource/action is controlled.
28+
/// </summary>
29+
private string subject;
30+
/// <summary>
31+
/// The entry value.
32+
/// </summary>
33+
private Value value;
34+
35+
/// <summary>
36+
/// Initializes a new instance of the <see cref="AclEntry"/> class.
37+
/// </summary>
38+
public AclEntry() { }
39+
40+
/// <summary>
41+
/// Initializes a new instance of the <see cref="T:AclEntry" /> class.
42+
/// </summary>
43+
/// <param name="resource">The controlled resource.</param>
44+
/// <param name="action">The controlled action on the resource.</param>
45+
/// <param name="subject">The subject whose access to the resource/action is controlled.</param>
46+
/// <param name="value">The entry value.</param>
47+
/// <exception cref="ArgumentNullException">If <paramref name="resource"/>, <paramref name="action"/> or <paramref name="subject"/> are <c>null</c>.</exception>
48+
/// <exception cref="ArgumentException">If <paramref name="resource"/>, <paramref name="action"/> or <paramref name="subject"/> are empty.</exception>
49+
public AclEntry(string resource, string action, string subject, Value value) {
50+
if(resource == null) throw new ArgumentNullException("resource");
51+
if(resource.Length == 0) throw new ArgumentException("Resource cannot be empty", "resource");
52+
if(action == null) throw new ArgumentNullException("action");
53+
if(action.Length == 0) throw new ArgumentException("Action cannot be empty", "action");
54+
if(subject == null) throw new ArgumentNullException("subject");
55+
if(subject.Length == 0) throw new ArgumentException("Subject cannot be empty", "subject");
56+
57+
this.resource = resource;
58+
this.action = action;
59+
this.subject = subject;
60+
this.value = value;
61+
}
62+
63+
/// <summary>
64+
/// Gets the controlled resource.
65+
/// </summary>
66+
public string Resource {
67+
get { return resource; }
68+
set { resource = value; }
69+
}
70+
71+
/// <summary>
72+
/// Gets the controlled action on the resource.
73+
/// </summary>
74+
public string Action {
75+
get { return action; }
76+
set { action = value; }
77+
}
78+
79+
/// <summary>
80+
/// Gets the subject of the entry.
81+
/// </summary>
82+
public string Subject {
83+
get { return subject; }
84+
set { subject = value; }
85+
}
86+
87+
/// <summary>
88+
/// Gets the value of the entry.
89+
/// </summary>
90+
public Value Value {
91+
get { return value; }
92+
set { this.value = value; }
93+
}
94+
95+
/// <summary>
96+
/// Gets a string representation of the current object.
97+
/// </summary>
98+
/// <returns>The string representation.</returns>
99+
public override string ToString() {
100+
return resource + "->" + action + ": " + subject + " (" + value.ToString() + ")";
101+
}
102+
103+
/// <summary>
104+
/// Gets a hash code for the current object.
105+
/// </summary>
106+
/// <returns>The hash code.</returns>
107+
public override int GetHashCode() {
108+
return base.GetHashCode();
109+
}
110+
111+
/// <summary>
112+
/// Determines whether this object equals another (by value).
113+
/// </summary>
114+
/// <param name="obj">The other object.</param>
115+
/// <returns><c>true</c> if this object equals <b>obj</b>, <c>false</c> otherwise.</returns>
116+
public override bool Equals(object obj) {
117+
AclEntry other = obj as AclEntry;
118+
if(other != null) return Equals(other);
119+
else return false;
120+
}
121+
122+
/// <summary>
123+
/// Determines whether this instance equals another (by value).
124+
/// </summary>
125+
/// <param name="other">The other instance.</param>
126+
/// <returns><c>true</c> if this instance equals <b>other</b>, <c>false</c> otherwise.</returns>
127+
public bool Equals(AclEntry other) {
128+
if(object.ReferenceEquals(other, null)) return false;
129+
else return resource == other.Resource &&
130+
action == other.Action && subject == other.Subject;
131+
}
132+
133+
/// <summary>
134+
/// Determines whether two instances of <see cref="T:AclEntry" /> are equal (by value).
135+
/// </summary>
136+
/// <param name="x">The first instance.</param>
137+
/// <param name="y">The second instance.</param>
138+
/// <returns><c>true</c> if <b>x</b> equals <b>y</b>, <c>false</c> otherwise.</returns>
139+
public static bool Equals(AclEntry x, AclEntry y) {
140+
if(object.ReferenceEquals(x, null) && !object.ReferenceEquals(x, null)) return false;
141+
if(!object.ReferenceEquals(x, null) && object.ReferenceEquals(x, null)) return false;
142+
if(object.ReferenceEquals(x, null) && object.ReferenceEquals(x, null)) return true;
143+
return x.Equals(y);
144+
}
145+
146+
}
147+
148+
/// <summary>
149+
/// Lists legal ACL Entry values.
150+
/// </summary>
151+
public enum Value {
152+
/// <summary>
153+
/// Deny the action.
154+
/// </summary>
155+
Deny = 0,
156+
/// <summary>
157+
/// Grant the action.
158+
/// </summary>
159+
Grant = 1
160+
}
161+
162+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+

2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace ScrewTurn.Wiki.AclEngine {
7+
8+
/// <summary>
9+
/// Implements tools for evaluating permissions.
10+
/// </summary>
11+
public static class AclEvaluator {
12+
13+
/// <summary>
14+
/// Decides whether a user, member of some groups, is authorized to perform an action on a resource.
15+
/// </summary>
16+
/// <param name="resource">The resource.</param>
17+
/// <param name="action">The action on the resource.</param>
18+
/// <param name="user">The user, in the form 'U.Name'.</param>
19+
/// <param name="groups">The groups the user is member of, in the form 'G.Name'.</param>
20+
/// <param name="entries">The available ACL entries for the resource.</param>
21+
/// <returns>The positive, negative, or indeterminate result.</returns>
22+
/// <exception cref="ArgumentNullException">If <paramref name="resource"/>, <paramref name="action"/>, <paramref name="user"/>, <paramref name="groups"/> or <paramref name="entries"/> are <c>null</c>.</exception>
23+
/// <exception cref="ArgumentException">If <paramref name="resource"/>, <paramref name="action"/>, <paramref name="user"/> are empty, or if <paramref name="action"/> equals <see cref="AclEntry.FullControlAction"/>.</exception>
24+
public static Authorization AuthorizeAction(string resource, string action, string user, string[] groups, AclEntry[] entries) {
25+
if(resource == null) throw new ArgumentNullException("resource");
26+
if(resource.Length == 0) throw new ArgumentException("Resource cannot be empty", "resource");
27+
if(action == null) throw new ArgumentNullException("action");
28+
if(action.Length == 0) throw new ArgumentException("Action cannot be empty", "action");
29+
if(action == AclEntry.FullControlAction) throw new ArgumentException("Action cannot be the FullControl flag", "action");
30+
if(user == null) throw new ArgumentNullException("user");
31+
if(user.Length == 0) throw new ArgumentException("User cannot be empty", "user");
32+
if(groups == null) throw new ArgumentNullException("groups");
33+
if(entries == null) throw new ArgumentNullException("entries");
34+
35+
// Simple ACL model
36+
// Sort entries so that FullControl ones are at the bottom
37+
// First look for an entry specific for the user
38+
// If not found, look for a group that denies the permission
39+
40+
AclEntry[] sortedEntries = new AclEntry[entries.Length];
41+
Array.Copy(entries, sortedEntries, entries.Length);
42+
43+
Array.Sort(sortedEntries, delegate(AclEntry x, AclEntry y) {
44+
return x.Action.CompareTo(y.Action);
45+
});
46+
Array.Reverse(sortedEntries);
47+
48+
foreach(AclEntry entry in sortedEntries) {
49+
if(entry.Resource == resource && (entry.Action == action || entry.Action == AclEntry.FullControlAction) && entry.Subject == user) {
50+
if(entry.Value == Value.Grant) return Authorization.Granted;
51+
else if(entry.Value == Value.Deny) return Authorization.Denied;
52+
else throw new NotSupportedException("Entry value not supported");
53+
}
54+
}
55+
56+
// For each group, a decision is made
57+
Dictionary<string, bool> groupFullControlGrant = new Dictionary<string, bool>();
58+
Dictionary<string, bool> groupExplicitGrant = new Dictionary<string, bool>();
59+
Dictionary<string, bool> groupFullControlDeny = new Dictionary<string, bool>();
60+
61+
foreach(string group in groups) {
62+
foreach(AclEntry entry in entries) {
63+
64+
if(entry.Resource == resource && entry.Subject == group) {
65+
if(!groupFullControlGrant.ContainsKey(group)) {
66+
groupFullControlGrant.Add(group, false);
67+
groupExplicitGrant.Add(group, false);
68+
groupFullControlDeny.Add(group, false);
69+
}
70+
71+
if(entry.Action == action) {
72+
// Explicit action
73+
if(entry.Value == Value.Grant) {
74+
// An explicit grant only wins if there are no other explicit deny
75+
groupExplicitGrant[group] = true;
76+
}
77+
else if(entry.Value == Value.Deny) {
78+
// An explicit deny wins over all other entries
79+
return Authorization.Denied;
80+
}
81+
}
82+
else if(entry.Action == AclEntry.FullControlAction) {
83+
// Full control, lower priority
84+
if(entry.Value == Value.Deny) {
85+
groupFullControlDeny[group] = true;
86+
}
87+
else if(entry.Value == Value.Grant) {
88+
groupFullControlGrant[group] = true;
89+
}
90+
}
91+
}
92+
}
93+
}
94+
95+
// Any explicit grant found at this step wins, because all explicit deny have been processed previously
96+
bool tentativeGrant = false;
97+
bool tentativeDeny = false;
98+
foreach(string group in groupFullControlGrant.Keys) {
99+
if(groupExplicitGrant[group]) return Authorization.Granted;
100+
101+
if(groupFullControlGrant[group] && !groupFullControlDeny[group]) tentativeGrant = true;
102+
if(!groupFullControlGrant[group] && groupFullControlDeny[group]) tentativeDeny = true;
103+
}
104+
if(tentativeGrant && !tentativeDeny) return Authorization.Granted;
105+
else if(tentativeDeny) return Authorization.Denied;
106+
else return Authorization.Unknown;
107+
}
108+
109+
}
110+
111+
/// <summary>
112+
/// Lists legal authorization values.
113+
/// </summary>
114+
public enum Authorization {
115+
/// <summary>
116+
/// Authorization granted.
117+
/// </summary>
118+
Granted,
119+
/// <summary>
120+
/// Authorization denied.
121+
/// </summary>
122+
Denied,
123+
/// <summary>
124+
/// No information available.
125+
/// </summary>
126+
Unknown
127+
}
128+
129+
}

0 commit comments

Comments
 (0)