예제 #1
0
        public IApiRepositoryConfig RegisterRepository <TEntity, TMappedEntity, TRepository>()
            where TEntity : class, IEntity
            where TMappedEntity : class
            where TRepository : IRepository
        {
            var fullType = typeof(ApiMappedRepository <TEntity, TMappedEntity>);
            var alias    = AliasHelper.GetRepositoryAlias(fullType);

            if (Repositories.Any(x => x.Alias == alias))
            {
                throw new NotUniqueException(nameof(TRepository));
            }

            var config = new ApiRepositoryConfig
            {
                Alias             = alias,
                EntityType        = typeof(TEntity),
                DatabaseType      = typeof(TMappedEntity),
                RepositoryType    = typeof(TRepository),
                ApiRepositoryType = fullType
            };

            Repositories.Add(config);
            return(config);
        }
예제 #2
0
        private async Task <HttpResponseMessage> DoRequestAsync(HttpRequestMessage request)
        {
            var entityType = typeof(TEntity).FullName;
            var repoType   = typeof(TCorrespondingRepository).FullName;

            var alias = AliasHelper.GetRepositoryAlias(typeof(ApiRepository <TEntity, TCorrespondingRepository>));

            var httpClient = _httpClientFactory.CreateClient(alias);

            if (httpClient.BaseAddress == default)
            {
                throw new InvalidOperationException($"Please configure an HttpClient for the repository '{alias}' using " +
                                                    $".{nameof(RapidCMSMiddleware.AddRapidCMSApiRepository)}([..]) and configure its BaseAddress correctly.");
            }

            var response = await httpClient.SendAsync(request);

            return(response.StatusCode switch
            {
                HttpStatusCode.OK => response,
                HttpStatusCode.Unauthorized => throw new UnauthorizedAccessException(),
                HttpStatusCode.Forbidden => throw new UnauthorizedAccessException(),
                HttpStatusCode.NotFound => throw new NotFoundException($"{request.RequestUri} not found."),

                _ => throw new InvalidOperationException()
            });
예제 #3
0
        public void Update(ProductViewModel productViewModel)
        {
            var productTags = new List <ProductTag>();

            if (!string.IsNullOrEmpty(productViewModel.Tags))
            {
                var tags = productViewModel.Tags.Split(',');
                foreach (var t in tags)
                {
                    var tagId = AliasHelper.ConvertToAlias(t);
                    if (!_tagRepository.FindAll(x => x.Id == tagId).Any())
                    {
                        var tag = new Tag {
                            Id = tagId, Name = t
                        };
                        _tagRepository.Add(tag);
                    }
                    _productTagRepository.RemoveMultiple(_productTagRepository.FindAll(x => x.Id == productViewModel.Id).ToList());
                    var productTag = new ProductTag
                    {
                        TagId = tagId
                    };
                    productTags.Add(productTag);
                }
            }

            var product = _mapper.Map <ProductViewModel, Product>(productViewModel);

            foreach (var productTag in productTags)
            {
                product.ProductTags.Add(productTag);
            }
            _productRepository.Update(product);
        }
예제 #4
0
 public async Task <IActionResult> SaveEntity(ProductViewModel productViewModel)
 {
     if (!ModelState.IsValid)
     {
         var allErrors = ModelState.Values.SelectMany(v => v.Errors);
         return(new BadRequestObjectResult(allErrors));
     }
     else
     {
         productViewModel.SeoAlias = AliasHelper.ConvertToAlias(productViewModel.Name);
         if (productViewModel.Id == 0)
         {
             var notificationId = Guid.NewGuid().ToString();
             var announcement   = new AnnouncementViewModel
             {
                 Title       = User.GetSpecificClaim("FullName"),
                 DateCreated = DateTime.Now,
                 Content     = $"Product {productViewModel.Name} has been created",
                 Id          = notificationId,
                 UserId      = User.GetUserId(),
                 Image       = User.GetSpecificClaim("Avatar"),
                 Status      = Status.Active
             };
             var announcementUsers = new List <AnnouncementUserViewModel>()
             {
                 new AnnouncementUserViewModel()
                 {
                     AnnouncementId = notificationId, HasRead = false, UserId = User.GetUserId()
                 }
             };
             _productService.Add(announcement, announcementUsers, productViewModel);
             await _hubContext.Clients.All.SendAsync("ReceiveMessage", announcement);
         }
         else
         {
             var notificationId = Guid.NewGuid().ToString();
             var announcement   = new AnnouncementViewModel
             {
                 Title       = User.GetSpecificClaim("FullName"),
                 DateCreated = DateTime.Now,
                 Content     = $"Product {productViewModel.Name} has been updated",
                 Id          = notificationId,
                 UserId      = User.GetUserId(),
                 Image       = User.GetSpecificClaim("Avatar"),
                 Status      = Status.Active
             };
             var announcementUsers = new List <AnnouncementUserViewModel>()
             {
                 new AnnouncementUserViewModel()
                 {
                     AnnouncementId = notificationId, HasRead = false, UserId = User.GetUserId()
                 }
             };
             _productService.Update(announcement, announcementUsers, productViewModel);
             await _hubContext.Clients.All.SendAsync("ReceiveMessage", announcement);
         }
         _productService.Save();
         return(new OkObjectResult(productViewModel));
     }
 }
예제 #5
0
        public ProductViewModel Add(ProductViewModel productViewModel)
        {
            var productTags = new List <ProductTag>();

            if (!string.IsNullOrEmpty(productViewModel.Tags))
            {
                var tags = productViewModel.Tags.Split(',');
                foreach (var t in tags)
                {
                    var tagId = AliasHelper.ConvertToAlias(t.Trim());
                    if (!_tagRepository.FindAll(x => x.Id == tagId).Any())
                    {
                        _tagRepository.Add(new Tag {
                            Id = tagId, Name = t
                        });
                    }
                    productTags.Add(new ProductTag {
                        TagId = tagId
                    });
                }
                var product = _mapper.Map <ProductViewModel, Product>(productViewModel);
                foreach (var productTag in productTags)
                {
                    product.ProductTags.Add(productTag);
                }
                _productRepository.Add(product);
            }
            return(productViewModel);
        }
        /// <summary>
        /// Adds a plain HttpClient for the given file upload handler which is hosted at the given baseAddress.
        /// The ApiFileHandler uses this HttpClient to communicate to the server.
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="services"></param>
        /// <param name="baseAddress">Base address of the api, for example: https://example.com</param>
        /// <param name="collectionAlias"></param>
        /// <returns></returns>
        public static IHttpClientBuilder AddRapidCMSFileUploadApiHttpClient <THandler>(this IServiceCollection services, Uri baseUri)
            where THandler : IFileUploadHandler
        {
            var alias = AliasHelper.GetFileUploaderAlias(typeof(THandler));

            return(services.AddHttpClient <ApiFileUploadHandler <THandler> >(alias)
                   .ConfigureHttpClient(x => x.BaseAddress = new Uri(baseUri, $"api/_rapidcms/{alias}/")));
        }
예제 #7
0
        public EntityModelJsonConverter()
        {
            var derivedTypes = typeof(TEntity).Assembly
                .GetTypes()
                .Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(TEntity)));

            _typeDictionary = derivedTypes.Append(typeof(TEntity)).ToDictionary(x => AliasHelper.GetEntityVariantAlias(x));
        }
        public ApiMappedRepository(IHttpClientFactory httpClientFactory)
        {
            var jsonSerializerSettings = new JsonSerializerSettings();

            jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter <TEntity>());
            var repositoryAlias = AliasHelper.GetRepositoryAlias(typeof(ApiMappedRepository <TEntity, TDatabaseEntity>));

            _apiRepositoryHelper = new ApiRepositoryHelper(httpClientFactory, jsonSerializerSettings, repositoryAlias);
        }
