From a28bf7aeaf257ff8bcf6dbd38e53fd3a08771251 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Wed, 26 Oct 2022 21:29:36 +0200 Subject: Iniciali commit backend-a. --- Backend/Api/.gitignore | 454 +++++++++++++++++++++++++ Backend/Api/Api.sln | 25 ++ Backend/Api/Api/Api.csproj | 20 ++ Backend/Api/Api/Program.cs | 23 ++ Backend/Api/Api/Properties/launchSettings.json | 31 ++ Backend/Api/Api/appsettings.Development.json | 8 + Backend/Api/Api/appsettings.json | 9 + 7 files changed, 570 insertions(+) create mode 100644 Backend/Api/.gitignore create mode 100644 Backend/Api/Api.sln create mode 100644 Backend/Api/Api/Api.csproj create mode 100644 Backend/Api/Api/Program.cs create mode 100644 Backend/Api/Api/Properties/launchSettings.json create mode 100644 Backend/Api/Api/appsettings.Development.json create mode 100644 Backend/Api/Api/appsettings.json (limited to 'Backend/Api') diff --git a/Backend/Api/.gitignore b/Backend/Api/.gitignore new file mode 100644 index 0000000..2afa2e2 --- /dev/null +++ b/Backend/Api/.gitignore @@ -0,0 +1,454 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# JetBrains Rider +.idea/ +*.sln.iml + +## +## Visual Studio Code +## +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json diff --git a/Backend/Api/Api.sln b/Backend/Api/Api.sln new file mode 100644 index 0000000..006fcf6 --- /dev/null +++ b/Backend/Api/Api.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32825.248 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api", "Api\Api.csproj", "{98D1F700-C988-4F19-89D1-9B7D002D702D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {98D1F700-C988-4F19-89D1-9B7D002D702D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98D1F700-C988-4F19-89D1-9B7D002D702D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98D1F700-C988-4F19-89D1-9B7D002D702D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98D1F700-C988-4F19-89D1-9B7D002D702D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E6AD5655-69C9-485B-9F63-FF2F67F42B51} + EndGlobalSection +EndGlobal diff --git a/Backend/Api/Api/Api.csproj b/Backend/Api/Api/Api.csproj new file mode 100644 index 0000000..6a05d5c --- /dev/null +++ b/Backend/Api/Api/Api.csproj @@ -0,0 +1,20 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + + diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs new file mode 100644 index 0000000..df2434c --- /dev/null +++ b/Backend/Api/Api/Program.cs @@ -0,0 +1,23 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/Backend/Api/Api/Properties/launchSettings.json b/Backend/Api/Api/Properties/launchSettings.json new file mode 100644 index 0000000..8ad1068 --- /dev/null +++ b/Backend/Api/Api/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:61217", + "sslPort": 0 + } + }, + "profiles": { + "Api": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5279", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Backend/Api/Api/appsettings.Development.json b/Backend/Api/Api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Backend/Api/Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Backend/Api/Api/appsettings.json b/Backend/Api/Api/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Backend/Api/Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} -- cgit v1.2.3 From f65890370609daeb4428b2a631f23d09d0b28445 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Wed, 26 Oct 2022 23:13:53 +0200 Subject: Dodat folder za controllere. --- Backend/Api/Api/Api.csproj | 1 + 1 file changed, 1 insertion(+) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Api.csproj b/Backend/Api/Api/Api.csproj index 6a05d5c..8732b1d 100644 --- a/Backend/Api/Api/Api.csproj +++ b/Backend/Api/Api/Api.csproj @@ -11,6 +11,7 @@ + -- cgit v1.2.3 From 426dcd9403192b7e7f40ad01bafb57f7e4f9071f Mon Sep 17 00:00:00 2001 From: Jelena Petrovic Date: Thu, 27 Oct 2022 01:15:21 +0200 Subject: omogucena komunikacija sa bazom #4 --- Backend/Api/Api/Api.csproj | 3 +-- Backend/Api/Api/Database/DatabaseConnection.cs | 10 ++++++++++ Backend/Api/Api/Interfaces/IDatabaseConnection.cs | 8 ++++++++ Backend/Api/Api/Program.cs | 14 ++++++++++++++ Backend/Api/Api/appsettings.json | 8 +++++++- 5 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 Backend/Api/Api/Database/DatabaseConnection.cs create mode 100644 Backend/Api/Api/Interfaces/IDatabaseConnection.cs (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Api.csproj b/Backend/Api/Api/Api.csproj index 8732b1d..f8d2732 100644 --- a/Backend/Api/Api/Api.csproj +++ b/Backend/Api/Api/Api.csproj @@ -7,14 +7,13 @@ + - - diff --git a/Backend/Api/Api/Database/DatabaseConnection.cs b/Backend/Api/Api/Database/DatabaseConnection.cs new file mode 100644 index 0000000..560eaee --- /dev/null +++ b/Backend/Api/Api/Database/DatabaseConnection.cs @@ -0,0 +1,10 @@ +using Api.Interfaces; + +namespace Api.Database +{ + public class DatabaseConnection : IDatabaseConnection + { + public string ConnectionString { get; set; } = String.Empty; + public string DatabaseName { get; set; } = String.Empty; + } +} diff --git a/Backend/Api/Api/Interfaces/IDatabaseConnection.cs b/Backend/Api/Api/Interfaces/IDatabaseConnection.cs new file mode 100644 index 0000000..ca5e320 --- /dev/null +++ b/Backend/Api/Api/Interfaces/IDatabaseConnection.cs @@ -0,0 +1,8 @@ +namespace Api.Interfaces +{ + public interface IDatabaseConnection + { + string ConnectionString { get; set; } + string DatabaseName { get; set; } + } +} diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs index df2434c..2dfd84d 100644 --- a/Backend/Api/Api/Program.cs +++ b/Backend/Api/Api/Program.cs @@ -1,7 +1,21 @@ +using Api.Database; +using Api.Interfaces; +using Microsoft.Extensions.Options; +using MongoDB.Driver; + var builder = WebApplication.CreateBuilder(args); // Add services to the container. +builder.Services.Configure( + builder.Configuration.GetSection("DatabaseSettings")); + +builder.Services.AddSingleton(sp => + sp.GetRequiredService>().Value); + +builder.Services.AddSingleton(s => + new MongoClient(builder.Configuration.GetValue("DatabaseSettings:ConnectionString"))); + builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/Backend/Api/Api/appsettings.json b/Backend/Api/Api/appsettings.json index 10f68b8..c2cbe28 100644 --- a/Backend/Api/Api/appsettings.json +++ b/Backend/Api/Api/appsettings.json @@ -5,5 +5,11 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "DatabaseSettings": { + + "ConnectionString": "mongodb://127.0.0.1:27017/", + "DatabaseName": "Odyssey" + + } } -- cgit v1.2.3 From 9f4a1d3f03848a86c12b0f758b525ff62e76e680 Mon Sep 17 00:00:00 2001 From: Jelena Petrovic Date: Thu, 27 Oct 2022 02:40:28 +0200 Subject: dodat model i servis za korisnike, sa osnovnim operacijama #5 --- Backend/Api/Api/Api.csproj | 2 - Backend/Api/Api/Database/DatabaseConnection.cs | 1 + Backend/Api/Api/Interfaces/IDatabaseConnection.cs | 1 + Backend/Api/Api/Interfaces/IUserService.cs | 14 ++++++ Backend/Api/Api/Models/User.cs | 17 +++++++ Backend/Api/Api/Program.cs | 3 ++ Backend/Api/Api/Services/UserService.cs | 58 +++++++++++++++++++++++ Backend/Api/Api/appsettings.json | 3 +- 8 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 Backend/Api/Api/Interfaces/IUserService.cs create mode 100644 Backend/Api/Api/Models/User.cs create mode 100644 Backend/Api/Api/Services/UserService.cs (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Api.csproj b/Backend/Api/Api/Api.csproj index f8d2732..eeacb93 100644 --- a/Backend/Api/Api/Api.csproj +++ b/Backend/Api/Api/Api.csproj @@ -13,8 +13,6 @@ - - diff --git a/Backend/Api/Api/Database/DatabaseConnection.cs b/Backend/Api/Api/Database/DatabaseConnection.cs index 560eaee..65f4f52 100644 --- a/Backend/Api/Api/Database/DatabaseConnection.cs +++ b/Backend/Api/Api/Database/DatabaseConnection.cs @@ -6,5 +6,6 @@ namespace Api.Database { public string ConnectionString { get; set; } = String.Empty; public string DatabaseName { get; set; } = String.Empty; + public string UserCollectionName { get; set; } = String.Empty; } } diff --git a/Backend/Api/Api/Interfaces/IDatabaseConnection.cs b/Backend/Api/Api/Interfaces/IDatabaseConnection.cs index ca5e320..8938127 100644 --- a/Backend/Api/Api/Interfaces/IDatabaseConnection.cs +++ b/Backend/Api/Api/Interfaces/IDatabaseConnection.cs @@ -4,5 +4,6 @@ { string ConnectionString { get; set; } string DatabaseName { get; set; } + string UserCollectionName { get; set; } } } diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs new file mode 100644 index 0000000..6de648e --- /dev/null +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -0,0 +1,14 @@ +using Api.Models; + +namespace Api.Interfaces +{ + public interface IUserService + { + User createUser(User user); + List getUsers(); + User getUserByEmail(String email); + User getUserByUsername(String username); + User updateUser(User user); + Boolean deleteUser(String email); + } +} diff --git a/Backend/Api/Api/Models/User.cs b/Backend/Api/Api/Models/User.cs new file mode 100644 index 0000000..eb7d1e8 --- /dev/null +++ b/Backend/Api/Api/Models/User.cs @@ -0,0 +1,17 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; + +namespace Api.Models +{ + public class User + { + [BsonId] + [BsonRepresentation(BsonType.ObjectId)] + public String _id { get; set; } + public String name { get; set; } + public String username { get; set; } + public String email { get; set; } + public String password { get; set; } + public DateTime creationDate { get; set; } + } +} diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs index 2dfd84d..7ae8798 100644 --- a/Backend/Api/Api/Program.cs +++ b/Backend/Api/Api/Program.cs @@ -1,5 +1,6 @@ using Api.Database; using Api.Interfaces; +using Api.Services; using Microsoft.Extensions.Options; using MongoDB.Driver; @@ -16,6 +17,8 @@ builder.Services.AddSingleton(sp => builder.Services.AddSingleton(s => new MongoClient(builder.Configuration.GetValue("DatabaseSettings:ConnectionString"))); +builder.Services.AddScoped(); + builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs new file mode 100644 index 0000000..787cf6a --- /dev/null +++ b/Backend/Api/Api/Services/UserService.cs @@ -0,0 +1,58 @@ +using Api.Interfaces; +using Api.Models; +using MongoDB.Driver; + +namespace Api.Services +{ + public class UserService : IUserService + { + private readonly IMongoCollection _users; + public UserService(IDatabaseConnection settings, IMongoClient mongoClient) + { + var database = mongoClient.GetDatabase(settings.DatabaseName); + _users = database.GetCollection(settings.UserCollectionName); + + } + + public User createUser(User user) + { + _users.InsertOne(user); + return user; + } + + public bool deleteUser(string email) + { + _users.FindOneAndDelete(x => x.email == email); + return true; + } + + public User getUserByEmail(string email) + { + return _users.Find(x => x.email == email).First(); + } + + public User getUserByUsername(string username) + { + return _users.Find(x => x.username == username).First(); + } + + public List getUsers() + { + return _users.Find(_=>true).ToList(); + } + + public User updateUser(User user) + { + /* + * ovako je odradjeno da bi radilo i kada se posalje potpuno novi objekat User-a bez generisanog _id polja + */ + User foundUser = _users.Find(x => x.email == user.email).First(); + if (foundUser!=null && user._id==null) + { + user._id = foundUser._id; + } + _users.ReplaceOne(x => x.email == user.email, user); + return user; + } + } +} diff --git a/Backend/Api/Api/appsettings.json b/Backend/Api/Api/appsettings.json index c2cbe28..e02ac8d 100644 --- a/Backend/Api/Api/appsettings.json +++ b/Backend/Api/Api/appsettings.json @@ -9,7 +9,8 @@ "DatabaseSettings": { "ConnectionString": "mongodb://127.0.0.1:27017/", - "DatabaseName": "Odyssey" + "DatabaseName": "Odyssey", + "UserCollectionName": "users" } } -- cgit v1.2.3 From 0882a4220556bdc271117b88098f51494055d847 Mon Sep 17 00:00:00 2001 From: Jelena Petrovic Date: Thu, 27 Oct 2022 16:45:11 +0200 Subject: prepravljene operacije tako da budu asinhrone #5 --- Backend/Api/Api/Interfaces/IUserService.cs | 12 +++++----- Backend/Api/Api/Services/UserService.cs | 37 ++++++++++++++++-------------- 2 files changed, 26 insertions(+), 23 deletions(-) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs index 6de648e..63fbd18 100644 --- a/Backend/Api/Api/Interfaces/IUserService.cs +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -4,11 +4,11 @@ namespace Api.Interfaces { public interface IUserService { - User createUser(User user); - List getUsers(); - User getUserByEmail(String email); - User getUserByUsername(String username); - User updateUser(User user); - Boolean deleteUser(String email); + Task createUser(User user); + Task> getUsers(); + Task getUserByEmail(String email); + Task getUserByUsername(String username); + Task updateUser(User user); + Task deleteUser(String email); } } diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index 787cf6a..264085c 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -14,45 +14,48 @@ namespace Api.Services } - public User createUser(User user) + public async Task createUser(User user) { - _users.InsertOne(user); - return user; + await _users.InsertOneAsync(user); + } - public bool deleteUser(string email) + public async Task deleteUser(string email) { - _users.FindOneAndDelete(x => x.email == email); - return true; + return await _users.FindOneAndDeleteAsync(x => x.email == email); } - public User getUserByEmail(string email) + public async Task getUserByEmail(string email) { - return _users.Find(x => x.email == email).First(); + return await _users.Find(x => x.email == email).SingleAsync(); } - public User getUserByUsername(string username) + public async Task getUserByUsername(string username) { - return _users.Find(x => x.username == username).First(); + return await _users.Find(x => x.username == username).SingleAsync(); } - public List getUsers() + public async Task> getUsers() { - return _users.Find(_=>true).ToList(); + return await _users.Find(_=>true).ToListAsync(); } - public User updateUser(User user) + public async Task updateUser(User user) { - /* + /* vraca broj izmenjenih korisnika * ovako je odradjeno da bi radilo i kada se posalje potpuno novi objekat User-a bez generisanog _id polja */ - User foundUser = _users.Find(x => x.email == user.email).First(); + User foundUser = await _users.Find(x => x.email == user.email).SingleAsync(); if (foundUser!=null && user._id==null) { user._id = foundUser._id; } - _users.ReplaceOne(x => x.email == user.email, user); - return user; + ReplaceOneResult res=await _users.ReplaceOneAsync(x => x.email == user.email, user); + if(res.IsAcknowledged) + return res.ModifiedCount; + return 0; } + + } } -- cgit v1.2.3 From e24cede22468991ad8452fbf1eec139e1b5ff886 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Thu, 27 Oct 2022 21:09:08 +0200 Subject: Napravljen servis za generisanje jwt tokena. Omoguceno koriscenje autentikacija. --- Backend/Api/Api/Api.csproj | 2 ++ Backend/Api/Api/Interfaces/IJwtService.cs | 9 ++++++++ Backend/Api/Api/Program.cs | 24 +++++++++++++++++++++ Backend/Api/Api/Services/JwtService.cs | 35 +++++++++++++++++++++++++++++++ Backend/Api/Api/appsettings.json | 28 ++++++++++++++----------- 5 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 Backend/Api/Api/Interfaces/IJwtService.cs create mode 100644 Backend/Api/Api/Services/JwtService.cs (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Api.csproj b/Backend/Api/Api/Api.csproj index eeacb93..5f63f8e 100644 --- a/Backend/Api/Api/Api.csproj +++ b/Backend/Api/Api/Api.csproj @@ -7,8 +7,10 @@ + + diff --git a/Backend/Api/Api/Interfaces/IJwtService.cs b/Backend/Api/Api/Interfaces/IJwtService.cs new file mode 100644 index 0000000..075ea6c --- /dev/null +++ b/Backend/Api/Api/Interfaces/IJwtService.cs @@ -0,0 +1,9 @@ +using Api.Models; + +namespace Api.Interfaces +{ + public interface IJwtService + { + Task GenToken(User user); + } +} \ No newline at end of file diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs index 7ae8798..2c2a444 100644 --- a/Backend/Api/Api/Program.cs +++ b/Backend/Api/Api/Program.cs @@ -1,7 +1,10 @@ +using System.Text; using Api.Database; 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); @@ -19,6 +22,24 @@ builder.Services.AddSingleton(s => builder.Services.AddScoped(); + + + +//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(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); @@ -35,6 +56,9 @@ if (app.Environment.IsDevelopment()) app.UseAuthorization(); +//Add Authentication +app.UseAuthentication(); + app.MapControllers(); app.Run(); diff --git a/Backend/Api/Api/Services/JwtService.cs b/Backend/Api/Api/Services/JwtService.cs new file mode 100644 index 0000000..0700619 --- /dev/null +++ b/Backend/Api/Api/Services/JwtService.cs @@ -0,0 +1,35 @@ +using System.Data; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using System.Xml.Linq; +using Api.Interfaces; +using Api.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.IdentityModel.Tokens; + +namespace Api.Services +{ + public class JwtService : IJwtService + { + private readonly IConfiguration _config; + public JwtService(IConfiguration config) + { + _config = config; + } + + public async Task GenToken(User user) + { + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:JwtToken").Value); + var tokenDescriptor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(new[] { new Claim("id", user._id) }), + Expires = DateTime.UtcNow.AddDays(7), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + }; + var token = tokenHandler.CreateToken(tokenDescriptor); + return tokenHandler.WriteToken(token); + } + } +} diff --git a/Backend/Api/Api/appsettings.json b/Backend/Api/Api/appsettings.json index e02ac8d..7cc504d 100644 --- a/Backend/Api/Api/appsettings.json +++ b/Backend/Api/Api/appsettings.json @@ -1,16 +1,20 @@ { - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*", - "DatabaseSettings": { + "AppSettings": { + "JwtToken": "PjrVqQJ1P2VOkuWLw7NaZUluT4z7bkau" + }, + + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "DatabaseSettings": { - "ConnectionString": "mongodb://127.0.0.1:27017/", - "DatabaseName": "Odyssey", - "UserCollectionName": "users" + "ConnectionString": "mongodb://127.0.0.1:27017/", + "DatabaseName": "Odyssey", + "UserCollectionName": "users" - } + } } -- cgit v1.2.3 From 8bfb37503f6af6dac4bf067337d851cedace1c67 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Thu, 27 Oct 2022 21:36:34 +0200 Subject: Omoguceno refreshovanje tokena. Dodata mogucnost da se iz jwt-a izvuce id korisnika. --- Backend/Api/Api/Interfaces/IJwtService.cs | 3 +++ Backend/Api/Api/Interfaces/IUserService.cs | 1 + Backend/Api/Api/Program.cs | 1 + Backend/Api/Api/Services/JwtService.cs | 40 +++++++++++++++++++++++++++++- Backend/Api/Api/Services/UserService.cs | 6 +++++ 5 files changed, 50 insertions(+), 1 deletion(-) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Interfaces/IJwtService.cs b/Backend/Api/Api/Interfaces/IJwtService.cs index 075ea6c..35f5843 100644 --- a/Backend/Api/Api/Interfaces/IJwtService.cs +++ b/Backend/Api/Api/Interfaces/IJwtService.cs @@ -5,5 +5,8 @@ namespace Api.Interfaces public interface IJwtService { Task GenToken(User user); + Task TokenToId(string token); + Task RenewToken(string existingToken); + } } \ No newline at end of file diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs index 63fbd18..8b6f6fc 100644 --- a/Backend/Api/Api/Interfaces/IUserService.cs +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -10,5 +10,6 @@ namespace Api.Interfaces Task getUserByUsername(String username); Task updateUser(User user); Task deleteUser(String email); + Task getUserById(string id); } } diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs index 2c2a444..1059a82 100644 --- a/Backend/Api/Api/Program.cs +++ b/Backend/Api/Api/Program.cs @@ -21,6 +21,7 @@ builder.Services.AddSingleton(s => new MongoClient(builder.Configuration.GetValue("DatabaseSettings:ConnectionString"))); builder.Services.AddScoped(); +builder.Services.AddScoped(); diff --git a/Backend/Api/Api/Services/JwtService.cs b/Backend/Api/Api/Services/JwtService.cs index 0700619..a10f093 100644 --- a/Backend/Api/Api/Services/JwtService.cs +++ b/Backend/Api/Api/Services/JwtService.cs @@ -13,9 +13,11 @@ namespace Api.Services public class JwtService : IJwtService { private readonly IConfiguration _config; - public JwtService(IConfiguration config) + private readonly IUserService _userService; + public JwtService(IConfiguration config,IUserService userService) { _config = config; + _userService = userService; } public async Task GenToken(User user) @@ -31,5 +33,41 @@ namespace Api.Services var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } + public async Task TokenToId(string token) + { + if (token == null) + return null; + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:JwtToken").Value); + try + { + tokenHandler.ValidateToken(token, new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(key), + ValidateIssuer = false, + ValidateAudience = false, + }, out SecurityToken validatedToken); + + var jwtToken = (JwtSecurityToken)validatedToken; + return jwtToken.Claims.First(x => x.Type == "id").Value; + } + catch + { + return null; + } + + } + + public async Task RenewToken(string existingToken) + { + var id = await TokenToId(existingToken); + if (id == null) + return null; + var user = await _userService.getUserById(id); + + return await GenToken(user); + + } } } diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index 264085c..40cc507 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -40,6 +40,12 @@ namespace Api.Services return await _users.Find(_=>true).ToListAsync(); } + public async Task getUserById(string id) + { + return await _users.Find(user => user._id == id).SingleAsync(); + + } + public async Task updateUser(User user) { /* vraca broj izmenjenih korisnika -- cgit v1.2.3 From cf00223fbf339757b3f1e5de144147eba9af3fa2 Mon Sep 17 00:00:00 2001 From: "branislav.radivojevic" Date: Thu, 27 Oct 2022 21:56:12 +0200 Subject: cors,auth controller,register --- Backend/Api/Api/Api.csproj | 4 --- Backend/Api/Api/Controllers/AuthController.cs | 36 +++++++++++++++++++++++++++ Backend/Api/Api/Interfaces/IUserService.cs | 2 +- Backend/Api/Api/Models/User.cs | 14 +++++++++++ Backend/Api/Api/Program.cs | 11 ++++++++ Backend/Api/Api/Services/UserService.cs | 9 +++++-- 6 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 Backend/Api/Api/Controllers/AuthController.cs (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Api.csproj b/Backend/Api/Api/Api.csproj index eeacb93..91e0755 100644 --- a/Backend/Api/Api/Api.csproj +++ b/Backend/Api/Api/Api.csproj @@ -11,8 +11,4 @@ - - - - diff --git a/Backend/Api/Api/Controllers/AuthController.cs b/Backend/Api/Api/Controllers/AuthController.cs new file mode 100644 index 0000000..b75bd6d --- /dev/null +++ b/Backend/Api/Api/Controllers/AuthController.cs @@ -0,0 +1,36 @@ +using Api.Interfaces; +using Api.Models; +using Microsoft.AspNetCore.Mvc; + +namespace Api.Controllers +{ + [Route("api/auth/")] + public class AuthController : Controller + { + private readonly IUserService _userService; + public AuthController(IUserService userService) + { + _userService = userService; + } + + public async Task> Register([FromBody] Register creds) + { + //this is beyond scuffed and will be cleaned up later, when users,login and controllers are made + User novi = new User(); + novi.email = creds.email; + novi.password = creds.password; + novi.username = creds.username; + novi.name = creds.name; + novi.creationDate = DateTime.Now; + novi._id = ""; + + int ret= await _userService.createUser(novi); + if (ret == -1) + return BadRequest("email already exists"); + if (ret == -2) + return BadRequest("username already exists"); + + return Ok(); + } + } +} diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs index 63fbd18..a2fa0a1 100644 --- a/Backend/Api/Api/Interfaces/IUserService.cs +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -4,7 +4,7 @@ namespace Api.Interfaces { public interface IUserService { - Task createUser(User user); + Task createUser(User user); Task> getUsers(); Task getUserByEmail(String email); Task getUserByUsername(String username); diff --git a/Backend/Api/Api/Models/User.cs b/Backend/Api/Api/Models/User.cs index eb7d1e8..1d351d1 100644 --- a/Backend/Api/Api/Models/User.cs +++ b/Backend/Api/Api/Models/User.cs @@ -14,4 +14,18 @@ namespace Api.Models public String password { get; set; } public DateTime creationDate { get; set; } } + + public class Login + { + public String email { get; set; } + public String password { get; set; } + } + + public class Register + { + public String name { get; set; } + public String username { get; set; } + public String email { get; set; } + public String password { get; set; } + } } diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs index 7ae8798..d00f39f 100644 --- a/Backend/Api/Api/Program.cs +++ b/Backend/Api/Api/Program.cs @@ -24,6 +24,17 @@ builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +builder.Services.AddCors(options => +{ + options.AddPolicy("CorsPolicy", + builder => + builder + .AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); +}); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index 264085c..fc582b5 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -14,10 +14,15 @@ namespace Api.Services } - public async Task createUser(User user) + public async Task createUser(User user) { - await _users.InsertOneAsync(user); + if (await _users.Find(x => x.email == user.email).FirstOrDefaultAsync() != null) + return -1; //email already exists + if (await _users.Find(x => x.username == user.username).FirstOrDefaultAsync() != null) + return -2; //username already exists + await _users.InsertOneAsync(user); + return 1; } public async Task deleteUser(string email) -- cgit v1.2.3 From 3193cbe98f170f5ce46d20139e77bc8113b98d70 Mon Sep 17 00:00:00 2001 From: "branislav.radivojevic" Date: Thu, 27 Oct 2022 22:01:02 +0200 Subject: controller path --- Backend/Api/Api/Controllers/AuthController.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Controllers/AuthController.cs b/Backend/Api/Api/Controllers/AuthController.cs index b75bd6d..456abd9 100644 --- a/Backend/Api/Api/Controllers/AuthController.cs +++ b/Backend/Api/Api/Controllers/AuthController.cs @@ -13,6 +13,7 @@ namespace Api.Controllers _userService = userService; } + [HttpPost("register")] public async Task> Register([FromBody] Register creds) { //this is beyond scuffed and will be cleaned up later, when users,login and controllers are made -- cgit v1.2.3 From 6b1650af927b4fb17cbadb145dfec598341f5cdf Mon Sep 17 00:00:00 2001 From: "branislav.radivojevic" Date: Fri, 28 Oct 2022 12:22:55 +0200 Subject: Registration with email verification (unfinished) --- Backend/Api/Api/Interfaces/IJwtService.cs | 7 +++-- Backend/Api/Api/Models/User.cs | 2 ++ Backend/Api/Api/Services/JwtService.cs | 50 +++++++++++++++++++++++++++---- Backend/Api/Api/Services/UserService.cs | 47 +++++++++++++++++++++++++++-- Backend/Api/Api/appsettings.json | 22 +++++++++----- 5 files changed, 109 insertions(+), 19 deletions(-) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Interfaces/IJwtService.cs b/Backend/Api/Api/Interfaces/IJwtService.cs index 35f5843..adb83a2 100644 --- a/Backend/Api/Api/Interfaces/IJwtService.cs +++ b/Backend/Api/Api/Interfaces/IJwtService.cs @@ -4,9 +4,10 @@ namespace Api.Interfaces { public interface IJwtService { - Task GenToken(User user); - Task TokenToId(string token); + string GenToken(User user); + string TokenToId(string token); Task RenewToken(string existingToken); - + public string GenEmailToken(User user); + public string EmailTokenToId(string token); } } \ No newline at end of file diff --git a/Backend/Api/Api/Models/User.cs b/Backend/Api/Api/Models/User.cs index 1d351d1..e9947a2 100644 --- a/Backend/Api/Api/Models/User.cs +++ b/Backend/Api/Api/Models/User.cs @@ -11,6 +11,8 @@ namespace Api.Models public String name { get; set; } public String username { get; set; } public String email { get; set; } + public String emailToken { get; set; } + public Boolean verified { get; set; } public String password { get; set; } public DateTime creationDate { get; set; } } diff --git a/Backend/Api/Api/Services/JwtService.cs b/Backend/Api/Api/Services/JwtService.cs index a10f093..42716fa 100644 --- a/Backend/Api/Api/Services/JwtService.cs +++ b/Backend/Api/Api/Services/JwtService.cs @@ -20,7 +20,7 @@ namespace Api.Services _userService = userService; } - public async Task GenToken(User user) + public string GenToken(User user) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:JwtToken").Value); @@ -33,7 +33,7 @@ namespace Api.Services var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } - public async Task TokenToId(string token) + public string TokenToId(string token) { if (token == null) return null; @@ -58,16 +58,56 @@ namespace Api.Services } } - public async Task RenewToken(string existingToken) { - var id = await TokenToId(existingToken); + var id = TokenToId(existingToken); if (id == null) return null; var user = await _userService.getUserById(id); - return await GenToken(user); + return GenToken(user); } + public string GenEmailToken(User user) + { + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:EmailToken").Value); + var tokenDescriptor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(new[] { new Claim("username", user.username), new Claim("id", user._id) }), + Expires = DateTime.UtcNow.AddMinutes(30), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + }; + var token = tokenHandler.CreateToken(tokenDescriptor); + return tokenHandler.WriteToken(token); + } + + public string EmailTokenToId(string token) + { + if (token == null) + return null; + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:EmailToken").Value.ToString()); + try + { + tokenHandler.ValidateToken(token, new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(key), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }, + out SecurityToken validatedToken); + var jwtToken = (JwtSecurityToken)validatedToken; + var username = (jwtToken.Claims.First(x => x.Type == "username").Value.ToString()); + return username; + //return jwtToken.Claims.First(x => x.Type == "id").Value; + } + catch + { + return null; + } + } } } diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index 2940d2e..b632ebc 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -7,11 +7,12 @@ namespace Api.Services public class UserService : IUserService { private readonly IMongoCollection _users; - public UserService(IDatabaseConnection settings, IMongoClient mongoClient) + private readonly IJwtService _jwtService; + public UserService(IDatabaseConnection settings, IMongoClient mongoClient, IJwtService jwtService) { var database = mongoClient.GetDatabase(settings.DatabaseName); _users = database.GetCollection(settings.UserCollectionName); - + _jwtService=jwtService; } public async Task createUser(User user) @@ -67,6 +68,46 @@ namespace Api.Services return 0; } - + public async Task Register(Register register) + { + if (await _users.FindAsync(x => x.email == register.email && x.verified==true).Result.AnyAsync()) + return "Email Exists"; + else if (await _users.FindAsync(x => x.username == register.username && x.verified==true).Result.AnyAsync()) + return "Username Exists"; + else + { + List unverified = await _users.Find(x => (x.username == register.username || x.email == register.email) && x.verified == false).ToListAsync(); + if (unverified.Count > 0) + { + foreach(var usr in unverified) + { + //ako user nema validan emailtoken, a nije verifikovan prethodno, onda se brise iz baze + if (_jwtService.EmailTokenToId(usr.emailToken) == null) + await _users.FindOneAndDeleteAsync(x => x._id == usr._id); + } + } + } + var user = new User(); + user.email = register.email; + user.username = register.username; + user.name = register.name; + user.verified = false; + user.password = register.password; // unhashed for now + + + return ""; + } + + public async Task VerifyUser(string _id) + { + User user = await _users.FindAsync(x => x._id==_id).Result.FirstAsync(); + if(user != null) + { + user.verified = true; + await _users.ReplaceOneAsync(x => x._id == _id, user); + return true; + } + return false; + } } } diff --git a/Backend/Api/Api/appsettings.json b/Backend/Api/Api/appsettings.json index 7cc504d..aa9b675 100644 --- a/Backend/Api/Api/appsettings.json +++ b/Backend/Api/Api/appsettings.json @@ -1,7 +1,8 @@ { - "AppSettings": { - "JwtToken": "PjrVqQJ1P2VOkuWLw7NaZUluT4z7bkau" - }, + "AppSettings": { + "JwtToken": "PjrVqQJ1P2VOkuWLw7NaZUluT4z7bkau", + "EmailToken": "e8X8c0lm9KS7itWi3wgE6BiPXR21WPvO" + }, "Logging": { "LogLevel": { @@ -10,11 +11,16 @@ } }, "AllowedHosts": "*", - "DatabaseSettings": { + "DatabaseSettings": { - "ConnectionString": "mongodb://127.0.0.1:27017/", - "DatabaseName": "Odyssey", - "UserCollectionName": "users" + "ConnectionString": "mongodb://127.0.0.1:27017/", + "DatabaseName": "Odyssey", + "UserCollectionName": "users" - } + }, + "EmailCfg": { + "Email": "oddyssey.brzodolokacije@gmail.com", + "SmtpServer": "smtp.gmail.com", + "Password": "msbs#556" + } } -- cgit v1.2.3 From 8e18b80aad411299de44a71668833b05c93dc156 Mon Sep 17 00:00:00 2001 From: "branislav.radivojevic" Date: Fri, 28 Oct 2022 13:27:11 +0200 Subject: moved renewtoken to prevent recursive call --- Backend/Api/Api/Interfaces/IJwtService.cs | 1 - Backend/Api/Api/Interfaces/IUserService.cs | 1 + Backend/Api/Api/Services/JwtService.cs | 14 +------------- Backend/Api/Api/Services/UserService.cs | 11 +++++++++++ 4 files changed, 13 insertions(+), 14 deletions(-) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Interfaces/IJwtService.cs b/Backend/Api/Api/Interfaces/IJwtService.cs index adb83a2..1a8fb0a 100644 --- a/Backend/Api/Api/Interfaces/IJwtService.cs +++ b/Backend/Api/Api/Interfaces/IJwtService.cs @@ -6,7 +6,6 @@ namespace Api.Interfaces { string GenToken(User user); string TokenToId(string token); - Task RenewToken(string existingToken); public string GenEmailToken(User user); public string EmailTokenToId(string token); } diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs index 33c0889..8faad45 100644 --- a/Backend/Api/Api/Interfaces/IUserService.cs +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -11,5 +11,6 @@ namespace Api.Interfaces Task updateUser(User user); Task deleteUser(String email); Task getUserById(string id); + Task RenewToken(string existingToken); } } diff --git a/Backend/Api/Api/Services/JwtService.cs b/Backend/Api/Api/Services/JwtService.cs index 42716fa..37ec88e 100644 --- a/Backend/Api/Api/Services/JwtService.cs +++ b/Backend/Api/Api/Services/JwtService.cs @@ -13,11 +13,9 @@ namespace Api.Services public class JwtService : IJwtService { private readonly IConfiguration _config; - private readonly IUserService _userService; - public JwtService(IConfiguration config,IUserService userService) + public JwtService(IConfiguration config) { _config = config; - _userService = userService; } public string GenToken(User user) @@ -57,16 +55,6 @@ namespace Api.Services return null; } - } - public async Task RenewToken(string existingToken) - { - var id = TokenToId(existingToken); - if (id == null) - return null; - var user = await _userService.getUserById(id); - - return GenToken(user); - } public string GenEmailToken(User user) { diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index b632ebc..1260814 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -109,5 +109,16 @@ namespace Api.Services } return false; } + + public async Task RenewToken(string existingToken) + { + var id = _jwtService.TokenToId(existingToken); + if (id == null) + return null; + var user = await getUserById(id); + + return _jwtService.GenToken(user); + + } } } -- cgit v1.2.3 From 174a2de4261dc2f4ea89e20a661a6a69475ed45a Mon Sep 17 00:00:00 2001 From: "branislav.radivojevic" Date: Fri, 28 Oct 2022 15:58:37 +0200 Subject: login and register pw encrypt, return jwt --- Backend/Api/Api/Api.csproj | 1 + Backend/Api/Api/Controllers/AuthController.cs | 13 ++++++ Backend/Api/Api/Interfaces/IJwtService.cs | 2 +- Backend/Api/Api/Interfaces/IUserService.cs | 6 +++ Backend/Api/Api/Program.cs | 2 + Backend/Api/Api/Services/JwtService.cs | 5 +-- Backend/Api/Api/Services/UserService.cs | 62 ++++++++++++++++++++++++--- 7 files changed, 82 insertions(+), 9 deletions(-) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Api.csproj b/Backend/Api/Api/Api.csproj index dc8b264..10faa3e 100644 --- a/Backend/Api/Api/Api.csproj +++ b/Backend/Api/Api/Api.csproj @@ -11,6 +11,7 @@ + diff --git a/Backend/Api/Api/Controllers/AuthController.cs b/Backend/Api/Api/Controllers/AuthController.cs index 456abd9..6727125 100644 --- a/Backend/Api/Api/Controllers/AuthController.cs +++ b/Backend/Api/Api/Controllers/AuthController.cs @@ -33,5 +33,18 @@ namespace Api.Controllers return Ok(); } + [HttpPost("login")] + public async Task> Login([FromBody] Login creds) + { + var id = await _userService.UserIdFromJwt(); + if (id != null) return Forbid(); + + var jwt= await _userService.Login(creds); + if (jwt != null) + { + return Ok(new { token = jwt }); + } + return BadRequest(); + } } } diff --git a/Backend/Api/Api/Interfaces/IJwtService.cs b/Backend/Api/Api/Interfaces/IJwtService.cs index 1a8fb0a..f9e5d5f 100644 --- a/Backend/Api/Api/Interfaces/IJwtService.cs +++ b/Backend/Api/Api/Interfaces/IJwtService.cs @@ -6,7 +6,7 @@ namespace Api.Interfaces { string GenToken(User user); string TokenToId(string token); - public string GenEmailToken(User user); + public string GenEmailToken(string username); public string EmailTokenToId(string token); } } \ No newline at end of file diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs index 8faad45..9e4e3b9 100644 --- a/Backend/Api/Api/Interfaces/IUserService.cs +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -11,6 +11,12 @@ namespace Api.Interfaces Task updateUser(User user); Task deleteUser(String email); Task getUserById(string id); + Task RenewToken(string existingToken); + Task Login(Login login); + Task Register(Register register); + Task VerifyUser(string _id); + Task UserIdFromJwt(); + } } diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs index 26ed445..4643937 100644 --- a/Backend/Api/Api/Program.cs +++ b/Backend/Api/Api/Program.cs @@ -23,6 +23,8 @@ builder.Services.AddSingleton(s => builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddHttpContextAccessor(); + diff --git a/Backend/Api/Api/Services/JwtService.cs b/Backend/Api/Api/Services/JwtService.cs index 37ec88e..e3688de 100644 --- a/Backend/Api/Api/Services/JwtService.cs +++ b/Backend/Api/Api/Services/JwtService.cs @@ -56,13 +56,13 @@ namespace Api.Services } } - public string GenEmailToken(User user) + public string GenEmailToken(string username) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:EmailToken").Value); var tokenDescriptor = new SecurityTokenDescriptor { - Subject = new ClaimsIdentity(new[] { new Claim("username", user.username), new Claim("id", user._id) }), + Subject = new ClaimsIdentity(new[] { new Claim("username", username)}), Expires = DateTime.UtcNow.AddMinutes(30), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; @@ -90,7 +90,6 @@ namespace Api.Services var jwtToken = (JwtSecurityToken)validatedToken; var username = (jwtToken.Claims.First(x => x.Type == "username").Value.ToString()); return username; - //return jwtToken.Claims.First(x => x.Type == "id").Value; } catch { diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index 1260814..7c00c05 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -1,18 +1,22 @@ using Api.Interfaces; using Api.Models; using MongoDB.Driver; +using Microsoft.AspNetCore.Http; +using System.Security.Claims; namespace Api.Services { public class UserService : IUserService { + private readonly IHttpContextAccessor _httpContext; private readonly IMongoCollection _users; private readonly IJwtService _jwtService; - public UserService(IDatabaseConnection settings, IMongoClient mongoClient, IJwtService jwtService) + public UserService(IDatabaseConnection settings, IMongoClient mongoClient, IJwtService jwtService, IHttpContextAccessor httpContextAccessor) { var database = mongoClient.GetDatabase(settings.DatabaseName); _users = database.GetCollection(settings.UserCollectionName); _jwtService=jwtService; + this._httpContext = httpContextAccessor; } public async Task createUser(User user) @@ -20,8 +24,9 @@ namespace Api.Services if (await _users.Find(x => x.email == user.email).FirstOrDefaultAsync() != null) return -1; //email already exists if (await _users.Find(x => x.username == user.username).FirstOrDefaultAsync() != null) - return -2; //username already exists - + return -2; //username already + // + user.password = hashPassword(user.password); await _users.InsertOneAsync(user); return 1; } @@ -68,6 +73,29 @@ namespace Api.Services return 0; } + private static int difficulty = 10; + + public static String hashPassword(String password) + { + String salt = BCrypt.Net.BCrypt.GenerateSalt(difficulty); + String passwordHash = BCrypt.Net.BCrypt.HashPassword(password, salt); + + return passwordHash; + } + + public static Boolean checkPassword(String plainText, String hash) + { + Boolean verified = false; + + if (hash == null || !hash.StartsWith("$2a$")) + return false; + + verified = BCrypt.Net.BCrypt.Verify(plainText, hash); + + return verified; + + } + public async Task Register(Register register) { if (await _users.FindAsync(x => x.email == register.email && x.verified==true).Result.AnyAsync()) @@ -87,15 +115,18 @@ namespace Api.Services } } } + var user = new User(); user.email = register.email; user.username = register.username; user.name = register.name; user.verified = false; - user.password = register.password; // unhashed for now + user.password = hashPassword(register.password); + user.emailToken = _jwtService.GenEmailToken(user.username); + await _users.InsertOneAsync(user); - return ""; + return "User Registered"; } public async Task VerifyUser(string _id) @@ -118,7 +149,28 @@ namespace Api.Services var user = await getUserById(id); return _jwtService.GenToken(user); + } + public async Task Login(Login login) + { + User user = await _users.FindAsync(x => x.email == login.email).Result.FirstAsync(); // add && x.verified == true after implementing + if(user != null && checkPassword(login.password, user.password)) + { + return _jwtService.GenToken(user); + } + return null; + } + public async Task UserIdFromJwt() + { + string id = null; + if (_httpContext.HttpContext.User.FindFirstValue("id") != null) + { + id = _httpContext.HttpContext.User.FindFirstValue("id").ToString(); + var _id = await _users.FindAsync(x => x._id == id).Result.FirstAsync(); + if (_id == null) + id = null; + } + return id; } } } -- cgit v1.2.3 From 9f8d6ef3f15f71be7ad4212d943fa13c0f6de072 Mon Sep 17 00:00:00 2001 From: Ognjen Cirkovic Date: Sat, 29 Oct 2022 23:30:08 +0200 Subject: Sitne ispravke. Popravljeno citanje json response-a. --- Backend/Api/Api/Controllers/AuthController.cs | 6 +++--- .../example/brzodolokacije/Fragments/FragmentLogin.kt | 16 ++-------------- .../example/brzodolokacije/Fragments/FragmentRegister.kt | 4 +--- .../example/brzodolokacije/Services/RetrofitHelper.kt | 7 ++++++- .../app/src/main/res/layout/activity_login_register.xml | 1 - 5 files changed, 12 insertions(+), 22 deletions(-) (limited to 'Backend/Api') diff --git a/Backend/Api/Api/Controllers/AuthController.cs b/Backend/Api/Api/Controllers/AuthController.cs index 6727125..5973c8c 100644 --- a/Backend/Api/Api/Controllers/AuthController.cs +++ b/Backend/Api/Api/Controllers/AuthController.cs @@ -22,7 +22,7 @@ namespace Api.Controllers novi.password = creds.password; novi.username = creds.username; novi.name = creds.name; - novi.creationDate = DateTime.Now; + novi.creationDate = DateTime.Now.ToUniversalTime(); novi._id = ""; int ret= await _userService.createUser(novi); @@ -42,9 +42,9 @@ namespace Api.Controllers var jwt= await _userService.Login(creds); if (jwt != null) { - return Ok(new { token = jwt }); + return Ok(jwt); } - return BadRequest(); + return BadRequest("Pogresno uneti podaci"); } } } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt index ab6794c..3bc62bd 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentLogin.kt @@ -29,10 +29,6 @@ class FragmentLogin : Fragment() { private lateinit var emailString:String - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -52,7 +48,6 @@ class FragmentLogin : Fragment() { login.setOnClickListener{ emailString=email.text.toString().trim() passwordString=password.text.toString().trim() - //prazan unos? if(emailString.isEmpty()) { @@ -81,9 +76,7 @@ class FragmentLogin : Fragment() { SharedPreferencesHelper.addValue("jwt",token,activity!!) }else{ if(response.errorBody()!=null) - Toast.makeText( - activity, response.errorBody()!!.string(), Toast.LENGTH_LONG - ).show(); + Toast.makeText(activity, response.errorBody()!!.string(), Toast.LENGTH_LONG).show(); } @@ -91,16 +84,11 @@ class FragmentLogin : Fragment() { override fun onFailure(call: Call, t: Throwable) { Toast.makeText( - activity, "Greska, pokusajte ponovo.", Toast.LENGTH_LONG + activity, t.toString(), Toast.LENGTH_LONG ).show(); } }) - Toast.makeText( - activity, "Korisnik sa unetim podacima nije pronađen. " + "\n" + - "Proverite podatke i pokušajte ponovo", Toast.LENGTH_LONG - ).show(); - } } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt index 4843675..f6300b8 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentRegister.kt @@ -92,9 +92,7 @@ class FragmentRegister : Fragment() { //TODO(navigate to login) }else{ if(response.errorBody()!=null) - Toast.makeText( - activity, response.errorBody()!!.string(), Toast.LENGTH_LONG - ).show(); + Toast.makeText(activity, response.errorBody()!!.string(), Toast.LENGTH_LONG).show() } diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Services/RetrofitHelper.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Services/RetrofitHelper.kt index 5721816..cc7eb56 100644 --- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Services/RetrofitHelper.kt +++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Services/RetrofitHelper.kt @@ -1,13 +1,18 @@ package com.example.brzodolokacije.Services +import com.google.gson.GsonBuilder import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory + object RetrofitHelper { val baseUrl="http://10.0.2.2:5279" fun getInstance():Retrofit{ + val gson = GsonBuilder() + .setLenient() + .create() return Retrofit.Builder().baseUrl(baseUrl) - .addConverterFactory(GsonConverterFactory.create()) + .addConverterFactory(GsonConverterFactory.create(gson)) .build() } } diff --git a/Client/BrzoDoLokacije/app/src/main/res/layout/activity_login_register.xml b/Client/BrzoDoLokacije/app/src/main/res/layout/activity_login_register.xml index 50d903b..ac526e0 100644 --- a/Client/BrzoDoLokacije/app/src/main/res/layout/activity_login_register.xml +++ b/Client/BrzoDoLokacije/app/src/main/res/layout/activity_login_register.xml @@ -9,7 +9,6 @@ android:foregroundTint="#5E010F13" android:foregroundTintMode="add" tools:context=".Activities.ActivityLoginRegister"> -