예제 #1
0
        public override void OnAuthorization(AuthorizationContext context)
        {
            Logger.Trace("OnAuthorization");

            if (Permissions == null)
            {
                throw new InvalidOperationException("No permission sets found");
            }

            if (PrincipalProvider == null)
            {
                throw new InvalidOperationException("No principal provider found");
            }

            var user       = PrincipalProvider.GetCurrent();
            var authorized = actions.Any(action => Permissions.CanPerform(user, resourceType, action));

            if (authorized)
            {
                return;
            }

            context.Result = new HttpForbiddenResult();

            Logger.Warn("unauthorized access detected by {0}",
                        user == null ? "Anonymous" : user.Identity.Name);
        }
예제 #2
0
        /// <inheritdoc/>
        protected override async Task <ResultModel> ProtectedHandleAsync(GetByIdQuery request, CancellationToken cancellationToken)
        {
            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            Expression <Func <ResultEntity, bool> > expression = PredicateBuilder.Create <ResultEntity>(e => e.Id == Guid.Parse(request.Id));

            if (!principal.IsInRole(RoleType.Administrator))
            {
                expression = expression.And(e => e.Task.Object.UserId == principal.Identity.Name);
            }

            var entity = await Context.ResultRepository.GetFirstOrDefaultAsync(expression, cancellationToken);

            if (entity == null)
            {
                throw new NotFoundException(nameof(ResultEntity), request.Id);
            }

            return(ResultModel.Create(entity, Serializer));
        }
        /// <inheritdoc/>
        protected override async Task <EventModel> ProtectedHandleAsync(GetByIdQuery request, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            Expression <Func <EventEntity, bool> > expression = PredicateBuilder.Create <EventEntity>(e => e.Id == Guid.Parse(request.Id));

            if (!principal.IsInRole(RoleType.Administrator))
            {
                expression = expression.And(e => e.UserId == principal.Identity.Name);
            }

            var result = Context.EventRepository
                         .GetQuery()
                         .Where(expression)
                         .FirstOrDefault();

            if (result == null)
            {
                throw new NotFoundException(nameof(WebhookEntity), request.Id);
            }

            var model = EventModel.Create(result, Serializer);

            await Task.CompletedTask;

            return(model);
        }
예제 #4
0
        /// <summary>
        ///     Attempts to sign in the specified <paramref name="principal"/>.
        /// </summary>
        /// <param name="principal">The principal to sign in.</param>
        /// <returns>Instance of <see cref="TokenContext"/>.</returns>
        public virtual ValueTask <TokenContext> SignInAsync(ClaimsPrincipal principal)
        {
            if (principal is null)
            {
                throw new ArgumentNullException(nameof(principal));
            }

            var(user, tenant) = PrincipalProvider.GetUserAndTenant <User, Organization>(principal);
            if (user is null || tenant is null)
            {
                throw new AuthenticationException();
            }

            Claim claim = principal.FindFirst(FunderMapsAuthenticationClaimTypes.TenantRole);

            if (claim is null)
            {
                throw new AuthenticationException();
            }

            Logger.LogTrace($"User '{user}' sign in was successful.");

            principal = PrincipalProvider.CreateTenantUserPrincipal(user, tenant,
                                                                    Enum.Parse <OrganizationRole>(claim.Value),
                                                                    JwtBearerDefaults.AuthenticationScheme);
            return(new(TokenProvider.GetTokenContext(principal)));
        }
        /// <summary>
        /// Asynchronously handles the command request.
        /// </summary>
        /// <param name="request">The command request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A task that represents the asynchronous operation.
        /// The task result contains the result of the command request.</returns>
        public async Task <TResponse> Handle(TRequest request, CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                var response = await ProtectedHandleAsync(request, cancellationToken);

                if (SubEventType != SubEventType.None)
                {
                    var principal = PrincipalProvider.GetPrincipal();
                    var auditData = new AuditDataModel()
                    {
                        Entity  = response,
                        Command = request
                    };
                    await Audit.AddDefaultEventAsync(principal, auditData, SubEventType);
                }

                return(response);
            }
            catch (Exception)
            {
                Context.RollBackTransaction();

                throw;
            }
        }
예제 #6
0
        protected override System.Threading.Tasks.Task <HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            AuthenticationHeaderValue authValue = request.Headers.Authorization;

            if (authValue != null && !String.IsNullOrWhiteSpace(authValue.Parameter))
            {
                Credentials parsedCredentials = ParseAuthorizationHeader(authValue.Parameter);
                if (parsedCredentials != null)
                {
                    Thread.CurrentPrincipal = PrincipalProvider
                                              .CreatePrincipal(parsedCredentials.Username, parsedCredentials.Password);

                    request.GetRequestContext().Principal = Thread.CurrentPrincipal;
                }
            }
            return(base.SendAsync(request, cancellationToken)
                   .ContinueWith(task =>
            {
                var response = task.Result;
                if (response.StatusCode == HttpStatusCode.Unauthorized &&
                    !response.Headers.Contains(BasicAuthResponseHeader))
                {
                    response.Headers.Add(BasicAuthResponseHeader
                                         , BasicAuthResponseHeaderValue);
                }
                return response;
            }));
        }
