public RemoteIOModule(IOMServerContext serverContext) : base("/io")
        {
            ServerContext = serverContext;

            var pathRoutes = new[] { @"^(?:(?<dbid>[\w]+)\/(?<path>.*?)(?=\.json))" };

            foreach (var pathRoute in pathRoutes)
            {
                Put(pathRoute, HandlePutDataAsync);
                Patch(pathRoute, HandlePatchDataAsync);
                Post(pathRoute, HandlePostDataAsync);
                Delete(pathRoute, HandleDeleteDataAsync);
                Get(pathRoute, HandleGetDataAsync);
            }

            // Do some initial setup
            Before += ctx => { return(null); };
            // Check requested response type argument
            // Refer to https://firebase.google.com/docs/database/rest/retrieve-data
            After += ctx =>
            {
                var queryData     = ctx.Request.Query;
                var printArgument = (string)queryData.print;
                switch (printArgument)
                {
                case "silent":     // User does not want a response.
                    ctx.Response = null;
                    ctx.Response = HttpStatusCode.NoContent;
                    break;

                default:
                    break;
                }
            };
        }
        public RemoteSecurityModule(IOMServerContext serverContext) : base("/rsec")
        {
            ServerContext = serverContext;

            var accessValidator = new StatelessClientValidator <OMAccessKey, OMApiAccessScope>();

            this.RequiresAllClaims(new[] { accessValidator.GetAccessClaim(OMApiAccessScope.Admin) });

            // Rule management (these can also manage keys)
            Post("/rules/create/{dbid?}", HandleCreateRuleRequestAsync);
            Delete("/rules/clear/{dbid?}", HandleClearRulesRequestAsync);
            Delete("/rules/delete/{dbid?}", HandleDeleteRuleRequestAsync);
            Get("/rules/list/{dbid?}", HandleGetRuleListRequestAsync);
            Get("/rules/get/{dbid?}", HandleGetRuleByIdRequestAsync);

            // API key management
            Post("/keys/create/{keyid}", HandleCreateKeyRequestAsync);
            Get("/keys/get/{keyid}", HandleGetKeyRequestAsync);
            Delete("/keys/delete/{keyid}", HandleDeleteKeyRequestAsync);

            // Persist state after successful request
            After += ctx =>
            {
                if (ctx.Response.StatusCode == HttpStatusCode.OK)
                {
                    ServerContext.ServerState.Persist();
                }
            };
        }
        public static RequestProcessor CreateRequestProcessor(IOMServerContext serverContext)
        {
            var processor = new RequestProcessor(serverContext.OMContext);

            processor.AuthTokenValidator = accessRequest =>
            {
                // get key identity
                var authenticator = new StatelessAuthenticationService <OMAccessKey, OMApiAccessScope>(serverContext);
                var identity      = authenticator.ResolveClientIdentity(accessRequest.AuthToken);
                if (identity == null)
                {
                    return(false);
                }
                var accessKey = authenticator.ResolveKey(accessRequest.AuthToken);
                // make sure realm is allowed
                if (!accessKey.AllowedRealms.Contains(accessRequest.DatabaseId))
                {
                    return(false);
                }
                // check more rules
                if (processor.ValidateAdditionalRules(accessRequest, accessKey.SecurityRules).Granted)
                {
                    return(true);
                }
                // only check admin
                var accessValidator = new StatelessClientValidator <OMAccessKey, OMApiAccessScope>();
                if (identity.EnsureClaim(accessValidator.GetAccessClaim(OMApiAccessScope.Admin)))
                {
                    return(true);
                }

                return(false);
            };

            return(processor);
        }
        public RemoteIOModule(IOMServerContext serverContext) : base("/a")
        {
            ServerContext = serverContext;

            Get("/info", _ => "OsmiumMine.Core.Server Standalone Edition");
        }