Skip to content

Commit 02e928b

Browse files
author
gauffininteractive
committed
* started implemented authorization for applications
* updated the schema for invites so that the handling is more straightforward. * Limited cleanup routines to 1000 rows per removal to avoid deadlocks * Minor styling fixes.
1 parent ab59c2a commit 02e928b

File tree

23 files changed

+112
-60
lines changed

23 files changed

+112
-60
lines changed

src/Server/OneTrueError.App/Core/Accounts/Account.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ protected Account()
7070
// ReSharper disable once UnusedAutoPropertyAccessor.Local
7171
public int Id { get; private set; }
7272

73+
/// <summary>
74+
/// IS system administrator
75+
/// </summary>
76+
public bool IsSysAdmin { get; set; }
77+
7378
/// <summary>
7479
/// When last successful login attempt was made.
7580
/// </summary>

src/Server/OneTrueError.App/Core/Accounts/Requests/ActivateAccountHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ public async Task<ActivateAccountReply> ExecuteAsync(ActivateAccount request)
5252
account.Activate();
5353
await _repository.UpdateAsync(account);
5454

55-
var query = new GetApplicationList();
55+
var query = new GetApplicationList {AccountId = account.Id};
5656
var apps = await _queryBus.QueryAsync(query);
5757
var claims =
5858
apps.Select(x => new Claim(OneTrueClaims.Application, x.Id.ToString(), ClaimValueTypes.Integer32))
5959
.ToArray();
6060