예제 #7
0
        /// <inheritdoc/>
        protected override async Task <PaginationResultModel <EventModel> > ProtectedHandleAsync(GetPaginatedQuery request, CancellationToken cancellationToken)
        {
            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            Expression <Func <EventEntity, bool> > expression = PredicateBuilder.True <EventEntity>();

            if (!principal.IsInRole(RoleType.Administrator))
            {
                expression = expression.And(e => e.UserId == principal.Identity.Name);
            }

            int total = await Context.EventRepository.CountAsync(expression, cancellationToken);

            var query = Context.EventRepository
                        .GetQuery(expression)
                        .OrderByDescending(e => e.CreatedDate)
                        .Skip(request.Page * request.Limit)
                        .Take(request.Limit);

            var entities = await Context.ToListAsync(query, cancellationToken);

            var models = entities.Select(e => EventModel.Create(e, Serializer));

            return(PaginationResultModel <EventModel> .Create(models, request.Page, request.Limit, total));
        }
예제 #8
0
        public override void TestFixtureSetUp()
        {
            var cryptoProvider    = new SHA2CryptoProvider(HashAlgorithm.SHA256);
            var principalProvider = new PrincipalProvider(cryptoProvider);

            this.TokenProvider = new SentinelTokenProvider(cryptoProvider, principalProvider);

            base.TestFixtureSetUp();
        }
예제 #9
0
        /// <inheritdoc/>
        protected override async Task <FileByteResultModel> ProtectedHandleAsync(GetZipQuery request, CancellationToken cancellationToken)
        {
            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            Expression <Func <ResultEntity, bool> > expression = PredicateBuilder.Create <ResultEntity>(e => e.Id == Guid.Parse(request.Id));

            if (!principal.IsInRole(RoleType.Administrator))
            {
                expression = expression.And(e => e.Task.Object.UserId == principal.Identity.Name);
            }

            var entity = await Context.ResultRepository.GetFirstOrDefaultAsync(expression, cancellationToken);

            if (entity == null)
            {
                throw new NotFoundException(nameof(ResultEntity), request.Id);
            }

            if (string.IsNullOrWhiteSpace(entity.BasePath))
            {
                throw new UnexpectedNullException($"The base path of result {request.Id} is null.");
            }

            var fs = fileSystemStrategy.Create(configuration.Options.WorkingDirectory);

            if (fs == null)
            {
                throw new UnexpectedNullException("Filesystem could not be created based on the working directory.");
            }

            var fullBasePath = fs.Path.Combine(configuration.Options.WorkingDirectory, entity.BasePath);
            var items        = fs.Directory.EnumerateFiles(fullBasePath, "*.*", SearchOption.TopDirectoryOnly);

            var archive = writer.Create(CompressionType.None);
            await writer.AddFilesAsync(items, dfp => dfp, en => en.Substring(fullBasePath.Length), archive, cancellationToken);

            var stream = new MemoryStream();

            writer.Write(stream, archive);

            var result = new FileByteResultModel()
            {
                FileContents     = stream.ToArray(),
                ContentType      = "application/zip",
                FileDownloadName = $"{Constants.ApplicationNameShort}_{request.Id}_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.zip"
            };

            return(result);
        }
예제 #10
0
        public override void SetUp()
        {
            var principalProvider = new PrincipalProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512));
            var tokenRepository   = new MemoryTokenRepository();

            this.TokenManager = new TokenManager(
                LogManager.GetLogger(typeof(MemoryTokenManagerTests)),
                principalProvider,
                new SentinelTokenProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512), principalProvider),
                tokenRepository);

            base.SetUp();
        }
예제 #11
0
        /// <summary>
        /// Ensures AD objects (for console mode purposes).
        /// </summary>
        private static void EnsureObjects()
        {
            MessageLog.LogEvent(ResHelper.GetString("Console_LoadingObjectFromAD"));

            if ((ImportProfile.ImportUsersType == ImportType.All) || (ImportProfile.ImportUsersType == ImportType.UpdateSelectedImportNew))
            {
                PrincipalProvider.LoadAllUsers();
            }

            if ((ImportProfile.ImportRolesType == ImportType.All) || (ImportProfile.ImportRolesType == ImportType.UpdateSelectedImportNew))
            {
                PrincipalProvider.LoadAllGroups();
            }
        }
예제 #12
0
        public override void SetUp()
        {
            var principalProvider = new PrincipalProvider(new SHA2CryptoProvider(HashAlgorithm.SHA256));
            var tokenRepository   = new RavenDbTokenRepository(
                new RavenDbTokenRepositoryConfiguration(new EmbeddableDocumentStore()
            {
                RunInMemory = true
            }, LogManager.GetLogger <RavenDbTokenManagerTests>()));

            this.TokenManager = new TokenManager(
                LogManager.GetLogger(typeof(RavenDbTokenManagerTests)),
                principalProvider,
                new SentinelTokenProvider(new SHA2CryptoProvider(HashAlgorithm.SHA256), principalProvider),
                tokenRepository);

            base.SetUp();
        }
        public override void SetUp()
        {
            var connectionStringBuilder = this.instance.CreateConnectionStringBuilder();

            connectionStringBuilder.SetInitialCatalogName(this.databaseName);

            var principalProvider = new PrincipalProvider(new PBKDF2CryptoProvider());
            var tokenRepository   = new SqlServerTokenRepository(connectionStringBuilder.ToString());

            this.TokenManager = new TokenManager(
                LogManager.GetLogger(typeof(SqlServerTokenManagerTests)),
                principalProvider,
                new SentinelTokenProvider(new SHA2CryptoProvider(HashAlgorithm.SHA256), principalProvider),
                tokenRepository);

            base.SetUp();
        }