예제 #9
0
        public ApiRepository(IHttpClientFactory httpClientFactory, IMemoryCache memoryCache)
        {
            var jsonSerializerSettings = new JsonSerializerSettings();

            jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter <TEntity>());
            var repositoryAlias = AliasHelper.GetRepositoryAlias(typeof(ApiRepository <TEntity, TCorrespondingRepository>));

            _apiRepositoryHelper = new ApiRepositoryHelper(memoryCache, httpClientFactory, jsonSerializerSettings, repositoryAlias);
        }
 public static NavigationRequest NavigateToCreateNewEntity(string collectionAlias, IParent?parent, Type?entityVariant = null)
 {
     return(new NavigationRequest(collectionAlias)
     {
         ParentPath = parent?.GetParentPath(),
         IsEdit = true,
         IsNew = true,
         VariantAlias = entityVariant == null ? null : AliasHelper.GetEntityVariantAlias(entityVariant)
     });
 }
예제 #11
0
        public IApiConfig RegisterFileUploadHandler <THandler>() where THandler : IFileUploadHandler
        {
            FileUploadHandlers.Add(new FileUploadHandlerConfig
            {
                Alias       = AliasHelper.GetFileUploaderAlias(typeof(THandler)),
                HandlerType = typeof(THandler)
            });

            return(this);
        }
        public CmsRepositoryTypeResolver(ICmsConfig cmsConfig, IServiceProvider serviceProvider)
        {
            using var repositoryResolvingScope = serviceProvider.CreateScope();

            var types = cmsConfig.RepositoryTypes.Distinct();

            _repositoryTypes = types.ToDictionary(
                type => AliasHelper.GetRepositoryAlias(repositoryResolvingScope.ServiceProvider.GetRequiredService(type).GetType()));

            _originallyRegisterdRepositoriesToAlias = _repositoryTypes.ToDictionary(x => x.Value, x => x.Key);
        }
        /// <summary>
        /// Adds the repository as scoped service and adds a plain HttpClient for the given repository.
        /// </summary>
        /// <typeparam name="TIRepository"></typeparam>
        /// <typeparam name="TRepository"></typeparam>
        /// <param name="services"></param>
        /// <param name="baseUri"></param>
        /// <returns></returns>
        public static IHttpClientBuilder AddRapidCMSApiRepository <TIRepository, TRepository>(this IServiceCollection services, Uri baseUri)
            where TIRepository : class
            where TRepository : class, TIRepository
        {
            var alias = AliasHelper.GetRepositoryAlias(typeof(TRepository));

            services.AddScoped <TIRepository, TRepository>();

            return(services.AddHttpClient(alias)
                   .ConfigureHttpClient(x => x.BaseAddress = new Uri(baseUri, $"api/_rapidcms/{alias}/")));
        }
