예제 #1
0
        private string SampleJsonFile(string link)
        {
            Dictionary <string, object> ret = new Dictionary <string, object>();

            ret.Add("Title", "Welcome to Kvpbase");
            ret.Add("Body", "If you can see this file, your Kvpbase node is running!");
            ret.Add("Github", link);
            return(Common.SerializeJson(ret, true));
        }
예제 #2
0
        /// <summary>
        /// Main method.
        /// </summary>
        /// <param name="args">Command line arguments.</param>
        public static void Main(string[] args)
        {
            _Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();

            bool initialSetup = false;

            if (args != null && args.Length >= 1)
            {
                if (String.Compare(args[0], "setup") == 0)
                {
                    initialSetup = true;
                }
            }

            if (!Common.FileExists("System.json"))
            {
                initialSetup = true;
            }
            if (initialSetup)
            {
                Setup setup = new Setup();
            }

            _Settings = Settings.FromFile("System.json");

            Welcome(initialSetup);
            CreateDirectories();
            InitializeGlobals();

            if (_Settings.EnableConsole && Environment.UserInteractive)
            {
                _ConsoleMgr.Worker();
            }
            else
            {
                EventWaitHandle waitHandle       = new EventWaitHandle(false, EventResetMode.AutoReset, null);
                bool            waitHandleSignal = false;
                do
                {
                    waitHandleSignal = waitHandle.WaitOne(1000);
                }while (!waitHandleSignal);
            }

            _Logging.Debug(_Header + "exiting");
        }
