public KeyStore Sign(KeyUsage usage, int quota, AccountData account, DateTime from, DateTime to)
        {
            var key = new byte[GlobalConfig.TOKEN_LENGTH];

            _cryptoRandom.GetBytes(key);

            if (usage.Usage == 0)
            {
                throw new InvalidOperationException("Key Usage Not Recorded");
            }

            //var keyStore = _context.KeyStore.CreateProxy();
            var keyStore = new KeyStore();

            {
                keyStore.Key = key;
                keyStore.HoldingAccountNavigation = account;
                keyStore.ValidFrom       = from;
                keyStore.ValidUntil      = to;
                keyStore.LastActive      = _time.UtcNow;
                keyStore.UsageNavigation = usage;
                keyStore.ReuseCounter    = -1;
                keyStore.Quota           = quota;
            };

            _context.KeyStore.Add(keyStore);

            _context.SaveChanges();

            _auth.EnsureKey(keyStore, usage, GlobalOperation.GENERATE_APIKEY, 0, "Sign New Key", "N/A");

            return(keyStore);
        }
        public string Sign(TokenPayload payload)
        {
            //var issue = _context.TokenIssueList.CreateProxy();
            var issue = new TokenIssueList();

            {
                issue.HoldingAccount = payload.AccountId;
                issue.Reason         = (int)payload.Purpose;
                issue.IssueTime      = _time.UtcNow;
                issue.ValidUntil     = payload.ValidTo;
            };

            _context.TokenIssueList.Add(issue);

            _context.SaveChanges();

            payload.TokenId = issue.TokenSerial;

            return(_signer.Encode(payload.ToPayloadBytes()));
        }
