/// <summary>
    ///     The main method of the program.
    /// </summary>
    public static void Main()
    {
        AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);

        Console.WriteLine("Setting up the database...");

        var context = new MqttContext(
            new DatabaseConnectionSettings
        {
            Host     = "localhost",
            Database = "mqtt",
            Port     = 5432,
            Username = "******",
            Password = "******"
        });

        Console.WriteLine("Delete database...");
        context.Database.EnsureDeleted();

        Console.WriteLine("Create database...");
        context.Database.EnsureCreated();

        Console.WriteLine("Adding seed data...");
        SeedData(context);

        Console.WriteLine("Press any key to close this window...");
        Console.ReadKey();
    }
Exemple #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserController"/> class.
 /// </summary>
 /// <param name="databaseContext">The database context.</param>
 /// <param name="userManager">The user manager.</param>
 /// <param name="autoMapper">The automapper service.</param>
 // ReSharper disable once StyleCop.SA1650
 public UserController(MqttContext databaseContext, UserManager <User> userManager, IMapper autoMapper)
 {
     this.databaseContext = databaseContext;
     this.userManager     = userManager;
     this.autoMapper      = autoMapper;
     this.passwordHasher  = new PasswordHasher <User>();
 }
Exemple #3
0
        /// <summary>
        /// The main method of the program.
        /// </summary>
        /// <param name="args">Some parameters, currently unused.</param>
        public static void Main(string[] args)
        {
            Console.WriteLine("Setting up the database...");
            var context = new MqttContext(new DatabaseConnectionSettings {
                Host = "localhost", Database = "mqtt", Port = 5432, Username = "******", Password = "******"
            });

            Console.WriteLine("Delete database...");
            context.Database.EnsureDeleted();

            Console.WriteLine("Create database...");
            context.Database.EnsureCreated();

            Console.WriteLine("Adding seed data...");
            SeedData(context);

            Console.WriteLine("Press any key to close this window...");
            Console.ReadKey();
        }
 public ClaimController(MqttContext databaseContext, IMapper autoMapper)
 {
     this.databaseContext = databaseContext;
     this.autoMapper      = autoMapper;
 }
    /// <summary>
    ///     Seeds the database with some data. Use this method to add custom data as needed.
    /// </summary>
    /// <param name="context">The <see cref="MqttContext" /> to use.</param>
    private static void SeedData(MqttContext context)
    {
        var version = new DbVersion {
            Version = "1.0.0.0", VersionName = "Sicario", CreatedAt = DateTimeOffset.Now
        };

        if (context.DbVersions is null)
        {
            return;
        }

        context.DbVersions.Add(version);
        context.SaveChanges();

        var user = new User
        {
            UserName             = "******",
            AccessFailedCount    = 0,
            ConcurrencyStamp     = new Guid().ToString(),
            CreatedAt            = DateTimeOffset.Now,
            Email                = "*****@*****.**",
            EmailConfirmed       = true,
            LockoutEnabled       = false,
            NormalizedEmail      = "*****@*****.**",
            NormalizedUserName   = "******",
            PhoneNumber          = "01234567890",
            SecurityStamp        = new Guid().ToString(),
            TwoFactorEnabled     = false,
            PhoneNumberConfirmed = true,
            ValidateClientId     = true,
            ThrottleUser         = true,
            MonthlyByteLimit     = 10000
        };

        context.Users.Add(user);

        user.PasswordHash = new PasswordHasher <User>().HashPassword(user, "Hans");

        context.SaveChanges();

        context.UserClaims.Add(new UserClaim
        {
            ClaimType  = "SubscriptionBlacklist",
            ClaimValue = JsonConvert.SerializeObject(new List <string> {
                "a", "b/+", "c/#"
            }),
            UserId    = 1,
            CreatedAt = DateTimeOffset.Now
        });

        context.UserClaims.Add(new UserClaim
        {
            ClaimType  = "SubscriptionWhitelist",
            ClaimValue = JsonConvert.SerializeObject(new List <string> {
                "d", "e/+", "f/#"
            }),
            UserId    = 1,
            CreatedAt = DateTimeOffset.Now
        });

        context.UserClaims.Add(new UserClaim
        {
            ClaimType  = "PublishBlacklist",
            ClaimValue = JsonConvert.SerializeObject(new List <string> {
                "a", "b/+", "c/#"
            }),
            UserId    = 1,
            CreatedAt = DateTimeOffset.Now
        });

        context.UserClaims.Add(new UserClaim
        {
            ClaimType  = "PublishWhitelist",
            ClaimValue = JsonConvert.SerializeObject(new List <string> {
                "d", "e/+", "f/#"
            }),
            UserId    = 1,
            CreatedAt = DateTimeOffset.Now
        });

        context.SaveChanges();
    }
        /// <summary>
        ///     Configures the services.
        /// </summary>
        /// <param name="services">The services.</param>
        public void ConfigureServices(IServiceCollection services)
        {
            // Added the custom configuration options
            services.Configure <DatabaseConnectionSettings>(this.Configuration.GetSection("DatabaseConnectionSettings"));
            services.Configure <MqttSettings>(this.Configuration.GetSection("MqttSettings"));

            // Load database connection settings
            var databaseConnection =
                this.Configuration.GetSection("DatabaseConnectionSettings").Get <DatabaseConnectionSettings>()
                ?? new DatabaseConnectionSettings();

            // Load MQTT configuration settings
            var mqttSettings = this.Configuration.GetSection("MqttSettings").Get <MqttSettings>();

            // Configure database context
            databaseContext = new MqttContext(databaseConnection);

            // Added the identity stuff and the database connection
            services.AddDbContext <MqttContext>(options => options.UseNpgsql(databaseConnection.ToConnectionString()));

            services.AddIdentity <User, Role>().AddEntityFrameworkStores <MqttContext>().AddDefaultTokenProviders();

            // Add response compression
            services.AddResponseCompression();

            // Add AutoMapper
            services.AddAutoMapper(typeof(UserClaimsProfile), typeof(UserProfile));

            // Add swagger
            // Add swagger document for the API
            services.AddSwaggerDocument(
                config =>
            {
                var version         = Assembly.GetExecutingAssembly().GetName().Version;
                config.DocumentName = $"NetCoreMQTTExampleIdentityConfig {version}";
                config.PostProcess  = document =>
                {
                    document.Info.Version     = $"{version}";
                    document.Info.Title       = "NetCoreMQTTExampleIdentityConfig";
                    document.Info.Description = "NetCoreMQTTExampleIdentityConfig";
                };
            });

            // Read certificate
            var currentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            var certificate = new X509Certificate2(
                Path.Combine(currentPath, "certificate.pfx"),
                "test",
                X509KeyStorageFlags.Exportable);

            // Add MQTT stuff
            services.AddHostedMqttServer(
                builder => builder

                //// .WithDefaultEndpoint().WithDefaultEndpointPort(1883) // For testing purposes only
                .WithDefaultEndpoint().WithDefaultEndpointPort(1883)     // For testing purposes only
                // .WithoutDefaultEndpoint()
                .WithEncryptedEndpoint().WithEncryptedEndpointPort(mqttSettings.Port)
                .WithEncryptionCertificate(certificate.Export(X509ContentType.Pfx))
                .WithEncryptionSslProtocol(SslProtocols.Tls12).WithConnectionValidator(
                    c =>
            {
                var currentUser = databaseContext.Users.FirstOrDefault(u => u.UserName == c.Username);

                if (currentUser == null)
                {
                    c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                    return;
                }

                if (c.Username != currentUser.UserName)
                {
                    c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                    return;
                }

                var hashingResult = Hasher.VerifyHashedPassword(
                    currentUser,
                    currentUser.PasswordHash,
                    c.Password);

                if (hashingResult == PasswordVerificationResult.Failed)
                {
                    c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                    return;
                }

                if (string.IsNullOrWhiteSpace(currentUser.ClientIdPrefix))
                {
                    if (c.ClientId != currentUser.ClientId)
                    {
                        c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                        return;
                    }

                    c.SessionItems.Add(currentUser.ClientId, currentUser);
                }
                else
                {
                    c.SessionItems.Add(currentUser.ClientIdPrefix, currentUser);
                }

                c.ReasonCode = MqttConnectReasonCode.Success;
            }).WithSubscriptionInterceptor(
                    c =>
            {
                var clientIdPrefix = GetClientIdPrefix(c.ClientId);
                User currentUser;
                bool userFound;

                if (clientIdPrefix == null)
                {
                    userFound   = c.SessionItems.TryGetValue(c.ClientId, out var currentUserObject);
                    currentUser = currentUserObject as User;
                }
                else
                {
                    userFound   = c.SessionItems.TryGetValue(clientIdPrefix, out var currentUserObject);
                    currentUser = currentUserObject as User;
                }

                if (!userFound || currentUser == null)
                {
                    c.AcceptSubscription = false;
                    return;
                }

                var topic = c.TopicFilter.Topic;

                // Get blacklist
                var subscriptionBlackList = databaseContext.UserClaims.FirstOrDefault(
                    uc => uc.UserId == currentUser.Id &&
                    uc.ClaimType == ClaimType.SubscriptionBlacklist.ToString());

                var blacklist =
                    JsonConvert.DeserializeObject <List <string> >(subscriptionBlackList?.ClaimValue)
                    ?? new List <string>();

                // Get whitelist
                var subscriptionWhitelist = databaseContext.UserClaims.FirstOrDefault(
                    uc => uc.UserId == currentUser.Id &&
                    uc.ClaimType == ClaimType.SubscriptionWhitelist.ToString());

                var whitelist =
                    JsonConvert.DeserializeObject <List <string> >(subscriptionWhitelist?.ClaimValue)
                    ?? new List <string>();

                // Check matches
                if (blacklist.Contains(topic))
                {
                    c.AcceptSubscription = false;
                    return;
                }

                if (whitelist.Contains(topic))
                {
                    c.AcceptSubscription = true;
                    return;
                }

                foreach (var forbiddenTopic in blacklist)
                {
                    var doesTopicMatch = TopicChecker.Regex(forbiddenTopic, topic);
                    if (!doesTopicMatch)
                    {
                        continue;
                    }

                    c.AcceptSubscription = false;
                    return;
                }

                foreach (var allowedTopic in whitelist)
                {
                    var doesTopicMatch = TopicChecker.Regex(allowedTopic, topic);
                    if (!doesTopicMatch)
                    {
                        continue;
                    }

                    c.AcceptSubscription = true;
                    return;
                }

                c.AcceptSubscription = false;
            }).WithApplicationMessageInterceptor(
                    c =>
            {
                var clientIdPrefix = GetClientIdPrefix(c.ClientId);
                User currentUser;
                bool userFound;

                if (clientIdPrefix == null)
                {
                    userFound   = c.SessionItems.TryGetValue(c.ClientId, out var currentUserObject);
                    currentUser = currentUserObject as User;
                }
                else
                {
                    userFound   = c.SessionItems.TryGetValue(clientIdPrefix, out var currentUserObject);
                    currentUser = currentUserObject as User;
                }

                if (!userFound || currentUser == null)
                {
                    c.AcceptPublish = false;
                    return;
                }

                var topic = c.ApplicationMessage.Topic;

                // Get blacklist
                var subscriptionBlackList = databaseContext.UserClaims.FirstOrDefault(
                    uc => uc.UserId == currentUser.Id &&
                    uc.ClaimType == ClaimType.PublishBlacklist.ToString());

                var blacklist =
                    JsonConvert.DeserializeObject <List <string> >(subscriptionBlackList?.ClaimValue)
                    ?? new List <string>();

                // Get whitelist
                var subscriptionWhitelist = databaseContext.UserClaims.FirstOrDefault(
                    uc => uc.UserId == currentUser.Id &&
                    uc.ClaimType == ClaimType.PublishWhitelist.ToString());

                var whitelist =
                    JsonConvert.DeserializeObject <List <string> >(subscriptionWhitelist?.ClaimValue)
                    ?? new List <string>();

                // Check matches
                if (blacklist.Contains(topic))
                {
                    c.AcceptPublish = false;
                    return;
                }

                if (whitelist.Contains(topic))
                {
                    c.AcceptPublish = true;
                    return;
                }

                foreach (var forbiddenTopic in blacklist)
                {
                    var doesTopicMatch = TopicChecker.Regex(forbiddenTopic, topic);
                    if (!doesTopicMatch)
                    {
                        continue;
                    }

                    c.AcceptPublish = false;
                    return;
                }

                foreach (var allowedTopic in whitelist)
                {
                    var doesTopicMatch = TopicChecker.Regex(allowedTopic, topic);
                    if (!doesTopicMatch)
                    {
                        continue;
                    }

                    c.AcceptPublish = true;
                    return;
                }

                c.AcceptPublish = false;
            }));

            services.AddMqttConnectionHandler();

            // Add the MVC stuff
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }
Exemple #7
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="ClaimController" /> class.
 /// </summary>
 /// <param name="logger">The logger.</param>
 /// <param name="databaseContext">The database context.</param>
 /// <param name="autoMapper">The auto mapper service.</param>
 public ClaimController(ILogger logger, MqttContext databaseContext, IMapper autoMapper)
 {
     this.logger          = logger;
     this.databaseContext = databaseContext;
     this.autoMapper      = autoMapper;
 }