예제 #3
0
        private void RunSetup()
        {
            #region Variables

            DateTime timestamp = DateTime.Now;
            Settings settings  = new Settings();

            #endregion

            #region Welcome

            Console.WriteLine("");
            Console.ForegroundColor = ConsoleColor.DarkGray;
            Console.WriteLine(@"   _             _                    ");
            Console.WriteLine(@"  | |____ ___ __| |__  __ _ ___ ___   ");
            Console.WriteLine(@"  | / /\ V / '_ \ '_ \/ _` (_-</ -_)  ");
            Console.WriteLine(@"  |_\_\ \_/| .__/_.__/\__,_/__/\___|  ");
            Console.WriteLine(@"           |_|                        ");
            Console.WriteLine(@"                                      ");
            Console.ResetColor();

            Console.WriteLine("");
            Console.WriteLine("Kvpbase Storage Server");
            Console.WriteLine("");
            //                          1         2         3         4         5         6         7
            //                 12345678901234567890123456789012345678901234567890123456789012345678901234567890
            Console.WriteLine("Thank you for using Kvpbase!  We'll put together a basic system configuration");
            Console.WriteLine("so you can be up and running quickly.  You'll want to modify the System.json");
            Console.WriteLine("file after to ensure a more secure operating environment.");

            #endregion

            #region Initial-Settings

            settings.EnableConsole = true;

            settings.Server                 = new Settings.SettingsServer();
            settings.Server.Port            = 8000;
            settings.Server.DnsHostname     = "localhost";
            settings.Server.Ssl             = false;
            settings.Server.HeaderApiKey    = "x-api-key";
            settings.Server.MaxObjectSize   = 2199023255552;    // 2TB object size
            settings.Server.MaxTransferSize = 536870912;        // 512MB transfer size

            settings.Storage           = new Settings.SettingsStorage();
            settings.Storage.Directory = "./Storage/";
            Directory.CreateDirectory(settings.Storage.Directory);

            settings.Syslog = new Settings.SettingsSyslog();
            settings.Syslog.ConsoleLogging = true;
            settings.Syslog.Header         = "kvpbase";
            settings.Syslog.ServerIp       = "127.0.0.1";
            settings.Syslog.ServerPort     = 514;
            settings.Syslog.MinimumLevel   = Severity.Info;
            settings.Syslog.FileLogging    = true;
            settings.Syslog.LogDirectory   = "./Logs/";

            if (!Directory.Exists(settings.Syslog.LogDirectory))
            {
                Directory.CreateDirectory(settings.Syslog.LogDirectory);
            }

            settings.Debug             = new Settings.SettingsDebug();
            settings.Debug.Database    = false;
            settings.Debug.HttpRequest = false;

            #endregion

            #region Databases

            //                          1         2         3         4         5         6         7
            //                 12345678901234567890123456789012345678901234567890123456789012345678901234567890
            Console.WriteLine("");
            Console.WriteLine("Kvpbase requires access to a database, either Sqlite, Microsoft SQL Server,");
            Console.WriteLine("MySQL, or PostgreSQL.  Please provide access details for your database.  The");
            Console.WriteLine("user account supplied must have the ability to CREATE and DROP tables along");
            Console.WriteLine("with issue queries containing SELECT, INSERT, UPDATE, and DELETE.  Setup will");
            Console.WriteLine("attempt to create tables on your behalf if they dont exist.");
            Console.WriteLine("");

            bool dbSet = false;
            while (!dbSet)
            {
                string userInput = Common.InputString("Database type [sqlite|sqlserver|mysql|postgresql]:", "sqlite", false);
                switch (userInput)
                {
                case "sqlite":
                    settings.Database = new DatabaseSettings(
                        Common.InputString("Filename:", "./Kvpbase.db", false)
                        );

                    //                          1         2         3         4         5         6         7
                    //                 12345678901234567890123456789012345678901234567890123456789012345678901234567890
                    Console.WriteLine("");
                    Console.WriteLine("IMPORTANT: Using Sqlite in production is not recommended if deploying within a");
                    Console.WriteLine("containerized environment and the database file is stored within the container.");
                    Console.WriteLine("Store the database file in external storage to ensure persistence.");
                    Console.WriteLine("");
                    dbSet = true;
                    break;

                case "sqlserver":
                    settings.Database = new DatabaseSettings(
                        Common.InputString("Hostname:", "localhost", false),
                        Common.InputInteger("Port:", 1433, true, false),
                        Common.InputString("Username:"******"sa", false),
                        Common.InputString("Password:"******"Instance (for SQLEXPRESS):", null, true),
                        Common.InputString("Database name:", "kvpbase", false)
                        );
                    dbSet = true;
                    break;

                case "mysql":
                    settings.Database = new DatabaseSettings(
                        DbTypes.Mysql,
                        Common.InputString("Hostname:", "localhost", false),
                        Common.InputInteger("Port:", 3306, true, false),
                        Common.InputString("Username:"******"root", false),
                        Common.InputString("Password:"******"Schema name:", "kvpbase", false)
                        );
                    dbSet = true;
                    break;

                case "postgresql":
                    settings.Database = new DatabaseSettings(
                        DbTypes.Postgresql,
                        Common.InputString("Hostname:", "localhost", false),
                        Common.InputInteger("Port:", 5432, true, false),
                        Common.InputString("Username:"******"postgres", false),
                        Common.InputString("Password:"******"Schema name:", "kvpbase", false)
                        );
                    dbSet = true;
                    break;
                }
            }

            #endregion

            #region Write-Files-and-Records

            Console.WriteLine("");
            Console.WriteLine("| Writing system.json");

            Common.WriteFile("System.json", Encoding.UTF8.GetBytes(Common.SerializeJson(settings, true)));

            Console.WriteLine("| Initializing logging");

            LoggingModule logging = new LoggingModule("127.0.0.1", 514);
            logging.MinimumSeverity = Severity.Info;

            Console.WriteLine("| Initializing database");

            WatsonORM orm = new WatsonORM(settings.Database);
            orm.InitializeDatabase();
            orm.InitializeTable(typeof(ApiKey));
            orm.InitializeTable(typeof(AuditLogEntry));
            orm.InitializeTable(typeof(Container));
            orm.InitializeTable(typeof(ContainerKeyValuePair));
            orm.InitializeTable(typeof(ObjectKeyValuePair));
            orm.InitializeTable(typeof(ObjectMetadata));
            orm.InitializeTable(typeof(Permission));
            orm.InitializeTable(typeof(UrlLock));
            orm.InitializeTable(typeof(UserMaster));

            Console.WriteLine("| Adding user [default]");

            UserMaster user = new UserMaster();
            user.GUID       = "default";
            user.Email      = "*****@*****.**";
            user.Password   = "******";
            user.FirstName  = "Default";
            user.LastName   = "User";
            user.CreatedUtc = timestamp;
            user.Active     = true;
            user            = orm.Insert <UserMaster>(user);

            Console.WriteLine("| Adding API key [default]");

            ApiKey apiKey = new ApiKey();
            apiKey          = new ApiKey();
            apiKey.GUID     = "default";
            apiKey.UserGUID = user.GUID;
            apiKey.Active   = true;
            apiKey          = orm.Insert <ApiKey>(apiKey);

            Console.WriteLine("| Adding permission [default]");

            Permission perm = new Permission();
            perm.GUID            = Guid.NewGuid().ToString();
            perm.UserGUID        = user.GUID;
            perm.ContainerGUID   = "default";
            perm.DeleteContainer = true;
            perm.DeleteObject    = true;
            perm.ReadContainer   = true;
            perm.ReadObject      = true;
            perm.WriteContainer  = true;
            perm.WriteObject     = true;
            perm.IsAdmin         = true;
            perm.ApiKeyGUID      = apiKey.GUID;
            perm.Notes           = "Created by setup script";
            perm.Active          = true;
            perm = orm.Insert <Permission>(perm);

            Console.WriteLine("| Creating container [default]");

            string htmlFile = SampleHtmlFile("http://github.com/kvpbase");
            string textFile = SampleTextFile("http://github.com/kvpbase");
            string jsonFile = SampleJsonFile("http://github.com/kvpbase");

            ContainerManager containerMgr = new ContainerManager(settings, logging, orm);

            Container container = new Container();
            container.UserGUID           = "default";
            container.Name               = "default";
            container.GUID               = "default";
            container.ObjectsDirectory   = settings.Storage.Directory + container.UserGUID + "/" + container.Name + "/";
            container.EnableAuditLogging = true;
            container.IsPublicRead       = true;
            container.IsPublicWrite      = false;
            containerMgr.Add(container);

            ContainerClient client = containerMgr.GetContainerClient("default", "default");

            Console.WriteLine("| Writing sample files to container [default]");

            ErrorCode error;
            client.WriteObject("hello.html", "text/html", Encoding.UTF8.GetBytes(htmlFile), null, out error);
            client.WriteObject("hello.txt", "text/plain", Encoding.UTF8.GetBytes(textFile), null, out error);
            client.WriteObject("hello.json", "application/json", Encoding.UTF8.GetBytes(jsonFile), null, out error);

            #endregion

            #region Wrap-Up

            //                         1         2         3         4         5         6         7
            //                12345678901234567890123456789012345678901234567890123456789012345678901234567890
            Console.WriteLine("");
            Console.WriteLine(Common.Line(79, "-"));
            Console.WriteLine("");
            Console.WriteLine("We have created your first user account and permissions.");
            Console.WriteLine("");

            ConsoleColor prior = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("IMPORTANT: The default API key setup creates has administrative privileges and");
            Console.WriteLine("can use admin APIs.  We recommend you modify your configuration and reduce its");
            Console.WriteLine("permissions before exposing Kvpbase outside of localhost.");
            Console.ForegroundColor = prior;
            Console.WriteLine("");
            Console.WriteLine("  API Key  : " + apiKey.GUID);
            Console.WriteLine("");
            Console.WriteLine("We've also created sample files for you so that you can see your node in");
            Console.WriteLine("action.  Go to the following URLs in your browser and see what happens!");
            Console.WriteLine("");
            Console.WriteLine("  http://localhost:8000/");
            Console.WriteLine("  http://localhost:8000/default/default?_container&html");
            Console.WriteLine("  http://localhost:8000/default/default/hello.html");
            Console.WriteLine("  http://localhost:8000/default/default/hello.html?metadata");
            Console.WriteLine("  http://localhost:8000/default/default/hello.txt");
            Console.WriteLine("  http://localhost:8000/default/default/hello.json");
            Console.WriteLine("");

            #endregion
        }