示例#3
0
        public ActionResult <MilvanethProtocol> SessionCreate(MilvanethProtocol data)
        {
            if (!(data?.Data is AuthRequest request) || !request.Check())
            {
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new AuthResponse
                    {
                        Message = GlobalMessage.DATA_INVALID_INPUT,
                        ReportTime = _time.SafeNow,
                    }
                });
            }

            try
            {
                var key = _context.KeyStore
                          .Include(x => x.HoldingAccountNavigation)
                          .ThenInclude(x => x.PrivilegeLevelNavigation)
                          .Include(x => x.UsageNavigation)
                          .Single(x => x.Key.SequenceEqual(request.AuthToken));

                _auth.EnsureKey(key, new KeyUsage {
                    CreateSession = true
                }, GlobalOperation.SESSION_CREATE, 0, "Create session via session/create",
                                _accessor.GetIp());

                var account = key.HoldingAccountNavigation;

                _auth.EnsureAccount(account, new PrivilegeConfig {
                    AccessData = true
                }, GlobalOperation.SESSION_CREATE, 0,
                                    "Create session via session/create", _accessor.GetIp());

                var renew = _api.Sign(_renewToken, 1, account, _time.UtcNow,
                                      _time.UtcNow.AddSeconds(GlobalConfig.TOKEN_RENEW_LIFE_TIME));

                var access = _token.Sign(new TokenPayload(_time.UtcNow.AddSeconds(GlobalConfig.TOKEN_DATA_LIFE_TIME),
                                                          account.AccountId, TokenPurpose.AccessToken, renew.KeyId));

                _context.SaveChanges();

                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new AuthResponse
                    {
                        Message = GlobalMessage.OK_SUCCESS,
                        ReportTime = _time.SafeNow,
                        RenewToken = renew.Key,
                        SessionToken = access
                    }
                });
            }
            catch (Exception e)
            {
                Log.Error(e, "Error in SESSION/CREATE");
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        Message = GlobalMessage.OP_INVALID,
                        ReportTime = _time.SafeNow,
                    }
                });
            }
        }
        public IEnumerable <RetainerData> CommitRange(long accountId, IEnumerable <RetainerData> data, bool saveChange)
        {
            if (data == null)
            {
                throw new InvalidOperationException();
            }

            var snapshot = data.ToImmutableList();

            if (snapshot.Any(x => x.RetainerId <= 0))
            {
                throw new InvalidOperationException();
            }

            var count = snapshot.Count;

            if (count <= 0)
            {
                return(null);
            }

            if (count == 1)
            {
                return new[] { Commit(accountId, data.Single(), saveChange) }
            }
            ;

            if (count >= 2)
            {
                var search = snapshot.Select(x => x.RetainerId);

                var source       = _context.RetainerData.Where(x => search.Contains(x.RetainerId));
                var sourceMirror = source.AsNoTracking().ToImmutableList();
                var remain       = snapshot.Where(x => sourceMirror.All(y => y.RetainerId != x.RetainerId));
                //var remain = snapshot.Where(x => source.AsNoTracking().All(y => y.RetainerId != x.RetainerId));

                foreach (var entity in source)
                {
                    var delta = snapshot.Single(x => x.RetainerId == entity.RetainerId);
                    if (delta.RetainerName != null && delta.RetainerName != entity.RetainerName)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.RetainerName,
                            ToValue     = delta.RetainerName,
                            Operator    = accountId,
                            RecordId    = entity.RetainerId,
                            TableColumn = GlobalOperation.COLUMN_RETAINER_NAME,
                            ReportTime  = _time.UtcNow
                        });

                        entity.RetainerName = delta.RetainerName;
                    }

                    if (delta.Character != 0 && delta.Character != entity.Character)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.Character.ToString(),
                            ToValue     = delta.Character.ToString(),
                            Operator    = accountId,
                            RecordId    = entity.RetainerId,
                            TableColumn = GlobalOperation.COLUMN_RETAINER_CHARA,
                            ReportTime  = _time.UtcNow
                        });

                        entity.Character = delta.Character;
                    }

                    if (delta.World != 0 && delta.World != entity.World)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.World.ToString(),
                            ToValue     = delta.World.ToString(),
                            Operator    = accountId,
                            RecordId    = entity.RetainerId,
                            TableColumn = GlobalOperation.COLUMN_RETAINER_WORLD,
                            ReportTime  = _time.UtcNow
                        });

                        entity.World = delta.World;
                    }

                    if (delta.Location != 0 && delta.Location != entity.Location)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.Location.ToString(),
                            ToValue     = delta.Location.ToString(),
                            Operator    = accountId,
                            RecordId    = entity.RetainerId,
                            TableColumn = GlobalOperation.COLUMN_RETAINER_LOCATION,
                            ReportTime  = _time.UtcNow
                        });

                        entity.Location = delta.Location;
                    }

                    if (delta.Inventory != null)
                    {
                        entity.Inventory = delta.Inventory;
                    }
                }

                if (remain.Any())
                {
                    _context.RetainerData.AddRange(remain);

                    _context.DataLog.Add(new DataLog
                    {
                        FromValue   = null,
                        ToValue     = "INITIAL COMMIT MULTIPLE",
                        Operator    = accountId,
                        RecordId    = 0,
                        TableColumn = GlobalOperation.COLUMN_RETAINER_NEW,
                        ReportTime  = _time.UtcNow
                    });
                }

                if (saveChange)
                {
                    _context.SaveChanges();
                }

                return(source.Concat(remain));
            }

            return(null);
        }
示例#5
0
        public ActionResult <MilvanethProtocol> AuthStart(MilvanethProtocol data)
        {
            if (!(data?.Data is ClientChallenge challenge) || !challenge.Check())
            {
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        Message = GlobalMessage.DATA_INVALID_INPUT,
                        ReportTime = _time.SafeNow,
                    }
                });
            }

            if (!_pow.Verify(challenge.ProofOfWork) && _pow.ConditionalGenerate(out var requirement))
            {
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        Message = GlobalMessage.RATE_POW_REQUIRED,
                        ProofOfWork = requirement,
                        ReportTime = _time.SafeNow,
                    }
                });
            }

            try
            {
                var accountData = _context.AccountData.Include(x => x.PrivilegeLevelNavigation).SingleOrDefault(x => x.AccountName == challenge.Username);

                if (accountData == null)
                {
                    return(new MilvanethProtocol
                    {
                        Context = null,
                        Data = new ServerChallenge
                        {
                            Message = GlobalMessage.DATA_NO_SUCH_USER,
                            ReportTime = _time.SafeNow,
                        }
                    });
                }

                if (accountData.PrivilegeLevel == GlobalConfig.ACCOUNT_BLOCKED_LEVEL)
                {
                    return(new MilvanethProtocol
                    {
                        Context = null,
                        Data = new ServerChallenge
                        {
                            Message = GlobalMessage.OP_SANCTION,
                            ReportTime = _time.SafeNow,
                        }
                    });
                }

                if (accountData.HasSuspended() && accountData.SuspendUntil >= _time.UtcNow)
                {
                    return(new MilvanethProtocol
                    {
                        Context = null,
                        Data = new ServerChallenge
                        {
                            Message = GlobalMessage.OP_ACCOUNT_SUSPENDED,
                            ReportTime = _time.SafeNow,
                        }
                    });
                }

                if (accountData.PasswordRetry > GlobalConfig.ACCOUNT_PASSWORD_RETRY_TOLERANCE && accountData.LastRetry.HasValue &&
                    (_time.UtcNow - accountData.LastRetry.Value).Seconds < GlobalConfig.ACCOUNT_PASSWORD_RETRY_COOLDOWN)
                {
                    return(new MilvanethProtocol
                    {
                        Context = null,
                        Data = new ServerChallenge
                        {
                            Message = GlobalMessage.OP_PASSWORD_RETRY_TOO_MUCH,
                            ReportTime = _time.SafeNow,
                        }
                    });
                }

                _auth.EnsureAccount(accountData, new PrivilegeConfig {
                    Login = true
                }, GlobalOperation.AUTH_START, 0,
                                    "Start login via auth/start", _accessor.GetIp());

                var session = _srp.DoServerResponse(accountData.AccountId, accountData.GroupParam, accountData.Verifier, out var token);

                _context.AccountData.Update(accountData);

                _context.SaveChanges();

                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        GroupParam = accountData.GroupParam,
                        Message = GlobalMessage.OK_SUCCESS,
                        ReportTime = _time.SafeNow,
                        Salt = accountData.Salt,
                        ServerToken = token,
                        SessionId = session
                    }
                });
            }
            catch (Exception e)
            {
                Log.Error(e, "Error in AUTH/START");
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        Message = GlobalMessage.OP_INVALID,
                        ReportTime = _time.SafeNow,
                    }
                });
            }
        }
