Final task implemented
This commit is contained in:
parent
4e4a0b442c
commit
57eaccb746
1322 changed files with 31526 additions and 1 deletions
25
FinalTask/.dockerignore
Normal file
25
FinalTask/.dockerignore
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
**/.classpath
|
||||||
|
**/.dockerignore
|
||||||
|
**/.env
|
||||||
|
**/.git
|
||||||
|
**/.gitignore
|
||||||
|
**/.project
|
||||||
|
**/.settings
|
||||||
|
**/.toolstarget
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/*.*proj.user
|
||||||
|
**/*.dbmdl
|
||||||
|
**/*.jfm
|
||||||
|
**/azds.yaml
|
||||||
|
**/bin
|
||||||
|
**/charts
|
||||||
|
**/docker-compose*
|
||||||
|
**/Dockerfile*
|
||||||
|
**/node_modules
|
||||||
|
**/npm-debug.log
|
||||||
|
**/obj
|
||||||
|
**/secrets.dev.yaml
|
||||||
|
**/values.dev.yaml
|
||||||
|
LICENSE
|
||||||
|
README.md
|
57
FinalTask/FinalTask.sln
Normal file
57
FinalTask/FinalTask.sln
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.3.32819.101
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileAPI", "MobileAPI\MobileAPI.csproj", "{1977554E-2340-4721-9142-122CBDDA8F29}"
|
||||||
|
EndProject
|
||||||
|
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{1E938B61-E2A1-4CD5-91DC-F07329CD5DAA}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PushAPI", "PushAPI\PushAPI.csproj", "{F2BB9E8F-3A3C-470D-BF58-6172D55ACA08}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PushShared", "PushShared\PushShared.csproj", "{1DCD4394-2244-40F0-812A-C09600285058}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PushSender", "PushSender\PushSender.csproj", "{F4CEFE06-CA08-4A39-952B-BF4BCA0E8392}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsAPI", "StatsAPI\StatsAPI.csproj", "{5204DD72-EF3B-42EA-8A3A-D6C79B25218C}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "postgres-data", "postgres-data", "{C4F6D0E0-339F-4D75-A1DB-8224A0EE658E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{1977554E-2340-4721-9142-122CBDDA8F29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1977554E-2340-4721-9142-122CBDDA8F29}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1977554E-2340-4721-9142-122CBDDA8F29}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1977554E-2340-4721-9142-122CBDDA8F29}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1E938B61-E2A1-4CD5-91DC-F07329CD5DAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1E938B61-E2A1-4CD5-91DC-F07329CD5DAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1E938B61-E2A1-4CD5-91DC-F07329CD5DAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1E938B61-E2A1-4CD5-91DC-F07329CD5DAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F2BB9E8F-3A3C-470D-BF58-6172D55ACA08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F2BB9E8F-3A3C-470D-BF58-6172D55ACA08}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F2BB9E8F-3A3C-470D-BF58-6172D55ACA08}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F2BB9E8F-3A3C-470D-BF58-6172D55ACA08}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1DCD4394-2244-40F0-812A-C09600285058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1DCD4394-2244-40F0-812A-C09600285058}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1DCD4394-2244-40F0-812A-C09600285058}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1DCD4394-2244-40F0-812A-C09600285058}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F4CEFE06-CA08-4A39-952B-BF4BCA0E8392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F4CEFE06-CA08-4A39-952B-BF4BCA0E8392}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F4CEFE06-CA08-4A39-952B-BF4BCA0E8392}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F4CEFE06-CA08-4A39-952B-BF4BCA0E8392}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5204DD72-EF3B-42EA-8A3A-D6C79B25218C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5204DD72-EF3B-42EA-8A3A-D6C79B25218C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5204DD72-EF3B-42EA-8A3A-D6C79B25218C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5204DD72-EF3B-42EA-8A3A-D6C79B25218C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {FD5BC6D8-4B8B-4F36-8E31-65CC0FD31BAE}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
53
FinalTask/MobileAPI/Controllers/MobileController.cs
Normal file
53
FinalTask/MobileAPI/Controllers/MobileController.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using PushShared;
|
||||||
|
using PushShared.Mobile.Data;
|
||||||
|
|
||||||
|
namespace MobileAPI.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("mobile_apps")]
|
||||||
|
public class MobileController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILogger<MobileController> _logger;
|
||||||
|
private readonly MobileContext _mobileContext;
|
||||||
|
|
||||||
|
public MobileController(ILogger<MobileController> logger, MobileContext mobileContext)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_mobileContext = mobileContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("register_app")]
|
||||||
|
public IActionResult RegisterUser(MobileAppUser user)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Registering a new user app...");
|
||||||
|
var exists = _mobileContext.MobileAppUsers.Any(u => u.AppGuid == user.AppGuid);
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("User app with GUID {AppGuid} already exists", user.AppGuid);
|
||||||
|
return BadRequest("User app with this GUID already exists");
|
||||||
|
}
|
||||||
|
_mobileContext.MobileAppUsers.Add(user);
|
||||||
|
_mobileContext.SaveChanges();
|
||||||
|
_logger.LogInformation("User app successfully registered");
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("delete_app")]
|
||||||
|
public IActionResult DeleteUser([GuidAttribue] string guid)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Deleteing a user app...");
|
||||||
|
var exists = _mobileContext.MobileAppUsers.Any(u => u.AppGuid == guid);
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("User app with GUID {guid} was not found", guid);
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
var userToDelete = _mobileContext.MobileAppUsers.First(u => u.AppGuid == guid);
|
||||||
|
_mobileContext.MobileAppUsers.Remove(userToDelete);
|
||||||
|
_mobileContext.SaveChanges();
|
||||||
|
_logger.LogInformation("User app successfully deleted");
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FinalTask/MobileAPI/Dockerfile
Normal file
22
FinalTask/MobileAPI/Dockerfile
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#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/aspnet:6.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["MobileAPI/MobileAPI.csproj", "MobileAPI/"]
|
||||||
|
RUN dotnet restore "MobileAPI/MobileAPI.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/MobileAPI"
|
||||||
|
RUN dotnet build "MobileAPI.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "MobileAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "MobileAPI.dll"]
|
23
FinalTask/MobileAPI/MobileAPI.csproj
Normal file
23
FinalTask/MobileAPI/MobileAPI.csproj
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UserSecretsId>38a4d0c3-a019-452f-80db-b0e3876be206</UserSecretsId>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0-preview.7.22376.2" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0-preview.7" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PushShared\PushShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
27
FinalTask/MobileAPI/Program.cs
Normal file
27
FinalTask/MobileAPI/Program.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using PushShared;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
builder.Services.AddDbContext<MobileContext>();
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
38
FinalTask/MobileAPI/Properties/launchSettings.json
Normal file
38
FinalTask/MobileAPI/Properties/launchSettings.json
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"MobileAPI": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"applicationUrl": "https://localhost:7165;http://localhost:5165"
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Docker": {
|
||||||
|
"commandName": "Docker",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||||
|
"publishAllPorts": true,
|
||||||
|
"useSSL": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:36599",
|
||||||
|
"sslPort": 44354
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
FinalTask/MobileAPI/appsettings.Development.json
Normal file
8
FinalTask/MobileAPI/appsettings.Development.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
FinalTask/MobileAPI/appsettings.json
Normal file
12
FinalTask/MobileAPI/appsettings.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"Postgres": "host=postgres-mobile;port=5432;database=mobile;username=postgres;password=postgres"
|
||||||
|
}
|
||||||
|
}
|
56
FinalTask/PushAPI/Controllers/PushController.cs
Normal file
56
FinalTask/PushAPI/Controllers/PushController.cs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using PushShared;
|
||||||
|
using PushShared.Mobile.Data;
|
||||||
|
using PushShared.Push.Data;
|
||||||
|
|
||||||
|
namespace PushAPI.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("push")]
|
||||||
|
public class PushController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILogger<PushController> _logger;
|
||||||
|
private readonly MobileContext _context;
|
||||||
|
private readonly IPushService _pushService;
|
||||||
|
|
||||||
|
public PushController(ILogger<PushController> logger, MobileContext context, IPushService pushService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_context = context;
|
||||||
|
_pushService = pushService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("create")]
|
||||||
|
public IActionResult CreatePush(PushNotification push)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Received a request to create a new push notification...");
|
||||||
|
_logger.LogInformation("Title: {Title}", push.Title);
|
||||||
|
var guids = new List<string>();
|
||||||
|
_logger.LogInformation("Fetching GUIDs...");
|
||||||
|
foreach (var phone in push.SendToNumbers)
|
||||||
|
{
|
||||||
|
var guidsForPhone = _context.MobileAppUsers.Where(u => phone == u.Phone).Select(u => u.AppGuid);
|
||||||
|
if (!guidsForPhone.Any())
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Phone number {phone} isn't registered in the database", phone);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
guids.AddRange(guidsForPhone);
|
||||||
|
var msg = new Message() { Phone = phone, Title = push.Title, Contents = push.Message };
|
||||||
|
_context.Messages.Add(msg);
|
||||||
|
}
|
||||||
|
if (!guids.Any())
|
||||||
|
{
|
||||||
|
var error = "None of the specified numbers are registered in the database, push notification won't be sent";
|
||||||
|
_logger.LogWarning(error);
|
||||||
|
return NotFound(error);
|
||||||
|
}
|
||||||
|
_pushService.SendPush(push);
|
||||||
|
_logger.LogInformation("Successfully sent push notification to queue");
|
||||||
|
_logger.LogInformation("Saving sent messages to database...");
|
||||||
|
_context.SaveChanges();
|
||||||
|
_logger.LogInformation("Successfully saved the messages");
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FinalTask/PushAPI/Dockerfile
Normal file
22
FinalTask/PushAPI/Dockerfile
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#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/aspnet:6.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["PushAPI/PushAPI.csproj", "PushAPI/"]
|
||||||
|
RUN dotnet restore "PushAPI/PushAPI.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/PushAPI"
|
||||||
|
RUN dotnet build "PushAPI.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "PushAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "PushAPI.dll"]
|
28
FinalTask/PushAPI/Program.cs
Normal file
28
FinalTask/PushAPI/Program.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using PushShared;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
builder.Services.AddSingleton<IPushService, RabbitPushService>();
|
||||||
|
builder.Services.AddDbContext<MobileContext>();
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
38
FinalTask/PushAPI/Properties/launchSettings.json
Normal file
38
FinalTask/PushAPI/Properties/launchSettings.json
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"PushAPI": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"applicationUrl": "https://localhost:7170;http://localhost:5170"
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Docker": {
|
||||||
|
"commandName": "Docker",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||||
|
"publishAllPorts": true,
|
||||||
|
"useSSL": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:37638",
|
||||||
|
"sslPort": 44356
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
FinalTask/PushAPI/PushAPI.csproj
Normal file
23
FinalTask/PushAPI/PushAPI.csproj
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UserSecretsId>cd44cefb-7a63-461e-b3af-94972ea9acdd</UserSecretsId>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PushShared\PushShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
||||||
|
|
||||||
|
</Project>
|
8
FinalTask/PushAPI/appsettings.Development.json
Normal file
8
FinalTask/PushAPI/appsettings.Development.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
FinalTask/PushAPI/appsettings.json
Normal file
13
FinalTask/PushAPI/appsettings.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"Postgres": "host=postgres-mobile;port=5432;database=mobile;username=postgres;password=postgres",
|
||||||
|
"RabbitMQ": "amqp://guest:guest@rabbitmq:5672"
|
||||||
|
}
|
||||||
|
}
|
20
FinalTask/PushSender/Dockerfile
Normal file
20
FinalTask/PushSender/Dockerfile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#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/runtime:6.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["PushSender/PushSender.csproj", "PushSender/"]
|
||||||
|
RUN dotnet restore "PushSender/PushSender.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/PushSender"
|
||||||
|
RUN dotnet build "PushSender.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "PushSender.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "PushSender.dll"]
|
12
FinalTask/PushSender/Program.cs
Normal file
12
FinalTask/PushSender/Program.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using PushSender;
|
||||||
|
using PushShared;
|
||||||
|
|
||||||
|
IHost host = Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddSingleton<IPushService, RabbitPushService>();
|
||||||
|
services.AddHostedService<PushSenderWorker>();
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
await host.RunAsync();
|
14
FinalTask/PushSender/Properties/launchSettings.json
Normal file
14
FinalTask/PushSender/Properties/launchSettings.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"PushSender": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"environmentVariables": {
|
||||||
|
"DOTNET_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"dotnetRunMessages": true
|
||||||
|
},
|
||||||
|
"Docker": {
|
||||||
|
"commandName": "Docker"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
FinalTask/PushSender/PushSender.csproj
Normal file
19
FinalTask/PushSender/PushSender.csproj
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UserSecretsId>dotnet-PushSender-536BE94D-F909-4337-AA5A-208060D4A368</UserSecretsId>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PushShared\PushShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
32
FinalTask/PushSender/PushSenderWorker.cs
Normal file
32
FinalTask/PushSender/PushSenderWorker.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using PushShared;
|
||||||
|
|
||||||
|
namespace PushSender
|
||||||
|
{
|
||||||
|
public class PushSenderWorker : BackgroundService
|
||||||
|
{
|
||||||
|
private readonly ILogger<PushSenderWorker> _logger;
|
||||||
|
private readonly IPushService _pushService;
|
||||||
|
|
||||||
|
public PushSenderWorker(ILogger<PushSenderWorker> logger, IPushService pushService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_pushService = pushService;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Waiting for a push notification to send...");
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
var push = _pushService.ReceivePush();
|
||||||
|
if (push is not null)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Sending push notifications with title {Title}...", push.Title);
|
||||||
|
await Task.Delay(100, stoppingToken);
|
||||||
|
_logger.LogInformation("Push notification successfully sent");
|
||||||
|
}
|
||||||
|
await Task.Delay(1000, stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
FinalTask/PushSender/appsettings.Development.json
Normal file
8
FinalTask/PushSender/appsettings.Development.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
FinalTask/PushSender/appsettings.json
Normal file
11
FinalTask/PushSender/appsettings.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RabbitMQ": "amqp://guest:guest@rabbitmq:5672"
|
||||||
|
}
|
||||||
|
}
|
10
FinalTask/PushShared/IPushService.cs
Normal file
10
FinalTask/PushShared/IPushService.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using PushShared.Push.Data;
|
||||||
|
|
||||||
|
namespace PushShared
|
||||||
|
{
|
||||||
|
public interface IPushService
|
||||||
|
{
|
||||||
|
public void SendPush(PushNotification push);
|
||||||
|
public PushNotification? ReceivePush();
|
||||||
|
}
|
||||||
|
}
|
30
FinalTask/PushShared/MobileContext.cs
Normal file
30
FinalTask/PushShared/MobileContext.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using PushShared.Mobile.Data;
|
||||||
|
|
||||||
|
namespace PushShared;
|
||||||
|
|
||||||
|
public class MobileContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<MobileAppUser> MobileAppUsers { get; set; } = null!;
|
||||||
|
public DbSet<Message> Messages { get; set; } = null!;
|
||||||
|
private readonly ILogger<MobileContext> _logger;
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
public MobileContext(ILogger<MobileContext> logger, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_configuration = configuration;
|
||||||
|
_logger.LogInformation("Ensuring that the database exists...");
|
||||||
|
Database.EnsureCreated();
|
||||||
|
_logger.LogInformation("Success");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Connecting to database...");
|
||||||
|
optionsBuilder.UseNpgsql(_configuration.GetConnectionString("Postgres"));
|
||||||
|
_logger.LogInformation("Connection established");
|
||||||
|
}
|
||||||
|
}
|
43
FinalTask/PushShared/MobileData.cs
Normal file
43
FinalTask/PushShared/MobileData.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using PushShared.Push.Data;
|
||||||
|
|
||||||
|
namespace PushShared.Mobile.Data
|
||||||
|
{
|
||||||
|
[Table("app_users")]
|
||||||
|
public class MobileAppUser
|
||||||
|
{
|
||||||
|
[Key, Column("id"), JsonIgnore]
|
||||||
|
public long Id { get; set; }
|
||||||
|
[Required, GuidAttribue, Column("app_guid")]
|
||||||
|
public string AppGuid { get; set; }
|
||||||
|
[Required, Phone, Column("phone")]
|
||||||
|
public string Phone { get; set; }
|
||||||
|
[Required, Column("version")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Table("messages")]
|
||||||
|
public class Message
|
||||||
|
{
|
||||||
|
[Key, Column("id"), JsonIgnore]
|
||||||
|
public long Id { get; set; }
|
||||||
|
[Required, Column("title")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
[Required, Column("contents")]
|
||||||
|
public string Contents { get; set; }
|
||||||
|
[Required, Column("phone"), JsonIgnore]
|
||||||
|
public string Phone { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GuidAttribue : ValidationAttribute
|
||||||
|
{
|
||||||
|
public override bool IsValid(object? value)
|
||||||
|
{
|
||||||
|
if (value == null) return false;
|
||||||
|
if (value is not string guid) return false;
|
||||||
|
return Guid.TryParse(guid, out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
FinalTask/PushShared/PushData.cs
Normal file
32
FinalTask/PushShared/PushData.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace PushShared.Push.Data
|
||||||
|
{
|
||||||
|
public class PushNotification
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Title { get; set; }
|
||||||
|
[Required]
|
||||||
|
public string Message { get; set; }
|
||||||
|
[Required, EnumerablePhones]
|
||||||
|
public IEnumerable<string> SendToNumbers { get; set; }
|
||||||
|
[JsonIgnore]
|
||||||
|
public IEnumerable<string> SendToGuids { get; set; } = Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EnumerablePhonesAttribute : ValidationAttribute
|
||||||
|
{
|
||||||
|
public override bool IsValid(object? value)
|
||||||
|
{
|
||||||
|
if (value == null) return false;
|
||||||
|
if (value is not IEnumerable<string> phones) return false;
|
||||||
|
var phoneAttribute = new PhoneAttribute();
|
||||||
|
foreach (var phone in phones)
|
||||||
|
{
|
||||||
|
if (!phoneAttribute.IsValid(phone)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
FinalTask/PushShared/PushShared.csproj
Normal file
16
FinalTask/PushShared/PushShared.csproj
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0-preview.7.22376.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0-preview.7.22375.6" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0-preview.7" />
|
||||||
|
<PackageReference Include="RabbitMQ.Client" Version="6.4.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
56
FinalTask/PushShared/RabbitPushService.cs
Normal file
56
FinalTask/PushShared/RabbitPushService.cs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using PushShared.Push.Data;
|
||||||
|
using RabbitMQ.Client;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace PushShared
|
||||||
|
{
|
||||||
|
public class RabbitPushService : IPushService
|
||||||
|
{
|
||||||
|
private readonly ILogger<RabbitPushService> _logger;
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
private readonly ConnectionFactory _connectionFactory;
|
||||||
|
private readonly IConnection _connection;
|
||||||
|
private readonly IModel _channel;
|
||||||
|
|
||||||
|
public RabbitPushService(ILogger<RabbitPushService> logger, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_configuration = configuration;
|
||||||
|
_connectionFactory = new() { Uri = new(_configuration.GetConnectionString("RabbitMQ")!) };
|
||||||
|
_connection = _connectionFactory.CreateConnection();
|
||||||
|
_channel = _connection.CreateModel();
|
||||||
|
_channel.QueueDeclare(queue: "push-queue",
|
||||||
|
durable: false,
|
||||||
|
exclusive: false,
|
||||||
|
autoDelete: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendPush(PushNotification push)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Serializing push notification...");
|
||||||
|
var body = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(push));
|
||||||
|
_logger.LogInformation("Publishing push notification to queue");
|
||||||
|
_channel.BasicPublish(exchange: "",
|
||||||
|
routingKey: "push-queue",
|
||||||
|
body: body);
|
||||||
|
_logger.LogInformation("Publish successful");
|
||||||
|
}
|
||||||
|
|
||||||
|
public PushNotification? ReceivePush()
|
||||||
|
{
|
||||||
|
var result = _channel.BasicGet("push-queue", true);
|
||||||
|
if (result is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
_logger.LogInformation("Push notification found, deserializing...");
|
||||||
|
var body = result.Body.ToArray();
|
||||||
|
var push = JsonSerializer.Deserialize<PushNotification>(Encoding.UTF8.GetString(body));
|
||||||
|
_logger.LogInformation("Get successful, returning push notification");
|
||||||
|
return push;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
FinalTask/StatsAPI/Controllers/StatsController.cs
Normal file
61
FinalTask/StatsAPI/Controllers/StatsController.cs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
using Microsoft.AspNetCore.Cors;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using PushShared;
|
||||||
|
using PushShared.Mobile.Data;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace StatsAPI.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("stats")]
|
||||||
|
public class StatsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILogger<StatsController> _logger;
|
||||||
|
private readonly MobileContext _context;
|
||||||
|
|
||||||
|
public StatsController(ILogger<StatsController> logger, MobileContext context)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("user_apps")]
|
||||||
|
public IActionResult GetUserApps()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Fetching the user apps data...");
|
||||||
|
var userAppStats = new
|
||||||
|
{
|
||||||
|
AppUsers = new List<MobileAppUser>(),
|
||||||
|
VersionRegistrations = new Dictionary<string, int>(),
|
||||||
|
VersionUniquePhones = new Dictionary<string, int>()
|
||||||
|
};
|
||||||
|
_logger.LogInformation("Getting all user apps from databse...");
|
||||||
|
var appUsers = _context.MobileAppUsers.Select(u => u).AsEnumerable();
|
||||||
|
userAppStats.AppUsers.AddRange(appUsers);
|
||||||
|
_logger.LogInformation("Calculating registrations and unique phone numbers for each version...");
|
||||||
|
var versions = appUsers.Select(u => u.Version).ToHashSet();
|
||||||
|
foreach (var version in versions)
|
||||||
|
{
|
||||||
|
userAppStats.VersionRegistrations[version] = appUsers.Count(u => u.Version == version);
|
||||||
|
userAppStats.VersionUniquePhones[version] = appUsers.DistinctBy(u => u.Phone).Count(u => u.Version == version);
|
||||||
|
}
|
||||||
|
_logger.LogInformation("Successfully fetched the data");
|
||||||
|
return Ok(userAppStats);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("messages")]
|
||||||
|
public IActionResult GetMessages([Phone] string phone)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Fetching the messages for phone number {phone}...", phone);
|
||||||
|
var messageStats = new { Messages = new List<Message>() };
|
||||||
|
messageStats.Messages.AddRange(_context.Messages.Where(m => m.Phone == phone).Select(m => m));
|
||||||
|
if (!messageStats.Messages.Any())
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Phone number {phone} doesn't have any messages", phone);
|
||||||
|
return NotFound("The specefied number hasn't received any push notifications yet");
|
||||||
|
}
|
||||||
|
_logger.LogInformation("Successfully fetched the messages");
|
||||||
|
return Ok(messageStats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FinalTask/StatsAPI/Dockerfile
Normal file
22
FinalTask/StatsAPI/Dockerfile
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#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/aspnet:6.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["StatsAPI/StatsAPI.csproj", "StatsAPI/"]
|
||||||
|
RUN dotnet restore "StatsAPI/StatsAPI.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/StatsAPI"
|
||||||
|
RUN dotnet build "StatsAPI.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "StatsAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "StatsAPI.dll"]
|
34
FinalTask/StatsAPI/Program.cs
Normal file
34
FinalTask/StatsAPI/Program.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using PushShared;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
builder.Services.AddDbContext<MobileContext>();
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseCors(options =>
|
||||||
|
{
|
||||||
|
options.AllowAnyOrigin();
|
||||||
|
options.AllowAnyMethod();
|
||||||
|
options.AllowAnyHeader();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
38
FinalTask/StatsAPI/Properties/launchSettings.json
Normal file
38
FinalTask/StatsAPI/Properties/launchSettings.json
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"StatsAPI": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"applicationUrl": "https://localhost:7182;http://localhost:5182"
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Docker": {
|
||||||
|
"commandName": "Docker",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||||
|
"publishAllPorts": true,
|
||||||
|
"useSSL": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:40342",
|
||||||
|
"sslPort": 44360
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
FinalTask/StatsAPI/StatsAPI.csproj
Normal file
21
FinalTask/StatsAPI/StatsAPI.csproj
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UserSecretsId>8c7ea8a2-6f18-482c-a3e4-3320f3f47843</UserSecretsId>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PushShared\PushShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
8
FinalTask/StatsAPI/appsettings.Development.json
Normal file
8
FinalTask/StatsAPI/appsettings.Development.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
FinalTask/StatsAPI/appsettings.json
Normal file
12
FinalTask/StatsAPI/appsettings.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"Postgres": "host=postgres-mobile;port=5432;database=mobile;username=postgres;password=postgres"
|
||||||
|
}
|
||||||
|
}
|
23
FinalTask/docker-compose.dcproj
Normal file
23
FinalTask/docker-compose.dcproj
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectVersion>2.1</ProjectVersion>
|
||||||
|
<DockerTargetOS>Linux</DockerTargetOS>
|
||||||
|
<ProjectGuid>1e938b61-e2a1-4cd5-91dc-f07329cd5daa</ProjectGuid>
|
||||||
|
<DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
|
||||||
|
<DockerServiceUrl>{Scheme}://localhost:{ServicePort}/swagger</DockerServiceUrl>
|
||||||
|
<DockerServiceName>mobileapi</DockerServiceName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="docker-compose.override.yml">
|
||||||
|
<DependentUpon>docker-compose.yml</DependentUpon>
|
||||||
|
</None>
|
||||||
|
<None Include="docker-compose.yml" />
|
||||||
|
<None Include=".dockerignore" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<UserProperties launchsettings_1json__JsonSchema="" />
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
</Project>
|
24
FinalTask/docker-compose.dcproj.bak
Normal file
24
FinalTask/docker-compose.dcproj.bak
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectVersion>2.1</ProjectVersion>
|
||||||
|
<DockerTargetOS>Linux</DockerTargetOS>
|
||||||
|
<ProjectGuid>1e938b61-e2a1-4cd5-91dc-f07329cd5daa</ProjectGuid>
|
||||||
|
<DockerComposeUpArguments>--build<DockerComposeUpArguments/>
|
||||||
|
<DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
|
||||||
|
<DockerServiceUrl>{Scheme}://localhost:{ServicePort}/swagger</DockerServiceUrl>
|
||||||
|
<DockerServiceName>mobileapi</DockerServiceName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="docker-compose.override.yml">
|
||||||
|
<DependentUpon>docker-compose.yml</DependentUpon>
|
||||||
|
</None>
|
||||||
|
<None Include="docker-compose.yml" />
|
||||||
|
<None Include=".dockerignore" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<UserProperties launchsettings_1json__JsonSchema="" />
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
</Project>
|
40
FinalTask/docker-compose.override.yml
Normal file
40
FinalTask/docker-compose.override.yml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
version: '3.4'
|
||||||
|
|
||||||
|
services:
|
||||||
|
mobileapi:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=https://+:443;http://+:80
|
||||||
|
ports:
|
||||||
|
- "80"
|
||||||
|
- "443"
|
||||||
|
volumes:
|
||||||
|
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
|
||||||
|
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
|
||||||
|
pushapi:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=https://+:443;http://+:80
|
||||||
|
ports:
|
||||||
|
- "80"
|
||||||
|
- "443"
|
||||||
|
volumes:
|
||||||
|
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
|
||||||
|
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
|
||||||
|
|
||||||
|
pushsender:
|
||||||
|
environment:
|
||||||
|
- DOTNET_ENVIRONMENT=Development
|
||||||
|
volumes:
|
||||||
|
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
|
||||||
|
|
||||||
|
statsapi:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=https://+:443;http://+:80
|
||||||
|
ports:
|
||||||
|
- "80"
|
||||||
|
- "443"
|
||||||
|
volumes:
|
||||||
|
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
|
||||||
|
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
|
82
FinalTask/docker-compose.yml
Normal file
82
FinalTask/docker-compose.yml
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
version: '3.4'
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
container_name: postgres-mobile
|
||||||
|
image: postgres
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
volumes:
|
||||||
|
- ./postgres-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
container_name: rabbitmq-push
|
||||||
|
image: rabbitmq
|
||||||
|
ports:
|
||||||
|
- 15672:15672
|
||||||
|
|
||||||
|
mobileapi:
|
||||||
|
container_name: mobile-api
|
||||||
|
image: ${DOCKER_REGISTRY-}mobileapi
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: MobileAPI/Dockerfile
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_URLS=https://+:443;http://+:80
|
||||||
|
- ASPNETCORE_HTTPS_PORT=443
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
ports:
|
||||||
|
- 8701:80
|
||||||
|
- 8702:443
|
||||||
|
|
||||||
|
pushapi:
|
||||||
|
container_name: push-api
|
||||||
|
image: ${DOCKER_REGISTRY-}pushapi
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: PushAPI/Dockerfile
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_URLS=https://+:443;http://+:80
|
||||||
|
- ASPNETCORE_HTTPS_PORT=443
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
- rabbitmq
|
||||||
|
ports:
|
||||||
|
- 8703:80
|
||||||
|
- 8704:443
|
||||||
|
|
||||||
|
pushsender:
|
||||||
|
container_name: push-sender
|
||||||
|
image: ${DOCKER_REGISTRY-}pushsender
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: PushSender/Dockerfile
|
||||||
|
depends_on:
|
||||||
|
- rabbitmq
|
||||||
|
|
||||||
|
statswebsite:
|
||||||
|
container_name: stats-website
|
||||||
|
image: ${DOCKER_REGISTRY-}statswebsite
|
||||||
|
build:
|
||||||
|
context: stats-website
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
depends_on:
|
||||||
|
- statsapi
|
||||||
|
ports:
|
||||||
|
- 3000:3000
|
||||||
|
|
||||||
|
statsapi:
|
||||||
|
container_name: stats-api
|
||||||
|
image: ${DOCKER_REGISTRY-}statsapi
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: StatsAPI/Dockerfile
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_URLS=https://+:443;http://+:80
|
||||||
|
- ASPNETCORE_HTTPS_PORT=443
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
ports:
|
||||||
|
- 8705:80
|
||||||
|
- 8706:443
|
18
FinalTask/launchSettings.json
Normal file
18
FinalTask/launchSettings.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Docker Compose": {
|
||||||
|
"commandName": "DockerCompose",
|
||||||
|
"commandVersion": "1.0",
|
||||||
|
"composeLaunchAction": "LaunchBrowser",
|
||||||
|
"composeLaunchServiceName": "statswebsite",
|
||||||
|
"composeLaunchUrl": "{Scheme}://localhost:{ServicePort}",
|
||||||
|
"serviceActions": {
|
||||||
|
"mobileapi": "StartDebugging",
|
||||||
|
"postgres": "StartWithoutDebugging",
|
||||||
|
"pushapi": "StartDebugging",
|
||||||
|
"pushsender": "StartDebugging",
|
||||||
|
"rabbitmq": "StartWithoutDebugging"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
FinalTask/postgres-data/PG_VERSION
Normal file
1
FinalTask/postgres-data/PG_VERSION
Normal file
|
@ -0,0 +1 @@
|
||||||
|
14
|
BIN
FinalTask/postgres-data/base/1/112
Normal file
BIN
FinalTask/postgres-data/base/1/112
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/113
Normal file
BIN
FinalTask/postgres-data/base/1/113
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1247
Normal file
BIN
FinalTask/postgres-data/base/1/1247
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1247_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/1247_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1247_vm
Normal file
BIN
FinalTask/postgres-data/base/1/1247_vm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1249
Normal file
BIN
FinalTask/postgres-data/base/1/1249
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1249_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/1249_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1249_vm
Normal file
BIN
FinalTask/postgres-data/base/1/1249_vm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1255
Normal file
BIN
FinalTask/postgres-data/base/1/1255
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1255_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/1255_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1255_vm
Normal file
BIN
FinalTask/postgres-data/base/1/1255_vm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1259
Normal file
BIN
FinalTask/postgres-data/base/1/1259
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1259_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/1259_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/1259_vm
Normal file
BIN
FinalTask/postgres-data/base/1/1259_vm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13575
Normal file
BIN
FinalTask/postgres-data/base/1/13575
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13575_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/13575_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13575_vm
Normal file
BIN
FinalTask/postgres-data/base/1/13575_vm
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/13578
Normal file
0
FinalTask/postgres-data/base/1/13578
Normal file
BIN
FinalTask/postgres-data/base/1/13579
Normal file
BIN
FinalTask/postgres-data/base/1/13579
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13580
Normal file
BIN
FinalTask/postgres-data/base/1/13580
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13580_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/13580_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13580_vm
Normal file
BIN
FinalTask/postgres-data/base/1/13580_vm
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/13583
Normal file
0
FinalTask/postgres-data/base/1/13583
Normal file
BIN
FinalTask/postgres-data/base/1/13584
Normal file
BIN
FinalTask/postgres-data/base/1/13584
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13585
Normal file
BIN
FinalTask/postgres-data/base/1/13585
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13585_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/13585_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13585_vm
Normal file
BIN
FinalTask/postgres-data/base/1/13585_vm
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/13588
Normal file
0
FinalTask/postgres-data/base/1/13588
Normal file
BIN
FinalTask/postgres-data/base/1/13589
Normal file
BIN
FinalTask/postgres-data/base/1/13589
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13590
Normal file
BIN
FinalTask/postgres-data/base/1/13590
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13590_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/13590_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/13590_vm
Normal file
BIN
FinalTask/postgres-data/base/1/13590_vm
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/13593
Normal file
0
FinalTask/postgres-data/base/1/13593
Normal file
BIN
FinalTask/postgres-data/base/1/13594
Normal file
BIN
FinalTask/postgres-data/base/1/13594
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/1417
Normal file
0
FinalTask/postgres-data/base/1/1417
Normal file
0
FinalTask/postgres-data/base/1/1418
Normal file
0
FinalTask/postgres-data/base/1/1418
Normal file
BIN
FinalTask/postgres-data/base/1/174
Normal file
BIN
FinalTask/postgres-data/base/1/174
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/175
Normal file
BIN
FinalTask/postgres-data/base/1/175
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2187
Normal file
BIN
FinalTask/postgres-data/base/1/2187
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/2224
Normal file
0
FinalTask/postgres-data/base/1/2224
Normal file
BIN
FinalTask/postgres-data/base/1/2228
Normal file
BIN
FinalTask/postgres-data/base/1/2228
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/2328
Normal file
0
FinalTask/postgres-data/base/1/2328
Normal file
0
FinalTask/postgres-data/base/1/2336
Normal file
0
FinalTask/postgres-data/base/1/2336
Normal file
BIN
FinalTask/postgres-data/base/1/2337
Normal file
BIN
FinalTask/postgres-data/base/1/2337
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2579
Normal file
BIN
FinalTask/postgres-data/base/1/2579
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2600
Normal file
BIN
FinalTask/postgres-data/base/1/2600
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2600_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/2600_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2600_vm
Normal file
BIN
FinalTask/postgres-data/base/1/2600_vm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2601
Normal file
BIN
FinalTask/postgres-data/base/1/2601
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2601_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/2601_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2601_vm
Normal file
BIN
FinalTask/postgres-data/base/1/2601_vm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2602
Normal file
BIN
FinalTask/postgres-data/base/1/2602
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2602_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/2602_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2602_vm
Normal file
BIN
FinalTask/postgres-data/base/1/2602_vm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2603
Normal file
BIN
FinalTask/postgres-data/base/1/2603
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2603_fsm
Normal file
BIN
FinalTask/postgres-data/base/1/2603_fsm
Normal file
Binary file not shown.
BIN
FinalTask/postgres-data/base/1/2603_vm
Normal file
BIN
FinalTask/postgres-data/base/1/2603_vm
Normal file
Binary file not shown.
0
FinalTask/postgres-data/base/1/2604
Normal file
0
FinalTask/postgres-data/base/1/2604
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue