source: resTools_backend/backend/Services/UserService.cs@ 13f1472

Last change on this file since 13f1472 was 13f1472, checked in by Danilo <danilo.najkov@…>, 22 months ago

vip functionallity + menu fields + alergens filtering + google/fb login + email queueing

  • Property mode set to 100644
File size: 6.7 KB
Line 
1namespace backend.Services;
2
3using backend.Data;
4using backend.DTOs;
5using backend.Email;
6using backend.Entities;
7using backend.Helpers;
8using backend.Models;
9using Microsoft.EntityFrameworkCore;
10using Microsoft.Extensions.Options;
11using Microsoft.IdentityModel.Tokens;
12using System.IdentityModel.Tokens.Jwt;
13using System.Security.Claims;
14using System.Security.Cryptography;
15using System.Text;
16
17public interface IUserService
18{
19 Task<AuthenticateResponse> Authenticate(AuthenticateRequest model);
20 Task<AuthenticateResponse> Register(CreateUserRequest req, bool isFirst);
21 Task<User> GetById(int id);
22 Task<User> GetByEmail(string email);
23 Task SendEmailConfirmation(string email);
24 Task SendPasswordReset(string email);
25 Task ConfirmEmail(User user, string checkValid);
26 Task ResetPassword(string checkValid, string password);
27 Task<List<UserResponse>> GetUsers();
28 Task UpdateVipStatus(int id, bool isVip);
29
30}
31
32public class UserService : IUserService
33{
34 private readonly AppSettings _appSettings;
35 private readonly DataContext _context = null;
36 private readonly IEmailSender _emailSender;
37
38 public UserService(IOptions<AppSettings> appSettings, DataContext context, IEmailSender emailSender)
39 {
40 _appSettings = appSettings.Value;
41 _context = context;
42 _emailSender = emailSender;
43 }
44
45 public async Task<User> GetByEmail(string email)
46 {
47 return await _context.Users.FirstOrDefaultAsync(x => x.Email == email);
48 }
49
50 public async Task<AuthenticateResponse> Authenticate(AuthenticateRequest model)
51 {
52 User user = await _context.Users.FirstOrDefaultAsync(x => x.Email == model.Email && x.Password == model.Password);
53
54 // return null if user not found
55 if (user == null) return null;
56
57 // authentication successful so generate jwt token
58 var token = generateJwtToken(user);
59
60 return new AuthenticateResponse { Email = user.Email, Id = user.Id, Token = token, IsAdmin = user.IsAdmin, IsConfirmed = user.IsConfirmed, isVip = user.IsVip};
61 }
62
63 public async Task ConfirmEmail(User user, string checkValid)
64 {
65 if(user.ConfirmationURL != checkValid)
66 {
67 throw new Exception("Invalid check");
68 }
69 if(user.ConfirmationValidTo < DateTime.UtcNow)
70 {
71 throw new Exception("Link expired");
72 }
73
74 user.IsConfirmed = true;
75 _context.Users.Update(user);
76 await _context.SaveChangesAsync();
77 }
78
79 public async Task<User> GetById(int id)
80 {
81 return await _context.Users.FindAsync(id);
82 }
83
84 public async Task<AuthenticateResponse> Register(CreateUserRequest req, bool isFirst)
85 {
86 var exists = await _context.Users.FirstOrDefaultAsync(x => x.Email == req.Email);
87 if(exists != null && req.IsConfirmed)
88 {
89 return new AuthenticateResponse { Email = exists.Email, Id = exists.Id, IsAdmin = exists.IsAdmin, IsConfirmed = true };
90 }
91 User user = new User() { Email = req.Email, Password = req.Password, IsAdmin = isFirst, IsConfirmed = req.IsConfirmed, IsVip = false };
92 await _context.Users.AddAsync(user);
93 await _context.SaveChangesAsync();
94 var token = generateJwtToken(user);
95 return new AuthenticateResponse { Email = user.Email, Id = user.Id, Token = token, IsAdmin = user.IsAdmin, IsConfirmed = req.IsConfirmed, isVip = user.IsVip };
96 }
97
98 public async Task ResetPassword(string checkValid, string password)
99 {
100 var user = await _context.Users.Where(x => x.PasswordResetURL == checkValid).FirstOrDefaultAsync();
101 if (user == null)
102 {
103 throw new Exception("Invalid check");
104 }
105 if (user.PasswordResetValidTo < DateTime.UtcNow)
106 {
107 throw new Exception("Link expired");
108 }
109
110 user.Password = password;
111 _context.Users.Update(user);
112 await _context.SaveChangesAsync();
113 }
114
115 public async Task SendEmailConfirmation(string email)
116 {
117 User user = await _context.Users.FirstOrDefaultAsync(x => x.Email == email);
118 user.ConfirmationURL = Guid.NewGuid().ToString();
119 user.ConfirmationValidTo = DateTime.UtcNow.AddHours(24);
120 _context.Users.Update(user);
121 await _context.SaveChangesAsync();
122 await _emailSender.SendEmailAsync(
123 "Потврдете го вашиот емаил",
124 "Ве молиме кликнете на следниот линк за да го потврдите вашиот емаил: http://localhost:3000/confirm?id=" + user.ConfirmationURL,
125 email);
126 }
127
128 public async Task SendPasswordReset(string email)
129 {
130 User user = await _context.Users.FirstOrDefaultAsync(x => x.Email == email);
131 user.PasswordResetURL = Guid.NewGuid().ToString();
132 user.PasswordResetValidTo = DateTime.UtcNow.AddHours(24);
133 _context.Users.Update(user);
134 await _context.SaveChangesAsync();
135 await _emailSender.SendEmailAsync(
136 "Ресетирајте ја лозинката",
137 "Ве молиме кликнете на следниот линк за да ја ресетирате лозинката: http://localhost:3000/reset?id=" + user.PasswordResetURL,
138 email);
139 }
140
141 public async Task<List<UserResponse>> GetUsers()
142 {
143 return await _context.Users.Select(x => new UserResponse()
144 {
145 Email = x.Email,
146 Id = x.Id,
147 IsVip = x.IsVip
148 }).OrderBy(x => x.Id).ToListAsync();
149 }
150
151 public async Task UpdateVipStatus(int id, bool isVip)
152 {
153 var user = await _context.Users.FindAsync(id);
154 user.IsVip = isVip;
155 _context.Users.Update(user);
156 await _context.SaveChangesAsync();
157 }
158
159 private string generateJwtToken(User user)
160 {
161 // generate token that is valid for 7 days
162 var tokenHandler = new JwtSecurityTokenHandler();
163 var key = System.Text.Encoding.ASCII.GetBytes(_appSettings.Secret);
164 var tokenDescriptor = new SecurityTokenDescriptor
165 {
166 Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
167 Expires = DateTime.UtcNow.AddDays(7),
168 SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
169 };
170 var token = tokenHandler.CreateToken(tokenDescriptor);
171 return tokenHandler.WriteToken(token);
172 }
173
174 private string sha256Hash(String value)
175 {
176 using (SHA256 hash = SHA256.Create())
177 {
178 return String.Concat(hash
179 .ComputeHash(Encoding.UTF8.GetBytes(value))
180 .Select(item => item.ToString("x2")));
181 }
182 }
183}
Note: See TracBrowser for help on using the repository browser.