6161
if (ClaimsPrincipal.Current.IsAccount(account.Id))
6262
{
63-
var context = new PrincipalFactoryContext(account.Id, account.UserName, new string[0]) {Claims = claims};
63+
var context = new PrincipalFactoryContext(account.Id, account.UserName, new string[0]) { Claims = claims };
6464
var identity = await PrincipalFactory.CreateAsync(context);
6565
identity.AddUpdateCredentialClaim();
6666
Thread.CurrentPrincipal = identity;

src/Server/OneTrueError.App/Core/Applications/QueryHandlers/GetMyApplications.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Griffin.Container;
66
using OneTrueError.Api.Core.Applications;
77
using OneTrueError.Api.Core.Applications.Queries;
8+
using OneTrueError.App.Core.Accounts;
89

910
namespace OneTrueError.App.Core.Applications.QueryHandlers
1011
{
@@ -15,15 +16,18 @@ namespace OneTrueError.App.Core.Applications.QueryHandlers
1516
public class GetApplicationListHandler : IQueryHandler<GetApplicationList, ApplicationListItem[]>
1617
{
1718
private readonly IApplicationRepository _applicationRepository;
19+
private readonly IAccountRepository _accountRepository;
1820

1921
/// <summary>
2022
/// Creates a new instance of <see cref="GetApplicationInfoHandler" />.
2123
/// </summary>
2224
/// <param name="applicationRepository">repos</param>
23-
public GetApplicationListHandler(IApplicationRepository applicationRepository)
25+
public GetApplicationListHandler(IApplicationRepository applicationRepository,
26+
IAccountRepository accountRepository)
2427
{
2528
if (applicationRepository == null) throw new ArgumentNullException("applicationRepository");
2629
_applicationRepository = applicationRepository;
30+
_accountRepository = accountRepository;
2731
}
2832

2933
/// <summary>
@@ -38,10 +42,21 @@ public async Task<ApplicationListItem[]> ExecuteAsync(GetApplicationList query)
3842
if (query == null) throw new ArgumentNullException("query");
3943
ApplicationListItem[] result;
4044

45+
if (query.AccountId > 0)
46+
{
47+
var account = await _accountRepository.GetByIdAsync(query.AccountId);
48+
if (account.IsSysAdmin)
49+
query.AccountId = 0;
50+
}
51+
4152
if (query.AccountId != 0)
42-
result = (await _applicationRepository.GetForUserAsync(query.AccountId))
43-
.Select(x => new ApplicationListItem(x.ApplicationId, x.ApplicationName) {IsAdmin = x.IsAdmin})
44-
.ToArray();
53+
{
54+
var apps = await _applicationRepository.GetForUserAsync(query.AccountId);
55+
result = (
56+
from x in apps
57+
select new ApplicationListItem(x.ApplicationId, x.ApplicationName) {IsAdmin = x.IsAdmin}
58+
).ToArray();
59+
}
4560
else
4661
result = (await _applicationRepository.GetAllAsync())
4762
.Select(x => new ApplicationListItem(x.Id, x.Name))

src/Server/OneTrueError.App/Core/Incidents/Jobs/DeleteEmptyIncidents.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public async Task ExecuteAsync()
3939
using (var cmd = _unitOfWork.CreateDbCommand())
4040
{
4141
cmd.CommandText =
42-
@"DELETE Incidents WHERE Id IN (select Incidents.Id
42+
@"DELETE TOP(1000) Incidents WHERE Id IN (select Incidents.Id
4343
FROM Incidents
4444
LEFT JOIN ErrorReports ON (ErrorReports.IncidentId = Incidents.Id)
4545
WHERE ErrorReports.Id IS NULL) AND IgnoreReports <> 1";

src/Server/OneTrueError.App/Core/Invitations/CommandHandlers/InviteUserHandler.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System.Linq;
2+
using System.Security;
3+
using System.Security.Claims;
24
using System.Threading.Tasks;
35
using DotNetCqs;
46
using Griffin.Container;
@@ -12,6 +14,7 @@
1214
using OneTrueError.App.Core.Applications;
1315
using OneTrueError.App.Core.Users;
1416
using OneTrueError.Infrastructure.Configuration;
17+
using OneTrueError.Infrastructure.Security;
1518

1619
namespace OneTrueError.App.Core.Invitations.CommandHandlers
1720
{
@@ -55,6 +58,13 @@ public InviteUserHandler(IInvitationRepository invitationRepository, IEventBus e
5558
public async Task ExecuteAsync(InviteUser command)
5659
{
5760
var inviter = await _userRepository.GetUserAsync(command.UserId);
61+
if (!ClaimsPrincipal.Current.IsSysAdmin() &&
62+
!ClaimsPrincipal.Current.IsApplicationAdmin(command.ApplicationId))
63+
{
64+
_logger.Warn($"User {command.UserId} attempted to do an invite for an application: {command.ApplicationId}.");
65+
throw new SecurityException("You are not an admin of that application.");
66+
}
67+
5868
var invitedUser = await _userRepository.FindByEmailAsync(command.EmailAddress);
5969
if (invitedUser != null)
6070
{

src/Server/OneTrueError.App/Core/Reports/Jobs/DeleteOldReports.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public async Task ExecuteAsync()
5454
{
5555
using (var cmd = _unitOfWork.CreateDbCommand())
5656
{
57-
var sql = @"DELETE FROM ErrorReports WHERE CreatedAtUtc < @date";
57+
var sql = @"DELETE TOP(1000) FROM ErrorReports WHERE CreatedAtUtc < @date";
5858
cmd.CommandText = sql;
5959
cmd.AddParameter("date", DateTime.UtcNow.AddDays(-RetentionDays));
6060
cmd.CommandTimeout = 90;

src/Server/OneTrueError.Data.Common/Security/OneTrueClaims.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class OneTrueClaims
77
public const string CurrentApplicationId = "http://onetrueerror.com/claims/currentapplicationid";
88
public const string Application = "http://onetrueerror.com/claims/application";
99
public const string ApplicationName = "http://onetrueerror.com/claims/application/name";
10-
public const string ApplicationAdmin = "http://onetrueerror.com/claims/application";
10+
public const string ApplicationAdmin = "http://onetrueerror.com/claims/application/admin";
1111

1212
public const string RoleSysAdmin = "SysAdmin";
1313
public const string RoleUser = "SysAdmin";

src/Server/OneTrueError.SqlServer/Core/Users/ApplicationTeamMemberMapper.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ public class ApplicationTeamMemberMapper : CrudEntityMapper<ApplicationTeamMembe
88
{
99
public ApplicationTeamMemberMapper() : base("ApplicationMembers")
1010
{
11-
Property(x => x.EmailAddress)
12-
.PrimaryKey(false);
11+
Property(x => x.Id)
12+
.PrimaryKey(true);
1313

1414
Property(x => x.AccountId)
15-
.ToColumnValue(x => x == 0 ? (object) DBNull.Value : x)
16-
.ToPropertyValue(x => x is DBNull ? 0 : (int) x);
15+
.ToColumnValue(x => x == 0 ? (object)DBNull.Value : x)
16+
.ToPropertyValue(x => x is DBNull ? 0 : (int)x);
1717

1818
Property(x => x.UserName)
1919
.NotForCrud();
2020

2121
Property(x => x.Roles)
2222
.ToColumnValue(x => string.Join(",", x))
23-
.ToPropertyValue(x => ((string) x).Split(','));
23+
.ToPropertyValue(x => ((string)x).Split(','));
2424
}
2525
}
2626
}

src/Server/OneTrueError.SqlServer/OneTrueError.SqlServer.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@
181181
<ItemGroup>
182182
<EmbeddedResource Include="Schema\Update.v3.sql" />
183183
</ItemGroup>
184+
<ItemGroup>
185+
<EmbeddedResource Include="Schema\Update.v4.sql" />
186+
</ItemGroup>
187+
<ItemGroup>
188+
<EmbeddedResource Include="Schema\Update.v5.sql" />
189+
</ItemGroup>
184190
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
185191
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
186192
Other similar extension points exist, see Microsoft.Common.targets.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--version 1.0 (part A) of OneTrueError
2+
3+
ALTER TABLE Accounts ADD IsSysAdmin bit not null default 0;
4+
alter table ApplicationMembers add Id int identity not null primary key;
5+
ALTER TABLE ApplicationMembers ALTER COLUMN [EmailAddress] nvarchar(255) null;
6+
7+
8+
UPDATE DatabaseSchema SET Version = 4;

0 commit comments

Comments
 (0)