예제 #14
0
        /// <summary>
        /// Deletes domain objects that exist in CMS and doesn't exist in AD.
        /// </summary>
        /// <param name="usersChanged">Records removed users for CMS event log.</param>
        /// <param name="rolesChanged">Records removed roles for CMS event log.</param>
        private static void DeleteNonExistingObjects(CumulatedChanges usersChanged, CumulatedChanges rolesChanged)
        {
            // Remove CMS (domain) roles that do not exist in AD anymore
            IQueryable <RoleInfo> excessiveRoles = RoleInfo.Provider
                                                   .Get()
                                                   .WhereTrue("RoleIsDomain")
                                                   .WhereNotEquals("RoleGUID", Guid.Empty)
                                                   .WhereGreaterThan("RoleID", 0)
                                                   .Columns("RoleID", "RoleGUID", "RoleName")
                                                   .Where(x => !PrincipalProvider.Exists(x.RoleGUID));

            foreach (var role in excessiveRoles)
            {
                // Delete role
                RoleInfo.Provider.Delete(role);

                // Store deleted role GUID and name for EventLog
                rolesChanged.Add(role.RoleGUID, role.RoleDisplayName, ChangeActionEnum.Deleted);

                // Add message to log
                MessageLog.LogEvent(ResHelper.GetString("Log_DeletingRole", role.RoleDisplayName));
            }

            // Remove CMS (domain) users that do not exist in AD anymore
            IQueryable <UserInfo> excessiveUsers = UserInfo.Provider
                                                   .Get()
                                                   .WhereTrue("UserIsDomain")
                                                   .WhereNotEquals("UserGUID", Guid.Empty)
                                                   .WhereGreaterThan("UserID", 0)
                                                   .Columns("UserID", "UserGUID", "UserName")
                                                   .Where(x => !PrincipalProvider.Exists(x.UserGUID));

            foreach (var user in excessiveUsers)
            {
                // Delete user
                UserInfo.Provider.Delete(user);

                // Store deleted user GUID and name for EventLog
                usersChanged.Add(user.UserGUID, user.UserName, ChangeActionEnum.Deleted);

                // Add message to log
                MessageLog.LogEvent(ResHelper.GetString("Log_DeletingUser", user.UserName));
            }
        }
        public override void SetUp()
        {
            var principalProvider = new PrincipalProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512));
            var tokenRepository   =
                new RedisTokenRepository(
                    new RedisTokenRepositoryConfiguration(
                        ConfigurationManager.AppSettings["RedisHost"],
                        4,
                        "sentinel.oauth.RedisTokenManagerTests",
                        LogManager.GetLogger(typeof(RedisTokenManagerTests))));

            this.TokenManager = new TokenManager(
                LogManager.GetLogger(typeof(RedisTokenManagerTests)),
                principalProvider,
                new SentinelTokenProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512), principalProvider),
                tokenRepository);

            base.SetUp();
        }
