Exemple #1
0
        static void Main(string[] args)
        {
            string header = "[Komodo.Server] ";

            try
            {
                _Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();

                #region Initial-Setup

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

                if (!File.Exists("system.json"))
                {
                    initialSetup = true;
                }
                if (initialSetup)
                {
                    Setup setup = new Setup();
                }

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

                #endregion

                Welcome(initialSetup);
                InitializeGlobals();

                EventWaitHandle waitHandle       = new EventWaitHandle(false, EventResetMode.AutoReset);
                bool            waitHandleSignal = false;
                do
                {
                    waitHandleSignal = waitHandle.WaitOne(1000);
                } while (!waitHandleSignal);

                _Logging.Debug(header + "exiting");
            }
            catch (Exception e)
            {
                Console.WriteLine(Common.SerializeJson(e, true));
            }
        }
Exemple #2
0
        /// <summary>
        /// Load the configuration from a file.
        /// </summary>
        /// <param name="filename">Filename.</param>
        /// <returns>Configuration object.</returns>
        public static DaemonSettings FromFile(string filename)
        {
            if (String.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException(nameof(filename));
            }
            if (!File.Exists(filename))
            {
                throw new FileNotFoundException("Unable to find " + filename);
            }
            string         contents = File.ReadAllText(filename);
            DaemonSettings ret      = Common.DeserializeJson <DaemonSettings>(contents);

            return(ret);
        }
Exemple #3
0
        private static async Task GetIndex(RequestMetadata md)
        {
            string header = "[Komodo.Server] " + md.Http.Request.Source.IpAddress + ":" + md.Http.Request.Source.Port + " GetIndex ";

            string indexName = md.Http.Request.Url.Elements[0];
            Index  index     = _Daemon.GetIndex(indexName);

            if (index == null)
            {
                _Logging.Warn(header + "index " + indexName + " does not exist");
                md.Http.Response.StatusCode  = 404;
                md.Http.Response.ContentType = "application/json";
                await md.Http.Response.Send(new ErrorResponse(404, "Unknown index.", null, null).ToJson(true));

                return;
            }

            md.Http.Response.StatusCode  = 200;
            md.Http.Response.ContentType = "application/json";
            await md.Http.Response.Send(Common.SerializeJson(index, md.Params.Pretty));

            return;
        }