示例#6
0
        public ActionResult DataUpload([FromQuery] string token, MilvanethProtocol data)
        {
            if (!_token.TryDecode(token, out var payload))
            {
                return(StatusCode(401));
            }

            if (!(data?.Context).Check() || !(data?.Data is PackedResult result) || !result.Check())
            {
                return(StatusCode(400));
            }

            try
            {
                if (payload.ValidTo < _time.UtcNow)
                {
                    return(StatusCode(511));
                }

                _auth.EnsureToken(payload, TokenPurpose.AccessToken, GlobalOperation.DATA_UPLOAD, 0, out var account);

                // virtual deduction for token validation operation
                var karmaBefore = account.Karma;
                account.Karma -= 20;

                switch (result.Type)
                {
                case PackedResultType.Inventory:
                    var inventory = (InventoryResult)result.Result;

                    if (inventory.Context != data.Context.CharacterId)
                    {
                        break;
                    }

                    _repo.Character.Commit(account.AccountId, new CharacterData
                    {
                        CharacterId = inventory.Context,
                        ServiceId   = data.Context.ServiceId,
                        AccountId   = account.AccountId,
                        Inventory   = LZ4MessagePackSerializer.Serialize(data.Data)
                    }, false);

                    account.Karma += 20;
                    break;

                case PackedResultType.InventoryNetwork:
                    var inventoryNetwork = (InventoryResult)result.Result;
                    _repo.Retainer.Commit(account.AccountId, new RetainerData
                    {
                        RetainerId = inventoryNetwork.Context,
                        Character  = data.Context.CharacterId,
                        World      = data.Context.World,
                        Inventory  = LZ4MessagePackSerializer.Serialize(data.Data)
                    }, false);

                    account.Karma += 20;
                    break;

                case PackedResultType.Artisan:
                    var artisan = (ArtisanResult)result.Result;
                    _repo.Character.CommitRange(account.AccountId, artisan.ArtisanList.Select(x => new CharacterData
                    {
                        CharacterId   = x.CharacterId,
                        CharacterName = x.IsValid ? x.CharacterName : null,
                        HomeWorld     = x.IsValid && !x.FromMemory ? data.Context.World : 0,
                    }), false);

                    account.Karma += 20 + artisan.ArtisanList.Count(x => x.IsValid) * 10 + artisan.ArtisanList.Count(x => !x.IsValid) * 3;
                    break;

                case PackedResultType.MarketHistory:
                    var marketHistory = (MarketHistoryResult)result.Result;
                    _repo.History.CommitRange(data.Context.CharacterId,
                                              marketHistory.HistoryItems.Select(x => x.ToDb(result.ReportTime, data.Context.World)),
                                              false);

                    account.Karma += 20 + 30;
                    break;

                case PackedResultType.MarketListing:
                    var marketListing = (MarketListingResult)result.Result;

                    var artisanFk = marketListing.ListingItems.Select(x => x.ArtisanId);
                    var ownerFk   = marketListing.ListingItems.Select(x => new { x.OwnerId, x.PlayerName }).ToImmutableList();

                    _repo.Character.CommitRange(account.AccountId,
                                                ownerFk.Where(x => x.OwnerId != 0).GroupBy(x => x.OwnerId).Select(y =>
                    {
                        var x = y.First();
                        return(new CharacterData
                        {
                            CharacterId = x.OwnerId,
                            HomeWorld = data.Context.World,
                            CharacterName = x.PlayerName
                        });
                    }),
                                                false);

                    _repo.Character.CommitRange(account.AccountId,
                                                artisanFk.Where(x => x > 0 && ownerFk.All(y => y.OwnerId != x)).Distinct().Select(x => new CharacterData {
                        CharacterId = x
                    }),
                                                true);

                    _repo.Retainer.CommitRange(account.AccountId,
                                               marketListing.ListingItems.GroupBy(x => x.RetainerId).Select(y =>
                    {
                        var x = y.First();
                        return(new RetainerData
                        {
                            RetainerId = x.RetainerId, Character = x.OwnerId, RetainerName = x.RetainerName, Location = x.RetainerLocation, World = data.Context.World
                        });
                    }),
                                               true);

                    _repo.Listing.CommitRange(data.Context.CharacterId,
                                              marketListing.ListingItems.Select(x => x.ToDb(result.ReportTime, data.Context.World)),
                                              false);

                    foreach (var x in marketListing.ListingItems.GroupBy(x => x.ItemId))
                    {
                        _repo.Overview.Commit(data.Context.CharacterId,
                                              new OverviewData
                        {
                            ReportTime  = result.ReportTime,
                            World       = data.Context.World,
                            ItemId      = x.Key,
                            OpenListing = (short)x.Count(),
                        }, false);
                    }


                    account.Karma += 20 + 100;
                    break;

                case PackedResultType.MarketOverview:
                    var marketOverview = (MarketOverviewResult)result.Result;
                    _repo.Overview.CommitRange(data.Context.CharacterId,
                                               marketOverview.ResultItems.Select(x => x.ToDb(result.ReportTime, data.Context.World)),
                                               false);

                    account.Karma += 20 + 30 + marketOverview.ResultItems.Count;
                    break;

                case PackedResultType.RetainerHistory:
                    // todo
                    break;

                case PackedResultType.RetainerList:
                    var retainerList = (RetainerInfoResult)result.Result;
                    _repo.Retainer.CommitRange(account.AccountId,
                                               retainerList.RetainerInfo.Select(x => x.ToDb(data.Context.CharacterId, data.Context.World)), false);

                    account.Karma += 20 + retainerList.RetainerInfo.Count * 4;
                    break;

                case PackedResultType.RetainerUpdate:
                    #region NotFinishedCode
                    // todo

                    // 目前有两种方案,直接更新和Copy-on-Update,前者的主要问题在于并发条件下Time-Bucket体系可能会出现问题,后者则在于性能开销,故目前暂不对此数据进行处理

                    //var retainerUpdate = (RetainerUpdateResult)result.Result;

                    //foreach (var item in retainerUpdate.UpdateItems)
                    //{
                    //    var record = _context.ListingData
                    //        .Where(x => x.RetainerId == item.RetainerId && x.ContainerId == (short)item.ContainerId && x.SlotId == item.ContainerSlot)
                    //        .OrderByDescending(x => x.ReportTime).Take(1);

                    //    if (!record.Any())
                    //    {
                    //        var retInfo =
                    //            _context.RetainerData.SingleOrDefault(x => x.RetainerId == item.RetainerId);

                    //        var record2 = _context.ListingData.Where(x =>
                    //                x.World == data.Context.World && x.ItemId == item.ItemInfo.ItemId &&
                    //                x.ReportTime <= result.ReportTime)
                    //            .OrderByDescending(x => x.ReportTime).Take(1);

                    //        _repo.Commit(data.Context.CharacterId, new ListingData
                    //        {
                    //            BucketId = record2.Any() ? record2.First().BucketId : Guid.Empty,
                    //            ReportTime = result.ReportTime,
                    //            World = data.Context.World,
                    //            ReporterId = data.Context.CharacterId,
                    //            ListingId = 0,
                    //            RetainerId = item.RetainerId,
                    //            OwnerId = data.Context.CharacterId,
                    //            ArtisanId = item.ItemInfo.ArtisanId,
                    //            UnitPrice = item.NewPrice,
                    //            TotalTax = 0,
                    //            Quantity = item.ItemInfo.Amount,
                    //            ItemId = item.ItemInfo.ItemId,
                    //            UpdateTime = Helper.DateTimeToUnixTimeStamp(result.ReportTime),
                    //            ContainerId = (short)item.ContainerId,
                    //            SlotId = (short)item.ContainerSlot,
                    //            Condition = (short)item.ItemInfo.Durability,
                    //            SpiritBond = (short)item.ItemInfo.SpiritBond,
                    //            Materia1 = item.ItemInfo.Materia1,
                    //            Materia2 = item.ItemInfo.Materia2,
                    //            Materia3 = item.ItemInfo.Materia3,
                    //            Materia4 = item.ItemInfo.Materia4,
                    //            Materia5 = item.ItemInfo.Materia5,
                    //            RetainerName = retInfo?.RetainerName,
                    //            PlayerName = item.ContainerId == InventoryContainerId.HIRE_LISTING ? null : _context.CharacterData.SingleOrDefault(x => x.CharacterId == data.Context.CharacterId)?.CharacterName,
                    //            IsHq = item.ItemInfo.IsHq,
                    //            MateriaCount = 0, //todo
                    //            OnMannequin = item.ContainerId != InventoryContainerId.HIRE_LISTING,
                    //            RetainerLoc = 0,//todo
                    //            DyeId = item.ItemInfo.DyeId
                    //        }, true);

                    //        account.Karma += 25;
                    //        continue;
                    //    }

                    //    var recordEntity = record.First();

                    //    if (recordEntity.ReportTime >= result.ReportTime)
                    //    {
                    //        account.Karma -= 25;
                    //        continue;
                    //    }

                    //    recordEntity.
                    //}

                    //account.Karma += 20 + retainerUpdate.UpdateItems.Count * 25;

                    #endregion

                    account.Karma += 20;
                    break;

                case PackedResultType.Status:
                    var status = (StatusResult)result.Result;

                    if (status.CharacterId != data.Context.CharacterId)
                    {
                        break;
                    }

                    if (account.PlayedCharacter == null)
                    {
                        account.PlayedCharacter = new long[0];
                    }

                    if (!account.PlayedCharacter.Contains(status.CharacterId))
                    {
                        var temp = new long[account.PlayedCharacter.Length + 1];
                        Array.Copy(account.PlayedCharacter, temp, account.PlayedCharacter.Length);
                        temp[temp.Length - 1]   = status.CharacterId;
                        account.PlayedCharacter = temp;
                    }

                    _repo.Character.Commit(account.AccountId, new CharacterData
                    {
                        CharacterId   = status.CharacterId,
                        CharacterName = status.CharacterName,
                        ServiceId     = data.Context.ServiceId,
                        AccountId     = account.AccountId,
                        HomeWorld     = status.CharacterHomeWorld,
                        JobLevels     = status.LevelInfo.ToDb(),
                        GilHold       = status.CharaInfo.GilHold
                    }, false);

                    account.Karma += 20 + 40;

                    break;

                case PackedResultType.LobbyService:
                    var lobbyService = (LobbyServiceResult)result.Result;

                    if (lobbyService.ServiceId != data.Context.ServiceId)
                    {
                        break;
                    }

                    if (account.RelatedService == null)
                    {
                        account.RelatedService = new long[0];
                    }

                    if (!account.RelatedService.Contains(lobbyService.ServiceId))
                    {
                        var temp = new long[account.RelatedService.Length + 1];
                        Array.Copy(account.RelatedService, temp, account.RelatedService.Length);
                        temp[temp.Length - 1]  = lobbyService.ServiceId;
                        account.RelatedService = temp;
                    }

                    account.Karma += 20;
                    break;

                case PackedResultType.LobbyCharacter:
                    var lobbyCharacter = (LobbyCharacterResult)result.Result;
                    if (!DataChecker.CheckOnlineCharacterBinding(data.Context.ServiceId,
                                                                 lobbyCharacter.CharacterItems))
                    {
#warning api availability is not checked.
                        account.Karma -= 180;
                        break;
                    }

                    if (account.RelatedService == null)
                    {
                        account.RelatedService = new long[0];
                    }

                    if (!account.RelatedService.Contains(data.Context.ServiceId))
                    {
                        var temp = new long[account.RelatedService.Length + 1];
                        Array.Copy(account.RelatedService, temp, account.RelatedService.Length);
                        temp[temp.Length - 1]  = data.Context.ServiceId;
                        account.RelatedService = temp;
                    }

                    _repo.Character.CommitRange(account.AccountId, lobbyCharacter.CharacterItems.Select(x => x.ToDb(data.Context.ServiceId)), false);

                    account.Karma += 20 + 20 * lobbyCharacter.CharacterItems.Count;
                    break;

                default:
                    // do nothing
                    break;
                }

                _context.KarmaLog.Add(new KarmaLog
                {
                    ReportTime = _time.UtcNow,
                    AccountId  = account.AccountId,
                    Reason     = GlobalOperation.DATA_UPLOAD + (int)result.Type,
                    Before     = karmaBefore,
                    After      = account.Karma
                });

                _context.AccountData.Update(account);
                _context.SaveChanges();

                return(StatusCode(200));
            }
            catch (Exception e)
            {
                Log.Error(e, "Error in DATA/UPLOAD");
                return(StatusCode(500));
            }
        }
        public IEnumerable <CharacterData> CommitRange(long accountId, IEnumerable <CharacterData> data, bool saveChange)
        {
            if (data == null)
            {
                throw new InvalidOperationException();
            }

            var snapshot = data.ToImmutableList();

            if (snapshot.Any(x => x.CharacterId <= 0))
            {
                throw new InvalidOperationException();
            }

            var count = snapshot.Count;

            if (count <= 0)
            {
                return(null);
            }

            if (count == 1)
            {
                return new[] { Commit(accountId, snapshot.Single(), saveChange) }
            }
            ;

            if (count >= 2)
            {
                var search = snapshot.Select(x => x.CharacterId);

                var source       = _context.CharacterData.Where(x => search.Contains(x.CharacterId));
                var sourceMirror = source.AsNoTracking().ToImmutableList();
                var remain       = snapshot.Where(x => sourceMirror.All(y => y.CharacterId != x.CharacterId));
                //var remain = snapshot.Where(x => source.AsNoTracking().All(y => y.CharacterId != x.CharacterId));

                foreach (var entity in source)
                {
                    var delta = snapshot.Single(x => x.CharacterId == entity.CharacterId);
                    if (delta.CharacterName != null && delta.CharacterName != entity.CharacterName)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.CharacterName,
                            ToValue     = delta.CharacterName,
                            Operator    = accountId,
                            RecordId    = entity.CharacterId,
                            TableColumn = GlobalOperation.COLUMN_CHARACTER_NAME,
                            ReportTime  = _time.UtcNow
                        });

                        entity.CharacterName = delta.CharacterName;
                    }

                    if (delta.AccountId != 0 && delta.AccountId != entity.AccountId)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.AccountId.ToString(),
                            ToValue     = delta.AccountId.ToString(),
                            Operator    = accountId,
                            RecordId    = entity.CharacterId,
                            TableColumn = GlobalOperation.COLUMN_CHARACTER_ACCOUNT,
                            ReportTime  = _time.UtcNow
                        });

                        entity.AccountId = delta.AccountId;
                    }

                    if (delta.ServiceId != 0 && delta.ServiceId != entity.ServiceId)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.ServiceId.ToString(),
                            ToValue     = delta.ServiceId.ToString(),
                            Operator    = accountId,
                            RecordId    = entity.CharacterId,
                            TableColumn = GlobalOperation.COLUMN_CHARACTER_SERVICE,
                            ReportTime  = _time.UtcNow
                        });

                        entity.ServiceId = delta.ServiceId;
                    }

                    if (delta.HomeWorld != 0 && delta.HomeWorld != entity.HomeWorld)
                    {
                        _context.DataLog.Add(new DataLog
                        {
                            FromValue   = entity.HomeWorld.ToString(),
                            ToValue     = delta.HomeWorld.ToString(),
                            Operator    = accountId,
                            RecordId    = entity.CharacterId,
                            TableColumn = GlobalOperation.COLUMN_CHARACTER_WORLD,
                            ReportTime  = _time.UtcNow
                        });

                        entity.HomeWorld = delta.HomeWorld;
                    }

                    if (delta.RetainerList != null && !delta.RetainerList.SequenceEqual(entity.RetainerList))
                    {
                        entity.RetainerList = delta.RetainerList;
                    }

                    if (delta.JobLevels != null && !delta.JobLevels.SequenceEqual(entity.JobLevels))
                    {
                        entity.JobLevels = delta.JobLevels;
                    }

                    if (delta.Inventory != null)
                    {
                        entity.Inventory = delta.Inventory;
                    }

                    if (delta.GilHold != null)
                    {
                        entity.GilHold = delta.GilHold;
                    }

                    _context.CharacterData.Update(entity);
                }

                if (remain.Any())
                {
                    _context.CharacterData.AddRange(remain);

                    _context.DataLog.Add(new DataLog
                    {
                        FromValue   = null,
                        ToValue     = "INITIAL COMMIT MULTIPLE",
                        Operator    = accountId,
                        RecordId    = 0,
                        TableColumn = GlobalOperation.COLUMN_CHARACTER_NEW,
                        ReportTime  = _time.UtcNow
                    });
                }

                if (saveChange)
                {
                    _context.SaveChanges();
                }

                return(source.Concat(remain));
            }

            return(null);
        }
示例#8
0
        public ActionResult <MilvanethProtocol> AccountCreate(MilvanethProtocol data)
        {
            if (!(data?.Data is RegisterForm form) || !form.Check())
            {
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        Message = GlobalMessage.DATA_INVALID_INPUT,
                        ReportTime = _time.SafeNow,
                    }
                });
            }

            if (!_pow.Verify(form.ProofOfWork))
            {
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        Message = GlobalMessage.RATE_POW_REQUIRED,
                        ProofOfWork = _pow.Generate((byte)Math.Max(GlobalConfig.POW_SENSITIVE_OPERATION, _pow.Difficulty)),
                        ReportTime = _time.SafeNow,
                    }
                });
            }

            try
            {
                if (_context.AccountData.Any(x => x.AccountName == form.Username))
                {
                    return(new MilvanethProtocol
                    {
                        Context = null,
                        Data = new ServerChallenge
                        {
                            Message = GlobalMessage.DATA_USERNAME_OCCUPIED,
                            ReportTime = _time.SafeNow,
                        }
                    });
                }

                //var accountData = _context.AccountData.CreateProxy();
                var accountData = new AccountData();
                {
                    accountData.AccountName              = form.Username;
                    accountData.DisplayName              = form.DisplayName;
                    accountData.Email                    = form.Email;
                    accountData.EmailConfirmed           = false;
                    accountData.Salt                     = form.Salt;
                    accountData.Verifier                 = form.Verifier;
                    accountData.GroupParam               = (short)form.GroupParam;
                    accountData.RegisterService          = form.Service.ServiceId;
                    accountData.RelatedService           = new long[] { form.Service.ServiceId };
                    accountData.PlayedCharacter          = null;
                    accountData.Trace                    = form.Trace;
                    accountData.Karma                    = 0;
                    accountData.PrivilegeLevelNavigation = _userPrivilege;
                    accountData.SuspendUntil             = null;
                    accountData.PasswordRetry            = 0;
                    accountData.LastRetry                = DateTime.UtcNow;
                }

                _context.AccountData.Add(accountData);

                _context.SaveChanges();

                _repo.Character.CommitRange(accountData.AccountId, form.Character.CharacterItems.Select(x => x.ToDb(accountData.RegisterService)), true);

                _auth.EnsureAccount(accountData, new PrivilegeConfig {
                    Login = true
                }, GlobalOperation.ACCOUNT_CREATE, GlobalConfig.USER_INITIAL_KARMA,
                                    "Registered new account via account/create", _accessor.GetIp());

                var session = _srp.DoServerResponse(accountData.AccountId, accountData.GroupParam, accountData.Verifier, out var token);

                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        GroupParam = accountData.GroupParam,
                        Message = GlobalMessage.OK_SUCCESS,
                        ReportTime = _time.SafeNow,
                        Salt = accountData.Salt,
                        ServerToken = token,
                        SessionId = session
                    }
                });
            }
            catch (Exception e)
            {
                Log.Error(e, "Error in ACCOUNT/CREATE");
                return(new MilvanethProtocol
                {
                    Context = null,
                    Data = new ServerChallenge
                    {
                        Message = GlobalMessage.OP_INVALID,
                        ReportTime = _time.SafeNow,
                    }
                });
            }
        }