예제 #16
0
        /// <summary>
        ///     Attempts to sign in the specified <paramref name="email"/> and <paramref name="password"/> combination.
        /// </summary>
        /// <param name="email">The user email to sign in.</param>
        /// <param name="password">The password to attempt to authenticate.</param>
        /// <returns>Instance of <see cref="TokenContext"/>.</returns>
        public virtual async Task <TokenContext> PasswordSignInAsync(string email, string password)
        {
            if (await UserRepository.GetByEmailAsync(email) is not IUser user)
            {
                throw new AuthenticationException();
            }

            // FUTURE: Single call?
            var organizationId = await OrganizationUserRepository.GetOrganizationByUserIdAsync(user.Id);

            if (await CheckPasswordAsync(user.Id, password))
            {
                if (await UserRepository.GetAccessFailedCount(user.Id) > 10)
                {
                    Logger.LogWarning($"User '{user}' locked out.");

                    throw new AuthenticationException();
                }

                await UserRepository.ResetAccessFailed(user.Id);

                await UserRepository.RegisterAccess(user.Id);

                Logger.LogInformation($"User '{user}' password sign in was successful.");

                Organization organization = await OrganizationRepository.GetByIdAsync(organizationId);

                OrganizationRole organizationRole = await OrganizationUserRepository.GetOrganizationRoleByUserIdAsync(user.Id);

                ClaimsPrincipal principal = PrincipalProvider.CreateTenantUserPrincipal(user, organization,
                                                                                        organizationRole,
                                                                                        JwtBearerDefaults.AuthenticationScheme);
                return(TokenProvider.GetTokenContext(principal));
            }

            Logger.LogWarning($"User '{user}' failed to provide the correct password.");

            await UserRepository.BumpAccessFailed(user.Id);

            throw new AuthenticationException();
        }
        /// <inheritdoc/>
        protected override async Task <ObjectModel> ProtectedHandleAsync(GetByIdQuery request, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            Expression <Func <ObjectEntity, bool> > expression = PredicateBuilder.Create <ObjectEntity>(e => e.Id == Guid.Parse(request.Id));

            if (!principal.IsInRole(RoleType.Administrator))
            {
                expression = expression.And(e => e.UserId == principal.Identity.Name);
            }

            var result = Context.ObjectRepository
                         .GetQuery()
                         .Where(expression)
                         .Select(e => new
            {
                Object  = e,
                Tasks   = e.Tasks.OrderByDescending(e1 => e1.CreatedDate).Take(Constants.DefaultPaginationLimit),
                Results = e.Tasks.OrderByDescending(e1 => e1.CreatedDate).Select(e1 => e1.Result).Take(Constants.DefaultPaginationLimit)
            })
                         .FirstOrDefault();

            if (result == null)
            {
                throw new NotFoundException(nameof(ObjectEntity), request.Id);
            }

            var model = ObjectModel.Create(result.Object, result.Tasks, result.Results, Serializer);

            await Task.CompletedTask;

            return(model);
        }
        public override void TestFixtureSetUp()
        {
            var client = new Client()
            {
                ClientId     = "NUnit",
                ClientSecret = "10000:gW7zpVeugKl8IFu7TcpPskcgQjy4185eAwBk9fFlZK6JNd1I45tLyCYtJrzWzE+kVCUP7lMSY8o808EjUgfavBzYU/ZtWypcdCdCJ0BMfMcf8Mk+XIYQCQLiFpt9Rjrf5mAY86NuveUtd1yBdPjxX5neMXEtquNYhu9I6iyzcN4=:Lk2ZkpmTDkNtO/tsB/GskMppdAX2bXehP+ED4oLis0AAv3Q1VeI8KL0SxIIWdxjKH0NJKZ6qniRFkfZKZRS2hS4SB8oyB34u/jyUlmv+RZGZSt9nJ9FYJn1percd/yFA7sSQOpkGljJ6OTwdthe0Bw0A/8qlKHbO2y2M5BFgYHY=",
                RedirectUri  = "http://localhost",
                Enabled      = true
            };
            var user = new User()
            {
                UserId    = "azzlack",
                Password  = "******",
                FirstName = "Ove",
                LastName  = "Andersen",
                Enabled   = true
            };

            var clientRepository = new Mock <IClientRepository>();

            clientRepository.Setup(x => x.GetClient("NUnit")).ReturnsAsync(client);
            clientRepository.Setup(x => x.GetClients()).ReturnsAsync(new List <IClient>()
            {
                client
            });

            var userRepository = new Mock <IUserRepository>();

            userRepository.Setup(x => x.GetUser("azzlack")).ReturnsAsync(user);
            userRepository.Setup(x => x.GetUsers()).ReturnsAsync(new List <IUser>()
            {
                user
            });

            this.Server = TestServer.Create(
                app =>
            {
                var principalProvider = new PrincipalProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512));
                var tokenProvider     = new SentinelTokenProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512), principalProvider);

                app.UseSentinelAuthorizationServer(
                    new SentinelAuthorizationServerOptions()
                {
                    ClientRepository = clientRepository.Object,
                    UserRepository   = userRepository.Object,
                    TokenProvider    = tokenProvider,
                    IssuerUri        = new Uri("https://sentinel.oauth")
                });

                // Start up web api
                var httpConfig = new HttpConfiguration();
                httpConfig.MapHttpAttributeRoutes();

                // Configure Web API to use only Bearer token authentication.
                httpConfig.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

                httpConfig.EnsureInitialized();

                app.UseWebApi(httpConfig);
            });

            base.TestFixtureSetUp();
        }
        /// <inheritdoc/>
        protected override async Task <TaskModel> ProtectedHandleAsync(CreateTaskCommand request, CancellationToken cancellationToken)
        {
            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            if (request.Command.CommandType != CommandType.ProcessObjectCommand || request.Command.GetType() != typeof(ProcessObjectCommand))
            {
                throw new NotSupportedException("The provided command type is not supported.");
            }

            var command = request.Command as ProcessObjectCommand;

            Guid objectId      = Guid.Parse(command.Id);
            var  objectOwnerId = Context.ObjectRepository.GetQuery(e => e.Id == objectId).Select(e => e.UserId).FirstOrDefault();

            if (!AuthService.IsAuthorized(objectOwnerId))
            {
                throw new ForbiddenException("Not authorized");
            }

            processMutex = new Mutex(false, this.GetMethodName());

            return(await processMutex.Execute(new TimeSpan(0, 0, 2), async() =>
            {
                var activeCount = await Context.TaskRepository.CountAsync(e =>
                                                                          e.ObjectId == objectId &&
                                                                          (e.Status == (int)Domain.Enums.TaskStatus.Created ||
                                                                           e.Status == (int)Domain.Enums.TaskStatus.Queued ||
                                                                           e.Status == (int)Domain.Enums.TaskStatus.Processing));

                if (activeCount > 0)
                {
                    throw new AmiException("The specified object is already actively being processed.");
                }

                var position = await Context.TaskRepository.CountAsync(e =>
                                                                       e.Status == (int)Domain.Enums.TaskStatus.Queued);

                var entity = new TaskEntity()
                {
                    Id = idGenerator.GenerateId(),
                    CreatedDate = DateTime.UtcNow,
                    ModifiedDate = DateTime.UtcNow,
                    QueuedDate = DateTime.UtcNow,
                    Status = (int)Domain.Enums.TaskStatus.Queued,
                    Progress = 0,
                    Position = position,
                    CommandType = (int)CommandType.ProcessObjectCommand,
                    CommandSerialized = serializer.Serialize(command),
                    UserId = principal.Identity.Name,
                    ObjectId = objectId
                };

                Context.TaskRepository.Add(entity);

                await Context.SaveChangesAsync(cancellationToken);

                var result = await mediator.Send(new GetByIdQuery()
                {
                    Id = entity.Id.ToString()
                });
                if (result == null)
                {
                    throw new UnexpectedNullException($"The task '{entity.Id.ToString()}' could not be retrieved after creating it.");
                }

                if (entity.Object != null)
                {
                    await Events.CreateAsync(entity.Object.UserId, EventType.TaskCreated, result, cancellationToken);
                    await Gateway.NotifyGroupsAsync(entity.Object.UserId, EventType.TaskCreated, result, cancellationToken);
                }

                backgroundService.EnqueueTask(result.Id);

                return result;
            }));
        }