Exemple #4
0
        private static async Task RequestReceived(HttpContext ctx)
        {
            string   header    = "[Komodo.Server] " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " RequestReceived ";
            DateTime startTime = DateTime.Now;

            try
            {
                #region Base-Handlers

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

                    return;
                }

                if (ctx.Request.Url.Elements == null || ctx.Request.Url.Elements.Length == 0)
                {
                    ctx.Response.StatusCode  = 200;
                    ctx.Response.ContentType = "text/html; charset=utf-8";
                    await ctx.Response.Send(RootHtml());

                    return;
                }

                if (ctx.Request.Url.Elements != null && ctx.Request.Url.Elements.Length > 0)
                {
                    if (ctx.Request.Url.Elements.Length == 1)
                    {
                        if (String.Compare(ctx.Request.Url.Elements[0].ToLower(), "favicon.ico") == 0)
                        {
                            ctx.Response.StatusCode = 200;
                            await ctx.Response.Send(Common.ReadBinaryFile("Assets/favicon.ico"));

                            return;
                        }

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

                            return;
                        }

                        if (String.Compare(ctx.Request.Url.Elements[0].ToLower(), "loopback") == 0)
                        {
                            ctx.Response.StatusCode = 200;
                            await ctx.Response.Send();

                            return;
                        }

                        if (String.Compare(ctx.Request.Url.Elements[0].ToLower(), "version") == 0)
                        {
                            ctx.Response.StatusCode  = 200;
                            ctx.Response.ContentType = "text/plain";
                            await ctx.Response.Send(_Version);

                            return;
                        }
                    }
                }

                #endregion

                #region Admin-API

                string apiKey = ctx.Request.RetrieveHeaderValue(_Settings.Server.HeaderApiKey);

                if (ctx.Request.Url.Elements != null &&
                    ctx.Request.Url.Elements.Length > 0 &&
                    ctx.Request.Url.Elements[0].Equals("admin"))
                {
                    if (String.IsNullOrEmpty(apiKey))
                    {
                        _Logging.Warn(header + "admin API requested but no API key specified");
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(401, "No API key specified.", null, null).ToJson(true));

                        return;
                    }

                    if (String.Compare(_Settings.Server.AdminApiKey, apiKey) != 0)
                    {
                        _Logging.Warn(header + "admin API requested with invalid API key");
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(401, "Authentication failed.", null, null).ToJson(true));

                        return;
                    }

                    await AdminApiHandler(ctx);

                    return;
                }

                #endregion

                #region Determine-Request-Type

                PermissionType permType = PermissionType.Unknown;

                if (ctx.Request.Url.Elements.Length == 1)
                {
                    if (ctx.Request.Method == HttpMethod.GET && ctx.Request.Url.Elements[0].Equals("indices"))
                    {
                        // GET /indices, i.e. search
                        permType = PermissionType.Search;
                    }
                    else if (ctx.Request.Method == HttpMethod.GET)
                    {
                        // GET /[index], i.e. search
                        permType = PermissionType.Search;
                    }
                    else if (ctx.Request.Method == HttpMethod.PUT)
                    {
                        // PUT /[index], i.e. search
                        // PUT /[index]?enumerate, i.e. search
                        permType = PermissionType.Search;
                    }
                    else if (ctx.Request.Method == HttpMethod.POST)
                    {
                        if (ctx.Request.Url.Elements[0].Equals("_parse"))
                        {
                            // POST /_parse, i.e. parse document (without storing)
                            permType = PermissionType.CreateDocument;
                        }
                        else if (ctx.Request.Url.Elements[0].Equals("_postings"))
                        {
                            // POST /_postings, i.e. create postings (without storing)
                            permType = PermissionType.CreateDocument;
                        }
                        else if (ctx.Request.Url.Elements[0].Equals("indices"))
                        {
                            // POST /indices, i.e. create index
                            permType = PermissionType.CreateIndex;
                        }
                        else
                        {
                            // POST /[index], i.e. create document
                            permType = PermissionType.CreateDocument;
                        }
                    }
                    else if (ctx.Request.Method == HttpMethod.DELETE)
                    {
                        // DELETE /[index], i.e. delete index
                        permType = PermissionType.DeleteIndex;
                    }
                }
                else if (ctx.Request.Url.Elements.Length == 2)
                {
                    if (ctx.Request.Method == HttpMethod.GET)
                    {
                        if (ctx.Request.Url.Elements[1].Equals("stats"))
                        {
                            // GET /[index]/stats, i.e. search
                            permType = PermissionType.Search;
                        }
                        else
                        {
                            // GET /[index]/[documentID], i.e. search
                            permType = PermissionType.Search;
                        }
                    }
                    else if (ctx.Request.Method == HttpMethod.POST)
                    {
                        // POST /[index]/[document], i.e. create document with specific GUID
                        permType = PermissionType.CreateDocument;
                    }
                    else if (ctx.Request.Method == HttpMethod.DELETE)
                    {
                        // DELETE /[index]/[document], i.e. delete document
                        permType = PermissionType.DeleteDocument;
                    }
                }

                if (permType == PermissionType.Unknown)
                {
                    _Logging.Warn(header + "unable to verify request type");
                    ctx.Response.StatusCode  = 400;
                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.Send(new ErrorResponse(400, "Unable to discern request type.", null, null).ToJson(true));

                    return;
                }

                #endregion

                #region Authenticate-Request-and-Build-Metadata

                User       user = null;
                ApiKey     key  = null;
                Permission perm = null;

                if (!String.IsNullOrEmpty(apiKey))
                {
                    if (!_Auth.AuthenticateAndAuthorize(apiKey, permType, out user, out key, out perm))
                    {
                        _Logging.Warn(header + "unable to authenticate and authorize request");
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(401, "Unable to authenticate or authorize request.", null, null).ToJson(true));

                        return;
                    }
                }
                else
                {
                    _Logging.Warn(header + "authenticated API requested but no authentication material supplied");
                    ctx.Response.StatusCode  = 401;
                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.Send(new ErrorResponse(401, "No authentication material.", null, null).ToJson(true));

                    return;
                }

                RequestMetadata md = new RequestMetadata(ctx, user, key, perm);

                if (!String.IsNullOrEmpty(md.Params.Type))
                {
                    List <string> matchVals = new List <string> {
                        "json", "xml", "html", "sql", "text", "unknown"
                    };
                    if (!matchVals.Contains(md.Params.Type))
                    {
                        _Logging.Warn(header + "invalid 'type' value found in querystring: " + md.Params.Type);
                        ctx.Response.StatusCode  = 400;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(400, "Invalid 'type' in querystring, use [json/xml/html/sql/text].", null, null).ToJson(true));

                        return;
                    }
                }

                #endregion

                #region Call-User-API

                await UserApiHandler(md);

                return;

                #endregion
            }
            catch (Exception e)
            {
                _Logging.Alert(header + "exception encountered" + Environment.NewLine + Common.SerializeJson(e, true));
                ctx.Response.StatusCode  = 500;
                ctx.Response.ContentType = "application/json";
                await ctx.Response.Send(new ErrorResponse(500, "Outer exception.", e, null).ToJson(true));

                return;
            }
            finally
            {
                _Logging.Debug(header + ctx.Request.Method + " " + ctx.Request.Url.RawWithoutQuery + " " + ctx.Response.StatusCode + " [" + Common.TotalMsFrom(startTime) + "ms]");
            }
        }
