From 4549d31b6ec32e66881d2a1deaab475c05ad4225 Mon Sep 17 00:00:00 2001 From: MaxchilKH Date: Sat, 29 Aug 2020 17:25:48 +0200 Subject: [PATCH] whatever --- .docker/docker-compose.yaml | 3 + .../AspNet.Security.OAuth.MyGut.csproj | 11 + .../AuthenticationBuilderExtension.cs | 20 + .../MyGutAuthenticationConstants.cs | 20 + .../MyGutAuthenticationDefaults.cs | 19 + .../MyGutAuthenticationHandler.cs | 19 + .../MyGutAuthenticationOptions.cs | 16 + src/InternshipSystem.Api/ApiProfile.cs | 12 + .../Controllers/AccessController.cs | 68 ++ .../Controllers/AdminController.cs | 4 +- .../Controllers/DocumentsController.cs | 37 +- .../Controllers/EditionController.cs | 79 ++- .../Controllers/RegistrationController.cs | 32 +- src/InternshipSystem.Api/Dockerfile | 3 +- .../Extensions/ServiceCollectionExtensions.cs | 35 + .../InternshipSystem.Api.csproj | 1 + .../ModelBinders/UserBinder.cs | 37 ++ .../ModelBinders/UserBinderProvider.cs | 25 + .../Options/SecurityOptions.cs | 8 + .../Result/EditionConfigurationResult.cs | 15 + .../Result/EditionResult.cs | 12 +- .../Security/InternshipClaims.cs | 9 + .../Security/JwtTokenService.cs | 37 ++ src/InternshipSystem.Api/Security/Policies.cs | 7 + src/InternshipSystem.Api/Security/User.cs | 12 + .../Services/UserService.cs | 7 + src/InternshipSystem.Api/Startup.cs | 23 +- src/InternshipSystem.Core/Entity/Edition.cs | 9 + .../Entity/Internship/Internship.cs | 16 + .../Entity/Internship/InternshipProgram.cs | 5 + .../Internship/InternshipRegistration.cs | 5 + src/InternshipSystem.Core/Entity/Report.cs | 5 + .../Repository/IInternshipRepository.cs | 11 - .../Repository/IStudentRepository.cs | 11 - .../ValueObject/InternshipStatus.cs | 10 + .../InternshipDbContext.cs | 2 + .../20200828182238_Init.Designer.cs | 609 ++++++++++++++++++ .../Migrations/20200828182238_Init.cs | 438 +++++++++++++ .../InternshipDbContextModelSnapshot.cs | 607 +++++++++++++++++ 39 files changed, 2234 insertions(+), 65 deletions(-) create mode 100644 src/AspNet.Security.OAuth.MyGut/AspNet.Security.OAuth.MyGut.csproj create mode 100644 src/AspNet.Security.OAuth.MyGut/AuthenticationBuilderExtension.cs create mode 100644 src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationConstants.cs create mode 100644 src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationDefaults.cs create mode 100644 src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationHandler.cs create mode 100644 src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationOptions.cs create mode 100644 src/InternshipSystem.Api/Controllers/AccessController.cs create mode 100644 src/InternshipSystem.Api/Extensions/ServiceCollectionExtensions.cs create mode 100644 src/InternshipSystem.Api/ModelBinders/UserBinder.cs create mode 100644 src/InternshipSystem.Api/ModelBinders/UserBinderProvider.cs create mode 100644 src/InternshipSystem.Api/Options/SecurityOptions.cs create mode 100644 src/InternshipSystem.Api/Result/EditionConfigurationResult.cs create mode 100644 src/InternshipSystem.Api/Security/InternshipClaims.cs create mode 100644 src/InternshipSystem.Api/Security/JwtTokenService.cs create mode 100644 src/InternshipSystem.Api/Security/Policies.cs create mode 100644 src/InternshipSystem.Api/Security/User.cs create mode 100644 src/InternshipSystem.Api/Services/UserService.cs delete mode 100644 src/InternshipSystem.Core/Interface/Repository/IInternshipRepository.cs delete mode 100644 src/InternshipSystem.Core/Interface/Repository/IStudentRepository.cs create mode 100644 src/InternshipSystem.Core/ValueObject/InternshipStatus.cs create mode 100644 src/InternshipSystem.Repository/Migrations/20200828182238_Init.Designer.cs create mode 100644 src/InternshipSystem.Repository/Migrations/20200828182238_Init.cs create mode 100644 src/InternshipSystem.Repository/Migrations/InternshipDbContextModelSnapshot.cs diff --git a/.docker/docker-compose.yaml b/.docker/docker-compose.yaml index f2625a2..5e6599f 100644 --- a/.docker/docker-compose.yaml +++ b/.docker/docker-compose.yaml @@ -6,6 +6,9 @@ services: environment: CONNECTIONSTRINGS__INTERNSHIPDATABASE: "Host=db.postgres;Port=5432;Database=postgres;Username=postgres;Password=szwoniu" ASPNETCORE_ENVIRONMENT: Development + ASPNETCORE_URLS: http://+:80 + SECURITYOPTIONS__SECRET: PDv7DrqznYL6nv7DrqzjnQYO9JxIsWdcjnQYL6nu0f + SECURITYOPTIONS__EXPIRATION: 20 depends_on: - db.postgres ports: diff --git a/src/AspNet.Security.OAuth.MyGut/AspNet.Security.OAuth.MyGut.csproj b/src/AspNet.Security.OAuth.MyGut/AspNet.Security.OAuth.MyGut.csproj new file mode 100644 index 0000000..e5cfdb1 --- /dev/null +++ b/src/AspNet.Security.OAuth.MyGut/AspNet.Security.OAuth.MyGut.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + + + + + + + diff --git a/src/AspNet.Security.OAuth.MyGut/AuthenticationBuilderExtension.cs b/src/AspNet.Security.OAuth.MyGut/AuthenticationBuilderExtension.cs new file mode 100644 index 0000000..b442239 --- /dev/null +++ b/src/AspNet.Security.OAuth.MyGut/AuthenticationBuilderExtension.cs @@ -0,0 +1,20 @@ +using System; +using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.DependencyInjection; + +namespace AspNet.Security.OAuth.MyGut +{ + public static class AuthenticationBuilderExtension + { + public static AuthenticationBuilder AddMyGut(this AuthenticationBuilder builder) => + builder.AddMyGut(MyGutAuthenticationDefaults.AuthenticationScheme, MyGutAuthenticationDefaults.DisplayName, options => { }); + + public static AuthenticationBuilder AddMyGut( + this AuthenticationBuilder builder, + string scheme, + string caption, + Action configuration + ) => + builder.AddOAuth(scheme, caption, configuration); + } +} \ No newline at end of file diff --git a/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationConstants.cs b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationConstants.cs new file mode 100644 index 0000000..7edb2e5 --- /dev/null +++ b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationConstants.cs @@ -0,0 +1,20 @@ +namespace AspNet.Security.OAuth.MyGut +{ + public static class MyGutAuthenticationConstants + { + public static class Urls + { + } + + public static class Claims + { + public const string AlbumNumber = "urn:mygut:albumnumber"; + } + + public static class UrlQueryParameterValues + { + public const string Consent = "consent"; + public const string None = "none"; + } + } +} \ No newline at end of file diff --git a/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationDefaults.cs b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationDefaults.cs new file mode 100644 index 0000000..5e07b0d --- /dev/null +++ b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationDefaults.cs @@ -0,0 +1,19 @@ +namespace AspNet.Security.OAuth.MyGut +{ + public static class MyGutAuthenticationDefaults + { + public const string AuthenticationScheme = "MyGut"; + + public const string DisplayName = "MyGut"; + + public const string Issuer = "MyGut"; + + public const string CallbackPath = "/signin-mygut"; + + public const string AuthorizationEndpoint = "https://logowanie.pg.edu.pl/login"; + + public const string TokenEndpoint = "https://logowanie.pg.edu.pl/login"; + + public const string UserInformationEndpoint = "https://logowanie.pg.edu.pl/login"; + } +} \ No newline at end of file diff --git a/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationHandler.cs b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationHandler.cs new file mode 100644 index 0000000..6782093 --- /dev/null +++ b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationHandler.cs @@ -0,0 +1,19 @@ +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.OAuth; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace AspNet.Security.OAuth.MyGut +{ + public class MyGutAuthenticationHandler : OAuthHandler + { + public MyGutAuthenticationHandler( + IOptionsMonitor options, + ILoggerFactory logger, + UrlEncoder encoder, + ISystemClock clock) : base(options, logger, encoder, clock) + { + } + } +} \ No newline at end of file diff --git a/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationOptions.cs b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationOptions.cs new file mode 100644 index 0000000..c3f027d --- /dev/null +++ b/src/AspNet.Security.OAuth.MyGut/MyGutAuthenticationOptions.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Authentication.OAuth; + +namespace AspNet.Security.OAuth.MyGut +{ + public class MyGutAuthenticationOptions : OAuthOptions + { + public MyGutAuthenticationOptions() + { + ClaimsIssuer = MyGutAuthenticationDefaults.Issuer; + CallbackPath = MyGutAuthenticationDefaults.CallbackPath; + AuthorizationEndpoint = MyGutAuthenticationDefaults.AuthorizationEndpoint; + TokenEndpoint = MyGutAuthenticationDefaults.TokenEndpoint; + UserInformationEndpoint = MyGutAuthenticationDefaults.UserInformationEndpoint; + } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/ApiProfile.cs b/src/InternshipSystem.Api/ApiProfile.cs index a25d338..7bb6c8e 100644 --- a/src/InternshipSystem.Api/ApiProfile.cs +++ b/src/InternshipSystem.Api/ApiProfile.cs @@ -1,6 +1,9 @@ using AutoMapper; using InternshipSystem.Api.Queries; +using InternshipSystem.Api.Result; using InternshipSystem.Core; +using InternshipSystem.Core.Entity.Internship; +using InternshipSystem.Core.UglyOrmArtifacts; namespace InternshipSystem.Api { @@ -9,6 +12,15 @@ namespace InternshipSystem.Api public ApiProfile() { CreateMap(); + + CreateMap() + .ForMember( + result => result.Status, + opt => opt.MapFrom(edition => edition.IsOpen ? "Open" : "Archival")); + + CreateMap(); + + CreateMap().IncludeMembers(es => es.Subject); } } } \ No newline at end of file diff --git a/src/InternshipSystem.Api/Controllers/AccessController.cs b/src/InternshipSystem.Api/Controllers/AccessController.cs new file mode 100644 index 0000000..44d1b95 --- /dev/null +++ b/src/InternshipSystem.Api/Controllers/AccessController.cs @@ -0,0 +1,68 @@ +using System; +using System.Linq; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using InternshipSystem.Api.Options; +using InternshipSystem.Api.Security; +using InternshipSystem.Repository; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; + +namespace InternshipSystem.Api.Controllers +{ + [Route("access")] + [ApiController] + public class AccessController : ControllerBase + { + private readonly InternshipDbContext _context; + private readonly JwtTokenService _tokenService; + private readonly SecurityOptions _securityOptions; + + public AccessController(IOptions options, InternshipDbContext context, JwtTokenService tokenService) + { + _context = context; + _tokenService = tokenService; + _securityOptions = options.Value; + } + + + [HttpGet("login")] + public async Task Authenticate(string code, CancellationToken cancellationToken) + { + var identity = new ClaimsIdentity(new[] + { + new Claim(ClaimTypes.Name, "Jan"), + new Claim(ClaimTypes.Surname, "Kowalski"), + new Claim(InternshipClaims.PersonNumber, "1") + }); + + return Ok(_tokenService.generateToken(identity)); + } + + [HttpGet("loginEdition")] + [Authorize] + public async Task LoginIntoEdition(Guid editionId, User user, CancellationToken token) + { + var edition = await _context.Editions.FindAsync(editionId); + + var hasInternship = await _context.Entry(edition) + .Collection(e => e.Internships) + .Query() + .AnyAsync(i => i.Student.Id == user.PersonNumber, token); + + if (!hasInternship) + { + return Unauthorized("Student isn't registered for this edition"); + } + + var newIdentity = User.Identities.First(); + + newIdentity.AddClaim(new Claim(InternshipClaims.Edition, editionId.ToString())); + + return Ok(_tokenService.generateToken(newIdentity)); + } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Controllers/AdminController.cs b/src/InternshipSystem.Api/Controllers/AdminController.cs index 25f5408..3fbb0ef 100644 --- a/src/InternshipSystem.Api/Controllers/AdminController.cs +++ b/src/InternshipSystem.Api/Controllers/AdminController.cs @@ -1,5 +1,7 @@ using System.Threading.Tasks; using InternshipSystem.Repository; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; namespace InternshipSystem.Api.Controllers @@ -16,7 +18,7 @@ namespace InternshipSystem.Api.Controllers public DatabaseFiller FillerService { get; } - [HttpPost("fill")] + [HttpPost("fill")] public async Task Fill() { await FillerService.FillCompanies(); await FillerService.FillEditions(); diff --git a/src/InternshipSystem.Api/Controllers/DocumentsController.cs b/src/InternshipSystem.Api/Controllers/DocumentsController.cs index 938bbe6..9350e02 100644 --- a/src/InternshipSystem.Api/Controllers/DocumentsController.cs +++ b/src/InternshipSystem.Api/Controllers/DocumentsController.cs @@ -1,9 +1,13 @@ using System; +using System.Diagnostics; +using System.Linq; using System.Threading.Tasks; using AutoMapper; using InternshipSystem.Api.Queries; +using InternshipSystem.Api.Security; using InternshipSystem.Core; using InternshipSystem.Repository; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -37,7 +41,8 @@ namespace InternshipSystem.Api.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public async Task AddDocumentToInternship([FromBody] DocumentPublishRequest documentRequest) + [Authorize(Policy = Policies.RegisteredOnly)] + public async Task AddDocumentToInternship([FromBody] DocumentPublishRequest documentRequest, User user) { var validator = new DocumentPublishRequest.Validator(); var validationResult = await validator.ValidateAsync(documentRequest); @@ -46,16 +51,23 @@ namespace InternshipSystem.Api.Controllers { return BadRequest(validationResult.ToString()); } - - var studentInternship = await GetCurrentStudentInternship(); - + + var edition = + await Context.Editions + .FindAsync(user.EditionId.Value); + + var internship = await Context.Entry(edition) + .Collection(e => e.Internships) + .Query() + .SingleAsync(i => i.Student.Id == user.PersonNumber); + var document = Mapper.Map(documentRequest); if (documentRequest.Id.HasValue) { try { - studentInternship.UpdateDocument(document); + internship.UpdateDocument(document); } catch (InvalidOperationException) { @@ -64,24 +76,11 @@ namespace InternshipSystem.Api.Controllers } else { - studentInternship.AddNewDocument(document); + internship.AddNewDocument(document); } await Context.SaveChangesAsync(); return Ok(); } - - private async Task GetCurrentStudentInternship() - { - // TODO: rewrite when authentication will be implemented - var edition = await Context - .Editions - .FirstAsync(); - - return await Context.Entry(edition) - .Collection(e => e.Internships) - .Query() - .FirstAsync(); - } } } \ No newline at end of file diff --git a/src/InternshipSystem.Api/Controllers/EditionController.cs b/src/InternshipSystem.Api/Controllers/EditionController.cs index a104275..67c2f81 100644 --- a/src/InternshipSystem.Api/Controllers/EditionController.cs +++ b/src/InternshipSystem.Api/Controllers/EditionController.cs @@ -1,32 +1,93 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; using System.Threading.Tasks; +using AutoMapper; +using AutoMapper.QueryableExtensions; +using IdentityServer4.Extensions; using InternshipSystem.Api.Result; -using InternshipSystem.Core; +using InternshipSystem.Api.Security; +using InternshipSystem.Core.Entity.Internship; using InternshipSystem.Repository; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; namespace InternshipSystem.Api.Controllers { - [Route("edition")] + [Route("editions")] public class EditionController : ControllerBase { private InternshipDbContext Context { get; } + private IMapper Mapper { get; } - public EditionController(InternshipDbContext context) + public EditionController(InternshipDbContext context, IMapper mapper) { Context = context; + Mapper = mapper; } - + /// - /// Get current edition parameters + /// Get accessible editions /// - /// Parameters of edition registered for by student - /// This action is only available for authorized student registered for current edition + /// Editions accessible by the current user + /// This action is only available for authorized student /// [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetCurrentEdition() => - throw new NotImplementedException(); + [ProducesResponseType(StatusCodes.Status404NotFound)] + [Authorize] + public async Task>> GetAvailableEditions(CancellationToken token) + { + var personNumber = long.Parse(User.FindFirst("PersonNumber").Value); + + var editions = + await Context.Editions + .Where(edition => + edition.Internships + .Any(internship => internship.Student.Id == personNumber)) + .ProjectTo(Mapper.ConfigurationProvider) + .ToListAsync(token); + + if (editions.IsNullOrEmpty()) + { + return NotFound(); + } + + return Ok(editions); + } + + /// + /// Get edition's configuration + /// + /// Parameters of edition registered for by student + /// This action is only available for authorized student registered for this edition edition + /// Specified edition doesn't exist + /// + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [Authorize(Policy = "RegisteredForEditionOnly")] + public async Task> GetEditionsConfiguration(Guid id, CancellationToken token) + { + var personNumber = long.Parse(User.FindFirst(InternshipClaims.PersonNumber).Value); + + var edition = + await Context.Editions + .Include(e => e.AvailableSubjects) + .Where(e => e.Id == id) + .ProjectTo(Mapper.ConfigurationProvider) + .FirstOrDefaultAsync(token); + + if (edition == null) + { + return NotFound(); + } + + return Ok(edition); + } + } } \ No newline at end of file diff --git a/src/InternshipSystem.Api/Controllers/RegistrationController.cs b/src/InternshipSystem.Api/Controllers/RegistrationController.cs index 76bc0db..26931fc 100644 --- a/src/InternshipSystem.Api/Controllers/RegistrationController.cs +++ b/src/InternshipSystem.Api/Controllers/RegistrationController.cs @@ -1,6 +1,11 @@ using System; +using System.Threading; using System.Threading.Tasks; using InternshipSystem.Api.Result; +using InternshipSystem.Api.Security; +using InternshipSystem.Core; +using InternshipSystem.Repository; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -10,6 +15,13 @@ namespace InternshipSystem.Api.Controllers [Route("register")] public class RegistrationController : ControllerBase { + private readonly InternshipDbContext _context; + + public RegistrationController(InternshipDbContext context) + { + _context = context; + } + /// /// Register student for edition using provided registration code /// @@ -22,9 +34,23 @@ namespace InternshipSystem.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task RegisterStudentForEdition([FromBody] Guid registrationCode) => - throw new NotImplementedException(); - + [Authorize] + public async Task RegisterStudentForEdition([FromBody] Guid registrationCode, User user, CancellationToken token) + { + var edition = await _context.Editions.FindAsync(registrationCode); + + if (edition == null) + { + return NotFound(); + } + + var student = await _context.Students.FindAsync(user.PersonNumber); + + edition.RegisterInternship(student); + await _context.SaveChangesAsync(); + + return Ok(); + } } } \ No newline at end of file diff --git a/src/InternshipSystem.Api/Dockerfile b/src/InternshipSystem.Api/Dockerfile index f76cce3..47e62c2 100644 --- a/src/InternshipSystem.Api/Dockerfile +++ b/src/InternshipSystem.Api/Dockerfile @@ -13,7 +13,8 @@ COPY . ./ RUN dotnet publish ./InternshipSystem.Api -c Release -o out # Build runtime image -FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine +FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 +RUN curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l /vsdbg WORKDIR /app COPY --from=build-env /app/out . ENTRYPOINT ["dotnet", "./InternshipSystem.Api.dll"] diff --git a/src/InternshipSystem.Api/Extensions/ServiceCollectionExtensions.cs b/src/InternshipSystem.Api/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..84f18bc --- /dev/null +++ b/src/InternshipSystem.Api/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,35 @@ +using System.Text; +using InternshipSystem.Api.Options; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace InternshipSystem.Api.Extensions +{ + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddStudentAuthentication(this IServiceCollection services) + { + var options = services.BuildServiceProvider().GetService>().Value; + + services + .AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(o => + { + o.TokenValidationParameters = new TokenValidationParameters + { + IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(options.Secret)), + ValidateAudience = false, + ValidateIssuer = false + }; + }); + + return services; + } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/InternshipSystem.Api.csproj b/src/InternshipSystem.Api/InternshipSystem.Api.csproj index d5c17c0..133fa45 100644 --- a/src/InternshipSystem.Api/InternshipSystem.Api.csproj +++ b/src/InternshipSystem.Api/InternshipSystem.Api.csproj @@ -23,6 +23,7 @@ + diff --git a/src/InternshipSystem.Api/ModelBinders/UserBinder.cs b/src/InternshipSystem.Api/ModelBinders/UserBinder.cs new file mode 100644 index 0000000..8a5fe2a --- /dev/null +++ b/src/InternshipSystem.Api/ModelBinders/UserBinder.cs @@ -0,0 +1,37 @@ +using System; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using InternshipSystem.Api.Security; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace InternshipSystem.Api.ModelBinders +{ + public class UserBinder : IModelBinder + { + public Task BindModelAsync(ModelBindingContext bindingContext) + { + if (bindingContext == null) + { + throw new ArgumentNullException(nameof(bindingContext)); + } + + var principal = bindingContext.HttpContext.User; + + if (principal == null) + { + return Task.CompletedTask; + } + + var user = new User + { + Name = principal.FindFirst(ClaimTypes.Name).Value, + PersonNumber = long.Parse(principal.FindFirst(InternshipClaims.PersonNumber).Value), + EditionId = Guid.TryParse(principal.FindFirst(InternshipClaims.Edition).Value, out var edition) ? edition : (Guid?) null + }; + + bindingContext.Result = ModelBindingResult.Success(user); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/ModelBinders/UserBinderProvider.cs b/src/InternshipSystem.Api/ModelBinders/UserBinderProvider.cs new file mode 100644 index 0000000..d2e3d25 --- /dev/null +++ b/src/InternshipSystem.Api/ModelBinders/UserBinderProvider.cs @@ -0,0 +1,25 @@ +using System; +using InternshipSystem.Api.Security; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; + +namespace InternshipSystem.Api.ModelBinders +{ + public class UserBinderProvider : IModelBinderProvider + { + public IModelBinder GetBinder(ModelBinderProviderContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (context.Metadata.ModelType == typeof(User)) + { + return new BinderTypeModelBinder(typeof(UserBinder)); + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Options/SecurityOptions.cs b/src/InternshipSystem.Api/Options/SecurityOptions.cs new file mode 100644 index 0000000..2fcf5fe --- /dev/null +++ b/src/InternshipSystem.Api/Options/SecurityOptions.cs @@ -0,0 +1,8 @@ +namespace InternshipSystem.Api.Options +{ + public class SecurityOptions + { + public string Secret { get; set; } + public double Expiration { get; set; } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Result/EditionConfigurationResult.cs b/src/InternshipSystem.Api/Result/EditionConfigurationResult.cs new file mode 100644 index 0000000..5ded37a --- /dev/null +++ b/src/InternshipSystem.Api/Result/EditionConfigurationResult.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using InternshipSystem.Core.Entity.Internship; +using InternshipSystem.Core.UglyOrmArtifacts; + +namespace InternshipSystem.Api.Result +{ + public class EditionConfigurationResult + { + public List AvailableSubjects { get; set; } + public DateTime EditionStart { get; set; } + public DateTime EditionFinish { get; set; } + public DateTime ReportingStart { get; set; } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Result/EditionResult.cs b/src/InternshipSystem.Api/Result/EditionResult.cs index 6436990..5e91432 100644 --- a/src/InternshipSystem.Api/Result/EditionResult.cs +++ b/src/InternshipSystem.Api/Result/EditionResult.cs @@ -1,13 +1,13 @@ -using System.Collections.Generic; -using InternshipSystem.Core; -using InternshipSystem.Core.Entity.Internship; +using System; namespace InternshipSystem.Api.Result { public struct EditionResult { - public List Types { get; set; } - public List Subjects { get; set; } - public Student Student { get; set; } + public Guid Id { get; set; } + public DateTime EditionStart { get; set; } + public DateTime EditionFinish { get; set; } + public string CourseName { get; set; } + public string Status { get; set; } } } \ No newline at end of file diff --git a/src/InternshipSystem.Api/Security/InternshipClaims.cs b/src/InternshipSystem.Api/Security/InternshipClaims.cs new file mode 100644 index 0000000..43ae182 --- /dev/null +++ b/src/InternshipSystem.Api/Security/InternshipClaims.cs @@ -0,0 +1,9 @@ +namespace InternshipSystem.Api.Security +{ + public static class InternshipClaims + { + public static string Edition = "Edition"; + + public static string PersonNumber = "PersonNumber"; + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Security/JwtTokenService.cs b/src/InternshipSystem.Api/Security/JwtTokenService.cs new file mode 100644 index 0000000..3fc154a --- /dev/null +++ b/src/InternshipSystem.Api/Security/JwtTokenService.cs @@ -0,0 +1,37 @@ +using System; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using InternshipSystem.Api.Options; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace InternshipSystem.Api.Security +{ + public class JwtTokenService + { + private SecurityOptions _securityOptions; + + public JwtTokenService(IOptions securityOptions) + { + _securityOptions = securityOptions.Value; + } + + public string generateToken(ClaimsIdentity identity) + { + var handler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(_securityOptions.Secret); + + var descriptor = new SecurityTokenDescriptor + { + Subject = identity, + Expires = DateTime.UtcNow.AddMinutes(_securityOptions.Expiration), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + }; + + var jwtToken = handler.CreateJwtSecurityToken(descriptor); + + return handler.WriteToken(jwtToken); + } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Security/Policies.cs b/src/InternshipSystem.Api/Security/Policies.cs new file mode 100644 index 0000000..58e6d99 --- /dev/null +++ b/src/InternshipSystem.Api/Security/Policies.cs @@ -0,0 +1,7 @@ +namespace InternshipSystem.Api.Security +{ + public static class Policies + { + public const string RegisteredOnly = "RegisteredForEditionOnly"; + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Security/User.cs b/src/InternshipSystem.Api/Security/User.cs new file mode 100644 index 0000000..b569d6f --- /dev/null +++ b/src/InternshipSystem.Api/Security/User.cs @@ -0,0 +1,12 @@ +using System; + +namespace InternshipSystem.Api.Security +{ + public class User + { + public long PersonNumber { get; set; } + public string Name { get; set; } + + public Guid? EditionId { get; set; } + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Services/UserService.cs b/src/InternshipSystem.Api/Services/UserService.cs new file mode 100644 index 0000000..64f9e89 --- /dev/null +++ b/src/InternshipSystem.Api/Services/UserService.cs @@ -0,0 +1,7 @@ +namespace InternshipSystem.Api.Services +{ + public class UserService + { + + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Api/Startup.cs b/src/InternshipSystem.Api/Startup.cs index 1f46ea9..af8297f 100644 --- a/src/InternshipSystem.Api/Startup.cs +++ b/src/InternshipSystem.Api/Startup.cs @@ -2,6 +2,10 @@ using System; using System.IO; using System.Reflection; using AutoMapper; +using InternshipSystem.Api.Extensions; +using InternshipSystem.Api.ModelBinders; +using InternshipSystem.Api.Options; +using InternshipSystem.Api.Security; using InternshipSystem.Repository; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -22,6 +26,7 @@ namespace InternshipSystem.Api public void ConfigureServices(IServiceCollection services) => services + .Configure(Configuration.GetSection("SecurityOptions")) .AddDbContext(o => o.UseNpgsql(Configuration.GetConnectionString("InternshipDatabase"))) .AddSwaggerGen(options => { @@ -31,8 +36,17 @@ namespace InternshipSystem.Api options.IncludeXmlComments(xmlPath); }) .AddScoped() + .AddScoped() .AddAutoMapper(cfg => cfg.AddProfile()) - .AddControllers() + .AddStudentAuthentication() + .AddAuthorization(o => + { + o.AddPolicy(Policies.RegisteredOnly, policy => policy.RequireClaim("Edition")); + }) + .AddControllers(o => + { + o.ModelBinderProviders.Insert(0, new UserBinderProvider()); + }) ; public void Configure(IApplicationBuilder app, IWebHostEnvironment env) @@ -43,16 +57,17 @@ namespace InternshipSystem.Api } app - .UseSwagger() - .UseSwaggerUI(options => options.SwaggerEndpoint(Path.Join(Configuration.GetValue("ApiPrefix"), "/swagger/v1/swagger.json"), "InternshipSystem Api")) .UseHttpsRedirection() .UseRouting() + .UseAuthentication() .UseAuthorization() .UseCors() .UseEndpoints(endpoints => { endpoints.MapControllers(); - }); + }) + .UseSwagger() + .UseSwaggerUI(options => options.SwaggerEndpoint(Path.Join(Configuration.GetValue("ApiPrefix"), "/swagger/v1/swagger.json"), "InternshipSystem Api")); } } } diff --git a/src/InternshipSystem.Core/Entity/Edition.cs b/src/InternshipSystem.Core/Entity/Edition.cs index 165b31c..64172af 100644 --- a/src/InternshipSystem.Core/Entity/Edition.cs +++ b/src/InternshipSystem.Core/Entity/Edition.cs @@ -15,6 +15,8 @@ namespace InternshipSystem.Core public List Internships { get; set; } public List AvailableSubjects { get; set; } + public bool IsOpen => EditionFinish < DateTime.Today; + public Edition CreateEdition(DateTime start, DateTime end, DateTime reportingStart) { return new Edition @@ -24,5 +26,12 @@ namespace InternshipSystem.Core ReportingStart = reportingStart }; } + + public void RegisterInternship(Student student) + { + var internship = Internship.CreateStudentsInternship(student); + + Internships.Add(internship); + } } } \ No newline at end of file diff --git a/src/InternshipSystem.Core/Entity/Internship/Internship.cs b/src/InternshipSystem.Core/Entity/Internship/Internship.cs index 52aaf69..b9981d8 100644 --- a/src/InternshipSystem.Core/Entity/Internship/Internship.cs +++ b/src/InternshipSystem.Core/Entity/Internship/Internship.cs @@ -13,6 +13,7 @@ namespace InternshipSystem.Core public Report Report { get; set; } public List Approvals { get; set; } public List Documentation { get; set; } + public float? Grade { get; set; } public void UpdateDocument(Document document) { @@ -30,5 +31,20 @@ namespace InternshipSystem.Core Documentation.Add(document); } + + public static Internship CreateStudentsInternship(Student student) + { + var internship = new Internship(); + + internship.Student = student; + + internship.InternshipRegistration = InternshipRegistration.Create(); + internship.InternshipProgram = InternshipProgram.Create(); + internship.Report = Report.Create(); + internship.Approvals = new List(); + internship.Documentation = new List(); + + return internship; + } } } \ No newline at end of file diff --git a/src/InternshipSystem.Core/Entity/Internship/InternshipProgram.cs b/src/InternshipSystem.Core/Entity/Internship/InternshipProgram.cs index 71dc540..f5fc545 100644 --- a/src/InternshipSystem.Core/Entity/Internship/InternshipProgram.cs +++ b/src/InternshipSystem.Core/Entity/Internship/InternshipProgram.cs @@ -10,5 +10,10 @@ namespace InternshipSystem.Core public Mentor Mentor { get; set; } public DocumentState State { get; set; } public List ChosenSubjects { get; set; } + + public static InternshipProgram Create() + { + return new InternshipProgram(); + } } } \ No newline at end of file diff --git a/src/InternshipSystem.Core/Entity/Internship/InternshipRegistration.cs b/src/InternshipSystem.Core/Entity/Internship/InternshipRegistration.cs index 449230e..e12679a 100644 --- a/src/InternshipSystem.Core/Entity/Internship/InternshipRegistration.cs +++ b/src/InternshipSystem.Core/Entity/Internship/InternshipRegistration.cs @@ -12,5 +12,10 @@ namespace InternshipSystem.Core public DateTime End { get; set; } public InternshipType Type { get; set; } public DocumentState State { get; set; } + + public static InternshipRegistration Create() + { + return new InternshipRegistration(); + } } } \ No newline at end of file diff --git a/src/InternshipSystem.Core/Entity/Report.cs b/src/InternshipSystem.Core/Entity/Report.cs index 944678d..35f60a5 100644 --- a/src/InternshipSystem.Core/Entity/Report.cs +++ b/src/InternshipSystem.Core/Entity/Report.cs @@ -4,5 +4,10 @@ { public long Id { get; set; } public DocumentState State { get; set; } + + public static Report Create() + { + return new Report(); + } } } \ No newline at end of file diff --git a/src/InternshipSystem.Core/Interface/Repository/IInternshipRepository.cs b/src/InternshipSystem.Core/Interface/Repository/IInternshipRepository.cs deleted file mode 100644 index d2de047..0000000 --- a/src/InternshipSystem.Core/Interface/Repository/IInternshipRepository.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; - -namespace InternshipSystem.Core.Interface.Repository -{ - public interface IInternshipRepository - { - Task SaveInternship(Internship internship, CancellationToken token); - Task GetStudentsInternship(Student student, CancellationToken token); - } -} \ No newline at end of file diff --git a/src/InternshipSystem.Core/Interface/Repository/IStudentRepository.cs b/src/InternshipSystem.Core/Interface/Repository/IStudentRepository.cs deleted file mode 100644 index 7cc0826..0000000 --- a/src/InternshipSystem.Core/Interface/Repository/IStudentRepository.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; - -namespace InternshipSystem.Core.Interface.Repository -{ - public interface IStudentRepository - { - Task GetAlbumNumber(int album, CancellationToken token); - Task SaveStudent(Student student, CancellationToken token); - } -} \ No newline at end of file diff --git a/src/InternshipSystem.Core/ValueObject/InternshipStatus.cs b/src/InternshipSystem.Core/ValueObject/InternshipStatus.cs new file mode 100644 index 0000000..be62a97 --- /dev/null +++ b/src/InternshipSystem.Core/ValueObject/InternshipStatus.cs @@ -0,0 +1,10 @@ +namespace InternshipSystem.Core.ValueObject +{ + public enum InternshipStatus + { + Incomplete, + InProcess, + Graded, + Archival + } +} \ No newline at end of file diff --git a/src/InternshipSystem.Repository/InternshipDbContext.cs b/src/InternshipSystem.Repository/InternshipDbContext.cs index 716aef9..cd73ffb 100644 --- a/src/InternshipSystem.Repository/InternshipDbContext.cs +++ b/src/InternshipSystem.Repository/InternshipDbContext.cs @@ -10,6 +10,8 @@ namespace InternshipSystem.Repository public DbSet Companies { get; set; } public DbSet Editions { get; set; } + public DbSet Students { get; set; } + public InternshipDbContext(DbContextOptions options) : base(options) { diff --git a/src/InternshipSystem.Repository/Migrations/20200828182238_Init.Designer.cs b/src/InternshipSystem.Repository/Migrations/20200828182238_Init.Designer.cs new file mode 100644 index 0000000..0f84439 --- /dev/null +++ b/src/InternshipSystem.Repository/Migrations/20200828182238_Init.Designer.cs @@ -0,0 +1,609 @@ +// +using System; +using InternshipSystem.Repository; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace InternshipSystem.Repository.Migrations +{ + [DbContext(typeof(InternshipDbContext))] + [Migration("20200828182238_Init")] + partial class Init + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("InternshipSystem.Core.BranchOffice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("CompanyId") + .HasColumnName("company_id") + .HasColumnType("bigint"); + + b.HasKey("Id") + .HasName("pk_branch_office"); + + b.HasIndex("CompanyId") + .HasName("ix_branch_office_company_id"); + + b.ToTable("branch_office"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Name") + .HasColumnName("name") + .HasColumnType("text"); + + b.Property("Nip") + .IsRequired() + .HasColumnName("nip") + .HasColumnType("text"); + + b.Property("Range") + .HasColumnName("range") + .HasColumnType("integer"); + + b.Property("SiteAddress") + .HasColumnName("site_address") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_companies"); + + b.ToTable("companies"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Course", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Name") + .HasColumnName("name") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_course"); + + b.ToTable("course"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Description") + .HasColumnName("description") + .HasColumnType("text"); + + b.Property("InternshipId") + .HasColumnName("internship_id") + .HasColumnType("bigint"); + + b.Property("InternshipId1") + .HasColumnName("internship_id1") + .HasColumnType("bigint"); + + b.Property("RejectionReason") + .HasColumnName("rejection_reason") + .HasColumnType("text"); + + b.Property("Scan") + .HasColumnName("scan") + .HasColumnType("bytea"); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnName("type") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_document"); + + b.HasIndex("InternshipId") + .HasName("ix_document_internship_id"); + + b.HasIndex("InternshipId1") + .HasName("ix_document_internship_id1"); + + b.ToTable("document"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Edition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("uuid"); + + b.Property("CourseId") + .HasColumnName("course_id") + .HasColumnType("bigint"); + + b.Property("EditionFinish") + .HasColumnName("edition_finish") + .HasColumnType("timestamp without time zone"); + + b.Property("EditionStart") + .HasColumnName("edition_start") + .HasColumnType("timestamp without time zone"); + + b.Property("ReportingStart") + .HasColumnName("reporting_start") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id") + .HasName("pk_editions"); + + b.HasIndex("CourseId") + .HasName("ix_editions_course_id"); + + b.ToTable("editions"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Entity.Internship.InternshipSubject", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Description") + .HasColumnName("description") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_internship_subject"); + + b.ToTable("internship_subject"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Entity.Internship.InternshipType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Description") + .HasColumnName("description") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnName("type") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_internship_type"); + + b.ToTable("internship_type"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Internship", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("EditionId") + .HasColumnName("edition_id") + .HasColumnType("uuid"); + + b.Property("Grade") + .HasColumnName("grade") + .HasColumnType("real"); + + b.Property("InternshipProgramId") + .HasColumnName("internship_program_id") + .HasColumnType("bigint"); + + b.Property("InternshipRegistrationId") + .HasColumnName("internship_registration_id") + .HasColumnType("bigint"); + + b.Property("ReportId") + .HasColumnName("report_id") + .HasColumnType("bigint"); + + b.Property("StudentId") + .HasColumnName("student_id") + .HasColumnType("bigint"); + + b.HasKey("Id") + .HasName("pk_internship"); + + b.HasIndex("EditionId") + .HasName("ix_internship_edition_id"); + + b.HasIndex("InternshipProgramId") + .HasName("ix_internship_internship_program_id"); + + b.HasIndex("InternshipRegistrationId") + .HasName("ix_internship_internship_registration_id"); + + b.HasIndex("ReportId") + .HasName("ix_internship_report_id"); + + b.HasIndex("StudentId") + .HasName("ix_internship_student_id"); + + b.ToTable("internship"); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipProgram", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_internship_program"); + + b.ToTable("internship_program"); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipRegistration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("BranchAddressId") + .HasColumnName("branch_address_id") + .HasColumnType("bigint"); + + b.Property("CompanyId") + .HasColumnName("company_id") + .HasColumnType("bigint"); + + b.Property("End") + .HasColumnName("end") + .HasColumnType("timestamp without time zone"); + + b.Property("Start") + .HasColumnName("start") + .HasColumnType("timestamp without time zone"); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.Property("TypeId") + .HasColumnName("type_id") + .HasColumnType("bigint"); + + b.HasKey("Id") + .HasName("pk_internship_registration"); + + b.HasIndex("BranchAddressId") + .HasName("ix_internship_registration_branch_address_id"); + + b.HasIndex("CompanyId") + .HasName("ix_internship_registration_company_id"); + + b.HasIndex("TypeId") + .HasName("ix_internship_registration_type_id"); + + b.ToTable("internship_registration"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Report", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_report"); + + b.ToTable("report"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Student", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("AlbumNumber") + .HasColumnName("album_number") + .HasColumnType("integer"); + + b.Property("Email") + .HasColumnName("email") + .HasColumnType("text"); + + b.Property("FirstName") + .HasColumnName("first_name") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnName("last_name") + .HasColumnType("text"); + + b.Property("Semester") + .HasColumnName("semester") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_student"); + + b.ToTable("student"); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.EditionSubject", b => + { + b.Property("EditionId") + .HasColumnName("edition_id") + .HasColumnType("uuid"); + + b.Property("InternshipSubjectId") + .HasColumnName("internship_subject_id") + .HasColumnType("bigint"); + + b.HasKey("EditionId", "InternshipSubjectId") + .HasName("pk_edition_subject"); + + b.HasIndex("InternshipSubjectId") + .HasName("ix_edition_subject_internship_subject_id"); + + b.ToTable("edition_subject"); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.ProgramSubject", b => + { + b.Property("InternshipProgramId") + .HasColumnName("internship_program_id") + .HasColumnType("bigint"); + + b.Property("InternshipSubjectId") + .HasColumnName("internship_subject_id") + .HasColumnType("bigint"); + + b.HasKey("InternshipProgramId", "InternshipSubjectId") + .HasName("pk_program_subject"); + + b.HasIndex("InternshipSubjectId") + .HasName("ix_program_subject_internship_subject_id"); + + b.ToTable("program_subject"); + }); + + modelBuilder.Entity("InternshipSystem.Core.BranchOffice", b => + { + b.HasOne("InternshipSystem.Core.Company", null) + .WithMany("Branches") + .HasForeignKey("CompanyId") + .HasConstraintName("fk_branch_office_companies_company_id"); + + b.OwnsOne("InternshipSystem.Core.BranchAddress", "Address", b1 => + { + b1.Property("BranchOfficeId") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b1.Property("Building") + .HasColumnName("building") + .HasColumnType("text"); + + b1.Property("City") + .HasColumnName("city") + .HasColumnType("text"); + + b1.Property("Country") + .HasColumnName("country") + .HasColumnType("text"); + + b1.Property("PostalCode") + .HasColumnName("postal_code") + .HasColumnType("text"); + + b1.Property("Street") + .HasColumnName("street") + .HasColumnType("text"); + + b1.HasKey("BranchOfficeId") + .HasName("pk_branch_office"); + + b1.ToTable("branch_office"); + + b1.WithOwner() + .HasForeignKey("BranchOfficeId") + .HasConstraintName("fk_branch_address_branch_office_branch_office_id"); + }); + }); + + modelBuilder.Entity("InternshipSystem.Core.Document", b => + { + b.HasOne("InternshipSystem.Core.Internship", null) + .WithMany("Approvals") + .HasForeignKey("InternshipId") + .HasConstraintName("fk_document_internship_internship_id"); + + b.HasOne("InternshipSystem.Core.Internship", null) + .WithMany("Documentation") + .HasForeignKey("InternshipId1") + .HasConstraintName("fk_document_internship_internship_id1"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Edition", b => + { + b.HasOne("InternshipSystem.Core.Course", "Course") + .WithMany() + .HasForeignKey("CourseId") + .HasConstraintName("fk_editions_course_course_id"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Internship", b => + { + b.HasOne("InternshipSystem.Core.Edition", null) + .WithMany("Internships") + .HasForeignKey("EditionId") + .HasConstraintName("fk_internship_editions_edition_id"); + + b.HasOne("InternshipSystem.Core.InternshipProgram", "InternshipProgram") + .WithMany() + .HasForeignKey("InternshipProgramId") + .HasConstraintName("fk_internship_internship_program_internship_program_id"); + + b.HasOne("InternshipSystem.Core.InternshipRegistration", "InternshipRegistration") + .WithMany() + .HasForeignKey("InternshipRegistrationId") + .HasConstraintName("fk_internship_internship_registration_internship_registration_"); + + b.HasOne("InternshipSystem.Core.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .HasConstraintName("fk_internship_report_report_id"); + + b.HasOne("InternshipSystem.Core.Student", "Student") + .WithMany() + .HasForeignKey("StudentId") + .HasConstraintName("fk_internship_student_student_id"); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipProgram", b => + { + b.OwnsOne("InternshipSystem.Core.Mentor", "Mentor", b1 => + { + b1.Property("InternshipProgramId") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b1.Property("Email") + .HasColumnName("email") + .HasColumnType("text"); + + b1.Property("FirstName") + .HasColumnName("first_name") + .HasColumnType("text"); + + b1.Property("LastName") + .HasColumnName("last_name") + .HasColumnType("text"); + + b1.Property("PhoneNumber") + .IsRequired() + .HasColumnName("mentor_phone_number") + .HasColumnType("text"); + + b1.HasKey("InternshipProgramId") + .HasName("pk_internship_program"); + + b1.ToTable("internship_program"); + + b1.WithOwner() + .HasForeignKey("InternshipProgramId") + .HasConstraintName("fk_mentor_internship_program_internship_program_id"); + }); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipRegistration", b => + { + b.HasOne("InternshipSystem.Core.BranchOffice", "BranchAddress") + .WithMany() + .HasForeignKey("BranchAddressId") + .HasConstraintName("fk_internship_registration_branch_office_branch_address_id"); + + b.HasOne("InternshipSystem.Core.Company", "Company") + .WithMany() + .HasForeignKey("CompanyId") + .HasConstraintName("fk_internship_registration_companies_company_id"); + + b.HasOne("InternshipSystem.Core.Entity.Internship.InternshipType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .HasConstraintName("fk_internship_registration_internship_type_type_id"); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.EditionSubject", b => + { + b.HasOne("InternshipSystem.Core.Edition", "Edition") + .WithMany("AvailableSubjects") + .HasForeignKey("EditionId") + .HasConstraintName("fk_edition_subject_editions_edition_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("InternshipSystem.Core.Entity.Internship.InternshipSubject", "Subject") + .WithMany() + .HasForeignKey("InternshipSubjectId") + .HasConstraintName("fk_edition_subject_internship_subject_internship_subject_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.ProgramSubject", b => + { + b.HasOne("InternshipSystem.Core.InternshipProgram", "Program") + .WithMany("ChosenSubjects") + .HasForeignKey("InternshipProgramId") + .HasConstraintName("fk_program_subject_internship_program_internship_program_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("InternshipSystem.Core.Entity.Internship.InternshipSubject", "Subject") + .WithMany() + .HasForeignKey("InternshipSubjectId") + .HasConstraintName("fk_program_subject_internship_subject_internship_subject_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/InternshipSystem.Repository/Migrations/20200828182238_Init.cs b/src/InternshipSystem.Repository/Migrations/20200828182238_Init.cs new file mode 100644 index 0000000..e1b6129 --- /dev/null +++ b/src/InternshipSystem.Repository/Migrations/20200828182238_Init.cs @@ -0,0 +1,438 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace InternshipSystem.Repository.Migrations +{ + public partial class Init : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "companies", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + nip = table.Column(nullable: false), + name = table.Column(nullable: true), + range = table.Column(nullable: false), + site_address = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_companies", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "course", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + name = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_course", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "internship_program", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + first_name = table.Column(nullable: true), + last_name = table.Column(nullable: true), + email = table.Column(nullable: true), + mentor_phone_number = table.Column(nullable: true), + state = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_internship_program", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "internship_subject", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + description = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_internship_subject", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "internship_type", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + type = table.Column(nullable: true), + description = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_internship_type", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "report", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + state = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_report", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "student", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + album_number = table.Column(nullable: false), + first_name = table.Column(nullable: true), + last_name = table.Column(nullable: true), + email = table.Column(nullable: true), + semester = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_student", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "branch_office", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + street = table.Column(nullable: true), + building = table.Column(nullable: true), + city = table.Column(nullable: true), + postal_code = table.Column(nullable: true), + country = table.Column(nullable: true), + company_id = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_branch_office", x => x.id); + table.ForeignKey( + name: "fk_branch_office_companies_company_id", + column: x => x.company_id, + principalTable: "companies", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "editions", + columns: table => new + { + id = table.Column(nullable: false), + edition_start = table.Column(nullable: false), + edition_finish = table.Column(nullable: false), + reporting_start = table.Column(nullable: false), + course_id = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_editions", x => x.id); + table.ForeignKey( + name: "fk_editions_course_course_id", + column: x => x.course_id, + principalTable: "course", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "program_subject", + columns: table => new + { + internship_program_id = table.Column(nullable: false), + internship_subject_id = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_program_subject", x => new { x.internship_program_id, x.internship_subject_id }); + table.ForeignKey( + name: "fk_program_subject_internship_program_internship_program_id", + column: x => x.internship_program_id, + principalTable: "internship_program", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_program_subject_internship_subject_internship_subject_id", + column: x => x.internship_subject_id, + principalTable: "internship_subject", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "internship_registration", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + company_id = table.Column(nullable: true), + branch_address_id = table.Column(nullable: true), + start = table.Column(nullable: false), + end = table.Column(nullable: false), + type_id = table.Column(nullable: true), + state = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_internship_registration", x => x.id); + table.ForeignKey( + name: "fk_internship_registration_branch_office_branch_address_id", + column: x => x.branch_address_id, + principalTable: "branch_office", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "fk_internship_registration_companies_company_id", + column: x => x.company_id, + principalTable: "companies", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "fk_internship_registration_internship_type_type_id", + column: x => x.type_id, + principalTable: "internship_type", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "edition_subject", + columns: table => new + { + edition_id = table.Column(nullable: false), + internship_subject_id = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_edition_subject", x => new { x.edition_id, x.internship_subject_id }); + table.ForeignKey( + name: "fk_edition_subject_editions_edition_id", + column: x => x.edition_id, + principalTable: "editions", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_edition_subject_internship_subject_internship_subject_id", + column: x => x.internship_subject_id, + principalTable: "internship_subject", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "internship", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + student_id = table.Column(nullable: true), + internship_registration_id = table.Column(nullable: true), + internship_program_id = table.Column(nullable: true), + report_id = table.Column(nullable: true), + grade = table.Column(nullable: false), + edition_id = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_internship", x => x.id); + table.ForeignKey( + name: "fk_internship_editions_edition_id", + column: x => x.edition_id, + principalTable: "editions", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "fk_internship_internship_program_internship_program_id", + column: x => x.internship_program_id, + principalTable: "internship_program", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "fk_internship_internship_registration_internship_registration_", + column: x => x.internship_registration_id, + principalTable: "internship_registration", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "fk_internship_report_report_id", + column: x => x.report_id, + principalTable: "report", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "fk_internship_student_student_id", + column: x => x.student_id, + principalTable: "student", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "document", + columns: table => new + { + id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + description = table.Column(nullable: true), + scan = table.Column(nullable: true), + type = table.Column(nullable: false), + state = table.Column(nullable: false), + rejection_reason = table.Column(nullable: true), + internship_id = table.Column(nullable: true), + internship_id1 = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_document", x => x.id); + table.ForeignKey( + name: "fk_document_internship_internship_id", + column: x => x.internship_id, + principalTable: "internship", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "fk_document_internship_internship_id1", + column: x => x.internship_id1, + principalTable: "internship", + principalColumn: "id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "ix_branch_office_company_id", + table: "branch_office", + column: "company_id"); + + migrationBuilder.CreateIndex( + name: "ix_document_internship_id", + table: "document", + column: "internship_id"); + + migrationBuilder.CreateIndex( + name: "ix_document_internship_id1", + table: "document", + column: "internship_id1"); + + migrationBuilder.CreateIndex( + name: "ix_edition_subject_internship_subject_id", + table: "edition_subject", + column: "internship_subject_id"); + + migrationBuilder.CreateIndex( + name: "ix_editions_course_id", + table: "editions", + column: "course_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_edition_id", + table: "internship", + column: "edition_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_internship_program_id", + table: "internship", + column: "internship_program_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_internship_registration_id", + table: "internship", + column: "internship_registration_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_report_id", + table: "internship", + column: "report_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_student_id", + table: "internship", + column: "student_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_registration_branch_address_id", + table: "internship_registration", + column: "branch_address_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_registration_company_id", + table: "internship_registration", + column: "company_id"); + + migrationBuilder.CreateIndex( + name: "ix_internship_registration_type_id", + table: "internship_registration", + column: "type_id"); + + migrationBuilder.CreateIndex( + name: "ix_program_subject_internship_subject_id", + table: "program_subject", + column: "internship_subject_id"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "document"); + + migrationBuilder.DropTable( + name: "edition_subject"); + + migrationBuilder.DropTable( + name: "program_subject"); + + migrationBuilder.DropTable( + name: "internship"); + + migrationBuilder.DropTable( + name: "internship_subject"); + + migrationBuilder.DropTable( + name: "editions"); + + migrationBuilder.DropTable( + name: "internship_program"); + + migrationBuilder.DropTable( + name: "internship_registration"); + + migrationBuilder.DropTable( + name: "report"); + + migrationBuilder.DropTable( + name: "student"); + + migrationBuilder.DropTable( + name: "course"); + + migrationBuilder.DropTable( + name: "branch_office"); + + migrationBuilder.DropTable( + name: "internship_type"); + + migrationBuilder.DropTable( + name: "companies"); + } + } +} diff --git a/src/InternshipSystem.Repository/Migrations/InternshipDbContextModelSnapshot.cs b/src/InternshipSystem.Repository/Migrations/InternshipDbContextModelSnapshot.cs new file mode 100644 index 0000000..59b3a8f --- /dev/null +++ b/src/InternshipSystem.Repository/Migrations/InternshipDbContextModelSnapshot.cs @@ -0,0 +1,607 @@ +// +using System; +using InternshipSystem.Repository; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace InternshipSystem.Repository.Migrations +{ + [DbContext(typeof(InternshipDbContext))] + partial class InternshipDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("InternshipSystem.Core.BranchOffice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("CompanyId") + .HasColumnName("company_id") + .HasColumnType("bigint"); + + b.HasKey("Id") + .HasName("pk_branch_office"); + + b.HasIndex("CompanyId") + .HasName("ix_branch_office_company_id"); + + b.ToTable("branch_office"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Name") + .HasColumnName("name") + .HasColumnType("text"); + + b.Property("Nip") + .IsRequired() + .HasColumnName("nip") + .HasColumnType("text"); + + b.Property("Range") + .HasColumnName("range") + .HasColumnType("integer"); + + b.Property("SiteAddress") + .HasColumnName("site_address") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_companies"); + + b.ToTable("companies"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Course", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Name") + .HasColumnName("name") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_course"); + + b.ToTable("course"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Description") + .HasColumnName("description") + .HasColumnType("text"); + + b.Property("InternshipId") + .HasColumnName("internship_id") + .HasColumnType("bigint"); + + b.Property("InternshipId1") + .HasColumnName("internship_id1") + .HasColumnType("bigint"); + + b.Property("RejectionReason") + .HasColumnName("rejection_reason") + .HasColumnType("text"); + + b.Property("Scan") + .HasColumnName("scan") + .HasColumnType("bytea"); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnName("type") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_document"); + + b.HasIndex("InternshipId") + .HasName("ix_document_internship_id"); + + b.HasIndex("InternshipId1") + .HasName("ix_document_internship_id1"); + + b.ToTable("document"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Edition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("uuid"); + + b.Property("CourseId") + .HasColumnName("course_id") + .HasColumnType("bigint"); + + b.Property("EditionFinish") + .HasColumnName("edition_finish") + .HasColumnType("timestamp without time zone"); + + b.Property("EditionStart") + .HasColumnName("edition_start") + .HasColumnType("timestamp without time zone"); + + b.Property("ReportingStart") + .HasColumnName("reporting_start") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id") + .HasName("pk_editions"); + + b.HasIndex("CourseId") + .HasName("ix_editions_course_id"); + + b.ToTable("editions"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Entity.Internship.InternshipSubject", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Description") + .HasColumnName("description") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_internship_subject"); + + b.ToTable("internship_subject"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Entity.Internship.InternshipType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Description") + .HasColumnName("description") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnName("type") + .HasColumnType("text"); + + b.HasKey("Id") + .HasName("pk_internship_type"); + + b.ToTable("internship_type"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Internship", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("EditionId") + .HasColumnName("edition_id") + .HasColumnType("uuid"); + + b.Property("Grade") + .HasColumnName("grade") + .HasColumnType("real"); + + b.Property("InternshipProgramId") + .HasColumnName("internship_program_id") + .HasColumnType("bigint"); + + b.Property("InternshipRegistrationId") + .HasColumnName("internship_registration_id") + .HasColumnType("bigint"); + + b.Property("ReportId") + .HasColumnName("report_id") + .HasColumnType("bigint"); + + b.Property("StudentId") + .HasColumnName("student_id") + .HasColumnType("bigint"); + + b.HasKey("Id") + .HasName("pk_internship"); + + b.HasIndex("EditionId") + .HasName("ix_internship_edition_id"); + + b.HasIndex("InternshipProgramId") + .HasName("ix_internship_internship_program_id"); + + b.HasIndex("InternshipRegistrationId") + .HasName("ix_internship_internship_registration_id"); + + b.HasIndex("ReportId") + .HasName("ix_internship_report_id"); + + b.HasIndex("StudentId") + .HasName("ix_internship_student_id"); + + b.ToTable("internship"); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipProgram", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_internship_program"); + + b.ToTable("internship_program"); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipRegistration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("BranchAddressId") + .HasColumnName("branch_address_id") + .HasColumnType("bigint"); + + b.Property("CompanyId") + .HasColumnName("company_id") + .HasColumnType("bigint"); + + b.Property("End") + .HasColumnName("end") + .HasColumnType("timestamp without time zone"); + + b.Property("Start") + .HasColumnName("start") + .HasColumnType("timestamp without time zone"); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.Property("TypeId") + .HasColumnName("type_id") + .HasColumnType("bigint"); + + b.HasKey("Id") + .HasName("pk_internship_registration"); + + b.HasIndex("BranchAddressId") + .HasName("ix_internship_registration_branch_address_id"); + + b.HasIndex("CompanyId") + .HasName("ix_internship_registration_company_id"); + + b.HasIndex("TypeId") + .HasName("ix_internship_registration_type_id"); + + b.ToTable("internship_registration"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Report", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("State") + .HasColumnName("state") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_report"); + + b.ToTable("report"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Student", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("AlbumNumber") + .HasColumnName("album_number") + .HasColumnType("integer"); + + b.Property("Email") + .HasColumnName("email") + .HasColumnType("text"); + + b.Property("FirstName") + .HasColumnName("first_name") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnName("last_name") + .HasColumnType("text"); + + b.Property("Semester") + .HasColumnName("semester") + .HasColumnType("integer"); + + b.HasKey("Id") + .HasName("pk_student"); + + b.ToTable("student"); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.EditionSubject", b => + { + b.Property("EditionId") + .HasColumnName("edition_id") + .HasColumnType("uuid"); + + b.Property("InternshipSubjectId") + .HasColumnName("internship_subject_id") + .HasColumnType("bigint"); + + b.HasKey("EditionId", "InternshipSubjectId") + .HasName("pk_edition_subject"); + + b.HasIndex("InternshipSubjectId") + .HasName("ix_edition_subject_internship_subject_id"); + + b.ToTable("edition_subject"); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.ProgramSubject", b => + { + b.Property("InternshipProgramId") + .HasColumnName("internship_program_id") + .HasColumnType("bigint"); + + b.Property("InternshipSubjectId") + .HasColumnName("internship_subject_id") + .HasColumnType("bigint"); + + b.HasKey("InternshipProgramId", "InternshipSubjectId") + .HasName("pk_program_subject"); + + b.HasIndex("InternshipSubjectId") + .HasName("ix_program_subject_internship_subject_id"); + + b.ToTable("program_subject"); + }); + + modelBuilder.Entity("InternshipSystem.Core.BranchOffice", b => + { + b.HasOne("InternshipSystem.Core.Company", null) + .WithMany("Branches") + .HasForeignKey("CompanyId") + .HasConstraintName("fk_branch_office_companies_company_id"); + + b.OwnsOne("InternshipSystem.Core.BranchAddress", "Address", b1 => + { + b1.Property("BranchOfficeId") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b1.Property("Building") + .HasColumnName("building") + .HasColumnType("text"); + + b1.Property("City") + .HasColumnName("city") + .HasColumnType("text"); + + b1.Property("Country") + .HasColumnName("country") + .HasColumnType("text"); + + b1.Property("PostalCode") + .HasColumnName("postal_code") + .HasColumnType("text"); + + b1.Property("Street") + .HasColumnName("street") + .HasColumnType("text"); + + b1.HasKey("BranchOfficeId") + .HasName("pk_branch_office"); + + b1.ToTable("branch_office"); + + b1.WithOwner() + .HasForeignKey("BranchOfficeId") + .HasConstraintName("fk_branch_address_branch_office_branch_office_id"); + }); + }); + + modelBuilder.Entity("InternshipSystem.Core.Document", b => + { + b.HasOne("InternshipSystem.Core.Internship", null) + .WithMany("Approvals") + .HasForeignKey("InternshipId") + .HasConstraintName("fk_document_internship_internship_id"); + + b.HasOne("InternshipSystem.Core.Internship", null) + .WithMany("Documentation") + .HasForeignKey("InternshipId1") + .HasConstraintName("fk_document_internship_internship_id1"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Edition", b => + { + b.HasOne("InternshipSystem.Core.Course", "Course") + .WithMany() + .HasForeignKey("CourseId") + .HasConstraintName("fk_editions_course_course_id"); + }); + + modelBuilder.Entity("InternshipSystem.Core.Internship", b => + { + b.HasOne("InternshipSystem.Core.Edition", null) + .WithMany("Internships") + .HasForeignKey("EditionId") + .HasConstraintName("fk_internship_editions_edition_id"); + + b.HasOne("InternshipSystem.Core.InternshipProgram", "InternshipProgram") + .WithMany() + .HasForeignKey("InternshipProgramId") + .HasConstraintName("fk_internship_internship_program_internship_program_id"); + + b.HasOne("InternshipSystem.Core.InternshipRegistration", "InternshipRegistration") + .WithMany() + .HasForeignKey("InternshipRegistrationId") + .HasConstraintName("fk_internship_internship_registration_internship_registration_"); + + b.HasOne("InternshipSystem.Core.Report", "Report") + .WithMany() + .HasForeignKey("ReportId") + .HasConstraintName("fk_internship_report_report_id"); + + b.HasOne("InternshipSystem.Core.Student", "Student") + .WithMany() + .HasForeignKey("StudentId") + .HasConstraintName("fk_internship_student_student_id"); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipProgram", b => + { + b.OwnsOne("InternshipSystem.Core.Mentor", "Mentor", b1 => + { + b1.Property("InternshipProgramId") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b1.Property("Email") + .HasColumnName("email") + .HasColumnType("text"); + + b1.Property("FirstName") + .HasColumnName("first_name") + .HasColumnType("text"); + + b1.Property("LastName") + .HasColumnName("last_name") + .HasColumnType("text"); + + b1.Property("PhoneNumber") + .IsRequired() + .HasColumnName("mentor_phone_number") + .HasColumnType("text"); + + b1.HasKey("InternshipProgramId") + .HasName("pk_internship_program"); + + b1.ToTable("internship_program"); + + b1.WithOwner() + .HasForeignKey("InternshipProgramId") + .HasConstraintName("fk_mentor_internship_program_internship_program_id"); + }); + }); + + modelBuilder.Entity("InternshipSystem.Core.InternshipRegistration", b => + { + b.HasOne("InternshipSystem.Core.BranchOffice", "BranchAddress") + .WithMany() + .HasForeignKey("BranchAddressId") + .HasConstraintName("fk_internship_registration_branch_office_branch_address_id"); + + b.HasOne("InternshipSystem.Core.Company", "Company") + .WithMany() + .HasForeignKey("CompanyId") + .HasConstraintName("fk_internship_registration_companies_company_id"); + + b.HasOne("InternshipSystem.Core.Entity.Internship.InternshipType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .HasConstraintName("fk_internship_registration_internship_type_type_id"); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.EditionSubject", b => + { + b.HasOne("InternshipSystem.Core.Edition", "Edition") + .WithMany("AvailableSubjects") + .HasForeignKey("EditionId") + .HasConstraintName("fk_edition_subject_editions_edition_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("InternshipSystem.Core.Entity.Internship.InternshipSubject", "Subject") + .WithMany() + .HasForeignKey("InternshipSubjectId") + .HasConstraintName("fk_edition_subject_internship_subject_internship_subject_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("InternshipSystem.Core.UglyOrmArtifacts.ProgramSubject", b => + { + b.HasOne("InternshipSystem.Core.InternshipProgram", "Program") + .WithMany("ChosenSubjects") + .HasForeignKey("InternshipProgramId") + .HasConstraintName("fk_program_subject_internship_program_internship_program_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("InternshipSystem.Core.Entity.Internship.InternshipSubject", "Subject") + .WithMany() + .HasForeignKey("InternshipSubjectId") + .HasConstraintName("fk_program_subject_internship_subject_internship_subject_id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} -- 2.45.2