예제 #20
0
        /// <inheritdoc/>
        protected override async Task <ObjectModel> ProtectedHandleAsync(CreateObjectCommand request, CancellationToken cancellationToken)
        {
            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            int objectLimit = 0;

            if (principal.IsInRole(RoleType.User))
            {
                objectLimit = apiConfiguration.Options.ObjectLimit;
            }
            else
            {
                objectLimit = apiConfiguration.Options.ObjectLimitAnonymous;
            }

            processMutex = new Mutex(false, this.GetMethodName());

            return(await processMutex.Execute(new TimeSpan(0, 0, 2), async() =>
            {
                if (objectLimit > 0)
                {
                    var count = await Context.ObjectRepository.CountAsync(e => e.UserId == principal.Identity.Name, cancellationToken);
                    if (count >= objectLimit)
                    {
                        throw new AmiException($"The object limit of {objectLimit} has been reached.");
                    }
                }

                string fileExtension = fileSystem.Path.GetExtension(request.OriginalFilename);

                Guid guid = idGenerator.GenerateId();
                string path = fileSystem.Path.Combine("Binary", "Objects", guid.ToString());
                string destFilename = string.Concat(guid.ToString(), fileExtension);
                string destPath = fileSystem.Path.Combine(path, destFilename);

                fileSystem.Directory.CreateDirectory(fileSystem.Path.Combine(appConfiguration.Options.WorkingDirectory, path));
                fileSystem.File.Move(request.SourcePath, fileSystem.Path.Combine(appConfiguration.Options.WorkingDirectory, destPath));

                var entity = new ObjectEntity()
                {
                    Id = guid,
                    CreatedDate = DateTime.UtcNow,
                    ModifiedDate = DateTime.UtcNow,
                    OriginalFilename = request.OriginalFilename,
                    SourcePath = destPath,
                    UserId = principal.Identity.Name
                };

                Context.ObjectRepository.Add(entity);

                await Context.SaveChangesAsync(cancellationToken);

                var result = ObjectModel.Create(entity);

                await Events.CreateAsync(entity.UserId, EventType.ObjectCreated, result, cancellationToken);
                await Gateway.NotifyGroupsAsync(entity.UserId, EventType.ObjectCreated, result, cancellationToken);

                return result;
            }));
        }
