public IActionResult Modify([FromQuery] int id, [FromBody] PostModifyDto data) { if (string.IsNullOrEmpty(data.Content)) { return(BadRequest()); } var userId = ClaimsReader.GetUserId(Request); var post = context.Posts.FirstOrDefault(a => a.Id == id && a.UserId == userId); if (post == null) { return(NotFound()); } post.EditDate = DateTime.UtcNow; post.Content = data.Content; try { context.SaveChanges(); return(Ok(new { post.EditDate })); } catch (Exception) { return(BadRequest()); } }
public async Task <IActionResult> RegisteredZoneCheckin([FromBody] ZoneServerCheckinRequestModel zoneCheckinRequest) { //This is ok, it means the zone was unregistered before the checkin message was recieved. //It doesn't alone indicate a failure. if (!await ZoneRepository.ContainsAsync(ClaimsReader.GetAccountIdInt(User))) { if (Logger.IsEnabled(LogLevel.Warning)) { Logger.LogWarning($"UserId: {ClaimsReader.GetPlayerAccountId(User)} attempted to checkin ZoneId: {ClaimsReader.GetAccountId(User)} but the zone was not registered."); } return(Ok()); } ZoneInstanceEntryModel model = await ZoneRepository.RetrieveAsync(ClaimsReader.GetAccountIdInt(User)); //We don't REMOVE if expired. This should only update checkin time //something else should be responsible for removal if expired at some point. model.UpdateCheckinTime(); await ZoneRepository.UpdateAsync(model.ZoneId, model); //We don't really have anything to reply to, this shouldn't be called externally. //It's basically handling a proxied message queue message. return(Ok()); }
CreateCharacterAsync([FromBody] RPGCharacterCreationRequest <TRaceType, TClassType> request, CancellationToken token = default) { //TODO: Fix GetAccountId API int accountId = ClaimsReader.GetAccountId <int>(User); if (!ModelState.IsValid) { return(Failure <RPGCharacterCreationResult, CharacterCreationResponseCode>(CharacterCreationResponseCode.GeneralError)); } //TODO: Add validation pipeline. if (String.IsNullOrWhiteSpace(request.Name)) { return(Failure <RPGCharacterCreationResult, CharacterCreationResponseCode>(CharacterCreationResponseCode.InvalidName)); } try { DBRPGCharacter character = await CharacterRepository.CreateCharacterAsync(accountId, request.Name, request.Race, request.ClassType, token); return(Success <RPGCharacterCreationResult, CharacterCreationResponseCode>(new RPGCharacterCreationResult(character.Id))); } catch (Exception e) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create Character: {request} Reason: {e}"); } return(Failure <RPGCharacterCreationResult, CharacterCreationResponseCode>(CharacterCreationResponseCode.GeneralError)); } }
public IActionResult ResolveApplication([FromBody] GroupAccessAcceptanceDto data) { var userId = ClaimsReader.GetUserId(Request); if (!CheckAdminPriviliges(userId, data.GroupId)) { return(BadRequest()); } var targetId = context.Users.SingleOrDefault(a => a.Id == data.UserId).Id; var group = context.Groups.SingleOrDefault(a => a.Id == data.GroupId); var connection = context.UserGroups.SingleOrDefault(a => a.UserId == targetId && a.GroupId == data.GroupId); if (data.Accepted) { connection.Relation = GroupRelation.User; } else { context.UserGroups.Remove(connection); } try { context.SaveChanges(); return(Ok()); } catch (Exception) { return(BadRequest()); } }
public async Task <CharacterListResponse> GetCharacters() { int accountId = ClaimsReader.GetUserIdInt(User); //So to check characters we just need to query for the //characters with this account id int[] characterIds = await CharacterRepository.CharacterIdsForAccountId(accountId); #warning This is just for the test build, we need to change this ProjectVersionStage.AssertInternalTesting(); if (characterIds.Length == 0) { //We just create a new one for testing. bool result = await CharacterRepository.TryCreateAsync(new CharacterEntryModel(accountId, ClaimsReader.GetUserName(User))) .ConfigureAwait(false); if (result) { //Just return the get, a character should now exist. return(await GetCharacters()); } else { return(new CharacterListResponse(CharacterListResponseCode.NoCharactersFoundError)); } } /*if(characterIds.Length == 0) * return new CharacterListResponse(CharacterListResponseCode.NoCharactersFoundError);*/ //The reason we only provide the IDs is all other character data can be looked up //by the client when it needs it. Like name query, visible/character details/look stuff. //No reason to send all this data when they may only need names. Which can be queried through the known API return(new CharacterListResponse(characterIds)); }
public IActionResult GetAdminGroupDetails([FromQuery] int id) { var userId = ClaimsReader.GetUserId(Request); if (!CheckAdminPriviliges(userId, id)) { return(BadRequest()); } var group = context.Groups .Include(a => a.Users) .ThenInclude(a => a.User) .FirstOrDefault(a => a.Id == id); var result = new GroupAdminDetailsDto { Name = group.Name, Description = group.Description, IsPrivate = group.IsPrivate, Candidates = group.Users .Where(a => a.Relation == GroupRelation.Requesting) .Select(a => new GroupCandidateDto { UserId = a.UserId, UserLogin = a.User.Login }).ToList() }; return(Ok(result)); }
public IActionResult Modify([FromBody] GroupModifyDto data) { var userId = ClaimsReader.GetUserId(Request); if (!context.UserGroups.Any(a => a.GroupId == data.Id && a.UserId == userId && a.Relation == GroupRelation.Owner)) { return(BadRequest()); } var group = context.Groups.FirstOrDefault(a => a.Id == data.Id); group.Name = data.Name; group.Description = data.Description; group.IsPrivate = data.IsPrivate; try { context.SaveChanges(); return(Ok()); } catch (Exception) { return(BadRequest()); } }
public async Task <int> RetrieveAuthorizedCharacterAsync(CancellationToken token = default) { //Idea here is that a principal used for authorization may contain the claim for //the subaccount id. The subaccount id is to be treated as the character id //in our backend. return(ClaimsReader.GetCharacterId(User)); }
public IActionResult AskForInvite([FromBody] GroupInviteDto data) { var userId = ClaimsReader.GetUserId(Request); var group = context.Groups.SingleOrDefault(a => a.Id == data.Id); if (group == null) { return(NotFound()); } var connection = new UserGroup { UserId = userId, GroupId = group.Id, Relation = group.IsPrivate ? GroupRelation.Requesting : GroupRelation.User }; context.UserGroups.Add(connection); try { context.SaveChanges(); return(Ok()); } catch (Exception) { return(BadRequest()); } }
public IActionResult ResolveGroupInvite([FromBody] GroupInviteResolveDto data) { var userId = ClaimsReader.GetUserId(Request); var connection = context.UserGroups.SingleOrDefault(a => a.UserId == userId && a.GroupId == data.Id); if (data.Value) { connection.Relation = GroupRelation.User; } else { context.UserGroups.Remove(connection); } try { context.SaveChanges(); return(Ok()); } catch (Exception) { return(BadRequest()); } }
public IActionResult Get([FromQuery] GroupQueryDto query) { var userId = ClaimsReader.GetUserId(Request); if (!context.UserGroups.Any(a => a.GroupId == query.GroupId && a.UserId == userId && (a.Relation == GroupRelation.Owner || a.Relation == GroupRelation.User))) { return(BadRequest()); } var result = context.Posts .Where(a => a.GroupId == query.GroupId) .OrderByDescending(a => a.DateAdded) .ThenBy(a => a.DateAdded) .Skip(query.PageSize * (query.Page - 1)) .Take(query.PageSize) .Select(a => new PostDto { Id = a.Id, DateAdded = a.DateAdded, Content = a.Content, EditDate = a.EditDate, IsOwner = a.UserId == userId, Owner = a.User.Login, Comments = a.Comments.OrderBy(b => b.DateAdded).Select(b => new CommentDto { Id = b.Id, DateAdded = b.DateAdded, Content = b.Content, IsOwner = b.UserId == userId, Owner = b.User.Login }).ToList() }).ToList(); return(Ok(result)); }
/// <inheritdoc /> public override async Task OnConnectedAsync() { await base.OnConnectedAsync() .ConfigureAwaitFalseVoid(); if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Account Connected: {ClaimsReader.GetAccountName(Context.User)}:{ClaimsReader.GetAccountId(Context.User)} with SignalR UserId: {Context.UserIdentifier}"); } try { foreach (var listener in OnConnectionHubListeners) { HubOnConnectionState connectionState = await listener.OnConnected(this).ConfigureAwaitFalse(); //if the listener indicated we need to abort for whatever reason we //should believe it and just abort. if (connectionState == HubOnConnectionState.Abort) { Context.Abort(); break; } } } catch (Exception e) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Account: {ClaimsReader.GetAccountName(Context.User)}:{ClaimsReader.GetAccountId(Context.User)} failed to properly connect to hub. Error: {e.ToString()}\n\nStack: {e.StackTrace}"); } Context.Abort(); } }
public async Task <IActionResult> RequestWorldDownloadUrl( [FromRoute(Name = "id")] long worldId, [FromServices] IWorldEntryRepository worldEntryRepository, [FromServices] IStorageUrlBuilder urlBuilder, [FromServices] IContentDownloadAuthroizationValidator downloadAuthorizer) { if (worldEntryRepository == null) { throw new ArgumentNullException(nameof(worldEntryRepository)); } //TODO: We want to rate limit access to this API //TODO: We should use both app logging but also another logging service that always gets hit //TODO: Consolidate this shared logic between controllers if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Recieved {nameof(RequestWorldDownloadUrl)} request from {ClaimsReader.GetUserName(User)}:{ClaimsReader.GetUserId(User)}."); } //TODO: We should probably check the flags of world to see if it's private (IE hidden from user). Or if it's unlisted or removed. //It's possible a user is requesting a world that doesn't exist //Could be malicious or it could have been deleted for whatever reason if (!await worldEntryRepository.ContainsAsync(worldId).ConfigureAwait(false)) { return(Json(new ContentDownloadURLResponse(ContentDownloadURLResponseCode.NoContentId))); } //TODO: Refactor this into a validation dependency //Now we need to do some validation to determine if they should even be downloading this world //we do not want people downloading a world they have no business of going to int userId = ClaimsReader.GetUserIdInt(User); if (!await downloadAuthorizer.CanUserAccessWorldContet(userId, worldId)) { return(Json(new ContentDownloadURLResponse(ContentDownloadURLResponseCode.AuthorizationFailed))); } //We can get the URL from the urlbuilder if we provide the world storage GUID string downloadUrl = await urlBuilder.BuildRetrivalUrl(UserContentType.World, (await worldEntryRepository.RetrieveAsync(worldId)).StorageGuid); //TODO: Should we be validating S3 availability? if (String.IsNullOrEmpty(downloadUrl)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create world upload URL for {ClaimsReader.GetUserName(User)}:{ClaimsReader.GetUserId(User)} with ID: {worldId}."); } return(Json(new ContentDownloadURLResponse(ContentDownloadURLResponseCode.ContentDownloadServiceUnavailable))); } if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Success. Sending {ClaimsReader.GetUserName(User)} URL: {downloadUrl}"); } return(Json(new ContentDownloadURLResponse(downloadUrl))); }
public async Task <JsonResult> GetToken(bool regenerateToken = false) { var user = await this.userService.GetUserByEmailAsync(ClaimsReader.ReadEmail(this.User)); var token = await this.tokenService.GetLongLivedUserToken(user, regenerateToken); return(Json(token)); }
/// <summary> /// Indicates if the provided character id is valid for the user in the message context. /// </summary> /// <param name="characterId">The id to check.</param> /// <param name="characterRepository">The character repository service.</param> /// <returns>True if the character id is valid/</returns> private async Task<bool> IsCharacterIdValidForUser(int characterId, ICharacterRepository characterRepository) { //We only support positive character ids so if they request a less than 0 it's invalid and likely spoofed //or if they request an id they don't own //or if it's an not a known character return characterId >= 0 && await characterRepository.ContainsAsync(characterId) && (await characterRepository.RetrieveAsync(characterId)).AccountId == ClaimsReader.GetAccountIdInt(User); }
public async Task <CharacterSessionDataResponse> GetCharacterSessionData([FromRoute(Name = "id")] int characterId) { int accountId = ClaimsReader.GetUserIdInt(User); //TODO: Do we want to expose this to non-controlers? //First we should validate that the account that is authorized owns the character it is requesting session data from return(await RetrieveSessionDataIfAvailable(characterId, accountId) .ConfigureAwait(false)); }
/// <inheritdoc /> public async Task <HubOnConnectionState> OnConnected([JetBrains.Annotations.NotNull] Hub hubConnectedTo) { if (hubConnectedTo == null) { throw new ArgumentNullException(nameof(hubConnectedTo)); } //We should never be here unless auth worked //so we can assume that and just try to request character session data //for the account. CharacterSessionDataResponse characterSessionDataResponse = await SocialToGameClient.GetCharacterSessionDataByAccount(ClaimsReader.GetUserIdInt(hubConnectedTo.Context.User)) .ConfigureAwait(false); //TODO: To support website chat we shouldn't disconnect just because they don't have a zone session. //If the session data request fails we should just abort //and disconnect, the user shouldn't be connecting if (!characterSessionDataResponse.isSuccessful) { if (Logger.IsEnabled(LogLevel.Warning)) { Logger.LogWarning($"Failed to Query SessionData for AccountId: {ClaimsReader.GetUserId(hubConnectedTo.Context.User)} Reason: {characterSessionDataResponse.ResultCode}"); } //TODO: Eventually we don't want to do this. return(HubOnConnectionState.Abort); } //This is ABSOLUTELY CRITICAL we need to validate that the character header they sent actually //is the character they have a session as //NOT CHECKING THIS IS EQUIVALENT TO LETTING USERS PRETEND THEY ARE ANYONE! if (hubConnectedTo.Context.UserIdentifier != characterSessionDataResponse.CharacterId.ToString()) { //We can log account name and id here, because they were successfully authed. if (Logger.IsEnabled(LogLevel.Warning)) { Logger.LogWarning($"User with AccountId: {ClaimsReader.GetUserName(hubConnectedTo.Context.User)}:{ClaimsReader.GetUserId(hubConnectedTo.Context.User)} attempted to spoof as CharacterId: {hubConnectedTo.Context.UserIdentifier} but had session for CharacterID: {characterSessionDataResponse.CharacterId}."); } return(HubOnConnectionState.Abort); } if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Recieved SessionData: Id: {characterSessionDataResponse.CharacterId} ZoneId: {characterSessionDataResponse.ZoneId}"); } //Registers for lookup so that we can tell where a connection is zone-wise. ZoneLookupService.Register(hubConnectedTo.Context.ConnectionId, characterSessionDataResponse.ZoneId); //TODO: We should have group name builders. Not hardcoded //Join the zoneserver's chat channel group await hubConnectedTo.Groups.AddToGroupAsync(hubConnectedTo.Context.ConnectionId, $"zone:{characterSessionDataResponse.ZoneId}", hubConnectedTo.Context.ConnectionAborted) .ConfigureAwait(false); return(HubOnConnectionState.Success); }
/// <summary> /// Verifies that the provided <see cref="characterId"/> /// is owned by the current User claim. /// </summary> /// <param name="characterId"></param> /// <returns></returns> public async Task <bool> VerifyCharacterOwnedByAccount(int characterId) { int accountId = ClaimsReader.GetUserIdInt(User); //TODO: Do we want to expose this to non-controlers? //First we should validate that the account that is authorized owns the character it is requesting session data from return((await CharacterRepository.CharacterIdsForAccountId(accountId).ConfigureAwait(false)) .Contains(characterId)); }
public async Task <RPGCharacterData <TRaceType, TClassType>[]> RetrieveCharactersDataAsync(CancellationToken token = default) { //TODO: Fix GetAccountId API int accountId = ClaimsReader.GetAccountId <int>(User); return((await CharacterRepository .RetrieveOwnedCharactersAsync(accountId, token)) .Select(ConvertDbToTransit) .ToArray()); }
public async Task <int[]> RetrieveCharacterBasicListAsync(CancellationToken token = default) { //TODO: Properly handle failure and return correct response codes. int accountId = ClaimsReader.GetAccountId <int>(User); return((await CharacterRepository .RetrieveOwnedCharactersAsync(accountId, token)) .Select(d => d.Character.Id) .OrderBy(i => i) .ToArray()); }
public IActionResult GetProfile() { var userId = ClaimsReader.GetUserId(HttpContext.Request); var user = context.Users.SingleOrDefault(x => x.Id == userId); return(Ok(new UserProfileDto { Login = user.Login, Email = user.Email, ReceiveNotifications = user.ReceiveNotifications })); }
private async Task <bool> CheckZoneAuthorizedToModifyCharacterData(int characterId) { if (!await CharacterSessionRepository.CharacterHasActiveSession(characterId)) { return(false); } CharacterSessionModel model = await CharacterSessionRepository.RetrieveAsync(characterId); //If they aren't in this zone we shouldn't be allowed to save it. return(ClaimsReader.GetAccountIdInt(User) == model.ZoneId); }
public async Task <IActionResult> CreateZoneServerAccount([FromBody][JetBrains.Annotations.NotNull] ZoneServerAccountRegistrationRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } //We want to log this out for information purposes whenever an auth request begins if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Zone Register Request by UserAccount: {ClaimsReader.GetAccountName(this.User)}:{ClaimsReader.GetAccountIdInt(this.User)} {HttpContext.Connection.RemoteIpAddress}:{HttpContext.Connection.RemotePort}"); } //TODO: Create cryptographically secure random bytes for password and user. string zoneUserName = Guid.NewGuid().ToString(); string zonePassword = Guid.NewGuid().ToString(); ZoneServerApplicationUser user = new ZoneServerApplicationUser(ClaimsReader.GetAccountIdInt(this.User)) { UserName = zoneUserName, Email = "*****@*****.**", //TODO: Real email??? }; IdentityResult identityResult = await UserManager.CreateAsync(user, zonePassword); if (identityResult.Succeeded) { //Adds the vrgid account owner claim. await UserManager.AddClaimAsync(user, new Claim(GladMMOAuthConstants.ACCOUNT_ID_OWNER_CLAIM_NAME, ClaimsReader.GetAccountId(this.User))); //Here we inherit each role the user account has to the zoneserver account foreach (var claim in User.Claims) { if (claim.Type == "role") //TODO: Is there a constant for this?? { if (claim.Value.ToLower() != GladMMOAuthConstants.PLAYERACCOUNT_AUTHORIZATION_ROLE) //DO NOT add the player role. { await UserManager.AddToRoleAsync(user, claim.Value); } } } //Also add the ZoneServer role await UserManager.AddToRoleAsync(user, GladMMOAuthConstants.ZONESERVER_AUTHORIZATION_ROLE); //At this point, the account has the PlayFab id claim so it's ready for use. return(Json(new ZoneServerAccountRegistrationResponse(user.Id, zoneUserName, zonePassword))); } else { return(BadRequest(identityResult.Errors.Aggregate("", (s, error) => $"{s} {error.Code}:{error.Description}"))); } }
public IActionResult Create([FromBody] CommentCreateDto data) { if (string.IsNullOrEmpty(data.Content)) { return(BadRequest()); } var userId = ClaimsReader.GetUserId(Request); var post = context.Posts.FirstOrDefault(a => a.Id == data.PostId); if (post == null) { return(NotFound()); } if (!context.UserGroups.Any(a => a.GroupId == post.GroupId && a.UserId == userId && (a.Relation == GroupRelation.Owner || a.Relation == GroupRelation.User))) { return(BadRequest()); } var comment = new Comment { DateAdded = DateTime.UtcNow, Content = data.Content, PostId = data.PostId, UserId = userId }; context.Comments.Add(comment); try { context.SaveChanges(); var user = context.Users.FirstOrDefault(a => a.Id == userId); var result = new CommentDto { Id = comment.Id, Content = comment.Content, DateAdded = comment.DateAdded, Owner = user.Login, IsOwner = true }; return(Ok(result)); } catch (Exception) { return(BadRequest()); } }
public async Task <IActionResult> SetWorldAsUploaded( [FromRoute(Name = "id")] long worldId, [FromServices] IWorldEntryRepository worldEntryRepository, [FromServices] IContentResourceExistenceVerifier contentResourceExistenceVerifier) { //At this point, the user is telling us they finished uploading the world. //They could be lying so we should check that the resource exists AND //we should also check that it's an asset bundle and gather some information from the header. //First we verify a world exists with this id if (!await worldEntryRepository.ContainsAsync(worldId).ConfigureAwaitFalse()) { //TODO: We should say something more specific return(BadRequest()); } WorldEntryModel model = await worldEntryRepository.RetrieveAsync(worldId) .ConfigureAwaitFalse(); //Check the model is associated with this account. Only 1 account can own a world resource if (model.AccountId != ClaimsReader.GetAccountIdInt(User)) { return(Unauthorized()); } //Now that we know the world is in the database and the account making this authorized requests owns it //we can now actually check that the resource exists on the storeage system //TODO: This relies on some outdated API/deprecated stuff. bool resourceExists = await contentResourceExistenceVerifier.VerifyResourceExists(UserContentType.World, model.StorageGuid) .ConfigureAwaitFalse(); //TODO: Don't hardcore bucket name //TODO: Be more descriptive if (!resourceExists) { return(NotFound()); } //Ok, so the user IS the resource owner AND he did upload something, so let's validate the assetbundle header. //TODO: Refactor this into an object that does the validation and generates readable data //TODO: Actually implement asset bundle validation //We haven't implemented this yet, we should do asset bundle parsing and validation //This REALLY important to prevent invalid bundles from being uploaded //or content that isn't even an asset bundle being uploaded //See: https://github.com/HearthSim/UnityPack/wiki/Format-Documentation //For now, since it's unimplemented let's just set it validated await worldEntryRepository.SetWorldValidated(model.WorldId) .ConfigureAwaitFalseVoid(); return(Ok()); }
public async Task <CharacterDataQueryResponseCode> CreateCharacterAppearanceAsync([FromRoute(Name = "id")] int characterId, [FromBody] RPGCharacterCustomizationData <TCustomizableSlotType, TColorStructureType, TProportionSlotType, TProportionStructureType> data, CancellationToken token = default) { if (!ModelState.IsValid) { return(CharacterDataQueryResponseCode.GeneralError); } int accountId = ClaimsReader.GetAccountId <int>(User); try { if (!await CharacterRepository.ContainsAsync(characterId, token)) { return(CharacterDataQueryResponseCode.CharacterDoesNotExist); } //Only allow users who own the character to create its appearance if (!await CharacterRepository.AccountOwnsCharacterAsync(accountId, characterId, token)) { return(CharacterDataQueryResponseCode.NotAuthorized); } //We scope the appearance persistence in a transaction because we don't want a HALF customized character. await using IDbContextTransaction transaction = await AppearanceRepository.CreateTransactionAsync(token); if (data.ProportionData.Count > 0) { await AppearanceRepository.CreateSlotsAsync(data.ProportionData.Select(p => new DBRPGCharacterProportionSlot <TProportionSlotType, TProportionStructureType>(characterId, p.Key, p.Value)).ToArray(), token); } if (data.SlotData.Count > 0) { await AppearanceRepository.CreateSlotsAsync(ConvertToCustomizableSlotData(characterId, data), token); } await transaction.CommitAsync(token); return(CharacterDataQueryResponseCode.Success); } catch (Exception e) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create character appearance for Character: {characterId} Account: {accountId}. Reason: {e}"); } return(CharacterDataQueryResponseCode.GeneralError); } }
public async Task <IActionResult> RequestWorldUploadUrl([FromServices] IWorldEntryRepository worldEntryRepository, [FromServices] IStorageUrlBuilder urlBuilder) { if (worldEntryRepository == null) { throw new ArgumentNullException(nameof(worldEntryRepository)); } //TODO: We want to rate limit access to this API //TODO: We should use both app logging but also another logging service that always gets hit if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Recieved {nameof(RequestWorldUploadUrl)} request from {ClaimsReader.GetUserName(User)}:{ClaimsReader.GetUserId(User)}."); } int userId = ClaimsReader.GetUserIdInt(User); //TODO: We should send this if we can't get a user id //return new JsonResult(RequestedUrlResponseModel.CreateFailure("Failed to authorize action.", RequestedUrlResponseCode.AuthorizationFailed)); //TODO: Abstract this behind an issuer Guid worldGuid = Guid.NewGuid(); //TODO: Check if the result is valid? We should maybe return bool from this API (we do return bool from this API now) //The idea is to create an entry which will contain a GUID. From that GUID we can then generate the upload URL WorldEntryModel world = new WorldEntryModel(userId, this.HttpContext.Connection.RemoteIpAddress.ToString(), worldGuid); bool result = await worldEntryRepository.TryCreateAsync(world); //TODO: Ok to just provide a guid right? //TODO: Check world's worldid has been set string uploadUrl = await urlBuilder.BuildUploadUrl(UserContentType.World, worldGuid); if (String.IsNullOrEmpty(uploadUrl)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create world upload URL for {ClaimsReader.GetUserName(User)}:{ClaimsReader.GetUserId(User)} with GUID: {worldGuid}."); } return(new JsonResult(RequestedUrlResponseModel.CreateFailure("Upload service unavailable.", RequestedUrlResponseCode.ServiceUnavailable))); } if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Success. Sending {ClaimsReader.GetUserName(User)} URL: {uploadUrl}"); } return(new JsonResult(RequestedUrlResponseModel.CreateSuccess(uploadUrl, world.WorldId))); }
/// <inheritdoc /> public override async Task OnConnectedAsync() { await base.OnConnectedAsync() .ConfigureAwait(false); if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Account Connected: {ClaimsReader.GetUserName(Context.User)}:{ClaimsReader.GetUserId(Context.User)}"); } NetworkEntityGuid guid = new NetworkEntityGuidBuilder() .WithId(int.Parse(Context.UserIdentifier)) .WithType(EntityType.Player) .Build(); //Register interest and then lock //We need to lock on the entity so only 1 connection for the entity can go through this process at a time. await EntityLockService.RegisterEntityInterestAsync(guid) .ConfigureAwait(false); using (await EntityLockService.AquireEntityLockAsync(guid).ConfigureAwait(false)) { try { foreach (var listener in OnConnectionHubListeners) { HubOnConnectionState connectionState = await listener.OnConnected(this).ConfigureAwait(false); //if the listener indicated we need to abort for whatever reason we //should believe it and just abort. if (connectionState == HubOnConnectionState.Abort) { Context.Abort(); break; } } } catch (Exception e) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogInformation($"Account: {ClaimsReader.GetUserName(Context.User)}:{ClaimsReader.GetUserId(Context.User)} failed to properly connect to hub. Error: {e.Message}\n\nStack: {e.StackTrace}"); } Context.Abort(); } } }
public IActionResult Details([FromQuery] int id) { var userId = ClaimsReader.GetUserId(Request); var group = context.Groups.SingleOrDefault(a => a.Id == id); var result = new GroupDetailsDto { Id = group.Id, Name = group.Name, Description = group.Description, IsPrivate = group.IsPrivate, IsOwner = CheckAdminPriviliges(userId, id) }; return(Ok(result)); }
public async Task <IActionResult> PostPointsToDevice(string id, [FromBody] TrackingPoint[] points) { var subject = ClaimsReader.ReadSubject(this.User); var audience = ClaimsReader.ReadAudience(this.User); if (audience == JwtAuthConstants.DeviceAudience && id != subject) { return(Forbid()); } points.ForEach((point) => point.TrackingDeviceId = id); var addedPoints = await this.pointService.AddAsync(points); await this.geoFenceService.HandlePoints(addedPoints.First().AssetId, addedPoints.ToArray()); return(Ok()); }