예제 #14
0
        private static void AddServicesRequiringRepositories(IServiceCollection services, CmsConfig rootConfig)
        {
            var repositoryTypeDictionary        = new Dictionary <string, Type>();
            var reverseRepositoryTypeDictionary = new Dictionary <Type, string>();
            var collectionAliasDictionary       = new Dictionary <string, List <string> >();

            foreach (var collection in rootConfig.CollectionsAndPages.OfType <ICollectionConfig>())
            {
                ProcessCollection(collection);
            }

            services.AddSingleton <IRepositoryTypeResolver>(new CmsRepositoryTypeResolver(repositoryTypeDictionary, reverseRepositoryTypeDictionary));
            services.AddSingleton <ICollectionAliasResolver>(new CollectionAliasResolver(collectionAliasDictionary));

            void ProcessCollection(ICollectionConfig collection)
            {
                foreach (var repository in collection.RepositoryTypes)
                {
                    var descriptor = services.FirstOrDefault(x => x.ServiceType == repository);
                    if (descriptor == null)
                    {
                        continue;
                    }

                    var implementationType = descriptor.ImplementationType;
                    if (implementationType == null)
                    {
                        continue;
                    }

                    var repositoryAlias = AliasHelper.GetRepositoryAlias(implementationType);

                    repositoryTypeDictionary[repositoryAlias]   = repository;
                    reverseRepositoryTypeDictionary[repository] = repositoryAlias;
                    if (implementationType != repository)
                    {
                        reverseRepositoryTypeDictionary[implementationType] = repositoryAlias;
                    }

                    if (!collectionAliasDictionary.ContainsKey(repositoryAlias))
                    {
                        collectionAliasDictionary.Add(repositoryAlias, new List <string>());
                    }
                    collectionAliasDictionary[repositoryAlias].Add(collection.Alias);
                }

                foreach (var subCollection in collection.CollectionsAndPages.OfType <ICollectionConfig>().Where(x => x is not ReferencedCollectionConfig))
                {
                    ProcessCollection(subCollection);
                }
            }
        }
