Пример #1
0
        public static void HandleRequest(HttpProcessor p, string jsonStr)
        {
            object response = null;

            try
            {
                dynamic       requestObj = JsonConvert.DeserializeObject(jsonStr);
                ServerSession session    = GetSession(requestObj);
                string        cmd        = Try.Get(() => (string)requestObj.cmd);
                if (cmd == "login")
                {
                    if (session == null)
                    {
                        session = ServerSession.CreateUnauthenticated();
                        SessionManager.AddSession(session);
                    }
                    // Get current challenge and generate a new one so the previous one can not be used again, preventing replay attacks.
                    byte[] currentChallenge = session.authChallenge;
                    session.authChallenge = ByteUtil.GenerateRandomBytes(32);
                    // Get user
                    string userName = Try.Get(() => (string)requestObj.user);
                    if (string.IsNullOrEmpty(userName))
                    {
                        response = new ResultFailWithReason(session, "missing parameter: \"user\"");
                        return;
                    }
                    User user = ServiceWrapper.db.GetUser(userName);

                    string responseToken = Try.Get(() => (string)requestObj.response);
                    if (string.IsNullOrEmpty(responseToken))
                    {
                        // No response token was provided. This is step 1 of authentication, where the client requests information necessary to build the response token.
                        string salt;
                        if (user != null)
                        {
                            salt = user.Salt;
                        }
                        else
                        {
                            salt = Util.GenerateFakeUserSalt(userName);
                            Logger.Info("Fake salt \"" + salt + "\" created for user name \"" + userName + "\". Remote IP: " + p.RemoteIPAddressStr);
                        }

                        response = new ResultLoginChallengeAndSalt(session, salt);
                    }
                    else
                    {
                        bool authenticated = false;
                        // If the user hasn't gotten a challenge token yet, currentChallenge will be blank.
                        if (currentChallenge != null && currentChallenge.Length > 0)
                        {
                            if (user != null)
                            {
                                authenticated = user.AuthenticateUser(responseToken, currentChallenge);
                            }
                        }
                        if (authenticated)
                        {
                            session.userId = user.ID;
                            response       = new ResultLoginSuccess(session, user.SettingsKey);
                        }
                        else
                        {
                            response = new ResultFailWithReason(session, "authentication rejected");
                        }
                    }
                    return;
                }
                else
                {
                    if (session == null || !session.IsAuthValid)
                    {
                        response = new ResultFailNoSession(session);
                        return;
                    }
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    // Commands after this point require an authenticated session, but not administrator permission. //
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    ///////////////////////////////////////////////////////////////////////////////////////////////////
                    User user = session.GetUser();
                    if (user == null)
                    {
                        Logger.Debug("Session has user ID " + session.userId + " but GetUser returned null");
                        response = new ResultFailWithReason(session, "session corrupted");
                        return;
                    }
                    bool handled = true;
                    switch (cmd)
                    {
                    case "getComputers":
                        UserGroup[]             userGroups = user.GetGroups();
                        GetComputerGroupsResult result     = new GetComputerGroupsResult();
                        result.Groups = userGroups.Select(g => new GroupOfComputers(g, ServiceWrapper.db.GetComputersInGroup(g.ID))).ToArray();
                        response      = result;
                        break;

                    case "logout":
                        SessionManager.RemoveSession(session.sid);
                        response = new ResultSuccess();
                        break;

                    default:
                        handled = false;
                        break;
                    }
                    if (handled)
                    {
                        return;
                    }

                    if (!user.IsAdmin)
                    {
                        response = new ResultFailInsufficientPrivileges();
                        return;
                    }
                    /////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////////////////////
                    // Commands after this point require administrator permission. //
                    /////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////////////////////
                    switch (cmd)
                    {
                        #region admin/getComputers
                    case "admin/getComputers":
                    {
                        ResultComputersAndTheirGroups result = new ResultComputersAndTheirGroups();

                        ComputerAndItsGroups[] allComputers = ServiceWrapper.db.GetAllComputersAndTheirGroups();
                        result.Computers = allComputers.Select(c => new AdminResultComputer(c)).ToArray();

                        response = result;
                        break;
                    }

                        #endregion
                        #region admin/getUsers
                    case "admin/getUsers":
                    {
                        ResultAllUsers result = new ResultAllUsers();

                        UserAndItsGroups[] allUsers = ServiceWrapper.db.GetAllUsersAndTheirGroups();
                        result.Users = allUsers.Select(u => new AdminResultUser(u)).ToArray();

                        response = result;
                        break;
                    }

                        #endregion
                    default:
                    {
                        response = new ResultFailWithReason(session, "unrecognized command");
                        break;
                    }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Debug(ex);
                response = new ResultFail()
                {
                    error = "An unexpected error occurred."
                };
            }
            finally
            {
                if (response == null)
                {
                    response = new ResultFail()
                    {
                        error = "Application Error: A response was not generated, so this response was generated as a fallback."
                    }
                }
                ;
                p.writeSuccess(jsonType);
                p.outputStream.Write(JsonConvert.SerializeObject(response));
            }
        }
Пример #2
0
        public static void HandleRequest(HttpProcessor p, string jsonStr)
        {
            object response = null;

            try
            {
                dynamic requestObj = JsonConvert.DeserializeObject(jsonStr);
                string  cmd        = Try.Get(() => (string)requestObj.cmd);
                switch (cmd)
                {
                case "log_get":
                {
                    int  nextLine = (int)requestObj.nextLine;
                    long logId    = (long)requestObj.logId;
                    if (logId == -1)
                    {
                        logId = ServiceWrapper.logReader.readerId;
                    }
                    else if (logId != ServiceWrapper.logReader.readerId)
                    {
                        response = new ResultLogGet("REFRESH", -1, ServiceWrapper.logReader.readerId, null);
                        break;
                    }
                    List <string> lines = ServiceWrapper.logReader.GetLogUpdate(logId, ref nextLine);
                    response = new ResultLogGet("OK", nextLine, ServiceWrapper.logReader.readerId, lines);
                    break;
                }

                    #region Hotkeys
                case "hotkey_reorder":
                case "hotkey_names":
                case "hotkey_list":
                case "hotkey_new":
                case "hotkey_get":
                case "hotkey_update":
                case "hotkey_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.hotkeys);
                    break;
                }

                case "beginHotkeyBind":
                {
                    int    hotkeyId = requestObj.hotkeyId;
                    string bindId   = ServiceWrapper.hotkeyManager.BeginHotkeyBind(hotkeyId);
                    if (bindId == null)
                    {
                        response = new ResultFailWithReason("hotkey not found");
                    }
                    else if (bindId == "")
                    {
                        response = new ResultFailWithReason("another bind is already in progress");
                    }
                    else
                    {
                        response = new ResultWithData(bindId);
                    }
                    break;
                }

                case "endHotkeyBind":
                {
                    int    hotkeyId = requestObj.hotkeyId;
                    Hotkey hotkey   = ServiceWrapper.config.hotkeys.Get(hotkeyId);
                    if (hotkey == null)
                    {
                        response = new ResultFailWithReason("hotkey not found");
                        break;
                    }
                    string bindId = requestObj.bindId;
                    if (string.IsNullOrWhiteSpace(bindId))
                    {
                        response = new ResultFailWithReason("invalid bindId");
                        break;
                    }
                    while (bindId == ServiceWrapper.hotkeyManager.GetCurrentBindId())
                    {
                        Thread.Sleep(100);
                    }
                    response = new ResultWithData(hotkey);
                    break;
                }

                case "cancelHotkeyBind":
                {
                    string bindId = requestObj.bindId;
                    if (string.IsNullOrWhiteSpace(bindId))
                    {
                        response = new ResultFailWithReason("invalid bindId");
                        break;
                    }
                    ServiceWrapper.hotkeyManager.CancelHotkeyBind(bindId);
                    response = new ResultSuccess();
                    break;
                }

                case "unbindHotkey":
                {
                    string bindId = requestObj.bindId;
                    if (string.IsNullOrWhiteSpace(bindId))
                    {
                        response = new ResultFailWithReason("invalid bindId");
                        break;
                    }
                    Hotkey hotkey = ServiceWrapper.hotkeyManager.UnbindHotkey(bindId);
                    if (hotkey != null)
                    {
                        response = new ResultWithData(hotkey);
                    }
                    else
                    {
                        response = new ResultFailWithReason("Unable to unbind hotkey. Please try again.");
                    }
                    break;
                }

                case "executeHotkey":
                {
                    int    hotkeyId = requestObj.hotkeyId;
                    string error    = ServiceWrapper.hotkeyManager.ExecuteHotkeyById(hotkeyId);
                    if (error == null)
                    {
                        response = new ResultSuccess();
                    }
                    else
                    {
                        response = new ResultFailWithReason("Hotkey manual execution failed: " + error);
                    }
                    break;
                }

                    #endregion
                    #region BroadLink
                case "broadlink_reorder":
                case "broadlink_names":
                case "broadlink_list":
                case "broadlink_new":
                case "broadlink_get":
                case "broadlink_update":
                case "broadlink_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.broadLinks);
                    break;
                }

                case "broadlink_command_short_names":
                {
                    response = new ResultWithData(IRBlasters.IRCommands.GetIRCommandShortNames());
                    break;
                }

                    #endregion
                    #region BroadLink Commands
                case "broadlinkcmd_reorder":
                case "broadlinkcmd_names":
                case "broadlinkcmd_list":
                case "broadlinkcmd_new":
                case "broadlinkcmd_get":
                case "broadlinkcmd_update":
                case "broadlinkcmd_delete":
                {
                    response = NamedItemAPI(requestObj, BroadLinkCommands.commands, (Action)(() =>
                        {
                            BroadLinkCommands.Save(ServiceWrapper.BroadLinkCommandsFile);
                        }));
                    break;
                }

                case "broadlinkcmd_reload_commands":
                {
                    BroadLinkCommands.Load(ServiceWrapper.BroadLinkCommandsFile);
                    response = new ResultSuccess();
                    break;
                }

                case "beginBroadlinkCommandLearn":
                {
                    int    controllerId = requestObj.controllerId;
                    int    commandId    = requestObj.commandId;
                    string lessonId     = BroadLinkCommands.BeginLearning(controllerId, commandId);
                    if (lessonId == null)
                    {
                        response = new ResultFailWithReason("hotkey not found");
                    }
                    else if (lessonId == "")
                    {
                        response = new ResultFailWithReason("another bind is already in progress");
                    }
                    else
                    {
                        response = new ResultWithData(lessonId);
                    }
                    break;
                }

                case "endBroadlinkCommandLearn":
                {
                    int          controllerId = requestObj.controllerId;
                    int          commandId    = requestObj.commandId;
                    BroadLinkCmd command      = BroadLinkCommands.commands.Get(commandId);
                    if (command == null)
                    {
                        response = new ResultFailWithReason("command not found");
                        break;
                    }
                    string lessonId = requestObj.lessonId;
                    if (string.IsNullOrWhiteSpace(lessonId))
                    {
                        response = new ResultFailWithReason("invalid lessonId");
                        break;
                    }
                    BroadLinkCommands.AwaitLearningResult(controllerId, lessonId);
                    response = new ResultWithData(command);
                    break;
                }

                case "cancelBroadlinkCommandLearn":
                {
                    int    controllerId = requestObj.controllerId;
                    string lessonId     = requestObj.lessonId;
                    if (string.IsNullOrWhiteSpace(lessonId))
                    {
                        response = new ResultFailWithReason("invalid lessonId");
                        break;
                    }
                    BroadLinkCommands.CancelLearning(controllerId, lessonId);
                    response = new ResultSuccess();
                    break;
                }

                case "unlearnBroadlinkCommand":
                {
                    int    controllerId = requestObj.controllerId;
                    string lessonId     = requestObj.lessonId;
                    if (string.IsNullOrWhiteSpace(lessonId))
                    {
                        response = new ResultFailWithReason("invalid lessonId");
                        break;
                    }
                    BroadLinkCmd command = BroadLinkCommands.UnlearnCommandCodes(controllerId, lessonId);
                    if (command != null)
                    {
                        response = new ResultWithData(command);
                    }
                    else
                    {
                        response = new ResultFailWithReason("Unable to unbind command. Please try again.");
                    }
                    break;
                }

                    #endregion
                    #region iTach
                case "itach_reorder":
                case "itach_names":
                case "itach_list":
                case "itach_new":
                case "itach_get":
                case "itach_update":
                case "itach_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.iTachs);
                    break;
                }

                case "ir_command_short_names":
                {
                    response = new ResultWithData(IRBlasters.IRCommands.GetIRCommandShortNames());
                    break;
                }

                case "itach_reload_commands":
                {
                    iTachCommands.Load(ServiceWrapper.iTachCommandsFile);
                    response = new ResultSuccess();
                    break;
                }

                    #endregion
                    #region Vera
                case "vera_reorder":
                case "vera_names":
                case "vera_list":
                case "vera_new":
                case "vera_get":
                case "vera_update":
                case "vera_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.veras);
                    break;
                }

                case "vera_command_list":
                {
                    List <object> list = new List <object>();
                    Parallel.ForEach(ServiceWrapper.config.veras.List(), vera =>
                        {
                            ConcurrentDictionary <int, string> map = vera.GetDeviceIdToDisplayNameMap();
                            if (map != null)
                            {
                                int[] DeviceIds = map.Keys.ToArray();
                                string[] Names  = DeviceIds.Select(id => map[id]).ToArray();
                                lock (list)
                                {
                                    list.Add(new { Id = vera.id, Name = vera.name, DeviceIds = DeviceIds, Names = Names });
                                }
                            }
                        });
                    response = new ResultWithData(list);
                    break;
                }

                case "vera_reload_commands":
                {
                    int success = 0;
                    int failure = 0;
                    Parallel.ForEach(ServiceWrapper.config.veras.List(), vera =>
                        {
                            if (vera.LoadDisplayNames(true))
                            {
                                Interlocked.Increment(ref success);
                            }
                            else
                            {
                                Interlocked.Increment(ref failure);
                            }
                        });
                    response = new ResultWithData("Vera Command Loading complete. Successful loads: " + success + ". Failed loads: " + failure);
                    break;
                }

                    #endregion
                    #region HomeAssistant
                case "hass_reorder":
                case "hass_names":
                case "hass_list":
                case "hass_new":
                case "hass_get":
                case "hass_update":
                case "hass_delete":
                {
                    response = NamedItemAPI(requestObj, ServiceWrapper.config.homeAssistantServers);
                    break;
                }

                case "hass_entities":
                {
                    List <object> list = new List <object>();
                    Parallel.ForEach(ServiceWrapper.config.homeAssistantServers.List(), hass =>
                        {
                            List <object> listFromOneServer = hass.GetCommandList();
                            list.AddRange(listFromOneServer);
                        });
                    response = new ResultWithData(list);
                    break;
                }

                case "hass_load":
                {
                    int success = 0;
                    int failure = 0;
                    Parallel.ForEach(ServiceWrapper.config.homeAssistantServers.List(), hass =>
                        {
                            if (hass.Load())
                            {
                                Interlocked.Increment(ref success);
                            }
                            else
                            {
                                Interlocked.Increment(ref failure);
                            }
                        });
                    response = new ResultWithData("HomeAssistant Entity Loading complete. Successful loads: " + success + ". Failed loads: " + failure);
                    break;
                }

                    #endregion
                default:
                    response = new ResultFail()
                    {
                        error = "command \"" + cmd + "\" not supported"
                    };
                    break;
                }
            }
            catch (Exception ex)
            {
                Logger.Debug(ex);
                response = new ResultFail()
                {
                    error = "An unexpected error occurred. " + ex.ToString()
                };
            }
            finally
            {
                if (response == null)
                {
                    response = new ResultFail()
                    {
                        error = "Application Error: A response was not generated, so this response was generated as a fallback."
                    }
                }
                ;
                p.CompressResponseIfCompatible();
                p.writeSuccess(jsonType);
                p.outputStream.Write(JsonConvert.SerializeObject(response));
            }
        }