├── Template ├── ClientApp │ ├── src │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── app │ │ │ ├── users │ │ │ │ ├── users.component.css │ │ │ │ ├── users.component.spec.ts │ │ │ │ ├── users.component.html │ │ │ │ └── users.component.ts │ │ │ ├── app.component.html │ │ │ ├── home │ │ │ │ ├── home.component.ts │ │ │ │ └── home.component.html │ │ │ ├── app.component.ts │ │ │ ├── nav-menu │ │ │ │ ├── nav-menu.component.css │ │ │ │ ├── nav-menu.component.ts │ │ │ │ └── nav-menu.component.html │ │ │ ├── _data-services │ │ │ │ ├── user.data-service.js.map │ │ │ │ ├── user.data-service.js │ │ │ │ └── user.data-service.ts │ │ │ ├── app.server.module.ts │ │ │ ├── app.interceptor.module.ts │ │ │ └── app.module.ts │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.server.json │ │ ├── tsconfig.spec.json │ │ ├── styles.css │ │ ├── index.html │ │ ├── tslint.json │ │ ├── main.ts │ │ ├── test.ts │ │ ├── karma.conf.js │ │ └── polyfills.ts │ ├── e2e │ │ ├── src │ │ │ ├── app.po.ts │ │ │ └── app.e2e-spec.ts │ │ ├── tsconfig.e2e.json │ │ └── protractor.conf.js │ ├── .editorconfig │ ├── browserslist │ ├── tsconfig.json │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── tslint.json │ └── angular.json ├── wwwroot │ ├── favicon.ico │ └── api-doc.xml ├── Pages │ ├── _ViewImports.cshtml │ ├── Error.cshtml.cs │ └── Error.cshtml ├── appsettings.Development.json ├── WeatherForecast.cs ├── appsettings.json ├── Properties │ └── launchSettings.json ├── Program.cs ├── Controllers │ ├── WeatherForecastController.cs │ └── UsersController.cs ├── Startup.cs └── Template.csproj ├── Template.Domain ├── Template.Domain.csproj ├── Interfaces │ ├── IUserRepository.cs │ └── IRepository.cs ├── Entities │ └── User.cs └── Models │ └── Entity.cs ├── Template.Auth ├── Models │ └── Settings.cs ├── Template.Auth.csproj └── Services │ └── TokenService.cs ├── Template.Application ├── ViewModels │ ├── UserAuthenticateRequestViewModel.cs │ ├── EntityViewModel.cs │ ├── UserViewModel.cs │ └── UserAuthenticateResponseViewModel.cs ├── Interfaces │ └── IUserService.cs ├── Template.Application.csproj ├── AutoMapper │ └── AutoMapperSetup.cs └── Services │ └── UserService.cs ├── Template.Swagger ├── Template.Swagger.csproj └── SwaggerSetup.cs ├── Template.IoC ├── Template.IoC.csproj └── NativeInjector.cs ├── Template.Data ├── Repositories │ ├── UserRepository.cs │ └── Repository.cs ├── Template.Data.csproj ├── Mappings │ └── UserMap.cs ├── Migrations │ ├── 20200627153843_Field Email in User Table.cs │ ├── 20200627154559_Inserting Default User.cs │ ├── 20200627153606_User Table.cs │ ├── 20200627164403_Updating Default User.cs │ ├── 20200627164211_Common Fields.cs │ ├── 20200627153606_User Table.Designer.cs │ ├── 20200627153843_Field Email in User Table.Designer.cs │ ├── 20200627154559_Inserting Default User.Designer.cs │ ├── 20200627175238_GlobalConfigurations.cs │ ├── 20200926072248_Password Field.cs │ ├── 20200627164211_Common Fields.Designer.cs │ ├── 20200627164403_Updating Default User.Designer.cs │ ├── 20200627175238_GlobalConfigurations.Designer.cs │ ├── TemplateContextModelSnapshot.cs │ └── 20200926072248_Password Field.Designer.cs ├── Context │ └── TemplateContext.cs └── Extensions │ └── ModelBuilderExtension.cs ├── Template.Application.Tests ├── Template.Application.Tests.csproj └── Services │ └── UserServiceTests.cs ├── README.md ├── .gitignore └── Template.sln /Template/ClientApp/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/users/users.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Template/ClientApp/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /Template/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NicolasRibeiroFontes/Template-DotNetCore/HEAD/Template/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Template/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Template 2 | @namespace Template.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Template/wwwroot/api-doc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Template .Net Core 5 | 6 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /Template.Domain/Template.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-home', 5 | templateUrl: './home.component.html', 6 | }) 7 | export class HomeComponent { 8 | } 9 | -------------------------------------------------------------------------------- /Template/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html' 6 | }) 7 | export class AppComponent { 8 | title = 'app'; 9 | } 10 | -------------------------------------------------------------------------------- /Template/ClientApp/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "exclude": [ 8 | "src/test.ts", 9 | "**/*.spec.ts" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /Template/ClientApp/src/tsconfig.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "angularCompilerOptions": { 7 | "entryModule": "app/app.server.module#AppServerModule" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Template/ClientApp/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getMainHeading() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Template/ClientApp/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } -------------------------------------------------------------------------------- /Template.Auth/Models/Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Template.Auth.Models 6 | { 7 | public static class Settings 8 | { 9 | public static string Secret = "Template123Template123"; //Precisa ter mais de 16 caracteres. 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Template/ClientApp/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /Template.Domain/Interfaces/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Template.Domain.Entities; 5 | 6 | namespace Template.Domain.Interfaces 7 | { 8 | public interface IUserRepository: IRepository 9 | { 10 | IEnumerable GetAll(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Template/ClientApp/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "test.ts", 12 | "polyfills.ts" 13 | ], 14 | "include": [ 15 | "**/*.spec.ts", 16 | "**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Template.Application/ViewModels/UserAuthenticateRequestViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Template.Application.ViewModels 6 | { 7 | public class UserAuthenticateRequestViewModel 8 | { 9 | public string Email { get; set; } 10 | public string Password { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Template/ClientApp/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getMainHeading()).toEqual('Hello, world!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /Template/ClientApp/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | /* Provide sufficient contrast against white background */ 4 | a { 5 | color: #0366d6; 6 | } 7 | 8 | code { 9 | color: #e01a76; 10 | } 11 | 12 | .btn-primary { 13 | color: #fff; 14 | background-color: #1b6ec2; 15 | border-color: #1861ac; 16 | } 17 | -------------------------------------------------------------------------------- /Template/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Template 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/nav-menu/nav-menu.component.css: -------------------------------------------------------------------------------- 1 | a.navbar-brand { 2 | white-space: normal; 3 | text-align: center; 4 | word-break: break-all; 5 | } 6 | 7 | html { 8 | font-size: 14px; 9 | } 10 | @media (min-width: 768px) { 11 | html { 12 | font-size: 16px; 13 | } 14 | } 15 | 16 | .box-shadow { 17 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 18 | } 19 | -------------------------------------------------------------------------------- /Template/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "TemplateDB": "Server=DESKTOP-P1CHN45\\SQLEXPRESS; Database=Template; Trusted_Connection=True;" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*" 13 | } 14 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/_data-services/user.data-service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"user.data-service.js","sourceRoot":"","sources":["user.data-service.ts"],"names":[],"mappings":";;AAGA;IAIE,yBAAoB,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;QAFpC,WAAM,GAAW,YAAY,CAAC;IAEU,CAAC;IAEzC,6BAAG,GAAH;QACE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAEH,sBAAC;AAAD,CAAC,AAVD,IAUC;AAVY,0CAAe"} -------------------------------------------------------------------------------- /Template.Application/ViewModels/EntityViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Template.Application.ViewModels 6 | { 7 | public class EntityViewModel 8 | { 9 | public Guid Id { get; set; } 10 | public DateTime DateCreated { get; set; } 11 | public DateTime? DateUpdated { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Template.Domain/Entities/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Template.Domain.Models; 5 | 6 | namespace Template.Domain.Entities 7 | { 8 | public class User: Entity 9 | { 10 | public string Name { get; set; } 11 | public string Email { get; set; } 12 | public string Password { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Template.Domain/Models/Entity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Template.Domain.Models 6 | { 7 | public class Entity 8 | { 9 | public Guid Id { get; set; } 10 | public DateTime DateCreated { get; set; } 11 | public DateTime? DateUpdated { get; set; } 12 | public bool IsDeleted { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Template/ClientApp/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # For IE 9-11 support, please uncomment the last line of the file and adjust as needed 5 | > 0.5% 6 | last 2 versions 7 | Firefox ESR 8 | not dead 9 | # IE 9-11 -------------------------------------------------------------------------------- /Template/ClientApp/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Template 6 | 7 | 8 | 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | -------------------------------------------------------------------------------- /Template/ClientApp/src/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "app", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "app", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Template.Application/ViewModels/UserViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Template.Application.ViewModels 5 | { 6 | public class UserViewModel: EntityViewModel 7 | { 8 | [Required] 9 | public string Name { get; set; } 10 | [Required] 11 | public string Email { get; set; } 12 | [Required] 13 | public string Password { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/nav-menu/nav-menu.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-nav-menu', 5 | templateUrl: './nav-menu.component.html', 6 | styleUrls: ['./nav-menu.component.css'] 7 | }) 8 | export class NavMenuComponent { 9 | isExpanded = false; 10 | 11 | collapse() { 12 | this.isExpanded = false; 13 | } 14 | 15 | toggle() { 16 | this.isExpanded = !this.isExpanded; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/app.server.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ServerModule } from '@angular/platform-server'; 3 | import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; 4 | import { AppComponent } from './app.component'; 5 | import { AppModule } from './app.module'; 6 | 7 | @NgModule({ 8 | imports: [AppModule, ServerModule, ModuleMapLoaderModule], 9 | bootstrap: [AppComponent] 10 | }) 11 | export class AppServerModule { } 12 | -------------------------------------------------------------------------------- /Template.Swagger/Template.Swagger.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Template/ClientApp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "module": "esnext", 6 | "outDir": "./dist/out-tsc", 7 | "sourceMap": true, 8 | "declaration": false, 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "target": "es2015", 13 | "typeRoots": [ 14 | "node_modules/@types" 15 | ], 16 | "lib": [ 17 | "es2017", 18 | "dom" 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Template.Auth/Template.Auth.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Template.IoC/Template.IoC.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/_data-services/user.data-service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var UserDataService = /** @class */ (function () { 4 | function UserDataService(http) { 5 | this.http = http; 6 | this.module = '/api/users'; 7 | } 8 | UserDataService.prototype.get = function () { 9 | return this.http.get(this.module); 10 | }; 11 | return UserDataService; 12 | }()); 13 | exports.UserDataService = UserDataService; 14 | //# sourceMappingURL=user.data-service.js.map -------------------------------------------------------------------------------- /Template.Application/Interfaces/IUserService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Template.Application.ViewModels; 5 | 6 | namespace Template.Application.Interfaces 7 | { 8 | public interface IUserService 9 | { 10 | List Get(); 11 | bool Post(UserViewModel userViewModel); 12 | UserViewModel GetById(string id); 13 | bool Put(UserViewModel userViewModel); 14 | bool Delete(string id); 15 | UserAuthenticateResponseViewModel Authenticate(UserAuthenticateRequestViewModel user); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Template.Application/ViewModels/UserAuthenticateResponseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Template.Domain.Entities; 5 | 6 | namespace Template.Application.ViewModels 7 | { 8 | public class UserAuthenticateResponseViewModel 9 | { 10 | public UserAuthenticateResponseViewModel(UserViewModel user, string token) 11 | { 12 | this.User = user; 13 | this.Token = token; 14 | } 15 | 16 | public UserViewModel User { get; set; } 17 | public string Token { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Template.Data/Repositories/UserRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Template.Data.Context; 5 | using Template.Domain.Entities; 6 | using Template.Domain.Interfaces; 7 | 8 | namespace Template.Data.Repositories 9 | { 10 | public class UserRepository: Repository, IUserRepository 11 | { 12 | 13 | public UserRepository(TemplateContext context) 14 | : base(context) { } 15 | 16 | public IEnumerable GetAll() 17 | { 18 | return Query(x => !x.IsDeleted); 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Template.Application/Template.Application.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Template.Data/Template.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Template/ClientApp/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | export function getBaseUrl() { 8 | return document.getElementsByTagName('base')[0].href; 9 | } 10 | 11 | const providers = [ 12 | { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] } 13 | ]; 14 | 15 | if (environment.production) { 16 | enableProdMode(); 17 | } 18 | 19 | platformBrowserDynamic(providers).bootstrapModule(AppModule) 20 | .catch(err => console.log(err)); 21 | -------------------------------------------------------------------------------- /Template.Application/AutoMapper/AutoMapperSetup.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using Template.Application.ViewModels; 6 | using Template.Domain.Entities; 7 | 8 | namespace Template.Application.AutoMapper 9 | { 10 | public class AutoMapperSetup: Profile 11 | { 12 | public AutoMapperSetup() 13 | { 14 | #region ViewModelToDomain 15 | 16 | CreateMap(); 17 | 18 | #endregion 19 | 20 | #region DomainToViewModel 21 | 22 | CreateMap(); 23 | 24 | #endregion 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Template.Data/Mappings/UserMap.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using Template.Domain.Entities; 7 | 8 | namespace Template.Data.Mappings 9 | { 10 | public class UserMap: IEntityTypeConfiguration 11 | { 12 | public void Configure(EntityTypeBuilder builder) 13 | { 14 | builder.Property(x => x.Id).IsRequired(); 15 | 16 | builder.Property(x => x.Name).HasMaxLength(100).IsRequired(); 17 | 18 | builder.Property(x => x.Password).IsRequired().HasDefaultValue("TesteTemplate"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Template/ClientApp/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /dist-server 6 | /tmp 7 | /out-tsc 8 | 9 | # dependencies 10 | /node_modules 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.sass-cache 30 | /connect.lock 31 | /coverage 32 | /libpeerconnection.log 33 | npm-debug.log 34 | yarn-error.log 35 | testem.log 36 | /typings 37 | 38 | # System Files 39 | .DS_Store 40 | Thumbs.db 41 | -------------------------------------------------------------------------------- /Template/ClientApp/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * In development mode, to ignore zone related error stack frames such as 11 | * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can 12 | * import the following file, but please comment it out in production mode 13 | * because it will have performance impact when throw error 14 | */ 15 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 16 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627153843_Field Email in User Table.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace Template.Data.Migrations 4 | { 5 | public partial class FieldEmailinUserTable : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.AddColumn( 10 | name: "Email", 11 | table: "Users", 12 | nullable: true); 13 | } 14 | 15 | protected override void Down(MigrationBuilder migrationBuilder) 16 | { 17 | migrationBuilder.DropColumn( 18 | name: "Email", 19 | table: "Users"); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Template/ClientApp/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/_data-services/user.data-service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from "@angular/common/http"; 2 | import { Injectable } from "@angular/core"; 3 | 4 | @Injectable() 5 | export class UserDataService { 6 | 7 | module: string = '/api/users'; 8 | 9 | constructor(private http: HttpClient) { } 10 | 11 | get() { 12 | return this.http.get(this.module); 13 | } 14 | 15 | post(data) { 16 | return this.http.post(this.module, data); 17 | } 18 | 19 | put(data) { 20 | return this.http.put(this.module, data); 21 | } 22 | 23 | delete() { 24 | return this.http.delete(this.module); 25 | } 26 | 27 | authenticate(data) { 28 | return this.http.post(this.module + '/authenticate', data); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Template.IoC/NativeInjector.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using System; 3 | using Template.Application.Interfaces; 4 | using Template.Application.Services; 5 | using Template.Data.Repositories; 6 | using Template.Domain.Interfaces; 7 | 8 | namespace Template.IoC 9 | { 10 | public static class NativeInjector 11 | { 12 | public static void RegisterServices(IServiceCollection services) 13 | { 14 | #region Services 15 | 16 | services.AddScoped(); 17 | 18 | #endregion 19 | 20 | #region Repositories 21 | 22 | services.AddScoped(); 23 | 24 | #endregion 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/users/users.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UsersComponent } from './users.component'; 4 | 5 | describe('UsersComponent', () => { 6 | let component: UsersComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ UsersComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UsersComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /Template/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:59419", 7 | "sslPort": 44320 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "Template": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Template/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Template 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Template/ClientApp/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require("jasmine-spec-reporter"); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: ["./src/**/*.e2e-spec.ts"], 9 | capabilities: { 10 | browserName: "chrome" 11 | }, 12 | directConnect: true, 13 | baseUrl: "http://localhost:4200/", 14 | framework: "jasmine", 15 | jasmineNodeOpts: { 16 | showColors: true, 17 | defaultTimeoutInterval: 30000, 18 | print: function() {} 19 | }, 20 | onPrepare() { 21 | require("ts-node").register({ 22 | project: require("path").join(__dirname, "./tsconfig.e2e.json") 23 | }); 24 | jasmine 25 | .getEnv() 26 | .addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Template.Data/Context/TemplateContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using Template.Data.Extensions; 6 | using Template.Data.Mappings; 7 | using Template.Domain.Entities; 8 | 9 | namespace Template.Data.Context 10 | { 11 | public class TemplateContext: DbContext 12 | { 13 | public TemplateContext(DbContextOptions option) 14 | : base(option) { } 15 | 16 | #region "DBSets" 17 | 18 | public DbSet Users { get; set; } 19 | 20 | #endregion 21 | 22 | protected override void OnModelCreating(ModelBuilder modelBuilder) 23 | { 24 | modelBuilder.ApplyConfiguration(new UserMap()); 25 | 26 | modelBuilder.ApplyGlobalConfigurations(); 27 | modelBuilder.SeedData(); 28 | 29 | base.OnModelCreating(modelBuilder); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627154559_Inserting Default User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Template.Data.Migrations 5 | { 6 | public partial class InsertingDefaultUser : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.InsertData( 11 | table: "Users", 12 | columns: new[] { "Id", "Email", "Name" }, 13 | values: new object[] { new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), "userdefault@template.com", "User Default" }); 14 | } 15 | 16 | protected override void Down(MigrationBuilder migrationBuilder) 17 | { 18 | migrationBuilder.DeleteData( 19 | table: "Users", 20 | keyColumn: "Id", 21 | keyValue: new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919")); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Template/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Template.Pages 11 | { 12 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 13 | public class ErrorModel : PageModel 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public ErrorModel(ILogger logger) 18 | { 19 | _logger = logger; 20 | } 21 | 22 | public string RequestId { get; set; } 23 | 24 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 25 | 26 | public void OnGet() 27 | { 28 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Template/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

13 | Request ID: @Model.RequestId 14 |

15 | } 16 | 17 |

Development Mode

18 |

19 | Swapping to the Development environment displays detailed information about the error that occurred. 20 |

21 |

22 | The Development environment shouldn't be enabled for deployed applications. 23 | It can result in displaying sensitive information from exceptions to end users. 24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 25 | and restarting the app. 26 |

27 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627153606_User Table.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Template.Data.Migrations 5 | { 6 | public partial class UserTable : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "Users", 12 | columns: table => new 13 | { 14 | Id = table.Column(nullable: false), 15 | Name = table.Column(maxLength: 100, nullable: false) 16 | }, 17 | constraints: table => 18 | { 19 | table.PrimaryKey("PK_Users", x => x.Id); 20 | }); 21 | } 22 | 23 | protected override void Down(MigrationBuilder migrationBuilder) 24 | { 25 | migrationBuilder.DropTable( 26 | name: "Users"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Template.Application.Tests/Template.Application.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/app.interceptor.module.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, NgModule } from '@angular/core'; 2 | 3 | import { 4 | HttpEvent, 5 | HttpInterceptor, 6 | HttpHandler, 7 | HttpRequest, 8 | } from '@angular/common/http'; 9 | import { HTTP_INTERCEPTORS } from '@angular/common/http'; 10 | import { Observable } from 'rxjs'; 11 | 12 | 13 | @Injectable() 14 | export class HttpsRequestInterceptor implements HttpInterceptor { 15 | 16 | intercept( 17 | req: HttpRequest, 18 | next: HttpHandler, 19 | ): Observable> { 20 | var _user = JSON.parse(localStorage.getItem('user_logged')); 21 | 22 | const dupReq = req.clone({ 23 | headers: req.headers.set('authorization', (_user && _user.token) ? 'Bearer ' + _user.token : ''), 24 | }); 25 | return next.handle(dupReq); 26 | 27 | } 28 | 29 | } 30 | 31 | 32 | @NgModule({ 33 | providers: [ 34 | { 35 | provide: HTTP_INTERCEPTORS, 36 | useClass: HttpsRequestInterceptor, 37 | multi: true, 38 | }, 39 | ], 40 | }) 41 | 42 | export class Interceptor { } 43 | -------------------------------------------------------------------------------- /Template/ClientApp/src/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627164403_Updating Default User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Template.Data.Migrations 5 | { 6 | public partial class UpdatingDefaultUser : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.UpdateData( 11 | table: "Users", 12 | keyColumn: "Id", 13 | keyValue: new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 14 | column: "DateCreated", 15 | value: new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified)); 16 | } 17 | 18 | protected override void Down(MigrationBuilder migrationBuilder) 19 | { 20 | migrationBuilder.UpdateData( 21 | table: "Users", 22 | keyColumn: "Id", 23 | keyValue: new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 24 | column: "DateCreated", 25 | value: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Template/ClientApp/README.md: -------------------------------------------------------------------------------- 1 | # Template 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.0. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | import { AppComponent } from './app.component'; 8 | import { NavMenuComponent } from './nav-menu/nav-menu.component'; 9 | import { HomeComponent } from './home/home.component'; 10 | import { UsersComponent } from './users/users.component'; 11 | import { UserDataService } from './_data-services/user.data-service'; 12 | import { Interceptor } from './app.interceptor.module'; 13 | 14 | @NgModule({ 15 | declarations: [ 16 | AppComponent, 17 | NavMenuComponent, 18 | HomeComponent, 19 | UsersComponent 20 | ], 21 | imports: [ 22 | BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), 23 | HttpClientModule, 24 | FormsModule, 25 | RouterModule.forRoot([ 26 | { path: '', component: HomeComponent, pathMatch: 'full' }, 27 | { path: 'users', component: UsersComponent }, 28 | ]), 29 | Interceptor 30 | ], 31 | providers: [UserDataService], 32 | bootstrap: [AppComponent] 33 | }) 34 | export class AppModule { } 35 | -------------------------------------------------------------------------------- /Template/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace Template.Controllers 9 | { 10 | [ApiController] 11 | [Route("[controller]")] 12 | public class WeatherForecastController : ControllerBase 13 | { 14 | private static readonly string[] Summaries = new[] 15 | { 16 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 17 | }; 18 | 19 | private readonly ILogger _logger; 20 | 21 | public WeatherForecastController(ILogger logger) 22 | { 23 | _logger = logger; 24 | } 25 | 26 | [HttpGet] 27 | public IEnumerable Get() 28 | { 29 | var rng = new Random(); 30 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 31 | { 32 | Date = DateTime.Now.AddDays(index), 33 | TemperatureC = rng.Next(-20, 55), 34 | Summary = Summaries[rng.Next(Summaries.Length)] 35 | }) 36 | .ToArray(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/nav-menu/nav-menu.component.html: -------------------------------------------------------------------------------- 1 |
2 | 40 |
41 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627164211_Common Fields.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Template.Data.Migrations 5 | { 6 | public partial class CommonFields : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.AddColumn( 11 | name: "DateCreated", 12 | table: "Users", 13 | nullable: false, 14 | defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); 15 | 16 | migrationBuilder.AddColumn( 17 | name: "DateUpdated", 18 | table: "Users", 19 | nullable: true); 20 | 21 | migrationBuilder.AddColumn( 22 | name: "IsDeleted", 23 | table: "Users", 24 | nullable: false, 25 | defaultValue: false); 26 | } 27 | 28 | protected override void Down(MigrationBuilder migrationBuilder) 29 | { 30 | migrationBuilder.DropColumn( 31 | name: "DateCreated", 32 | table: "Users"); 33 | 34 | migrationBuilder.DropColumn( 35 | name: "DateUpdated", 36 | table: "Users"); 37 | 38 | migrationBuilder.DropColumn( 39 | name: "IsDeleted", 40 | table: "Users"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Template.Swagger/SwaggerSetup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.OpenApi.Models; 4 | using System.IO; 5 | 6 | namespace Template.Swagger 7 | { 8 | public static class SwaggerSetup 9 | { 10 | public static IServiceCollection AddSwaggerConfiguration(this IServiceCollection services) 11 | { 12 | return services.AddSwaggerGen(opt => 13 | { 14 | opt.SwaggerDoc("v1", new OpenApiInfo 15 | { 16 | Title = "Template .Net Core", 17 | Version = "v1", 18 | Description = "Tutorial de desenvolvimento com .Net Core e Angular.", 19 | Contact = new OpenApiContact 20 | { 21 | Name = "Nicolas Fontes", 22 | Email = "nicolas.rfontes@gmail.com" 23 | } 24 | }); 25 | 26 | string xmlPath = Path.Combine("wwwroot", "api-doc.xml"); 27 | opt.IncludeXmlComments(xmlPath); 28 | }); 29 | } 30 | 31 | public static IApplicationBuilder UseSwaggerConfiguration(this IApplicationBuilder app) 32 | { 33 | return app.UseSwagger().UseSwaggerUI(c => 34 | { 35 | c.RoutePrefix = "documentation"; 36 | c.SwaggerEndpoint("../swagger/v1/swagger.json", "API v1"); 37 | }); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |

Hello, world!!!

2 |

Welcome to your new single-page application, built with:

3 | 8 |

To help you get started, we've also set up:

9 |
    10 |
  • Client-side navigation. For example, click Counter then Back to return here.
  • 11 |
  • Angular CLI integration. In development mode, there's no need to run ng serve. It runs in the background automatically, so your client-side resources are dynamically built on demand and the page refreshes when you modify any file.
  • 12 |
  • Efficient production builds. In production mode, development-time features are disabled, and your dotnet publish configuration automatically invokes ng build to produce minified, ahead-of-time compiled JavaScript files.
  • 13 |
14 |

The ClientApp subdirectory is a standard Angular CLI application. If you open a command prompt in that directory, you can run any ng command (e.g., ng test), or use npm to install extra packages into it.

15 | -------------------------------------------------------------------------------- /Template.Auth/Services/TokenService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.IdentityModel.Tokens; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IdentityModel.Tokens.Jwt; 5 | using System.Security.Claims; 6 | using System.Security.Principal; 7 | using System.Text; 8 | using Template.Auth.Models; 9 | using Template.Domain.Entities; 10 | 11 | namespace Template.Auth.Services 12 | { 13 | public static class TokenService 14 | { 15 | public static string GenerateToken(User user) 16 | { 17 | var tokenHandler = new JwtSecurityTokenHandler(); 18 | var key = Encoding.ASCII.GetBytes(Settings.Secret); 19 | var tokenDescriptor = new SecurityTokenDescriptor 20 | { 21 | Subject = new ClaimsIdentity(new Claim[] 22 | { 23 | new Claim(ClaimTypes.Name, user.Name), 24 | new Claim(ClaimTypes.Email, user.Email), 25 | new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()) 26 | }), 27 | Expires = DateTime.UtcNow.AddHours(3), 28 | SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) 29 | }; 30 | var token = tokenHandler.CreateToken(tokenDescriptor); 31 | return tokenHandler.WriteToken(token); 32 | } 33 | 34 | public static string GetValueFromClaim(IIdentity identity, string field) 35 | { 36 | var claims = identity as ClaimsIdentity; 37 | 38 | return claims.FindFirst(field).Value; 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627153606_User Table.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Template.Data.Context; 9 | 10 | namespace Template.Data.Migrations 11 | { 12 | [DbContext(typeof(TemplateContext))] 13 | [Migration("20200627153606_User Table")] 14 | partial class UserTable 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("Template.Domain.Entities.User", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("uniqueidentifier"); 29 | 30 | b.Property("Name") 31 | .IsRequired() 32 | .HasColumnType("nvarchar(100)") 33 | .HasMaxLength(100); 34 | 35 | b.HasKey("Id"); 36 | 37 | b.ToTable("Users"); 38 | }); 39 | #pragma warning restore 612, 618 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Template.Domain/Interfaces/IRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Template.Domain.Interfaces 9 | { 10 | public interface IRepository : IDisposable where TEntity : class 11 | { 12 | TEntity Create(TEntity model); 13 | 14 | List Create(List model); 15 | 16 | bool Update(TEntity model); 17 | 18 | bool Update(List model); 19 | 20 | bool Delete(TEntity model); 21 | 22 | bool Delete(params object[] Keys); 23 | 24 | bool Delete(Expression> where); 25 | 26 | int Save(); 27 | 28 | TEntity Find(params object[] Keys); 29 | 30 | TEntity Find(Expression> where); 31 | 32 | TEntity Find(Expression> predicate, Func, object> includes); 33 | 34 | IQueryable Query(Expression> where); 35 | 36 | IQueryable Query(Expression> predicate, Func, object> includes); 37 | 38 | Task CreateAsync(TEntity model); 39 | 40 | Task UpdateAsync(TEntity model); 41 | 42 | Task DeleteAsync(Expression> where); 43 | 44 | Task DeleteAsync(TEntity model); 45 | 46 | Task DeleteAsync(params object[] Keys); 47 | 48 | Task SaveAsync(); 49 | 50 | Task GetAsync(params object[] Keys); 51 | 52 | Task GetAsync(Expression> where); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627153843_Field Email in User Table.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Template.Data.Context; 9 | 10 | namespace Template.Data.Migrations 11 | { 12 | [DbContext(typeof(TemplateContext))] 13 | [Migration("20200627153843_Field Email in User Table")] 14 | partial class FieldEmailinUserTable 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("Template.Domain.Entities.User", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("uniqueidentifier"); 29 | 30 | b.Property("Email") 31 | .HasColumnType("nvarchar(max)"); 32 | 33 | b.Property("Name") 34 | .IsRequired() 35 | .HasColumnType("nvarchar(100)") 36 | .HasMaxLength(100); 37 | 38 | b.HasKey("Id"); 39 | 40 | b.ToTable("Users"); 41 | }); 42 | #pragma warning restore 612, 618 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Template/ClientApp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "template", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "build:ssr": "ng run Template:server:dev", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@angular/animations": "8.2.12", 16 | "@angular/common": "8.2.12", 17 | "@angular/compiler": "8.2.12", 18 | "@angular/core": "8.2.12", 19 | "@angular/forms": "8.2.12", 20 | "@angular/platform-browser": "8.2.12", 21 | "@angular/platform-browser-dynamic": "8.2.12", 22 | "@angular/platform-server": "8.2.12", 23 | "@angular/router": "8.2.12", 24 | "@nguniversal/module-map-ngfactory-loader": "8.1.1", 25 | "aspnet-prerendering": "^3.0.1", 26 | "bootstrap": "^4.3.1", 27 | "core-js": "^3.3.3", 28 | "jquery": "3.4.1", 29 | "oidc-client": "^1.9.1", 30 | "popper.js": "^1.16.0", 31 | "rxjs": "^6.5.3", 32 | "zone.js": "0.9.1" 33 | }, 34 | "devDependencies": { 35 | "@angular-devkit/build-angular": "^0.803.14", 36 | "@angular/cli": "8.3.14", 37 | "@angular/compiler-cli": "8.2.12", 38 | "@angular/language-service": "8.2.12", 39 | "@types/jasmine": "~3.4.4", 40 | "@types/jasminewd2": "~2.0.8", 41 | "@types/node": "~12.11.6", 42 | "codelyzer": "^5.2.0", 43 | "jasmine-core": "~3.5.0", 44 | "jasmine-spec-reporter": "~4.2.1", 45 | "karma": "^4.4.1", 46 | "karma-chrome-launcher": "~3.1.0", 47 | "karma-coverage-istanbul-reporter": "~2.1.0", 48 | "karma-jasmine": "~2.0.1", 49 | "karma-jasmine-html-reporter": "^1.4.2", 50 | "typescript": "3.5.3" 51 | }, 52 | "optionalDependencies": { 53 | "node-sass": "^4.12.0", 54 | "protractor": "~5.4.2", 55 | "ts-node": "~8.4.1", 56 | "tslint": "~5.20.0" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627154559_Inserting Default User.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Template.Data.Context; 9 | 10 | namespace Template.Data.Migrations 11 | { 12 | [DbContext(typeof(TemplateContext))] 13 | [Migration("20200627154559_Inserting Default User")] 14 | partial class InsertingDefaultUser 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("Template.Domain.Entities.User", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("uniqueidentifier"); 29 | 30 | b.Property("Email") 31 | .HasColumnType("nvarchar(max)"); 32 | 33 | b.Property("Name") 34 | .IsRequired() 35 | .HasColumnType("nvarchar(100)") 36 | .HasMaxLength(100); 37 | 38 | b.HasKey("Id"); 39 | 40 | b.ToTable("Users"); 41 | 42 | b.HasData( 43 | new 44 | { 45 | Id = new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 46 | Email = "userdefault@template.com", 47 | Name = "User Default" 48 | }); 49 | }); 50 | #pragma warning restore 612, 618 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627175238_GlobalConfigurations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Template.Data.Migrations 5 | { 6 | public partial class GlobalConfigurations : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.AlterColumn( 11 | name: "IsDeleted", 12 | table: "Users", 13 | nullable: false, 14 | defaultValue: false, 15 | oldClrType: typeof(bool), 16 | oldType: "bit"); 17 | 18 | migrationBuilder.AlterColumn( 19 | name: "DateCreated", 20 | table: "Users", 21 | nullable: false, 22 | defaultValue: new DateTime(2020, 6, 27, 18, 52, 38, 325, DateTimeKind.Local).AddTicks(9630), 23 | oldClrType: typeof(DateTime), 24 | oldType: "datetime2"); 25 | 26 | migrationBuilder.UpdateData( 27 | table: "Users", 28 | keyColumn: "Id", 29 | keyValue: new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 30 | column: "DateCreated", 31 | value: new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified)); 32 | } 33 | 34 | protected override void Down(MigrationBuilder migrationBuilder) 35 | { 36 | migrationBuilder.AlterColumn( 37 | name: "IsDeleted", 38 | table: "Users", 39 | type: "bit", 40 | nullable: false, 41 | oldClrType: typeof(bool), 42 | oldDefaultValue: false); 43 | 44 | migrationBuilder.AlterColumn( 45 | name: "DateCreated", 46 | table: "Users", 47 | type: "datetime2", 48 | nullable: false, 49 | oldClrType: typeof(DateTime), 50 | oldDefaultValue: new DateTime(2020, 6, 27, 18, 52, 38, 325, DateTimeKind.Local).AddTicks(9630)); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Template/Controllers/UsersController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Claims; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Template.Application.Interfaces; 10 | using Template.Application.ViewModels; 11 | using Template.Auth.Services; 12 | 13 | namespace Template.Controllers 14 | { 15 | [Route("api/[controller]")] 16 | [ApiController, Authorize] 17 | public class UsersController : ControllerBase 18 | { 19 | 20 | private readonly IUserService userService; 21 | 22 | public UsersController(IUserService userService) 23 | { 24 | this.userService = userService; 25 | } 26 | 27 | [HttpGet] 28 | public IActionResult Get() 29 | { 30 | return Ok(this.userService.Get()); 31 | } 32 | 33 | [HttpPost, AllowAnonymous] 34 | public IActionResult Post(UserViewModel userViewModel) 35 | { 36 | if (!ModelState.IsValid) 37 | return BadRequest(ModelState); 38 | 39 | return Ok(this.userService.Post(userViewModel)); 40 | } 41 | 42 | [HttpGet("{id}")] 43 | public IActionResult GetById(string id) 44 | { 45 | return Ok(this.userService.GetById(id)); 46 | } 47 | 48 | [HttpPut] 49 | public IActionResult Put(UserViewModel userViewModel) 50 | { 51 | return Ok(this.userService.Put(userViewModel)); 52 | } 53 | 54 | [HttpDelete] 55 | public IActionResult Delete() 56 | { 57 | string _userId = TokenService.GetValueFromClaim(HttpContext.User.Identity, ClaimTypes.NameIdentifier); 58 | 59 | return Ok(this.userService.Delete(_userId)); 60 | } 61 | 62 | [HttpPost("authenticate"), AllowAnonymous] 63 | public IActionResult Authenticate(UserAuthenticateRequestViewModel userViewModel) 64 | { 65 | return Ok(this.userService.Authenticate(userViewModel)); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Template.Data/Extensions/ModelBuilderExtension.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using Template.Domain.Entities; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Template.Domain.Models; 8 | 9 | namespace Template.Data.Extensions 10 | { 11 | public static class ModelBuilderExtension 12 | { 13 | 14 | public static ModelBuilder ApplyGlobalConfigurations(this ModelBuilder builder) 15 | { 16 | foreach (IMutableEntityType entityType in builder.Model.GetEntityTypes()) 17 | { 18 | foreach (IMutableProperty property in entityType.GetProperties()) 19 | { 20 | switch (property.Name) 21 | { 22 | case nameof(Entity.Id): 23 | property.IsKey(); 24 | break; 25 | case nameof(Entity.DateUpdated): 26 | property.IsNullable = true; 27 | break; 28 | case nameof(Entity.DateCreated): 29 | property.IsNullable = false; 30 | property.SetDefaultValue(DateTime.Now); 31 | break; 32 | case nameof(Entity.IsDeleted): 33 | property.IsNullable = false; 34 | property.SetDefaultValue(false); 35 | break; 36 | default: 37 | break; 38 | } 39 | } 40 | } 41 | 42 | return builder; 43 | } 44 | 45 | public static ModelBuilder SeedData(this ModelBuilder builder) 46 | { 47 | builder.Entity() 48 | .HasData( 49 | new User { Id = Guid.Parse("c7dce21b-d207-4869-bf5f-08eb138bb919"), Name = "User Default", Email = "userdefault@template.com", DateCreated = new DateTime(2020,2,2), IsDeleted = false, DateUpdated = null } 50 | ); 51 | 52 | 53 | return builder; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200926072248_Password Field.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Template.Data.Migrations 5 | { 6 | public partial class PasswordField : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.AlterColumn( 11 | name: "DateCreated", 12 | table: "Users", 13 | nullable: false, 14 | defaultValue: new DateTime(2020, 9, 26, 8, 22, 47, 961, DateTimeKind.Local).AddTicks(3033), 15 | oldClrType: typeof(DateTime), 16 | oldType: "datetime2", 17 | oldDefaultValue: new DateTime(2020, 6, 27, 18, 52, 38, 325, DateTimeKind.Local).AddTicks(9630)); 18 | 19 | migrationBuilder.AddColumn( 20 | name: "Password", 21 | table: "Users", 22 | nullable: false, 23 | defaultValue: "TesteTemplate"); 24 | 25 | migrationBuilder.UpdateData( 26 | table: "Users", 27 | keyColumn: "Id", 28 | keyValue: new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 29 | column: "DateCreated", 30 | value: new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified)); 31 | } 32 | 33 | protected override void Down(MigrationBuilder migrationBuilder) 34 | { 35 | migrationBuilder.DropColumn( 36 | name: "Password", 37 | table: "Users"); 38 | 39 | migrationBuilder.AlterColumn( 40 | name: "DateCreated", 41 | table: "Users", 42 | type: "datetime2", 43 | nullable: false, 44 | defaultValue: new DateTime(2020, 6, 27, 18, 52, 38, 325, DateTimeKind.Local).AddTicks(9630), 45 | oldClrType: typeof(DateTime), 46 | oldDefaultValue: new DateTime(2020, 9, 26, 8, 22, 47, 961, DateTimeKind.Local).AddTicks(3033)); 47 | 48 | migrationBuilder.UpdateData( 49 | table: "Users", 50 | keyColumn: "Id", 51 | keyValue: new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 52 | column: "DateCreated", 53 | value: new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified)); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627164211_Common Fields.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Template.Data.Context; 9 | 10 | namespace Template.Data.Migrations 11 | { 12 | [DbContext(typeof(TemplateContext))] 13 | [Migration("20200627164211_Common Fields")] 14 | partial class CommonFields 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("Template.Domain.Entities.User", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("uniqueidentifier"); 29 | 30 | b.Property("DateCreated") 31 | .HasColumnType("datetime2"); 32 | 33 | b.Property("DateUpdated") 34 | .HasColumnType("datetime2"); 35 | 36 | b.Property("Email") 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("IsDeleted") 40 | .HasColumnType("bit"); 41 | 42 | b.Property("Name") 43 | .IsRequired() 44 | .HasColumnType("nvarchar(100)") 45 | .HasMaxLength(100); 46 | 47 | b.HasKey("Id"); 48 | 49 | b.ToTable("Users"); 50 | 51 | b.HasData( 52 | new 53 | { 54 | Id = new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 55 | DateCreated = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), 56 | Email = "userdefault@template.com", 57 | IsDeleted = false, 58 | Name = "User Default" 59 | }); 60 | }); 61 | #pragma warning restore 612, 618 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627164403_Updating Default User.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Template.Data.Context; 9 | 10 | namespace Template.Data.Migrations 11 | { 12 | [DbContext(typeof(TemplateContext))] 13 | [Migration("20200627164403_Updating Default User")] 14 | partial class UpdatingDefaultUser 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("Template.Domain.Entities.User", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("uniqueidentifier"); 29 | 30 | b.Property("DateCreated") 31 | .HasColumnType("datetime2"); 32 | 33 | b.Property("DateUpdated") 34 | .HasColumnType("datetime2"); 35 | 36 | b.Property("Email") 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("IsDeleted") 40 | .HasColumnType("bit"); 41 | 42 | b.Property("Name") 43 | .IsRequired() 44 | .HasColumnType("nvarchar(100)") 45 | .HasMaxLength(100); 46 | 47 | b.HasKey("Id"); 48 | 49 | b.ToTable("Users"); 50 | 51 | b.HasData( 52 | new 53 | { 54 | Id = new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 55 | DateCreated = new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), 56 | Email = "userdefault@template.com", 57 | IsDeleted = false, 58 | Name = "User Default" 59 | }); 60 | }); 61 | #pragma warning restore 612, 618 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/users/users.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Welcome ({{userLogged?.user?.name}})

4 | 5 |

Users ({{users?.length}})

6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 |
ActionsIDNameEmail
21 | 22 | 23 | {{user.id}}{{user.name}}{{user.email}}
30 |
31 |
32 |
33 |
34 |
35 | 36 | 37 |
38 |
39 | 40 | 41 |
42 |
43 | 44 | 45 |
46 | 47 |
48 |
49 | 50 |
51 |
52 |
53 | 54 | 55 |
56 |
57 | 58 | 59 |
60 | 61 |
62 |
63 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200627175238_GlobalConfigurations.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Template.Data.Context; 9 | 10 | namespace Template.Data.Migrations 11 | { 12 | [DbContext(typeof(TemplateContext))] 13 | [Migration("20200627175238_GlobalConfigurations")] 14 | partial class GlobalConfigurations 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("Template.Domain.Entities.User", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("uniqueidentifier"); 29 | 30 | b.Property("DateCreated") 31 | .ValueGeneratedOnAdd() 32 | .HasColumnType("datetime2") 33 | .HasDefaultValue(new DateTime(2020, 6, 27, 18, 52, 38, 325, DateTimeKind.Local).AddTicks(9630)); 34 | 35 | b.Property("DateUpdated") 36 | .HasColumnType("datetime2"); 37 | 38 | b.Property("Email") 39 | .HasColumnType("nvarchar(max)"); 40 | 41 | b.Property("IsDeleted") 42 | .ValueGeneratedOnAdd() 43 | .HasColumnType("bit") 44 | .HasDefaultValue(false); 45 | 46 | b.Property("Name") 47 | .IsRequired() 48 | .HasColumnType("nvarchar(100)") 49 | .HasMaxLength(100); 50 | 51 | b.HasKey("Id"); 52 | 53 | b.ToTable("Users"); 54 | 55 | b.HasData( 56 | new 57 | { 58 | Id = new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 59 | DateCreated = new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), 60 | Email = "userdefault@template.com", 61 | IsDeleted = false, 62 | Name = "User Default" 63 | }); 64 | }); 65 | #pragma warning restore 612, 618 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Template-DotNetCore 2 | 3 | ## Aplicação em .Net Core com Angular 4 | 5 | ### Vídeos: 6 | - Criando um projeto .Net Core com Angular no Visual Studio: 7 | * https://www.youtube.com/watch?v=zkbk1pnwz5Q&t=15s 8 | * https://medium.com/@nicolas.rfontes/criando-um-projeto-net-core-com-angular-no-visual-studio-a1ac1bc30f94 9 | 10 | - Publicando um projeto .Net Core no Github pelo Visual Studio: 11 | * https://www.youtube.com/watch?v=Bzz63URwTrw&t=19s 12 | * https://medium.com/@nicolas.rfontes/publicando-um-projeto-net-core-no-github-pelo-visual-studio-f6e91ac9d1e9 13 | 14 | - Criando uma arquitetura de projeto backend em .Net Core (Projetos e Pastas): 15 | * https://www.youtube.com/watch?v=SHyF8Tc-s8Q 16 | * https://medium.com/@nicolas.rfontes/criando-uma-arquitetura-de-projeto-backend-em-net-core-3f9a8a1df6f 17 | 18 | - Instalando e Configurando Entity Framework Core (Code First) em um projeto .Net Core: 19 | * https://www.youtube.com/watch?v=2FGTJX1sWZk 20 | * https://medium.com/@nicolas.rfontes/instalando-e-configurando-entity-framework-core-9980582ce148 21 | 22 | - Configurando Injeção de Dependência em um projeto .Net Core: 23 | * https://www.youtube.com/watch?v=kSAdyvMFL9I 24 | * https://medium.com/@nicolas.rfontes/configurando-inje%C3%A7%C3%A3o-de-depend%C3%AAncia-em-um-projeto-net-core-8b7a1a112c09 25 | 26 | - Criando api Get em .Net Core para retornar valores do banco SQL Server: 27 | * https://www.youtube.com/watch?v=hm4KbhEhdv4 28 | * https://medium.com/@nicolas.rfontes/criando-uma-api-get-em-net-core-comunicando-com-o-banco-de-dados-sql-server-14e37a415ad 29 | 30 | - Criando api Post em .Net Core para retornar valores do banco SQL Server: 31 | * https://www.youtube.com/watch?v=oDIXGnQlbfE 32 | * https://medium.com/@nicolas.rfontes/criando-uma-api-post-em-net-core-para-salvar-e-retornar-valores-do-banco-sql-server-27a1c4743a77 33 | 34 | - Configurando AutoMapper em um projeto .Net Core: 35 | * https://www.youtube.com/watch?v=gJ5xyhMPNWc 36 | * https://medium.com/@nicolas.rfontes/configurando-o-automapper-em-um-aplica%C3%A7%C3%A3o-net-core-2e5f5920640 37 | 38 | - Configurando o Swagger em um projeto .Net Core: 39 | * https://www.youtube.com/watch?v=wYLEMHhICXo 40 | * https://medium.com/@nicolas.rfontes/configurando-o-swagger-em-uma-aplica%C3%A7%C3%A3o-net-core-120776c320ce 41 | 42 | - Criando api GetOne e Put em uma aplicação .Net Core: 43 | * https://www.youtube.com/watch?v=9tO2UaE5YYI 44 | * https://medium.com/@nicolas.rfontes/criando-api-getone-e-put-em-uma-aplica%C3%A7%C3%A3o-net-core-e542c1ae13b0 45 | 46 | - Criando API Delete em uma aplicação .Net Core 47 | * https://www.youtube.com/watch?v=BUTZt669SpQ 48 | * https://medium.com/@nicolas.rfontes/criando-api-delete-em-uma-aplica%C3%A7%C3%A3o-net-core-5f1448d07bd5 49 | 50 | - Autenticando um usuário com JWT em uma aplicação .Net Core 51 | 52 | - Definindo APIs publicas e privadas em uma aplicação .Net Core 53 | -------------------------------------------------------------------------------- /Template.Data/Migrations/TemplateContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using Template.Data.Context; 8 | 9 | namespace Template.Data.Migrations 10 | { 11 | [DbContext(typeof(TemplateContext))] 12 | partial class TemplateContextModelSnapshot : ModelSnapshot 13 | { 14 | protected override void BuildModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("ProductVersion", "3.1.5") 19 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 21 | 22 | modelBuilder.Entity("Template.Domain.Entities.User", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasColumnType("uniqueidentifier"); 27 | 28 | b.Property("DateCreated") 29 | .ValueGeneratedOnAdd() 30 | .HasColumnType("datetime2") 31 | .HasDefaultValue(new DateTime(2020, 9, 26, 8, 22, 47, 961, DateTimeKind.Local).AddTicks(3033)); 32 | 33 | b.Property("DateUpdated") 34 | .HasColumnType("datetime2"); 35 | 36 | b.Property("Email") 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("IsDeleted") 40 | .ValueGeneratedOnAdd() 41 | .HasColumnType("bit") 42 | .HasDefaultValue(false); 43 | 44 | b.Property("Name") 45 | .IsRequired() 46 | .HasColumnType("nvarchar(100)") 47 | .HasMaxLength(100); 48 | 49 | b.Property("Password") 50 | .IsRequired() 51 | .ValueGeneratedOnAdd() 52 | .HasColumnType("nvarchar(max)") 53 | .HasDefaultValue("TesteTemplate"); 54 | 55 | b.HasKey("Id"); 56 | 57 | b.ToTable("Users"); 58 | 59 | b.HasData( 60 | new 61 | { 62 | Id = new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 63 | DateCreated = new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), 64 | Email = "userdefault@template.com", 65 | IsDeleted = false, 66 | Name = "User Default" 67 | }); 68 | }); 69 | #pragma warning restore 612, 618 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Template/ClientApp/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js/dist/zone'; // Included with Angular CLI. 59 | 60 | 61 | /*************************************************************************************************** 62 | * APPLICATION IMPORTS 63 | */ 64 | -------------------------------------------------------------------------------- /Template/ClientApp/src/app/users/users.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { UserDataService } from '../_data-services/user.data-service'; 3 | 4 | @Component({ 5 | selector: 'app-users', 6 | templateUrl: './users.component.html', 7 | styleUrls: ['./users.component.css'] 8 | }) 9 | export class UsersComponent implements OnInit { 10 | 11 | users: any[] = []; 12 | user: any = {}; 13 | userLogin: any = {}; 14 | userLogged: any = {}; 15 | showList: boolean = true; 16 | isAuthenticated: boolean = false; 17 | 18 | constructor(private userDataService: UserDataService) { } 19 | 20 | ngOnInit() { 21 | 22 | } 23 | 24 | get() { 25 | this.userDataService.get().subscribe((data:any[]) => { 26 | this.users = data; 27 | this.showList = true; 28 | }, error => { 29 | console.log(error); 30 | alert('erro interno do sistema'); 31 | }) 32 | } 33 | 34 | save() { 35 | if (this.user.id) { 36 | this.put(); 37 | } else { 38 | this.post(); 39 | } 40 | } 41 | 42 | openDetails(user) { 43 | this.showList = false; 44 | this.user = user; 45 | } 46 | 47 | post() { 48 | this.userDataService.post(this.user).subscribe(data => { 49 | if (data) { 50 | alert('Usuário cadastrado com sucesso'); 51 | this.get(); 52 | this.user = {}; 53 | } else { 54 | alert('Erro ao cadastrar usuário'); 55 | } 56 | }, error => { 57 | console.log(error); 58 | alert('erro interno do sistema'); 59 | }) 60 | } 61 | 62 | put() { 63 | this.userDataService.put(this.user).subscribe(data => { 64 | if (data) { 65 | alert('Usuário atualizado com sucesso'); 66 | this.get(); 67 | this.user = {}; 68 | } else { 69 | alert('Erro ao atualizar usuário'); 70 | } 71 | }, error => { 72 | console.log(error); 73 | alert('erro interno do sistema'); 74 | }) 75 | } 76 | 77 | delete() { 78 | this.userDataService.delete().subscribe(data => { 79 | if (data) { 80 | alert('Usuário excluído com sucesso'); 81 | this.get(); 82 | this.user = {}; 83 | } else { 84 | alert('Erro ao excluir usuário'); 85 | } 86 | }, error => { 87 | console.log(error); 88 | alert('erro interno do sistema'); 89 | }) 90 | } 91 | 92 | authenticate() { 93 | this.userDataService.authenticate(this.userLogin).subscribe((data:any) => { 94 | if (data.user) { 95 | localStorage.setItem('user_logged', JSON.stringify(data)); 96 | this.get(); 97 | this.getUserData(); 98 | } else { 99 | alert('User invalid.'); 100 | } 101 | }, error => { 102 | console.log(error); 103 | alert('User invalid'); 104 | }) 105 | } 106 | 107 | getUserData() { 108 | this.userLogged = JSON.parse(localStorage.getItem('user_logged')); 109 | this.isAuthenticated = this.userLogged != null; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /Template.Data/Migrations/20200926072248_Password Field.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Template.Data.Context; 9 | 10 | namespace Template.Data.Migrations 11 | { 12 | [DbContext(typeof(TemplateContext))] 13 | [Migration("20200926072248_Password Field")] 14 | partial class PasswordField 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("Template.Domain.Entities.User", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("uniqueidentifier"); 29 | 30 | b.Property("DateCreated") 31 | .ValueGeneratedOnAdd() 32 | .HasColumnType("datetime2") 33 | .HasDefaultValue(new DateTime(2020, 9, 26, 8, 22, 47, 961, DateTimeKind.Local).AddTicks(3033)); 34 | 35 | b.Property("DateUpdated") 36 | .HasColumnType("datetime2"); 37 | 38 | b.Property("Email") 39 | .HasColumnType("nvarchar(max)"); 40 | 41 | b.Property("IsDeleted") 42 | .ValueGeneratedOnAdd() 43 | .HasColumnType("bit") 44 | .HasDefaultValue(false); 45 | 46 | b.Property("Name") 47 | .IsRequired() 48 | .HasColumnType("nvarchar(100)") 49 | .HasMaxLength(100); 50 | 51 | b.Property("Password") 52 | .IsRequired() 53 | .ValueGeneratedOnAdd() 54 | .HasColumnType("nvarchar(max)") 55 | .HasDefaultValue("TesteTemplate"); 56 | 57 | b.HasKey("Id"); 58 | 59 | b.ToTable("Users"); 60 | 61 | b.HasData( 62 | new 63 | { 64 | Id = new Guid("c7dce21b-d207-4869-bf5f-08eb138bb919"), 65 | DateCreated = new DateTime(2020, 2, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), 66 | Email = "userdefault@template.com", 67 | IsDeleted = false, 68 | Name = "User Default" 69 | }); 70 | }); 71 | #pragma warning restore 612, 618 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Template/ClientApp/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs/Rx" 22 | ], 23 | "import-spacing": true, 24 | "indent": [ 25 | true, 26 | "spaces" 27 | ], 28 | "interface-over-type-literal": true, 29 | "label-position": true, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-arg": true, 47 | "no-bitwise": true, 48 | "no-console": [ 49 | true, 50 | "debug", 51 | "info", 52 | "time", 53 | "timeEnd", 54 | "trace" 55 | ], 56 | "no-construct": true, 57 | "no-debugger": true, 58 | "no-duplicate-super": true, 59 | "no-empty": false, 60 | "no-empty-interface": true, 61 | "no-eval": true, 62 | "no-inferrable-types": [ 63 | true, 64 | "ignore-params" 65 | ], 66 | "no-misused-new": true, 67 | "no-non-null-assertion": true, 68 | "no-shadowed-variable": true, 69 | "no-string-literal": false, 70 | "no-string-throw": true, 71 | "no-switch-case-fall-through": true, 72 | "no-trailing-whitespace": true, 73 | "no-unnecessary-initializer": true, 74 | "no-unused-expression": true, 75 | "no-use-before-declare": true, 76 | "no-var-keyword": true, 77 | "object-literal-sort-keys": false, 78 | "one-line": [ 79 | true, 80 | "check-open-brace", 81 | "check-catch", 82 | "check-else", 83 | "check-whitespace" 84 | ], 85 | "prefer-const": true, 86 | "quotemark": [ 87 | true, 88 | "single" 89 | ], 90 | "radix": true, 91 | "semicolon": [ 92 | true, 93 | "always" 94 | ], 95 | "triple-equals": [ 96 | true, 97 | "allow-null-check" 98 | ], 99 | "typedef-whitespace": [ 100 | true, 101 | { 102 | "call-signature": "nospace", 103 | "index-signature": "nospace", 104 | "parameter": "nospace", 105 | "property-declaration": "nospace", 106 | "variable-declaration": "nospace" 107 | } 108 | ], 109 | "unified-signatures": true, 110 | "variable-name": false, 111 | "whitespace": [ 112 | true, 113 | "check-branch", 114 | "check-decl", 115 | "check-operator", 116 | "check-separator", 117 | "check-type" 118 | ], 119 | "no-output-on-prefix": true, 120 | "no-inputs-metadata-property": true, 121 | "no-outputs-metadata-property": true, 122 | "no-host-metadata-property": true, 123 | "no-input-rename": true, 124 | "no-output-rename": true, 125 | "use-lifecycle-interface": true, 126 | "use-pipe-transform-interface": true, 127 | "component-class-suffix": true, 128 | "directive-class-suffix": true 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /Template/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.HttpsPolicy; 4 | using Microsoft.AspNetCore.SpaServices.AngularCli; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using Template.Data.Context; 9 | using Microsoft.EntityFrameworkCore; 10 | using Template.IoC; 11 | using Template.Application.AutoMapper; 12 | using AutoMapper; 13 | using Template.Swagger; 14 | using System.Text; 15 | using Template.Auth.Models; 16 | using Microsoft.AspNetCore.Authentication.JwtBearer; 17 | using Microsoft.IdentityModel.Tokens; 18 | 19 | namespace Template 20 | { 21 | public class Startup 22 | { 23 | public Startup(IConfiguration configuration) 24 | { 25 | Configuration = configuration; 26 | } 27 | 28 | public IConfiguration Configuration { get; } 29 | 30 | // This method gets called by the runtime. Use this method to add services to the container. 31 | public void ConfigureServices(IServiceCollection services) 32 | { 33 | services.AddControllersWithViews(); 34 | 35 | services.AddDbContext(opt => opt.UseSqlServer(Configuration.GetConnectionString("TemplateDB")).EnableSensitiveDataLogging()); 36 | NativeInjector.RegisterServices(services); 37 | 38 | services.AddAutoMapper(typeof(AutoMapperSetup)); 39 | services.AddSwaggerConfiguration(); 40 | 41 | var key = Encoding.ASCII.GetBytes(Settings.Secret); 42 | services.AddAuthentication(x => 43 | { 44 | x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 45 | x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 46 | }).AddJwtBearer(x => 47 | { 48 | x.RequireHttpsMetadata = false; 49 | x.SaveToken = true; 50 | x.TokenValidationParameters = new TokenValidationParameters 51 | { 52 | ValidateIssuerSigningKey = true, 53 | IssuerSigningKey = new SymmetricSecurityKey(key), 54 | ValidateIssuer = false, 55 | ValidateAudience = false 56 | }; 57 | }); 58 | 59 | 60 | // In production, the Angular files will be served from this directory 61 | services.AddSpaStaticFiles(configuration => 62 | { 63 | configuration.RootPath = "ClientApp/dist"; 64 | }); 65 | } 66 | 67 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 68 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 69 | { 70 | if (env.IsDevelopment()) 71 | { 72 | app.UseDeveloperExceptionPage(); 73 | } 74 | else 75 | { 76 | app.UseExceptionHandler("/Error"); 77 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 78 | app.UseHsts(); 79 | } 80 | 81 | app.UseSwaggerConfiguration(); 82 | 83 | app.UseHttpsRedirection(); 84 | app.UseStaticFiles(); 85 | if (!env.IsDevelopment()) 86 | { 87 | app.UseSpaStaticFiles(); 88 | } 89 | 90 | app.UseRouting(); 91 | 92 | app.UseAuthentication(); 93 | app.UseAuthorization(); 94 | 95 | app.UseEndpoints(endpoints => 96 | { 97 | endpoints.MapControllerRoute( 98 | name: "default", 99 | pattern: "{controller}/{action=Index}/{id?}"); 100 | }); 101 | 102 | app.UseSpa(spa => 103 | { 104 | // To learn more about options for serving an Angular SPA from ASP.NET Core, 105 | // see https://go.microsoft.com/fwlink/?linkid=864501 106 | 107 | spa.Options.SourcePath = "ClientApp"; 108 | 109 | if (env.IsDevelopment()) 110 | { 111 | spa.UseAngularCliServer(npmScript: "start"); 112 | } 113 | }); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Template.Application.Tests/Services/UserServiceTests.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Moq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using Template.Application.AutoMapper; 7 | using Template.Application.Services; 8 | using Template.Application.ViewModels; 9 | using Template.Domain.Entities; 10 | using Template.Domain.Interfaces; 11 | using Xunit; 12 | 13 | namespace Template.Application.Tests.Services 14 | { 15 | public class UserServiceTests 16 | { 17 | private UserService userService; 18 | 19 | public UserServiceTests() 20 | { 21 | userService = new UserService(new Mock().Object, new Mock().Object); 22 | } 23 | 24 | #region ValidatingSendingID 25 | 26 | [Fact] 27 | public void Post_SendingValidId() 28 | { 29 | var exception = Assert.Throws(() => userService.Post(new UserViewModel { Id = Guid.NewGuid() })); 30 | Assert.Equal("UserID must be empty", exception.Message); 31 | } 32 | 33 | [Fact] 34 | public void GetById_SendingEmptyGuid() 35 | { 36 | var exception = Assert.Throws(() => userService.GetById("")); 37 | Assert.Equal("UserID is not valid", exception.Message); 38 | } 39 | 40 | [Fact] 41 | public void Put_SendingEmptyGuid() 42 | { 43 | var exception = Assert.Throws(() => userService.Put(new UserViewModel())); 44 | Assert.Equal("ID is invalid", exception.Message); 45 | } 46 | 47 | [Fact] 48 | public void Delete_SendingEmptyGuid() 49 | { 50 | var exception = Assert.Throws(() => userService.Delete("")); 51 | Assert.Equal("UserID is not valid", exception.Message); 52 | } 53 | 54 | [Fact] 55 | public void Authenticate_SendingEmptyValues() 56 | { 57 | var exception = Assert.Throws(() => userService.Authenticate(new UserAuthenticateRequestViewModel())); 58 | Assert.Equal("Email/Password are required.", exception.Message); 59 | } 60 | 61 | #endregion 62 | 63 | #region ValidatingCorrectObject 64 | 65 | [Fact] 66 | public void Post_SendingValidObject() 67 | { 68 | var result = userService.Post(new UserViewModel { Name = "Nicolas Fontes", Email = "nicolas.rfontes@gmail.com" }); 69 | Assert.True(result); 70 | } 71 | 72 | [Fact] 73 | public void Get_ValidatingObject() 74 | { 75 | //Criando a lista com um objeto para que seja retornado pelo repository 76 | List _users = new List(); 77 | _users.Add(new User { Id = Guid.NewGuid(), Name = "Nicolas Fontes", Email = "nicolas.rfontes@gmail.com", DateCreated = DateTime.Now }); 78 | //Criando um objeto mock do UserRepository e configurando para retornar a lista criada anteriormente se chamar o método GetAll() 79 | var _userRepository = new Mock(); 80 | _userRepository.Setup(x => x.GetAll()).Returns(_users); 81 | //Criando um objeto mock do AutoMapper para que possamos converter o retorno para o tipo List() 82 | var _autoMapperProfile = new AutoMapperSetup(); 83 | var _configuration = new MapperConfiguration(x => x.AddProfile(_autoMapperProfile)); 84 | IMapper _mapper = new Mapper(_configuration); 85 | //Istanciando nossa classe de serviço novamente com os novos objetos mocks que criamos 86 | userService = new UserService(_userRepository.Object, _mapper); 87 | //Obtendo os valores do método Get para validar se vai retornar o objeto criado acima. 88 | var result = userService.Get(); 89 | //Validando se o retorno contém uma lista com objetos. 90 | Assert.True(result.Count > 0); 91 | } 92 | 93 | #endregion 94 | 95 | #region ValidatingRequiredFields 96 | 97 | [Fact] 98 | public void Post_SendingInvalidObject() 99 | { 100 | var exception = Assert.Throws(() => userService.Post(new UserViewModel { Name = "Nicolas Fontes" })); 101 | Assert.Equal("The Email field is required.", exception.Message); 102 | } 103 | 104 | #endregion 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Template/Template.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | true 6 | Latest 7 | false 8 | ClientApp\ 9 | $(DefaultItemExcludes);$(SpaRoot)node_modules\** 10 | 11 | 12 | false 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | all 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | 24 | 25 | 26 | all 27 | runtime; build; native; contentfiles; analyzers; buildtransitive 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | %(DistFiles.Identity) 79 | PreserveNewest 80 | true 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | bin/ 23 | Bin/ 24 | obj/ 25 | Obj/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | *.lock 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | 35 | # NUNIT 36 | *.VisualState.xml 37 | TestResult.xml 38 | 39 | # Build Results of an ATL Project 40 | [Dd]ebugPS/ 41 | [Rr]eleasePS/ 42 | dlldata.c 43 | 44 | *_i.c 45 | *_p.c 46 | *_i.h 47 | *.ilk 48 | *.meta 49 | *.obj 50 | *.pch 51 | *.pdb 52 | *.pgc 53 | *.pgd 54 | *.rsp 55 | *.sbr 56 | *.tlb 57 | *.tli 58 | *.tlh 59 | *.tmp 60 | *.tmp_proj 61 | *.log 62 | *.vspscc 63 | *.vssscc 64 | .builds 65 | *.pidb 66 | *.svclog 67 | *.scc 68 | 69 | # Chutzpah Test files 70 | _Chutzpah* 71 | 72 | # Visual C++ cache files 73 | ipch/ 74 | *.aps 75 | *.ncb 76 | *.opendb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | *.sap 86 | 87 | # TFS 2012 Local Workspace 88 | $tf/ 89 | 90 | # Guidance Automation Toolkit 91 | *.gpState 92 | 93 | # ReSharper is a .NET coding add-in 94 | _ReSharper*/ 95 | *.[Rr]e[Ss]harper 96 | *.DotSettings.user 97 | 98 | # JustCode is a .NET coding add-in 99 | .JustCode 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | _NCrunch_* 109 | .*crunch*.local.xml 110 | nCrunchTemp_* 111 | 112 | # MightyMoose 113 | *.mm.* 114 | AutoTest.Net/ 115 | 116 | # Web workbench (sass) 117 | .sass-cache/ 118 | 119 | # Installshield output folder 120 | [Ee]xpress/ 121 | 122 | # DocProject is a documentation generator add-in 123 | DocProject/buildhelp/ 124 | DocProject/Help/*.HxT 125 | DocProject/Help/*.HxC 126 | DocProject/Help/*.hhc 127 | DocProject/Help/*.hhk 128 | DocProject/Help/*.hhp 129 | DocProject/Help/Html2 130 | DocProject/Help/html 131 | 132 | # Click-Once directory 133 | publish/ 134 | 135 | # Publish Web Output 136 | *.[Pp]ublish.xml 137 | *.azurePubxml 138 | # TODO: Comment the next line if you want to checkin your web deploy settings 139 | # but database connection strings (with potential passwords) will be unencrypted 140 | *.pubxml 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Microsoft Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Microsoft Azure Emulator 157 | ecf/ 158 | rcf/ 159 | 160 | # Microsoft Azure ApplicationInsights config file 161 | ApplicationInsights.config 162 | 163 | # Windows Store app package directory 164 | AppPackages/ 165 | BundleArtifacts/ 166 | 167 | # Visual Studio cache files 168 | # files ending in .cache can be ignored 169 | *.[Cc]ache 170 | # but keep track of directories ending in .cache 171 | !*.[Cc]ache/ 172 | 173 | # Others 174 | ClientBin/ 175 | ~$* 176 | *~ 177 | *.dbmdl 178 | *.dbproj.schemaview 179 | *.pfx 180 | *.publishsettings 181 | orleans.codegen.cs 182 | 183 | /node_modules 184 | 185 | # RIA/Silverlight projects 186 | Generated_Code/ 187 | 188 | # Backup & report files from converting an old project file 189 | # to a newer Visual Studio version. Backup files are not needed, 190 | # because we have git ;-) 191 | _UpgradeReport_Files/ 192 | Backup*/ 193 | UpgradeLog*.XML 194 | UpgradeLog*.htm 195 | 196 | # SQL Server files 197 | *.mdf 198 | *.ldf 199 | 200 | # Business Intelligence projects 201 | *.rdl.data 202 | *.bim.layout 203 | *.bim_*.settings 204 | 205 | # Microsoft Fakes 206 | FakesAssemblies/ 207 | 208 | # GhostDoc plugin setting file 209 | *.GhostDoc.xml 210 | 211 | # Node.js Tools for Visual Studio 212 | .ntvs_analysis.dat 213 | 214 | # Visual Studio 6 build log 215 | *.plg 216 | 217 | # Visual Studio 6 workspace options file 218 | *.opt 219 | 220 | # Visual Studio LightSwitch build output 221 | **/*.HTMLClient/GeneratedArtifacts 222 | **/*.DesktopClient/GeneratedArtifacts 223 | **/*.DesktopClient/ModelManifest.xml 224 | **/*.Server/GeneratedArtifacts 225 | **/*.Server/ModelManifest.xml 226 | _Pvt_Extensions 227 | 228 | # Paket dependency manager 229 | .paket/paket.exe 230 | 231 | # FAKE - F# Make 232 | .fake/ 233 | -------------------------------------------------------------------------------- /Template.Application/Services/UserService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | using Template.Application.Interfaces; 8 | using Template.Application.ViewModels; 9 | using Template.Auth.Services; 10 | using Template.Domain.Entities; 11 | using Template.Domain.Interfaces; 12 | using ValidationContext = System.ComponentModel.DataAnnotations.ValidationContext; 13 | 14 | namespace Template.Application.Services 15 | { 16 | public class UserService : IUserService 17 | { 18 | 19 | private readonly IUserRepository userRepository; 20 | private readonly IMapper mapper; 21 | 22 | public UserService(IUserRepository userRepository, IMapper mapper) 23 | { 24 | this.userRepository = userRepository; 25 | this.mapper = mapper; 26 | } 27 | 28 | public List Get() 29 | { 30 | IEnumerable _users = this.userRepository.GetAll(); 31 | 32 | List _userViewModels = mapper.Map>(_users); 33 | 34 | return _userViewModels; 35 | } 36 | 37 | public bool Post(UserViewModel userViewModel) 38 | { 39 | if (userViewModel.Id != Guid.Empty) 40 | throw new Exception("UserID must be empty"); 41 | 42 | Validator.ValidateObject(userViewModel, new ValidationContext(userViewModel), true); 43 | 44 | User _user = mapper.Map(userViewModel); 45 | _user.Password = EncryptPassword(_user.Password); 46 | 47 | this.userRepository.Create(_user); 48 | 49 | return true; 50 | } 51 | 52 | public UserViewModel GetById(string id) 53 | { 54 | if (!Guid.TryParse(id, out Guid userId)) 55 | throw new Exception("UserID is not valid"); 56 | 57 | User _user = this.userRepository.Find(x => x.Id == userId && !x.IsDeleted); 58 | if (_user == null) 59 | throw new Exception("User not found"); 60 | 61 | return mapper.Map(_user); 62 | } 63 | 64 | public bool Put(UserViewModel userViewModel) 65 | { 66 | if (userViewModel.Id == Guid.Empty) 67 | throw new Exception("ID is invalid"); 68 | 69 | User _user = this.userRepository.Find(x => x.Id == userViewModel.Id && !x.IsDeleted); 70 | if (_user == null) 71 | throw new Exception("User not found"); 72 | 73 | _user = mapper.Map(userViewModel); 74 | _user.Password = EncryptPassword(_user.Password); 75 | 76 | this.userRepository.Update(_user); 77 | 78 | return true; 79 | } 80 | 81 | public bool Delete(string id) 82 | { 83 | if (!Guid.TryParse(id, out Guid userId)) 84 | throw new Exception("UserID is not valid"); 85 | 86 | User _user = this.userRepository.Find(x => x.Id == userId && !x.IsDeleted); 87 | if (_user == null) 88 | throw new Exception("User not found"); 89 | 90 | return this.userRepository.Delete(_user); 91 | } 92 | 93 | public UserAuthenticateResponseViewModel Authenticate(UserAuthenticateRequestViewModel user) 94 | { 95 | if (string.IsNullOrEmpty(user.Email) || string.IsNullOrEmpty(user.Password)) 96 | throw new Exception("Email/Password are required."); 97 | 98 | user.Password = EncryptPassword(user.Password); 99 | 100 | User _user = this.userRepository.Find(x => !x.IsDeleted && x.Email.ToLower() == user.Email.ToLower() 101 | && x.Password.ToLower() == user.Password.ToLower()); 102 | if (_user == null) 103 | throw new Exception("User not found"); 104 | 105 | return new UserAuthenticateResponseViewModel(mapper.Map(_user), TokenService.GenerateToken(_user)); 106 | } 107 | 108 | private string EncryptPassword(string password) 109 | { 110 | HashAlgorithm sha = new SHA1CryptoServiceProvider(); 111 | 112 | byte[] encryptedPassword = sha.ComputeHash(Encoding.UTF8.GetBytes(password)); 113 | 114 | StringBuilder stringBuilder = new StringBuilder(); 115 | foreach (var caracter in encryptedPassword) 116 | { 117 | stringBuilder.Append(caracter.ToString("X2")); 118 | } 119 | 120 | return stringBuilder.ToString(); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Template/ClientApp/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "Template": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "prefix": "app", 11 | "schematics": {}, 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:browser", 15 | "options": { 16 | "progress": false, 17 | "extractCss": true, 18 | "outputPath": "dist", 19 | "index": "src/index.html", 20 | "main": "src/main.ts", 21 | "polyfills": "src/polyfills.ts", 22 | "tsConfig": "src/tsconfig.app.json", 23 | "assets": ["src/assets"], 24 | "styles": [ 25 | "node_modules/bootstrap/dist/css/bootstrap.min.css", 26 | "src/styles.css" 27 | ], 28 | "scripts": [] 29 | }, 30 | "configurations": { 31 | "production": { 32 | "fileReplacements": [ 33 | { 34 | "replace": "src/environments/environment.ts", 35 | "with": "src/environments/environment.prod.ts" 36 | } 37 | ], 38 | "optimization": true, 39 | "outputHashing": "all", 40 | "sourceMap": false, 41 | "extractCss": true, 42 | "namedChunks": false, 43 | "aot": true, 44 | "extractLicenses": true, 45 | "vendorChunk": false, 46 | "buildOptimizer": true 47 | } 48 | } 49 | }, 50 | "serve": { 51 | "builder": "@angular-devkit/build-angular:dev-server", 52 | "options": { 53 | "browserTarget": "Template:build" 54 | }, 55 | "configurations": { 56 | "production": { 57 | "browserTarget": "Template:build:production" 58 | } 59 | } 60 | }, 61 | "extract-i18n": { 62 | "builder": "@angular-devkit/build-angular:extract-i18n", 63 | "options": { 64 | "browserTarget": "Template:build" 65 | } 66 | }, 67 | "test": { 68 | "builder": "@angular-devkit/build-angular:karma", 69 | "options": { 70 | "main": "src/test.ts", 71 | "polyfills": "src/polyfills.ts", 72 | "tsConfig": "src/tsconfig.spec.json", 73 | "karmaConfig": "src/karma.conf.js", 74 | "styles": ["src/styles.css"], 75 | "scripts": [], 76 | "assets": ["src/assets"] 77 | } 78 | }, 79 | "lint": { 80 | "builder": "@angular-devkit/build-angular:tslint", 81 | "options": { 82 | "tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json"], 83 | "exclude": ["**/node_modules/**"] 84 | } 85 | }, 86 | "server": { 87 | "builder": "@angular-devkit/build-angular:server", 88 | "options": { 89 | "outputPath": "dist-server", 90 | "main": "src/main.ts", 91 | "tsConfig": "src/tsconfig.server.json" 92 | }, 93 | "configurations": { 94 | "dev": { 95 | "optimization": true, 96 | "outputHashing": "all", 97 | "sourceMap": false, 98 | "namedChunks": false, 99 | "extractLicenses": true, 100 | "vendorChunk": true 101 | }, 102 | "production": { 103 | "optimization": true, 104 | "outputHashing": "all", 105 | "sourceMap": false, 106 | "namedChunks": false, 107 | "extractLicenses": true, 108 | "vendorChunk": false 109 | } 110 | } 111 | } 112 | } 113 | }, 114 | "Template-e2e": { 115 | "root": "e2e/", 116 | "projectType": "application", 117 | "architect": { 118 | "e2e": { 119 | "builder": "@angular-devkit/build-angular:protractor", 120 | "options": { 121 | "protractorConfig": "e2e/protractor.conf.js", 122 | "devServerTarget": "Template:serve" 123 | } 124 | }, 125 | "lint": { 126 | "builder": "@angular-devkit/build-angular:tslint", 127 | "options": { 128 | "tsConfig": "e2e/tsconfig.e2e.json", 129 | "exclude": ["**/node_modules/**"] 130 | } 131 | } 132 | } 133 | } 134 | }, 135 | "defaultProject": "Template" 136 | } 137 | -------------------------------------------------------------------------------- /Template.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template", "Template\Template.csproj", "{6320DFD8-E27B-4E4B-912F-BFD2951ECD83}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1-Web", "1-Web", "{5FDDA9FF-71E5-4C2C-9DAB-8EB130EE9410}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2-Application", "2-Application", "{5ADA0AA9-2348-4872-9BE6-05B5935E77ED}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3-Domain", "3-Domain", "{CA5C55F7-FBA6-42FC-B21D-9175306A4897}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4-Infra", "4-Infra", "{32B5710B-7A1E-4490-BF06-E9940194DAD1}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.Application", "Template.Application\Template.Application.csproj", "{EC79EA08-438C-4ED8-BD16-9C1975A9756F}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.Domain", "Template.Domain\Template.Domain.csproj", "{B5A019DD-7D6D-4EBC-BE6F-D8317F0059CE}" 19 | EndProject 20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4.1-Data", "4.1-Data", "{CA6EFB8A-8096-44F6-92C4-C1D3D358B126}" 21 | EndProject 22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4.2-CrossCutting", "4.2-CrossCutting", "{D1622043-B330-4635-A337-284F24CD86C6}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.Data", "Template.Data\Template.Data.csproj", "{6E215AC8-4ADD-4327-8E09-496D86A7866E}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.IoC", "Template.IoC\Template.IoC.csproj", "{EBB690B0-6FC8-49FE-BCF9-E649B086718B}" 27 | EndProject 28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.Swagger", "Template.Swagger\Template.Swagger.csproj", "{43BD5FC5-686A-47C3-8B0D-C479ABD05F16}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.Auth", "Template.Auth\Template.Auth.csproj", "{1A3A29A3-99CC-4EAF-B947-55DCAC33767B}" 31 | EndProject 32 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0-Tests", "0-Tests", "{971A04D8-EB17-42ED-971C-F52C8ED4AB8A}" 33 | EndProject 34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Template.Application.Tests", "Template.Application.Tests\Template.Application.Tests.csproj", "{352A6888-B09B-4248-83E0-2C00A32675D8}" 35 | EndProject 36 | Global 37 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 38 | Debug|Any CPU = Debug|Any CPU 39 | Release|Any CPU = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 42 | {6320DFD8-E27B-4E4B-912F-BFD2951ECD83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {6320DFD8-E27B-4E4B-912F-BFD2951ECD83}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {6320DFD8-E27B-4E4B-912F-BFD2951ECD83}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {6320DFD8-E27B-4E4B-912F-BFD2951ECD83}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {EC79EA08-438C-4ED8-BD16-9C1975A9756F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {EC79EA08-438C-4ED8-BD16-9C1975A9756F}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {EC79EA08-438C-4ED8-BD16-9C1975A9756F}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {EC79EA08-438C-4ED8-BD16-9C1975A9756F}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {B5A019DD-7D6D-4EBC-BE6F-D8317F0059CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {B5A019DD-7D6D-4EBC-BE6F-D8317F0059CE}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {B5A019DD-7D6D-4EBC-BE6F-D8317F0059CE}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {B5A019DD-7D6D-4EBC-BE6F-D8317F0059CE}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {6E215AC8-4ADD-4327-8E09-496D86A7866E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {6E215AC8-4ADD-4327-8E09-496D86A7866E}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {6E215AC8-4ADD-4327-8E09-496D86A7866E}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {6E215AC8-4ADD-4327-8E09-496D86A7866E}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {EBB690B0-6FC8-49FE-BCF9-E649B086718B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {EBB690B0-6FC8-49FE-BCF9-E649B086718B}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {EBB690B0-6FC8-49FE-BCF9-E649B086718B}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {EBB690B0-6FC8-49FE-BCF9-E649B086718B}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {43BD5FC5-686A-47C3-8B0D-C479ABD05F16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {43BD5FC5-686A-47C3-8B0D-C479ABD05F16}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {43BD5FC5-686A-47C3-8B0D-C479ABD05F16}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {43BD5FC5-686A-47C3-8B0D-C479ABD05F16}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {1A3A29A3-99CC-4EAF-B947-55DCAC33767B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {1A3A29A3-99CC-4EAF-B947-55DCAC33767B}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {1A3A29A3-99CC-4EAF-B947-55DCAC33767B}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {1A3A29A3-99CC-4EAF-B947-55DCAC33767B}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {352A6888-B09B-4248-83E0-2C00A32675D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {352A6888-B09B-4248-83E0-2C00A32675D8}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {352A6888-B09B-4248-83E0-2C00A32675D8}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {352A6888-B09B-4248-83E0-2C00A32675D8}.Release|Any CPU.Build.0 = Release|Any CPU 74 | EndGlobalSection 75 | GlobalSection(SolutionProperties) = preSolution 76 | HideSolutionNode = FALSE 77 | EndGlobalSection 78 | GlobalSection(NestedProjects) = preSolution 79 | {6320DFD8-E27B-4E4B-912F-BFD2951ECD83} = {5FDDA9FF-71E5-4C2C-9DAB-8EB130EE9410} 80 | {EC79EA08-438C-4ED8-BD16-9C1975A9756F} = {5ADA0AA9-2348-4872-9BE6-05B5935E77ED} 81 | {B5A019DD-7D6D-4EBC-BE6F-D8317F0059CE} = {CA5C55F7-FBA6-42FC-B21D-9175306A4897} 82 | {CA6EFB8A-8096-44F6-92C4-C1D3D358B126} = {32B5710B-7A1E-4490-BF06-E9940194DAD1} 83 | {D1622043-B330-4635-A337-284F24CD86C6} = {32B5710B-7A1E-4490-BF06-E9940194DAD1} 84 | {6E215AC8-4ADD-4327-8E09-496D86A7866E} = {CA6EFB8A-8096-44F6-92C4-C1D3D358B126} 85 | {EBB690B0-6FC8-49FE-BCF9-E649B086718B} = {D1622043-B330-4635-A337-284F24CD86C6} 86 | {43BD5FC5-686A-47C3-8B0D-C479ABD05F16} = {D1622043-B330-4635-A337-284F24CD86C6} 87 | {1A3A29A3-99CC-4EAF-B947-55DCAC33767B} = {D1622043-B330-4635-A337-284F24CD86C6} 88 | {352A6888-B09B-4248-83E0-2C00A32675D8} = {971A04D8-EB17-42ED-971C-F52C8ED4AB8A} 89 | EndGlobalSection 90 | GlobalSection(ExtensibilityGlobals) = postSolution 91 | SolutionGuid = {F53D0144-A66D-447B-87B9-5ACE17D16941} 92 | EndGlobalSection 93 | EndGlobal 94 | -------------------------------------------------------------------------------- /Template.Data/Repositories/Repository.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.ChangeTracking; 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 | using Template.Data.Context; 10 | using Template.Domain.Interfaces; 11 | using Template.Domain.Models; 12 | 13 | namespace Template.Data.Repositories 14 | { 15 | public class Repository : IRepository where TEntity : class 16 | { 17 | #region 'Properties' 18 | 19 | protected readonly TemplateContext _context; 20 | 21 | protected DbSet DbSet 22 | { 23 | get 24 | { 25 | return _context.Set(); 26 | } 27 | } 28 | 29 | #endregion 30 | 31 | public Repository(TemplateContext context) 32 | { 33 | _context = context; 34 | } 35 | 36 | #region 'Methods: Create/Update/Remove/Save' 37 | 38 | public TEntity Create(TEntity model) 39 | { 40 | try 41 | { 42 | DbSet.Add(model); 43 | Save(); 44 | return model; 45 | } 46 | catch (Exception) 47 | { 48 | 49 | throw; 50 | } 51 | } 52 | 53 | public List Create(List models) 54 | { 55 | try 56 | { 57 | DbSet.AddRange(models); 58 | Save(); 59 | return models; 60 | } 61 | catch (Exception) 62 | { 63 | throw; 64 | } 65 | } 66 | 67 | public bool Update(TEntity model) 68 | { 69 | try 70 | { 71 | EntityEntry entry = NewMethod(model); 72 | 73 | DbSet.Attach(model); 74 | 75 | entry.State = EntityState.Modified; 76 | 77 | return Save() > 0; 78 | } 79 | catch (Exception) 80 | { 81 | 82 | throw; 83 | } 84 | } 85 | 86 | private EntityEntry NewMethod(TEntity model) 87 | { 88 | return _context.Entry(model); 89 | } 90 | 91 | public bool Update(List models) 92 | { 93 | try 94 | { 95 | foreach (TEntity register in models) 96 | { 97 | EntityEntry entry = _context.Entry(register); 98 | DbSet.Attach(register); 99 | entry.State = EntityState.Modified; 100 | } 101 | 102 | return Save() > 0; 103 | } 104 | catch (Exception) 105 | { 106 | 107 | throw; 108 | } 109 | } 110 | 111 | public bool Delete(TEntity model) 112 | { 113 | try 114 | { 115 | if (model is Entity) 116 | { 117 | (model as Entity).IsDeleted = true; 118 | EntityEntry _entry = _context.Entry(model); 119 | 120 | DbSet.Attach(model); 121 | 122 | _entry.State = EntityState.Modified; 123 | } 124 | else 125 | { 126 | EntityEntry _entry = _context.Entry(model); 127 | DbSet.Attach(model); 128 | _entry.State = EntityState.Deleted; 129 | } 130 | 131 | return Save() > 0; 132 | } 133 | catch (Exception) 134 | { 135 | throw; 136 | } 137 | } 138 | 139 | public bool Delete(params object[] Keys) 140 | { 141 | try 142 | { 143 | TEntity model = DbSet.Find(Keys); 144 | return (model != null) && Delete(model); 145 | } 146 | catch (Exception) 147 | { 148 | 149 | throw; 150 | } 151 | } 152 | 153 | public bool Delete(Expression> where) 154 | { 155 | try 156 | { 157 | TEntity model = DbSet.Where(where).FirstOrDefault(); 158 | 159 | return (model != null) && Delete(model); 160 | } 161 | catch (Exception) 162 | { 163 | 164 | throw; 165 | } 166 | } 167 | 168 | public int Save() 169 | { 170 | try 171 | { 172 | return _context.SaveChanges(); 173 | } 174 | catch (Exception) 175 | { 176 | 177 | throw; 178 | } 179 | } 180 | 181 | #endregion 182 | 183 | #region 'Methods: Search' 184 | 185 | public TEntity Find(params object[] Keys) 186 | { 187 | try 188 | { 189 | return DbSet.Find(Keys); 190 | } 191 | catch (Exception) 192 | { 193 | 194 | throw; 195 | } 196 | } 197 | 198 | public TEntity Find(Expression> where) 199 | { 200 | try 201 | { 202 | return DbSet.AsNoTracking().FirstOrDefault(where); 203 | } 204 | catch (Exception) 205 | { 206 | 207 | throw; 208 | } 209 | } 210 | 211 | public TEntity Find(Expression> predicate, Func, object> includes) 212 | { 213 | try 214 | { 215 | IQueryable _query = DbSet; 216 | 217 | if (includes != null) 218 | _query = includes(_query) as IQueryable; 219 | 220 | return _query.SingleOrDefault(predicate); 221 | } 222 | catch (Exception) 223 | { 224 | 225 | throw; 226 | } 227 | } 228 | 229 | public IQueryable Query(Expression> where) 230 | { 231 | try 232 | { 233 | return DbSet.Where(where); 234 | } 235 | catch (Exception) 236 | { 237 | 238 | throw; 239 | } 240 | } 241 | //Func, IIncludableQueryable> include 242 | public IQueryable Query(Expression> predicate, Func, object> includes) 243 | { 244 | try 245 | { 246 | IQueryable _query = DbSet; 247 | 248 | if (includes != null) 249 | _query = includes(_query) as IQueryable; 250 | 251 | return _query.Where(predicate).AsQueryable(); 252 | } 253 | catch (Exception) 254 | { 255 | 256 | throw; 257 | } 258 | } 259 | 260 | #endregion 261 | 262 | #region 'Assyncronous Methods' 263 | 264 | public async Task CreateAsync(TEntity model) 265 | { 266 | try 267 | { 268 | DbSet.Add(model); 269 | await SaveAsync(); 270 | return model; 271 | } 272 | catch (Exception) 273 | { 274 | 275 | throw; 276 | } 277 | } 278 | 279 | public async Task UpdateAsync(TEntity model) 280 | { 281 | try 282 | { 283 | EntityEntry entry = _context.Entry(model); 284 | 285 | DbSet.Attach(model); 286 | 287 | entry.State = EntityState.Modified; 288 | 289 | return await SaveAsync() > 0; 290 | } 291 | catch (Exception) 292 | { 293 | 294 | throw; 295 | } 296 | } 297 | 298 | public async Task DeleteAsync(TEntity model) 299 | { 300 | try 301 | { 302 | EntityEntry entry = _context.Entry(model); 303 | 304 | DbSet.Attach(model); 305 | 306 | entry.State = EntityState.Deleted; 307 | 308 | return await SaveAsync() > 0; 309 | } 310 | catch (Exception) 311 | { 312 | 313 | throw; 314 | } 315 | } 316 | 317 | public async Task DeleteAsync(params object[] Keys) 318 | { 319 | try 320 | { 321 | TEntity model = DbSet.Find(Keys); 322 | return (model != null) && await DeleteAsync(model); 323 | } 324 | catch (Exception) 325 | { 326 | 327 | throw; 328 | } 329 | } 330 | 331 | public async Task DeleteAsync(Expression> where) 332 | { 333 | try 334 | { 335 | TEntity model = DbSet.FirstOrDefault(where); 336 | 337 | return (model != null) && await DeleteAsync(model); 338 | } 339 | catch (Exception) 340 | { 341 | 342 | throw; 343 | } 344 | } 345 | 346 | public async Task SaveAsync() 347 | { 348 | try 349 | { 350 | return await _context.SaveChangesAsync(); 351 | } 352 | catch (Exception) 353 | { 354 | 355 | throw; 356 | } 357 | } 358 | 359 | #endregion 360 | 361 | #region 'Search Methods Async' 362 | 363 | public async Task GetAsync(params object[] Keys) 364 | { 365 | try 366 | { 367 | return await DbSet.FindAsync(Keys); 368 | } 369 | catch (Exception) 370 | { 371 | 372 | throw; 373 | } 374 | } 375 | 376 | public async Task GetAsync(Expression> where) 377 | { 378 | try 379 | { 380 | return await DbSet.AsNoTracking().FirstOrDefaultAsync(where); 381 | } 382 | catch (Exception) 383 | { 384 | 385 | throw; 386 | } 387 | } 388 | 389 | #endregion 390 | 391 | 392 | public void Dispose() 393 | { 394 | try 395 | { 396 | if (_context != null) 397 | _context.Dispose(); 398 | GC.SuppressFinalize(this); 399 | } 400 | catch (Exception) 401 | { 402 | 403 | throw; 404 | } 405 | } 406 | } 407 | 408 | } 409 | --------------------------------------------------------------------------------