예제 #15
0
        private static void AddServicesRequiringRepositories(IServiceCollection services, CmsConfig rootConfig)
        {
            var repositoryTypeDictionary        = new Dictionary <string, Type>();
            var reverseRepositoryTypeDictionary = new Dictionary <Type, string>();
            var collectionAliasDictionary       = new Dictionary <string, List <string> >();

            foreach (var collection in rootConfig.CollectionsAndPages.OfType <ICollectionConfig>())
            {
                ProcessCollection(collection);
            }

            services.AddSingleton <IRepositoryTypeResolver>(new CmsRepositoryTypeResolver(repositoryTypeDictionary, reverseRepositoryTypeDictionary));
            services.AddSingleton <ICollectionAliasResolver>(new CollectionAliasResolver(collectionAliasDictionary));

            void ProcessCollection(ICollectionConfig collection)
            {
                var descriptor = services.FirstOrDefault(x => x.ServiceType == collection.RepositoryType);

                if (descriptor == null)
                {
                    throw new InvalidOperationException($"Could not find service descriptor for {collection.RepositoryType}. Please add it to the service collection.");
                }

                var implementationType = descriptor.ImplementationType;

                if (implementationType == null)
                {
                    throw new InvalidOperationException($"Could not find implementation type for {collection.RepositoryType}. Please add it as type to the service collection.");
                }

                var repositoryAlias = AliasHelper.GetRepositoryAlias(implementationType);

                repositoryTypeDictionary[repositoryAlias] = collection.RepositoryType;
                reverseRepositoryTypeDictionary[collection.RepositoryType] = repositoryAlias;
                if (implementationType != collection.RepositoryType)
                {
                    reverseRepositoryTypeDictionary[implementationType] = repositoryAlias;
                }


                if (!collectionAliasDictionary.ContainsKey(repositoryAlias))
                {
                    collectionAliasDictionary.Add(repositoryAlias, new List <string>());
                }
                collectionAliasDictionary[repositoryAlias].Add(collection.Alias);

                foreach (var subCollection in collection.CollectionsAndPages.OfType <ICollectionConfig>().Where(x => !x.Recursive))
                {
                    ProcessCollection(subCollection);
                }
            }
        }
예제 #16
0
        public static EntityModel <T> Create <T>(T entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            return(new EntityModel <T>
            {
                Entity = entity,
                VariantAlias = AliasHelper.GetEntityVariantAlias(entity.GetType())
            });
        }