예제 #4
0
        private static async Task RequestReceived(HttpContext ctx)
        {
            string header = _Header + ctx.Request.SourceIp + ":" + ctx.Request.SourcePort + " ";

            DateTime  startTime = DateTime.Now;
            Stopwatch sw        = new Stopwatch();

            sw.Start();

            RequestMetadata md = new RequestMetadata();

            md.Http = ctx;
            md.User = null;
            md.Key  = null;
            md.Perm = null;

            try
            {
                if (Common.IsTrue(_Settings.Debug.HttpRequest))
                {
                    _Logging.Debug(header + "RequestReceived request received: " + Environment.NewLine + md.Http.ToString());
                }

                if (ctx.Request.Method == HttpMethod.OPTIONS)
                {
                    await OptionsHandler(ctx);

                    return;
                }

                if (ctx.Request.RawUrlEntries != null && ctx.Request.RawUrlEntries.Count > 0)
                {
                    if (ctx.Request.RawUrlEntries[0].Equals("favicon.ico"))
                    {
                        ctx.Response.StatusCode = 200;
                        await ctx.Response.Send();

                        return;
                    }

                    if (ctx.Request.RawUrlEntries[0].Equals("robots.txt"))
                    {
                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send("User-Agent: *\r\nDisallow:\r\n");

                        return;
                    }
                }

                if (ctx.Request.RawUrlEntries == null || ctx.Request.RawUrlEntries.Count == 0)
                {
                    ctx.Response.StatusCode  = 200;
                    ctx.Response.ContentType = "text/html";
                    await ctx.Response.Send(DefaultPage("http://github.com/kvpbase"));

                    return;
                }

                _ConnMgr.Add(Thread.CurrentThread.ManagedThreadId, ctx);

                string     apiKeyVal            = ctx.Request.RetrieveHeaderValue(_Settings.Server.HeaderApiKey);
                UserMaster user                 = null;
                ApiKey     apiKey               = null;
                AuthResult authResult           = AuthResult.None;
                Permission effectivePermissions = null;

                if (!String.IsNullOrEmpty(apiKeyVal))
                {
                    if (!_AuthMgr.Authenticate(apiKeyVal, out user, out apiKey, out effectivePermissions, out authResult))
                    {
                        _Logging.Warn("RequestReceived unable to verify API key " + apiKeyVal + ": " + authResult);
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(Common.SerializeJson(new ErrorResponse(3, 401, null, null), true));

                        return;
                    }
                }

                md.User   = user;
                md.Key    = apiKey;
                md.Perm   = effectivePermissions;
                md.Params = RequestMetadata.Parameters.FromHttpRequest(ctx.Request);
                if (md.User != null)
                {
                    md.Params.UserGuid = md.User.GUID;
                }
                _ConnMgr.Update(Thread.CurrentThread.ManagedThreadId, md.User);

                if (ctx.Request.RawUrlEntries != null &&
                    ctx.Request.RawUrlEntries.Count >= 2 &&
                    ctx.Request.RawUrlEntries[0].Equals("admin") &&
                    md.Perm.IsAdmin)
                {
                    await AdminApiHandler(md);
                }
                else
                {
                    await UserApiHandler(md);
                }

                return;
            }
            catch (Exception e)
            {
                _Logging.Exception("StorageServer", "RequestReceived", e);
                ctx.Response.StatusCode  = 500;
                ctx.Response.ContentType = "application/json";
                await ctx.Response.Send(Common.SerializeJson(new ErrorResponse(1, 500, "Outer exception.", null), true));

                return;
            }
            finally
            {
                sw.Stop();

                _ConnMgr.Close(Thread.CurrentThread.ManagedThreadId);

                string msg =
                    header +
                    ctx.Request.Method + " " + ctx.Request.RawUrlWithoutQuery + " " +
                    ctx.Response.StatusCode + " " +
                    "[" + sw.ElapsedMilliseconds + "ms]";

                _Logging.Debug(msg);
            }
        }
예제 #5
0
 private static void WebserverException(object sender, ExceptionEventArgs args)
 {
     _Logging.Warn(_Header + "exception for " + args.Ip + ":" + args.Port + ":" + Environment.NewLine + Common.SerializeJson(args.Exception, true));
 }