public async Task <CreateMutationResponse <User> > SignUp( SignupInput input, [Service] SlackCloneDbContext dbContext, CancellationToken cancellationToken) { try { string salt = Guid.NewGuid().ToString("N"); using var sha = SHA512.Create(); byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(input.Password + salt)); var user = new User { Email = input.Email, PasswordHash = Convert.ToBase64String(hash), Salt = salt, DisplayName = input.DisplayName }; dbContext.Users.Add(user); await dbContext.SaveChangesAsync(cancellationToken); return(new CreateMutationResponse <User>(true, user)); } catch (DbUpdateException e) { throw new QueryException($"DbUpdateException error details - {e?.InnerException?.Message}"); } }
public async Task <LoginResponse> Login( LoginInput input, [Service] SlackCloneDbContext dbContext, CancellationToken cancellationToken ) { User user = await dbContext.Users.FirstOrDefaultAsync(t => t.Email == input.Email); if (user is null) { throw new QueryException( ErrorBuilder.New() .SetMessage("The user does not exist, please sign up.") .SetCode("INVALID_CREDENTIALS") .Build()); } using var sha = SHA512.Create(); byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(input.Password + user.Salt)); if (!Convert.ToBase64String(hash).Equals(user.PasswordHash, StringComparison.Ordinal)) { throw new QueryException( ErrorBuilder.New() .SetMessage("The specified password is invalid.") .SetCode("INVALID_PASSWORD") .Build()); } var identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, user.DisplayName), new Claim(ClaimTypes.Email, user.Email) }); var tokenHandler = new JwtSecurityTokenHandler(); var tokenDescriptor = new SecurityTokenDescriptor { Subject = identity, Expires = DateTime.UtcNow.AddHours(12), SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(Startup.SharedSecret), SecurityAlgorithms.HmacSha256Signature) }; SecurityToken token = tokenHandler.CreateToken(tokenDescriptor); string tokenString = tokenHandler.WriteToken(token); return(new LoginResponse(user, tokenString)); }
public async Task <CreateMutationResponse <Channel> > CreateChannel( CreateChannelInput input, [GlobalState] string currentUserEmail, [Service] SlackCloneDbContext dbContext, [Service] ITopicEventSender eventSender, CancellationToken cancellationToken) { try { if (string.IsNullOrEmpty(input.Name)) { throw new QueryException( ErrorBuilder.New() .SetMessage("The channel name can not be null.") .SetCode("INVALID_INPUT") .Build()); } var channel = new Channel() { Name = input.Name, Description = input.Description, CreatedAt = DateTime.UtcNow, CreatedByEmail = currentUserEmail }; dbContext.Channels.Add(channel); await dbContext.SaveChangesAsync(cancellationToken); bool ok = true; await eventSender.SendAsync("channelCreated", channel, cancellationToken).ConfigureAwait(false); return(new CreateMutationResponse <Channel>(ok, channel)); } catch (DbUpdateException e) { throw new QueryException($"DbUpdateException error details - {e?.InnerException?.Message}"); } }
public async Task <AddMessageToChannelResponse> AddMessageToChannel( AddMessageToChannelInput input, [GlobalState] string currentUserEmail, [Service] SlackCloneDbContext dbContext, [Service] ITopicEventSender eventSender, CancellationToken cancellationToken) { var message = new ChannelMessage { Id = Guid.NewGuid(), ChannelId = input.ChannelId, Text = input.Text, CreatedAtUTC = DateTime.UtcNow, CreatedByEmail = currentUserEmail, Likes = 0 }; dbContext.ChannelMessages.Add(message); await dbContext.SaveChangesAsync(cancellationToken); await eventSender.SendAsync(input.ChannelId, message, cancellationToken).ConfigureAwait(false); return(new AddMessageToChannelResponse(true)); }
public IQueryable <User> Users( [Service] SlackCloneDbContext dbContext) => dbContext.Users;
public IQueryable <User> Me( [GlobalState] string currentUserEmail, [Service] SlackCloneDbContext dbContext) => dbContext.Users.Where(user => user.Email == currentUserEmail);
public IQueryable <ChannelMessage> ChannelMessages([Service] SlackCloneDbContext dbContext) { return(dbContext.ChannelMessages); }