Exemple #5
0
        private void RunSetup()
        {
            #region Variables

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

            #endregion

            #region Welcome

            Console.WriteLine(
                Environment.NewLine +
                Environment.NewLine +
                "oooo                                                    .o8            " + Environment.NewLine +
                "`888                                                    888            " + Environment.NewLine +
                " 888  oooo   .ooooo.  ooo. .oo.  .oo.    .ooooo.   .oooo888   .ooooo.  " + Environment.NewLine +
                " 888 .8P'   d88' `88b `888P'Y88bP'Y88b  d88' `88b d88' `888  d88' `88b " + Environment.NewLine +
                " 888888.    888   888  888   888   888  888   888 888   888  888   888 " + Environment.NewLine +
                " 888 `88b.  888   888  888   888   888  888   888 888   888  888   888 " + Environment.NewLine +
                "o888o o888o `Y8bod8P' o888o o888o o888o `Y8bod8P' `Y8bod88P  `Y8bod8P' " + Environment.NewLine +
                Environment.NewLine +
                Environment.NewLine);

            // ________________         1         2         3         4         5         6         7
            // ________________12345678901234567890123456789012345678901234567890123456789012345678901234567890
            Console.WriteLine("Thank you for using Komodo!  We'll put together a basic system configuration");
            Console.WriteLine("so you can be up and running quickly.");
            Console.WriteLine("");
            Console.WriteLine(Common.Line(79, "-"));
            Console.WriteLine("");

            #endregion

            #region Initial-Settings

            settings.EnableConsole = true;

            settings.Server = new Settings.ServerSettings();
            settings.Server.HeaderApiKey     = "x-api-key";
            settings.Server.AdminApiKey      = "komodoadmin";
            settings.Server.ListenerPort     = 9090;
            settings.Server.ListenerHostname = "localhost";

            settings.Logging = new Settings.LoggingSettings();
            settings.Logging.ConsoleLogging   = true;
            settings.Logging.Header           = "komodo";
            settings.Logging.SyslogServerIp   = "127.0.0.1";
            settings.Logging.SyslogServerPort = 514;
            settings.Logging.MinimumLevel     = Severity.Info;
            settings.Logging.FileLogging      = true;
            settings.Logging.FileDirectory    = "./logs/";
            settings.Logging.Filename         = "Komodo.log";

            if (!Directory.Exists("./data/"))
            {
                Directory.CreateDirectory("./data/");
            }
            if (!Directory.Exists("./logs/"))
            {
                Directory.CreateDirectory("./logs/");
            }

            settings.Database = new DbSettings("./data/komodo.db");

            string tempDirectory = "./data/temp/";
            settings.TempStorage = new StorageSettings(new DiskSettings(tempDirectory));
            if (!Directory.Exists(tempDirectory))
            {
                Directory.CreateDirectory(tempDirectory);
            }

            string sourceDirectory = "./data/source/";
            settings.SourceDocuments = new StorageSettings(new DiskSettings(sourceDirectory));
            if (!Directory.Exists(sourceDirectory))
            {
                Directory.CreateDirectory(sourceDirectory);
            }

            string parsedDirectory = "./data/parsed/";
            settings.ParsedDocuments = new StorageSettings(new DiskSettings(parsedDirectory));
            if (!Directory.Exists(parsedDirectory))
            {
                Directory.CreateDirectory(parsedDirectory);
            }

            #endregion

            #region Initialize-Database-and-Create-Records

            WatsonORM orm = new WatsonORM(settings.Database.ToDatabaseSettings());

            orm.InitializeDatabase();
            orm.InitializeTable(typeof(ApiKey));
            orm.InitializeTable(typeof(Index));
            orm.InitializeTable(typeof(Metadata));
            orm.InitializeTable(typeof(MetadataDocument));
            orm.InitializeTable(typeof(Node));
            orm.InitializeTable(typeof(ParsedDocument));
            orm.InitializeTable(typeof(Permission));
            orm.InitializeTable(typeof(SourceDocument));
            orm.InitializeTable(typeof(TermDoc));
            orm.InitializeTable(typeof(TermGuid));
            orm.InitializeTable(typeof(User));

            DbExpression e = new DbExpression("id", DbOperators.GreaterThan, 0);

            User       user   = null;
            ApiKey     apiKey = null;
            Permission perm   = null;
            Index      idx    = null;

            List <User> users = orm.SelectMany <User>(e);
            if (users == null || users.Count < 1)
            {
                Console.WriteLine("| Creating first user 'default'");
                user = new User("default", "Default", "*****@*****.**", "default");
                user = orm.Insert <User>(user);
            }
            else
            {
                Console.WriteLine("| Users already exist, not creating default user");
            }

            List <Index> indices = orm.SelectMany <Index>(e);
            if (indices == null || indices.Count < 1)
            {
                Console.WriteLine("| Creating first index 'default'");
                idx = new Index(user.GUID, "default");
                idx = orm.Insert <Index>(idx);
            }
            else
            {
                Console.WriteLine("| Indices already exist, not creating default index");
            }

            List <ApiKey> keys = orm.SelectMany <ApiKey>(e);
            if (keys == null || keys.Count < 1)
            {
                Console.WriteLine("| Creating first API key 'default'");
                apiKey = new ApiKey("default", user.GUID, true);
                apiKey = orm.Insert <ApiKey>(apiKey);
            }
            else
            {
                Console.WriteLine("| API keys already exist, not creating default API key");
            }

            List <Permission> perms = orm.SelectMany <Permission>(e);
            if (perms == null || perms.Count < 1)
            {
                Console.WriteLine("| Creating first permission 'default'");
                perm = new Permission(idx.GUID, user.GUID, apiKey.GUID, true, true, true, true, true);
                perm = orm.Insert <Permission>(perm);
            }
            else
            {
                Console.WriteLine("| Permissions already exist, not creating default permissions");
            }

            #endregion

            #region Write-System-JSON

            File.WriteAllBytes("./system.json", Encoding.UTF8.GetBytes(Common.SerializeJson(settings, true)));

            #endregion

            #region Wrap-Up

            string baseUrl = "http://localhost:" + settings.Server.ListenerPort;

            // ________________         1         2         3         4         5         6         7
            // ________________12345678901234567890123456789012345678901234567890123456789012345678901234567890
            Console.WriteLine("");
            Console.WriteLine("All finished!");
            Console.WriteLine("");
            Console.WriteLine("If you ever want to return to this setup wizard, just re-run the application");
            Console.WriteLine("from the terminal with the 'setup' argument.");
            Console.WriteLine("");
            Console.WriteLine("Verify Komodo is running in your browser using the following URL:");
            Console.WriteLine("");
            Console.WriteLine("  " + baseUrl);
            Console.WriteLine("");
            Console.WriteLine("We've created your first index for you called 'First'.  Try POSTing a JSON");
            Console.WriteLine("document to the index using the API key 'default' using the URL:");
            Console.WriteLine("");
            Console.WriteLine("  " + baseUrl + "/default?type=json&name=My+First+Document&x-api-key=default");
            Console.WriteLine("");

            #endregion
        }