예제 #21
0
        private static void ImportWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                BackgroundWorker worker = (BackgroundWorker)sender;

                // Save import profile
                if (ImportProfile.SaveImportProfile && !ImportProfile.UsesConsole)
                {
                    SaveFile(SaveImportProfile);
                }

                // Decide whether to import
                if (!ImportProfile.ImportNow && !ImportProfile.UsesConsole)
                {
                    return;
                }

                using (new CMSActionContext()
                {
                    LogEvents = false, ContinuousIntegrationAllowObjectSerialization = false
                })
                {
                    #region "Initialization"

                    // Import canceled
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    DateTime start = DateTime.Now;

                    // Initialize CMS context
                    CMSInit();

                    if (ImportProfile.UsesConsole)
                    {
                        // Ensure object in case they are not present in import profile
                        EnsureObjects();
                    }

                    if (ImportProfile.ImportUsersOnlyFromSelectedRoles)
                    {
                        // Narrow down imported users according to imported roles
                        ImportProfile.Users.Clear();
                    }

                    // Import canceled
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    // Initialize cumulative changed users and roles storages
                    var rolesChanged = new CumulatedChanges(WellKnownEventLogEventsEnum.RolesCreated, WellKnownEventLogEventsEnum.RolesUpdated, WellKnownEventLogEventsEnum.RolesDeleted);
                    var usersChanged = new CumulatedChanges(WellKnownEventLogEventsEnum.UsersCreated, WellKnownEventLogEventsEnum.UsersUpdated, WellKnownEventLogEventsEnum.UsersDeleted);

                    #endregion

                    // Delete non-existing objects (this also prevents conflicting code names)
                    if (ImportProfile.DeleteNotExistingObjects)
                    {
                        DeleteNonExistingObjects(usersChanged, rolesChanged);
                    }

                    #region "Role import"

                    foreach (var siteInfo in ImportProfile
                             .Sites
                             .Select(site => SiteInfo.Provider.Get(site.Key))
                             .Where(info => info != null))
                    {
                        foreach (Guid groupGuid in ImportProfile.Groups)
                        {
                            // Import canceled
                            if (worker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }

                            // Try to get group
                            IPrincipalObject group = PrincipalProvider.GetPrincipalObject(groupGuid);

                            // If group is still null
                            if (group == null)
                            {
                                MessageLog.LogEvent(ResHelper.GetString("Log_SkippingNonExistingObject"));
                                warnings++;
                                // If deleting of not existing objects is enabled
                                if (ImportProfile.DeleteNotExistingObjects)
                                {
                                    DeleteRole(siteInfo, groupGuid);
                                }
                            }
                            else
                            {
                                // Get role description
                                string roleDescription = String.Empty;
                                if (ImportProfile.ImportRoleDescription && (group.Description != null))
                                {
                                    roleDescription = group.Description;
                                }

                                // Get correct role name format
                                string roleCodeName = group.GetCMSCodeName(true);

                                // Get role display name
                                string roleDisplayName = group.GetCMSDisplayName();

                                // Get safe role name
                                roleCodeName = ValidationHelper.GetSafeRoleName(roleCodeName, siteInfo.SiteName);

                                if (!String.IsNullOrEmpty(roleCodeName))
                                {
                                    // Add message to log
                                    MessageLog.LogEvent(ResHelper.GetString("Log_ImportingRole", roleDisplayName, CMS.Helpers.ResHelper.LocalizeString(siteInfo.DisplayName)));

                                    // Import role
                                    ImportRole(roleCodeName, roleDisplayName, siteInfo.SiteID, roleDescription, groupGuid, ImportProfile.UpdateObjectData, rolesChanged);

                                    if (ImportProfile.ImportUsersOnlyFromSelectedRoles)
                                    {
                                        ImportProfile.Users.AddRange(PrincipalProvider.GetUsersOf(group).Select(u => u.Identifier));
                                    }
                                }
                                else
                                {
                                    // Add message to log
                                    MessageLog.LogEvent(ResHelper.GetString("Log_SkippingEmptyRolename", group.Identifier));
                                    warnings++;
                                }
                            }
                        }
                    }

                    // Log created and updated and removed roles to EventLog
                    rolesChanged.WriteEventsToEventLog();

                    #endregion

                    #region "User import"

                    foreach (var user in ImportProfile
                             .Users
                             .Distinct()
                             .Select(userGuid => PrincipalProvider.GetPrincipalObject(userGuid)))
                    {
                        // Import canceled
                        if (worker.CancellationPending)
                        {
                            e.Cancel = true;
                            return;
                        }

                        if (user == null)
                        {
                            MessageLog.LogEvent(ResHelper.GetString("Log_SkippingNonExistingObject"));
                            continue;
                        }

                        string domainName = user.GetCMSCodeName(true);

                        if (!String.IsNullOrEmpty(domainName))
                        {
                            // Get user info object
                            UserInfo userInfo = (UserInfo.Provider.Get((Guid)user.Identifier) ?? UserInfo.Provider.Get(domainName));
                            bool     newUser  = (userInfo == null);

                            // When is desired to import new users only from selected roles
                            if (newUser && ImportProfile.ImportNewUsersOnlyFromSelectedRoles)
                            {
                                // Skip users that does not belong to one of selected role
                                bool skip = ImportProfile.Groups.Cast <Guid>().All(groupGuid => !user.IsPrincipalInGroup(groupGuid));
                                if (skip)
                                {
                                    MessageLog.LogEvent(ResHelper.GetString("Log_SkippingDoesNotBelongToSelectedRole", domainName));
                                    continue;
                                }
                            }

                            if (ImportProfile.UpdateObjectData || newUser)
                            {
                                if (userInfo == null)
                                {
                                    userInfo = new UserInfo();
                                    // Add message to log
                                    MessageLog.LogEvent(ResHelper.GetString("Log_ImportingUser", domainName));
                                }
                                else
                                {
                                    // Add message to log
                                    MessageLog.LogEvent(ResHelper.GetString("Log_UpdatingUser", domainName));
                                }

                                using (var transaction = new CMSTransactionScope())
                                {
                                    if (newUser)
                                    {
                                        userInfo.UserIsDomain = true;
                                        userInfo.UserGUID     = (Guid)user.Identifier;

                                        // Set privilege level
                                        UserPrivilegeLevelEnum privilegeLevel = ImportProfile.ConfigureAsCMSEditor ? UserPrivilegeLevelEnum.Editor : UserPrivilegeLevelEnum.None;
                                        userInfo.SiteIndependentPrivilegeLevel = privilegeLevel;
                                    }

                                    if (userInfo.UserIsDomain)
                                    {
                                        // Set user's properties
                                        userInfo.UserIsExternal = true;
                                        userInfo.UserName       = domainName;
                                        userInfo.Enabled        = ValidationHelper.GetBoolean(user.Enabled, true);

                                        // Bind properties
                                        foreach (KeyValuePair <string, string> property in ImportProfile.UserProperties)
                                        {
                                            // Get attribute
                                            object attribute = user.GetProperty(property.Value);

                                            if (attribute != null)
                                            {
                                                try
                                                {
                                                    string attrValue;

                                                    // Get string representation of the attribute
                                                    if (attribute is float || attribute is double || attribute is decimal)
                                                    {
                                                        attrValue = String.Format(CultureInfo.InvariantCulture, "{0}", attribute);
                                                    }
                                                    else if (attribute.GetType() == typeof(byte[]))
                                                    {
                                                        attrValue = PrincipalProvider.GetSID(attribute);
                                                    }
                                                    else if (attribute.GetType().BaseType == typeof(MarshalByRefObject))
                                                    {
                                                        attrValue = PrincipalProvider.GetTimeFromInterval(attribute);
                                                    }
                                                    else
                                                    {
                                                        attrValue = attribute.ToString();
                                                    }

                                                    // Set property
                                                    userInfo.SetValue(property.Key, LimitLengthForField(attrValue, property.Key));
                                                }
                                                catch
                                                {
                                                    MessageLog.LogEvent(ResHelper.GetString("Log_ErrorParsingAttr", property.Value));
                                                    warnings++;
                                                }
                                            }
                                            else
                                            {
                                                FormFieldInfo field = UserFormInfo.GetFormField(property.Key);
                                                userInfo.SetValue(property.Key, field.GetPropertyValue(FormFieldPropertyEnum.DefaultValue));
                                            }
                                        }

                                        // Create full name if empty
                                        if (String.IsNullOrEmpty(userInfo.FullName))
                                        {
                                            userInfo.FullName = user.GetCMSDisplayName();
                                        }

                                        // Store user info object and its user-settings
                                        if (userInfo.ChangedColumns().Any())
                                        {
                                            // Store created/updated user for EventLog
                                            // User name is used, because AD accounts does not have to have first and/or given name specified (e.g. Guest, …)
                                            usersChanged.Add(userInfo.UserGUID, userInfo.UserName, newUser ? ChangeActionEnum.Created : ChangeActionEnum.Updated);

                                            UserInfo.Provider.Set(userInfo);
                                        }
                                    }
                                    else
                                    {
                                        MessageLog.LogEvent(ResHelper.GetString("Log_UserIsNotDomain", userInfo.UserName));
                                        warnings++;
                                    }

                                    transaction.Commit();
                                }
                            }
                            else
                            {
                                MessageLog.LogEvent(ResHelper.GetString("Log_SkippingExistingUser", domainName));
                            }

                            // Import canceled
                            if (worker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }

                            // Assign user to sites and roles (for domain users only)
                            if (!userInfo.UserIsDomain)
                            {
                                continue;
                            }


                            #region "Membership (roles) synchronization"

                            if (!newUser && !ImportProfile.UpdateMemberships && !ImportProfile.UpdateMemberships)
                            {
                                // No membership synchronization will be performed
                                continue;
                            }

                            // Initialize collection to cumulate membership changes
                            var memberShipChanges = new CumulatedRolesMembership();

                            // Load all user roles from DB
                            var userRoles = new HashSet <RoleInfo>(newUser
                                ? Enumerable.Empty <RoleInfo>() // non-existing user cannot be present in a single role (in DB)
                                : RoleInfo.Provider
                                                                   .Get()
                                                                   .WhereIn("RoleID",
                                                                            UserRoleInfo.Provider
                                                                            .Get()
                                                                            .WhereEquals("UserID", userInfo.UserID)
                                                                            .Column("RoleID"))
                                                                   .Columns("RoleID", "RoleGUID", "RoleDisplayName", "RoleIsDomain"));

                            // Store user's roles before membership synchronization
                            memberShipChanges.SetRolesBefore(userRoles);
                            foreach (KeyValuePair <string, List <Guid> > site in ImportProfile.Sites)
                            {
                                // Get site info object
                                var siteInfo = SiteInfo.Provider.Get(site.Key);
                                if (siteInfo != null)
                                {
                                    try
                                    {
                                        // Add user to this site
                                        UserSiteInfo.Provider.Add(userInfo.UserID, siteInfo.SiteID);
                                    }
                                    catch (Exception ex)
                                    {
                                        MessageLog.LogEvent(ResHelper.GetString("Log_GeneralWarning", ex.Message));
                                        warnings++;
                                    }

                                    // Assign user to roles already existing in CMS
                                    if (newUser || ImportProfile.UpdateMemberships)
                                    {
                                        SetMemberships(user, userInfo, siteInfo, userRoles, site);
                                    }

                                    // Remove user from roles they is member no more
                                    if (!newUser && ImportProfile.UpdateMemberships)
                                    {
                                        RemoveExcessiveMemberships(user, userInfo, userRoles);
                                    }
                                }
                                else
                                {
                                    MessageLog.LogEvent(ResHelper.GetString("Log_SiteNotExist", site.Key));
                                    warnings++;
                                }
                            }

                            // Store user's roles after membership synchronization
                            memberShipChanges.SetRolesAfter(userRoles);

                            // Log created and removed memberships to EventLog
                            memberShipChanges.WriteEventsToEventLog(userInfo.UserName);

                            #endregion
                        }
                        else
                        {
                            // Add message to log
                            MessageLog.LogEvent(ResHelper.GetString("Log_SkippingEmptyUsername", user.Identifier));
                            warnings++;
                        }
                    }

                    // Log created and updated and deleted users to EventLog
                    usersChanged.WriteEventsToEventLog();

                    #endregion

                    // Import canceled
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    TimeSpan duration = DateTime.Now - start;

                    if (!worker.CancellationPending)
                    {
                        // Add message to log
                        MessageLog.LogEvent(warnings == 0
                            ? ResHelper.GetString("Log_ImportComplete", duration.Hours, duration.Minutes, duration.Seconds)
                            : ResHelper.GetString("Log_ImportCompleteWithWarnings", warnings, duration.Hours, duration.Minutes, duration.Seconds));
                    }
                }
            }
            catch (Exception ex)
            {
                MessageLog.LogError(ResHelper.GetString("Error_General"), ex);
            }
        }
        public override void TestFixtureSetUp()
        {
            base.TestFixtureSetUp();

            var client = new Client()
            {
                ClientId     = "NUnit",
                ClientSecret = this.PasswordCryptoProvider.CreateHash("PFJTQUtleVZhbHVlPjxNb2R1bHVzPnFKMEtXaXZWSjUxUWtKWGdIU1hidkxOTEJsa09rOE9uSWtvRTljU1FrRzhOZm5VYXBrWHpkTlEvb3FLZE9BSWxYK1hFMnNwN0xFcS9KRnJMaDRNblhRPT08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjxQPnljRXBJUDJseG1oa0hRMGRrKzRBVk1lZDhWRUFFVHN5TXgvL3NaNS9TbFU9PC9QPjxRPjFmTEVGWU1JMk1TMUJQbzYwcnYyQmhkYWNBaTI2d2Z0V1N2OVl0aUdnT2s9PC9RPjxEUD5uZ0dYTW0wejdXVklNckJZMzhmZm5vWVBIalR2dG84RHk2SmQ0RDlmTlZrPTwvRFA+PERRPk5FZEQzclhNSFp2RFY5b0ZNYVU0TXJqV0luWWVyRU9kbmFLQUlmMGlzTEU9PC9EUT48SW52ZXJzZVE+ZGQzNVh6T0RvUlZQaXQxb2REL0lKRHpXdUtYMXZrb2NjcXQ4REZGVTlwVT08L0ludmVyc2VRPjxEPkFBcC80VW1oSmFJcm9DcWJ5eXdRbDViY0xFMXNSSkwxek50dllkdGxNTCsxWVFRdWx6YzVPRkh1WUcxQW56OE8vbXU2MXNDN0dNVm04ZTVqSUp6SldRPT08L0Q+PC9SU0FLZXlWYWx1ZT4="),
                //ClientSecret = "10000:gW7zpVeugKl8IFu7TcpPskcgQjy4185eAwBk9fFlZK6JNd1I45tLyCYtJrzWzE+kVCUP7lMSY8o808EjUgfavBzYU/ZtWypcdCdCJ0BMfMcf8Mk+XIYQCQLiFpt9Rjrf5mAY86NuveUtd1yBdPjxX5neMXEtquNYhu9I6iyzcN4=:Lk2ZkpmTDkNtO/tsB/GskMppdAX2bXehP+ED4oLis0AAv3Q1VeI8KL0SxIIWdxjKH0NJKZ6qniRFkfZKZRS2hS4SB8oyB34u/jyUlmv+RZGZSt9nJ9FYJn1percd/yFA7sSQOpkGljJ6OTwdthe0Bw0A/8qlKHbO2y2M5BFgYHY=",
                PublicKey   = "PFJTQUtleVZhbHVlPjxNb2R1bHVzPnFKMEtXaXZWSjUxUWtKWGdIU1hidkxOTEJsa09rOE9uSWtvRTljU1FrRzhOZm5VYXBrWHpkTlEvb3FLZE9BSWxYK1hFMnNwN0xFcS9KRnJMaDRNblhRPT08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFsdWU+",
                RedirectUri = "http://localhost",
                Enabled     = true
            };
            var user = new User()
            {
                UserId   = "azzlack",
                Password = this.PasswordCryptoProvider.CreateHash("aabbccddee"),
                //Password = "******",
                FirstName = "Ove",
                LastName  = "Andersen",
                Enabled   = true
            };
            var userApiKeys = new List <IUserApiKey>()
            {
                new UserApiKey()
                {
                    UserId = "azzlack", ApiKey = "PFJTQUtleVZhbHVlPjxNb2R1bHVzPnlidFpyM0pWS0p1L2hlUFMrV0Zla1kyYmRYVDlJMU1MeHZheTlIMW9IenRwRmI4QzJtQmUzY1EzVDhjUzE0ajJ4bk9lRkt2YVZ4Ukw5S2ozd0tOL1B3PT08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFsdWU+"
                }
            };

            var clientRepository = new Mock <IClientRepository>();

            clientRepository.Setup(x => x.GetClient("NUnit")).ReturnsAsync(client);
            clientRepository.Setup(x => x.GetClients()).ReturnsAsync(new List <IClient>()
            {
                client
            });

            var userRepository = new Mock <IUserRepository>();

            userRepository.Setup(x => x.GetUser("azzlack")).ReturnsAsync(user);
            userRepository.Setup(x => x.GetUsers()).ReturnsAsync(new List <IUser>()
            {
                user
            });

            var userApiKeyRepository = new Mock <IUserApiKeyRepository>();

            userApiKeyRepository.Setup(x => x.GetForUser("azzlack")).ReturnsAsync(userApiKeys);

            this.Server = TestServer.Create(
                app =>
            {
                var principalProvider = new PrincipalProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512));
                var tokenProvider     = new SentinelTokenProvider(new SHA2CryptoProvider(HashAlgorithm.SHA512), principalProvider);

                app.UseSentinelAuthorizationServer(
                    new SentinelAuthorizationServerOptions()
                {
                    RequireSecureConnection       = false,
                    EnableBasicAuthentication     = true,
                    EnableSignatureAuthentication = true,
                    ClientRepository     = clientRepository.Object,
                    UserRepository       = userRepository.Object,
                    UserApiKeyRepository = userApiKeyRepository.Object,
                    TokenProvider        = tokenProvider,
                    IssuerUri            = new Uri("https://sentinel.oauth")
                });

                // Start up web api
                var httpConfig = new HttpConfiguration();
                httpConfig.MapHttpAttributeRoutes();

                // Configure Web API to use only Bearer token authentication.
                httpConfig.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

                httpConfig.EnsureInitialized();

                app.UseWebApi(httpConfig);
            });
        }
        /// <inheritdoc/>
        protected override async Task <WebhookModel> ProtectedHandleAsync(CreateWebhookCommand request, CancellationToken cancellationToken)
        {
            var principal = PrincipalProvider.GetPrincipal();

            if (principal == null)
            {
                throw new ForbiddenException("Not authenticated");
            }

            int webhookLimit;

            if (principal.IsInRole(RoleType.Administrator))
            {
                webhookLimit = 0;
            }
            else
            {
                webhookLimit = apiConfiguration.Options.WebhookLimit;
            }

            processMutex = new Mutex(false, this.GetMethodName());

            return(await processMutex.Execute(new TimeSpan(0, 0, 2), async() =>
            {
                if (webhookLimit > 0)
                {
                    var count = await Context.WebhookRepository.CountAsync(
                        e => e.UserId == principal.Identity.Name, cancellationToken);
                    if (count >= webhookLimit)
                    {
                        throw new AmiException($"The webhook limit of {webhookLimit} has been reached.");
                    }
                }

                Guid guid = idGenerator.GenerateId();

                string enabledEvents = request.EnabledEvents.Contains(constants.WildcardCharacter) ?
                                       constants.WildcardCharacter.Embed(constants.ValueSeparator) :
                                       request.EnabledEvents.ToArray().ToString(",", constants.ValueSeparator);

                var entity = new WebhookEntity()
                {
                    Id = guid,
                    CreatedDate = DateTime.UtcNow,
                    ModifiedDate = DateTime.UtcNow,
                    Url = request.Url,
                    ApiVersion = request.ApiVersion,
                    Secret = request.Secret,
                    EnabledEvents = enabledEvents,
                    UserId = principal.Identity.Name
                };

                Context.WebhookRepository.Add(entity);

                await Context.SaveChangesAsync(cancellationToken);

                var result = WebhookModel.Create(entity, constants);

                return result;
            }));
        }