├── TaskManagementAPP ├── .dockerignore ├── .gitignore ├── Business │ ├── Business.csproj │ ├── Constants │ │ └── Messages.cs │ ├── DependencyResolvers │ │ └── AutofacBusinessModule.cs │ ├── Handlers │ │ ├── Comments │ │ │ ├── Commands │ │ │ │ ├── CreateCommentCommand.cs │ │ │ │ ├── RemoveCommentCommand.cs │ │ │ │ └── UpdateCommentCommand.cs │ │ │ └── Validations │ │ │ │ └── CommentValidator.cs │ │ ├── TaskStatuses │ │ │ └── Queries │ │ │ │ └── GetAllTaskStatusesQuery.cs │ │ ├── Tasks │ │ │ ├── Commands │ │ │ │ ├── CreateTaskCommand.cs │ │ │ │ ├── RemoveTaskCommand.cs │ │ │ │ └── UpdateTaskCommand.cs │ │ │ ├── Queries │ │ │ │ ├── GetTaskDetailByIdQuery.cs │ │ │ │ └── GetTasksByUserIdQuery.cs │ │ │ └── Validations │ │ │ │ └── TaskValidator.cs │ │ └── Users │ │ │ ├── Commands │ │ │ ├── ConfirmEmailCommand.cs │ │ │ ├── LoginCommand.cs │ │ │ └── RegisterCommand.cs │ │ │ ├── Queries │ │ │ ├── GetAuthenticatedUserQuery.cs │ │ │ └── GetUserByEmailQuery.cs │ │ │ └── Validations │ │ │ ├── LoginValidator.cs │ │ │ └── RegisterValidator.cs │ ├── Mappings │ │ └── Automapper.cs │ └── Services │ │ ├── Abstract │ │ └── ITokenService.cs │ │ └── Concrete │ │ └── TokenManager.cs ├── Core │ ├── Aspects │ │ └── Autofac │ │ │ └── Validation │ │ │ └── ValidationAspect.cs │ ├── Configurations │ │ ├── EmailSettings.cs │ │ └── JWTOptions.cs │ ├── Core.csproj │ ├── CrossCuttingConcerns │ │ ├── Logging │ │ │ ├── ErrorLog.cs │ │ │ ├── LogDetail.cs │ │ │ └── SeriLog │ │ │ │ ├── ConfigurationModels │ │ │ │ └── PostgreSqlConfiguration.cs │ │ │ │ ├── LoggerServiceBase.cs │ │ │ │ └── Loggers │ │ │ │ └── PostgreSqlLogger.cs │ │ └── Validation │ │ │ └── FluentValidation │ │ │ └── ValidationTool.cs │ ├── DataAccess │ │ ├── EntityFramework │ │ │ └── EfEntityRepositoryBase.cs │ │ ├── IEntityRepository.cs │ │ └── UnitOfWork.cs │ ├── DependencyResolvers │ │ └── CoreModule.cs │ ├── Entities │ │ ├── IDTO.cs │ │ └── IEntity.cs │ ├── Exceptions │ │ └── ApiException.cs │ └── Utilities │ │ ├── EmailManager.cs │ │ ├── Extensions │ │ ├── ExceptionMiddleware.cs │ │ ├── ExceptionMiddlewareExtensions.cs │ │ └── ServiceCollectionExtensions.cs │ │ ├── FileManager.cs │ │ ├── Helpers │ │ ├── SecurityKeyHelper.cs │ │ └── SigningCredentialsHelper.cs │ │ ├── IEmailService.cs │ │ ├── Interceptors │ │ ├── AspectInterceptorSelector.cs │ │ ├── MethodInterception.cs │ │ └── MethodInterceptionBaseAttribute.cs │ │ ├── IoC │ │ ├── ICoreModule.cs │ │ └── ServiceTool.cs │ │ └── Responses │ │ ├── Abstract │ │ ├── IDataResponse.cs │ │ ├── IErrorResponse.cs │ │ ├── IPagedDataResponse.cs │ │ ├── IResponse.cs │ │ └── ISuccessResponse.cs │ │ └── Concrete │ │ ├── DataResponse.cs │ │ ├── ErrorResponse.cs │ │ ├── PagedDataResponse.cs │ │ ├── Response.cs │ │ └── SuccessResponse.cs ├── DataAccess │ ├── Abstract │ │ ├── ICommentRepository.cs │ │ ├── ITaskRepository.cs │ │ └── ITaskStatusRepository.cs │ ├── Concrete │ │ └── EntityFramework │ │ │ ├── Contexts │ │ │ └── TaskContext.cs │ │ │ ├── EfCommentRepository.cs │ │ │ ├── EfTaskRepository.cs │ │ │ ├── EfTaskStatusRepository.cs │ │ │ └── UnitOfWork │ │ │ └── UnitOfWork.cs │ ├── Configurations │ │ ├── CommentConfiguration.cs │ │ ├── TaskConfiguration.cs │ │ ├── TaskStatusConfiguration.cs │ │ ├── UserConfiguration.cs │ │ └── UserTaskConfiguration.cs │ ├── DataAccess.csproj │ └── Migrations │ │ ├── 20220501210412_CreateDatabase.Designer.cs │ │ ├── 20220501210412_CreateDatabase.cs │ │ └── TaskContextModelSnapshot.cs ├── Entities │ ├── Concrete │ │ ├── Comment.cs │ │ ├── Task.cs │ │ ├── TaskStatus.cs │ │ ├── User.cs │ │ └── UserTask.cs │ ├── Dtos │ │ ├── CommentDTO.cs │ │ ├── TaskDTO.cs │ │ ├── TaskDetailDTO.cs │ │ ├── TaskStatusDTO.cs │ │ ├── TokenDTO.cs │ │ ├── UserDTO.cs │ │ └── UserTaskDTO.cs │ └── Entities.csproj ├── TaskManagementAPP.sln ├── WebAPI │ ├── Controllers │ │ ├── AuthController.cs │ │ ├── CommentsController.cs │ │ ├── TaskStatusesController.cs │ │ └── TasksController.cs │ ├── Dockerfile │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── WebAPI.csproj │ ├── appsettings.Development.json │ └── appsettings.json ├── docker-compose.dcproj └── docker-compose.yml ├── TaskManagementUI ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── .vscode │ ├── extensions.json │ └── settings.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── favicon.ico │ └── icons │ │ ├── favicon-128x128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ └── favicon-96x96.png ├── quasar.config.js ├── src │ ├── App.vue │ ├── assets │ │ └── quasar-logo-vertical.svg │ ├── boot │ │ ├── .gitkeep │ │ └── axios.ts │ ├── components │ │ ├── Alert.vue │ │ ├── CreateTask.vue │ │ ├── Task.vue │ │ └── TaskDetail.vue │ ├── composables │ │ └── useNotify.ts │ ├── css │ │ ├── app.scss │ │ └── quasar.variables.scss │ ├── env.d.ts │ ├── layouts │ │ └── MainLayout.vue │ ├── models │ │ ├── Auth │ │ │ ├── ConfirmEmail.ts │ │ │ ├── Login.ts │ │ │ ├── Register.ts │ │ │ └── TokenDTO.ts │ │ ├── Comment │ │ │ ├── CommentDTO.ts │ │ │ ├── CreateComment.ts │ │ │ └── UpdateComment.ts │ │ ├── Responses │ │ │ ├── DataResponse.ts │ │ │ ├── ErrorResponse.ts │ │ │ └── SuccessResponse.ts │ │ ├── Task │ │ │ ├── CreateTask.ts │ │ │ ├── TaskDTO.ts │ │ │ ├── TaskDetailDTO.ts │ │ │ ├── UpdateTask.ts │ │ │ └── UserTaskDTO.ts │ │ ├── TaskStatus │ │ │ └── TaskStatusDTO.ts │ │ └── UserDTO.ts │ ├── pages │ │ ├── Auth.vue │ │ ├── ConfirmEmail.vue │ │ ├── ErrorNotFound.vue │ │ └── IndexPage.vue │ ├── quasar.d.ts │ ├── router │ │ ├── index.ts │ │ └── routes.ts │ ├── shims-vue.d.ts │ ├── stores │ │ ├── Alert.ts │ │ ├── Auth.ts │ │ ├── Comment.ts │ │ ├── Task.ts │ │ ├── TaskStatus.ts │ │ ├── index.ts │ │ └── store-flag.d.ts │ └── utilities │ │ └── validators.ts ├── tailwind.config.js └── tsconfig.json ├── assets └── taskmanagement.gif └── readme.md /TaskManagementAPP/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /TaskManagementAPP/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Business.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Constants/Messages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Business.Constants 8 | { 9 | public static class Messages 10 | { 11 | 12 | public static string AddedSuccesfully => "Added Successfully"; 13 | public static string UpdatedSuccessfully => "Updated Successfully"; 14 | public static string DeletedSuccessfully => "Deleted Successfully"; 15 | public static string NotFound => "Entity not found"; 16 | 17 | public static string CommentNotYours => "The comment is not yours"; 18 | public static string UserNameOrPasswordIsIncorrect => "Username or password is incorrect"; 19 | public static string ConfirmYourAccount => "Please confirm your account"; 20 | public static string EmailIsAlreadyExist => "Email is already exist"; 21 | public static string UsernameIsAlreadyExist => "Username is already exist"; 22 | public static string PasswordDontMatchWithConfirmation => "Password doesn't match its confirmation"; 23 | public static string RegisterSuccessfully => "Register successfuly please look at your mail box for account confirmation."; 24 | public static string UserNotFound => "User not found"; 25 | public static string TokenOrUserNotFound => "Token or User Not Found"; 26 | public static string RefreshTokenNotFound => "Refresh Token Not Found"; 27 | public static string AlreadyAccountConfirmed => "Already your account confirmed"; 28 | public static string SuccessfullyAccountConfirmed => "Account confirmed successfully.You can login now"; 29 | public static string AccountDontConfirmed => "Account dont Confirmed"; 30 | public static string LogoutSuccessfully => "Logout successfully"; 31 | public static string RefreshTokenExpired => "Refresh Token Expired"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/DependencyResolvers/AutofacBusinessModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Autofac.Extras.DynamicProxy; 3 | using AutoMapper; 4 | using Business.Services.Abstract; 5 | using Business.Services.Concrete; 6 | using Castle.DynamicProxy; 7 | using Core.DataAccess; 8 | using Core.Utilities.Interceptors; 9 | using DataAccess.Abstract; 10 | using DataAccess.Concrete.EntityFramework; 11 | using DataAccess.Concrete.EntityFramework.UnitOfWork; 12 | using MediatR; 13 | 14 | namespace Business.DependencyResolvers 15 | { 16 | public class AutofacBusinessModule : Module 17 | { 18 | protected override void Load(ContainerBuilder builder) 19 | { 20 | builder.RegisterType().As().InstancePerLifetimeScope(); 21 | builder.RegisterType().As().InstancePerLifetimeScope(); 22 | builder.RegisterType().As().InstancePerLifetimeScope(); 23 | builder.RegisterType().As().InstancePerLifetimeScope(); 24 | builder.RegisterType().As().InstancePerLifetimeScope(); 25 | 26 | var assembly = System.Reflection.Assembly.GetExecutingAssembly(); 27 | 28 | builder.RegisterAssemblyTypes(assembly) 29 | .Where(t => typeof(Profile).IsAssignableFrom(t) && !t.IsAbstract && t.IsPublic) 30 | .As(); 31 | 32 | builder.Register(c => new MapperConfiguration(cfg => 33 | { 34 | foreach (var profile in c.Resolve>()) 35 | { 36 | cfg.AddProfile(profile); 37 | } 38 | })).AsSelf().SingleInstance(); 39 | 40 | builder.Register(c => c.Resolve() 41 | .CreateMapper(c.Resolve)) 42 | .As() 43 | .InstancePerLifetimeScope(); 44 | 45 | builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces() 46 | .EnableInterfaceInterceptors(new ProxyGenerationOptions() 47 | { 48 | Selector = new AspectInterceptorSelector() 49 | }).SingleInstance().InstancePerDependency(); 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Comments/Commands/CreateCommentCommand.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Constants; 3 | using Business.Handlers.Comments.Validations; 4 | using Core.Aspects.Autofac.Validation; 5 | using Core.DataAccess; 6 | using Core.Utilities.Responses.Abstract; 7 | using Core.Utilities.Responses.Concrete; 8 | using DataAccess.Abstract; 9 | using Entities.Concrete; 10 | using MediatR; 11 | using Microsoft.AspNetCore.Http; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Linq; 15 | using System.Security.Claims; 16 | using System.Text; 17 | using System.Threading.Tasks; 18 | 19 | namespace Business.Handlers.Comments.Commands 20 | { 21 | public class CreateCommentCommand:IRequest 22 | { 23 | public int TaskId { get; set; } 24 | public string Description { get; set; } 25 | 26 | public class CreateCommentCommandHandler : IRequestHandler 27 | { 28 | private ICommentRepository _commentRepository; 29 | private IMapper _mapper; 30 | private IHttpContextAccessor _httpContextAccessor; 31 | private IUnitOfWork _unitOfWork; 32 | 33 | public CreateCommentCommandHandler(ICommentRepository commentRepository, IMapper mapper, IHttpContextAccessor httpContextAccessor, IUnitOfWork unitOfWork) 34 | { 35 | _commentRepository = commentRepository; 36 | _mapper = mapper; 37 | _httpContextAccessor = httpContextAccessor; 38 | _unitOfWork = unitOfWork; 39 | } 40 | 41 | 42 | [ValidationAspect(typeof(CreateCommentValidator))] 43 | public async Task Handle(CreateCommentCommand request, CancellationToken cancellationToken) 44 | { 45 | var userid = _httpContextAccessor?.HttpContext?.User?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value; 46 | var comment = _mapper.Map(request); 47 | comment.CommentDate = DateTime.UtcNow; 48 | comment.UserId = userid; 49 | await _commentRepository.AddAsync(comment); 50 | await _unitOfWork.SaveChangesAsync(); 51 | return new SuccessResponse(200, Messages.AddedSuccesfully); 52 | } 53 | } 54 | 55 | 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Comments/Commands/RemoveCommentCommand.cs: -------------------------------------------------------------------------------- 1 | using Business.Constants; 2 | using Core.DataAccess; 3 | using Core.Exceptions; 4 | using Core.Utilities.Responses.Abstract; 5 | using Core.Utilities.Responses.Concrete; 6 | using DataAccess.Abstract; 7 | using MediatR; 8 | using Microsoft.AspNetCore.Http; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Security.Claims; 13 | using System.Text; 14 | using System.Threading.Tasks; 15 | 16 | namespace Business.Handlers.Comments.Commands 17 | { 18 | public class RemoveCommentCommand:IRequest 19 | { 20 | public int Id { get; set; } 21 | public RemoveCommentCommand(int id) 22 | { 23 | Id = id; 24 | } 25 | 26 | public class RemoveCommentCommandHandler : IRequestHandler 27 | { 28 | private ICommentRepository _commentRepository; 29 | private IUnitOfWork _unitOfWork; 30 | private IHttpContextAccessor _httpContextAccessor; 31 | 32 | public RemoveCommentCommandHandler(ICommentRepository commentRepository, IUnitOfWork unitOfWork, IHttpContextAccessor httpContextAccessor) 33 | { 34 | _commentRepository = commentRepository; 35 | _unitOfWork = unitOfWork; 36 | _httpContextAccessor = httpContextAccessor; 37 | } 38 | 39 | public async Task Handle(RemoveCommentCommand request, CancellationToken cancellationToken) 40 | { 41 | var userid = _httpContextAccessor?.HttpContext?.User?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value; 42 | var existcomment = await _commentRepository.GetByIdAsync(request.Id); 43 | if (existcomment == null) 44 | { 45 | throw new ApiException(404, Messages.NotFound); 46 | } 47 | if (existcomment.UserId != userid) 48 | { 49 | throw new ApiException(401, Messages.CommentNotYours); 50 | } 51 | _commentRepository.Remove(existcomment); 52 | await _unitOfWork.SaveChangesAsync(); 53 | return new SuccessResponse(200, Messages.DeletedSuccessfully); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Comments/Commands/UpdateCommentCommand.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Constants; 3 | using Business.Handlers.Comments.Validations; 4 | using Core.Aspects.Autofac.Validation; 5 | using Core.DataAccess; 6 | using Core.Exceptions; 7 | using Core.Utilities.Responses.Abstract; 8 | using Core.Utilities.Responses.Concrete; 9 | using DataAccess.Abstract; 10 | using MediatR; 11 | using Microsoft.AspNetCore.Http; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Linq; 15 | using System.Security.Claims; 16 | using System.Text; 17 | using System.Threading.Tasks; 18 | 19 | namespace Business.Handlers.Comments.Commands 20 | { 21 | public class UpdateCommentCommand:IRequest 22 | { 23 | public int Id { get; set; } 24 | public string Description { get; set; } 25 | 26 | public class UpdateCommentCommandHandler : IRequestHandler 27 | { 28 | private ICommentRepository _commentRepository; 29 | private IMapper _mapper; 30 | private IHttpContextAccessor _httpContextAccessor; 31 | private IUnitOfWork _unitOfWork; 32 | 33 | public UpdateCommentCommandHandler(ICommentRepository commentRepository, IMapper mapper, IHttpContextAccessor httpContextAccessor, IUnitOfWork unitOfWork) 34 | { 35 | _commentRepository = commentRepository; 36 | _mapper = mapper; 37 | _httpContextAccessor = httpContextAccessor; 38 | _unitOfWork = unitOfWork; 39 | } 40 | 41 | [ValidationAspect(typeof(UpdateCommentValidator))] 42 | public async Task Handle(UpdateCommentCommand request, CancellationToken cancellationToken) 43 | { 44 | var userid = _httpContextAccessor?.HttpContext?.User?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value; 45 | var existcomment = await _commentRepository.GetByIdAsync(request.Id); 46 | if (existcomment == null) 47 | { 48 | throw new ApiException(404, Messages.NotFound); 49 | } 50 | if (existcomment.UserId != userid) 51 | { 52 | throw new ApiException(401, Messages.CommentNotYours); 53 | } 54 | var updatedcomment = _mapper.Map(request, existcomment); 55 | _commentRepository.Update(updatedcomment); 56 | await _unitOfWork.SaveChangesAsync(); 57 | return new SuccessResponse(200,Messages.UpdatedSuccessfully); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Comments/Validations/CommentValidator.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.Comments.Commands; 2 | using FluentValidation; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Business.Handlers.Comments.Validations 10 | { 11 | public class CreateCommentValidator: AbstractValidator 12 | { 13 | public CreateCommentValidator() 14 | { 15 | RuleFor(x => x.Description).NotEmpty().WithMessage("Description").MinimumLength(5); 16 | RuleFor(x => x.TaskId).NotEmpty().WithMessage("TaskId is required"); 17 | } 18 | } 19 | 20 | public class UpdateCommentValidator : AbstractValidator 21 | { 22 | public UpdateCommentValidator() 23 | { 24 | RuleFor(x => x.Id).NotEmpty().WithMessage("Id is required"); 25 | RuleFor(x => x.Description).NotEmpty().WithMessage("Description").MinimumLength(5); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/TaskStatuses/Queries/GetAllTaskStatusesQuery.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Core.Utilities.Responses.Abstract; 3 | using Core.Utilities.Responses.Concrete; 4 | using DataAccess.Abstract; 5 | using Entities.Dtos; 6 | using MediatR; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace Business.Handlers.TaskStatuses.Queries 14 | { 15 | public class GetAllTaskStatusesQuery : IRequest 16 | { 17 | public class GetAllTaskStatusesQueryHandler : IRequestHandler 18 | { 19 | private ITaskStatusRepository _taskStatusRepository; 20 | private IMapper _mapper; 21 | 22 | public GetAllTaskStatusesQueryHandler(ITaskStatusRepository taskStatusRepository, IMapper mapper) 23 | { 24 | _taskStatusRepository = taskStatusRepository; 25 | _mapper = mapper; 26 | } 27 | 28 | public async Task Handle(GetAllTaskStatusesQuery request, CancellationToken cancellationToken) 29 | { 30 | var taskStatuses = await _taskStatusRepository.GetAllAsync(); 31 | var mappedtaskStatuses = _mapper.Map>(taskStatuses); 32 | return new DataResponse>(mappedtaskStatuses,200); 33 | } 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Tasks/Commands/CreateTaskCommand.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Constants; 3 | using Business.Handlers.Tasks.Validations; 4 | using Core.Aspects.Autofac.Validation; 5 | using Core.DataAccess; 6 | using Core.Utilities.Responses.Abstract; 7 | using Core.Utilities.Responses.Concrete; 8 | using DataAccess.Abstract; 9 | using Entities.Concrete; 10 | using MediatR; 11 | using Microsoft.AspNetCore.Http; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Linq; 15 | using System.Security.Claims; 16 | using System.Text; 17 | using System.Threading.Tasks; 18 | using Task = Entities.Concrete.Task; 19 | 20 | namespace Business.Handlers.Tasks.Commands 21 | { 22 | public class CreateTaskCommand : IRequest 23 | { 24 | public string Title { get; set; } 25 | public string Description { get; set; } 26 | public string StringDeadline { get; set; } 27 | public string[] UserIds { get; set; } 28 | 29 | public class CreateTaskCommandHandler : IRequestHandler 30 | { 31 | private ITaskRepository _taskRepository; 32 | private IUnitOfWork _unitOfWork; 33 | private IHttpContextAccessor _httpContextAccessor; 34 | private IMapper _mapper; 35 | 36 | public CreateTaskCommandHandler(ITaskRepository taskRepository, IUnitOfWork unitOfWork, IHttpContextAccessor httpContextAccessor, IMapper mapper) 37 | { 38 | _taskRepository = taskRepository; 39 | _unitOfWork = unitOfWork; 40 | _httpContextAccessor = httpContextAccessor; 41 | _mapper = mapper; 42 | } 43 | 44 | [ValidationAspect(typeof(CreateTaskValidator))] 45 | public async Task Handle(CreateTaskCommand request, CancellationToken cancellationToken) 46 | { 47 | var userid = _httpContextAccessor?.HttpContext?.User?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value; 48 | var task = _mapper.Map(request); 49 | task.CreatorId = userid; 50 | task.TaskStatusId = 1; 51 | task.Deadline = DateTime.ParseExact(request.StringDeadline, "dd-MM-yyyy HH:mm", null).ToUniversalTime(); 52 | task.UserTasks = request.UserIds.Select(x => new UserTask() { UserId = x, TaskId = task.Id }).ToList(); 53 | await _taskRepository.AddAsync(task); 54 | await _unitOfWork.SaveChangesAsync(); 55 | return new SuccessResponse(200, Messages.AddedSuccesfully); 56 | } 57 | } 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Tasks/Commands/RemoveTaskCommand.cs: -------------------------------------------------------------------------------- 1 | using Business.Constants; 2 | using Core.DataAccess; 3 | using Core.Exceptions; 4 | using Core.Utilities.Responses.Abstract; 5 | using Core.Utilities.Responses.Concrete; 6 | using DataAccess.Abstract; 7 | using MediatR; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace Business.Handlers.Tasks.Commands 15 | { 16 | public class RemoveTaskCommand : IRequest 17 | { 18 | public int Id { get; set; } 19 | public RemoveTaskCommand(int id) 20 | { 21 | Id = id; 22 | } 23 | public class RemoveTaskCommandHandler : IRequestHandler 24 | { 25 | private IUnitOfWork _unitOfWork; 26 | private ITaskRepository _taskRepository; 27 | 28 | public RemoveTaskCommandHandler(IUnitOfWork unitOfWork, ITaskRepository taskRepository) 29 | { 30 | _unitOfWork = unitOfWork; 31 | _taskRepository = taskRepository; 32 | } 33 | 34 | public async Task Handle(RemoveTaskCommand request, CancellationToken cancellationToken) 35 | { 36 | var task = await _taskRepository.GetByIdAsync(request.Id); 37 | if (task == null) 38 | { 39 | throw new ApiException(404, Messages.NotFound); 40 | } 41 | _taskRepository.Remove(task); 42 | await _unitOfWork.SaveChangesAsync(); 43 | return new SuccessResponse(200, Messages.DeletedSuccessfully); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Tasks/Commands/UpdateTaskCommand.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Constants; 3 | using Business.Handlers.Tasks.Validations; 4 | using Core.Aspects.Autofac.Validation; 5 | using Core.DataAccess; 6 | using Core.Exceptions; 7 | using Core.Utilities.Responses.Abstract; 8 | using Core.Utilities.Responses.Concrete; 9 | using DataAccess.Abstract; 10 | using Entities.Concrete; 11 | using MediatR; 12 | using System.Globalization; 13 | 14 | namespace Business.Handlers.Tasks.Commands 15 | { 16 | public class UpdateTaskCommand:IRequest 17 | { 18 | public int Id { get; set; } 19 | public string Title { get; set; } 20 | public string Description { get; set; } 21 | public string StringDeadline { get; set; } 22 | public int TaskStatusId { get; set; } 23 | public string[] UserIds { get; set; } 24 | 25 | 26 | public class UpdateTaskCommandHandler : IRequestHandler 27 | { 28 | private ITaskRepository _taskRepository; 29 | private IUnitOfWork _unitOfWork; 30 | private IMapper _mapper; 31 | 32 | public UpdateTaskCommandHandler(ITaskRepository taskRepository, IUnitOfWork unitOfWork, IMapper mapper) 33 | { 34 | _taskRepository = taskRepository; 35 | _unitOfWork = unitOfWork; 36 | _mapper = mapper; 37 | } 38 | 39 | 40 | [ValidationAspect(typeof(UpdateTaskValidator))] 41 | public async Task Handle(UpdateTaskCommand request, CancellationToken cancellationToken) 42 | { 43 | var task = await _taskRepository.GetTaskWithUserTasksByIdAsync(request.Id); 44 | if (task == null) 45 | { 46 | throw new ApiException(404, Messages.NotFound); 47 | } 48 | var mappedtask = _mapper.Map(request, task); 49 | mappedtask.UserTasks = request.UserIds.Select(userid => new UserTask() 50 | { 51 | TaskId = task.Id, 52 | UserId = userid 53 | }).ToList(); 54 | mappedtask.Deadline = DateTime.ParseExact(request.StringDeadline, "dd-MM-yyyy HH:mm",null).ToUniversalTime(); 55 | _taskRepository.Update(mappedtask); 56 | await _unitOfWork.SaveChangesAsync(); 57 | return new SuccessResponse(200, Messages.UpdatedSuccessfully); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Tasks/Queries/GetTaskDetailByIdQuery.cs: -------------------------------------------------------------------------------- 1 | using Business.Constants; 2 | using Core.Exceptions; 3 | using Core.Utilities.Responses.Abstract; 4 | using Core.Utilities.Responses.Concrete; 5 | using DataAccess.Abstract; 6 | using Entities.Dtos; 7 | using MediatR; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace Business.Handlers.Tasks.Queries 15 | { 16 | public class GetTaskDetailByIdQuery:IRequest 17 | { 18 | public int Id { get; set; } 19 | 20 | public GetTaskDetailByIdQuery(int id) 21 | { 22 | Id = id; 23 | } 24 | public class GetTaskDetailByIdQueryHandler : IRequestHandler 25 | { 26 | private ITaskRepository _taskRepository; 27 | public GetTaskDetailByIdQueryHandler(ITaskRepository taskRepository) 28 | { 29 | _taskRepository = taskRepository; 30 | } 31 | 32 | public async Task Handle(GetTaskDetailByIdQuery request, CancellationToken cancellationToken) 33 | { 34 | var taskdetail = await _taskRepository.GetTaskDetailByIdAsync(request.Id); 35 | if (taskdetail == null) 36 | { 37 | throw new ApiException(404, Messages.NotFound); 38 | } 39 | return new DataResponse(taskdetail, 200); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Tasks/Queries/GetTasksByUserIdQuery.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Core.Utilities.Responses.Abstract; 3 | using Core.Utilities.Responses.Concrete; 4 | using DataAccess.Abstract; 5 | using Entities.Dtos; 6 | using MediatR; 7 | using Microsoft.AspNetCore.Http; 8 | 9 | namespace Business.Handlers.Tasks.Queries 10 | { 11 | public class GetTasksByUserIdQuery:IRequest 12 | { 13 | public string UserId { get; set; } 14 | public GetTasksByUserIdQuery(string userid) 15 | { 16 | UserId = userid; 17 | } 18 | public class GetTasksByUserIdQueryHandler : IRequestHandler 19 | { 20 | private ITaskRepository _taskRepository; 21 | private IHttpContextAccessor _httpContextAccessor; 22 | private IMapper _mapper; 23 | 24 | public GetTasksByUserIdQueryHandler(ITaskRepository taskRepository, IHttpContextAccessor httpContextAccessor, IMapper mapper) 25 | { 26 | _taskRepository = taskRepository; 27 | _httpContextAccessor = httpContextAccessor; 28 | _mapper = mapper; 29 | } 30 | 31 | public async Task Handle(GetTasksByUserIdQuery request, CancellationToken cancellationToken) 32 | { 33 | var tasks = await _taskRepository.GetTasksByUserIdAsync(request.UserId); 34 | return new DataResponse>(tasks, 200); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Tasks/Validations/TaskValidator.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.Tasks.Commands; 2 | using FluentValidation; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Business.Handlers.Tasks.Validations 10 | { 11 | public class CreateTaskValidator: AbstractValidator 12 | { 13 | public CreateTaskValidator() 14 | { 15 | RuleFor(x => x.Title).NotEmpty().WithMessage("Title is required").MinimumLength(5); ; 16 | RuleFor(x => x.Description).NotEmpty().WithMessage("Description is required").MinimumLength(5); 17 | RuleFor(x => x.StringDeadline).NotEmpty().WithMessage("Deadline is required"); 18 | RuleFor(x => x.UserIds).NotEmpty().WithMessage("At least one user is required"); 19 | } 20 | } 21 | 22 | public class UpdateTaskValidator : AbstractValidator 23 | { 24 | public UpdateTaskValidator() 25 | { 26 | RuleFor(x => x.Title).NotEmpty().WithMessage("Title is required").MinimumLength(5); 27 | RuleFor(x => x.Description).NotEmpty().WithMessage("Description is required").MinimumLength(5); 28 | RuleFor(x => x.StringDeadline).NotEmpty().WithMessage("Deadline is required"); 29 | RuleFor(x => x.TaskStatusId).NotEmpty().WithMessage("Task Status is required"); 30 | RuleFor(x => x.UserIds).NotEmpty().WithMessage("At least one user is required"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Users/Commands/ConfirmEmailCommand.cs: -------------------------------------------------------------------------------- 1 | using Business.Constants; 2 | using Core.Exceptions; 3 | using Core.Utilities.Responses.Abstract; 4 | using Core.Utilities.Responses.Concrete; 5 | using Entities.Concrete; 6 | using MediatR; 7 | using Microsoft.AspNetCore.Identity; 8 | using Microsoft.AspNetCore.WebUtilities; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace Business.Handlers.Users.Commands 16 | { 17 | public class ConfirmEmailCommand : IRequest 18 | { 19 | public string UserId { get; set; } 20 | public string Token { get; set; } 21 | 22 | 23 | public class ConfirmEmailCommandHandler : IRequestHandler 24 | { 25 | private UserManager _userManager; 26 | 27 | public ConfirmEmailCommandHandler(UserManager userManager) 28 | { 29 | _userManager = userManager; 30 | } 31 | 32 | public async Task Handle(ConfirmEmailCommand request, CancellationToken cancellationToken) 33 | { 34 | if (request.UserId == null || request.Token == null) 35 | { 36 | throw new ApiException(404, Messages.TokenOrUserNotFound); 37 | } 38 | var user = await _userManager.FindByIdAsync(request.UserId); 39 | if (user == null) 40 | { 41 | throw new ApiException(404, Messages.UserNotFound); 42 | } 43 | if (user.EmailConfirmed) 44 | { 45 | throw new ApiException(400, Messages.AlreadyAccountConfirmed); 46 | } 47 | var tokenDecodedBytes = WebEncoders.Base64UrlDecode(request.Token); 48 | var tokenDecoded = Encoding.UTF8.GetString(tokenDecodedBytes); 49 | var result = await _userManager.ConfirmEmailAsync(user, tokenDecoded); 50 | if (result.Succeeded) 51 | { 52 | return new SuccessResponse(200, Messages.SuccessfullyAccountConfirmed); 53 | } 54 | throw new ApiException(400, Messages.AccountDontConfirmed); 55 | } 56 | } 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Users/Commands/LoginCommand.cs: -------------------------------------------------------------------------------- 1 | using Business.Constants; 2 | using Business.Handlers.Users.Validations; 3 | using Business.Services.Abstract; 4 | using Core.Aspects.Autofac.Validation; 5 | using Core.DataAccess; 6 | using Core.Exceptions; 7 | using Core.Utilities.Responses.Abstract; 8 | using Core.Utilities.Responses.Concrete; 9 | using DataAccess.Abstract; 10 | using Entities.Concrete; 11 | using Entities.Dtos; 12 | using MediatR; 13 | using Microsoft.AspNetCore.Identity; 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Threading.Tasks; 19 | 20 | namespace Business.Handlers.Users.Commands 21 | { 22 | public class LoginCommand:IRequest 23 | { 24 | public string UserName { get; set; } 25 | public string Password { get; set; } 26 | 27 | public class LoginCommandHandler : IRequestHandler 28 | { 29 | private UserManager _userManager; 30 | private ITokenService _tokenService; 31 | 32 | public LoginCommandHandler(UserManager userManager,ITokenService tokenService) 33 | { 34 | _tokenService = tokenService; 35 | _userManager = userManager; 36 | } 37 | 38 | [ValidationAspect(typeof(LoginValidator))] 39 | public async Task Handle(LoginCommand request, CancellationToken cancellationToken) 40 | { 41 | var user = await _userManager.FindByNameAsync(request.UserName); 42 | if (user == null) 43 | { 44 | throw new ApiException(400, Messages.UserNameOrPasswordIsIncorrect); 45 | } 46 | if (!user.EmailConfirmed) 47 | { 48 | throw new ApiException(400, Messages.ConfirmYourAccount); 49 | } 50 | var identityResult = await _userManager.CheckPasswordAsync(user, request.Password); 51 | if (!identityResult) 52 | { 53 | throw new ApiException(400, Messages.UserNameOrPasswordIsIncorrect); 54 | } 55 | var token = await _tokenService.CreateToken(user); 56 | return new DataResponse(token, 200); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Users/Commands/RegisterCommand.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Constants; 3 | using Business.Handlers.Users.Validations; 4 | using Core.Aspects.Autofac.Validation; 5 | using Core.Exceptions; 6 | using Core.Utilities; 7 | using Core.Utilities.Responses.Abstract; 8 | using Core.Utilities.Responses.Concrete; 9 | using Entities.Concrete; 10 | using MediatR; 11 | using Microsoft.AspNetCore.Identity; 12 | using Microsoft.AspNetCore.WebUtilities; 13 | using System; 14 | using System.Collections.Generic; 15 | using System.Linq; 16 | using System.Text; 17 | using System.Threading.Tasks; 18 | 19 | namespace Business.Handlers.Users.Commands 20 | { 21 | public class RegisterCommand:IRequest 22 | { 23 | public string Email { get; set; } 24 | public string FirstName { get; set; } 25 | public string LastName { get; set; } 26 | public string UserName { get; set; } 27 | public string Password { get; set; } 28 | public string ConfirmPassword { get; set; } 29 | 30 | 31 | public class RegisterCommandHandler : IRequestHandler 32 | { 33 | private UserManager _userManager; 34 | private IMapper _mapper; 35 | private IEmailService _emailService; 36 | public RegisterCommandHandler(UserManager userManager, IMapper mapper, IEmailService emailService) 37 | { 38 | _userManager = userManager; 39 | _mapper = mapper; 40 | _emailService = emailService; 41 | } 42 | 43 | [ValidationAspect(typeof(RegisterValidator))] 44 | public async Task Handle(RegisterCommand request, CancellationToken cancellationToken) 45 | { 46 | var email = await _userManager.FindByEmailAsync(request.Email); 47 | if (email != null) 48 | { 49 | throw new ApiException(400, Messages.EmailIsAlreadyExist); 50 | } 51 | var username = await _userManager.FindByNameAsync(request.UserName); 52 | if (username != null) 53 | { 54 | throw new ApiException(400, Messages.UsernameIsAlreadyExist); 55 | } 56 | if (request.Password != request.ConfirmPassword) 57 | { 58 | throw new ApiException(400, Messages.PasswordDontMatchWithConfirmation); 59 | } 60 | var user = _mapper.Map(request); 61 | var IdentityResult = await _userManager.CreateAsync(user, request.Password); 62 | if (IdentityResult.Succeeded) 63 | { 64 | string token = await _userManager.GenerateEmailConfirmationTokenAsync(user); 65 | byte[] tokenGeneratedBytes = Encoding.UTF8.GetBytes(token); 66 | var tokenEncoded = WebEncoders.Base64UrlEncode(tokenGeneratedBytes); 67 | string link = "http://localhost:8080/confirmemail/" + user.Id + "/" + tokenEncoded; 68 | await _emailService.ConfirmationMailAsync(link, request.Email); 69 | return new SuccessResponse(200, Messages.RegisterSuccessfully); 70 | } 71 | else 72 | { 73 | throw new ApiException(400, IdentityResult.Errors.Select(e => e.Description).ToList()); 74 | } 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Users/Queries/GetAuthenticatedUserQuery.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Constants; 3 | using Core.Exceptions; 4 | using Core.Utilities.Responses.Abstract; 5 | using Core.Utilities.Responses.Concrete; 6 | using Entities.Concrete; 7 | using Entities.Dtos; 8 | using MediatR; 9 | using Microsoft.AspNetCore.Identity; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Threading.Tasks; 15 | 16 | namespace Business.Handlers.Users.Queries 17 | { 18 | public class GetAuthenticatedUserQuery:IRequest 19 | { 20 | public string UserId { get; set; } 21 | public GetAuthenticatedUserQuery(string userid) 22 | { 23 | UserId = userid; 24 | } 25 | public class GetAuthenticatedUserQueryHander : IRequestHandler 26 | { 27 | private UserManager _userManager; 28 | private IMapper _mapper; 29 | 30 | public GetAuthenticatedUserQueryHander(UserManager userManager,IMapper mapper) 31 | { 32 | _userManager = userManager; 33 | _mapper = mapper; 34 | } 35 | 36 | public async Task Handle(GetAuthenticatedUserQuery request, CancellationToken cancellationToken) 37 | { 38 | var user = await _userManager.FindByIdAsync(request.UserId); 39 | if (user == null) 40 | { 41 | throw new ApiException(404, Messages.UserNotFound); 42 | } 43 | var mappeduser = _mapper.Map(user); 44 | return new DataResponse(mappeduser, 200); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Users/Queries/GetUserByEmailQuery.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Constants; 3 | using Core.Exceptions; 4 | using Core.Utilities.Responses.Abstract; 5 | using Core.Utilities.Responses.Concrete; 6 | using Entities.Concrete; 7 | using Entities.Dtos; 8 | using MediatR; 9 | using Microsoft.AspNetCore.Identity; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Threading.Tasks; 15 | 16 | namespace Business.Handlers.Users.Queries 17 | { 18 | public class GetUserByEmailQuery:IRequest 19 | { 20 | public string Email { get; set; } 21 | public GetUserByEmailQuery(string email) 22 | { 23 | Email = email; 24 | } 25 | public class GetUserByEmailQueryHandler : IRequestHandler 26 | { 27 | private UserManager _userManager; 28 | private IMapper _mapper; 29 | 30 | public GetUserByEmailQueryHandler(UserManager userManager, IMapper mapper) 31 | { 32 | _userManager = userManager; 33 | _mapper = mapper; 34 | } 35 | 36 | public async Task Handle(GetUserByEmailQuery request, CancellationToken cancellationToken) 37 | { 38 | var user = await _userManager.FindByEmailAsync(request.Email); 39 | if (user == null) 40 | { 41 | throw new ApiException(404, Messages.UserNotFound); 42 | } 43 | var mappeduser = _mapper.Map(user); 44 | return new DataResponse(mappeduser, 200); 45 | } 46 | } 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Users/Validations/LoginValidator.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.Users.Commands; 2 | using FluentValidation; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Business.Handlers.Users.Validations 10 | { 11 | public class LoginValidator:AbstractValidator 12 | { 13 | public LoginValidator() 14 | { 15 | RuleFor(x => x.UserName).NotEmpty().WithMessage("UserName is required"); 16 | RuleFor(x => x.Password).NotEmpty().WithMessage("Password is required"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Handlers/Users/Validations/RegisterValidator.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.Users.Commands; 2 | using FluentValidation; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Business.Handlers.Users.Validations 10 | { 11 | public class RegisterValidator : AbstractValidator 12 | { 13 | public RegisterValidator() 14 | { 15 | RuleFor(x => x.UserName).NotEmpty(); 16 | RuleFor(x => x.FirstName).NotEmpty(); 17 | RuleFor(x => x.LastName).NotEmpty(); 18 | RuleFor(x => x.Email).NotEmpty().EmailAddress(); 19 | RuleFor(x => x.Password).NotEmpty(); 20 | RuleFor(x => x.ConfirmPassword).NotEmpty(); 21 | RuleFor(x => x).Custom((x, context) => 22 | { 23 | if (x.Password != x.ConfirmPassword) 24 | { 25 | context.AddFailure(nameof(x.Password), "Passwords should match"); 26 | } 27 | }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Mappings/Automapper.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Business.Handlers.Tasks.Commands; 3 | using Business.Handlers.Users.Commands; 4 | using Entities.Concrete; 5 | using Entities.Dtos; 6 | using TaskStatus = Entities.Concrete.TaskStatus; 7 | using Task = Entities.Concrete.Task; 8 | using Business.Handlers.Comments.Commands; 9 | 10 | namespace Business.Mappings 11 | { 12 | public class Automapper : Profile 13 | { 14 | public Automapper() 15 | { 16 | CreateMap().ReverseMap(); 17 | CreateMap().ReverseMap(); 18 | CreateMap().ReverseMap(); 19 | CreateMap().ReverseMap(); 20 | CreateMap().ReverseMap(); 21 | CreateMap().ReverseMap(); 22 | CreateMap().ReverseMap(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Services/Abstract/ITokenService.cs: -------------------------------------------------------------------------------- 1 | using Entities.Concrete; 2 | using Entities.Dtos; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Business.Services.Abstract 10 | { 11 | public interface ITokenService 12 | { 13 | Task CreateToken (User user); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TaskManagementAPP/Business/Services/Concrete/TokenManager.cs: -------------------------------------------------------------------------------- 1 | using Business.Services.Abstract; 2 | using Core.Configurations; 3 | using Core.Utilities.Helpers; 4 | using Entities.Concrete; 5 | using Entities.Dtos; 6 | using Microsoft.AspNetCore.Identity; 7 | using Microsoft.Extensions.Options; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.IdentityModel.Tokens.Jwt; 11 | using System.Linq; 12 | using System.Security.Claims; 13 | using System.Security.Cryptography; 14 | using System.Text; 15 | using System.Threading.Tasks; 16 | 17 | namespace Business.Services.Concrete 18 | { 19 | public class TokenManager : ITokenService 20 | { 21 | private readonly JWTOptions _jwtOptions; 22 | private readonly UserManager _userManager; 23 | public TokenManager(IOptions options, UserManager userManager) 24 | { 25 | _jwtOptions = options.Value; 26 | _userManager = userManager; 27 | } 28 | 29 | public async Task CreateToken(User user) 30 | { 31 | var accessTokenExpiration = DateTime.Now.AddMinutes(_jwtOptions.AccessTokenExpiration); 32 | var refreshTokenExpiration = DateTime.Now.AddMinutes(_jwtOptions.RefreshTokenExpiration); 33 | var securityKey = SecurityKeyHelper.GetSymmetricSecurityKey(_jwtOptions.SecurityKey); 34 | var signingCredentials = SigningCredentialsHelper.CreateSigningCredentials(securityKey); 35 | 36 | 37 | JwtSecurityToken jwtSecurityToken = new JwtSecurityToken( 38 | issuer: _jwtOptions.Issuer, 39 | audience: _jwtOptions.Audience[0], 40 | expires: accessTokenExpiration, 41 | notBefore: DateTime.Now, 42 | claims: await GetClaims(user, _jwtOptions.Audience), 43 | signingCredentials: signingCredentials); 44 | 45 | var handler = new JwtSecurityTokenHandler(); 46 | 47 | var token = handler.WriteToken(jwtSecurityToken); 48 | 49 | var tokenDto = new TokenDTO 50 | { 51 | AccessToken = token, 52 | AccessTokenExpiration = accessTokenExpiration, 53 | }; 54 | 55 | return tokenDto; 56 | } 57 | private async Task> GetClaims(User user, List audiences) 58 | { 59 | var roles = await _userManager.GetRolesAsync(user); 60 | var claims = new List 61 | { 62 | new Claim(ClaimTypes.Email,user.Email), 63 | new Claim(ClaimTypes.Name,user.UserName), 64 | new Claim(ClaimTypes.NameIdentifier,user.Id), 65 | new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()) 66 | }; 67 | foreach (var role in roles) 68 | { 69 | claims.Add(new Claim(ClaimTypes.Role, role)); 70 | } 71 | claims.AddRange(audiences.Select(x => new Claim(JwtRegisteredClaimNames.Aud, x))); 72 | return claims; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Aspects/Autofac/Validation/ValidationAspect.cs: -------------------------------------------------------------------------------- 1 | using Castle.DynamicProxy; 2 | using Core.CrossCuttingConcerns.Validation.FluentValidation; 3 | using Core.Utilities.Interceptors; 4 | using Core.Utilities.Responses.Concrete; 5 | using FluentValidation; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | 11 | namespace Core.Aspects.Autofac.Validation 12 | { 13 | public class ValidationAspect : MethodInterception 14 | { 15 | private readonly Type _validatorType; 16 | public ValidationAspect(Type validatorType) 17 | { 18 | if (!typeof(IValidator).IsAssignableFrom(validatorType)) 19 | { 20 | throw new ArgumentException("Wrong validator type"); 21 | } 22 | _validatorType = validatorType; 23 | } 24 | protected override void OnBefore(IInvocation invocation) 25 | { 26 | var validator = (IValidator)Activator.CreateInstance(_validatorType); 27 | var entityType = _validatorType.BaseType.GetGenericArguments()[0]; 28 | var entities = invocation.Arguments.Where(t => t.GetType() == entityType); 29 | foreach (var entity in entities) 30 | { 31 | ValidatonTool.FluentValidate(validator, entity); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Configurations/EmailSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.Configurations 8 | { 9 | public class EmailSettings 10 | { 11 | public string Email { get; set; } 12 | public string Password { get; set; } 13 | public string Host { get; set; } 14 | public int Port { get; set; } 15 | public bool EnableSSL { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Configurations/JWTOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.Configurations 8 | { 9 | public class JWTOptions 10 | { 11 | public List Audience { get; set; } 12 | public string Issuer { get; set; } 13 | public int AccessTokenExpiration { get; set; } 14 | public int RefreshTokenExpiration { get; set; } 15 | public string SecurityKey { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/CrossCuttingConcerns/Logging/ErrorLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Core.CrossCuttingConcerns.Logging 6 | { 7 | public class ErrorLog 8 | { 9 | public string UserId { get; set; } 10 | public string Username { get; set; } 11 | public string ManagerName { get; set; } 12 | public string MethodName { get; set; } 13 | public List Errors { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/CrossCuttingConcerns/Logging/LogDetail.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Core.CrossCuttingConcerns.Logging 6 | { 7 | public class LogDetail 8 | { 9 | public string UserId { get; set; } 10 | public string Username { get; set; } 11 | public string ManagerName { get; set; } 12 | public string MethodName { get; set; } 13 | public object Data { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/CrossCuttingConcerns/Logging/SeriLog/ConfigurationModels/PostgreSqlConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.CrossCuttingConcerns.Logging.SeriLog.ConfigurationModels 8 | { 9 | public class PostgreSqlConfiguration 10 | { 11 | public string ConnectionString { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/CrossCuttingConcerns/Logging/SeriLog/LoggerServiceBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Serilog; 5 | 6 | namespace Core.CrossCuttingConcerns.Logging.SeriLog 7 | { 8 | public abstract class LoggerServiceBase 9 | { 10 | public ILogger Logger; 11 | public void Verbose(string message) => Logger.Verbose(message); 12 | public void Fatal(string message) => Logger.Fatal(message); 13 | public void Info(string message) => Logger.Information(message); 14 | public void Warn(string message) => Logger.Warning(message); 15 | public void Debug(string message) => Logger.Debug(message); 16 | public void Error(string message) => Logger.Error(message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/CrossCuttingConcerns/Logging/SeriLog/Loggers/PostgreSqlLogger.cs: -------------------------------------------------------------------------------- 1 | using Core.CrossCuttingConcerns.Logging.SeriLog.ConfigurationModels; 2 | using Core.Utilities.IoC; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Serilog; 6 | using Serilog.Sinks.PostgreSQL; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace Core.CrossCuttingConcerns.Logging.SeriLog.Loggers 14 | { 15 | public class PostgreSqlLogger:LoggerServiceBase 16 | { 17 | public PostgreSqlLogger() 18 | { 19 | var configuration = ServiceTool.ServiceProvider.GetService(); 20 | 21 | var logConfig = configuration.GetSection("SeriLogConfigurations:PostgreSqlConfiguration") 22 | .Get() ?? throw new Exception("PostgreSQLConnectionString is null"); 23 | var seriLogConfig = new LoggerConfiguration() 24 | .WriteTo.PostgreSQL(connectionString: logConfig.ConnectionString,tableName:"Logs",needAutoCreateTable:true) 25 | .CreateLogger(); 26 | Logger = seriLogConfig; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/CrossCuttingConcerns/Validation/FluentValidation/ValidationTool.cs: -------------------------------------------------------------------------------- 1 | using Core.Utilities; 2 | using FluentValidation; 3 | using FluentValidation.TestHelper; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Text; 10 | 11 | namespace Core.CrossCuttingConcerns.Validation.FluentValidation 12 | { 13 | public class ValidatonTool 14 | { 15 | public static void FluentValidate(IValidator validator, object entity) 16 | { 17 | var context = new ValidationContext(entity); 18 | var result = validator.Validate(context); 19 | if (!result.IsValid) 20 | { 21 | throw new ValidationException(result.Errors); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/DataAccess/EntityFramework/EfEntityRepositoryBase.cs: -------------------------------------------------------------------------------- 1 | using Core.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Core.DataAccess.EntityFramework 11 | { 12 | public class EfEntityRepositoryBase : IEntityRepository 13 | where TEntity : class, IEntity, new() 14 | where TContext : DbContext 15 | { 16 | protected readonly TContext _context; 17 | public EfEntityRepositoryBase(TContext context) 18 | { 19 | _context = context; 20 | } 21 | public TEntity Add(TEntity entity) 22 | { 23 | _context.Set().Add(entity); 24 | return entity; 25 | } 26 | 27 | public async Task AddAsync(TEntity entity) 28 | { 29 | await _context.Set().AddAsync(entity); 30 | return entity; 31 | } 32 | 33 | public IEnumerable AddRange(IEnumerable entities) 34 | { 35 | _context.Set().AddRange(entities); 36 | return entities; 37 | } 38 | public async Task> AddRangeAsync(IEnumerable entities) 39 | { 40 | await _context.Set().AddRangeAsync(entities); 41 | return entities; 42 | } 43 | 44 | public void Remove(TEntity entity) 45 | { 46 | _context.Set().Remove(entity); 47 | } 48 | 49 | public TEntity Get(Expression> filter) 50 | { 51 | return _context.Set().FirstOrDefault(filter); 52 | } 53 | 54 | public async Task GetAsync(Expression> filter) 55 | { 56 | return await _context.Set().FirstOrDefaultAsync(filter); 57 | } 58 | 59 | public IEnumerable GetAll(Expression> filter = null) 60 | { 61 | return filter == null 62 | ? _context.Set().ToList() 63 | : _context.Set().Where(filter).ToList(); 64 | } 65 | 66 | public async Task> GetAllAsync(Expression> filter = null) 67 | { 68 | return filter == null 69 | ? await _context.Set().ToListAsync() 70 | : await _context.Set().Where(filter).ToListAsync(); 71 | } 72 | 73 | public TEntity GetById(int id) 74 | { 75 | return _context.Set().Find(id); 76 | } 77 | 78 | public async Task GetByIdAsync(int id) 79 | { 80 | return await _context.Set().FindAsync(id); 81 | } 82 | public void Update(TEntity entity) 83 | { 84 | _context.Set().Update(entity); 85 | } 86 | public int Count() 87 | { 88 | return _context.Set().Count(); 89 | } 90 | 91 | public async Task CountAsync() 92 | { 93 | return await _context.Set().CountAsync(); 94 | } 95 | 96 | public void UpdateRange(IEnumerable entities) 97 | { 98 | _context.Set().UpdateRange(entities); 99 | } 100 | 101 | public void RemoveRange(IEnumerable entities) 102 | { 103 | _context.Set().RemoveRange(entities); 104 | } 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/DataAccess/IEntityRepository.cs: -------------------------------------------------------------------------------- 1 | using Core.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Core.DataAccess 10 | { 11 | public interface IEntityRepository where TEntity : class, IEntity, new() 12 | { 13 | TEntity Get(Expression> filter); 14 | Task GetAsync(Expression> filter); 15 | TEntity GetById(int id); 16 | Task GetByIdAsync(int id); 17 | IEnumerable GetAll(Expression> filter = null); 18 | Task> GetAllAsync(Expression> filter = null); 19 | TEntity Add(TEntity entity); 20 | Task AddAsync(TEntity entity); 21 | IEnumerable AddRange(IEnumerable entities); 22 | Task> AddRangeAsync(IEnumerable entities); 23 | void Update(TEntity entity); 24 | void UpdateRange(IEnumerable entities); 25 | void Remove(TEntity entity); 26 | void RemoveRange(IEnumerable entities); 27 | int Count(); 28 | Task CountAsync(); 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/DataAccess/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.DataAccess 8 | { 9 | public interface IUnitOfWork 10 | { 11 | Task SaveChangesAsync(); 12 | void SaveChanges(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/DependencyResolvers/CoreModule.cs: -------------------------------------------------------------------------------- 1 |  2 | using Core.Configurations; 3 | using Core.Utilities; 4 | using Core.Utilities.IoC; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Diagnostics; 11 | using System.Text; 12 | 13 | namespace Core.DependencyResolvers 14 | { 15 | public class CoreModule : ICoreModule 16 | { 17 | public void Load(IServiceCollection services, IConfiguration configuration) 18 | { 19 | services.AddSingleton(); 20 | services.Configure(configuration.GetSection("EmailSettings")); 21 | services.AddTransient(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Entities/IDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.Entities 8 | { 9 | public interface IDTO 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Entities/IEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.Entities 8 | { 9 | public interface IEntity 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Exceptions/ApiException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Core.Exceptions 9 | { 10 | [Serializable] 11 | public class ApiException : Exception 12 | { 13 | public int StatusCode { get; } 14 | public List Errors { get; private set; } = new List(); 15 | 16 | public ApiException(int statuscode, List errors) 17 | { 18 | StatusCode = statuscode; 19 | Errors = errors; 20 | } 21 | public ApiException(int statuscode, string error) 22 | { 23 | StatusCode = statuscode; 24 | Errors.Add(error); 25 | } 26 | public ApiException(SerializationInfo info, StreamingContext context) : base(info, context) { } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/EmailManager.cs: -------------------------------------------------------------------------------- 1 | using Core.Configurations; 2 | using Microsoft.Extensions.Options; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Net.Mail; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Core.Utilities 12 | { 13 | public class EmailManager : IEmailService 14 | { 15 | private readonly EmailSettings _emailSettings; 16 | public EmailManager(IOptions options) 17 | { 18 | _emailSettings = options.Value; 19 | } 20 | public async Task ConfirmationMailAsync(string link, string email) 21 | { 22 | var client = new SmtpClient(_emailSettings.Host, _emailSettings.Port) 23 | { 24 | Credentials = new NetworkCredential(_emailSettings.Email, _emailSettings.Password), 25 | EnableSsl = _emailSettings.EnableSSL 26 | }; 27 | var subject = $"www.TaskManagerApp.com || Confirm Email"; 28 | var body = "

Please click this link for confirm email


"; 29 | body += $"Confirmation Link"; 30 | await client.SendMailAsync( 31 | new MailMessage(_emailSettings.Email, email, subject, body) { IsBodyHtml = true } 32 | ); 33 | } 34 | 35 | public async Task ForgetPasswordMailAsync(string link, string email) 36 | { 37 | var client = new SmtpClient(_emailSettings.Host, _emailSettings.Port) 38 | { 39 | Credentials = new NetworkCredential(_emailSettings.Email, _emailSettings.Password), 40 | EnableSsl = _emailSettings.EnableSSL 41 | }; 42 | var subject = $"www.TaskManagerApp.com || Reset Password"; 43 | var body = "

Please click this link for reset password


"; 44 | body += $"reset password link"; 45 | await client.SendMailAsync( 46 | new MailMessage(_emailSettings.Email, email, subject, body) { IsBodyHtml = true } 47 | ); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Extensions/ExceptionMiddleware.cs: -------------------------------------------------------------------------------- 1 | using Core.CrossCuttingConcerns.Logging; 2 | using Core.CrossCuttingConcerns.Logging.SeriLog; 3 | using Core.CrossCuttingConcerns.Logging.SeriLog.Loggers; 4 | using Core.Exceptions; 5 | using Core.Utilities.Responses.Concrete; 6 | using FluentValidation; 7 | using FluentValidation.Results; 8 | using Microsoft.AspNetCore.Http; 9 | using Newtonsoft.Json; 10 | using Newtonsoft.Json.Serialization; 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Linq; 14 | using System.Net; 15 | using System.Text; 16 | using System.Threading.Tasks; 17 | 18 | namespace Core.Utilities.Extensions 19 | { 20 | public class ExceptionMiddleware 21 | { 22 | private RequestDelegate _next; 23 | private readonly LoggerServiceBase _loggerServiceBase; 24 | public ExceptionMiddleware(RequestDelegate next) 25 | { 26 | _next = next; 27 | _loggerServiceBase = (LoggerServiceBase)Activator.CreateInstance(typeof(PostgreSqlLogger)); 28 | } 29 | 30 | public async Task InvokeAsync(HttpContext httpContext) 31 | { 32 | try 33 | { 34 | await _next(httpContext); 35 | } 36 | catch (Exception e) 37 | { 38 | await HandleExceptionAsync(httpContext, e); 39 | } 40 | } 41 | private Task HandleExceptionAsync(HttpContext httpContext, Exception e) 42 | { 43 | httpContext.Response.ContentType = "application/json"; 44 | httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; 45 | string message = "Internal Server Error"; 46 | if (e.GetType() == typeof(ValidationException)) 47 | { 48 | IEnumerable errors; 49 | errors = ((ValidationException)e).Errors; 50 | httpContext.Response.StatusCode = 400; 51 | var validationerror = JsonConvert.SerializeObject(new ErrorResponse(400, errors.Select(x => x.ErrorMessage).ToList()), new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); 52 | return httpContext.Response.WriteAsync(validationerror); 53 | } 54 | 55 | else if (e.InnerException is ApiException || e.GetType() == typeof(ApiException)) 56 | { 57 | var ex = e.InnerException != null ? (ApiException)e.InnerException : (ApiException)e; 58 | httpContext.Response.StatusCode = ex.StatusCode; 59 | var apierror = JsonConvert.SerializeObject(new ErrorResponse(ex.StatusCode, ex.Errors),new JsonSerializerSettings { ContractResolver=new CamelCasePropertyNamesContractResolver()}); 60 | return httpContext.Response.WriteAsync(apierror); 61 | } 62 | 63 | List exceptions = new List(); 64 | 65 | if (e.InnerException != null) 66 | { 67 | exceptions.Add(e.InnerException.ToString()); 68 | if (e.InnerException.Message != null) 69 | { 70 | exceptions.Add(e.InnerException.Message); 71 | } 72 | else if (e.InnerException.InnerException.Message != null) 73 | { 74 | exceptions.Add(e.InnerException.InnerException.Message); 75 | } 76 | } 77 | 78 | else if (e.Message != null) 79 | { 80 | exceptions.Add(e.Message); 81 | } 82 | var errorlogDetail = new ErrorLog 83 | { 84 | Errors = exceptions, 85 | }; 86 | var serializederror=JsonConvert.SerializeObject(errorlogDetail); 87 | _loggerServiceBase.Error(serializederror); 88 | 89 | var error = JsonConvert.SerializeObject(new ErrorResponse(httpContext.Response.StatusCode, message)); 90 | return httpContext.Response.WriteAsync(error); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Extensions/ExceptionMiddlewareExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities.Extensions 7 | { 8 | public static class ExceptionMiddlewareExtensions 9 | { 10 | public static void UseCustomExceptionMiddleware(this IApplicationBuilder app) 11 | { 12 | app.UseMiddleware(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Extensions/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | using Core.Utilities.IoC; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace Core.Utilities.Extensions 10 | { 11 | public static class ServiceCollectionExtensions 12 | { 13 | public static IServiceCollection AddDependencyResolvers(this IServiceCollection services, IConfiguration configuration,ICoreModule[] modules) 14 | { 15 | foreach (var module in modules) 16 | { 17 | module.Load(services,configuration); 18 | } 19 | return ServiceTool.Create(services); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/FileManager.cs: -------------------------------------------------------------------------------- 1 | using Core.Exceptions; 2 | using Core.Utilities.IoC; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace Core.Utilities 14 | { 15 | public static class FileManager 16 | { 17 | public static string SaveFile(string foldername, IFormFile file) 18 | { 19 | string filename = Guid.NewGuid().ToString().Substring(0, 9) + "_" + file.FileName; 20 | if (!Directory.Exists(@"Uploads//" + foldername)) 21 | Directory.CreateDirectory(@"Uploads//" + foldername); 22 | var path = Path.Combine(Directory.GetCurrentDirectory(), "Uploads//" + foldername, filename); 23 | using (var stream = new FileStream(path, FileMode.Create)) 24 | { 25 | file.CopyTo(stream); 26 | } 27 | return "Uploads/" + foldername + "/" + filename; 28 | } 29 | 30 | public static void DeleteFile(string filename) 31 | { 32 | var path = Path.Combine(Directory.GetCurrentDirectory(), filename); 33 | if (System.IO.File.Exists(path)) 34 | System.IO.File.Delete(path); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Helpers/SecurityKeyHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.IdentityModel.Tokens; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Core.Utilities.Helpers 9 | { 10 | public static class SecurityKeyHelper 11 | { 12 | public static SecurityKey GetSymmetricSecurityKey(string securityKey) 13 | { 14 | return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Helpers/SigningCredentialsHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.IdentityModel.Tokens; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Core.Utilities.Helpers 9 | { 10 | public static class SigningCredentialsHelper 11 | { 12 | public static SigningCredentials CreateSigningCredentials(SecurityKey securityKey) 13 | { 14 | return new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/IEmailService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Core.Utilities 8 | { 9 | public interface IEmailService 10 | { 11 | Task ConfirmationMailAsync(string link, string email); 12 | Task ForgetPasswordMailAsync(string link, string email); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Interceptors/AspectInterceptorSelector.cs: -------------------------------------------------------------------------------- 1 | using Castle.DynamicProxy; 2 | using Core.CrossCuttingConcerns.Logging.SeriLog.Loggers; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | 9 | namespace Core.Utilities.Interceptors 10 | { 11 | public class AspectInterceptorSelector : IInterceptorSelector 12 | { 13 | public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors) 14 | { 15 | var classAttributes = type.GetCustomAttributes(true).ToList(); 16 | var methodAttributes = type.GetMethod(method.Name).GetCustomAttributes(true); 17 | classAttributes.AddRange(methodAttributes); 18 | return classAttributes.OrderBy(x => x.Priority).ToArray(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Interceptors/MethodInterception.cs: -------------------------------------------------------------------------------- 1 | using Castle.DynamicProxy; 2 | using Core.CrossCuttingConcerns.Logging; 3 | using Core.CrossCuttingConcerns.Logging.SeriLog; 4 | using Core.CrossCuttingConcerns.Logging.SeriLog.Loggers; 5 | using Core.Exceptions; 6 | using Core.Utilities.Responses.Abstract; 7 | using Newtonsoft.Json; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Reflection; 11 | using System.Runtime.CompilerServices; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace Core.Utilities.Interceptors 16 | { 17 | public abstract class MethodInterception : MethodInterceptionBaseAttribute 18 | { 19 | protected virtual void OnBefore(IInvocation invocation) { } 20 | protected virtual void OnAfter(IInvocation invocation) { } 21 | protected virtual void OnException(IInvocation invocation, Exception e) { } 22 | protected virtual void OnSuccess(IInvocation invocation) { } 23 | public override void Intercept(IInvocation invocation) 24 | { 25 | var isSuccess = true; 26 | OnBefore(invocation); 27 | try 28 | { 29 | invocation.Proceed(); 30 | Task result = invocation.ReturnValue as Task; 31 | result?.Wait(); 32 | if (result?.IsFaulted ?? false) 33 | throw result.Exception?.InnerException ?? result.Exception; 34 | } 35 | catch (Exception e) 36 | { 37 | isSuccess = false; 38 | if (invocation.ReturnValue is Task result && result.IsFaulted) 39 | OnException(invocation, result.Exception?.InnerException ?? result.Exception ?? e); 40 | else 41 | OnException(invocation, e); 42 | throw; 43 | } 44 | finally 45 | { 46 | if (isSuccess) 47 | { 48 | OnSuccess(invocation); 49 | } 50 | } 51 | OnAfter(invocation); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Interceptors/MethodInterceptionBaseAttribute.cs: -------------------------------------------------------------------------------- 1 | using Castle.DynamicProxy; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities.Interceptors 7 | { 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Assembly, AllowMultiple = true, Inherited = true)] 9 | public abstract class MethodInterceptionBaseAttribute : Attribute, IInterceptor 10 | { 11 | public int Priority { get; set; } 12 | 13 | public virtual void Intercept(IInvocation invocation) 14 | { 15 | 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/IoC/ICoreModule.cs: -------------------------------------------------------------------------------- 1 |  2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace Core.Utilities.IoC 9 | { 10 | public interface ICoreModule 11 | { 12 | void Load(IServiceCollection serviceCollection, IConfiguration configuration); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/IoC/ServiceTool.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities.IoC 7 | { 8 | public static class ServiceTool 9 | { 10 | public static IServiceProvider ServiceProvider { get; set; } 11 | 12 | public static IServiceCollection Create(IServiceCollection services) 13 | { 14 | ServiceProvider = services.BuildServiceProvider(); 15 | return services; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Abstract/IDataResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Core.Utilities.Responses.Abstract 6 | { 7 | public interface IDataResponse : IResponse 8 | { 9 | T Data { get; } 10 | string Message { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Abstract/IErrorResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Core.Utilities.Responses.Abstract 6 | { 7 | public interface IErrorResponse : IResponse 8 | { 9 | List Errors { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Abstract/IPagedDataResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Core.Utilities.Responses.Abstract 6 | { 7 | interface IPagedDataResponse : IResponse 8 | { 9 | int TotalItems { get; } 10 | T Data { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Abstract/IResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Core.Utilities.Responses.Abstract 6 | { 7 | public interface IResponse 8 | { 9 | bool Success { get; } 10 | int StatusCode { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Abstract/ISuccessResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Core.Utilities.Responses.Abstract 6 | { 7 | public interface ISuccessResponse : IResponse 8 | { 9 | string Message { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Concrete/DataResponse.cs: -------------------------------------------------------------------------------- 1 | using Core.Utilities.Responses.Abstract; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities.Responses.Concrete 7 | { 8 | public class DataResponse : IDataResponse 9 | { 10 | public bool Success { get; } = true; 11 | public T Data { get; } 12 | 13 | public int StatusCode { get; } 14 | public string Message { get; set; } 15 | public DataResponse(T data, int statuscode) 16 | { 17 | Data = data; 18 | StatusCode = statuscode; 19 | } 20 | public DataResponse(T data, int statuscode,string message) 21 | { 22 | Data = data; 23 | StatusCode = statuscode; 24 | Message = message; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Concrete/ErrorResponse.cs: -------------------------------------------------------------------------------- 1 | using Core.Utilities.Responses.Abstract; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities.Responses.Concrete 7 | { 8 | public class ErrorResponse : IErrorResponse 9 | { 10 | public bool Success { get; } = false; 11 | public int StatusCode { get; } 12 | public List Errors { get; private set; } = new List(); 13 | 14 | public ErrorResponse(int statuscode, List errors) 15 | { 16 | StatusCode = statuscode; 17 | Errors = errors; 18 | } 19 | 20 | public ErrorResponse(int statuscode, string error) 21 | { 22 | StatusCode = statuscode; 23 | Errors.Add(error); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Concrete/PagedDataResponse.cs: -------------------------------------------------------------------------------- 1 | using Core.Utilities.Responses.Abstract; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities.Responses.Concrete 7 | { 8 | public class PagedDataResponse : IPagedDataResponse 9 | { 10 | public bool Success { get; } = true; 11 | public int TotalItems { get; } 12 | 13 | public T Data { get; } 14 | 15 | public int StatusCode { get; } 16 | 17 | public PagedDataResponse(T data, int statuscode, int totalitems) 18 | { 19 | Data = data; 20 | StatusCode = statuscode; 21 | TotalItems = totalitems; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Concrete/Response.cs: -------------------------------------------------------------------------------- 1 | using Core.Utilities.Responses.Abstract; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities 7 | { 8 | public class Response : IResponse 9 | { 10 | public bool Success { get; } 11 | 12 | public int StatusCode { get; } 13 | 14 | public Response(bool success,int statuscode) 15 | { 16 | Success = success; 17 | StatusCode = statuscode; 18 | } 19 | 20 | public Response(bool success) 21 | { 22 | Success = success; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TaskManagementAPP/Core/Utilities/Responses/Concrete/SuccessResponse.cs: -------------------------------------------------------------------------------- 1 | using Core.Utilities.Responses.Abstract; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Core.Utilities.Responses.Concrete 7 | { 8 | public class SuccessResponse : ISuccessResponse 9 | { 10 | public bool Success { get; } = true; 11 | public string Message { get; } 12 | public int StatusCode { get; } 13 | 14 | 15 | public SuccessResponse() 16 | { 17 | 18 | } 19 | 20 | public SuccessResponse(int statuscode, string message) 21 | { 22 | StatusCode = statuscode; 23 | Message = message; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Abstract/ICommentRepository.cs: -------------------------------------------------------------------------------- 1 | using Core.DataAccess; 2 | using Entities.Concrete; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DataAccess.Abstract 10 | { 11 | public interface ICommentRepository:IEntityRepository 12 | { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Abstract/ITaskRepository.cs: -------------------------------------------------------------------------------- 1 | using Core.DataAccess; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Core.Entities; 8 | using System.Linq.Expressions; 9 | using Task = Entities.Concrete.Task; 10 | using Entities.Dtos; 11 | 12 | namespace DataAccess.Abstract 13 | { 14 | public interface ITaskRepository : IEntityRepository 15 | { 16 | Task GetTaskWithUserTasksByIdAsync(int id); 17 | Task GetTaskDetailByIdAsync(int id); 18 | Task> GetTasksByUserIdAsync(string userid); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Abstract/ITaskStatusRepository.cs: -------------------------------------------------------------------------------- 1 | using Core.DataAccess; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using TaskStatus = Entities.Concrete.TaskStatus; 8 | 9 | namespace DataAccess.Abstract 10 | { 11 | public interface ITaskStatusRepository:IEntityRepository 12 | { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Concrete/EntityFramework/Contexts/TaskContext.cs: -------------------------------------------------------------------------------- 1 | using Entities.Concrete; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore; 5 | using Task = Entities.Concrete.Task; 6 | using TaskStatus = Entities.Concrete.TaskStatus; 7 | 8 | namespace DataAccess.Concrete.EntityFramework.Contexts 9 | { 10 | public class TaskContext:IdentityDbContext 11 | { 12 | public TaskContext(DbContextOptions options) : base(options) 13 | { 14 | 15 | } 16 | protected override void OnModelCreating(ModelBuilder builder) 17 | { 18 | base.OnModelCreating(builder); 19 | builder.Entity(entity => { entity.ToTable(name: "Users"); }); 20 | builder.Entity(entity => { entity.ToTable(name: "Roles"); }); 21 | builder.Entity>(entity => { entity.ToTable(name:"UserRoles"); }); 22 | builder.Entity>(entity => { entity.ToTable(name:"UserClaims"); }); 23 | builder.Entity>(entity => { entity.ToTable(name:"UserLogins"); }); 24 | builder.Entity>(entity => { entity.ToTable(name:"UserTokens"); }); 25 | builder.Entity>(entity => { entity.ToTable(name:"RoleClaims"); }); 26 | builder.ApplyConfigurationsFromAssembly(GetType().Assembly); 27 | } 28 | 29 | public DbSet Tasks { get; set; } 30 | public DbSet Comments { get; set; } 31 | public DbSet UserTasks { get; set; } 32 | public DbSet TaskStatuses { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Concrete/EntityFramework/EfCommentRepository.cs: -------------------------------------------------------------------------------- 1 | using Core.DataAccess.EntityFramework; 2 | using DataAccess.Abstract; 3 | using DataAccess.Concrete.EntityFramework.Contexts; 4 | using Entities.Concrete; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DataAccess.Concrete.EntityFramework 12 | { 13 | public class EfCommentRepository : EfEntityRepositoryBase, ICommentRepository 14 | { 15 | public EfCommentRepository(TaskContext context) : base(context) 16 | { 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Concrete/EntityFramework/EfTaskRepository.cs: -------------------------------------------------------------------------------- 1 | using Core.DataAccess.EntityFramework; 2 | using DataAccess.Abstract; 3 | using DataAccess.Concrete.EntityFramework.Contexts; 4 | using Entities.Dtos; 5 | using Microsoft.EntityFrameworkCore; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using Task = Entities.Concrete.Task; 12 | 13 | namespace DataAccess.Concrete.EntityFramework 14 | { 15 | public class EfTaskRepository : EfEntityRepositoryBase, ITaskRepository 16 | { 17 | public EfTaskRepository(TaskContext context) : base(context) 18 | { 19 | 20 | } 21 | 22 | public async Task GetTaskDetailByIdAsync(int id) 23 | { 24 | return await _context.Tasks.Select(task => new TaskDetailDTO 25 | { 26 | Id = task.Id, 27 | Title = task.Title, 28 | Deadline = task.Deadline.ToString("dd-MM-yyyy HH:mm",null), 29 | Description = task.Description, 30 | CreatorId = task.CreatorId, 31 | TaskStatusId=task.TaskStatusId, 32 | AssignedUsers = task.UserTasks.Select(usertask => new UserTaskDTO 33 | { 34 | TaskId = usertask.TaskId, 35 | UserId = usertask.UserId, 36 | User = new UserDTO 37 | { 38 | FirstName = usertask.User.FirstName, 39 | LastName = usertask.User.LastName, 40 | Email = usertask.User.Email, 41 | Id = usertask.User.Id, 42 | UserName = usertask.User.UserName 43 | } 44 | }).ToList(), 45 | Comments = task.Comments.Select(comment => new CommentDTO 46 | { 47 | Id = comment.Id, 48 | Description = comment.Description, 49 | UserId = comment.UserId, 50 | TaskId = comment.TaskId, 51 | CommentDate=comment.CommentDate, 52 | User = new UserDTO 53 | { 54 | FirstName = comment.User.FirstName, 55 | LastName = comment.User.LastName, 56 | Email = comment.User.Email, 57 | Id = comment.User.Id, 58 | UserName = comment.User.UserName 59 | } 60 | }).ToList() 61 | }).FirstOrDefaultAsync(x => x.Id == id); 62 | } 63 | 64 | public async Task> GetTasksByUserIdAsync(string userid) 65 | { 66 | return await _context.Tasks.Where(ut => ut.UserTasks.Any(u => u.UserId == userid) || ut.CreatorId == userid).Select(task => new TaskDTO 67 | { 68 | Id = task.Id, 69 | Title = task.Title, 70 | Deadline = task.Deadline.ToString("dd-MM-yyyy HH:mm", null), 71 | CreatorId = task.CreatorId, 72 | Status = task.TaskStatus.Status, 73 | AssignedUsers = task.UserTasks.Select(usertask => new UserTaskDTO 74 | { 75 | TaskId = usertask.TaskId, 76 | UserId = usertask.UserId, 77 | User = new UserDTO 78 | { 79 | FirstName = usertask.User.FirstName, 80 | LastName = usertask.User.LastName, 81 | Email = usertask.User.Email, 82 | Id = usertask.User.Id, 83 | UserName = usertask.User.UserName 84 | } 85 | }).ToList(), 86 | }).ToListAsync(); 87 | } 88 | 89 | public async Task GetTaskWithUserTasksByIdAsync(int id) 90 | { 91 | return await _context.Tasks.Include(x => x.UserTasks).FirstOrDefaultAsync(t => t.Id == id); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Concrete/EntityFramework/EfTaskStatusRepository.cs: -------------------------------------------------------------------------------- 1 | using Core.DataAccess.EntityFramework; 2 | using DataAccess.Abstract; 3 | using DataAccess.Concrete.EntityFramework.Contexts; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using TaskStatus = Entities.Concrete.TaskStatus; 10 | 11 | namespace DataAccess.Concrete.EntityFramework 12 | { 13 | public class EfTaskStatusRepository : EfEntityRepositoryBase, ITaskStatusRepository 14 | { 15 | public EfTaskStatusRepository(TaskContext context) : base(context) 16 | { 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Concrete/EntityFramework/UnitOfWork/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using Core.DataAccess; 2 | using DataAccess.Concrete.EntityFramework.Contexts; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DataAccess.Concrete.EntityFramework.UnitOfWork 10 | { 11 | public class UnitOfWork : IUnitOfWork 12 | { 13 | private readonly TaskContext _context; 14 | 15 | public UnitOfWork(TaskContext context) 16 | { 17 | _context = context; 18 | } 19 | public void SaveChanges() 20 | { 21 | _context.SaveChanges(); 22 | } 23 | 24 | public async Task SaveChangesAsync() 25 | { 26 | await _context.SaveChangesAsync(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Configurations/CommentConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Entities.Concrete; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DataAccess.Configurations 11 | { 12 | public class CommentConfiguration : IEntityTypeConfiguration 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | builder.Property(x => x.UserId).IsRequired(); 17 | builder.Property(x => x.CommentDate).IsRequired(); 18 | builder.Property(x => x.Description).IsRequired(); 19 | builder.Property(x => x.TaskId).IsRequired(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Configurations/TaskConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Task = Entities.Concrete.Task; 9 | 10 | namespace DataAccess.Configurations 11 | { 12 | public class TaskConfiguration : IEntityTypeConfiguration 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | builder.Property(x => x.CreatorId).IsRequired(); 17 | builder.Property(x => x.Deadline).IsRequired(); 18 | builder.Property(x => x.Title).IsRequired(); 19 | builder.Property(x => x.Description).IsRequired(); 20 | builder.Property(x => x.TaskStatusId).IsRequired(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Configurations/TaskStatusConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using TaskStatus = Entities.Concrete.TaskStatus; 9 | 10 | namespace DataAccess.Configurations 11 | { 12 | public class TaskStatusConfiguration : IEntityTypeConfiguration 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | builder.Property(x => x.Status).IsRequired(); 17 | builder.HasData(new TaskStatus { Id = 1, Status = "Ongoing" }, new TaskStatus { Id = 2, Status = "Completed" }); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Configurations/UserConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Entities.Concrete; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DataAccess.Configurations 12 | { 13 | public class UserConfiguration : IEntityTypeConfiguration 14 | { 15 | private const string DefaultUserId = "B22698B8-42A2-4115-9631-1C2D1E2AC5F7"; 16 | public void Configure(EntityTypeBuilder builder) 17 | { 18 | builder.Property(x => x.FirstName).IsRequired().HasMaxLength(200); 19 | builder.Property(x => x.LastName).IsRequired().HasMaxLength(200); 20 | var defaultuser = new User 21 | { 22 | Id = DefaultUserId, 23 | UserName = "defaultuser", 24 | NormalizedUserName = "DEFAULTUSER", 25 | FirstName = "Default", 26 | LastName = "User", 27 | Email = "User@gmail.com", 28 | NormalizedEmail = "USER@GMAIL.COM", 29 | EmailConfirmed = true, 30 | PhoneNumberConfirmed = true, 31 | }; 32 | defaultuser.PasswordHash = PassGenerate(defaultuser); 33 | builder.HasData(defaultuser); 34 | } 35 | 36 | public string PassGenerate(User user) 37 | { 38 | var passHash = new PasswordHasher(); 39 | return passHash.HashPassword(user, "159357456qW"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/Configurations/UserTaskConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Entities.Concrete; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DataAccess.Configurations 11 | { 12 | public class UserTaskConfiguration : IEntityTypeConfiguration 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | builder.HasKey(ut => new { ut.TaskId, ut.UserId }); 17 | builder.Property(x => x.UserId).IsRequired(); 18 | builder.Property(x => x.TaskId).IsRequired(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TaskManagementAPP/DataAccess/DataAccess.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Concrete/Comment.cs: -------------------------------------------------------------------------------- 1 | using Core.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Entities.Concrete 9 | { 10 | public class Comment:IEntity 11 | { 12 | public int Id { get; set; } 13 | public DateTime CommentDate { get; set; } 14 | public string Description { get; set; } 15 | public string UserId { get; set; } 16 | public User User { get; set; } 17 | public int TaskId { get; set; } 18 | public Task Task { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Concrete/Task.cs: -------------------------------------------------------------------------------- 1 | using Core.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Entities.Concrete 9 | { 10 | public class Task : IEntity 11 | { 12 | public int Id { get; set; } 13 | public string CreatorId { get; set; } 14 | public DateTime Deadline { get; set; } 15 | public string Title { get; set; } 16 | public string Description { get; set; } 17 | public int TaskStatusId { get; set; } 18 | public TaskStatus TaskStatus { get; set; } 19 | public ICollection UserTasks { get; set; } 20 | public ICollection Comments { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Concrete/TaskStatus.cs: -------------------------------------------------------------------------------- 1 | using Core.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Entities.Concrete 9 | { 10 | public class TaskStatus : IEntity 11 | { 12 | public int Id { get; set; } 13 | public string Status { get; set; } 14 | public ICollection Tasks { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Concrete/User.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Entities.Concrete 9 | { 10 | public class User:IdentityUser 11 | { 12 | public string FirstName { get; set; } 13 | public string LastName { get; set; } 14 | public ICollection Tasks { get; set; } 15 | public ICollection Comments { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Concrete/UserTask.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Core.Entities; 7 | 8 | namespace Entities.Concrete 9 | { 10 | public class UserTask : IEntity 11 | { 12 | public int TaskId { get; set; } 13 | public Task Task { get; set; } 14 | public string UserId { get; set; } 15 | public User User { get; set; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Dtos/CommentDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Entities.Dtos 8 | { 9 | public class CommentDTO 10 | { 11 | public int Id { get; set; } 12 | public DateTime CommentDate { get; set; } 13 | public string Description { get; set; } 14 | public string UserId { get; set; } 15 | public UserDTO User { get; set; } 16 | public int TaskId { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Dtos/TaskDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Entities.Dtos 8 | { 9 | public class TaskDTO 10 | { 11 | public int Id { get; set; } 12 | public string CreatorId { get; set; } 13 | public string Deadline { get; set; } 14 | public string Title { get; set; } 15 | public string Status { get; set; } 16 | public List AssignedUsers { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Dtos/TaskDetailDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Entities.Dtos 8 | { 9 | public class TaskDetailDTO 10 | { 11 | public int Id { get; set; } 12 | public string CreatorId { get; set; } 13 | public string Title { get; set; } 14 | public string Description { get; set; } 15 | public int TaskStatusId { get; set; } 16 | public string Deadline { get; set; } 17 | public List AssignedUsers { get; set; } 18 | public List Comments { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Dtos/TaskStatusDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Entities.Dtos 8 | { 9 | public class TaskStatusDTO 10 | { 11 | public int Id { get; set; } 12 | public string Status { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Dtos/TokenDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Entities.Dtos 8 | { 9 | public class TokenDTO 10 | { 11 | public string AccessToken { get; set; } 12 | public DateTime AccessTokenExpiration { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Dtos/UserDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Entities.Dtos 8 | { 9 | public class UserDTO 10 | { 11 | public string Id { get; set; } 12 | public string UserName { get; set; } 13 | public string FirstName { get; set; } 14 | public string LastName { get; set; } 15 | public string Email { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Dtos/UserTaskDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Entities.Dtos 8 | { 9 | public class UserTaskDTO 10 | { 11 | public int TaskId { get; set; } 12 | public string UserId { get; set; } 13 | public UserDTO User { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TaskManagementAPP/Entities/Entities.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /TaskManagementAPP/TaskManagementAPP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32228.430 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Business", "Business\Business.csproj", "{03A7D451-39D8-4FCF-9CBC-83F7FC8B6FE5}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataAccess", "DataAccess\DataAccess.csproj", "{CDCFD7A6-AB36-40AB-A66A-2ECAB47A7792}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "Core\Core.csproj", "{E022C223-CD4A-41FB-BE08-085FF8BF69DC}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Entities", "Entities\Entities.csproj", "{C8F40586-1AF0-43AA-B908-3F46D5E18A29}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAPI", "WebAPI\WebAPI.csproj", "{26F0C8A8-0156-454F-9A8E-E1F0EF5CA16E}" 15 | EndProject 16 | Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{B5893C25-59EE-48E9-A2EC-8A98EFE2EC12}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {03A7D451-39D8-4FCF-9CBC-83F7FC8B6FE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {03A7D451-39D8-4FCF-9CBC-83F7FC8B6FE5}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {03A7D451-39D8-4FCF-9CBC-83F7FC8B6FE5}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {03A7D451-39D8-4FCF-9CBC-83F7FC8B6FE5}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {CDCFD7A6-AB36-40AB-A66A-2ECAB47A7792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {CDCFD7A6-AB36-40AB-A66A-2ECAB47A7792}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {CDCFD7A6-AB36-40AB-A66A-2ECAB47A7792}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {CDCFD7A6-AB36-40AB-A66A-2ECAB47A7792}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {E022C223-CD4A-41FB-BE08-085FF8BF69DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {E022C223-CD4A-41FB-BE08-085FF8BF69DC}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {E022C223-CD4A-41FB-BE08-085FF8BF69DC}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {E022C223-CD4A-41FB-BE08-085FF8BF69DC}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {C8F40586-1AF0-43AA-B908-3F46D5E18A29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {C8F40586-1AF0-43AA-B908-3F46D5E18A29}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {C8F40586-1AF0-43AA-B908-3F46D5E18A29}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {C8F40586-1AF0-43AA-B908-3F46D5E18A29}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {26F0C8A8-0156-454F-9A8E-E1F0EF5CA16E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {26F0C8A8-0156-454F-9A8E-E1F0EF5CA16E}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {26F0C8A8-0156-454F-9A8E-E1F0EF5CA16E}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {26F0C8A8-0156-454F-9A8E-E1F0EF5CA16E}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {B5893C25-59EE-48E9-A2EC-8A98EFE2EC12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {B5893C25-59EE-48E9-A2EC-8A98EFE2EC12}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {B5893C25-59EE-48E9-A2EC-8A98EFE2EC12}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {B5893C25-59EE-48E9-A2EC-8A98EFE2EC12}.Release|Any CPU.Build.0 = Release|Any CPU 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(ExtensibilityGlobals) = postSolution 53 | SolutionGuid = {4B762F6B-DE2B-4CA0-8809-B5E6A3569D63} 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/Controllers/AuthController.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.Users.Commands; 2 | using Business.Handlers.Users.Queries; 3 | using Core.Utilities.Responses.Abstract; 4 | using MediatR; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Mvc; 8 | using System.Security.Claims; 9 | 10 | namespace WebAPI.Controllers 11 | { 12 | [Route("api/[controller]")] 13 | [ApiController] 14 | public class AuthController : ControllerBase 15 | { 16 | private readonly IMediator _mediator; 17 | private IHttpContextAccessor _httpContextAccessor; 18 | 19 | public AuthController(IMediator mediator,IHttpContextAccessor httpContextAccessor) 20 | { 21 | _mediator = mediator; 22 | _httpContextAccessor = httpContextAccessor; 23 | } 24 | 25 | [HttpGet] 26 | [Authorize] 27 | public async Task GetAuthenticatedUser() 28 | { 29 | var userid = _httpContextAccessor?.HttpContext?.User?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value; 30 | return await _mediator.Send(new GetAuthenticatedUserQuery(userid)); 31 | } 32 | 33 | [HttpGet("{email}")] 34 | [Authorize] 35 | public async Task GetUserByEmail(string email) 36 | { 37 | return await _mediator.Send(new GetUserByEmailQuery(email)); 38 | } 39 | 40 | 41 | [HttpPost("login")] 42 | public async TaskLogin(LoginCommand command) 43 | { 44 | return await _mediator.Send(command); 45 | } 46 | 47 | [HttpPost("register")] 48 | public async TaskRegister(RegisterCommand command) 49 | { 50 | return await _mediator.Send(command); 51 | } 52 | 53 | 54 | [HttpPost("confirmemail")] 55 | public async Task ConfirmEmail(ConfirmEmailCommand command) 56 | { 57 | return await _mediator.Send(command); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/Controllers/CommentsController.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.Comments.Commands; 2 | using Core.Utilities.Responses.Abstract; 3 | using MediatR; 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | 8 | namespace WebAPI.Controllers 9 | { 10 | [Route("api/[controller]")] 11 | [ApiController] 12 | public class CommentsController : ControllerBase 13 | { 14 | private readonly IMediator _mediator; 15 | 16 | public CommentsController(IMediator mediator) 17 | { 18 | _mediator = mediator; 19 | } 20 | 21 | [Authorize] 22 | [HttpPost] 23 | public async Task CreateComment(CreateCommentCommand command) 24 | { 25 | return await _mediator.Send(command); 26 | } 27 | 28 | [Authorize] 29 | [HttpPut] 30 | public async Task UpdateCommand(UpdateCommentCommand command) 31 | { 32 | return await _mediator.Send(command); 33 | } 34 | 35 | [Authorize] 36 | [HttpDelete("{id}")] 37 | public async Task RemoveCommand(int id) 38 | { 39 | return await _mediator.Send(new RemoveCommentCommand(id)); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/Controllers/TaskStatusesController.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.TaskStatuses.Queries; 2 | using Core.Utilities.Responses.Abstract; 3 | using MediatR; 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace WebAPI.Controllers 8 | { 9 | [Route("api/[controller]")] 10 | [ApiController] 11 | public class TaskStatusesController : ControllerBase 12 | { 13 | private IMediator _mediator; 14 | 15 | public TaskStatusesController(IMediator mediator) 16 | { 17 | _mediator = mediator; 18 | } 19 | 20 | 21 | [HttpGet] 22 | public async Task GetAll() 23 | { 24 | return await _mediator.Send(new GetAllTaskStatusesQuery()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/Controllers/TasksController.cs: -------------------------------------------------------------------------------- 1 | using Business.Handlers.Tasks.Commands; 2 | using Business.Handlers.Tasks.Queries; 3 | using Core.Utilities.Responses.Abstract; 4 | using MediatR; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Mvc; 8 | using System.Security.Claims; 9 | 10 | namespace WebAPI.Controllers 11 | { 12 | [Route("api/[controller]")] 13 | [ApiController] 14 | public class TasksController : ControllerBase 15 | { 16 | private IMediator _mediator; 17 | private IHttpContextAccessor _httpContextAccessor; 18 | 19 | public TasksController(IMediator mediator, IHttpContextAccessor httpContextAccessor) 20 | { 21 | _mediator = mediator; 22 | _httpContextAccessor = httpContextAccessor; 23 | } 24 | 25 | [Authorize] 26 | [HttpGet] 27 | public async Task GetTasks() 28 | { 29 | var userid = _httpContextAccessor?.HttpContext?.User?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value; 30 | return await _mediator.Send(new GetTasksByUserIdQuery(userid)); 31 | } 32 | 33 | 34 | [Authorize] 35 | [HttpGet("{id}")] 36 | public async Task GetTaskDetailById(int id) 37 | { 38 | return await _mediator.Send(new GetTaskDetailByIdQuery(id)); 39 | } 40 | 41 | [Authorize] 42 | [HttpPost] 43 | public async Task CreateTask (CreateTaskCommand command) 44 | { 45 | return await _mediator.Send(command); 46 | } 47 | 48 | [Authorize] 49 | [HttpPut] 50 | public async Task UpdateTask(UpdateTaskCommand command) 51 | { 52 | return await _mediator.Send(command); 53 | } 54 | 55 | [Authorize] 56 | [HttpDelete("{id}")] 57 | public async Task RemoveTask(int id) 58 | { 59 | return await _mediator.Send(new RemoveTaskCommand(id)); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build 6 | WORKDIR /src 7 | COPY ["WebAPI/WebAPI.csproj", "WebAPI/"] 8 | COPY ["Business/Business.csproj", "Business/"] 9 | COPY ["DataAccess/DataAccess.csproj", "DataAccess/"] 10 | COPY ["Core/Core.csproj", "Core/"] 11 | COPY ["Entities/Entities.csproj", "Entities/"] 12 | RUN dotnet restore "WebAPI/WebAPI.csproj" 13 | COPY . . 14 | WORKDIR "/src/WebAPI" 15 | RUN dotnet build "WebAPI.csproj" -c Release -o /app/build 16 | 17 | FROM build AS publish 18 | RUN dotnet publish "WebAPI.csproj" -c Release -o /app/publish 19 | 20 | FROM base AS final 21 | WORKDIR /app 22 | COPY --from=publish /app/publish . 23 | ENTRYPOINT ["dotnet", "WebAPI.dll"] 24 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Autofac.Extensions.DependencyInjection; 3 | using Business.DependencyResolvers; 4 | using Core.Configurations; 5 | using Core.DependencyResolvers; 6 | using Core.Utilities.Extensions; 7 | using Core.Utilities.Helpers; 8 | using Core.Utilities.IoC; 9 | using DataAccess.Concrete.EntityFramework.Contexts; 10 | using Entities.Concrete; 11 | using FluentValidation; 12 | using MediatR; 13 | using Microsoft.AspNetCore.Authentication.JwtBearer; 14 | using Microsoft.AspNetCore.Identity; 15 | using Microsoft.AspNetCore.Mvc; 16 | using Microsoft.EntityFrameworkCore; 17 | using Microsoft.IdentityModel.Tokens; 18 | using Microsoft.OpenApi.Models; 19 | using Newtonsoft.Json; 20 | using Newtonsoft.Json.Converters; 21 | using System.Reflection; 22 | 23 | var builder = WebApplication.CreateBuilder(args); 24 | 25 | // Add services to the container. 26 | 27 | builder.Services.AddControllers().AddNewtonsoftJson(opts => 28 | { 29 | opts.SerializerSettings.Converters.Add(new StringEnumConverter()); 30 | opts.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 31 | }); 32 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 33 | builder.Services.AddEndpointsApiExplorer(); 34 | 35 | builder.Services.AddSwaggerGen(c => 36 | { 37 | c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() 38 | { 39 | Name = "Authorization", 40 | Type = SecuritySchemeType.ApiKey, 41 | Scheme = "Bearer", 42 | BearerFormat = "JWT", 43 | In = ParameterLocation.Header, 44 | Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 1safsfsdfdfd\"", 45 | }); 46 | c.AddSecurityRequirement(new OpenApiSecurityRequirement 47 | { 48 | { 49 | new OpenApiSecurityScheme 50 | { 51 | Reference = new OpenApiReference 52 | { 53 | Type = ReferenceType.SecurityScheme, 54 | Id = "Bearer" 55 | } 56 | }, 57 | new string[] {} 58 | } 59 | }); 60 | }); 61 | 62 | builder.Services.AddMediatR(Assembly.GetExecutingAssembly()); 63 | builder.Services.Configure(options => 64 | { 65 | options.SuppressModelStateInvalidFilter = true; 66 | }); 67 | 68 | builder.Services.AddDbContext(options => 69 | { 70 | options.UseNpgsql(builder.Configuration.GetConnectionString("PostgreSqlConnection")); 71 | }); 72 | builder.Services.AddIdentity() 73 | .AddEntityFrameworkStores() 74 | .AddDefaultTokenProviders(); 75 | builder.Services.Configure(builder.Configuration.GetSection("JWTOptions")); 76 | builder.Services.AddAuthentication(options => 77 | { 78 | options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 79 | options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 80 | }).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, opts => 81 | { 82 | var jwtOptions = builder.Configuration.GetSection("JWTOptions").Get(); 83 | opts.TokenValidationParameters = new TokenValidationParameters() 84 | { 85 | ValidIssuer = jwtOptions.Issuer, 86 | ValidAudience = jwtOptions.Audience[0], 87 | IssuerSigningKey = SecurityKeyHelper.GetSymmetricSecurityKey(jwtOptions.SecurityKey), 88 | ValidateIssuerSigningKey = true, 89 | ValidateAudience = true, 90 | ValidateIssuer = true, 91 | ValidateLifetime = true, 92 | ClockSkew = TimeSpan.Zero 93 | }; 94 | }); 95 | 96 | builder.Services.Configure(options => 97 | { 98 | options.Password.RequireDigit = true; 99 | options.Password.RequireLowercase = true; 100 | options.Password.RequireUppercase = true; 101 | options.Password.RequiredLength = 9; 102 | options.Password.RequireNonAlphanumeric = false; 103 | options.User.RequireUniqueEmail = true; 104 | }); 105 | 106 | builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); 107 | builder.Services.AddDependencyResolvers((IConfiguration)builder.Configuration, new ICoreModule[] { 108 | new CoreModule() 109 | }); 110 | 111 | // Register services directly with Autofac here. 112 | // Don't call builder.Populate(), that happens in AutofacServiceProviderFactory. 113 | builder.Host.ConfigureContainer(builder => builder.RegisterModule(new AutofacBusinessModule())); 114 | 115 | ValidatorOptions.Global.LanguageManager.Enabled = false; 116 | 117 | var app = builder.Build(); 118 | AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); 119 | // Configure the HTTP request pipeline. 120 | if (app.Environment.IsDevelopment()) 121 | { 122 | app.UseSwagger(); 123 | app.UseSwaggerUI(); 124 | } 125 | 126 | 127 | 128 | using (var scope = app.Services.CreateScope()) 129 | { 130 | var dataContext = scope.ServiceProvider.GetRequiredService(); 131 | dataContext.Database.Migrate(); 132 | } 133 | 134 | 135 | app.UseCustomExceptionMiddleware(); 136 | app.UseHttpsRedirection(); 137 | app.UseAuthentication(); 138 | app.UseCors(builder => 139 | { 140 | builder 141 | .AllowAnyOrigin() 142 | .AllowAnyMethod() 143 | .AllowAnyHeader(); 144 | }); 145 | app.UseAuthorization(); 146 | 147 | app.MapControllers(); 148 | 149 | app.Run(); 150 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:28916", 8 | "sslPort": 44342 9 | } 10 | }, 11 | "profiles": { 12 | "WebAPI": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5129", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "IIS Express": { 23 | "commandName": "IISExpress", 24 | "launchBrowser": true, 25 | "launchUrl": "swagger", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/WebAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /TaskManagementAPP/WebAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "ConnectionStrings": { 9 | "PostgreSqlConnection": "User Id=postgres;Password=1283;Server=localhost;Port=5432;Database=Tasks;Integrated Security=true;" 10 | }, 11 | "JWTOptions": { 12 | "Audience": [ "www.taskapp.com" ], 13 | "Issuer": "www.taskapp.com", 14 | "AccessTokenExpiration": 120, 15 | "SecurityKey": "mysecuritykeyysdadsadsadadsadsadsadsadsadsadsadsadsadsadsa" 16 | }, 17 | "EmailSettings": { 18 | "Host": "yoursmtp", 19 | "Port": 587, 20 | "EnableSSL": true, 21 | "Email": "yourmail", 22 | "Password": "yourpassword" 23 | }, 24 | "SeriLogConfigurations": { 25 | "PostgreSqlConfiguration": { 26 | "ConnectionString": "User Id=postgres;Password=1283;Server=localhost;Port=5432;Database=Tasks;Integrated Security=true;" 27 | } 28 | }, 29 | "AllowedHosts": "*" 30 | } 31 | -------------------------------------------------------------------------------- /TaskManagementAPP/docker-compose.dcproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.1 5 | Linux 6 | b5893c25-59ee-48e9-a2ec-8a98efe2ec12 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TaskManagementAPP/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | tasksdb: 5 | image: postgres 6 | container_name: tasksdb 7 | restart : always 8 | ports: 9 | - 5432:5432 10 | environment: 11 | - "POSTGRES_USER=postgres" 12 | - "POSTGRES_PASSWORD=1283" 13 | volumes: 14 | - postgres_volume:/var/lib/postgresql/data 15 | webapi: 16 | image: webapi 17 | restart: always 18 | build: 19 | context: . 20 | dockerfile: WebAPI/Dockerfile 21 | ports: 22 | - "5129:80" 23 | environment: 24 | - ASPNETCORE_ENVIRONMENT=Development 25 | - "ConnectionStrings:PostgreSqlConnection=User ID=postgres; Password=1283; Server=tasksdb; Port=5432;Database=Tasks;Integrated Security=true;" 26 | - "SeriLogConfigurations:PostgreSqlConfiguration:ConnectionString=User ID=postgres; Password=1283; Server=tasksdb; Port=5432;Database=Tasks;Integrated Security=true;" 27 | 28 | volumes: 29 | postgres_volume: -------------------------------------------------------------------------------- /TaskManagementUI/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /TaskManagementUI/.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /src-capacitor 3 | /src-cordova 4 | /.quasar 5 | /node_modules 6 | .eslintrc.js 7 | /src-ssr 8 | -------------------------------------------------------------------------------- /TaskManagementUI/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy 3 | // This option interrupts the configuration hierarchy at this file 4 | // Remove this if you have an higher level ESLint config file (it usually happens into a monorepos) 5 | root: true, 6 | 7 | // https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser 8 | // Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working 9 | // `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted 10 | parserOptions: { 11 | parser: require.resolve('@typescript-eslint/parser'), 12 | extraFileExtensions: [ '.vue' ] 13 | }, 14 | 15 | env: { 16 | browser: true, 17 | es2021: true, 18 | node: true, 19 | 'vue/setup-compiler-macros': true 20 | }, 21 | 22 | // Rules order is important, please avoid shuffling them 23 | extends: [ 24 | // Base ESLint recommended rules 25 | // 'eslint:recommended', 26 | 27 | // https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage 28 | // ESLint typescript rules 29 | 'plugin:@typescript-eslint/recommended', 30 | 31 | // Uncomment any of the lines below to choose desired strictness, 32 | // but leave only one uncommented! 33 | // See https://eslint.vuejs.org/rules/#available-rules 34 | 'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention) 35 | // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) 36 | // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) 37 | 38 | // https://github.com/prettier/eslint-config-prettier#installation 39 | // usage with Prettier, provided by 'eslint-config-prettier'. 40 | 'prettier' 41 | ], 42 | 43 | plugins: [ 44 | // required to apply rules which need type information 45 | '@typescript-eslint', 46 | 47 | // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files 48 | // required to lint *.vue files 49 | 'vue' 50 | 51 | // https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674 52 | // Prettier has not been included as plugin to avoid performance impact 53 | // add it as an extension for your IDE 54 | 55 | ], 56 | 57 | globals: { 58 | ga: 'readonly', // Google Analytics 59 | cordova: 'readonly', 60 | __statics: 'readonly', 61 | __QUASAR_SSR__: 'readonly', 62 | __QUASAR_SSR_SERVER__: 'readonly', 63 | __QUASAR_SSR_CLIENT__: 'readonly', 64 | __QUASAR_SSR_PWA__: 'readonly', 65 | process: 'readonly', 66 | Capacitor: 'readonly', 67 | chrome: 'readonly' 68 | }, 69 | 70 | // add your custom rules here 71 | rules: { 72 | 73 | 'prefer-promise-reject-errors': 'off', 74 | 75 | quotes: ['warn', 'single', { avoidEscape: true }], 76 | 77 | // this rule, if on, would require explicit return type on the `render` function 78 | '@typescript-eslint/explicit-function-return-type': 'off', 79 | 80 | // in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled 81 | '@typescript-eslint/no-var-requires': 'off', 82 | 83 | // The core 'no-unused-vars' rules (in the eslint:recommeded ruleset) 84 | // does not work with type definitions 85 | 'no-unused-vars': 'off', 86 | 87 | // allow debugger during development only 88 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /TaskManagementUI/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .thumbs.db 3 | node_modules 4 | 5 | # Quasar core related directories 6 | .quasar 7 | /dist 8 | 9 | # Cordova related directories and files 10 | /src-cordova/node_modules 11 | /src-cordova/platforms 12 | /src-cordova/plugins 13 | /src-cordova/www 14 | 15 | # Capacitor related directories and files 16 | /src-capacitor/www 17 | /src-capacitor/node_modules 18 | 19 | # BEX related directories and files 20 | /src-bex/www 21 | /src-bex/js/core 22 | 23 | # Log files 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # Editor directories and files 29 | .idea 30 | *.suo 31 | *.ntvs* 32 | *.njsproj 33 | *.sln 34 | -------------------------------------------------------------------------------- /TaskManagementUI/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": true 4 | } 5 | -------------------------------------------------------------------------------- /TaskManagementUI/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "editorconfig.editorconfig", 6 | "johnsoncodehk.volar", 7 | "wayou.vscode-todo-highlight" 8 | ], 9 | "unwantedRecommendations": [ 10 | "octref.vetur", 11 | "hookyqr.beautify", 12 | "dbaeumer.jshint", 13 | "ms-vscode.vscode-typescript-tslint-plugin" 14 | ] 15 | } -------------------------------------------------------------------------------- /TaskManagementUI/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.bracketPairColorization.enabled": true, 3 | "editor.guides.bracketPairs": true, 4 | "editor.formatOnSave": true, 5 | "editor.defaultFormatter": "esbenp.prettier-vscode", 6 | "editor.codeActionsOnSave": [ 7 | "source.fixAll.eslint" 8 | ], 9 | "eslint.validate": [ 10 | "javascript", 11 | "javascriptreact", 12 | "typescript", 13 | "vue" 14 | ], 15 | "typescript.tsdk": "node_modules/typescript/lib" 16 | } -------------------------------------------------------------------------------- /TaskManagementUI/README.md: -------------------------------------------------------------------------------- 1 | # Task Management (taskmanagementui) 2 | 3 | Task Management 4 | 5 | ## Install the dependencies 6 | ```bash 7 | yarn 8 | # or 9 | npm install 10 | ``` 11 | 12 | ### Start the app in development mode (hot-code reloading, error reporting, etc.) 13 | ```bash 14 | quasar dev 15 | ``` 16 | 17 | 18 | ### Lint the files 19 | ```bash 20 | yarn lint 21 | # or 22 | npm run lint 23 | ``` 24 | 25 | 26 | ### Format the files 27 | ```bash 28 | yarn format 29 | # or 30 | npm run format 31 | ``` 32 | 33 | 34 | 35 | ### Build the app for production 36 | ```bash 37 | quasar build 38 | ``` 39 | 40 | ### Customize the configuration 41 | See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js). 42 | -------------------------------------------------------------------------------- /TaskManagementUI/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= productName %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /TaskManagementUI/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "taskmanagementui", 3 | "version": "0.0.1", 4 | "description": "Task Management", 5 | "productName": "Task Management", 6 | "author": "Yalçın ", 7 | "private": true, 8 | "scripts": { 9 | "lint": "eslint --ext .js,.ts,.vue ./", 10 | "format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore", 11 | "test": "echo \"No test specified\" && exit 0" 12 | }, 13 | "dependencies": { 14 | "@quasar/cli": "^1.3.2", 15 | "@quasar/extras": "^1.0.0", 16 | "@vuelidate/core": "^2.0.0-alpha.40", 17 | "@vuelidate/validators": "^2.0.0-alpha.28", 18 | "axios": "^0.21.1", 19 | "pinia": "^2.0.11", 20 | "quasar": "^2.6.0", 21 | "vue": "3.2.31", 22 | "vue-router": "^4.0.0" 23 | }, 24 | "devDependencies": { 25 | "@quasar/app-vite": "^1.0.0-alpha.0", 26 | "@types/node": "^12.20.21", 27 | "@typescript-eslint/eslint-plugin": "^5.10.0", 28 | "@typescript-eslint/parser": "^5.10.0", 29 | "autoprefixer": "^10.4.4", 30 | "eslint": "^8.10.0", 31 | "eslint-config-prettier": "^8.1.0", 32 | "eslint-plugin-vue": "^8.5.0", 33 | "postcss": "^8.4.12", 34 | "prettier": "^2.5.1", 35 | "tailwindcss": "^3.0.24", 36 | "typescript": "^4.5.4" 37 | }, 38 | "engines": { 39 | "node": "^18 || ^16 || ^14.19", 40 | "npm": ">= 6.13.4", 41 | "yarn": ">= 1.21.1" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /TaskManagementUI/postcss.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // https://github.com/michael-ciniawsky/postcss-load-config 3 | 4 | module.exports = { 5 | plugins: [ 6 | // https://github.com/postcss/autoprefixer 7 | require('tailwindcss'), 8 | require('autoprefixer')({ 9 | overrideBrowserslist: [ 10 | 'last 4 Chrome versions', 11 | 'last 4 Firefox versions', 12 | 'last 4 Edge versions', 13 | 'last 4 Safari versions', 14 | 'last 4 Android versions', 15 | 'last 4 ChromeAndroid versions', 16 | 'last 4 FirefoxAndroid versions', 17 | 'last 4 iOS versions' 18 | ] 19 | }) 20 | 21 | // https://github.com/elchininet/postcss-rtlcss 22 | // If you want to support RTL css, then 23 | // 1. yarn/npm install postcss-rtlcss 24 | // 2. optionally set quasar.config.js > framework > lang to an RTL language 25 | // 3. uncomment the following line: 26 | // require('postcss-rtlcss') 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /TaskManagementUI/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YALCINCAN/NET6_Vue3Typescript_TaskManagementAPP/efcecccf2ced10d5d6bef13af8006e24c83d14b4/TaskManagementUI/public/favicon.ico -------------------------------------------------------------------------------- /TaskManagementUI/public/icons/favicon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YALCINCAN/NET6_Vue3Typescript_TaskManagementAPP/efcecccf2ced10d5d6bef13af8006e24c83d14b4/TaskManagementUI/public/icons/favicon-128x128.png -------------------------------------------------------------------------------- /TaskManagementUI/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YALCINCAN/NET6_Vue3Typescript_TaskManagementAPP/efcecccf2ced10d5d6bef13af8006e24c83d14b4/TaskManagementUI/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /TaskManagementUI/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YALCINCAN/NET6_Vue3Typescript_TaskManagementAPP/efcecccf2ced10d5d6bef13af8006e24c83d14b4/TaskManagementUI/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /TaskManagementUI/public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YALCINCAN/NET6_Vue3Typescript_TaskManagementAPP/efcecccf2ced10d5d6bef13af8006e24c83d14b4/TaskManagementUI/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /TaskManagementUI/quasar.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | /* 4 | * This file runs in a Node context (it's NOT transpiled by Babel), so use only 5 | * the ES6 features that are supported by your Node version. https://node.green/ 6 | */ 7 | 8 | // Configuration for your app 9 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js 10 | 11 | 12 | const { configure } = require('quasar/wrappers'); 13 | 14 | 15 | module.exports = configure(function (/* ctx */) { 16 | return { 17 | eslint: { 18 | // fix: true, 19 | // include = [], 20 | // exclude = [], 21 | // rawOptions = {}, 22 | warnings: true, 23 | errors: false 24 | }, 25 | 26 | // https://v2.quasar.dev/quasar-cli-vite/prefetch-feature 27 | // preFetch: true, 28 | 29 | // app boot file (/src/boot) 30 | // --> boot files are part of "main.js" 31 | // https://v2.quasar.dev/quasar-cli-vite/boot-files 32 | boot: [ 33 | 34 | 'axios', 35 | ], 36 | 37 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css 38 | css: [ 39 | 'app.scss' 40 | ], 41 | 42 | // https://github.com/quasarframework/quasar/tree/dev/extras 43 | extras: [ 44 | // 'ionicons-v4', 45 | // 'mdi-v5', 46 | 'fontawesome-v6', 47 | // 'eva-icons', 48 | // 'themify', 49 | // 'line-awesome', 50 | // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! 51 | 52 | 'roboto-font', // optional, you are not bound to it 53 | 'material-icons', // optional, you are not bound to it 54 | ], 55 | 56 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build 57 | build: { 58 | target: { 59 | browser: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ], 60 | node: 'node16' 61 | }, 62 | 63 | vueRouterMode: 'history', // available values: 'hash', 'history' 64 | // vueRouterBase, 65 | // vueDevtools, 66 | // vueOptionsAPI: false, 67 | 68 | // rebuildCache: true, // rebuilds Vite/linter/etc cache on startup 69 | 70 | // publicPath: '/', 71 | // analyze: true, 72 | // env: {}, 73 | // rawDefine: {} 74 | // ignorePublicFolder: true, 75 | // minify: false, 76 | // polyfillModulePreload: true, 77 | // distDir 78 | 79 | // extendViteConf (viteConf) {}, 80 | // viteVuePluginOptions: {}, 81 | 82 | 83 | // vitePlugins: [ 84 | // [ 'package-name', { ..options.. } ] 85 | // ] 86 | }, 87 | 88 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer 89 | devServer: { 90 | // https: true 91 | open: false, // opens browser window automatically 92 | port: 8080 93 | }, 94 | 95 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework 96 | framework: { 97 | config: {}, 98 | 99 | // iconSet: 'material-icons', // Quasar icon set 100 | // lang: 'en-US', // Quasar language pack 101 | 102 | // For special cases outside of where the auto-import strategy can have an impact 103 | // (like functional components as one of the examples), 104 | // you can manually specify Quasar components/directives to be available everywhere: 105 | // 106 | // components: [], 107 | // directives: [], 108 | 109 | // Quasar plugins 110 | plugins: [ 111 | 'Notify', 112 | ] 113 | }, 114 | 115 | // animations: 'all', // --- includes all animations 116 | // https://v2.quasar.dev/options/animations 117 | animations: [], 118 | 119 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#sourcefiles 120 | // sourceFiles: { 121 | // rootComponent: 'src/App.vue', 122 | // router: 'src/router/index', 123 | // store: 'src/store/index', 124 | // registerServiceWorker: 'src-pwa/register-service-worker', 125 | // serviceWorker: 'src-pwa/custom-service-worker', 126 | // pwaManifestFile: 'src-pwa/manifest.json', 127 | // electronMain: 'src-electron/electron-main', 128 | // electronPreload: 'src-electron/electron-preload' 129 | // }, 130 | 131 | // https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr 132 | ssr: { 133 | // ssrPwaHtmlFilename: 'offline.html', // do NOT use index.html as name! 134 | // will mess up SSR 135 | 136 | // extendSSRWebserverConf (esbuildConf) {}, 137 | // extendPackageJson (json) {}, 138 | 139 | pwa: false, 140 | 141 | // manualStoreHydration: true, 142 | // manualPostHydrationTrigger: true, 143 | 144 | prodPort: 3000, // The default port that the production server should use 145 | // (gets superseded if process.env.PORT is specified at runtime) 146 | 147 | middlewares: [ 148 | 'render' // keep this as last one 149 | ] 150 | }, 151 | 152 | // https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa 153 | pwa: { 154 | workboxMode: 'generateSW', // or 'injectManifest' 155 | injectPwaMetaTags: true, 156 | swFilename: 'sw.js', 157 | manifestFilename: 'manifest.json', 158 | useCredentialsForManifestTag: false, 159 | // extendGenerateSWOptions (cfg) {} 160 | // extendInjectManifestOptions (cfg) {}, 161 | // extendManifestJson (json) {} 162 | // extendPWACustomSWConf (esbuildConf) {} 163 | }, 164 | 165 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-cordova-apps/configuring-cordova 166 | cordova: { 167 | // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing 168 | }, 169 | 170 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor 171 | capacitor: { 172 | hideSplashscreen: true 173 | }, 174 | 175 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron 176 | electron: { 177 | // extendElectronMainConf (esbuildConf) 178 | // extendElectronPreloadConf (esbuildConf) 179 | 180 | inspectPort: 5858, 181 | 182 | bundler: 'packager', // 'packager' or 'builder' 183 | 184 | packager: { 185 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options 186 | 187 | // OS X / Mac App Store 188 | // appBundleId: '', 189 | // appCategoryType: '', 190 | // osxSign: '', 191 | // protocol: 'myapp://path', 192 | 193 | // Windows only 194 | // win32metadata: { ... } 195 | }, 196 | 197 | builder: { 198 | // https://www.electron.build/configuration/configuration 199 | 200 | appId: 'taskmanagementui' 201 | } 202 | }, 203 | 204 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex 205 | bex: { 206 | contentScripts: [ 207 | 'my-content-script' 208 | ], 209 | 210 | // extendBexScriptsConf (esbuildConf) {} 211 | // extendBexManifestJson (json) {} 212 | } 213 | } 214 | }); 215 | -------------------------------------------------------------------------------- /TaskManagementUI/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 16 | -------------------------------------------------------------------------------- /TaskManagementUI/src/assets/quasar-logo-vertical.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /TaskManagementUI/src/boot/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YALCINCAN/NET6_Vue3Typescript_TaskManagementAPP/efcecccf2ced10d5d6bef13af8006e24c83d14b4/TaskManagementUI/src/boot/.gitkeep -------------------------------------------------------------------------------- /TaskManagementUI/src/boot/axios.ts: -------------------------------------------------------------------------------- 1 | import { boot } from 'quasar/wrappers'; 2 | import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'; 3 | 4 | declare module '@vue/runtime-core' { 5 | interface ComponentCustomProperties { 6 | $axios: AxiosInstance; 7 | } 8 | } 9 | const baseUrl = 'http://localhost:5129/api/'; 10 | // Be careful when using SSR for cross-request state pollution 11 | // due to creating a Singleton instance here; 12 | // If any client changes this (global) instance, it might be a 13 | // good idea to move this instance creation inside of the 14 | // "export default () => {}" function below (which runs individually 15 | // for each client) 16 | const api = axios.create({ baseURL: baseUrl }); 17 | 18 | 19 | export default boot(({ app, redirect }) => { 20 | api.interceptors.request.use( 21 | (config: AxiosRequestConfig): AxiosRequestConfig => { 22 | const accessToken = localStorage.getItem('accessToken'); 23 | if (accessToken) config.headers.Authorization = `Bearer ${accessToken}`; 24 | return config; 25 | } 26 | ); 27 | api.interceptors.response.use( 28 | (config) => config, 29 | async (error) => { 30 | if ( 31 | error.response && 32 | error.response.status === 401 33 | ) { 34 | redirect('/auth'); 35 | } else throw error; 36 | } 37 | ); 38 | }); 39 | 40 | export { api }; 41 | -------------------------------------------------------------------------------- /TaskManagementUI/src/components/Alert.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /TaskManagementUI/src/components/CreateTask.vue: -------------------------------------------------------------------------------- 1 | 177 | 178 | 271 | 272 | 273 | -------------------------------------------------------------------------------- /TaskManagementUI/src/components/Task.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /TaskManagementUI/src/composables/useNotify.ts: -------------------------------------------------------------------------------- 1 | import { useQuasar } from 'quasar'; 2 | 3 | export default function useNotify() { 4 | const $q = useQuasar(); 5 | 6 | const notifySuccess = (message: string) => { 7 | $q.notify({ 8 | type: 'positive', 9 | message: message || 'All right !', 10 | timeout: 2000, 11 | position: 'top-right', 12 | }); 13 | }; 14 | 15 | return { 16 | notifySuccess, 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /TaskManagementUI/src/css/app.scss: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/base"; 2 | @import "tailwindcss/components"; 3 | @import "tailwindcss/utilities"; 4 | -------------------------------------------------------------------------------- /TaskManagementUI/src/css/quasar.variables.scss: -------------------------------------------------------------------------------- 1 | // Quasar SCSS (& Sass) Variables 2 | // -------------------------------------------------- 3 | // To customize the look and feel of this app, you can override 4 | // the Sass/SCSS variables found in Quasar's source Sass/SCSS files. 5 | 6 | // Check documentation for full list of Quasar variables 7 | 8 | // Your own variables (that are declared here) and Quasar's own 9 | // ones will be available out of the box in your .vue/.scss/.sass files 10 | 11 | // It's highly recommended to change the default colors 12 | // to match your app's branding. 13 | // Tip: Use the "Theme Builder" on Quasar's documentation website. 14 | 15 | $primary : #1976D2; 16 | $secondary : #26A69A; 17 | $accent : #9C27B0; 18 | 19 | $dark : #1D1D1D; 20 | 21 | $positive : #21BA45; 22 | $negative : #C10015; 23 | $info : #31CCEC; 24 | $warning : #F2C037; 25 | -------------------------------------------------------------------------------- /TaskManagementUI/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | declare namespace NodeJS { 4 | interface ProcessEnv { 5 | NODE_ENV: string; 6 | VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined; 7 | VUE_ROUTER_BASE: string | undefined; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /TaskManagementUI/src/layouts/MainLayout.vue: -------------------------------------------------------------------------------- 1 | 65 | 66 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Auth/ConfirmEmail.ts: -------------------------------------------------------------------------------- 1 | export interface ConfirmEmail{ 2 | userId:string 3 | token:string 4 | } -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Auth/Login.ts: -------------------------------------------------------------------------------- 1 | export interface Login { 2 | username: string, 3 | password: string, 4 | } 5 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Auth/Register.ts: -------------------------------------------------------------------------------- 1 | export interface Register { 2 | username: string; 3 | password: string; 4 | confirmpassword: string; 5 | firstName: string; 6 | lastName:string, 7 | email: string; 8 | } 9 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Auth/TokenDTO.ts: -------------------------------------------------------------------------------- 1 | export interface TokenDTO{ 2 | accessToken:string, 3 | accessTokenExpiration:string, 4 | } 5 | 6 | 7 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Comment/CommentDTO.ts: -------------------------------------------------------------------------------- 1 | import { UserDTO } from '../UserDTO'; 2 | export interface CommentDTO{ 3 | id:number; 4 | commentDate:Date; 5 | description:string; 6 | userId:string; 7 | taskId:number; 8 | user:UserDTO; 9 | } 10 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Comment/CreateComment.ts: -------------------------------------------------------------------------------- 1 | export interface CreateComment { 2 | taskId: number; 3 | description: string; 4 | } 5 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Comment/UpdateComment.ts: -------------------------------------------------------------------------------- 1 | export interface UpdateComment { 2 | id: number; 3 | description: string; 4 | } 5 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Responses/DataResponse.ts: -------------------------------------------------------------------------------- 1 | export interface DataResponse{ 2 | data:T 3 | message:string, 4 | success:boolean, 5 | statusCode:number 6 | } -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Responses/ErrorResponse.ts: -------------------------------------------------------------------------------- 1 | export interface ErrorResponse{ 2 | success:boolean, 3 | statusCode:number, 4 | errors:string[] 5 | } -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Responses/SuccessResponse.ts: -------------------------------------------------------------------------------- 1 | export interface SuccessResponse{ 2 | success:boolean, 3 | statusCode:number, 4 | message:string 5 | } -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Task/CreateTask.ts: -------------------------------------------------------------------------------- 1 | export interface CreateTask { 2 | title:string; 3 | description:string; 4 | stringdeadline:string 5 | userIds:string[]; 6 | } 7 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Task/TaskDTO.ts: -------------------------------------------------------------------------------- 1 | import { UserTaskDTO } from './UserTaskDTO'; 2 | 3 | export interface TaskDTO { 4 | id: number; 5 | title: string; 6 | deadline: string; 7 | creatorId: string; 8 | status: string; 9 | assignedUsers: UserTaskDTO[]; 10 | } 11 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Task/TaskDetailDTO.ts: -------------------------------------------------------------------------------- 1 | import { CommentDTO } from '../Comment/CommentDTO'; 2 | import { UserTaskDTO } from './UserTaskDTO'; 3 | export interface TaskDetailDTO{ 4 | id:number; 5 | creatorId:string; 6 | title:string; 7 | description:string; 8 | taskStatusId:number; 9 | deadline:string; 10 | assignedUsers:UserTaskDTO[]; 11 | comments:CommentDTO[]; 12 | } 13 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Task/UpdateTask.ts: -------------------------------------------------------------------------------- 1 | export interface UpdateTask { 2 | id:number; 3 | title: string; 4 | description: string; 5 | stringdeadline: string; 6 | taskStatusId:number; 7 | userIds:string[] 8 | } 9 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/Task/UserTaskDTO.ts: -------------------------------------------------------------------------------- 1 | import { UserDTO } from '../UserDTO'; 2 | export interface UserTaskDTO { 3 | taskId:number; 4 | userId:string; 5 | user:UserDTO 6 | } 7 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/TaskStatus/TaskStatusDTO.ts: -------------------------------------------------------------------------------- 1 | export interface TaskStatusDTO { 2 | id: number; 3 | status: string; 4 | } 5 | -------------------------------------------------------------------------------- /TaskManagementUI/src/models/UserDTO.ts: -------------------------------------------------------------------------------- 1 | export interface UserDTO { 2 | id:string, 3 | userName:string, 4 | firstName:string, 5 | lastName:string, 6 | email:string 7 | } 8 | -------------------------------------------------------------------------------- /TaskManagementUI/src/pages/ConfirmEmail.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /TaskManagementUI/src/pages/ErrorNotFound.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 32 | -------------------------------------------------------------------------------- /TaskManagementUI/src/pages/IndexPage.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 34 | -------------------------------------------------------------------------------- /TaskManagementUI/src/quasar.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Forces TS to apply `@quasar/app-vite` augmentations of `quasar` package 4 | // Removing this would break `quasar/wrappers` imports as those typings are declared 5 | // into `@quasar/app-vite` 6 | // As a side effect, since `@quasar/app-vite` reference `quasar` to augment it, 7 | // this declaration also apply `quasar` own 8 | // augmentations (eg. adds `$q` into Vue component context) 9 | /// 10 | -------------------------------------------------------------------------------- /TaskManagementUI/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { route } from 'quasar/wrappers'; 2 | import { 3 | createMemoryHistory, 4 | createRouter, 5 | createWebHashHistory, 6 | createWebHistory, 7 | } from 'vue-router'; 8 | 9 | import routes from './routes'; 10 | 11 | /* 12 | * If not building with SSR mode, you can 13 | * directly export the Router instantiation; 14 | * 15 | * The function below can be async too; either use 16 | * async/await or return a Promise which resolves 17 | * with the Router instance. 18 | */ 19 | 20 | export default route(function (/* { store, ssrContext } */) { 21 | const createHistory = process.env.SERVER 22 | ? createMemoryHistory 23 | : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory); 24 | 25 | const Router = createRouter({ 26 | scrollBehavior: () => ({ left: 0, top: 0 }), 27 | routes, 28 | 29 | // Leave this as is and make changes in quasar.conf.js instead! 30 | // quasar.conf.js -> build -> vueRouterMode 31 | // quasar.conf.js -> build -> publicPath 32 | history: createHistory(process.env.VUE_ROUTER_BASE), 33 | }); 34 | Router.beforeEach((to) => { 35 | if (to.meta.requiresLogin) { 36 | const accessToken = window.localStorage.getItem('accessToken'); 37 | if (accessToken == null) { 38 | return { 39 | path: '/auth', 40 | }; 41 | } 42 | } 43 | }); 44 | return Router; 45 | }); 46 | -------------------------------------------------------------------------------- /TaskManagementUI/src/router/routes.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | 3 | const routes: RouteRecordRaw[] = [ 4 | { 5 | path: '/', 6 | component: () => import('layouts/MainLayout.vue'), 7 | children: [ 8 | { 9 | path: '', 10 | name: 'Index', 11 | component: () => import('pages/IndexPage.vue'), 12 | meta: { requiresLogin: true }, 13 | }, 14 | { 15 | path: '/auth', 16 | name: 'Auth', 17 | component: () => import('pages/Auth.vue'), 18 | }, 19 | { 20 | path: '/confirmemail/:userId/:token', 21 | name: 'ConfirmEmail', 22 | component: () => import('pages/ConfirmEmail.vue'), 23 | }, 24 | ], 25 | }, 26 | 27 | // Always leave this as last one, 28 | // but you can also remove it 29 | { 30 | path: '/:catchAll(.*)*', 31 | component: () => import('pages/ErrorNotFound.vue'), 32 | }, 33 | ]; 34 | 35 | export default routes; 36 | -------------------------------------------------------------------------------- /TaskManagementUI/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | /// 4 | /// 5 | 6 | // Mocks all files ending in `.vue` showing them as plain Vue instances 7 | declare module '*.vue' { 8 | import type { DefineComponent } from 'vue' 9 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 10 | const component: DefineComponent<{}, {}, any> 11 | export default component 12 | } 13 | -------------------------------------------------------------------------------- /TaskManagementUI/src/stores/Alert.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | interface AlertStore { 4 | errors: string[]; 5 | message: string; 6 | show: boolean; 7 | } 8 | 9 | export const useAlertStore = defineStore({ 10 | id: 'alert', 11 | state: (): AlertStore => ({ 12 | errors: [], 13 | message: '', 14 | show: false, 15 | }), 16 | getters: { 17 | getMessage(): string { 18 | return this.message; 19 | }, 20 | getErrors(): string[] { 21 | return this.errors; 22 | }, 23 | getShowStatus(): boolean { 24 | return this.show; 25 | }, 26 | }, 27 | actions: { 28 | setMessage(message: string) { 29 | if (message) { 30 | this.message = message; 31 | this.show = true; 32 | } 33 | }, 34 | setErrors(errors: string[]) { 35 | if (errors) { 36 | this.errors = errors; 37 | this.show = true; 38 | } 39 | }, 40 | clearAlert() { 41 | this.errors = []; 42 | (this.message = ''), (this.show = false); 43 | }, 44 | }, 45 | }); 46 | -------------------------------------------------------------------------------- /TaskManagementUI/src/stores/Auth.ts: -------------------------------------------------------------------------------- 1 | import { ConfirmEmail } from '../models/Auth/ConfirmEmail'; 2 | import { DataResponse } from './../models/Responses/DataResponse'; 3 | import { Register } from '../models/Auth/Register'; 4 | import { useAlertStore } from './Alert'; 5 | import { ErrorResponse } from './../models/Responses/ErrorResponse'; 6 | import { TokenDTO } from '../models/Auth/TokenDTO'; 7 | import { Login } from '../models/Auth/Login'; 8 | import { UserDTO } from '../models/UserDTO'; 9 | import { api } from 'boot/axios'; 10 | import { defineStore } from 'pinia'; 11 | import { AxiosError } from 'axios'; 12 | import { SuccessResponse } from 'src/models/Responses/SuccessResponse'; 13 | 14 | interface AuthStore { 15 | user: UserDTO; 16 | loggedIn: boolean; 17 | searcheduser: UserDTO; 18 | } 19 | 20 | export const useAuthStore = defineStore({ 21 | id: 'auth', 22 | state: (): AuthStore => ({ 23 | user: {} as UserDTO, 24 | loggedIn: false, 25 | searcheduser: {} as UserDTO, 26 | }), 27 | getters: { 28 | getLoggedIn(): boolean { 29 | return this.loggedIn; 30 | }, 31 | getUser(): UserDTO { 32 | return this.user; 33 | }, 34 | getSearchedUserFromState(): UserDTO { 35 | return this.searcheduser; 36 | }, 37 | }, 38 | actions: { 39 | async login(logincredentials: Login) { 40 | return await api 41 | .post>('auth/login', logincredentials) 42 | .then(async (response) => { 43 | if (response.data.success) { 44 | localStorage.setItem('accessToken', response.data.data.accessToken); 45 | await this.getAuthenticatedUser(); 46 | return response.data.success; 47 | } 48 | }) 49 | .catch((error: AxiosError) => { 50 | if (error.response && error.response.data) { 51 | const errorresponse = error.response.data as ErrorResponse; 52 | const alertStore = useAlertStore(); 53 | alertStore.setErrors(errorresponse.errors); 54 | } 55 | }); 56 | }, 57 | logout() { 58 | localStorage.removeItem('accessToken'); 59 | this.user = {} as UserDTO; 60 | this.loggedIn = false; 61 | }, 62 | async register(registercredentials: Register) { 63 | await api 64 | .post('auth/register', registercredentials) 65 | .then((response) => { 66 | if (response.data.success) { 67 | const alertStore = useAlertStore(); 68 | alertStore.setMessage(response.data.message); 69 | } 70 | }) 71 | .catch((error: AxiosError) => { 72 | if (error.response && error.response.data) { 73 | const alertStore = useAlertStore(); 74 | alertStore.clearAlert(); 75 | const errorresponse = error.response.data as ErrorResponse; 76 | alertStore.setErrors(errorresponse.errors); 77 | } 78 | }); 79 | }, 80 | async getAuthenticatedUser() { 81 | await api.get>('auth').then((response) => { 82 | this.user = response.data.data; 83 | this.loggedIn = true; 84 | }); 85 | }, 86 | async getUserByEmail(email: string) { 87 | await api 88 | .get>(`auth/${email}`) 89 | .then((response) => { 90 | if (response.data.success) { 91 | this.searcheduser = response.data.data; 92 | } 93 | }) 94 | .catch((error: AxiosError) => { 95 | if (error.response && error.response.data) { 96 | const alertStore = useAlertStore(); 97 | alertStore.clearAlert(); 98 | const errorresponse = error.response.data as ErrorResponse; 99 | alertStore.setErrors(errorresponse.errors); 100 | } 101 | }); 102 | }, 103 | async confirmEmail(confirmemaildata: ConfirmEmail) { 104 | await api 105 | .post('auth/confirmemail', confirmemaildata) 106 | .then((response) => { 107 | const alertStore = useAlertStore(); 108 | alertStore.setMessage(response.data.message); 109 | }) 110 | .catch((error: AxiosError) => { 111 | if (error.response && error.response.data) { 112 | const errorresponse = error.response.data as ErrorResponse; 113 | const alertStore = useAlertStore(); 114 | alertStore.setErrors(errorresponse.errors); 115 | } 116 | }); 117 | }, 118 | }, 119 | }); 120 | -------------------------------------------------------------------------------- /TaskManagementUI/src/stores/Comment.ts: -------------------------------------------------------------------------------- 1 | import { useTaskStore } from './Task'; 2 | import { UpdateComment } from './../models/Comment/UpdateComment'; 3 | import { CreateComment } from './../models/Comment/CreateComment'; 4 | import { ErrorResponse } from './../models/Responses/ErrorResponse'; 5 | import { api } from 'boot/axios'; 6 | import { defineStore } from 'pinia'; 7 | import { AxiosError } from 'axios'; 8 | import { SuccessResponse } from './../models/Responses/SuccessResponse'; 9 | import { useAlertStore } from './Alert'; 10 | 11 | export const useCommentStore = defineStore({ 12 | id: 'comment', 13 | state: () => ({}), 14 | actions: { 15 | async addComment(comment: CreateComment) { 16 | return await api 17 | .post('comments', comment) 18 | .then(async (response) => { 19 | if (response.data.success) { 20 | const taskStore = useTaskStore(); 21 | await taskStore.getTaskDetail(taskStore.selectedtaskId); 22 | return response.data.message; 23 | } 24 | }) 25 | .catch((error: AxiosError) => { 26 | if (error.response && error.response.data) { 27 | const errorresponse = error.response.data as ErrorResponse; 28 | const alertStore = useAlertStore(); 29 | alertStore.setErrors(errorresponse.errors); 30 | } 31 | }); 32 | }, 33 | async updateComment(comment: UpdateComment) { 34 | return await api 35 | .put('comments', comment) 36 | .then(async (response) => { 37 | if (response.data.success) { 38 | const taskStore = useTaskStore(); 39 | await taskStore.getTaskDetail(taskStore.selectedtaskId); 40 | return response.data.message; 41 | } 42 | }) 43 | .catch((error: AxiosError) => { 44 | if (error.response && error.response.data) { 45 | const errorresponse = error.response.data as ErrorResponse; 46 | const alertStore = useAlertStore(); 47 | alertStore.setErrors(errorresponse.errors); 48 | } 49 | }); 50 | }, 51 | async removeComment(commentId: number) { 52 | return await api 53 | .delete(`comments/${commentId}`) 54 | .then(async (response) => { 55 | if (response.data.success) { 56 | const taskStore = useTaskStore(); 57 | await taskStore.getTaskDetail(taskStore.selectedtaskId); 58 | return response.data.message; 59 | } 60 | }) 61 | .catch((error: AxiosError) => { 62 | if (error.response && error.response.data) { 63 | const errorresponse = error.response.data as ErrorResponse; 64 | const alertStore = useAlertStore(); 65 | alertStore.setErrors(errorresponse.errors); 66 | } 67 | }); 68 | } 69 | }, 70 | }); 71 | -------------------------------------------------------------------------------- /TaskManagementUI/src/stores/Task.ts: -------------------------------------------------------------------------------- 1 | import { UpdateTask } from './../models/Task/UpdateTask'; 2 | import { CreateTask } from './../models/Task/CreateTask'; 3 | import { TaskDetailDTO } from './../models/Task/TaskDetailDTO'; 4 | import { TaskDTO } from '../models/Task/TaskDTO'; 5 | import { DataResponse } from './../models/Responses/DataResponse'; 6 | import { useAlertStore } from './Alert'; 7 | import { ErrorResponse } from './../models/Responses/ErrorResponse'; 8 | import { api } from 'boot/axios'; 9 | import { defineStore } from 'pinia'; 10 | import { AxiosError } from 'axios'; 11 | import { SuccessResponse } from 'src/models/Responses/SuccessResponse'; 12 | 13 | interface TaskStore { 14 | tasks: TaskDTO[]; 15 | filteredtasks: TaskDTO[]; 16 | taskdetail: TaskDetailDTO; 17 | showDialog: boolean; 18 | showTaskDetailDialog: boolean; 19 | selectedtaskId: number; 20 | } 21 | 22 | export const useTaskStore = defineStore({ 23 | id: 'task', 24 | state: (): TaskStore => ({ 25 | tasks: [], 26 | filteredtasks: [], 27 | taskdetail: { description: '' } as TaskDetailDTO, 28 | showDialog: false, 29 | selectedtaskId: 0, 30 | showTaskDetailDialog: false, 31 | }), 32 | getters: { 33 | getTasksFromState(): TaskDTO[] { 34 | return this.tasks; 35 | }, 36 | getTaskDetailFromState(): TaskDetailDTO { 37 | return this.taskdetail; 38 | }, 39 | getShowDialog(): boolean { 40 | return this.showDialog; 41 | }, 42 | getFilteredTasks(): TaskDTO[] { 43 | return this.filteredtasks; 44 | }, 45 | }, 46 | actions: { 47 | async getTasks() { 48 | await api.get>('tasks').then((response) => { 49 | if (response.data.success) { 50 | this.tasks = response.data.data; 51 | this.filteredtasks = response.data.data; 52 | } 53 | }); 54 | }, 55 | async getTaskDetail(taskId: number) { 56 | this.selectedtaskId = taskId; 57 | this.showTaskDetailDialog = true; 58 | await api 59 | .get>(`tasks/${taskId}`) 60 | .then((response) => { 61 | if (response.data.success) { 62 | this.taskdetail = response.data.data; 63 | } 64 | }); 65 | }, 66 | async createTask(task: CreateTask) { 67 | return await api 68 | .post('tasks', task) 69 | .then(async (response) => { 70 | if (response.data.success) { 71 | await this.getTasks(); 72 | return response.data.message; 73 | } 74 | }) 75 | .catch((error: AxiosError) => { 76 | if (error.response && error.response.data) { 77 | const errorresponse = error.response.data as ErrorResponse; 78 | const alertStore = useAlertStore(); 79 | alertStore.clearAlert(); 80 | alertStore.setErrors(errorresponse.errors); 81 | } 82 | }); 83 | }, 84 | async updateTask(task: UpdateTask) { 85 | return await api 86 | .put('tasks', task) 87 | .then(async (response) => { 88 | if (response.data.success) { 89 | this.tasks = []; 90 | this.filteredtasks=[]; 91 | await this.getTasks(); 92 | return response.data.message; 93 | } 94 | }) 95 | .catch((error: AxiosError) => { 96 | if (error.response && error.response.data) { 97 | const errorresponse = error.response.data as ErrorResponse; 98 | const alertStore = useAlertStore(); 99 | alertStore.setErrors(errorresponse.errors); 100 | } 101 | }); 102 | }, 103 | async removeTask(taskId: number) { 104 | return await api 105 | .delete(`tasks/${taskId}`) 106 | .then(async (response) => { 107 | if (response.data.success) { 108 | this.tasks = []; 109 | this.filteredtasks=[]; 110 | await this.getTasks(); 111 | return response.data.message; 112 | } 113 | }) 114 | .catch((error: AxiosError) => { 115 | if (error.response && error.response.data) { 116 | const errorresponse = error.response.data as ErrorResponse; 117 | const alertStore = useAlertStore(); 118 | alertStore.setErrors(errorresponse.errors); 119 | } 120 | }); 121 | }, 122 | showCreateTaskDialog() { 123 | this.showDialog = true; 124 | }, 125 | clearSelectedTaskId(): void { 126 | this.selectedtaskId = 0; 127 | this.showTaskDetailDialog = false; 128 | this.showDialog = false; 129 | this.taskdetail = {} as TaskDetailDTO; 130 | }, 131 | searchTask(searchtext: string) { 132 | searchtext != '' && searchtext != null 133 | ? (this.filteredtasks = this.tasks.filter((task) => { 134 | return task.title.toLowerCase().includes(searchtext.toLowerCase()); 135 | })) 136 | : this.tasks; 137 | }, 138 | filterTasks(filter: string) { 139 | if (filter == 'all') { 140 | this.filteredtasks = this.tasks; 141 | } else { 142 | this.filteredtasks = this.tasks.filter((task) => { 143 | return task.status.toLowerCase() == filter.toLowerCase(); 144 | }); 145 | } 146 | }, 147 | }, 148 | }); 149 | -------------------------------------------------------------------------------- /TaskManagementUI/src/stores/TaskStatus.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | import { DataResponse } from "src/models/Responses/DataResponse"; 3 | import { api } from "src/boot/axios"; 4 | import { TaskStatusDTO } from "src/models/TaskStatus/TaskStatusDTO"; 5 | 6 | interface TaskStatusStore { 7 | taskStatuses: TaskStatusDTO[]; 8 | } 9 | 10 | export const useTaskStatusStore = defineStore({ 11 | id: "taskStatus", 12 | state: (): TaskStatusStore => ({ 13 | taskStatuses: [], 14 | }), 15 | getters: { 16 | getTaskStatusesFromState(): TaskStatusDTO[] { 17 | return this.taskStatuses; 18 | } 19 | }, 20 | actions: { 21 | async getTaskStatuses() { 22 | await api.get>('taskstatuses').then((response) => { 23 | if (response.data.success) { 24 | this.taskStatuses = response.data.data; 25 | } 26 | }); 27 | } 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /TaskManagementUI/src/stores/index.ts: -------------------------------------------------------------------------------- 1 | import { store } from 'quasar/wrappers' 2 | import { createPinia } from 'pinia' 3 | 4 | /* 5 | * If not building with SSR mode, you can 6 | * directly export the Store instantiation; 7 | * 8 | * The function below can be async too; either use 9 | * async/await or return a Promise which resolves 10 | * with the Store instance. 11 | */ 12 | 13 | export default store((/* { ssrContext } */) => { 14 | const pinia = createPinia() 15 | 16 | // You can add Pinia plugins here 17 | // pinia.use(SomePiniaPlugin) 18 | 19 | return pinia 20 | }) 21 | -------------------------------------------------------------------------------- /TaskManagementUI/src/stores/store-flag.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED, 3 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING 4 | import "quasar/dist/types/feature-flag"; 5 | 6 | declare module "quasar/dist/types/feature-flag" { 7 | interface QuasarFeatureFlags { 8 | store: true; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /TaskManagementUI/src/utilities/validators.ts: -------------------------------------------------------------------------------- 1 | export function oneUpperCase (password:string) :boolean { 2 | return /[A-Z]/.test(password) 3 | } 4 | -------------------------------------------------------------------------------- /TaskManagementUI/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ["./src/**/*.{vue,js,ts,jsx,tsx}"], 3 | theme: { 4 | extend: {}, 5 | screens: { 6 | sm: "600px", 7 | md: "1024px", 8 | lg: "1440px", 9 | xl: "1920px", 10 | }, 11 | }, 12 | plugins: [], 13 | prefix:"tw-" 14 | }; 15 | -------------------------------------------------------------------------------- /TaskManagementUI/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@quasar/app-vite/tsconfig-preset", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "src/*": [ 7 | "src/*" 8 | ], 9 | "app/*": [ 10 | "*" 11 | ], 12 | "components/*": [ 13 | "src/components/*" 14 | ], 15 | "layouts/*": [ 16 | "src/layouts/*" 17 | ], 18 | "pages/*": [ 19 | "src/pages/*" 20 | ], 21 | "assets/*": [ 22 | "src/assets/*" 23 | ], 24 | "boot/*": [ 25 | "src/boot/*" 26 | ], 27 | "stores/*": [ 28 | "src/stores/*" 29 | ] 30 | } 31 | }, 32 | "include": [ 33 | "src/**/*.ts", 34 | "src/**/*.d.ts", 35 | "src/**/*.tsx", 36 | "src/**/*.vue" 37 | ] 38 | } -------------------------------------------------------------------------------- /assets/taskmanagement.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YALCINCAN/NET6_Vue3Typescript_TaskManagementAPP/efcecccf2ced10d5d6bef13af8006e24c83d14b4/assets/taskmanagement.gif -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # NET6 with VueJS 3 (Typescript) Composition API (Quasar Framework) Task Management Project 2 | 3 | TaskManagement 4 | 5 | **

Features

** 6 | 7 | ## Backend 8 | - .NET6 9 | - Entity Framework Core – Code First 10 | - Response Wrappers 11 | - CQRS Pattern 12 | - Mediatr 13 | - UnitOfWork Pattern 14 | - Docker 15 | - Automapper 16 | - Repository Pattern 17 | - Net Core Identity with JWT Authentication 18 | - Database Seeding 19 | - Custom Exception Handling Middleware, 20 | - Confirmation Mail 21 | - Logging (Serilog) 22 | - Validation (Fluent Validation) with Aspect (Autofac,Castle.DynamicProxy) 23 | 24 | ## Frontend 25 | - Vue3 26 | - Composition API 27 | - Typescript 28 | - Vuelidate 29 | - Tailwindcss 30 | - Pinia 31 | - Route guards 32 | 33 | ## How To Start .Net API 34 | 35 | For api, you must edit the appsettings.json file before typing these commands. 36 | I used postgresql as database 37 | 38 | Docker support added you can start project with docker, first you must look docker compose yaml file and write 39 | 40 | ```sh 41 | docker compose -f "docker-compose.yml" up -d --build 42 | ``` 43 | 44 | When the project is up, the migrations run automatically, but you can run it manually with the following command. 45 | 46 | ```sh 47 | dotnet ef database update --context TaskContext --project "DataAccess" --startup-project "WebAPI" 48 | ``` 49 | 50 | After these commands, a database will be created. 51 | 52 | 53 | Default User Account : 54 | 55 | ```sh 56 | Username : defaultuser 57 | Password : 159357456qW 58 | ``` 59 | 60 | 61 | ## How To Start Quasar Project 62 | 63 | 64 | ```sh 65 | npm install 66 | quasar dev 67 | ``` 68 | 69 | 70 | 71 | --------------------------------------------------------------------------------