예제 #1
0
        /// <summary> Connected database service </summary>

        /// <summary> Client -> Server RPC. Checks user and credentials to validate login, responds with <see cref="LoginResponse(RPCMessage)"/></summary>
        /// <param name="msg"> RPC Info. </param>
        public void Login(RPCMessage msg)
        {
#if !UNITY
            string user    = msg[0];
            string hash    = msg[1];
            string version = msg.numArgs >= 3 ? msg[2] : "[[Version Not Set]]";
            // Login flow.
            Credentials   creds    = null;
            LoginResult   result   = LoginResult.Failed_Unspecified;
            string        reason   = "none";
            UserLoginInfo userInfo = null;

            #region Submethod CheckLogin()
            {             // SubMethod: CheckLogin()
                if (version != versionCode)
                {
                    Log.Debug($"{nameof(LoginService)}: Version mismatch {version}, expected {versionCode}");
                    reason = VERSION_MISMATCH;
                    result = LoginResult.Failed_VersionMismatch;
                }
                else if (!usernameValidator(user))
                {
                    Log.Debug($"{nameof(LoginService)}: Bad username {user}");
                    reason = "Invalid Username";
                    result = LoginResult.Failed_BadUsername;
                }
                else if (GetLogin(msg.sender) != null)
                {
                    Log.Debug($"{nameof(LoginService)}: Client {msg.sender.identity} already logged in");
                    reason = "Already Logged In";
                    result = LoginResult.Failed_ClientAlreadyLoggedIn;
                }
                else
                {
                    userInfo = dbService.Get <UserLoginInfo>(nameof(userInfo.userName), user);

                    if (userInfo == null)
                    {
                        Log.Debug($"{nameof(LoginService)}: User {user} not found, creating them now. ");

                        Guid userId = Guid.NewGuid();
                        userInfo = CreateNewUser(msg);

                        if (userInfo != null)
                        {
                            result = LoginResult.Success_Created;
                            creds  = new Credentials(user, hash, userInfo.guid);
                        }
                        else
                        {
                            result = LoginResult.Failed_CreationCooldown;
                            reason = "Too many account creations";
                        }
                    }
                    else
                    {
                        // Check credentials against existing credentials.
                        if (loginsByUserId.ContainsKey(userInfo.guid))
                        {
                            reason = "Already logged in";
                            result = LoginResult.Failed_UserAlreadyLoggedIn;
                        }
                        else if (hash != userInfo.hash)
                        {
                            reason = "Bad credentials";
                            result = LoginResult.Failed_BadCredentials;
                        }
                        else
                        {
                            creds  = new Credentials(user, hash, userInfo.guid);
                            result = LoginResult.Success;
                        }
                    }
                }
            }             // Submethod: CheckLogin()
            #endregion

            #region Submethod RecordLoginAttempt
            {             // SubMethod: RecordLoginAttempt()
                LoginAttempt attempt = new LoginAttempt();
                attempt.result      = result;
                attempt.result_desc = result.ToString();
                attempt.timestamp   = DateTime.UtcNow;
                attempt.hash        = hash;
                attempt.userName    = user;
                attempt.ip          = msg.sender.remoteIP;
                if (userInfo != null)
                {
                    attempt.success  = true;
                    attempt.creation = result == LoginResult.Success_Created;
                    attempt.guid     = userInfo.guid;
                }
                else
                {
                    attempt.success = attempt.creation = false;
                    attempt.guid    = Guid.Empty;
                }

                dbService.Save(attempt);
            }             // Submethod: RecordLoginAttempt()
            #endregion

            #region Submethod Respond
            {            // Submethod: Respond()
                if (creds == null)
                {
                    msg.sender.Call(LoginResponse, "fail", reason);

                    Log.Info($"Client {msg.sender.identity} Failed to login.");

                    server.On(new LoginFailure_Server()
                    {
                        ip = msg.sender.remoteIP
                    });
                }
                else
                {
                    var session = new Session(msg.sender, creds);
                    loginsByClient[msg.sender]   = session;
                    loginsByUserId[creds.userId] = session;

                    userInfo.lastLogin = DateTime.UtcNow;
                    dbService.Save(userInfo);

                    msg.sender.Call(LoginResponse, "succ", creds.userId);

                    Log.Info($"Client {msg.sender.identity} logged in as user {creds.username} / {creds.userId}. ");

                    server.On(new LoginSuccess_Server(msg.sender));
                }
            }             // Submethod: Respond()
            #endregion
#endif
        }
예제 #2
0
 public Session(Client client, Credentials credentials)
 {
     this.client      = client;
     this.credentials = credentials;
 }