<file_sep># [0.3.0](https://github.com/OpenCodeFoundation/eSchool/compare/v0.2.0...v0.3.0) (2020-08-01)


### Features

* **deployment:** Initial deployment script  ([#178](https://github.com/OpenCodeFoundation/eSchool/issues/178)) ([5344488](https://github.com/OpenCodeFoundation/eSchool/commit/5344488dd5b13f81423ce4fce4cc256223957569)), closes [#146](https://github.com/OpenCodeFoundation/eSchool/issues/146)
* **enrolling:** add open telemetry integration ([eb751de](https://github.com/OpenCodeFoundation/eSchool/commit/eb751ded855a5923ef1f42707c9476e87e36a825))
* **enrolling:** publish docker image to docker hub ([#177](https://github.com/OpenCodeFoundation/eSchool/issues/177))Closes [#173](https://github.com/OpenCodeFoundation/eSchool/issues/173) ([43fb95c](https://github.com/OpenCodeFoundation/eSchool/commit/43fb95c3bb5039a2d47f2ed0b5e2fa496603c1d0))
* **enrolling:** update enrolling service to .NET 5.0 ([#186](https://github.com/OpenCodeFoundation/eSchool/issues/186)) ([a03d284](https://github.com/OpenCodeFoundation/eSchool/commit/a03d284d9ccdeb4127ce4377084557ffffb82120)), closes [#167](https://github.com/OpenCodeFoundation/eSchool/issues/167)
* **pipeline:** improve pipeline trigger ([60e7fb7](https://github.com/OpenCodeFoundation/eSchool/commit/60e7fb7efce0db773d6d8be3d8698c1ca3b0bad0))



## [0.2.0](https://github.com/OpenCodeFoundation/eSchool/compare/62af44a5c22bd198491bc95684b0a136f0a2b9cd...v0.2.0) (2020-07-01)


### Bug Fixes

* **enrolling:** change email address as required field ([e3da303](https://github.com/OpenCodeFoundation/eSchool/commit/e3da303c162a0a54158d5b8c07a919e37bd4ae44))
* **enrolling:** modify source path for code coverage ([#166](https://github.com/OpenCodeFoundation/eSchool/issues/166)) ([2845652](https://github.com/OpenCodeFoundation/eSchool/commit/284565244a4a278fbb3bbbb0a30d85f0f66ffc1f)), closes [#164](https://github.com/OpenCodeFoundation/eSchool/issues/164)
* **enrolling:** update NuGet packages ([#161](https://github.com/OpenCodeFoundation/eSchool/issues/161)) ([d4797b4](https://github.com/OpenCodeFoundation/eSchool/commit/d4797b4fb527ee2a664c037761cb0d123e44d03f))
* broken identity service removed ([62af44a](https://github.com/OpenCodeFoundation/eSchool/commit/62af44a5c22bd198491bc95684b0a136f0a2b9cd)), closes [#95](https://github.com/OpenCodeFoundation/eSchool/issues/95)


### Features

* add GitHub code scanning ([#165](https://github.com/OpenCodeFoundation/eSchool/issues/165)) ([0cbc451](https://github.com/OpenCodeFoundation/eSchool/commit/0cbc4519ae075f91a9d3d2af41af2755481d899e))
* **enrolling:** enable logging every command and query processing ([0ac94ec](https://github.com/OpenCodeFoundation/eSchool/commit/0ac94ec4aea4a4567db7487282e4daa267fafccb))
* **enrolling:** use mediatR to handle query ([70114d7](https://github.com/OpenCodeFoundation/eSchool/commit/70114d761aae5fcbe6f1ec9511c1578d46680e85))
* enable w3c trace context support ([#159](https://github.com/OpenCodeFoundation/eSchool/issues/159)) ([e1a69b8](https://github.com/OpenCodeFoundation/eSchool/commit/e1a69b8a8e95a84d60c988d42a0dd70ded6f06fb))
* **service-status:** use sql database to store service health status ([#157](https://github.com/OpenCodeFoundation/eSchool/issues/157)) ([43b1148](https://github.com/OpenCodeFoundation/eSchool/commit/43b114895dfc06a1efe053d8b3967429807853a2))
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using OpenCodeFoundation.ESchool.Services.Joining.Domain.AggregatesModel.JoinAggregate;

namespace OpenCodeFoundation.ESchool.Services.Joining.Infrastructure.Repositories
{
    public class JoinRepository
      : IJoinRepository
    {
        private readonly JoiningContext _context;

        public JoinRepository(JoiningContext context)
        {
            _context = context;
        }

        public Join Add(Join join)
        {
            return _context.Joins
                .Add(join)
                .Entity;
        }

        public async Task<Join> FindByIdAsync(Guid id)
        {
            return await _context.Joins
                .Where(e => e.Id == id)
                .SingleOrDefaultAsync();
        }

        public Join Update(Join join)
        {
            return _context.Joins
                .Update(join)
                .Entity;
        }
    }
}
<file_sep>﻿using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Samplers;

namespace OpenCodeFoundation.OpenTelemetry
{
    public static class Extensions
    {
        private const string SectionName = "OpenTelemetry";

        public static IServiceCollection AddOpenTelemetryIntegration(
            this IServiceCollection services,
            Action<OpenTelemetryOptions> options = null,
            string sectionName = SectionName)
        {
            var openTelemetryOptions = services.GetOptions(sectionName, options);

            if (openTelemetryOptions.Enabled)
            {
                ConfigureOpenTelemetry(services, openTelemetryOptions);
            }

            return services;
        }

        public static T GetOptions<T>(
            this IServiceCollection services,
            string sectionName,
            Action<T> configure = null)
        where T : IConfigurationOptions, new()
        {
            var provider = services.BuildServiceProvider();
            var configuration = provider.GetRequiredService<IConfiguration>();

            var options = new T();
            configure?.Invoke(options);

            configuration.GetSection(sectionName).Bind(options);

            options.Validate();
            return options;
        }

        private static void ConfigureOpenTelemetry(IServiceCollection services, OpenTelemetryOptions openTelemetryOptions)
        {
            services.AddOpenTelemetry(configure =>
            {
                ConfigureSampler(openTelemetryOptions, configure);
                ConfigureInstrumentations(openTelemetryOptions, configure);
                ConfigureExporters(openTelemetryOptions, configure);
            });
        }

        private static void ConfigureSampler(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
        {
            if (openTelemetryOptions.AlwaysOnSampler)
            {
                configure.SetSampler(new AlwaysOnSampler());
            }
        }

        private static void ConfigureExporters(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
        {
            if (openTelemetryOptions.Jaeger.Enabled)
            {
                configure.UseJaegerExporter(config =>
                {
                    config.ServiceName = openTelemetryOptions.Jaeger.ServiceName;

                    config.AgentHost = openTelemetryOptions.Jaeger.Host;
                    config.AgentPort = openTelemetryOptions.Jaeger.Port;
                });
            }
        }

        private static void ConfigureInstrumentations(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
        {
            configure.AddAspNetCoreInstrumentation(config =>
            {
                config.TextFormat = GetTextFormat(openTelemetryOptions);
            });

            configure.AddHttpClientInstrumentation(config =>
            {
                config.TextFormat = GetTextFormat(openTelemetryOptions);
            });

            configure.AddSqlClientDependencyInstrumentation();
        }

        private static ITextFormat GetTextFormat(OpenTelemetryOptions openTelemetryOptions)
            => openTelemetryOptions.Istio
                ? new B3Format()
                : (ITextFormat)new TraceContextFormat();
    }
}
<file_sep>﻿using System;
using System.Threading.Tasks;
using OpenCodeFoundation.ESchool.Services.Joining.Domain.SeedWork;

namespace OpenCodeFoundation.ESchool.Services.Joining.Domain.AggregatesModel.JoinAggregate
{
    public interface IJoinRepository
        : IRepository<Join>
    {
        Join Add(Join join);

        Join Update(Join join);

        Task<Join> FindByIdAsync(Guid id);
    }
}
<file_sep>﻿using MediatR;

namespace OpenCodeFoundation.ESchool.Services.Joining.API.Application.Commands
{
    public class JoinApplicationCommand
        : IRequest<bool>
    {
        public string Name { get; set; }

        public string Email { get; set; }

        public string Mobile { get; set; }
    }
}

<file_sep>#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src

COPY ["src/Services/Joining/Joining.API/Joining.API.csproj", "src/Services/Joining/Joining.API/"]
COPY ["src/Services/Joining/Joining.Domain/Joining.Domain.csproj", "src/Services/Joining/Joining.Domain/"]
COPY ["src/Services/Joining/Joining.Infrastructure/Joining.Infrastructure.csproj", "src/Services/Joining/Joining.Infrastructure/"]
COPY ["src/Services/Joining/Joining.UnitTests/Joining.UnitTests.csproj", "src/Services/Joining/Joining.UnitTests/"]
COPY ["src/Services/Joining/Joining.FunctionalTests/Joining.FunctionalTests.csproj", "src/Services/Joining/Joining.FunctionalTests/"]

RUN dotnet restore "src/Services/Joining/Joining.API/Joining.API.csproj"
RUN dotnet restore "src/Services/Joining/Joining.UnitTests/Joining.UnitTests.csproj"
RUN dotnet restore "src/Services/Joining/Joining.FunctionalTests/Joining.FunctionalTests.csproj"

COPY . .
WORKDIR "/src/src/Services/Joining/Joining.API"
RUN dotnet build "Joining.API.csproj" -c Release -o /app/build

FROM build as unittest
WORKDIR /src/src/Services/Joining/Joining.UnitTests

FROM build as functionaltest
WORKDIR /src/src/Services/Joining/Joining.FunctionalTests

FROM build AS publish
RUN dotnet publish "Joining.API.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Joining.API.dll"]<file_sep>﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using OpenCodeFoundation.ESchool.Services.Joining.Domain.AggregatesModel.JoinAggregate;

namespace OpenCodeFoundation.ESchool.Services.Joining.Infrastructure
{
    public class JoiningContext
        : DbContext
    {
        public JoiningContext(DbContextOptions<JoiningContext> options)
            : base(options)
        {
        }

        public DbSet<Join> Joins { get; set; }


    }

    public class JoiningContextFactory : IDesignTimeDbContextFactory<JoiningContext>
    {
        public JoiningContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<JoiningContext>()
                .UseSqlServer("Server=.;Initial Catalog=OpenCodeFoundation.JoiningDb;Integrated Security=true");

            return new JoiningContext(optionsBuilder.Options);
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Extensions.Logging;
using OpenCodeFoundation.ESchool.Services.Joining.Domain.AggregatesModel.JoinAggregate;
using OpenCodeFoundation.ESchool.Services.Joining.Infrastructure;

namespace OpenCodeFoundation.ESchool.Services.Joining.API.Application.Commands
{
    public class JoinApplicationCommandHandler
        :IRequestHandler<JoinApplicationCommand, bool>
    {
        private readonly ILogger<JoinApplicationCommandHandler> _logger;
        private readonly JoiningContext _context;

        public JoinApplicationCommandHandler(
            JoiningContext context,
            ILogger<JoinApplicationCommandHandler> logger)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        public async Task<bool> Handle(JoinApplicationCommand command, CancellationToken cancellationToken)
        {
            var join = new Join(command.Name, command.Email, command.Mobile);
            _context.Joins.Add(join);
            await _context.SaveChangesAsync();
            return true;
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using OpenCodeFoundation.ESchool.Services.Joining.API.Application.Commands;
using OpenCodeFoundation.ESchool.Services.Joining.Domain.AggregatesModel.JoinAggregate;
using OpenCodeFoundation.ESchool.Services.Joining.Infrastructure;

namespace OpenCodeFoundation.ESchool.Services.Joining.API.Controllers
{
    //[Route("api/[controller]")]
    [ApiController]
    [Route("[controller]")]
    public class JoinController : ControllerBase
    {
        private readonly ILogger<JoinController> _logger;
        private readonly IMediator _mediator;
        private readonly JoiningContext _context;

        public JoinController(
            ILogger<JoinController> logger,
            IMediator mediator,
            JoiningContext context)
        {
            _logger = logger;
            _mediator = mediator;
            _context = context;
        }

        [HttpGet]
        public async Task<List<Join>> Get()
        {
            _logger.LogInformation("Getting all Joins");
            var joins = await _context.Joins.ToListAsync();

            _logger.LogInformation("Total {NumberOfJoin} joins retrieved", joins.Count);
            return joins;
        }

        [HttpPost]
        public async Task<IActionResult> Post([FromBody] JoinApplicationCommand command)
        {
            _logger.LogInformation(
                "Sending command: {CommandName} - ({@Command})",
                command.GetType().Name,
                command);

            await _mediator.Send(command);
            return Ok();
        }
    }
}
<file_sep>﻿namespace OpenCodeFoundation.ESchool.Services.Joining.Domain.SeedWork
{
    public interface IRepository<T>
        where T : IAggregateRoot
    {
    }
}