예제 #17
0
        public GenericResult Update(AnnouncementViewModel announcementViewModel, List <AnnouncementUserViewModel> announcementUsers, ProductViewModel productViewModel)
        {
            try
            {
                var product = _mapper.Map <ProductViewModel, Product>(productViewModel);
                if (!string.IsNullOrEmpty(productViewModel.Tags))
                {
                    var productTags = new List <ProductTag>();
                    var tags        = productViewModel.Tags.Split(',');
                    foreach (var t in tags)
                    {
                        var tagId = AliasHelper.ConvertToAlias(t.Trim());
                        if (!_tagRepository.FindAll(x => x.Id == tagId).Any())
                        {
                            _tagRepository.Add(new Tag {
                                Id = tagId, Name = t
                            });
                        }

                        _productTagRepository.RemoveMultiple(_productTagRepository.FindAll(x => x.Id == productViewModel.Id)
                                                             .ToList());
                        productTags.Add(new ProductTag {
                            TagId = tagId
                        });
                    }

                    foreach (var productTag in productTags)
                    {
                        product.ProductTags.Add(productTag);
                    }
                }
                _productRepository.Update(product);
                // Real Time
                var announcement = _mapper.Map <AnnouncementViewModel, Announcement>(announcementViewModel);
                _announceRepository.Add(announcement);
                foreach (var announcementUserViewModel in announcementUsers)
                {
                    _announceUserRepository.Add(_mapper.Map <AnnouncementUserViewModel, AnnouncementUser>(announcementUserViewModel));
                }
                return(new GenericResult(true, "Update Successful", "Successful"));
            }
            catch (Exception)
            {
                return(new GenericResult(false, "Update Failed", "Error"));
            }
        }
예제 #18
0
        public EditContextModel(IEditContext <TEntity> editContext)
        {
            EntityModel = ApiBridge.EntityModel.Create(editContext.Entity);
            ParentPath  = editContext.Parent?.GetParentPath()?.ToPathString();

            var container = editContext.GetRelationContainer();

            RelationContainer = new RelationContainerModel
            {
                Relations = container.Relations.Select(relation =>
                {
                    return(new RelationModel
                    {
                        Elements = relation.RelatedElements.Select(el => el.Id),
                        PropertyName = relation.Property.PropertyName,
                        VariantAlias = AliasHelper.GetEntityVariantAlias(relation.RelatedEntityType)
                    });
                })
            };
        }
 public IActionResult SaveEntity(ProductViewModel productViewModel)
 {
     if (!ModelState.IsValid)
     {
         var allErrors = ModelState.Values.SelectMany(v => v.Errors);
         return(new BadRequestObjectResult(allErrors));
     }
     else
     {
         productViewModel.SeoAlias = AliasHelper.ConvertToAlias(productViewModel.Name);
         if (productViewModel.Id == 0)
         {
             _productService.Add(productViewModel);
         }
         else
         {
             _productService.Update(productViewModel);
         }
         _productService.Save();
         return(new OkObjectResult(productViewModel));
     }
 }
예제 #20
0
        public GenericResult Add(ProductViewModel productViewModel)
        {
            try
            {
                var product = _mapper.Map <ProductViewModel, Product>(productViewModel);
                if (!string.IsNullOrEmpty(productViewModel.Tags))
                {
                    var productTags = new List <ProductTag>();
                    var tags        = productViewModel.Tags.Split(',');
                    foreach (var t in tags)
                    {
                        var tagId = AliasHelper.ConvertToAlias(t.Trim());
                        if (!_tagRepository.FindAll(x => x.Id == tagId).Any())
                        {
                            _tagRepository.Add(new Tag {
                                Id = tagId, Name = t
                            });
                        }
                        productTags.Add(new ProductTag {
                            TagId = tagId
                        });
                    }

                    foreach (var productTag in productTags)
                    {
                        product.ProductTags.Add(productTag);
                    }
                }
                _productRepository.Add(product);
                return(new GenericResult(true, "Add Successful", "Successful"));
            }
            catch (Exception)
            {
                return(new GenericResult(false, "Add Failed", "Error"));
            }
        }
예제 #21
0
 public GlobalEntityVariantSetupResolver()
 {
     _types = typeof(IEntity).GetImplementingTypes().ToDictionary(x => AliasHelper.GetEntityVariantAlias(x));
 }
예제 #22
0
 public ApiFileUploadHandler(
     IHttpClientFactory httpClientFactory)
 {
     _httpClientFactory = httpClientFactory;
     _handlerAlias      = AliasHelper.GetFileUploaderAlias(typeof(THandler));
 }
