diff options
Diffstat (limited to 'backend/api')
20 files changed, 502 insertions, 57 deletions
diff --git a/backend/api/api/.gitignore b/backend/api/api/.gitignore index 8afdcb63..242abea5 100644 --- a/backend/api/api/.gitignore +++ b/backend/api/api/.gitignore @@ -3,6 +3,9 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +##Ignore contents for UploadedFiles Folder +UploadedFiles/* + # User-specific files *.rsuser *.suo diff --git a/backend/api/api/Controllers/AuthController.cs b/backend/api/api/Controllers/AuthController.cs index 1f47067f..e1601815 100644 --- a/backend/api/api/Controllers/AuthController.cs +++ b/backend/api/api/Controllers/AuthController.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using api.Services; +using Microsoft.AspNetCore.Authorization; namespace api.Controllers { @@ -9,10 +10,10 @@ namespace api.Controllers [ApiController] public class AuthController : ControllerBase { - private AuthService _auth; - public AuthController(IConfiguration configuration) + private IAuthService _auth; + public AuthController(IAuthService auth) { - _auth=new AuthService(configuration); + _auth = auth; } [HttpPost("register")] @@ -29,6 +30,14 @@ namespace api.Controllers return Ok(_auth.Login(user)); } + [HttpGet("Auth")] + [Authorize(Roles ="User")] + public async Task<ActionResult<string>> TestAuth() + { + return Ok("works"); + } + + } } diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs new file mode 100644 index 00000000..e1b888a1 --- /dev/null +++ b/backend/api/api/Controllers/DatasetController.cs @@ -0,0 +1,43 @@ +using Microsoft.AspNetCore.Mvc; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class DatasetController : ControllerBase + { + // GET: api/<DatasetController> + [HttpGet] + public IEnumerable<string> Get() + { + return new string[] { "value1", "value2" }; + } + + // GET api/<DatasetController>/5 + [HttpGet("{id}")] + public string Get(int id) + { + return "value"; + } + + // POST api/<DatasetController> + [HttpPost] + public void Post([FromBody] string value) + { + } + + // PUT api/<DatasetController>/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + } + + // DELETE api/<DatasetController>/5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/backend/api/api/Controllers/FileUploadController.cs b/backend/api/api/Controllers/FileUploadController.cs new file mode 100644 index 00000000..46e7f4f9 --- /dev/null +++ b/backend/api/api/Controllers/FileUploadController.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +namespace api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class FileUploadController : ControllerBase + { + private string[] permittedExtensions = { ".csv" }; + + + [HttpPost("Csv")] + [Authorize(Roles = "User")] + public async Task<ActionResult<string>> CsvUpload([FromForm]IFormFile file,[FromForm]string username)//???Umesto username poslati jwt odakle se moze preuzeti username radi sigurnosti + { + var filename=file.FileName; + var ext=Path.GetExtension(filename).ToLowerInvariant(); + var name = Path.GetFileNameWithoutExtension(filename).ToLowerInvariant(); + if (string.IsNullOrEmpty(ext) || ! permittedExtensions.Contains(ext)) { + return BadRequest("Wrong file type"); + } + var folderPath=Path.Combine(Directory.GetCurrentDirectory(),"UploadedFiles",username); + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + + var fullPath = Path.Combine(folderPath, filename); + int i=0; + + while (System.IO.File.Exists(fullPath)) { + i++; + fullPath = Path.Combine(folderPath,name+i.ToString()+ext); + } + + + + using (var stream=new FileStream(fullPath, FileMode.Create)) + { + await file.CopyToAsync(stream); + } + + return Ok(); + } + } +} diff --git a/backend/api/api/Controllers/UserController.cs b/backend/api/api/Controllers/UserController.cs new file mode 100644 index 00000000..caf78d9c --- /dev/null +++ b/backend/api/api/Controllers/UserController.cs @@ -0,0 +1,110 @@ +using api.Models; +using api.Services; +using Microsoft.AspNetCore.Mvc; +using System.Diagnostics; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 +//dovrsi kontroler +namespace api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class UserController : ControllerBase + { + private readonly IUserService userService; + + public UserController(IUserService userService) + { + this.userService = userService; + } + + // GET: api/<UserController> + [HttpGet] + public ActionResult<List<User>> Get() + { + return userService.Get(); + } + + // GET api/<UserController>/5 + //potrebno za profile page + [HttpGet("{id}")] + public ActionResult<User> Get(string id) + { + var user = userService.Get(id); + + if (user == null) + return NotFound($"User with Id = {id} not found"); + + return user; + } + + // GET api/<UserController>/5 + //potrebno za profile page + [HttpGet("{id}")] + public ActionResult<User> GetUserUsername(string username) + { + var user = userService.GetUserUsername(username); + + if (user == null) + return NotFound($"User with Id = {username} not found"); + + return user; + } + + // POST api/<UserController> + [HttpPost] + public ActionResult<User> Post([FromBody] User user) + { + + var existingUser = userService.GetUserUsername(user.Username); + + if (existingUser != null) + return NotFound($"User with username = {user.Username} exisits"); + else + { + userService.Create(user); + + //Debug.WriteLine("\nTest.\n"); + + return CreatedAtAction(nameof(Get), new { id = user._id }, user); + } + } + + // PUT api/<UserController>/5 + [HttpPut("{id}")] + public ActionResult Put(string id, [FromBody] User user) + { + var existingUser = userService.Get(id); + + //ne mora da se proverava + if(existingUser == null) + return NotFound($"User with Id = {id} not found"); + + userService.Update(id, user); + return NoContent(); + } + + // DELETE api/<UserController>/5 + [HttpDelete("{id}")] + public ActionResult Delete(string id) + { + var user = userService.Get(id); + + if (user == null) + return NotFound($"User with Id = {id} not found"); + + userService.Delete(user._id); + return Ok($"Student with Id = {id} deleted"); + } + } +} +/* +{ + "_id": "", + "username" : "ivan996sk", + "email" : "ivan996sk@gmail.com", + "password" : "proba", + "firstName" : "Ivan", + "lastName" : "Ljubisavljevic" +} +*/
\ No newline at end of file diff --git a/backend/api/api/Data/MongoDbSettings.cs b/backend/api/api/Data/MongoDbSettings.cs deleted file mode 100644 index 8b42a02c..00000000 --- a/backend/api/api/Data/MongoDbSettings.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using MongoDB.Driver; - -namespace api.Data -{ - public class MongoDbSettings - { - public string? ConnectionURI { get; set; } = null; - public string? DatabaseName { get; set; } = null; - public string? CollectionName { get; set; } = null; - - - - - - } -} diff --git a/backend/api/api/Data/UserStoreDatabaseSettings.cs b/backend/api/api/Data/UserStoreDatabaseSettings.cs new file mode 100644 index 00000000..0efd2895 --- /dev/null +++ b/backend/api/api/Data/UserStoreDatabaseSettings.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore; +using MongoDB.Driver; +using api.Interfaces; + +namespace api.Data +{ + public class UserStoreDatabaseSettings : IUserStoreDatabaseSettings + { + public string ConnectionString { get; set; } = String.Empty; + public string DatabaseName { get; set; } = String.Empty; + public string CollectionName { get; set; } = String.Empty; + } +} diff --git a/backend/api/api/Interfaces/IUserStoreDatabaseSettings.cs b/backend/api/api/Interfaces/IUserStoreDatabaseSettings.cs new file mode 100644 index 00000000..8d2a175f --- /dev/null +++ b/backend/api/api/Interfaces/IUserStoreDatabaseSettings.cs @@ -0,0 +1,10 @@ +namespace api.Interfaces +{ + public interface IUserStoreDatabaseSettings + { + string ConnectionString { get; set; } + string DatabaseName { get; set; } + string CollectionName { get; set; } + string DatasetCollectionName { get; set; } + } +} diff --git a/backend/api/api/Models/Dataset.cs b/backend/api/api/Models/Dataset.cs new file mode 100644 index 00000000..448a6aa9 --- /dev/null +++ b/backend/api/api/Models/Dataset.cs @@ -0,0 +1,21 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; + +namespace api.Models +{ + public class Dataset + { + internal string uploaderId; + + [BsonId] + [BsonRepresentation(BsonType.ObjectId)]//mongo data type to .net + public string _id { get; set; } + [BsonElement("uploaderId")] + public string UploaderId { get; set; } + [BsonElement("extension")] + public string extension { get; set; } + [BsonElement("name")] + public string name { get; set; } + + } +} diff --git a/backend/api/api/Models/User.cs b/backend/api/api/Models/User.cs index d0f2bc0f..46db50ab 100644 --- a/backend/api/api/Models/User.cs +++ b/backend/api/api/Models/User.cs @@ -1,18 +1,28 @@ using System.ComponentModel.DataAnnotations; +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; + namespace api.Models { + [BsonIgnoreExtraElements]//ignorise visak elemenata iz baze --moze da se obrise jer nemamo viska public class User { - [Key] - public Guid userId { get; set; } - public string username { get; set; } - public string email { get; set; } - public string password { get; set; } + [BsonId] + [BsonRepresentation(BsonType.ObjectId)]//mongo data type to .net + public string _id { get; set; } + [BsonElement("username")] + public string Username { get; set; } + [BsonElement("email")] + public string Email { get; set; } + [BsonElement("password")] + public string Password { get; set; } - public string firstName { get; set; } - public int lastName { get; set; } + [BsonElement("firstName")] + public string FirstName { get; set; } + [BsonElement("lastName")] + public string LastName { get; set; } } } diff --git a/backend/api/api/Program.cs b/backend/api/api/Program.cs index 84514972..550f6ce1 100644 --- a/backend/api/api/Program.cs +++ b/backend/api/api/Program.cs @@ -1,9 +1,46 @@ +using System.Text; +using api.Data; +using api.Interfaces; +using api.Services; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; +using MongoDB.Driver; + var builder = WebApplication.CreateBuilder(args); //Add Cors builder.Services.AddCors(); // Add services to the container +//dodajemo dep inj + +builder.Services.Configure<UserStoreDatabaseSettings>( + builder.Configuration.GetSection(nameof(UserStoreDatabaseSettings))); + +builder.Services.AddSingleton<IUserStoreDatabaseSettings>(sp => + sp.GetRequiredService<IOptions<UserStoreDatabaseSettings>>().Value); + +builder.Services.AddSingleton<IMongoClient>(s => + new MongoClient(builder.Configuration.GetValue<string>("UserStoreDatabaseSettings:ConnectionString"))); + +//Inject Dependencies +builder.Services.AddScoped<IUserService, UserService>(); +builder.Services.AddScoped<IAuthService, AuthService>(); + +//Add Authentication +builder.Services.AddAuthentication( + JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration.GetSection("AppSettings:JwtToken").Value)), + ValidateIssuer=false, + ValidateAudience=false + }; + + }); + builder.Services.AddControllers(); @@ -19,6 +56,9 @@ app.UseCors( // Configure the HTTP request pipeline. +//Add Authentication +app.UseAuthentication(); + app.UseAuthorization(); app.MapControllers(); diff --git a/backend/api/api/Services/AuthService.cs b/backend/api/api/Services/AuthService.cs index 1a901cb8..015fdac7 100644 --- a/backend/api/api/Services/AuthService.cs +++ b/backend/api/api/Services/AuthService.cs @@ -1,34 +1,47 @@ -using api.Models; +using api.Interfaces; +using api.Models; using api.Models.Users; +using MongoDB.Driver; namespace api.Services { - public class AuthService + public class AuthService : IAuthService { private JwtToken _jwt; private readonly IConfiguration _configuration; - public AuthService(IConfiguration configuration) + private readonly IMongoCollection<User> _users; + public AuthService(IConfiguration configuration, IUserStoreDatabaseSettings settings, IMongoClient mongoClient) { _configuration = configuration; _jwt = new JwtToken(_configuration); + var database = mongoClient.GetDatabase(settings.DatabaseName); + _users = database.GetCollection<User>(settings.CollectionName); } public string Login(AuthRequest user) { - //Check username in DB - - //Verify password - - //gen token - + User u = _users.Find(x => x.Username == user.UserName).FirstOrDefault(); + if (u == null) + return "Username doesn't exist"; + if (!PasswordCrypt.checkPassword(user.Password, u.Password)) + return "Wrong password"; return _jwt.GenToken(user); } - public RegisterRequest Register(RegisterRequest user) + public string Register(RegisterRequest user) { - //check for existing email and username - user.password = PasswordCrypt.hashPassword(user.password); - //Add to DB. TO DO - return user; + User u = new User(); + u.Username = user.username; + u.Email = user.email; + u.Password = PasswordCrypt.hashPassword(user.password); + u.FirstName = user.firstName; + u.LastName = user.lastName; + if (_users.Find(user => user.Username == u.Username).FirstOrDefault() != null) + return "Username Already Exists"; + if (_users.Find(user => user.Email == u.Email).FirstOrDefault() != null) + return "Email Already Exists"; + + _users.InsertOne(u); + return "User added"; } diff --git a/backend/api/api/Services/DatasetService.cs b/backend/api/api/Services/DatasetService.cs new file mode 100644 index 00000000..154c9438 --- /dev/null +++ b/backend/api/api/Services/DatasetService.cs @@ -0,0 +1,40 @@ +using api.Interfaces; +using api.Models; +using MongoDB.Driver; + +namespace api.Services +{ + public class DatasetService : IDatasetService + { + private readonly IMongoCollection<Dataset> _dataset; + + public DatasetService(IUserStoreDatabaseSettings settings, IMongoClient mongoClient) + { + var database = mongoClient.GetDatabase(settings.DatabaseName); + _dataset = database.GetCollection<Dataset>(settings.DatasetCollectionName); + } + //kreiranje dataseta + public Dataset Create(Dataset dataset) + { + _dataset.InsertOne(dataset); + return dataset; + } + + //brisanje odredjenog name-a + public void Delete(string uploaderId, string name) + { + _dataset.DeleteOne(dataset => dataset.UploaderId == uploaderId && dataset.name == name); ; + } + + public Dataset Get(string uploaderId) + { + return _dataset.Find(dataset => dataset.UploaderId == uploaderId).FirstOrDefault(); + } + + //ako je potrebno da se zameni name ili ekstenzija + public void Update(string uploaderId, Dataset dataset) + { + _dataset.ReplaceOne(dataset => dataset.UploaderId == uploaderId, dataset); + } + } +} diff --git a/backend/api/api/Services/IAuthService.cs b/backend/api/api/Services/IAuthService.cs new file mode 100644 index 00000000..79085f8c --- /dev/null +++ b/backend/api/api/Services/IAuthService.cs @@ -0,0 +1,10 @@ +using api.Models.Users; + +namespace api.Services +{ + public interface IAuthService + { + string Login(AuthRequest user); + string Register(RegisterRequest user); + } +}
\ No newline at end of file diff --git a/backend/api/api/Services/IDatasetService.cs b/backend/api/api/Services/IDatasetService.cs new file mode 100644 index 00000000..22633c3c --- /dev/null +++ b/backend/api/api/Services/IDatasetService.cs @@ -0,0 +1,13 @@ + +using api.Models; + +namespace api.Services +{ + public interface IDatasetService + { + Dataset Get(string uploaderId); + Dataset Create(Dataset dataset); + void Update(string uploaderId, Dataset dataset); + void Delete(string uploaderId, string name); + } +} diff --git a/backend/api/api/Services/IUserService.cs b/backend/api/api/Services/IUserService.cs new file mode 100644 index 00000000..b6725694 --- /dev/null +++ b/backend/api/api/Services/IUserService.cs @@ -0,0 +1,14 @@ +using api.Models; + +namespace api.Services +{ + public interface IUserService + { + List<User> Get();// daje sve korisnike + User Get(string id); //daje korisnika po id-u + User GetUserUsername(string username); //daje korisnika po korisnickom imenu + User Create(User user); // kreira korisnika + void Update(string id, User user); //apdejruje korisnika po idu + void Delete(string id);//brise korisnika + } +} diff --git a/backend/api/api/Services/MongoDbService.cs b/backend/api/api/Services/MongoDbService.cs deleted file mode 100644 index f8b37536..00000000 --- a/backend/api/api/Services/MongoDbService.cs +++ /dev/null @@ -1,11 +0,0 @@ - - - -namespace api.Services -{ - public class MongoDbService - { - - - } -} diff --git a/backend/api/api/Services/UserService.cs b/backend/api/api/Services/UserService.cs new file mode 100644 index 00000000..c626889d --- /dev/null +++ b/backend/api/api/Services/UserService.cs @@ -0,0 +1,67 @@ +using api.Interfaces; +using api.Models; +using MongoDB.Driver; + +namespace api.Services +{ + public class UserService : IUserService + { + private readonly IMongoCollection<User> _users; + + public UserService(IUserStoreDatabaseSettings settings, IMongoClient mongoClient) + { + var database = mongoClient.GetDatabase(settings.DatabaseName); + _users = database.GetCollection<User>(settings.CollectionName); + } + public User Create(User user) + { + _users.InsertOne(user); + return user; + } + + public List<User> Get() + { + return _users.Find(user => true).ToList(); + } + + public User GetUserUsername(string username) + { + return _users.Find(user => user.Username == username).FirstOrDefault(); + } + + public User Get(string id) + { + return _users.Find(user => user._id == id).FirstOrDefault(); + } + + public void Delete(string id) + { + _users.DeleteOne(user => user._id == id); + + } + public void Update(string id, User user) + { + _users.ReplaceOne(user => user._id == id, user); + } + } +} +/* + { + "_id": "", + "username" : "ivan996sk", + "email" : "ivan996sk@gmail.com", + "password" : "proba", + "firstName" : "Ivan", + "lastName" : "Ljubisavljevic" +} + +{ + "_id": { + "$oid": "62291140d88e6bcf95c96a58" + }, + "uploaderId":"", + "extension" : "", + "name" : "" +} + +*/ diff --git a/backend/api/api/api.csproj b/backend/api/api/api.csproj index 1451fa77..46842c3e 100644 --- a/backend/api/api/api.csproj +++ b/backend/api/api/api.csproj @@ -8,6 +8,7 @@ <ItemGroup> <PackageReference Include="BCrypt.Net-Next" Version="4.0.3" /> + <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.3" /> <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.16.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.16.0" /> </ItemGroup> @@ -17,4 +18,8 @@ <PackageReference Include="MongoDB.Driver" Version="2.14.1" /> </ItemGroup> + <ItemGroup> + <Folder Include="UploadedFiles\" /> + </ItemGroup> + </Project> diff --git a/backend/api/api/appsettings.json b/backend/api/api/appsettings.json index b9144d93..3661f171 100644 --- a/backend/api/api/appsettings.json +++ b/backend/api/api/appsettings.json @@ -9,10 +9,15 @@ } }, "AllowedHosts": "*", - "MongoDb": { - "ConnectionURI": "mongodb+srv://LINKIKKKKKKK", - "DatabaseName": "", - "CollectionName": "" - + "UserStoreDatabaseSettings": { + /* LocalHost + "ConnectionString": "mongodb://127.0.0.1:27017/", + "DatabaseName": "si_project", + "CollectionName": "User" + */ + "ConnectionString": "mongodb+srv://si_user:si_user@sidatabase.twtfm.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", + "DatabaseName": "si_db", + "CollectionName": "users", + "DatasetCollectionName" : "Dataset" } } |