예제 #23
0
        /// <summary>
        /// Use this method to setup the Repository APIs to support RapidCMS WebAssenbly on a separate server.
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        public static IServiceCollection AddRapidCMSApi(this IServiceCollection services, Action <IApiConfig>?config = null)
        {
            if (_routeConvention != null || _controllerFeatureProvider != null)
            {
                throw new InvalidOperationException("Cannot call AddRapidCMSApi twice.");
            }

            var rootConfig = GetRootConfig(config);

            services.AddSingleton <IApiConfig>(rootConfig);

            services.AddHttpContextAccessor();

            if (rootConfig.AllowAnonymousUsage)
            {
                services.AddSingleton <IAuthorizationHandler, AllowAllAuthorizationHandler>();
                services.AddSingleton <AuthenticationStateProvider, AnonymousAuthenticationStateProvider>();
            }
            else
            {
                services.AddSingleton <AuthenticationStateProvider, HttpContextAuthenticationStateProvider>();
            }

            services.AddSingleton <ISetupResolver <IEntityVariantSetup>, GlobalEntityVariantSetupResolver>();

            services.AddTransient <IDataViewResolver, ApiDataViewResolver>();
            services.AddTransient <IRepositoryResolver, RepositoryResolver>();
            services.AddSingleton <IRepositoryTypeResolver, ApiRepositoryTypeResolver>();

            services.AddTransient <IPresentationDispatcher, GetEntityDispatcher>();
            services.AddTransient <IPresentationDispatcher, GetEntitiesDispatcher>();
            services.AddTransient <IPresentationService, PresentationService>();

            services.AddTransient <IInteractionDispatcher, RelateEntityDispatcher>();
            services.AddTransient <IInteractionDispatcher, ReorderEntityDispatcher>();
            services.AddTransient <IInteractionDispatcher, PersistEntityDispatcher>();
            services.AddTransient <IInteractionDispatcher, DeleteEntityDispatcher>();
            services.AddTransient <IInteractionService, InteractionService>();

            services.AddTransient <IAuthService, ApiAuthService>();
            services.AddSingleton <IExceptionService, ExceptionService>();
            // TODO: message service
            services.AddTransient <IParentService, ParentService>();

            services.AddTransient <IEditContextFactory, ApiEditContextWrapperFactory>();

            var controllersToAdd = rootConfig.Repositories.ToDictionary(
                repository =>
            {
                if (repository.DatabaseType == default)
                {
                    return(typeof(ApiRepositoryController <,>)
                           .MakeGenericType(repository.EntityType, repository.RepositoryType)
                           .GetTypeInfo());
                }
                else
                {
                    return(typeof(MappedApiRepositoryController <, ,>)
                           .MakeGenericType(repository.EntityType, repository.DatabaseType, repository.RepositoryType)
                           .GetTypeInfo());
                }
            },
                kv => kv.Alias);

            if (rootConfig.FileUploadHandlers.Any())
            {
                foreach (var handler in rootConfig.FileUploadHandlers)
                {
                    var type  = typeof(ApiFileUploadController <>).MakeGenericType(handler).GetTypeInfo();
                    var alias = AliasHelper.GetFileUploaderAlias(type);

                    controllersToAdd.Add(type, alias);
                }
            }

            _controllerFeatureProvider = new CollectionControllerFeatureProvider(controllersToAdd.Keys);
            _routeConvention           = new CollectionControllerRouteConvention(controllersToAdd);

            return(services);
        }
예제 #24
0
        public IResolvedSetup <IEntityVariantSetup> ResolveSetup(EntityVariantConfig config, ICollectionSetup?collection = default)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }

            if (config == default)
            {
                return(new ResolvedSetup <IEntityVariantSetup>(EntityVariantSetup.Undefined, true));
            }
            else
            {
                return(new ResolvedSetup <IEntityVariantSetup>(
                           new EntityVariantSetup(config.Name, config.Icon, config.Type, AliasHelper.GetEntityVariantAlias(config.Type)),
                           true));
            }
        }
예제 #25
0
 public ParentQueryModel(IParent?parent, Type?variantType, IQuery query) : this(parent, query)
 {
     VariantAlias = variantType == null ? null : AliasHelper.GetEntityVariantAlias(variantType);
 }